aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/imx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/imx')
-rw-r--r--drivers/gpu/drm/imx/Kconfig53
-rw-r--r--drivers/gpu/drm/imx/Makefile12
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c704
-rw-r--r--drivers/gpu/drm/imx/imx-drm.h56
-rw-r--r--drivers/gpu/drm/imx/imx-hdmi.c1766
-rw-r--r--drivers/gpu/drm/imx/imx-hdmi.h1032
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c615
-rw-r--r--drivers/gpu/drm/imx/imx-tve.c735
-rw-r--r--drivers/gpu/drm/imx/ipuv3-crtc.c518
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c363
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.h55
-rw-r--r--drivers/gpu/drm/imx/parallel-display.c295
12 files changed, 6204 insertions, 0 deletions
diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig
new file mode 100644
index 000000000000..82fb758a29bc
--- /dev/null
+++ b/drivers/gpu/drm/imx/Kconfig
@@ -0,0 +1,53 @@
1config DRM_IMX
2 tristate "DRM Support for Freescale i.MX"
3 select DRM_KMS_HELPER
4 select DRM_KMS_FB_HELPER
5 select VIDEOMODE_HELPERS
6 select DRM_GEM_CMA_HELPER
7 select DRM_KMS_CMA_HELPER
8 depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM)
9 help
10 enable i.MX graphics support
11
12config DRM_IMX_FB_HELPER
13 tristate "provide legacy framebuffer /dev/fb0"
14 select DRM_KMS_CMA_HELPER
15 depends on DRM_IMX
16 help
17 The DRM framework can provide a legacy /dev/fb0 framebuffer
18 for your device. This is necessary to get a framebuffer console
19 and also for applications using the legacy framebuffer API
20
21config DRM_IMX_PARALLEL_DISPLAY
22 tristate "Support for parallel displays"
23 select DRM_PANEL
24 depends on DRM_IMX
25 select VIDEOMODE_HELPERS
26
27config DRM_IMX_TVE
28 tristate "Support for TV and VGA displays"
29 depends on DRM_IMX
30 select REGMAP_MMIO
31 help
32 Choose this to enable the internal Television Encoder (TVe)
33 found on i.MX53 processors.
34
35config DRM_IMX_LDB
36 tristate "Support for LVDS displays"
37 depends on DRM_IMX && MFD_SYSCON
38 help
39 Choose this to enable the internal LVDS Display Bridge (LDB)
40 found on i.MX53 and i.MX6 processors.
41
42config DRM_IMX_IPUV3
43 tristate "DRM Support for i.MX IPUv3"
44 depends on DRM_IMX
45 depends on IMX_IPUV3_CORE
46 help
47 Choose this if you have a i.MX5 or i.MX6 processor.
48
49config DRM_IMX_HDMI
50 tristate "Freescale i.MX DRM HDMI"
51 depends on DRM_IMX
52 help
53 Choose this if you want to use HDMI on i.MX6.
diff --git a/drivers/gpu/drm/imx/Makefile b/drivers/gpu/drm/imx/Makefile
new file mode 100644
index 000000000000..582c438d8cbd
--- /dev/null
+++ b/drivers/gpu/drm/imx/Makefile
@@ -0,0 +1,12 @@
1
2imxdrm-objs := imx-drm-core.o
3
4obj-$(CONFIG_DRM_IMX) += imxdrm.o
5
6obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += parallel-display.o
7obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o
8obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
9
10imx-ipuv3-crtc-objs := ipuv3-crtc.o ipuv3-plane.o
11obj-$(CONFIG_DRM_IMX_IPUV3) += imx-ipuv3-crtc.o
12obj-$(CONFIG_DRM_IMX_HDMI) += imx-hdmi.o
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
new file mode 100644
index 000000000000..e48b2211d2d6
--- /dev/null
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -0,0 +1,704 @@
1/*
2 * Freescale i.MX drm driver
3 *
4 * Copyright (C) 2011 Sascha Hauer, Pengutronix
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16#include <linux/component.h>
17#include <linux/device.h>
18#include <linux/fb.h>
19#include <linux/module.h>
20#include <linux/of_graph.h>
21#include <linux/platform_device.h>
22#include <drm/drmP.h>
23#include <drm/drm_fb_helper.h>
24#include <drm/drm_crtc_helper.h>
25#include <drm/drm_gem_cma_helper.h>
26#include <drm/drm_fb_cma_helper.h>
27#include <drm/drm_plane_helper.h>
28
29#include "imx-drm.h"
30
31#define MAX_CRTC 4
32
33struct imx_drm_crtc;
34
35struct imx_drm_component {
36 struct device_node *of_node;
37 struct list_head list;
38};
39
40struct imx_drm_device {
41 struct drm_device *drm;
42 struct imx_drm_crtc *crtc[MAX_CRTC];
43 int pipes;
44 struct drm_fbdev_cma *fbhelper;
45};
46
47struct imx_drm_crtc {
48 struct drm_crtc *crtc;
49 int pipe;
50 struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs;
51 struct device_node *port;
52};
53
54static int legacyfb_depth = 16;
55module_param(legacyfb_depth, int, 0444);
56
57int imx_drm_crtc_id(struct imx_drm_crtc *crtc)
58{
59 return crtc->pipe;
60}
61EXPORT_SYMBOL_GPL(imx_drm_crtc_id);
62
63static void imx_drm_driver_lastclose(struct drm_device *drm)
64{
65#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
66 struct imx_drm_device *imxdrm = drm->dev_private;
67
68 if (imxdrm->fbhelper)
69 drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
70#endif
71}
72
73static int imx_drm_driver_unload(struct drm_device *drm)
74{
75#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
76 struct imx_drm_device *imxdrm = drm->dev_private;
77#endif
78
79 drm_kms_helper_poll_fini(drm);
80
81#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
82 if (imxdrm->fbhelper)
83 drm_fbdev_cma_fini(imxdrm->fbhelper);
84#endif
85
86 component_unbind_all(drm->dev, drm);
87
88 drm_vblank_cleanup(drm);
89 drm_mode_config_cleanup(drm);
90
91 platform_set_drvdata(drm->platformdev, NULL);
92
93 return 0;
94}
95
96static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
97{
98 struct imx_drm_device *imxdrm = crtc->dev->dev_private;
99 unsigned i;
100
101 for (i = 0; i < MAX_CRTC; i++)
102 if (imxdrm->crtc[i] && imxdrm->crtc[i]->crtc == crtc)
103 return imxdrm->crtc[i];
104
105 return NULL;
106}
107
108int imx_drm_panel_format_pins(struct drm_encoder *encoder,
109 u32 interface_pix_fmt, int hsync_pin, int vsync_pin)
110{
111 struct imx_drm_crtc_helper_funcs *helper;
112 struct imx_drm_crtc *imx_crtc;
113
114 imx_crtc = imx_drm_find_crtc(encoder->crtc);
115 if (!imx_crtc)
116 return -EINVAL;
117
118 helper = &imx_crtc->imx_drm_helper_funcs;
119 if (helper->set_interface_pix_fmt)
120 return helper->set_interface_pix_fmt(encoder->crtc,
121 encoder->encoder_type, interface_pix_fmt,
122 hsync_pin, vsync_pin);
123 return 0;
124}
125EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);
126
127int imx_drm_panel_format(struct drm_encoder *encoder, u32 interface_pix_fmt)
128{
129 return imx_drm_panel_format_pins(encoder, interface_pix_fmt, 2, 3);
130}
131EXPORT_SYMBOL_GPL(imx_drm_panel_format);
132
133int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
134{
135 return drm_vblank_get(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
136}
137EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get);
138
139void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc)
140{
141 drm_vblank_put(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
142}
143EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put);
144
145void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc)
146{
147 drm_handle_vblank(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
148}
149EXPORT_SYMBOL_GPL(imx_drm_handle_vblank);
150
151static int imx_drm_enable_vblank(struct drm_device *drm, int crtc)
152{
153 struct imx_drm_device *imxdrm = drm->dev_private;
154 struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
155 int ret;
156
157 if (!imx_drm_crtc)
158 return -EINVAL;
159
160 if (!imx_drm_crtc->imx_drm_helper_funcs.enable_vblank)
161 return -ENOSYS;
162
163 ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank(
164 imx_drm_crtc->crtc);
165
166 return ret;
167}
168
169static void imx_drm_disable_vblank(struct drm_device *drm, int crtc)
170{
171 struct imx_drm_device *imxdrm = drm->dev_private;
172 struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
173
174 if (!imx_drm_crtc)
175 return;
176
177 if (!imx_drm_crtc->imx_drm_helper_funcs.disable_vblank)
178 return;
179
180 imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc);
181}
182
183static void imx_drm_driver_preclose(struct drm_device *drm,
184 struct drm_file *file)
185{
186 int i;
187
188 if (!file->is_master)
189 return;
190
191 for (i = 0; i < MAX_CRTC; i++)
192 imx_drm_disable_vblank(drm, i);
193}
194
195static const struct file_operations imx_drm_driver_fops = {
196 .owner = THIS_MODULE,
197 .open = drm_open,
198 .release = drm_release,
199 .unlocked_ioctl = drm_ioctl,
200 .mmap = drm_gem_cma_mmap,
201 .poll = drm_poll,
202 .read = drm_read,
203 .llseek = noop_llseek,
204};
205
206void imx_drm_connector_destroy(struct drm_connector *connector)
207{
208 drm_connector_unregister(connector);
209 drm_connector_cleanup(connector);
210}
211EXPORT_SYMBOL_GPL(imx_drm_connector_destroy);
212
213void imx_drm_encoder_destroy(struct drm_encoder *encoder)
214{
215 drm_encoder_cleanup(encoder);
216}
217EXPORT_SYMBOL_GPL(imx_drm_encoder_destroy);
218
219static void imx_drm_output_poll_changed(struct drm_device *drm)
220{
221#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
222 struct imx_drm_device *imxdrm = drm->dev_private;
223
224 drm_fbdev_cma_hotplug_event(imxdrm->fbhelper);
225#endif
226}
227
228static struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
229 .fb_create = drm_fb_cma_create,
230 .output_poll_changed = imx_drm_output_poll_changed,
231};
232
233/*
234 * Main DRM initialisation. This binds, initialises and registers
235 * with DRM the subcomponents of the driver.
236 */
237static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
238{
239 struct imx_drm_device *imxdrm;
240 struct drm_connector *connector;
241 int ret;
242
243 imxdrm = devm_kzalloc(drm->dev, sizeof(*imxdrm), GFP_KERNEL);
244 if (!imxdrm)
245 return -ENOMEM;
246
247 imxdrm->drm = drm;
248
249 drm->dev_private = imxdrm;
250
251 /*
252 * enable drm irq mode.
253 * - with irq_enabled = true, we can use the vblank feature.
254 *
255 * P.S. note that we wouldn't use drm irq handler but
256 * just specific driver own one instead because
257 * drm framework supports only one irq handler and
258 * drivers can well take care of their interrupts
259 */
260 drm->irq_enabled = true;
261
262 /*
263 * set max width and height as default value(4096x4096).
264 * this value would be used to check framebuffer size limitation
265 * at drm_mode_addfb().
266 */
267 drm->mode_config.min_width = 64;
268 drm->mode_config.min_height = 64;
269 drm->mode_config.max_width = 4096;
270 drm->mode_config.max_height = 4096;
271 drm->mode_config.funcs = &imx_drm_mode_config_funcs;
272
273 drm_mode_config_init(drm);
274
275 ret = drm_vblank_init(drm, MAX_CRTC);
276 if (ret)
277 goto err_kms;
278
279 /*
280 * with vblank_disable_allowed = true, vblank interrupt will be
281 * disabled by drm timer once a current process gives up ownership
282 * of vblank event. (after drm_vblank_put function is called)
283 */
284 drm->vblank_disable_allowed = true;
285
286 platform_set_drvdata(drm->platformdev, drm);
287
288 /* Now try and bind all our sub-components */
289 ret = component_bind_all(drm->dev, drm);
290 if (ret)
291 goto err_vblank;
292
293 /*
294 * All components are now added, we can publish the connector sysfs
295 * entries to userspace. This will generate hotplug events and so
296 * userspace will expect to be able to access DRM at this point.
297 */
298 list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
299 ret = drm_connector_register(connector);
300 if (ret) {
301 dev_err(drm->dev,
302 "[CONNECTOR:%d:%s] drm_connector_register failed: %d\n",
303 connector->base.id,
304 connector->name, ret);
305 goto err_unbind;
306 }
307 }
308
309 /*
310 * All components are now initialised, so setup the fb helper.
311 * The fb helper takes copies of key hardware information, so the
312 * crtcs/connectors/encoders must not change after this point.
313 */
314#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
315 if (legacyfb_depth != 16 && legacyfb_depth != 32) {
316 dev_warn(drm->dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n");
317 legacyfb_depth = 16;
318 }
319 imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth,
320 drm->mode_config.num_crtc, MAX_CRTC);
321 if (IS_ERR(imxdrm->fbhelper)) {
322 ret = PTR_ERR(imxdrm->fbhelper);
323 imxdrm->fbhelper = NULL;
324 goto err_unbind;
325 }
326#endif
327
328 drm_kms_helper_poll_init(drm);
329
330 return 0;
331
332err_unbind:
333 component_unbind_all(drm->dev, drm);
334err_vblank:
335 drm_vblank_cleanup(drm);
336err_kms:
337 drm_mode_config_cleanup(drm);
338
339 return ret;
340}
341
342/*
343 * imx_drm_add_crtc - add a new crtc
344 */
345int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
346 struct imx_drm_crtc **new_crtc,
347 const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
348 struct device_node *port)
349{
350 struct imx_drm_device *imxdrm = drm->dev_private;
351 struct imx_drm_crtc *imx_drm_crtc;
352 int ret;
353
354 /*
355 * The vblank arrays are dimensioned by MAX_CRTC - we can't
356 * pass IDs greater than this to those functions.
357 */
358 if (imxdrm->pipes >= MAX_CRTC)
359 return -EINVAL;
360
361 if (imxdrm->drm->open_count)
362 return -EBUSY;
363
364 imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL);
365 if (!imx_drm_crtc)
366 return -ENOMEM;
367
368 imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs;
369 imx_drm_crtc->pipe = imxdrm->pipes++;
370 imx_drm_crtc->port = port;
371 imx_drm_crtc->crtc = crtc;
372
373 imxdrm->crtc[imx_drm_crtc->pipe] = imx_drm_crtc;
374
375 *new_crtc = imx_drm_crtc;
376
377 ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256);
378 if (ret)
379 goto err_register;
380
381 drm_crtc_helper_add(crtc,
382 imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
383
384 drm_crtc_init(drm, crtc,
385 imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
386
387 return 0;
388
389err_register:
390 imxdrm->crtc[imx_drm_crtc->pipe] = NULL;
391 kfree(imx_drm_crtc);
392 return ret;
393}
394EXPORT_SYMBOL_GPL(imx_drm_add_crtc);
395
396/*
397 * imx_drm_remove_crtc - remove a crtc
398 */
399int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc)
400{
401 struct imx_drm_device *imxdrm = imx_drm_crtc->crtc->dev->dev_private;
402
403 drm_crtc_cleanup(imx_drm_crtc->crtc);
404
405 imxdrm->crtc[imx_drm_crtc->pipe] = NULL;
406
407 kfree(imx_drm_crtc);
408
409 return 0;
410}
411EXPORT_SYMBOL_GPL(imx_drm_remove_crtc);
412
413/*
414 * Find the DRM CRTC possible mask for the connected endpoint.
415 *
416 * The encoder possible masks are defined by their position in the
417 * mode_config crtc_list. This means that CRTCs must not be added
418 * or removed once the DRM device has been fully initialised.
419 */
420static uint32_t imx_drm_find_crtc_mask(struct imx_drm_device *imxdrm,
421 struct device_node *endpoint)
422{
423 struct device_node *port;
424 unsigned i;
425
426 port = of_graph_get_remote_port(endpoint);
427 if (!port)
428 return 0;
429 of_node_put(port);
430
431 for (i = 0; i < MAX_CRTC; i++) {
432 struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[i];
433
434 if (imx_drm_crtc && imx_drm_crtc->port == port)
435 return drm_crtc_mask(imx_drm_crtc->crtc);
436 }
437
438 return 0;
439}
440
441static struct device_node *imx_drm_of_get_next_endpoint(
442 const struct device_node *parent, struct device_node *prev)
443{
444 struct device_node *node = of_graph_get_next_endpoint(parent, prev);
445
446 of_node_put(prev);
447 return node;
448}
449
450int imx_drm_encoder_parse_of(struct drm_device *drm,
451 struct drm_encoder *encoder, struct device_node *np)
452{
453 struct imx_drm_device *imxdrm = drm->dev_private;
454 struct device_node *ep = NULL;
455 uint32_t crtc_mask = 0;
456 int i;
457
458 for (i = 0; ; i++) {
459 u32 mask;
460
461 ep = imx_drm_of_get_next_endpoint(np, ep);
462 if (!ep)
463 break;
464
465 mask = imx_drm_find_crtc_mask(imxdrm, ep);
466
467 /*
468 * If we failed to find the CRTC(s) which this encoder is
469 * supposed to be connected to, it's because the CRTC has
470 * not been registered yet. Defer probing, and hope that
471 * the required CRTC is added later.
472 */
473 if (mask == 0)
474 return -EPROBE_DEFER;
475
476 crtc_mask |= mask;
477 }
478
479 of_node_put(ep);
480 if (i == 0)
481 return -ENOENT;
482
483 encoder->possible_crtcs = crtc_mask;
484
485 /* FIXME: this is the mask of outputs which can clone this output. */
486 encoder->possible_clones = ~0;
487
488 return 0;
489}
490EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of);
491
492/*
493 * @node: device tree node containing encoder input ports
494 * @encoder: drm_encoder
495 */
496int imx_drm_encoder_get_mux_id(struct device_node *node,
497 struct drm_encoder *encoder)
498{
499 struct imx_drm_crtc *imx_crtc = imx_drm_find_crtc(encoder->crtc);
500 struct device_node *ep = NULL;
501 struct of_endpoint endpoint;
502 struct device_node *port;
503 int ret;
504
505 if (!node || !imx_crtc)
506 return -EINVAL;
507
508 do {
509 ep = imx_drm_of_get_next_endpoint(node, ep);
510 if (!ep)
511 break;
512
513 port = of_graph_get_remote_port(ep);
514 of_node_put(port);
515 if (port == imx_crtc->port) {
516 ret = of_graph_parse_endpoint(ep, &endpoint);
517 return ret ? ret : endpoint.port;
518 }
519 } while (ep);
520
521 return -EINVAL;
522}
523EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id);
524
525static const struct drm_ioctl_desc imx_drm_ioctls[] = {
526 /* none so far */
527};
528
529static struct drm_driver imx_drm_driver = {
530 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
531 .load = imx_drm_driver_load,
532 .unload = imx_drm_driver_unload,
533 .lastclose = imx_drm_driver_lastclose,
534 .preclose = imx_drm_driver_preclose,
535 .set_busid = drm_platform_set_busid,
536 .gem_free_object = drm_gem_cma_free_object,
537 .gem_vm_ops = &drm_gem_cma_vm_ops,
538 .dumb_create = drm_gem_cma_dumb_create,
539 .dumb_map_offset = drm_gem_cma_dumb_map_offset,
540 .dumb_destroy = drm_gem_dumb_destroy,
541
542 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
543 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
544 .gem_prime_import = drm_gem_prime_import,
545 .gem_prime_export = drm_gem_prime_export,
546 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
547 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
548 .gem_prime_vmap = drm_gem_cma_prime_vmap,
549 .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
550 .gem_prime_mmap = drm_gem_cma_prime_mmap,
551 .get_vblank_counter = drm_vblank_count,
552 .enable_vblank = imx_drm_enable_vblank,
553 .disable_vblank = imx_drm_disable_vblank,
554 .ioctls = imx_drm_ioctls,
555 .num_ioctls = ARRAY_SIZE(imx_drm_ioctls),
556 .fops = &imx_drm_driver_fops,
557 .name = "imx-drm",
558 .desc = "i.MX DRM graphics",
559 .date = "20120507",
560 .major = 1,
561 .minor = 0,
562 .patchlevel = 0,
563};
564
565static int compare_of(struct device *dev, void *data)
566{
567 struct device_node *np = data;
568
569 /* Special case for LDB, one device for two channels */
570 if (of_node_cmp(np->name, "lvds-channel") == 0) {
571 np = of_get_parent(np);
572 of_node_put(np);
573 }
574
575 return dev->of_node == np;
576}
577
578static int imx_drm_bind(struct device *dev)
579{
580 return drm_platform_init(&imx_drm_driver, to_platform_device(dev));
581}
582
583static void imx_drm_unbind(struct device *dev)
584{
585 drm_put_dev(dev_get_drvdata(dev));
586}
587
588static const struct component_master_ops imx_drm_ops = {
589 .bind = imx_drm_bind,
590 .unbind = imx_drm_unbind,
591};
592
593static int imx_drm_platform_probe(struct platform_device *pdev)
594{
595 struct device_node *ep, *port, *remote;
596 struct component_match *match = NULL;
597 int ret;
598 int i;
599
600 /*
601 * Bind the IPU display interface ports first, so that
602 * imx_drm_encoder_parse_of called from encoder .bind callbacks
603 * works as expected.
604 */
605 for (i = 0; ; i++) {
606 port = of_parse_phandle(pdev->dev.of_node, "ports", i);
607 if (!port)
608 break;
609
610 component_match_add(&pdev->dev, &match, compare_of, port);
611 }
612
613 if (i == 0) {
614 dev_err(&pdev->dev, "missing 'ports' property\n");
615 return -ENODEV;
616 }
617
618 /* Then bind all encoders */
619 for (i = 0; ; i++) {
620 port = of_parse_phandle(pdev->dev.of_node, "ports", i);
621 if (!port)
622 break;
623
624 for_each_child_of_node(port, ep) {
625 remote = of_graph_get_remote_port_parent(ep);
626 if (!remote || !of_device_is_available(remote)) {
627 of_node_put(remote);
628 continue;
629 } else if (!of_device_is_available(remote->parent)) {
630 dev_warn(&pdev->dev, "parent device of %s is not available\n",
631 remote->full_name);
632 of_node_put(remote);
633 continue;
634 }
635
636 component_match_add(&pdev->dev, &match, compare_of, remote);
637 of_node_put(remote);
638 }
639 of_node_put(port);
640 }
641
642 ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
643 if (ret)
644 return ret;
645
646 return component_master_add_with_match(&pdev->dev, &imx_drm_ops, match);
647}
648
649static int imx_drm_platform_remove(struct platform_device *pdev)
650{
651 component_master_del(&pdev->dev, &imx_drm_ops);
652 return 0;
653}
654
655#ifdef CONFIG_PM_SLEEP
656static int imx_drm_suspend(struct device *dev)
657{
658 struct drm_device *drm_dev = dev_get_drvdata(dev);
659
660 /* The drm_dev is NULL before .load hook is called */
661 if (drm_dev == NULL)
662 return 0;
663
664 drm_kms_helper_poll_disable(drm_dev);
665
666 return 0;
667}
668
669static int imx_drm_resume(struct device *dev)
670{
671 struct drm_device *drm_dev = dev_get_drvdata(dev);
672
673 if (drm_dev == NULL)
674 return 0;
675
676 drm_helper_resume_force_mode(drm_dev);
677 drm_kms_helper_poll_enable(drm_dev);
678
679 return 0;
680}
681#endif
682
683static SIMPLE_DEV_PM_OPS(imx_drm_pm_ops, imx_drm_suspend, imx_drm_resume);
684
685static const struct of_device_id imx_drm_dt_ids[] = {
686 { .compatible = "fsl,imx-display-subsystem", },
687 { /* sentinel */ },
688};
689MODULE_DEVICE_TABLE(of, imx_drm_dt_ids);
690
691static struct platform_driver imx_drm_pdrv = {
692 .probe = imx_drm_platform_probe,
693 .remove = imx_drm_platform_remove,
694 .driver = {
695 .name = "imx-drm",
696 .pm = &imx_drm_pm_ops,
697 .of_match_table = imx_drm_dt_ids,
698 },
699};
700module_platform_driver(imx_drm_pdrv);
701
702MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
703MODULE_DESCRIPTION("i.MX drm driver core");
704MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/imx/imx-drm.h b/drivers/gpu/drm/imx/imx-drm.h
new file mode 100644
index 000000000000..7453ae00c412
--- /dev/null
+++ b/drivers/gpu/drm/imx/imx-drm.h
@@ -0,0 +1,56 @@
1#ifndef _IMX_DRM_H_
2#define _IMX_DRM_H_
3
4struct device_node;
5struct drm_crtc;
6struct drm_connector;
7struct drm_device;
8struct drm_display_mode;
9struct drm_encoder;
10struct drm_fbdev_cma;
11struct drm_framebuffer;
12struct imx_drm_crtc;
13struct platform_device;
14
15int imx_drm_crtc_id(struct imx_drm_crtc *crtc);
16
17struct imx_drm_crtc_helper_funcs {
18 int (*enable_vblank)(struct drm_crtc *crtc);
19 void (*disable_vblank)(struct drm_crtc *crtc);
20 int (*set_interface_pix_fmt)(struct drm_crtc *crtc, u32 encoder_type,
21 u32 pix_fmt, int hsync_pin, int vsync_pin);
22 const struct drm_crtc_helper_funcs *crtc_helper_funcs;
23 const struct drm_crtc_funcs *crtc_funcs;
24};
25
26int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
27 struct imx_drm_crtc **new_crtc,
28 const struct imx_drm_crtc_helper_funcs *imx_helper_funcs,
29 struct device_node *port);
30int imx_drm_remove_crtc(struct imx_drm_crtc *);
31int imx_drm_init_drm(struct platform_device *pdev,
32 int preferred_bpp);
33int imx_drm_exit_drm(void);
34
35int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc);
36void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc);
37void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc);
38
39void imx_drm_mode_config_init(struct drm_device *drm);
40
41struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
42
43int imx_drm_panel_format_pins(struct drm_encoder *encoder,
44 u32 interface_pix_fmt, int hsync_pin, int vsync_pin);
45int imx_drm_panel_format(struct drm_encoder *encoder,
46 u32 interface_pix_fmt);
47
48int imx_drm_encoder_get_mux_id(struct device_node *node,
49 struct drm_encoder *encoder);
50int imx_drm_encoder_parse_of(struct drm_device *drm,
51 struct drm_encoder *encoder, struct device_node *np);
52
53void imx_drm_connector_destroy(struct drm_connector *connector);
54void imx_drm_encoder_destroy(struct drm_encoder *encoder);
55
56#endif /* _IMX_DRM_H_ */
diff --git a/drivers/gpu/drm/imx/imx-hdmi.c b/drivers/gpu/drm/imx/imx-hdmi.c
new file mode 100644
index 000000000000..ddc53e039530
--- /dev/null
+++ b/drivers/gpu/drm/imx/imx-hdmi.c
@@ -0,0 +1,1766 @@
1/*
2 * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
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 as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * SH-Mobile High-Definition Multimedia Interface (HDMI) driver
10 * for SLISHDMI13T and SLIPHDMIT IP cores
11 *
12 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
13 */
14
15#include <linux/component.h>
16#include <linux/irq.h>
17#include <linux/delay.h>
18#include <linux/err.h>
19#include <linux/clk.h>
20#include <linux/hdmi.h>
21#include <linux/regmap.h>
22#include <linux/mfd/syscon.h>
23#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
24#include <linux/of_device.h>
25
26#include <drm/drmP.h>
27#include <drm/drm_crtc_helper.h>
28#include <drm/drm_edid.h>
29#include <drm/drm_encoder_slave.h>
30#include <video/imx-ipu-v3.h>
31
32#include "imx-hdmi.h"
33#include "imx-drm.h"
34
35#define HDMI_EDID_LEN 512
36
37#define RGB 0
38#define YCBCR444 1
39#define YCBCR422_16BITS 2
40#define YCBCR422_8BITS 3
41#define XVYCC444 4
42
43enum hdmi_datamap {
44 RGB444_8B = 0x01,
45 RGB444_10B = 0x03,
46 RGB444_12B = 0x05,
47 RGB444_16B = 0x07,
48 YCbCr444_8B = 0x09,
49 YCbCr444_10B = 0x0B,
50 YCbCr444_12B = 0x0D,
51 YCbCr444_16B = 0x0F,
52 YCbCr422_8B = 0x16,
53 YCbCr422_10B = 0x14,
54 YCbCr422_12B = 0x12,
55};
56
57enum imx_hdmi_devtype {
58 IMX6Q_HDMI,
59 IMX6DL_HDMI,
60};
61
62static const u16 csc_coeff_default[3][4] = {
63 { 0x2000, 0x0000, 0x0000, 0x0000 },
64 { 0x0000, 0x2000, 0x0000, 0x0000 },
65 { 0x0000, 0x0000, 0x2000, 0x0000 }
66};
67
68static const u16 csc_coeff_rgb_out_eitu601[3][4] = {
69 { 0x2000, 0x6926, 0x74fd, 0x010e },
70 { 0x2000, 0x2cdd, 0x0000, 0x7e9a },
71 { 0x2000, 0x0000, 0x38b4, 0x7e3b }
72};
73
74static const u16 csc_coeff_rgb_out_eitu709[3][4] = {
75 { 0x2000, 0x7106, 0x7a02, 0x00a7 },
76 { 0x2000, 0x3264, 0x0000, 0x7e6d },
77 { 0x2000, 0x0000, 0x3b61, 0x7e25 }
78};
79
80static const u16 csc_coeff_rgb_in_eitu601[3][4] = {
81 { 0x2591, 0x1322, 0x074b, 0x0000 },
82 { 0x6535, 0x2000, 0x7acc, 0x0200 },
83 { 0x6acd, 0x7534, 0x2000, 0x0200 }
84};
85
86static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
87 { 0x2dc5, 0x0d9b, 0x049e, 0x0000 },
88 { 0x62f0, 0x2000, 0x7d11, 0x0200 },
89 { 0x6756, 0x78ab, 0x2000, 0x0200 }
90};
91
92struct hdmi_vmode {
93 bool mdvi;
94 bool mhsyncpolarity;
95 bool mvsyncpolarity;
96 bool minterlaced;
97 bool mdataenablepolarity;
98
99 unsigned int mpixelclock;
100 unsigned int mpixelrepetitioninput;
101 unsigned int mpixelrepetitionoutput;
102};
103
104struct hdmi_data_info {
105 unsigned int enc_in_format;
106 unsigned int enc_out_format;
107 unsigned int enc_color_depth;
108 unsigned int colorimetry;
109 unsigned int pix_repet_factor;
110 unsigned int hdcp_enable;
111 struct hdmi_vmode video_mode;
112};
113
114struct imx_hdmi {
115 struct drm_connector connector;
116 struct drm_encoder encoder;
117
118 enum imx_hdmi_devtype dev_type;
119 struct device *dev;
120 struct clk *isfr_clk;
121 struct clk *iahb_clk;
122
123 struct hdmi_data_info hdmi_data;
124 int vic;
125
126 u8 edid[HDMI_EDID_LEN];
127 bool cable_plugin;
128
129 bool phy_enabled;
130 struct drm_display_mode previous_mode;
131
132 struct regmap *regmap;
133 struct i2c_adapter *ddc;
134 void __iomem *regs;
135
136 unsigned int sample_rate;
137 int ratio;
138};
139
140static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi *hdmi, int ipu_di)
141{
142 regmap_update_bits(hdmi->regmap, IOMUXC_GPR3,
143 IMX6Q_GPR3_HDMI_MUX_CTL_MASK,
144 ipu_di << IMX6Q_GPR3_HDMI_MUX_CTL_SHIFT);
145}
146
147static inline void hdmi_writeb(struct imx_hdmi *hdmi, u8 val, int offset)
148{
149 writeb(val, hdmi->regs + offset);
150}
151
152static inline u8 hdmi_readb(struct imx_hdmi *hdmi, int offset)
153{
154 return readb(hdmi->regs + offset);
155}
156
157static void hdmi_modb(struct imx_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
158{
159 u8 val = hdmi_readb(hdmi, reg) & ~mask;
160
161 val |= data & mask;
162 hdmi_writeb(hdmi, val, reg);
163}
164
165static void hdmi_mask_writeb(struct imx_hdmi *hdmi, u8 data, unsigned int reg,
166 u8 shift, u8 mask)
167{
168 hdmi_modb(hdmi, data << shift, mask, reg);
169}
170
171static void hdmi_set_clock_regenerator_n(struct imx_hdmi *hdmi,
172 unsigned int value)
173{
174 hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1);
175 hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2);
176 hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3);
177
178 /* nshift factor = 0 */
179 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
180}
181
182static void hdmi_regenerate_cts(struct imx_hdmi *hdmi, unsigned int cts)
183{
184 /* Must be set/cleared first */
185 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
186
187 hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
188 hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
189 hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
190 HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
191}
192
193static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
194 unsigned int ratio)
195{
196 unsigned int n = (128 * freq) / 1000;
197
198 switch (freq) {
199 case 32000:
200 if (pixel_clk == 25170000)
201 n = (ratio == 150) ? 9152 : 4576;
202 else if (pixel_clk == 27020000)
203 n = (ratio == 150) ? 8192 : 4096;
204 else if (pixel_clk == 74170000 || pixel_clk == 148350000)
205 n = 11648;
206 else
207 n = 4096;
208 break;
209
210 case 44100:
211 if (pixel_clk == 25170000)
212 n = 7007;
213 else if (pixel_clk == 74170000)
214 n = 17836;
215 else if (pixel_clk == 148350000)
216 n = (ratio == 150) ? 17836 : 8918;
217 else
218 n = 6272;
219 break;
220
221 case 48000:
222 if (pixel_clk == 25170000)
223 n = (ratio == 150) ? 9152 : 6864;
224 else if (pixel_clk == 27020000)
225 n = (ratio == 150) ? 8192 : 6144;
226 else if (pixel_clk == 74170000)
227 n = 11648;
228 else if (pixel_clk == 148350000)
229 n = (ratio == 150) ? 11648 : 5824;
230 else
231 n = 6144;
232 break;
233
234 case 88200:
235 n = hdmi_compute_n(44100, pixel_clk, ratio) * 2;
236 break;
237
238 case 96000:
239 n = hdmi_compute_n(48000, pixel_clk, ratio) * 2;
240 break;
241
242 case 176400:
243 n = hdmi_compute_n(44100, pixel_clk, ratio) * 4;
244 break;
245
246 case 192000:
247 n = hdmi_compute_n(48000, pixel_clk, ratio) * 4;
248 break;
249
250 default:
251 break;
252 }
253
254 return n;
255}
256
257static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
258 unsigned int ratio)
259{
260 unsigned int cts = 0;
261
262 pr_debug("%s: freq: %d pixel_clk: %ld ratio: %d\n", __func__, freq,
263 pixel_clk, ratio);
264
265 switch (freq) {
266 case 32000:
267 if (pixel_clk == 297000000) {
268 cts = 222750;
269 break;
270 }
271 case 48000:
272 case 96000:
273 case 192000:
274 switch (pixel_clk) {
275 case 25200000:
276 case 27000000:
277 case 54000000:
278 case 74250000:
279 case 148500000:
280 cts = pixel_clk / 1000;
281 break;
282 case 297000000:
283 cts = 247500;
284 break;
285 /*
286 * All other TMDS clocks are not supported by
287 * DWC_hdmi_tx. The TMDS clocks divided or
288 * multiplied by 1,001 coefficients are not
289 * supported.
290 */
291 default:
292 break;
293 }
294 break;
295 case 44100:
296 case 88200:
297 case 176400:
298 switch (pixel_clk) {
299 case 25200000:
300 cts = 28000;
301 break;
302 case 27000000:
303 cts = 30000;
304 break;
305 case 54000000:
306 cts = 60000;
307 break;
308 case 74250000:
309 cts = 82500;
310 break;
311 case 148500000:
312 cts = 165000;
313 break;
314 case 297000000:
315 cts = 247500;
316 break;
317 default:
318 break;
319 }
320 break;
321 default:
322 break;
323 }
324 if (ratio == 100)
325 return cts;
326 return (cts * ratio) / 100;
327}
328
329static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi,
330 unsigned long pixel_clk)
331{
332 unsigned int clk_n, clk_cts;
333
334 clk_n = hdmi_compute_n(hdmi->sample_rate, pixel_clk,
335 hdmi->ratio);
336 clk_cts = hdmi_compute_cts(hdmi->sample_rate, pixel_clk,
337 hdmi->ratio);
338
339 if (!clk_cts) {
340 dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
341 __func__, pixel_clk);
342 return;
343 }
344
345 dev_dbg(hdmi->dev, "%s: samplerate=%d ratio=%d pixelclk=%lu N=%d cts=%d\n",
346 __func__, hdmi->sample_rate, hdmi->ratio,
347 pixel_clk, clk_n, clk_cts);
348
349 hdmi_set_clock_regenerator_n(hdmi, clk_n);
350 hdmi_regenerate_cts(hdmi, clk_cts);
351}
352
353static void hdmi_init_clk_regenerator(struct imx_hdmi *hdmi)
354{
355 hdmi_set_clk_regenerator(hdmi, 74250000);
356}
357
358static void hdmi_clk_regenerator_update_pixel_clock(struct imx_hdmi *hdmi)
359{
360 hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
361}
362
363/*
364 * this submodule is responsible for the video data synchronization.
365 * for example, for RGB 4:4:4 input, the data map is defined as
366 * pin{47~40} <==> R[7:0]
367 * pin{31~24} <==> G[7:0]
368 * pin{15~8} <==> B[7:0]
369 */
370static void hdmi_video_sample(struct imx_hdmi *hdmi)
371{
372 int color_format = 0;
373 u8 val;
374
375 if (hdmi->hdmi_data.enc_in_format == RGB) {
376 if (hdmi->hdmi_data.enc_color_depth == 8)
377 color_format = 0x01;
378 else if (hdmi->hdmi_data.enc_color_depth == 10)
379 color_format = 0x03;
380 else if (hdmi->hdmi_data.enc_color_depth == 12)
381 color_format = 0x05;
382 else if (hdmi->hdmi_data.enc_color_depth == 16)
383 color_format = 0x07;
384 else
385 return;
386 } else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
387 if (hdmi->hdmi_data.enc_color_depth == 8)
388 color_format = 0x09;
389 else if (hdmi->hdmi_data.enc_color_depth == 10)
390 color_format = 0x0B;
391 else if (hdmi->hdmi_data.enc_color_depth == 12)
392 color_format = 0x0D;
393 else if (hdmi->hdmi_data.enc_color_depth == 16)
394 color_format = 0x0F;
395 else
396 return;
397 } else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
398 if (hdmi->hdmi_data.enc_color_depth == 8)
399 color_format = 0x16;
400 else if (hdmi->hdmi_data.enc_color_depth == 10)
401 color_format = 0x14;
402 else if (hdmi->hdmi_data.enc_color_depth == 12)
403 color_format = 0x12;
404 else
405 return;
406 }
407
408 val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
409 ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
410 HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
411 hdmi_writeb(hdmi, val, HDMI_TX_INVID0);
412
413 /* Enable TX stuffing: When DE is inactive, fix the output data to 0 */
414 val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
415 HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
416 HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
417 hdmi_writeb(hdmi, val, HDMI_TX_INSTUFFING);
418 hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA0);
419 hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA1);
420 hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA0);
421 hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA1);
422 hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA0);
423 hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1);
424}
425
426static int is_color_space_conversion(struct imx_hdmi *hdmi)
427{
428 return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
429}
430
431static int is_color_space_decimation(struct imx_hdmi *hdmi)
432{
433 if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
434 return 0;
435 if (hdmi->hdmi_data.enc_in_format == RGB ||
436 hdmi->hdmi_data.enc_in_format == YCBCR444)
437 return 1;
438 return 0;
439}
440
441static int is_color_space_interpolation(struct imx_hdmi *hdmi)
442{
443 if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
444 return 0;
445 if (hdmi->hdmi_data.enc_out_format == RGB ||
446 hdmi->hdmi_data.enc_out_format == YCBCR444)
447 return 1;
448 return 0;
449}
450
451static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi)
452{
453 const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
454 unsigned i;
455 u32 csc_scale = 1;
456
457 if (is_color_space_conversion(hdmi)) {
458 if (hdmi->hdmi_data.enc_out_format == RGB) {
459 if (hdmi->hdmi_data.colorimetry ==
460 HDMI_COLORIMETRY_ITU_601)
461 csc_coeff = &csc_coeff_rgb_out_eitu601;
462 else
463 csc_coeff = &csc_coeff_rgb_out_eitu709;
464 } else if (hdmi->hdmi_data.enc_in_format == RGB) {
465 if (hdmi->hdmi_data.colorimetry ==
466 HDMI_COLORIMETRY_ITU_601)
467 csc_coeff = &csc_coeff_rgb_in_eitu601;
468 else
469 csc_coeff = &csc_coeff_rgb_in_eitu709;
470 csc_scale = 0;
471 }
472 }
473
474 /* The CSC registers are sequential, alternating MSB then LSB */
475 for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
476 u16 coeff_a = (*csc_coeff)[0][i];
477 u16 coeff_b = (*csc_coeff)[1][i];
478 u16 coeff_c = (*csc_coeff)[2][i];
479
480 hdmi_writeb(hdmi, coeff_a & 0xff,
481 HDMI_CSC_COEF_A1_LSB + i * 2);
482 hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
483 hdmi_writeb(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
484 hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
485 hdmi_writeb(hdmi, coeff_c & 0xff,
486 HDMI_CSC_COEF_C1_LSB + i * 2);
487 hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
488 }
489
490 hdmi_modb(hdmi, csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK,
491 HDMI_CSC_SCALE);
492}
493
494static void hdmi_video_csc(struct imx_hdmi *hdmi)
495{
496 int color_depth = 0;
497 int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
498 int decimation = 0;
499
500 /* YCC422 interpolation to 444 mode */
501 if (is_color_space_interpolation(hdmi))
502 interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1;
503 else if (is_color_space_decimation(hdmi))
504 decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
505
506 if (hdmi->hdmi_data.enc_color_depth == 8)
507 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
508 else if (hdmi->hdmi_data.enc_color_depth == 10)
509 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
510 else if (hdmi->hdmi_data.enc_color_depth == 12)
511 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
512 else if (hdmi->hdmi_data.enc_color_depth == 16)
513 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
514 else
515 return;
516
517 /* Configure the CSC registers */
518 hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
519 hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
520 HDMI_CSC_SCALE);
521
522 imx_hdmi_update_csc_coeffs(hdmi);
523}
524
525/*
526 * HDMI video packetizer is used to packetize the data.
527 * for example, if input is YCC422 mode or repeater is used,
528 * data should be repacked this module can be bypassed.
529 */
530static void hdmi_video_packetize(struct imx_hdmi *hdmi)
531{
532 unsigned int color_depth = 0;
533 unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit;
534 unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP;
535 struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
536 u8 val, vp_conf;
537
538 if (hdmi_data->enc_out_format == RGB
539 || hdmi_data->enc_out_format == YCBCR444) {
540 if (!hdmi_data->enc_color_depth)
541 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
542 else if (hdmi_data->enc_color_depth == 8) {
543 color_depth = 4;
544 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
545 } else if (hdmi_data->enc_color_depth == 10)
546 color_depth = 5;
547 else if (hdmi_data->enc_color_depth == 12)
548 color_depth = 6;
549 else if (hdmi_data->enc_color_depth == 16)
550 color_depth = 7;
551 else
552 return;
553 } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
554 if (!hdmi_data->enc_color_depth ||
555 hdmi_data->enc_color_depth == 8)
556 remap_size = HDMI_VP_REMAP_YCC422_16bit;
557 else if (hdmi_data->enc_color_depth == 10)
558 remap_size = HDMI_VP_REMAP_YCC422_20bit;
559 else if (hdmi_data->enc_color_depth == 12)
560 remap_size = HDMI_VP_REMAP_YCC422_24bit;
561 else
562 return;
563 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
564 } else
565 return;
566
567 /* set the packetizer registers */
568 val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
569 HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
570 ((hdmi_data->pix_repet_factor <<
571 HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
572 HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
573 hdmi_writeb(hdmi, val, HDMI_VP_PR_CD);
574
575 hdmi_modb(hdmi, HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE,
576 HDMI_VP_STUFF_PR_STUFFING_MASK, HDMI_VP_STUFF);
577
578 /* Data from pixel repeater block */
579 if (hdmi_data->pix_repet_factor > 1) {
580 vp_conf = HDMI_VP_CONF_PR_EN_ENABLE |
581 HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
582 } else { /* data from packetizer block */
583 vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
584 HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
585 }
586
587 hdmi_modb(hdmi, vp_conf,
588 HDMI_VP_CONF_PR_EN_MASK |
589 HDMI_VP_CONF_BYPASS_SELECT_MASK, HDMI_VP_CONF);
590
591 hdmi_modb(hdmi, 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET,
592 HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, HDMI_VP_STUFF);
593
594 hdmi_writeb(hdmi, remap_size, HDMI_VP_REMAP);
595
596 if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
597 vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
598 HDMI_VP_CONF_PP_EN_ENABLE |
599 HDMI_VP_CONF_YCC422_EN_DISABLE;
600 } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
601 vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
602 HDMI_VP_CONF_PP_EN_DISABLE |
603 HDMI_VP_CONF_YCC422_EN_ENABLE;
604 } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
605 vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
606 HDMI_VP_CONF_PP_EN_DISABLE |
607 HDMI_VP_CONF_YCC422_EN_DISABLE;
608 } else {
609 return;
610 }
611
612 hdmi_modb(hdmi, vp_conf,
613 HDMI_VP_CONF_BYPASS_EN_MASK | HDMI_VP_CONF_PP_EN_ENMASK |
614 HDMI_VP_CONF_YCC422_EN_MASK, HDMI_VP_CONF);
615
616 hdmi_modb(hdmi, HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
617 HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE,
618 HDMI_VP_STUFF_PP_STUFFING_MASK |
619 HDMI_VP_STUFF_YCC422_STUFFING_MASK, HDMI_VP_STUFF);
620
621 hdmi_modb(hdmi, output_select, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
622 HDMI_VP_CONF);
623}
624
625static inline void hdmi_phy_test_clear(struct imx_hdmi *hdmi,
626 unsigned char bit)
627{
628 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET,
629 HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
630}
631
632static inline void hdmi_phy_test_enable(struct imx_hdmi *hdmi,
633 unsigned char bit)
634{
635 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET,
636 HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0);
637}
638
639static inline void hdmi_phy_test_clock(struct imx_hdmi *hdmi,
640 unsigned char bit)
641{
642 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET,
643 HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0);
644}
645
646static inline void hdmi_phy_test_din(struct imx_hdmi *hdmi,
647 unsigned char bit)
648{
649 hdmi_writeb(hdmi, bit, HDMI_PHY_TST1);
650}
651
652static inline void hdmi_phy_test_dout(struct imx_hdmi *hdmi,
653 unsigned char bit)
654{
655 hdmi_writeb(hdmi, bit, HDMI_PHY_TST2);
656}
657
658static bool hdmi_phy_wait_i2c_done(struct imx_hdmi *hdmi, int msec)
659{
660 while ((hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3) == 0) {
661 if (msec-- == 0)
662 return false;
663 udelay(1000);
664 }
665 return true;
666}
667
668static void __hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data,
669 unsigned char addr)
670{
671 hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0);
672 hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
673 hdmi_writeb(hdmi, (unsigned char)(data >> 8),
674 HDMI_PHY_I2CM_DATAO_1_ADDR);
675 hdmi_writeb(hdmi, (unsigned char)(data >> 0),
676 HDMI_PHY_I2CM_DATAO_0_ADDR);
677 hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
678 HDMI_PHY_I2CM_OPERATION_ADDR);
679 hdmi_phy_wait_i2c_done(hdmi, 1000);
680}
681
682static int hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data,
683 unsigned char addr)
684{
685 __hdmi_phy_i2c_write(hdmi, data, addr);
686 return 0;
687}
688
689static void imx_hdmi_phy_enable_power(struct imx_hdmi *hdmi, u8 enable)
690{
691 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
692 HDMI_PHY_CONF0_PDZ_OFFSET,
693 HDMI_PHY_CONF0_PDZ_MASK);
694}
695
696static void imx_hdmi_phy_enable_tmds(struct imx_hdmi *hdmi, u8 enable)
697{
698 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
699 HDMI_PHY_CONF0_ENTMDS_OFFSET,
700 HDMI_PHY_CONF0_ENTMDS_MASK);
701}
702
703static void imx_hdmi_phy_gen2_pddq(struct imx_hdmi *hdmi, u8 enable)
704{
705 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
706 HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET,
707 HDMI_PHY_CONF0_GEN2_PDDQ_MASK);
708}
709
710static void imx_hdmi_phy_gen2_txpwron(struct imx_hdmi *hdmi, u8 enable)
711{
712 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
713 HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET,
714 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK);
715}
716
717static void imx_hdmi_phy_sel_data_en_pol(struct imx_hdmi *hdmi, u8 enable)
718{
719 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
720 HDMI_PHY_CONF0_SELDATAENPOL_OFFSET,
721 HDMI_PHY_CONF0_SELDATAENPOL_MASK);
722}
723
724static void imx_hdmi_phy_sel_interface_control(struct imx_hdmi *hdmi, u8 enable)
725{
726 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
727 HDMI_PHY_CONF0_SELDIPIF_OFFSET,
728 HDMI_PHY_CONF0_SELDIPIF_MASK);
729}
730
731enum {
732 RES_8,
733 RES_10,
734 RES_12,
735 RES_MAX,
736};
737
738struct mpll_config {
739 unsigned long mpixelclock;
740 struct {
741 u16 cpce;
742 u16 gmp;
743 } res[RES_MAX];
744};
745
746static const struct mpll_config mpll_config[] = {
747 {
748 45250000, {
749 { 0x01e0, 0x0000 },
750 { 0x21e1, 0x0000 },
751 { 0x41e2, 0x0000 }
752 },
753 }, {
754 92500000, {
755 { 0x0140, 0x0005 },
756 { 0x2141, 0x0005 },
757 { 0x4142, 0x0005 },
758 },
759 }, {
760 148500000, {
761 { 0x00a0, 0x000a },
762 { 0x20a1, 0x000a },
763 { 0x40a2, 0x000a },
764 },
765 }, {
766 ~0UL, {
767 { 0x00a0, 0x000a },
768 { 0x2001, 0x000f },
769 { 0x4002, 0x000f },
770 },
771 }
772};
773
774struct curr_ctrl {
775 unsigned long mpixelclock;
776 u16 curr[RES_MAX];
777};
778
779static const struct curr_ctrl curr_ctrl[] = {
780 /* pixelclk bpp8 bpp10 bpp12 */
781 {
782 54000000, { 0x091c, 0x091c, 0x06dc },
783 }, {
784 58400000, { 0x091c, 0x06dc, 0x06dc },
785 }, {
786 72000000, { 0x06dc, 0x06dc, 0x091c },
787 }, {
788 74250000, { 0x06dc, 0x0b5c, 0x091c },
789 }, {
790 118800000, { 0x091c, 0x091c, 0x06dc },
791 }, {
792 216000000, { 0x06dc, 0x0b5c, 0x091c },
793 }
794};
795
796static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
797 unsigned char res, int cscon)
798{
799 unsigned res_idx, i;
800 u8 val, msec;
801
802 if (prep)
803 return -EINVAL;
804
805 switch (res) {
806 case 0: /* color resolution 0 is 8 bit colour depth */
807 case 8:
808 res_idx = RES_8;
809 break;
810 case 10:
811 res_idx = RES_10;
812 break;
813 case 12:
814 res_idx = RES_12;
815 break;
816 default:
817 return -EINVAL;
818 }
819
820 /* Enable csc path */
821 if (cscon)
822 val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
823 else
824 val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS;
825
826 hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL);
827
828 /* gen2 tx power off */
829 imx_hdmi_phy_gen2_txpwron(hdmi, 0);
830
831 /* gen2 pddq */
832 imx_hdmi_phy_gen2_pddq(hdmi, 1);
833
834 /* PHY reset */
835 hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
836 hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
837
838 hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
839
840 hdmi_phy_test_clear(hdmi, 1);
841 hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
842 HDMI_PHY_I2CM_SLAVE_ADDR);
843 hdmi_phy_test_clear(hdmi, 0);
844
845 /* PLL/MPLL Cfg - always match on final entry */
846 for (i = 0; i < ARRAY_SIZE(mpll_config) - 1; i++)
847 if (hdmi->hdmi_data.video_mode.mpixelclock <=
848 mpll_config[i].mpixelclock)
849 break;
850
851 hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
852 hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
853
854 for (i = 0; i < ARRAY_SIZE(curr_ctrl); i++)
855 if (hdmi->hdmi_data.video_mode.mpixelclock <=
856 curr_ctrl[i].mpixelclock)
857 break;
858
859 if (i >= ARRAY_SIZE(curr_ctrl)) {
860 dev_err(hdmi->dev,
861 "Pixel clock %d - unsupported by HDMI\n",
862 hdmi->hdmi_data.video_mode.mpixelclock);
863 return -EINVAL;
864 }
865
866 /* CURRCTRL */
867 hdmi_phy_i2c_write(hdmi, curr_ctrl[i].curr[res_idx], 0x10);
868
869 hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
870 hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
871 /* RESISTANCE TERM 133Ohm Cfg */
872 hdmi_phy_i2c_write(hdmi, 0x0005, 0x19); /* TXTERM */
873 /* PREEMP Cgf 0.00 */
874 hdmi_phy_i2c_write(hdmi, 0x800d, 0x09); /* CKSYMTXCTRL */
875 /* TX/CK LVL 10 */
876 hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E); /* VLEVCTRL */
877 /* REMOVE CLK TERM */
878 hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */
879
880 imx_hdmi_phy_enable_power(hdmi, 1);
881
882 /* toggle TMDS enable */
883 imx_hdmi_phy_enable_tmds(hdmi, 0);
884 imx_hdmi_phy_enable_tmds(hdmi, 1);
885
886 /* gen2 tx power on */
887 imx_hdmi_phy_gen2_txpwron(hdmi, 1);
888 imx_hdmi_phy_gen2_pddq(hdmi, 0);
889
890 /*Wait for PHY PLL lock */
891 msec = 5;
892 do {
893 val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
894 if (!val)
895 break;
896
897 if (msec == 0) {
898 dev_err(hdmi->dev, "PHY PLL not locked\n");
899 return -ETIMEDOUT;
900 }
901
902 udelay(1000);
903 msec--;
904 } while (1);
905
906 return 0;
907}
908
909static int imx_hdmi_phy_init(struct imx_hdmi *hdmi)
910{
911 int i, ret;
912 bool cscon = false;
913
914 /*check csc whether needed activated in HDMI mode */
915 cscon = (is_color_space_conversion(hdmi) &&
916 !hdmi->hdmi_data.video_mode.mdvi);
917
918 /* HDMI Phy spec says to do the phy initialization sequence twice */
919 for (i = 0; i < 2; i++) {
920 imx_hdmi_phy_sel_data_en_pol(hdmi, 1);
921 imx_hdmi_phy_sel_interface_control(hdmi, 0);
922 imx_hdmi_phy_enable_tmds(hdmi, 0);
923 imx_hdmi_phy_enable_power(hdmi, 0);
924
925 /* Enable CSC */
926 ret = hdmi_phy_configure(hdmi, 0, 8, cscon);
927 if (ret)
928 return ret;
929 }
930
931 hdmi->phy_enabled = true;
932 return 0;
933}
934
935static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi)
936{
937 u8 de;
938
939 if (hdmi->hdmi_data.video_mode.mdataenablepolarity)
940 de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH;
941 else
942 de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW;
943
944 /* disable rx detect */
945 hdmi_modb(hdmi, HDMI_A_HDCPCFG0_RXDETECT_DISABLE,
946 HDMI_A_HDCPCFG0_RXDETECT_MASK, HDMI_A_HDCPCFG0);
947
948 hdmi_modb(hdmi, de, HDMI_A_VIDPOLCFG_DATAENPOL_MASK, HDMI_A_VIDPOLCFG);
949
950 hdmi_modb(hdmi, HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE,
951 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
952}
953
954static void hdmi_config_AVI(struct imx_hdmi *hdmi)
955{
956 u8 val, pix_fmt, under_scan;
957 u8 act_ratio, coded_ratio, colorimetry, ext_colorimetry;
958 bool aspect_16_9;
959
960 aspect_16_9 = false; /* FIXME */
961
962 /* AVI Data Byte 1 */
963 if (hdmi->hdmi_data.enc_out_format == YCBCR444)
964 pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR444;
965 else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
966 pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR422;
967 else
968 pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_RGB;
969
970 under_scan = HDMI_FC_AVICONF0_SCAN_INFO_NODATA;
971
972 /*
973 * Active format identification data is present in the AVI InfoFrame.
974 * Under scan info, no bar data
975 */
976 val = pix_fmt | under_scan |
977 HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT |
978 HDMI_FC_AVICONF0_BAR_DATA_NO_DATA;
979
980 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0);
981
982 /* AVI Data Byte 2 -Set the Aspect Ratio */
983 if (aspect_16_9) {
984 act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9;
985 coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9;
986 } else {
987 act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3;
988 coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3;
989 }
990
991 /* Set up colorimetry */
992 if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
993 colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO;
994 if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
995 ext_colorimetry =
996 HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
997 else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
998 ext_colorimetry =
999 HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709;
1000 } else if (hdmi->hdmi_data.enc_out_format != RGB) {
1001 if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
1002 colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_SMPTE;
1003 else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
1004 colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_ITUR;
1005 ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
1006 } else { /* Carries no data */
1007 colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA;
1008 ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
1009 }
1010
1011 val = colorimetry | coded_ratio | act_ratio;
1012 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF1);
1013
1014 /* AVI Data Byte 3 */
1015 val = HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA | ext_colorimetry |
1016 HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT |
1017 HDMI_FC_AVICONF2_SCALING_NONE;
1018 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF2);
1019
1020 /* AVI Data Byte 4 */
1021 hdmi_writeb(hdmi, hdmi->vic, HDMI_FC_AVIVID);
1022
1023 /* AVI Data Byte 5- set up input and output pixel repetition */
1024 val = (((hdmi->hdmi_data.video_mode.mpixelrepetitioninput + 1) <<
1025 HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET) &
1026 HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK) |
1027 ((hdmi->hdmi_data.video_mode.mpixelrepetitionoutput <<
1028 HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET) &
1029 HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK);
1030 hdmi_writeb(hdmi, val, HDMI_FC_PRCONF);
1031
1032 /* IT Content and quantization range = don't care */
1033 val = HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS |
1034 HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED;
1035 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF3);
1036
1037 /* AVI Data Bytes 6-13 */
1038 hdmi_writeb(hdmi, 0, HDMI_FC_AVIETB0);
1039 hdmi_writeb(hdmi, 0, HDMI_FC_AVIETB1);
1040 hdmi_writeb(hdmi, 0, HDMI_FC_AVISBB0);
1041 hdmi_writeb(hdmi, 0, HDMI_FC_AVISBB1);
1042 hdmi_writeb(hdmi, 0, HDMI_FC_AVIELB0);
1043 hdmi_writeb(hdmi, 0, HDMI_FC_AVIELB1);
1044 hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB0);
1045 hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB1);
1046}
1047
1048static void hdmi_av_composer(struct imx_hdmi *hdmi,
1049 const struct drm_display_mode *mode)
1050{
1051 u8 inv_val;
1052 struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
1053 int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
1054
1055 vmode->mhsyncpolarity = !!(mode->flags & DRM_MODE_FLAG_PHSYNC);
1056 vmode->mvsyncpolarity = !!(mode->flags & DRM_MODE_FLAG_PVSYNC);
1057 vmode->minterlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
1058 vmode->mpixelclock = mode->clock * 1000;
1059
1060 dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
1061
1062 /* Set up HDMI_FC_INVIDCONF */
1063 inv_val = (hdmi->hdmi_data.hdcp_enable ?
1064 HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
1065 HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
1066
1067 inv_val |= (vmode->mvsyncpolarity ?
1068 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
1069 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
1070
1071 inv_val |= (vmode->mhsyncpolarity ?
1072 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
1073 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
1074
1075 inv_val |= (vmode->mdataenablepolarity ?
1076 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
1077 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
1078
1079 if (hdmi->vic == 39)
1080 inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH;
1081 else
1082 inv_val |= (vmode->minterlaced ?
1083 HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH :
1084 HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW);
1085
1086 inv_val |= (vmode->minterlaced ?
1087 HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
1088 HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE);
1089
1090 inv_val |= (vmode->mdvi ?
1091 HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE :
1092 HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE);
1093
1094 hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF);
1095
1096 /* Set up horizontal active pixel width */
1097 hdmi_writeb(hdmi, mode->hdisplay >> 8, HDMI_FC_INHACTV1);
1098 hdmi_writeb(hdmi, mode->hdisplay, HDMI_FC_INHACTV0);
1099
1100 /* Set up vertical active lines */
1101 hdmi_writeb(hdmi, mode->vdisplay >> 8, HDMI_FC_INVACTV1);
1102 hdmi_writeb(hdmi, mode->vdisplay, HDMI_FC_INVACTV0);
1103
1104 /* Set up horizontal blanking pixel region width */
1105 hblank = mode->htotal - mode->hdisplay;
1106 hdmi_writeb(hdmi, hblank >> 8, HDMI_FC_INHBLANK1);
1107 hdmi_writeb(hdmi, hblank, HDMI_FC_INHBLANK0);
1108
1109 /* Set up vertical blanking pixel region width */
1110 vblank = mode->vtotal - mode->vdisplay;
1111 hdmi_writeb(hdmi, vblank, HDMI_FC_INVBLANK);
1112
1113 /* Set up HSYNC active edge delay width (in pixel clks) */
1114 h_de_hs = mode->hsync_start - mode->hdisplay;
1115 hdmi_writeb(hdmi, h_de_hs >> 8, HDMI_FC_HSYNCINDELAY1);
1116 hdmi_writeb(hdmi, h_de_hs, HDMI_FC_HSYNCINDELAY0);
1117
1118 /* Set up VSYNC active edge delay (in lines) */
1119 v_de_vs = mode->vsync_start - mode->vdisplay;
1120 hdmi_writeb(hdmi, v_de_vs, HDMI_FC_VSYNCINDELAY);
1121
1122 /* Set up HSYNC active pulse width (in pixel clks) */
1123 hsync_len = mode->hsync_end - mode->hsync_start;
1124 hdmi_writeb(hdmi, hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1);
1125 hdmi_writeb(hdmi, hsync_len, HDMI_FC_HSYNCINWIDTH0);
1126
1127 /* Set up VSYNC active edge delay (in lines) */
1128 vsync_len = mode->vsync_end - mode->vsync_start;
1129 hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH);
1130}
1131
1132static void imx_hdmi_phy_disable(struct imx_hdmi *hdmi)
1133{
1134 if (!hdmi->phy_enabled)
1135 return;
1136
1137 imx_hdmi_phy_enable_tmds(hdmi, 0);
1138 imx_hdmi_phy_enable_power(hdmi, 0);
1139
1140 hdmi->phy_enabled = false;
1141}
1142
1143/* HDMI Initialization Step B.4 */
1144static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi)
1145{
1146 u8 clkdis;
1147
1148 /* control period minimum duration */
1149 hdmi_writeb(hdmi, 12, HDMI_FC_CTRLDUR);
1150 hdmi_writeb(hdmi, 32, HDMI_FC_EXCTRLDUR);
1151 hdmi_writeb(hdmi, 1, HDMI_FC_EXCTRLSPAC);
1152
1153 /* Set to fill TMDS data channels */
1154 hdmi_writeb(hdmi, 0x0B, HDMI_FC_CH0PREAM);
1155 hdmi_writeb(hdmi, 0x16, HDMI_FC_CH1PREAM);
1156 hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM);
1157
1158 /* Enable pixel clock and tmds data path */
1159 clkdis = 0x7F;
1160 clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
1161 hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
1162
1163 clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
1164 hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
1165
1166 /* Enable csc path */
1167 if (is_color_space_conversion(hdmi)) {
1168 clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
1169 hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
1170 }
1171}
1172
1173static void hdmi_enable_audio_clk(struct imx_hdmi *hdmi)
1174{
1175 hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
1176}
1177
1178/* Workaround to clear the overflow condition */
1179static void imx_hdmi_clear_overflow(struct imx_hdmi *hdmi)
1180{
1181 int count;
1182 u8 val;
1183
1184 /* TMDS software reset */
1185 hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
1186
1187 val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF);
1188 if (hdmi->dev_type == IMX6DL_HDMI) {
1189 hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
1190 return;
1191 }
1192
1193 for (count = 0; count < 4; count++)
1194 hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
1195}
1196
1197static void hdmi_enable_overflow_interrupts(struct imx_hdmi *hdmi)
1198{
1199 hdmi_writeb(hdmi, 0, HDMI_FC_MASK2);
1200 hdmi_writeb(hdmi, 0, HDMI_IH_MUTE_FC_STAT2);
1201}
1202
1203static void hdmi_disable_overflow_interrupts(struct imx_hdmi *hdmi)
1204{
1205 hdmi_writeb(hdmi, HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK,
1206 HDMI_IH_MUTE_FC_STAT2);
1207}
1208
1209static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct drm_display_mode *mode)
1210{
1211 int ret;
1212
1213 hdmi_disable_overflow_interrupts(hdmi);
1214
1215 hdmi->vic = drm_match_cea_mode(mode);
1216
1217 if (!hdmi->vic) {
1218 dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n");
1219 hdmi->hdmi_data.video_mode.mdvi = true;
1220 } else {
1221 dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic);
1222 hdmi->hdmi_data.video_mode.mdvi = false;
1223 }
1224
1225 if ((hdmi->vic == 6) || (hdmi->vic == 7) ||
1226 (hdmi->vic == 21) || (hdmi->vic == 22) ||
1227 (hdmi->vic == 2) || (hdmi->vic == 3) ||
1228 (hdmi->vic == 17) || (hdmi->vic == 18))
1229 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
1230 else
1231 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
1232
1233 if ((hdmi->vic == 10) || (hdmi->vic == 11) ||
1234 (hdmi->vic == 12) || (hdmi->vic == 13) ||
1235 (hdmi->vic == 14) || (hdmi->vic == 15) ||
1236 (hdmi->vic == 25) || (hdmi->vic == 26) ||
1237 (hdmi->vic == 27) || (hdmi->vic == 28) ||
1238 (hdmi->vic == 29) || (hdmi->vic == 30) ||
1239 (hdmi->vic == 35) || (hdmi->vic == 36) ||
1240 (hdmi->vic == 37) || (hdmi->vic == 38))
1241 hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 1;
1242 else
1243 hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
1244
1245 hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
1246
1247 /* TODO: Get input format from IPU (via FB driver interface) */
1248 hdmi->hdmi_data.enc_in_format = RGB;
1249
1250 hdmi->hdmi_data.enc_out_format = RGB;
1251
1252 hdmi->hdmi_data.enc_color_depth = 8;
1253 hdmi->hdmi_data.pix_repet_factor = 0;
1254 hdmi->hdmi_data.hdcp_enable = 0;
1255 hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
1256
1257 /* HDMI Initialization Step B.1 */
1258 hdmi_av_composer(hdmi, mode);
1259
1260 /* HDMI Initializateion Step B.2 */
1261 ret = imx_hdmi_phy_init(hdmi);
1262 if (ret)
1263 return ret;
1264
1265 /* HDMI Initialization Step B.3 */
1266 imx_hdmi_enable_video_path(hdmi);
1267
1268 /* not for DVI mode */
1269 if (hdmi->hdmi_data.video_mode.mdvi)
1270 dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
1271 else {
1272 dev_dbg(hdmi->dev, "%s CEA mode\n", __func__);
1273
1274 /* HDMI Initialization Step E - Configure audio */
1275 hdmi_clk_regenerator_update_pixel_clock(hdmi);
1276 hdmi_enable_audio_clk(hdmi);
1277
1278 /* HDMI Initialization Step F - Configure AVI InfoFrame */
1279 hdmi_config_AVI(hdmi);
1280 }
1281
1282 hdmi_video_packetize(hdmi);
1283 hdmi_video_csc(hdmi);
1284 hdmi_video_sample(hdmi);
1285 hdmi_tx_hdcp_config(hdmi);
1286
1287 imx_hdmi_clear_overflow(hdmi);
1288 if (hdmi->cable_plugin && !hdmi->hdmi_data.video_mode.mdvi)
1289 hdmi_enable_overflow_interrupts(hdmi);
1290
1291 return 0;
1292}
1293
1294/* Wait until we are registered to enable interrupts */
1295static int imx_hdmi_fb_registered(struct imx_hdmi *hdmi)
1296{
1297 hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
1298 HDMI_PHY_I2CM_INT_ADDR);
1299
1300 hdmi_writeb(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
1301 HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
1302 HDMI_PHY_I2CM_CTLINT_ADDR);
1303
1304 /* enable cable hot plug irq */
1305 hdmi_writeb(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
1306
1307 /* Clear Hotplug interrupts */
1308 hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
1309
1310 return 0;
1311}
1312
1313static void initialize_hdmi_ih_mutes(struct imx_hdmi *hdmi)
1314{
1315 u8 ih_mute;
1316
1317 /*
1318 * Boot up defaults are:
1319 * HDMI_IH_MUTE = 0x03 (disabled)
1320 * HDMI_IH_MUTE_* = 0x00 (enabled)
1321 *
1322 * Disable top level interrupt bits in HDMI block
1323 */
1324 ih_mute = hdmi_readb(hdmi, HDMI_IH_MUTE) |
1325 HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
1326 HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
1327
1328 hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
1329
1330 /* by default mask all interrupts */
1331 hdmi_writeb(hdmi, 0xff, HDMI_VP_MASK);
1332 hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK0);
1333 hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK1);
1334 hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK2);
1335 hdmi_writeb(hdmi, 0xff, HDMI_PHY_MASK0);
1336 hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_INT_ADDR);
1337 hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_CTLINT_ADDR);
1338 hdmi_writeb(hdmi, 0xff, HDMI_AUD_INT);
1339 hdmi_writeb(hdmi, 0xff, HDMI_AUD_SPDIFINT);
1340 hdmi_writeb(hdmi, 0xff, HDMI_AUD_HBR_MASK);
1341 hdmi_writeb(hdmi, 0xff, HDMI_GP_MASK);
1342 hdmi_writeb(hdmi, 0xff, HDMI_A_APIINTMSK);
1343 hdmi_writeb(hdmi, 0xff, HDMI_CEC_MASK);
1344 hdmi_writeb(hdmi, 0xff, HDMI_I2CM_INT);
1345 hdmi_writeb(hdmi, 0xff, HDMI_I2CM_CTLINT);
1346
1347 /* Disable interrupts in the IH_MUTE_* registers */
1348 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT0);
1349 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT1);
1350 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT2);
1351 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AS_STAT0);
1352 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_PHY_STAT0);
1353 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CM_STAT0);
1354 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_CEC_STAT0);
1355 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_VP_STAT0);
1356 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CMPHY_STAT0);
1357 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
1358
1359 /* Enable top level interrupt bits in HDMI block */
1360 ih_mute &= ~(HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
1361 HDMI_IH_MUTE_MUTE_ALL_INTERRUPT);
1362 hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
1363}
1364
1365static void imx_hdmi_poweron(struct imx_hdmi *hdmi)
1366{
1367 imx_hdmi_setup(hdmi, &hdmi->previous_mode);
1368}
1369
1370static void imx_hdmi_poweroff(struct imx_hdmi *hdmi)
1371{
1372 imx_hdmi_phy_disable(hdmi);
1373}
1374
1375static enum drm_connector_status imx_hdmi_connector_detect(struct drm_connector
1376 *connector, bool force)
1377{
1378 struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
1379 connector);
1380
1381 return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
1382 connector_status_connected : connector_status_disconnected;
1383}
1384
1385static int imx_hdmi_connector_get_modes(struct drm_connector *connector)
1386{
1387 struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
1388 connector);
1389 struct edid *edid;
1390 int ret;
1391
1392 if (!hdmi->ddc)
1393 return 0;
1394
1395 edid = drm_get_edid(connector, hdmi->ddc);
1396 if (edid) {
1397 dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
1398 edid->width_cm, edid->height_cm);
1399
1400 drm_mode_connector_update_edid_property(connector, edid);
1401 ret = drm_add_edid_modes(connector, edid);
1402 kfree(edid);
1403 } else {
1404 dev_dbg(hdmi->dev, "failed to get edid\n");
1405 }
1406
1407 return 0;
1408}
1409
1410static struct drm_encoder *imx_hdmi_connector_best_encoder(struct drm_connector
1411 *connector)
1412{
1413 struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
1414 connector);
1415
1416 return &hdmi->encoder;
1417}
1418
1419static void imx_hdmi_encoder_mode_set(struct drm_encoder *encoder,
1420 struct drm_display_mode *mode,
1421 struct drm_display_mode *adjusted_mode)
1422{
1423 struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
1424
1425 imx_hdmi_setup(hdmi, mode);
1426
1427 /* Store the display mode for plugin/DKMS poweron events */
1428 memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
1429}
1430
1431static bool imx_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
1432 const struct drm_display_mode *mode,
1433 struct drm_display_mode *adjusted_mode)
1434{
1435 return true;
1436}
1437
1438static void imx_hdmi_encoder_disable(struct drm_encoder *encoder)
1439{
1440}
1441
1442static void imx_hdmi_encoder_dpms(struct drm_encoder *encoder, int mode)
1443{
1444 struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
1445
1446 if (mode)
1447 imx_hdmi_poweroff(hdmi);
1448 else
1449 imx_hdmi_poweron(hdmi);
1450}
1451
1452static void imx_hdmi_encoder_prepare(struct drm_encoder *encoder)
1453{
1454 struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
1455
1456 imx_hdmi_poweroff(hdmi);
1457 imx_drm_panel_format(encoder, V4L2_PIX_FMT_RGB24);
1458}
1459
1460static void imx_hdmi_encoder_commit(struct drm_encoder *encoder)
1461{
1462 struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
1463 int mux = imx_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);
1464
1465 imx_hdmi_set_ipu_di_mux(hdmi, mux);
1466
1467 imx_hdmi_poweron(hdmi);
1468}
1469
1470static struct drm_encoder_funcs imx_hdmi_encoder_funcs = {
1471 .destroy = imx_drm_encoder_destroy,
1472};
1473
1474static struct drm_encoder_helper_funcs imx_hdmi_encoder_helper_funcs = {
1475 .dpms = imx_hdmi_encoder_dpms,
1476 .prepare = imx_hdmi_encoder_prepare,
1477 .commit = imx_hdmi_encoder_commit,
1478 .mode_set = imx_hdmi_encoder_mode_set,
1479 .mode_fixup = imx_hdmi_encoder_mode_fixup,
1480 .disable = imx_hdmi_encoder_disable,
1481};
1482
1483static struct drm_connector_funcs imx_hdmi_connector_funcs = {
1484 .dpms = drm_helper_connector_dpms,
1485 .fill_modes = drm_helper_probe_single_connector_modes,
1486 .detect = imx_hdmi_connector_detect,
1487 .destroy = imx_drm_connector_destroy,
1488};
1489
1490static struct drm_connector_helper_funcs imx_hdmi_connector_helper_funcs = {
1491 .get_modes = imx_hdmi_connector_get_modes,
1492 .best_encoder = imx_hdmi_connector_best_encoder,
1493};
1494
1495static irqreturn_t imx_hdmi_hardirq(int irq, void *dev_id)
1496{
1497 struct imx_hdmi *hdmi = dev_id;
1498 u8 intr_stat;
1499
1500 intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
1501 if (intr_stat)
1502 hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
1503
1504 return intr_stat ? IRQ_WAKE_THREAD : IRQ_NONE;
1505}
1506
1507static irqreturn_t imx_hdmi_irq(int irq, void *dev_id)
1508{
1509 struct imx_hdmi *hdmi = dev_id;
1510 u8 intr_stat;
1511 u8 phy_int_pol;
1512
1513 intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
1514
1515 phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0);
1516
1517 if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
1518 if (phy_int_pol & HDMI_PHY_HPD) {
1519 dev_dbg(hdmi->dev, "EVENT=plugin\n");
1520
1521 hdmi_modb(hdmi, 0, HDMI_PHY_HPD, HDMI_PHY_POL0);
1522
1523 imx_hdmi_poweron(hdmi);
1524 } else {
1525 dev_dbg(hdmi->dev, "EVENT=plugout\n");
1526
1527 hdmi_modb(hdmi, HDMI_PHY_HPD, HDMI_PHY_HPD,
1528 HDMI_PHY_POL0);
1529
1530 imx_hdmi_poweroff(hdmi);
1531 }
1532 drm_helper_hpd_irq_event(hdmi->connector.dev);
1533 }
1534
1535 hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
1536 hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
1537
1538 return IRQ_HANDLED;
1539}
1540
1541static int imx_hdmi_register(struct drm_device *drm, struct imx_hdmi *hdmi)
1542{
1543 int ret;
1544
1545 ret = imx_drm_encoder_parse_of(drm, &hdmi->encoder,
1546 hdmi->dev->of_node);
1547 if (ret)
1548 return ret;
1549
1550 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
1551
1552 drm_encoder_helper_add(&hdmi->encoder, &imx_hdmi_encoder_helper_funcs);
1553 drm_encoder_init(drm, &hdmi->encoder, &imx_hdmi_encoder_funcs,
1554 DRM_MODE_ENCODER_TMDS);
1555
1556 drm_connector_helper_add(&hdmi->connector,
1557 &imx_hdmi_connector_helper_funcs);
1558 drm_connector_init(drm, &hdmi->connector, &imx_hdmi_connector_funcs,
1559 DRM_MODE_CONNECTOR_HDMIA);
1560
1561 hdmi->connector.encoder = &hdmi->encoder;
1562
1563 drm_mode_connector_attach_encoder(&hdmi->connector, &hdmi->encoder);
1564
1565 return 0;
1566}
1567
1568static struct platform_device_id imx_hdmi_devtype[] = {
1569 {
1570 .name = "imx6q-hdmi",
1571 .driver_data = IMX6Q_HDMI,
1572 }, {
1573 .name = "imx6dl-hdmi",
1574 .driver_data = IMX6DL_HDMI,
1575 }, { /* sentinel */ }
1576};
1577MODULE_DEVICE_TABLE(platform, imx_hdmi_devtype);
1578
1579static const struct of_device_id imx_hdmi_dt_ids[] = {
1580{ .compatible = "fsl,imx6q-hdmi", .data = &imx_hdmi_devtype[IMX6Q_HDMI], },
1581{ .compatible = "fsl,imx6dl-hdmi", .data = &imx_hdmi_devtype[IMX6DL_HDMI], },
1582{ /* sentinel */ }
1583};
1584MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids);
1585
1586static int imx_hdmi_bind(struct device *dev, struct device *master, void *data)
1587{
1588 struct platform_device *pdev = to_platform_device(dev);
1589 const struct of_device_id *of_id =
1590 of_match_device(imx_hdmi_dt_ids, dev);
1591 struct drm_device *drm = data;
1592 struct device_node *np = dev->of_node;
1593 struct device_node *ddc_node;
1594 struct imx_hdmi *hdmi;
1595 struct resource *iores;
1596 int ret, irq;
1597
1598 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
1599 if (!hdmi)
1600 return -ENOMEM;
1601
1602 hdmi->dev = dev;
1603 hdmi->sample_rate = 48000;
1604 hdmi->ratio = 100;
1605
1606 if (of_id) {
1607 const struct platform_device_id *device_id = of_id->data;
1608
1609 hdmi->dev_type = device_id->driver_data;
1610 }
1611
1612 ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
1613 if (ddc_node) {
1614 hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
1615 if (!hdmi->ddc)
1616 dev_dbg(hdmi->dev, "failed to read ddc node\n");
1617
1618 of_node_put(ddc_node);
1619 } else {
1620 dev_dbg(hdmi->dev, "no ddc property found\n");
1621 }
1622
1623 irq = platform_get_irq(pdev, 0);
1624 if (irq < 0)
1625 return irq;
1626
1627 ret = devm_request_threaded_irq(dev, irq, imx_hdmi_hardirq,
1628 imx_hdmi_irq, IRQF_SHARED,
1629 dev_name(dev), hdmi);
1630 if (ret)
1631 return ret;
1632
1633 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1634 hdmi->regs = devm_ioremap_resource(dev, iores);
1635 if (IS_ERR(hdmi->regs))
1636 return PTR_ERR(hdmi->regs);
1637
1638 hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
1639 if (IS_ERR(hdmi->regmap))
1640 return PTR_ERR(hdmi->regmap);
1641
1642 hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
1643 if (IS_ERR(hdmi->isfr_clk)) {
1644 ret = PTR_ERR(hdmi->isfr_clk);
1645 dev_err(hdmi->dev,
1646 "Unable to get HDMI isfr clk: %d\n", ret);
1647 return ret;
1648 }
1649
1650 ret = clk_prepare_enable(hdmi->isfr_clk);
1651 if (ret) {
1652 dev_err(hdmi->dev,
1653 "Cannot enable HDMI isfr clock: %d\n", ret);
1654 return ret;
1655 }
1656
1657 hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb");
1658 if (IS_ERR(hdmi->iahb_clk)) {
1659 ret = PTR_ERR(hdmi->iahb_clk);
1660 dev_err(hdmi->dev,
1661 "Unable to get HDMI iahb clk: %d\n", ret);
1662 goto err_isfr;
1663 }
1664
1665 ret = clk_prepare_enable(hdmi->iahb_clk);
1666 if (ret) {
1667 dev_err(hdmi->dev,
1668 "Cannot enable HDMI iahb clock: %d\n", ret);
1669 goto err_isfr;
1670 }
1671
1672 /* Product and revision IDs */
1673 dev_info(dev,
1674 "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n",
1675 hdmi_readb(hdmi, HDMI_DESIGN_ID),
1676 hdmi_readb(hdmi, HDMI_REVISION_ID),
1677 hdmi_readb(hdmi, HDMI_PRODUCT_ID0),
1678 hdmi_readb(hdmi, HDMI_PRODUCT_ID1));
1679
1680 initialize_hdmi_ih_mutes(hdmi);
1681
1682 /*
1683 * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
1684 * N and cts values before enabling phy
1685 */
1686 hdmi_init_clk_regenerator(hdmi);
1687
1688 /*
1689 * Configure registers related to HDMI interrupt
1690 * generation before registering IRQ.
1691 */
1692 hdmi_writeb(hdmi, HDMI_PHY_HPD, HDMI_PHY_POL0);
1693
1694 /* Clear Hotplug interrupts */
1695 hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
1696
1697 ret = imx_hdmi_fb_registered(hdmi);
1698 if (ret)
1699 goto err_iahb;
1700
1701 ret = imx_hdmi_register(drm, hdmi);
1702 if (ret)
1703 goto err_iahb;
1704
1705 /* Unmute interrupts */
1706 hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
1707
1708 dev_set_drvdata(dev, hdmi);
1709
1710 return 0;
1711
1712err_iahb:
1713 clk_disable_unprepare(hdmi->iahb_clk);
1714err_isfr:
1715 clk_disable_unprepare(hdmi->isfr_clk);
1716
1717 return ret;
1718}
1719
1720static void imx_hdmi_unbind(struct device *dev, struct device *master,
1721 void *data)
1722{
1723 struct imx_hdmi *hdmi = dev_get_drvdata(dev);
1724
1725 /* Disable all interrupts */
1726 hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
1727
1728 hdmi->connector.funcs->destroy(&hdmi->connector);
1729 hdmi->encoder.funcs->destroy(&hdmi->encoder);
1730
1731 clk_disable_unprepare(hdmi->iahb_clk);
1732 clk_disable_unprepare(hdmi->isfr_clk);
1733 i2c_put_adapter(hdmi->ddc);
1734}
1735
1736static const struct component_ops hdmi_ops = {
1737 .bind = imx_hdmi_bind,
1738 .unbind = imx_hdmi_unbind,
1739};
1740
1741static int imx_hdmi_platform_probe(struct platform_device *pdev)
1742{
1743 return component_add(&pdev->dev, &hdmi_ops);
1744}
1745
1746static int imx_hdmi_platform_remove(struct platform_device *pdev)
1747{
1748 component_del(&pdev->dev, &hdmi_ops);
1749 return 0;
1750}
1751
1752static struct platform_driver imx_hdmi_driver = {
1753 .probe = imx_hdmi_platform_probe,
1754 .remove = imx_hdmi_platform_remove,
1755 .driver = {
1756 .name = "imx-hdmi",
1757 .of_match_table = imx_hdmi_dt_ids,
1758 },
1759};
1760
1761module_platform_driver(imx_hdmi_driver);
1762
1763MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
1764MODULE_DESCRIPTION("i.MX6 HDMI transmitter driver");
1765MODULE_LICENSE("GPL");
1766MODULE_ALIAS("platform:imx-hdmi");
diff --git a/drivers/gpu/drm/imx/imx-hdmi.h b/drivers/gpu/drm/imx/imx-hdmi.h
new file mode 100644
index 000000000000..39b677689db6
--- /dev/null
+++ b/drivers/gpu/drm/imx/imx-hdmi.h
@@ -0,0 +1,1032 @@
1/*
2 * Copyright (C) 2011 Freescale Semiconductor, Inc.
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 as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#ifndef __IMX_HDMI_H__
11#define __IMX_HDMI_H__
12
13/* Identification Registers */
14#define HDMI_DESIGN_ID 0x0000
15#define HDMI_REVISION_ID 0x0001
16#define HDMI_PRODUCT_ID0 0x0002
17#define HDMI_PRODUCT_ID1 0x0003
18#define HDMI_CONFIG0_ID 0x0004
19#define HDMI_CONFIG1_ID 0x0005
20#define HDMI_CONFIG2_ID 0x0006
21#define HDMI_CONFIG3_ID 0x0007
22
23/* Interrupt Registers */
24#define HDMI_IH_FC_STAT0 0x0100
25#define HDMI_IH_FC_STAT1 0x0101
26#define HDMI_IH_FC_STAT2 0x0102
27#define HDMI_IH_AS_STAT0 0x0103
28#define HDMI_IH_PHY_STAT0 0x0104
29#define HDMI_IH_I2CM_STAT0 0x0105
30#define HDMI_IH_CEC_STAT0 0x0106
31#define HDMI_IH_VP_STAT0 0x0107
32#define HDMI_IH_I2CMPHY_STAT0 0x0108
33#define HDMI_IH_AHBDMAAUD_STAT0 0x0109
34
35#define HDMI_IH_MUTE_FC_STAT0 0x0180
36#define HDMI_IH_MUTE_FC_STAT1 0x0181
37#define HDMI_IH_MUTE_FC_STAT2 0x0182
38#define HDMI_IH_MUTE_AS_STAT0 0x0183
39#define HDMI_IH_MUTE_PHY_STAT0 0x0184
40#define HDMI_IH_MUTE_I2CM_STAT0 0x0185
41#define HDMI_IH_MUTE_CEC_STAT0 0x0186
42#define HDMI_IH_MUTE_VP_STAT0 0x0187
43#define HDMI_IH_MUTE_I2CMPHY_STAT0 0x0188
44#define HDMI_IH_MUTE_AHBDMAAUD_STAT0 0x0189
45#define HDMI_IH_MUTE 0x01FF
46
47/* Video Sample Registers */
48#define HDMI_TX_INVID0 0x0200
49#define HDMI_TX_INSTUFFING 0x0201
50#define HDMI_TX_GYDATA0 0x0202
51#define HDMI_TX_GYDATA1 0x0203
52#define HDMI_TX_RCRDATA0 0x0204
53#define HDMI_TX_RCRDATA1 0x0205
54#define HDMI_TX_BCBDATA0 0x0206
55#define HDMI_TX_BCBDATA1 0x0207
56
57/* Video Packetizer Registers */
58#define HDMI_VP_STATUS 0x0800
59#define HDMI_VP_PR_CD 0x0801
60#define HDMI_VP_STUFF 0x0802
61#define HDMI_VP_REMAP 0x0803
62#define HDMI_VP_CONF 0x0804
63#define HDMI_VP_STAT 0x0805
64#define HDMI_VP_INT 0x0806
65#define HDMI_VP_MASK 0x0807
66#define HDMI_VP_POL 0x0808
67
68/* Frame Composer Registers */
69#define HDMI_FC_INVIDCONF 0x1000
70#define HDMI_FC_INHACTV0 0x1001
71#define HDMI_FC_INHACTV1 0x1002
72#define HDMI_FC_INHBLANK0 0x1003
73#define HDMI_FC_INHBLANK1 0x1004
74#define HDMI_FC_INVACTV0 0x1005
75#define HDMI_FC_INVACTV1 0x1006
76#define HDMI_FC_INVBLANK 0x1007
77#define HDMI_FC_HSYNCINDELAY0 0x1008
78#define HDMI_FC_HSYNCINDELAY1 0x1009
79#define HDMI_FC_HSYNCINWIDTH0 0x100A
80#define HDMI_FC_HSYNCINWIDTH1 0x100B
81#define HDMI_FC_VSYNCINDELAY 0x100C
82#define HDMI_FC_VSYNCINWIDTH 0x100D
83#define HDMI_FC_INFREQ0 0x100E
84#define HDMI_FC_INFREQ1 0x100F
85#define HDMI_FC_INFREQ2 0x1010
86#define HDMI_FC_CTRLDUR 0x1011
87#define HDMI_FC_EXCTRLDUR 0x1012
88#define HDMI_FC_EXCTRLSPAC 0x1013
89#define HDMI_FC_CH0PREAM 0x1014
90#define HDMI_FC_CH1PREAM 0x1015
91#define HDMI_FC_CH2PREAM 0x1016
92#define HDMI_FC_AVICONF3 0x1017
93#define HDMI_FC_GCP 0x1018
94#define HDMI_FC_AVICONF0 0x1019
95#define HDMI_FC_AVICONF1 0x101A
96#define HDMI_FC_AVICONF2 0x101B
97#define HDMI_FC_AVIVID 0x101C
98#define HDMI_FC_AVIETB0 0x101D
99#define HDMI_FC_AVIETB1 0x101E
100#define HDMI_FC_AVISBB0 0x101F
101#define HDMI_FC_AVISBB1 0x1020
102#define HDMI_FC_AVIELB0 0x1021
103#define HDMI_FC_AVIELB1 0x1022
104#define HDMI_FC_AVISRB0 0x1023
105#define HDMI_FC_AVISRB1 0x1024
106#define HDMI_FC_AUDICONF0 0x1025
107#define HDMI_FC_AUDICONF1 0x1026
108#define HDMI_FC_AUDICONF2 0x1027
109#define HDMI_FC_AUDICONF3 0x1028
110#define HDMI_FC_VSDIEEEID0 0x1029
111#define HDMI_FC_VSDSIZE 0x102A
112#define HDMI_FC_VSDIEEEID1 0x1030
113#define HDMI_FC_VSDIEEEID2 0x1031
114#define HDMI_FC_VSDPAYLOAD0 0x1032
115#define HDMI_FC_VSDPAYLOAD1 0x1033
116#define HDMI_FC_VSDPAYLOAD2 0x1034
117#define HDMI_FC_VSDPAYLOAD3 0x1035
118#define HDMI_FC_VSDPAYLOAD4 0x1036
119#define HDMI_FC_VSDPAYLOAD5 0x1037
120#define HDMI_FC_VSDPAYLOAD6 0x1038
121#define HDMI_FC_VSDPAYLOAD7 0x1039
122#define HDMI_FC_VSDPAYLOAD8 0x103A
123#define HDMI_FC_VSDPAYLOAD9 0x103B
124#define HDMI_FC_VSDPAYLOAD10 0x103C
125#define HDMI_FC_VSDPAYLOAD11 0x103D
126#define HDMI_FC_VSDPAYLOAD12 0x103E
127#define HDMI_FC_VSDPAYLOAD13 0x103F
128#define HDMI_FC_VSDPAYLOAD14 0x1040
129#define HDMI_FC_VSDPAYLOAD15 0x1041
130#define HDMI_FC_VSDPAYLOAD16 0x1042
131#define HDMI_FC_VSDPAYLOAD17 0x1043
132#define HDMI_FC_VSDPAYLOAD18 0x1044
133#define HDMI_FC_VSDPAYLOAD19 0x1045
134#define HDMI_FC_VSDPAYLOAD20 0x1046
135#define HDMI_FC_VSDPAYLOAD21 0x1047
136#define HDMI_FC_VSDPAYLOAD22 0x1048
137#define HDMI_FC_VSDPAYLOAD23 0x1049
138#define HDMI_FC_SPDVENDORNAME0 0x104A
139#define HDMI_FC_SPDVENDORNAME1 0x104B
140#define HDMI_FC_SPDVENDORNAME2 0x104C
141#define HDMI_FC_SPDVENDORNAME3 0x104D
142#define HDMI_FC_SPDVENDORNAME4 0x104E
143#define HDMI_FC_SPDVENDORNAME5 0x104F
144#define HDMI_FC_SPDVENDORNAME6 0x1050
145#define HDMI_FC_SPDVENDORNAME7 0x1051
146#define HDMI_FC_SDPPRODUCTNAME0 0x1052
147#define HDMI_FC_SDPPRODUCTNAME1 0x1053
148#define HDMI_FC_SDPPRODUCTNAME2 0x1054
149#define HDMI_FC_SDPPRODUCTNAME3 0x1055
150#define HDMI_FC_SDPPRODUCTNAME4 0x1056
151#define HDMI_FC_SDPPRODUCTNAME5 0x1057
152#define HDMI_FC_SDPPRODUCTNAME6 0x1058
153#define HDMI_FC_SDPPRODUCTNAME7 0x1059
154#define HDMI_FC_SDPPRODUCTNAME8 0x105A
155#define HDMI_FC_SDPPRODUCTNAME9 0x105B
156#define HDMI_FC_SDPPRODUCTNAME10 0x105C
157#define HDMI_FC_SDPPRODUCTNAME11 0x105D
158#define HDMI_FC_SDPPRODUCTNAME12 0x105E
159#define HDMI_FC_SDPPRODUCTNAME13 0x105F
160#define HDMI_FC_SDPPRODUCTNAME14 0x1060
161#define HDMI_FC_SPDPRODUCTNAME15 0x1061
162#define HDMI_FC_SPDDEVICEINF 0x1062
163#define HDMI_FC_AUDSCONF 0x1063
164#define HDMI_FC_AUDSSTAT 0x1064
165#define HDMI_FC_DATACH0FILL 0x1070
166#define HDMI_FC_DATACH1FILL 0x1071
167#define HDMI_FC_DATACH2FILL 0x1072
168#define HDMI_FC_CTRLQHIGH 0x1073
169#define HDMI_FC_CTRLQLOW 0x1074
170#define HDMI_FC_ACP0 0x1075
171#define HDMI_FC_ACP28 0x1076
172#define HDMI_FC_ACP27 0x1077
173#define HDMI_FC_ACP26 0x1078
174#define HDMI_FC_ACP25 0x1079
175#define HDMI_FC_ACP24 0x107A
176#define HDMI_FC_ACP23 0x107B
177#define HDMI_FC_ACP22 0x107C
178#define HDMI_FC_ACP21 0x107D
179#define HDMI_FC_ACP20 0x107E
180#define HDMI_FC_ACP19 0x107F
181#define HDMI_FC_ACP18 0x1080
182#define HDMI_FC_ACP17 0x1081
183#define HDMI_FC_ACP16 0x1082
184#define HDMI_FC_ACP15 0x1083
185#define HDMI_FC_ACP14 0x1084
186#define HDMI_FC_ACP13 0x1085
187#define HDMI_FC_ACP12 0x1086
188#define HDMI_FC_ACP11 0x1087
189#define HDMI_FC_ACP10 0x1088
190#define HDMI_FC_ACP9 0x1089
191#define HDMI_FC_ACP8 0x108A
192#define HDMI_FC_ACP7 0x108B
193#define HDMI_FC_ACP6 0x108C
194#define HDMI_FC_ACP5 0x108D
195#define HDMI_FC_ACP4 0x108E
196#define HDMI_FC_ACP3 0x108F
197#define HDMI_FC_ACP2 0x1090
198#define HDMI_FC_ACP1 0x1091
199#define HDMI_FC_ISCR1_0 0x1092
200#define HDMI_FC_ISCR1_16 0x1093
201#define HDMI_FC_ISCR1_15 0x1094
202#define HDMI_FC_ISCR1_14 0x1095
203#define HDMI_FC_ISCR1_13 0x1096
204#define HDMI_FC_ISCR1_12 0x1097
205#define HDMI_FC_ISCR1_11 0x1098
206#define HDMI_FC_ISCR1_10 0x1099
207#define HDMI_FC_ISCR1_9 0x109A
208#define HDMI_FC_ISCR1_8 0x109B
209#define HDMI_FC_ISCR1_7 0x109C
210#define HDMI_FC_ISCR1_6 0x109D
211#define HDMI_FC_ISCR1_5 0x109E
212#define HDMI_FC_ISCR1_4 0x109F
213#define HDMI_FC_ISCR1_3 0x10A0
214#define HDMI_FC_ISCR1_2 0x10A1
215#define HDMI_FC_ISCR1_1 0x10A2
216#define HDMI_FC_ISCR2_15 0x10A3
217#define HDMI_FC_ISCR2_14 0x10A4
218#define HDMI_FC_ISCR2_13 0x10A5
219#define HDMI_FC_ISCR2_12 0x10A6
220#define HDMI_FC_ISCR2_11 0x10A7
221#define HDMI_FC_ISCR2_10 0x10A8
222#define HDMI_FC_ISCR2_9 0x10A9
223#define HDMI_FC_ISCR2_8 0x10AA
224#define HDMI_FC_ISCR2_7 0x10AB
225#define HDMI_FC_ISCR2_6 0x10AC
226#define HDMI_FC_ISCR2_5 0x10AD
227#define HDMI_FC_ISCR2_4 0x10AE
228#define HDMI_FC_ISCR2_3 0x10AF
229#define HDMI_FC_ISCR2_2 0x10B0
230#define HDMI_FC_ISCR2_1 0x10B1
231#define HDMI_FC_ISCR2_0 0x10B2
232#define HDMI_FC_DATAUTO0 0x10B3
233#define HDMI_FC_DATAUTO1 0x10B4
234#define HDMI_FC_DATAUTO2 0x10B5
235#define HDMI_FC_DATMAN 0x10B6
236#define HDMI_FC_DATAUTO3 0x10B7
237#define HDMI_FC_RDRB0 0x10B8
238#define HDMI_FC_RDRB1 0x10B9
239#define HDMI_FC_RDRB2 0x10BA
240#define HDMI_FC_RDRB3 0x10BB
241#define HDMI_FC_RDRB4 0x10BC
242#define HDMI_FC_RDRB5 0x10BD
243#define HDMI_FC_RDRB6 0x10BE
244#define HDMI_FC_RDRB7 0x10BF
245#define HDMI_FC_STAT0 0x10D0
246#define HDMI_FC_INT0 0x10D1
247#define HDMI_FC_MASK0 0x10D2
248#define HDMI_FC_POL0 0x10D3
249#define HDMI_FC_STAT1 0x10D4
250#define HDMI_FC_INT1 0x10D5
251#define HDMI_FC_MASK1 0x10D6
252#define HDMI_FC_POL1 0x10D7
253#define HDMI_FC_STAT2 0x10D8
254#define HDMI_FC_INT2 0x10D9
255#define HDMI_FC_MASK2 0x10DA
256#define HDMI_FC_POL2 0x10DB
257#define HDMI_FC_PRCONF 0x10E0
258
259#define HDMI_FC_GMD_STAT 0x1100
260#define HDMI_FC_GMD_EN 0x1101
261#define HDMI_FC_GMD_UP 0x1102
262#define HDMI_FC_GMD_CONF 0x1103
263#define HDMI_FC_GMD_HB 0x1104
264#define HDMI_FC_GMD_PB0 0x1105
265#define HDMI_FC_GMD_PB1 0x1106
266#define HDMI_FC_GMD_PB2 0x1107
267#define HDMI_FC_GMD_PB3 0x1108
268#define HDMI_FC_GMD_PB4 0x1109
269#define HDMI_FC_GMD_PB5 0x110A
270#define HDMI_FC_GMD_PB6 0x110B
271#define HDMI_FC_GMD_PB7 0x110C
272#define HDMI_FC_GMD_PB8 0x110D
273#define HDMI_FC_GMD_PB9 0x110E
274#define HDMI_FC_GMD_PB10 0x110F
275#define HDMI_FC_GMD_PB11 0x1110
276#define HDMI_FC_GMD_PB12 0x1111
277#define HDMI_FC_GMD_PB13 0x1112
278#define HDMI_FC_GMD_PB14 0x1113
279#define HDMI_FC_GMD_PB15 0x1114
280#define HDMI_FC_GMD_PB16 0x1115
281#define HDMI_FC_GMD_PB17 0x1116
282#define HDMI_FC_GMD_PB18 0x1117
283#define HDMI_FC_GMD_PB19 0x1118
284#define HDMI_FC_GMD_PB20 0x1119
285#define HDMI_FC_GMD_PB21 0x111A
286#define HDMI_FC_GMD_PB22 0x111B
287#define HDMI_FC_GMD_PB23 0x111C
288#define HDMI_FC_GMD_PB24 0x111D
289#define HDMI_FC_GMD_PB25 0x111E
290#define HDMI_FC_GMD_PB26 0x111F
291#define HDMI_FC_GMD_PB27 0x1120
292
293#define HDMI_FC_DBGFORCE 0x1200
294#define HDMI_FC_DBGAUD0CH0 0x1201
295#define HDMI_FC_DBGAUD1CH0 0x1202
296#define HDMI_FC_DBGAUD2CH0 0x1203
297#define HDMI_FC_DBGAUD0CH1 0x1204
298#define HDMI_FC_DBGAUD1CH1 0x1205
299#define HDMI_FC_DBGAUD2CH1 0x1206
300#define HDMI_FC_DBGAUD0CH2 0x1207
301#define HDMI_FC_DBGAUD1CH2 0x1208
302#define HDMI_FC_DBGAUD2CH2 0x1209
303#define HDMI_FC_DBGAUD0CH3 0x120A
304#define HDMI_FC_DBGAUD1CH3 0x120B
305#define HDMI_FC_DBGAUD2CH3 0x120C
306#define HDMI_FC_DBGAUD0CH4 0x120D
307#define HDMI_FC_DBGAUD1CH4 0x120E
308#define HDMI_FC_DBGAUD2CH4 0x120F
309#define HDMI_FC_DBGAUD0CH5 0x1210
310#define HDMI_FC_DBGAUD1CH5 0x1211
311#define HDMI_FC_DBGAUD2CH5 0x1212
312#define HDMI_FC_DBGAUD0CH6 0x1213
313#define HDMI_FC_DBGAUD1CH6 0x1214
314#define HDMI_FC_DBGAUD2CH6 0x1215
315#define HDMI_FC_DBGAUD0CH7 0x1216
316#define HDMI_FC_DBGAUD1CH7 0x1217
317#define HDMI_FC_DBGAUD2CH7 0x1218
318#define HDMI_FC_DBGTMDS0 0x1219
319#define HDMI_FC_DBGTMDS1 0x121A
320#define HDMI_FC_DBGTMDS2 0x121B
321
322/* HDMI Source PHY Registers */
323#define HDMI_PHY_CONF0 0x3000
324#define HDMI_PHY_TST0 0x3001
325#define HDMI_PHY_TST1 0x3002
326#define HDMI_PHY_TST2 0x3003
327#define HDMI_PHY_STAT0 0x3004
328#define HDMI_PHY_INT0 0x3005
329#define HDMI_PHY_MASK0 0x3006
330#define HDMI_PHY_POL0 0x3007
331
332/* HDMI Master PHY Registers */
333#define HDMI_PHY_I2CM_SLAVE_ADDR 0x3020
334#define HDMI_PHY_I2CM_ADDRESS_ADDR 0x3021
335#define HDMI_PHY_I2CM_DATAO_1_ADDR 0x3022
336#define HDMI_PHY_I2CM_DATAO_0_ADDR 0x3023
337#define HDMI_PHY_I2CM_DATAI_1_ADDR 0x3024
338#define HDMI_PHY_I2CM_DATAI_0_ADDR 0x3025
339#define HDMI_PHY_I2CM_OPERATION_ADDR 0x3026
340#define HDMI_PHY_I2CM_INT_ADDR 0x3027
341#define HDMI_PHY_I2CM_CTLINT_ADDR 0x3028
342#define HDMI_PHY_I2CM_DIV_ADDR 0x3029
343#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR 0x302a
344#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR 0x302b
345#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR 0x302c
346#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR 0x302d
347#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR 0x302e
348#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR 0x302f
349#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR 0x3030
350#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR 0x3031
351#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR 0x3032
352
353/* Audio Sampler Registers */
354#define HDMI_AUD_CONF0 0x3100
355#define HDMI_AUD_CONF1 0x3101
356#define HDMI_AUD_INT 0x3102
357#define HDMI_AUD_CONF2 0x3103
358#define HDMI_AUD_N1 0x3200
359#define HDMI_AUD_N2 0x3201
360#define HDMI_AUD_N3 0x3202
361#define HDMI_AUD_CTS1 0x3203
362#define HDMI_AUD_CTS2 0x3204
363#define HDMI_AUD_CTS3 0x3205
364#define HDMI_AUD_INPUTCLKFS 0x3206
365#define HDMI_AUD_SPDIFINT 0x3302
366#define HDMI_AUD_CONF0_HBR 0x3400
367#define HDMI_AUD_HBR_STATUS 0x3401
368#define HDMI_AUD_HBR_INT 0x3402
369#define HDMI_AUD_HBR_POL 0x3403
370#define HDMI_AUD_HBR_MASK 0x3404
371
372/*
373 * Generic Parallel Audio Interface Registers
374 * Not used as GPAUD interface is not enabled in hw
375 */
376#define HDMI_GP_CONF0 0x3500
377#define HDMI_GP_CONF1 0x3501
378#define HDMI_GP_CONF2 0x3502
379#define HDMI_GP_STAT 0x3503
380#define HDMI_GP_INT 0x3504
381#define HDMI_GP_MASK 0x3505
382#define HDMI_GP_POL 0x3506
383
384/* Audio DMA Registers */
385#define HDMI_AHB_DMA_CONF0 0x3600
386#define HDMI_AHB_DMA_START 0x3601
387#define HDMI_AHB_DMA_STOP 0x3602
388#define HDMI_AHB_DMA_THRSLD 0x3603
389#define HDMI_AHB_DMA_STRADDR0 0x3604
390#define HDMI_AHB_DMA_STRADDR1 0x3605
391#define HDMI_AHB_DMA_STRADDR2 0x3606
392#define HDMI_AHB_DMA_STRADDR3 0x3607
393#define HDMI_AHB_DMA_STPADDR0 0x3608
394#define HDMI_AHB_DMA_STPADDR1 0x3609
395#define HDMI_AHB_DMA_STPADDR2 0x360a
396#define HDMI_AHB_DMA_STPADDR3 0x360b
397#define HDMI_AHB_DMA_BSTADDR0 0x360c
398#define HDMI_AHB_DMA_BSTADDR1 0x360d
399#define HDMI_AHB_DMA_BSTADDR2 0x360e
400#define HDMI_AHB_DMA_BSTADDR3 0x360f
401#define HDMI_AHB_DMA_MBLENGTH0 0x3610
402#define HDMI_AHB_DMA_MBLENGTH1 0x3611
403#define HDMI_AHB_DMA_STAT 0x3612
404#define HDMI_AHB_DMA_INT 0x3613
405#define HDMI_AHB_DMA_MASK 0x3614
406#define HDMI_AHB_DMA_POL 0x3615
407#define HDMI_AHB_DMA_CONF1 0x3616
408#define HDMI_AHB_DMA_BUFFSTAT 0x3617
409#define HDMI_AHB_DMA_BUFFINT 0x3618
410#define HDMI_AHB_DMA_BUFFMASK 0x3619
411#define HDMI_AHB_DMA_BUFFPOL 0x361a
412
413/* Main Controller Registers */
414#define HDMI_MC_SFRDIV 0x4000
415#define HDMI_MC_CLKDIS 0x4001
416#define HDMI_MC_SWRSTZ 0x4002
417#define HDMI_MC_OPCTRL 0x4003
418#define HDMI_MC_FLOWCTRL 0x4004
419#define HDMI_MC_PHYRSTZ 0x4005
420#define HDMI_MC_LOCKONCLOCK 0x4006
421#define HDMI_MC_HEACPHY_RST 0x4007
422
423/* Color Space Converter Registers */
424#define HDMI_CSC_CFG 0x4100
425#define HDMI_CSC_SCALE 0x4101
426#define HDMI_CSC_COEF_A1_MSB 0x4102
427#define HDMI_CSC_COEF_A1_LSB 0x4103
428#define HDMI_CSC_COEF_A2_MSB 0x4104
429#define HDMI_CSC_COEF_A2_LSB 0x4105
430#define HDMI_CSC_COEF_A3_MSB 0x4106
431#define HDMI_CSC_COEF_A3_LSB 0x4107
432#define HDMI_CSC_COEF_A4_MSB 0x4108
433#define HDMI_CSC_COEF_A4_LSB 0x4109
434#define HDMI_CSC_COEF_B1_MSB 0x410A
435#define HDMI_CSC_COEF_B1_LSB 0x410B
436#define HDMI_CSC_COEF_B2_MSB 0x410C
437#define HDMI_CSC_COEF_B2_LSB 0x410D
438#define HDMI_CSC_COEF_B3_MSB 0x410E
439#define HDMI_CSC_COEF_B3_LSB 0x410F
440#define HDMI_CSC_COEF_B4_MSB 0x4110
441#define HDMI_CSC_COEF_B4_LSB 0x4111
442#define HDMI_CSC_COEF_C1_MSB 0x4112
443#define HDMI_CSC_COEF_C1_LSB 0x4113
444#define HDMI_CSC_COEF_C2_MSB 0x4114
445#define HDMI_CSC_COEF_C2_LSB 0x4115
446#define HDMI_CSC_COEF_C3_MSB 0x4116
447#define HDMI_CSC_COEF_C3_LSB 0x4117
448#define HDMI_CSC_COEF_C4_MSB 0x4118
449#define HDMI_CSC_COEF_C4_LSB 0x4119
450
451/* HDCP Encryption Engine Registers */
452#define HDMI_A_HDCPCFG0 0x5000
453#define HDMI_A_HDCPCFG1 0x5001
454#define HDMI_A_HDCPOBS0 0x5002
455#define HDMI_A_HDCPOBS1 0x5003
456#define HDMI_A_HDCPOBS2 0x5004
457#define HDMI_A_HDCPOBS3 0x5005
458#define HDMI_A_APIINTCLR 0x5006
459#define HDMI_A_APIINTSTAT 0x5007
460#define HDMI_A_APIINTMSK 0x5008
461#define HDMI_A_VIDPOLCFG 0x5009
462#define HDMI_A_OESSWCFG 0x500A
463#define HDMI_A_TIMER1SETUP0 0x500B
464#define HDMI_A_TIMER1SETUP1 0x500C
465#define HDMI_A_TIMER2SETUP0 0x500D
466#define HDMI_A_TIMER2SETUP1 0x500E
467#define HDMI_A_100MSCFG 0x500F
468#define HDMI_A_2SCFG0 0x5010
469#define HDMI_A_2SCFG1 0x5011
470#define HDMI_A_5SCFG0 0x5012
471#define HDMI_A_5SCFG1 0x5013
472#define HDMI_A_SRMVERLSB 0x5014
473#define HDMI_A_SRMVERMSB 0x5015
474#define HDMI_A_SRMCTRL 0x5016
475#define HDMI_A_SFRSETUP 0x5017
476#define HDMI_A_I2CHSETUP 0x5018
477#define HDMI_A_INTSETUP 0x5019
478#define HDMI_A_PRESETUP 0x501A
479#define HDMI_A_SRM_BASE 0x5020
480
481/* CEC Engine Registers */
482#define HDMI_CEC_CTRL 0x7D00
483#define HDMI_CEC_STAT 0x7D01
484#define HDMI_CEC_MASK 0x7D02
485#define HDMI_CEC_POLARITY 0x7D03
486#define HDMI_CEC_INT 0x7D04
487#define HDMI_CEC_ADDR_L 0x7D05
488#define HDMI_CEC_ADDR_H 0x7D06
489#define HDMI_CEC_TX_CNT 0x7D07
490#define HDMI_CEC_RX_CNT 0x7D08
491#define HDMI_CEC_TX_DATA0 0x7D10
492#define HDMI_CEC_TX_DATA1 0x7D11
493#define HDMI_CEC_TX_DATA2 0x7D12
494#define HDMI_CEC_TX_DATA3 0x7D13
495#define HDMI_CEC_TX_DATA4 0x7D14
496#define HDMI_CEC_TX_DATA5 0x7D15
497#define HDMI_CEC_TX_DATA6 0x7D16
498#define HDMI_CEC_TX_DATA7 0x7D17
499#define HDMI_CEC_TX_DATA8 0x7D18
500#define HDMI_CEC_TX_DATA9 0x7D19
501#define HDMI_CEC_TX_DATA10 0x7D1a
502#define HDMI_CEC_TX_DATA11 0x7D1b
503#define HDMI_CEC_TX_DATA12 0x7D1c
504#define HDMI_CEC_TX_DATA13 0x7D1d
505#define HDMI_CEC_TX_DATA14 0x7D1e
506#define HDMI_CEC_TX_DATA15 0x7D1f
507#define HDMI_CEC_RX_DATA0 0x7D20
508#define HDMI_CEC_RX_DATA1 0x7D21
509#define HDMI_CEC_RX_DATA2 0x7D22
510#define HDMI_CEC_RX_DATA3 0x7D23
511#define HDMI_CEC_RX_DATA4 0x7D24
512#define HDMI_CEC_RX_DATA5 0x7D25
513#define HDMI_CEC_RX_DATA6 0x7D26
514#define HDMI_CEC_RX_DATA7 0x7D27
515#define HDMI_CEC_RX_DATA8 0x7D28
516#define HDMI_CEC_RX_DATA9 0x7D29
517#define HDMI_CEC_RX_DATA10 0x7D2a
518#define HDMI_CEC_RX_DATA11 0x7D2b
519#define HDMI_CEC_RX_DATA12 0x7D2c
520#define HDMI_CEC_RX_DATA13 0x7D2d
521#define HDMI_CEC_RX_DATA14 0x7D2e
522#define HDMI_CEC_RX_DATA15 0x7D2f
523#define HDMI_CEC_LOCK 0x7D30
524#define HDMI_CEC_WKUPCTRL 0x7D31
525
526/* I2C Master Registers (E-DDC) */
527#define HDMI_I2CM_SLAVE 0x7E00
528#define HDMI_I2CMESS 0x7E01
529#define HDMI_I2CM_DATAO 0x7E02
530#define HDMI_I2CM_DATAI 0x7E03
531#define HDMI_I2CM_OPERATION 0x7E04
532#define HDMI_I2CM_INT 0x7E05
533#define HDMI_I2CM_CTLINT 0x7E06
534#define HDMI_I2CM_DIV 0x7E07
535#define HDMI_I2CM_SEGADDR 0x7E08
536#define HDMI_I2CM_SOFTRSTZ 0x7E09
537#define HDMI_I2CM_SEGPTR 0x7E0A
538#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR 0x7E0B
539#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR 0x7E0C
540#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR 0x7E0D
541#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR 0x7E0E
542#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR 0x7E0F
543#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR 0x7E10
544#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR 0x7E11
545#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12
546
547enum {
548/* IH_FC_INT2 field values */
549 HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
550 HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
551 HDMI_IH_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
552
553/* IH_FC_STAT2 field values */
554 HDMI_IH_FC_STAT2_OVERFLOW_MASK = 0x03,
555 HDMI_IH_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
556 HDMI_IH_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
557
558/* IH_PHY_STAT0 field values */
559 HDMI_IH_PHY_STAT0_RX_SENSE3 = 0x20,
560 HDMI_IH_PHY_STAT0_RX_SENSE2 = 0x10,
561 HDMI_IH_PHY_STAT0_RX_SENSE1 = 0x8,
562 HDMI_IH_PHY_STAT0_RX_SENSE0 = 0x4,
563 HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2,
564 HDMI_IH_PHY_STAT0_HPD = 0x1,
565
566/* IH_MUTE_I2CMPHY_STAT0 field values */
567 HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2,
568 HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1,
569
570/* IH_AHBDMAAUD_STAT0 field values */
571 HDMI_IH_AHBDMAAUD_STAT0_ERROR = 0x20,
572 HDMI_IH_AHBDMAAUD_STAT0_LOST = 0x10,
573 HDMI_IH_AHBDMAAUD_STAT0_RETRY = 0x08,
574 HDMI_IH_AHBDMAAUD_STAT0_DONE = 0x04,
575 HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
576 HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
577
578/* IH_MUTE_FC_STAT2 field values */
579 HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK = 0x03,
580 HDMI_IH_MUTE_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
581 HDMI_IH_MUTE_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
582
583/* IH_MUTE_AHBDMAAUD_STAT0 field values */
584 HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = 0x20,
585 HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = 0x10,
586 HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = 0x08,
587 HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = 0x04,
588 HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
589 HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
590
591/* IH_MUTE field values */
592 HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT = 0x2,
593 HDMI_IH_MUTE_MUTE_ALL_INTERRUPT = 0x1,
594
595/* TX_INVID0 field values */
596 HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_MASK = 0x80,
597 HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_ENABLE = 0x80,
598 HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE = 0x00,
599 HDMI_TX_INVID0_VIDEO_MAPPING_MASK = 0x1F,
600 HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET = 0,
601
602/* TX_INSTUFFING field values */
603 HDMI_TX_INSTUFFING_BDBDATA_STUFFING_MASK = 0x4,
604 HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE = 0x4,
605 HDMI_TX_INSTUFFING_BDBDATA_STUFFING_DISABLE = 0x0,
606 HDMI_TX_INSTUFFING_RCRDATA_STUFFING_MASK = 0x2,
607 HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE = 0x2,
608 HDMI_TX_INSTUFFING_RCRDATA_STUFFING_DISABLE = 0x0,
609 HDMI_TX_INSTUFFING_GYDATA_STUFFING_MASK = 0x1,
610 HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE = 0x1,
611 HDMI_TX_INSTUFFING_GYDATA_STUFFING_DISABLE = 0x0,
612
613/* VP_PR_CD field values */
614 HDMI_VP_PR_CD_COLOR_DEPTH_MASK = 0xF0,
615 HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET = 4,
616 HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK = 0x0F,
617 HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET = 0,
618
619/* VP_STUFF field values */
620 HDMI_VP_STUFF_IDEFAULT_PHASE_MASK = 0x20,
621 HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET = 5,
622 HDMI_VP_STUFF_IFIX_PP_TO_LAST_MASK = 0x10,
623 HDMI_VP_STUFF_IFIX_PP_TO_LAST_OFFSET = 4,
624 HDMI_VP_STUFF_ICX_GOTO_P0_ST_MASK = 0x8,
625 HDMI_VP_STUFF_ICX_GOTO_P0_ST_OFFSET = 3,
626 HDMI_VP_STUFF_YCC422_STUFFING_MASK = 0x4,
627 HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE = 0x4,
628 HDMI_VP_STUFF_YCC422_STUFFING_DIRECT_MODE = 0x0,
629 HDMI_VP_STUFF_PP_STUFFING_MASK = 0x2,
630 HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE = 0x2,
631 HDMI_VP_STUFF_PP_STUFFING_DIRECT_MODE = 0x0,
632 HDMI_VP_STUFF_PR_STUFFING_MASK = 0x1,
633 HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE = 0x1,
634 HDMI_VP_STUFF_PR_STUFFING_DIRECT_MODE = 0x0,
635
636/* VP_CONF field values */
637 HDMI_VP_CONF_BYPASS_EN_MASK = 0x40,
638 HDMI_VP_CONF_BYPASS_EN_ENABLE = 0x40,
639 HDMI_VP_CONF_BYPASS_EN_DISABLE = 0x00,
640 HDMI_VP_CONF_PP_EN_ENMASK = 0x20,
641 HDMI_VP_CONF_PP_EN_ENABLE = 0x20,
642 HDMI_VP_CONF_PP_EN_DISABLE = 0x00,
643 HDMI_VP_CONF_PR_EN_MASK = 0x10,
644 HDMI_VP_CONF_PR_EN_ENABLE = 0x10,
645 HDMI_VP_CONF_PR_EN_DISABLE = 0x00,
646 HDMI_VP_CONF_YCC422_EN_MASK = 0x8,
647 HDMI_VP_CONF_YCC422_EN_ENABLE = 0x8,
648 HDMI_VP_CONF_YCC422_EN_DISABLE = 0x0,
649 HDMI_VP_CONF_BYPASS_SELECT_MASK = 0x4,
650 HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER = 0x4,
651 HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER = 0x0,
652 HDMI_VP_CONF_OUTPUT_SELECTOR_MASK = 0x3,
653 HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS = 0x3,
654 HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422 = 0x1,
655 HDMI_VP_CONF_OUTPUT_SELECTOR_PP = 0x0,
656
657/* VP_REMAP field values */
658 HDMI_VP_REMAP_MASK = 0x3,
659 HDMI_VP_REMAP_YCC422_24bit = 0x2,
660 HDMI_VP_REMAP_YCC422_20bit = 0x1,
661 HDMI_VP_REMAP_YCC422_16bit = 0x0,
662
663/* FC_INVIDCONF field values */
664 HDMI_FC_INVIDCONF_HDCP_KEEPOUT_MASK = 0x80,
665 HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE = 0x80,
666 HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE = 0x00,
667 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_MASK = 0x40,
668 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH = 0x40,
669 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
670 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_MASK = 0x20,
671 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH = 0x20,
672 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
673 HDMI_FC_INVIDCONF_DE_IN_POLARITY_MASK = 0x10,
674 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH = 0x10,
675 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW = 0x00,
676 HDMI_FC_INVIDCONF_DVI_MODEZ_MASK = 0x8,
677 HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE = 0x8,
678 HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE = 0x0,
679 HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_MASK = 0x2,
680 HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH = 0x2,
681 HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW = 0x0,
682 HDMI_FC_INVIDCONF_IN_I_P_MASK = 0x1,
683 HDMI_FC_INVIDCONF_IN_I_P_INTERLACED = 0x1,
684 HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE = 0x0,
685
686/* FC_AUDICONF0 field values */
687 HDMI_FC_AUDICONF0_CC_OFFSET = 4,
688 HDMI_FC_AUDICONF0_CC_MASK = 0x70,
689 HDMI_FC_AUDICONF0_CT_OFFSET = 0,
690 HDMI_FC_AUDICONF0_CT_MASK = 0xF,
691
692/* FC_AUDICONF1 field values */
693 HDMI_FC_AUDICONF1_SS_OFFSET = 3,
694 HDMI_FC_AUDICONF1_SS_MASK = 0x18,
695 HDMI_FC_AUDICONF1_SF_OFFSET = 0,
696 HDMI_FC_AUDICONF1_SF_MASK = 0x7,
697
698/* FC_AUDICONF3 field values */
699 HDMI_FC_AUDICONF3_LFEPBL_OFFSET = 5,
700 HDMI_FC_AUDICONF3_LFEPBL_MASK = 0x60,
701 HDMI_FC_AUDICONF3_DM_INH_OFFSET = 4,
702 HDMI_FC_AUDICONF3_DM_INH_MASK = 0x10,
703 HDMI_FC_AUDICONF3_LSV_OFFSET = 0,
704 HDMI_FC_AUDICONF3_LSV_MASK = 0xF,
705
706/* FC_AUDSCHNLS0 field values */
707 HDMI_FC_AUDSCHNLS0_CGMSA_OFFSET = 4,
708 HDMI_FC_AUDSCHNLS0_CGMSA_MASK = 0x30,
709 HDMI_FC_AUDSCHNLS0_COPYRIGHT_OFFSET = 0,
710 HDMI_FC_AUDSCHNLS0_COPYRIGHT_MASK = 0x01,
711
712/* FC_AUDSCHNLS3-6 field values */
713 HDMI_FC_AUDSCHNLS3_OIEC_CH0_OFFSET = 0,
714 HDMI_FC_AUDSCHNLS3_OIEC_CH0_MASK = 0x0f,
715 HDMI_FC_AUDSCHNLS3_OIEC_CH1_OFFSET = 4,
716 HDMI_FC_AUDSCHNLS3_OIEC_CH1_MASK = 0xf0,
717 HDMI_FC_AUDSCHNLS4_OIEC_CH2_OFFSET = 0,
718 HDMI_FC_AUDSCHNLS4_OIEC_CH2_MASK = 0x0f,
719 HDMI_FC_AUDSCHNLS4_OIEC_CH3_OFFSET = 4,
720 HDMI_FC_AUDSCHNLS4_OIEC_CH3_MASK = 0xf0,
721
722 HDMI_FC_AUDSCHNLS5_OIEC_CH0_OFFSET = 0,
723 HDMI_FC_AUDSCHNLS5_OIEC_CH0_MASK = 0x0f,
724 HDMI_FC_AUDSCHNLS5_OIEC_CH1_OFFSET = 4,
725 HDMI_FC_AUDSCHNLS5_OIEC_CH1_MASK = 0xf0,
726 HDMI_FC_AUDSCHNLS6_OIEC_CH2_OFFSET = 0,
727 HDMI_FC_AUDSCHNLS6_OIEC_CH2_MASK = 0x0f,
728 HDMI_FC_AUDSCHNLS6_OIEC_CH3_OFFSET = 4,
729 HDMI_FC_AUDSCHNLS6_OIEC_CH3_MASK = 0xf0,
730
731/* HDMI_FC_AUDSCHNLS7 field values */
732 HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
733 HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
734
735/* HDMI_FC_AUDSCHNLS8 field values */
736 HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
737 HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET = 4,
738 HDMI_FC_AUDSCHNLS8_WORDLEGNTH_MASK = 0x0f,
739 HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET = 0,
740
741/* FC_AUDSCONF field values */
742 HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_MASK = 0xF0,
743 HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_OFFSET = 4,
744 HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_MASK = 0x1,
745 HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_OFFSET = 0,
746 HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT1 = 0x1,
747 HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT0 = 0x0,
748
749/* FC_STAT2 field values */
750 HDMI_FC_STAT2_OVERFLOW_MASK = 0x03,
751 HDMI_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
752 HDMI_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
753
754/* FC_INT2 field values */
755 HDMI_FC_INT2_OVERFLOW_MASK = 0x03,
756 HDMI_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
757 HDMI_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
758
759/* FC_MASK2 field values */
760 HDMI_FC_MASK2_OVERFLOW_MASK = 0x03,
761 HDMI_FC_MASK2_LOW_PRIORITY_OVERFLOW = 0x02,
762 HDMI_FC_MASK2_HIGH_PRIORITY_OVERFLOW = 0x01,
763
764/* FC_PRCONF field values */
765 HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK = 0xF0,
766 HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET = 4,
767 HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK = 0x0F,
768 HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET = 0,
769
770/* FC_AVICONF0-FC_AVICONF3 field values */
771 HDMI_FC_AVICONF0_PIX_FMT_MASK = 0x03,
772 HDMI_FC_AVICONF0_PIX_FMT_RGB = 0x00,
773 HDMI_FC_AVICONF0_PIX_FMT_YCBCR422 = 0x01,
774 HDMI_FC_AVICONF0_PIX_FMT_YCBCR444 = 0x02,
775 HDMI_FC_AVICONF0_ACTIVE_FMT_MASK = 0x40,
776 HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT = 0x40,
777 HDMI_FC_AVICONF0_ACTIVE_FMT_NO_INFO = 0x00,
778 HDMI_FC_AVICONF0_BAR_DATA_MASK = 0x0C,
779 HDMI_FC_AVICONF0_BAR_DATA_NO_DATA = 0x00,
780 HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR = 0x04,
781 HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR = 0x08,
782 HDMI_FC_AVICONF0_BAR_DATA_VERT_HORIZ_BAR = 0x0C,
783 HDMI_FC_AVICONF0_SCAN_INFO_MASK = 0x30,
784 HDMI_FC_AVICONF0_SCAN_INFO_OVERSCAN = 0x10,
785 HDMI_FC_AVICONF0_SCAN_INFO_UNDERSCAN = 0x20,
786 HDMI_FC_AVICONF0_SCAN_INFO_NODATA = 0x00,
787
788 HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_MASK = 0x0F,
789 HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_USE_CODED = 0x08,
790 HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3 = 0x09,
791 HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9 = 0x0A,
792 HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_14_9 = 0x0B,
793 HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_MASK = 0x30,
794 HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_NO_DATA = 0x00,
795 HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3 = 0x10,
796 HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9 = 0x20,
797 HDMI_FC_AVICONF1_COLORIMETRY_MASK = 0xC0,
798 HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA = 0x00,
799 HDMI_FC_AVICONF1_COLORIMETRY_SMPTE = 0x40,
800 HDMI_FC_AVICONF1_COLORIMETRY_ITUR = 0x80,
801 HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO = 0xC0,
802
803 HDMI_FC_AVICONF2_SCALING_MASK = 0x03,
804 HDMI_FC_AVICONF2_SCALING_NONE = 0x00,
805 HDMI_FC_AVICONF2_SCALING_HORIZ = 0x01,
806 HDMI_FC_AVICONF2_SCALING_VERT = 0x02,
807 HDMI_FC_AVICONF2_SCALING_HORIZ_VERT = 0x03,
808 HDMI_FC_AVICONF2_RGB_QUANT_MASK = 0x0C,
809 HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT = 0x00,
810 HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE = 0x04,
811 HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE = 0x08,
812 HDMI_FC_AVICONF2_EXT_COLORIMETRY_MASK = 0x70,
813 HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601 = 0x00,
814 HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709 = 0x10,
815 HDMI_FC_AVICONF2_EXT_COLORIMETRY_SYCC601 = 0x20,
816 HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_YCC601 = 0x30,
817 HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_RGB = 0x40,
818 HDMI_FC_AVICONF2_IT_CONTENT_MASK = 0x80,
819 HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA = 0x00,
820 HDMI_FC_AVICONF2_IT_CONTENT_VALID = 0x80,
821
822 HDMI_FC_AVICONF3_IT_CONTENT_TYPE_MASK = 0x03,
823 HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS = 0x00,
824 HDMI_FC_AVICONF3_IT_CONTENT_TYPE_PHOTO = 0x01,
825 HDMI_FC_AVICONF3_IT_CONTENT_TYPE_CINEMA = 0x02,
826 HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GAME = 0x03,
827 HDMI_FC_AVICONF3_QUANT_RANGE_MASK = 0x0C,
828 HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00,
829 HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04,
830
831/* FC_DBGFORCE field values */
832 HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
833 HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,
834
835/* PHY_CONF0 field values */
836 HDMI_PHY_CONF0_PDZ_MASK = 0x80,
837 HDMI_PHY_CONF0_PDZ_OFFSET = 7,
838 HDMI_PHY_CONF0_ENTMDS_MASK = 0x40,
839 HDMI_PHY_CONF0_ENTMDS_OFFSET = 6,
840 HDMI_PHY_CONF0_SPARECTRL = 0x20,
841 HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10,
842 HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4,
843 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8,
844 HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET = 3,
845 HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK = 0x4,
846 HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET = 2,
847 HDMI_PHY_CONF0_SELDATAENPOL_MASK = 0x2,
848 HDMI_PHY_CONF0_SELDATAENPOL_OFFSET = 1,
849 HDMI_PHY_CONF0_SELDIPIF_MASK = 0x1,
850 HDMI_PHY_CONF0_SELDIPIF_OFFSET = 0,
851
852/* PHY_TST0 field values */
853 HDMI_PHY_TST0_TSTCLR_MASK = 0x20,
854 HDMI_PHY_TST0_TSTCLR_OFFSET = 5,
855 HDMI_PHY_TST0_TSTEN_MASK = 0x10,
856 HDMI_PHY_TST0_TSTEN_OFFSET = 4,
857 HDMI_PHY_TST0_TSTCLK_MASK = 0x1,
858 HDMI_PHY_TST0_TSTCLK_OFFSET = 0,
859
860/* PHY_STAT0 field values */
861 HDMI_PHY_RX_SENSE3 = 0x80,
862 HDMI_PHY_RX_SENSE2 = 0x40,
863 HDMI_PHY_RX_SENSE1 = 0x20,
864 HDMI_PHY_RX_SENSE0 = 0x10,
865 HDMI_PHY_HPD = 0x02,
866 HDMI_PHY_TX_PHY_LOCK = 0x01,
867
868/* PHY_I2CM_SLAVE_ADDR field values */
869 HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69,
870 HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY = 0x49,
871
872/* PHY_I2CM_OPERATION_ADDR field values */
873 HDMI_PHY_I2CM_OPERATION_ADDR_WRITE = 0x10,
874 HDMI_PHY_I2CM_OPERATION_ADDR_READ = 0x1,
875
876/* HDMI_PHY_I2CM_INT_ADDR */
877 HDMI_PHY_I2CM_INT_ADDR_DONE_POL = 0x08,
878 HDMI_PHY_I2CM_INT_ADDR_DONE_MASK = 0x04,
879
880/* HDMI_PHY_I2CM_CTLINT_ADDR */
881 HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL = 0x80,
882 HDMI_PHY_I2CM_CTLINT_ADDR_NAC_MASK = 0x40,
883 HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08,
884 HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04,
885
886/* AUD_CTS3 field values */
887 HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5,
888 HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0,
889 HDMI_AUD_CTS3_N_SHIFT_1 = 0,
890 HDMI_AUD_CTS3_N_SHIFT_16 = 0x20,
891 HDMI_AUD_CTS3_N_SHIFT_32 = 0x40,
892 HDMI_AUD_CTS3_N_SHIFT_64 = 0x60,
893 HDMI_AUD_CTS3_N_SHIFT_128 = 0x80,
894 HDMI_AUD_CTS3_N_SHIFT_256 = 0xa0,
895 /* note that the CTS3 MANUAL bit has been removed
896 from our part. Can't set it, will read as 0. */
897 HDMI_AUD_CTS3_CTS_MANUAL = 0x10,
898 HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f,
899
900/* AHB_DMA_CONF0 field values */
901 HDMI_AHB_DMA_CONF0_SW_FIFO_RST_OFFSET = 7,
902 HDMI_AHB_DMA_CONF0_SW_FIFO_RST_MASK = 0x80,
903 HDMI_AHB_DMA_CONF0_HBR = 0x10,
904 HDMI_AHB_DMA_CONF0_EN_HLOCK_OFFSET = 3,
905 HDMI_AHB_DMA_CONF0_EN_HLOCK_MASK = 0x08,
906 HDMI_AHB_DMA_CONF0_INCR_TYPE_OFFSET = 1,
907 HDMI_AHB_DMA_CONF0_INCR_TYPE_MASK = 0x06,
908 HDMI_AHB_DMA_CONF0_INCR4 = 0x0,
909 HDMI_AHB_DMA_CONF0_INCR8 = 0x2,
910 HDMI_AHB_DMA_CONF0_INCR16 = 0x4,
911 HDMI_AHB_DMA_CONF0_BURST_MODE = 0x1,
912
913/* HDMI_AHB_DMA_START field values */
914 HDMI_AHB_DMA_START_START_OFFSET = 0,
915 HDMI_AHB_DMA_START_START_MASK = 0x01,
916
917/* HDMI_AHB_DMA_STOP field values */
918 HDMI_AHB_DMA_STOP_STOP_OFFSET = 0,
919 HDMI_AHB_DMA_STOP_STOP_MASK = 0x01,
920
921/* AHB_DMA_STAT, AHB_DMA_INT, AHB_DMA_MASK, AHB_DMA_POL field values */
922 HDMI_AHB_DMA_DONE = 0x80,
923 HDMI_AHB_DMA_RETRY_SPLIT = 0x40,
924 HDMI_AHB_DMA_LOSTOWNERSHIP = 0x20,
925 HDMI_AHB_DMA_ERROR = 0x10,
926 HDMI_AHB_DMA_FIFO_THREMPTY = 0x04,
927 HDMI_AHB_DMA_FIFO_FULL = 0x02,
928 HDMI_AHB_DMA_FIFO_EMPTY = 0x01,
929
930/* AHB_DMA_BUFFSTAT, AHB_DMA_BUFFINT,AHB_DMA_BUFFMASK,AHB_DMA_BUFFPOL values */
931 HDMI_AHB_DMA_BUFFSTAT_FULL = 0x02,
932 HDMI_AHB_DMA_BUFFSTAT_EMPTY = 0x01,
933
934/* MC_CLKDIS field values */
935 HDMI_MC_CLKDIS_HDCPCLK_DISABLE = 0x40,
936 HDMI_MC_CLKDIS_CECCLK_DISABLE = 0x20,
937 HDMI_MC_CLKDIS_CSCCLK_DISABLE = 0x10,
938 HDMI_MC_CLKDIS_AUDCLK_DISABLE = 0x8,
939 HDMI_MC_CLKDIS_PREPCLK_DISABLE = 0x4,
940 HDMI_MC_CLKDIS_TMDSCLK_DISABLE = 0x2,
941 HDMI_MC_CLKDIS_PIXELCLK_DISABLE = 0x1,
942
943/* MC_SWRSTZ field values */
944 HDMI_MC_SWRSTZ_TMDSSWRST_REQ = 0x02,
945
946/* MC_FLOWCTRL field values */
947 HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_MASK = 0x1,
948 HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH = 0x1,
949 HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS = 0x0,
950
951/* MC_PHYRSTZ field values */
952 HDMI_MC_PHYRSTZ_ASSERT = 0x0,
953 HDMI_MC_PHYRSTZ_DEASSERT = 0x1,
954
955/* MC_HEACPHY_RST field values */
956 HDMI_MC_HEACPHY_RST_ASSERT = 0x1,
957 HDMI_MC_HEACPHY_RST_DEASSERT = 0x0,
958
959/* CSC_CFG field values */
960 HDMI_CSC_CFG_INTMODE_MASK = 0x30,
961 HDMI_CSC_CFG_INTMODE_OFFSET = 4,
962 HDMI_CSC_CFG_INTMODE_DISABLE = 0x00,
963 HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1 = 0x10,
964 HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA2 = 0x20,
965 HDMI_CSC_CFG_DECMODE_MASK = 0x3,
966 HDMI_CSC_CFG_DECMODE_OFFSET = 0,
967 HDMI_CSC_CFG_DECMODE_DISABLE = 0x0,
968 HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA1 = 0x1,
969 HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA2 = 0x2,
970 HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3 = 0x3,
971
972/* CSC_SCALE field values */
973 HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK = 0xF0,
974 HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP = 0x00,
975 HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP = 0x50,
976 HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP = 0x60,
977 HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP = 0x70,
978 HDMI_CSC_SCALE_CSCSCALE_MASK = 0x03,
979
980/* A_HDCPCFG0 field values */
981 HDMI_A_HDCPCFG0_ELVENA_MASK = 0x80,
982 HDMI_A_HDCPCFG0_ELVENA_ENABLE = 0x80,
983 HDMI_A_HDCPCFG0_ELVENA_DISABLE = 0x00,
984 HDMI_A_HDCPCFG0_I2CFASTMODE_MASK = 0x40,
985 HDMI_A_HDCPCFG0_I2CFASTMODE_ENABLE = 0x40,
986 HDMI_A_HDCPCFG0_I2CFASTMODE_DISABLE = 0x00,
987 HDMI_A_HDCPCFG0_BYPENCRYPTION_MASK = 0x20,
988 HDMI_A_HDCPCFG0_BYPENCRYPTION_ENABLE = 0x20,
989 HDMI_A_HDCPCFG0_BYPENCRYPTION_DISABLE = 0x00,
990 HDMI_A_HDCPCFG0_SYNCRICHECK_MASK = 0x10,
991 HDMI_A_HDCPCFG0_SYNCRICHECK_ENABLE = 0x10,
992 HDMI_A_HDCPCFG0_SYNCRICHECK_DISABLE = 0x00,
993 HDMI_A_HDCPCFG0_AVMUTE_MASK = 0x8,
994 HDMI_A_HDCPCFG0_AVMUTE_ENABLE = 0x8,
995 HDMI_A_HDCPCFG0_AVMUTE_DISABLE = 0x0,
996 HDMI_A_HDCPCFG0_RXDETECT_MASK = 0x4,
997 HDMI_A_HDCPCFG0_RXDETECT_ENABLE = 0x4,
998 HDMI_A_HDCPCFG0_RXDETECT_DISABLE = 0x0,
999 HDMI_A_HDCPCFG0_EN11FEATURE_MASK = 0x2,
1000 HDMI_A_HDCPCFG0_EN11FEATURE_ENABLE = 0x2,
1001 HDMI_A_HDCPCFG0_EN11FEATURE_DISABLE = 0x0,
1002 HDMI_A_HDCPCFG0_HDMIDVI_MASK = 0x1,
1003 HDMI_A_HDCPCFG0_HDMIDVI_HDMI = 0x1,
1004 HDMI_A_HDCPCFG0_HDMIDVI_DVI = 0x0,
1005
1006/* A_HDCPCFG1 field values */
1007 HDMI_A_HDCPCFG1_DISSHA1CHECK_MASK = 0x8,
1008 HDMI_A_HDCPCFG1_DISSHA1CHECK_DISABLE = 0x8,
1009 HDMI_A_HDCPCFG1_DISSHA1CHECK_ENABLE = 0x0,
1010 HDMI_A_HDCPCFG1_PH2UPSHFTENC_MASK = 0x4,
1011 HDMI_A_HDCPCFG1_PH2UPSHFTENC_ENABLE = 0x4,
1012 HDMI_A_HDCPCFG1_PH2UPSHFTENC_DISABLE = 0x0,
1013 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK = 0x2,
1014 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE = 0x2,
1015 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_ENABLE = 0x0,
1016 HDMI_A_HDCPCFG1_SWRESET_MASK = 0x1,
1017 HDMI_A_HDCPCFG1_SWRESET_ASSERT = 0x0,
1018
1019/* A_VIDPOLCFG field values */
1020 HDMI_A_VIDPOLCFG_UNENCRYPTCONF_MASK = 0x60,
1021 HDMI_A_VIDPOLCFG_UNENCRYPTCONF_OFFSET = 5,
1022 HDMI_A_VIDPOLCFG_DATAENPOL_MASK = 0x10,
1023 HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH = 0x10,
1024 HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW = 0x0,
1025 HDMI_A_VIDPOLCFG_VSYNCPOL_MASK = 0x8,
1026 HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_HIGH = 0x8,
1027 HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_LOW = 0x0,
1028 HDMI_A_VIDPOLCFG_HSYNCPOL_MASK = 0x2,
1029 HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2,
1030 HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0,
1031};
1032#endif /* __IMX_HDMI_H__ */
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
new file mode 100644
index 000000000000..2638dc1671d0
--- /dev/null
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -0,0 +1,615 @@
1/*
2 * i.MX drm driver - LVDS display bridge
3 *
4 * Copyright (C) 2012 Sascha Hauer, Pengutronix
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301, USA.
19 */
20
21#include <linux/module.h>
22#include <linux/clk.h>
23#include <linux/component.h>
24#include <drm/drmP.h>
25#include <drm/drm_fb_helper.h>
26#include <drm/drm_crtc_helper.h>
27#include <linux/mfd/syscon.h>
28#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
29#include <linux/of_address.h>
30#include <linux/of_device.h>
31#include <video/of_videomode.h>
32#include <linux/regmap.h>
33#include <linux/videodev2.h>
34
35#include "imx-drm.h"
36
37#define DRIVER_NAME "imx-ldb"
38
39#define LDB_CH0_MODE_EN_TO_DI0 (1 << 0)
40#define LDB_CH0_MODE_EN_TO_DI1 (3 << 0)
41#define LDB_CH0_MODE_EN_MASK (3 << 0)
42#define LDB_CH1_MODE_EN_TO_DI0 (1 << 2)
43#define LDB_CH1_MODE_EN_TO_DI1 (3 << 2)
44#define LDB_CH1_MODE_EN_MASK (3 << 2)
45#define LDB_SPLIT_MODE_EN (1 << 4)
46#define LDB_DATA_WIDTH_CH0_24 (1 << 5)
47#define LDB_BIT_MAP_CH0_JEIDA (1 << 6)
48#define LDB_DATA_WIDTH_CH1_24 (1 << 7)
49#define LDB_BIT_MAP_CH1_JEIDA (1 << 8)
50#define LDB_DI0_VS_POL_ACT_LOW (1 << 9)
51#define LDB_DI1_VS_POL_ACT_LOW (1 << 10)
52#define LDB_BGREF_RMODE_INT (1 << 15)
53
54#define con_to_imx_ldb_ch(x) container_of(x, struct imx_ldb_channel, connector)
55#define enc_to_imx_ldb_ch(x) container_of(x, struct imx_ldb_channel, encoder)
56
57struct imx_ldb;
58
59struct imx_ldb_channel {
60 struct imx_ldb *ldb;
61 struct drm_connector connector;
62 struct drm_encoder encoder;
63 struct device_node *child;
64 int chno;
65 void *edid;
66 int edid_len;
67 struct drm_display_mode mode;
68 int mode_valid;
69};
70
71struct bus_mux {
72 int reg;
73 int shift;
74 int mask;
75};
76
77struct imx_ldb {
78 struct regmap *regmap;
79 struct device *dev;
80 struct imx_ldb_channel channel[2];
81 struct clk *clk[2]; /* our own clock */
82 struct clk *clk_sel[4]; /* parent of display clock */
83 struct clk *clk_pll[2]; /* upstream clock we can adjust */
84 u32 ldb_ctrl;
85 const struct bus_mux *lvds_mux;
86};
87
88static enum drm_connector_status imx_ldb_connector_detect(
89 struct drm_connector *connector, bool force)
90{
91 return connector_status_connected;
92}
93
94static int imx_ldb_connector_get_modes(struct drm_connector *connector)
95{
96 struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
97 int num_modes = 0;
98
99 if (imx_ldb_ch->edid) {
100 drm_mode_connector_update_edid_property(connector,
101 imx_ldb_ch->edid);
102 num_modes = drm_add_edid_modes(connector, imx_ldb_ch->edid);
103 }
104
105 if (imx_ldb_ch->mode_valid) {
106 struct drm_display_mode *mode;
107
108 mode = drm_mode_create(connector->dev);
109 if (!mode)
110 return -EINVAL;
111 drm_mode_copy(mode, &imx_ldb_ch->mode);
112 mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
113 drm_mode_probed_add(connector, mode);
114 num_modes++;
115 }
116
117 return num_modes;
118}
119
120static struct drm_encoder *imx_ldb_connector_best_encoder(
121 struct drm_connector *connector)
122{
123 struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
124
125 return &imx_ldb_ch->encoder;
126}
127
128static void imx_ldb_encoder_dpms(struct drm_encoder *encoder, int mode)
129{
130}
131
132static bool imx_ldb_encoder_mode_fixup(struct drm_encoder *encoder,
133 const struct drm_display_mode *mode,
134 struct drm_display_mode *adjusted_mode)
135{
136 return true;
137}
138
139static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno,
140 unsigned long serial_clk, unsigned long di_clk)
141{
142 int ret;
143
144 dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__,
145 clk_get_rate(ldb->clk_pll[chno]), serial_clk);
146 clk_set_rate(ldb->clk_pll[chno], serial_clk);
147
148 dev_dbg(ldb->dev, "%s after: %ld\n", __func__,
149 clk_get_rate(ldb->clk_pll[chno]));
150
151 dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__,
152 clk_get_rate(ldb->clk[chno]),
153 (long int)di_clk);
154 clk_set_rate(ldb->clk[chno], di_clk);
155
156 dev_dbg(ldb->dev, "%s after: %ld\n", __func__,
157 clk_get_rate(ldb->clk[chno]));
158
159 /* set display clock mux to LDB input clock */
160 ret = clk_set_parent(ldb->clk_sel[mux], ldb->clk[chno]);
161 if (ret)
162 dev_err(ldb->dev,
163 "unable to set di%d parent clock to ldb_di%d\n", mux,
164 chno);
165}
166
167static void imx_ldb_encoder_prepare(struct drm_encoder *encoder)
168{
169 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
170 struct imx_ldb *ldb = imx_ldb_ch->ldb;
171 struct drm_display_mode *mode = &encoder->crtc->mode;
172 u32 pixel_fmt;
173 unsigned long serial_clk;
174 unsigned long di_clk = mode->clock * 1000;
175 int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder);
176
177 if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
178 /* dual channel LVDS mode */
179 serial_clk = 3500UL * mode->clock;
180 imx_ldb_set_clock(ldb, mux, 0, serial_clk, di_clk);
181 imx_ldb_set_clock(ldb, mux, 1, serial_clk, di_clk);
182 } else {
183 serial_clk = 7000UL * mode->clock;
184 imx_ldb_set_clock(ldb, mux, imx_ldb_ch->chno, serial_clk,
185 di_clk);
186 }
187
188 switch (imx_ldb_ch->chno) {
189 case 0:
190 pixel_fmt = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH0_24) ?
191 V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666;
192 break;
193 case 1:
194 pixel_fmt = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH1_24) ?
195 V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666;
196 break;
197 default:
198 dev_err(ldb->dev, "unable to config di%d panel format\n",
199 imx_ldb_ch->chno);
200 pixel_fmt = V4L2_PIX_FMT_RGB24;
201 }
202
203 imx_drm_panel_format(encoder, pixel_fmt);
204}
205
206static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
207{
208 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
209 struct imx_ldb *ldb = imx_ldb_ch->ldb;
210 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
211 int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder);
212
213 if (dual) {
214 clk_prepare_enable(ldb->clk[0]);
215 clk_prepare_enable(ldb->clk[1]);
216 }
217
218 if (imx_ldb_ch == &ldb->channel[0] || dual) {
219 ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
220 if (mux == 0 || ldb->lvds_mux)
221 ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI0;
222 else if (mux == 1)
223 ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI1;
224 }
225 if (imx_ldb_ch == &ldb->channel[1] || dual) {
226 ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
227 if (mux == 1 || ldb->lvds_mux)
228 ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI1;
229 else if (mux == 0)
230 ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI0;
231 }
232
233 if (ldb->lvds_mux) {
234 const struct bus_mux *lvds_mux = NULL;
235
236 if (imx_ldb_ch == &ldb->channel[0])
237 lvds_mux = &ldb->lvds_mux[0];
238 else if (imx_ldb_ch == &ldb->channel[1])
239 lvds_mux = &ldb->lvds_mux[1];
240
241 regmap_update_bits(ldb->regmap, lvds_mux->reg, lvds_mux->mask,
242 mux << lvds_mux->shift);
243 }
244
245 regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
246}
247
248static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
249 struct drm_display_mode *mode,
250 struct drm_display_mode *adjusted_mode)
251{
252 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
253 struct imx_ldb *ldb = imx_ldb_ch->ldb;
254 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
255
256 if (mode->clock > 170000) {
257 dev_warn(ldb->dev,
258 "%s: mode exceeds 170 MHz pixel clock\n", __func__);
259 }
260 if (mode->clock > 85000 && !dual) {
261 dev_warn(ldb->dev,
262 "%s: mode exceeds 85 MHz pixel clock\n", __func__);
263 }
264
265 /* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */
266 if (imx_ldb_ch == &ldb->channel[0]) {
267 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
268 ldb->ldb_ctrl |= LDB_DI0_VS_POL_ACT_LOW;
269 else if (mode->flags & DRM_MODE_FLAG_PVSYNC)
270 ldb->ldb_ctrl &= ~LDB_DI0_VS_POL_ACT_LOW;
271 }
272 if (imx_ldb_ch == &ldb->channel[1]) {
273 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
274 ldb->ldb_ctrl |= LDB_DI1_VS_POL_ACT_LOW;
275 else if (mode->flags & DRM_MODE_FLAG_PVSYNC)
276 ldb->ldb_ctrl &= ~LDB_DI1_VS_POL_ACT_LOW;
277 }
278}
279
280static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
281{
282 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
283 struct imx_ldb *ldb = imx_ldb_ch->ldb;
284
285 /*
286 * imx_ldb_encoder_disable is called by
287 * drm_helper_disable_unused_functions without
288 * the encoder being enabled before.
289 */
290 if (imx_ldb_ch == &ldb->channel[0] &&
291 (ldb->ldb_ctrl & LDB_CH0_MODE_EN_MASK) == 0)
292 return;
293 else if (imx_ldb_ch == &ldb->channel[1] &&
294 (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0)
295 return;
296
297 if (imx_ldb_ch == &ldb->channel[0])
298 ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
299 else if (imx_ldb_ch == &ldb->channel[1])
300 ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
301
302 regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
303
304 if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
305 clk_disable_unprepare(ldb->clk[0]);
306 clk_disable_unprepare(ldb->clk[1]);
307 }
308}
309
310static struct drm_connector_funcs imx_ldb_connector_funcs = {
311 .dpms = drm_helper_connector_dpms,
312 .fill_modes = drm_helper_probe_single_connector_modes,
313 .detect = imx_ldb_connector_detect,
314 .destroy = imx_drm_connector_destroy,
315};
316
317static struct drm_connector_helper_funcs imx_ldb_connector_helper_funcs = {
318 .get_modes = imx_ldb_connector_get_modes,
319 .best_encoder = imx_ldb_connector_best_encoder,
320};
321
322static struct drm_encoder_funcs imx_ldb_encoder_funcs = {
323 .destroy = imx_drm_encoder_destroy,
324};
325
326static struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = {
327 .dpms = imx_ldb_encoder_dpms,
328 .mode_fixup = imx_ldb_encoder_mode_fixup,
329 .prepare = imx_ldb_encoder_prepare,
330 .commit = imx_ldb_encoder_commit,
331 .mode_set = imx_ldb_encoder_mode_set,
332 .disable = imx_ldb_encoder_disable,
333};
334
335static int imx_ldb_get_clk(struct imx_ldb *ldb, int chno)
336{
337 char clkname[16];
338
339 snprintf(clkname, sizeof(clkname), "di%d", chno);
340 ldb->clk[chno] = devm_clk_get(ldb->dev, clkname);
341 if (IS_ERR(ldb->clk[chno]))
342 return PTR_ERR(ldb->clk[chno]);
343
344 snprintf(clkname, sizeof(clkname), "di%d_pll", chno);
345 ldb->clk_pll[chno] = devm_clk_get(ldb->dev, clkname);
346
347 return PTR_ERR_OR_ZERO(ldb->clk_pll[chno]);
348}
349
350static int imx_ldb_register(struct drm_device *drm,
351 struct imx_ldb_channel *imx_ldb_ch)
352{
353 struct imx_ldb *ldb = imx_ldb_ch->ldb;
354 int ret;
355
356 ret = imx_drm_encoder_parse_of(drm, &imx_ldb_ch->encoder,
357 imx_ldb_ch->child);
358 if (ret)
359 return ret;
360
361 ret = imx_ldb_get_clk(ldb, imx_ldb_ch->chno);
362 if (ret)
363 return ret;
364
365 if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
366 ret = imx_ldb_get_clk(ldb, 1);
367 if (ret)
368 return ret;
369 }
370
371 drm_encoder_helper_add(&imx_ldb_ch->encoder,
372 &imx_ldb_encoder_helper_funcs);
373 drm_encoder_init(drm, &imx_ldb_ch->encoder, &imx_ldb_encoder_funcs,
374 DRM_MODE_ENCODER_LVDS);
375
376 drm_connector_helper_add(&imx_ldb_ch->connector,
377 &imx_ldb_connector_helper_funcs);
378 drm_connector_init(drm, &imx_ldb_ch->connector,
379 &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
380
381 drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
382 &imx_ldb_ch->encoder);
383
384 return 0;
385}
386
387enum {
388 LVDS_BIT_MAP_SPWG,
389 LVDS_BIT_MAP_JEIDA
390};
391
392static const char * const imx_ldb_bit_mappings[] = {
393 [LVDS_BIT_MAP_SPWG] = "spwg",
394 [LVDS_BIT_MAP_JEIDA] = "jeida",
395};
396
397static const int of_get_data_mapping(struct device_node *np)
398{
399 const char *bm;
400 int ret, i;
401
402 ret = of_property_read_string(np, "fsl,data-mapping", &bm);
403 if (ret < 0)
404 return ret;
405
406 for (i = 0; i < ARRAY_SIZE(imx_ldb_bit_mappings); i++)
407 if (!strcasecmp(bm, imx_ldb_bit_mappings[i]))
408 return i;
409
410 return -EINVAL;
411}
412
413static struct bus_mux imx6q_lvds_mux[2] = {
414 {
415 .reg = IOMUXC_GPR3,
416 .shift = 6,
417 .mask = IMX6Q_GPR3_LVDS0_MUX_CTL_MASK,
418 }, {
419 .reg = IOMUXC_GPR3,
420 .shift = 8,
421 .mask = IMX6Q_GPR3_LVDS1_MUX_CTL_MASK,
422 }
423};
424
425/*
426 * For a device declaring compatible = "fsl,imx6q-ldb", "fsl,imx53-ldb",
427 * of_match_device will walk through this list and take the first entry
428 * matching any of its compatible values. Therefore, the more generic
429 * entries (in this case fsl,imx53-ldb) need to be ordered last.
430 */
431static const struct of_device_id imx_ldb_dt_ids[] = {
432 { .compatible = "fsl,imx6q-ldb", .data = imx6q_lvds_mux, },
433 { .compatible = "fsl,imx53-ldb", .data = NULL, },
434 { }
435};
436MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids);
437
438static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
439{
440 struct drm_device *drm = data;
441 struct device_node *np = dev->of_node;
442 const struct of_device_id *of_id =
443 of_match_device(imx_ldb_dt_ids, dev);
444 struct device_node *child;
445 const u8 *edidp;
446 struct imx_ldb *imx_ldb;
447 int datawidth;
448 int mapping;
449 int dual;
450 int ret;
451 int i;
452
453 imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL);
454 if (!imx_ldb)
455 return -ENOMEM;
456
457 imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
458 if (IS_ERR(imx_ldb->regmap)) {
459 dev_err(dev, "failed to get parent regmap\n");
460 return PTR_ERR(imx_ldb->regmap);
461 }
462
463 imx_ldb->dev = dev;
464
465 if (of_id)
466 imx_ldb->lvds_mux = of_id->data;
467
468 dual = of_property_read_bool(np, "fsl,dual-channel");
469 if (dual)
470 imx_ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN;
471
472 /*
473 * There are three different possible clock mux configurations:
474 * i.MX53: ipu1_di0_sel, ipu1_di1_sel
475 * i.MX6q: ipu1_di0_sel, ipu1_di1_sel, ipu2_di0_sel, ipu2_di1_sel
476 * i.MX6dl: ipu1_di0_sel, ipu1_di1_sel, lcdif_sel
477 * Map them all to di0_sel...di3_sel.
478 */
479 for (i = 0; i < 4; i++) {
480 char clkname[16];
481
482 sprintf(clkname, "di%d_sel", i);
483 imx_ldb->clk_sel[i] = devm_clk_get(imx_ldb->dev, clkname);
484 if (IS_ERR(imx_ldb->clk_sel[i])) {
485 ret = PTR_ERR(imx_ldb->clk_sel[i]);
486 imx_ldb->clk_sel[i] = NULL;
487 break;
488 }
489 }
490 if (i == 0)
491 return ret;
492
493 for_each_child_of_node(np, child) {
494 struct imx_ldb_channel *channel;
495
496 ret = of_property_read_u32(child, "reg", &i);
497 if (ret || i < 0 || i > 1)
498 return -EINVAL;
499
500 if (dual && i > 0) {
501 dev_warn(dev, "dual-channel mode, ignoring second output\n");
502 continue;
503 }
504
505 if (!of_device_is_available(child))
506 continue;
507
508 channel = &imx_ldb->channel[i];
509 channel->ldb = imx_ldb;
510 channel->chno = i;
511 channel->child = child;
512
513 edidp = of_get_property(child, "edid", &channel->edid_len);
514 if (edidp) {
515 channel->edid = kmemdup(edidp, channel->edid_len,
516 GFP_KERNEL);
517 } else {
518 ret = of_get_drm_display_mode(child, &channel->mode, 0);
519 if (!ret)
520 channel->mode_valid = 1;
521 }
522
523 ret = of_property_read_u32(child, "fsl,data-width", &datawidth);
524 if (ret)
525 datawidth = 0;
526 else if (datawidth != 18 && datawidth != 24)
527 return -EINVAL;
528
529 mapping = of_get_data_mapping(child);
530 switch (mapping) {
531 case LVDS_BIT_MAP_SPWG:
532 if (datawidth == 24) {
533 if (i == 0 || dual)
534 imx_ldb->ldb_ctrl |=
535 LDB_DATA_WIDTH_CH0_24;
536 if (i == 1 || dual)
537 imx_ldb->ldb_ctrl |=
538 LDB_DATA_WIDTH_CH1_24;
539 }
540 break;
541 case LVDS_BIT_MAP_JEIDA:
542 if (datawidth == 18) {
543 dev_err(dev, "JEIDA standard only supported in 24 bit\n");
544 return -EINVAL;
545 }
546 if (i == 0 || dual)
547 imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 |
548 LDB_BIT_MAP_CH0_JEIDA;
549 if (i == 1 || dual)
550 imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 |
551 LDB_BIT_MAP_CH1_JEIDA;
552 break;
553 default:
554 dev_err(dev, "data mapping not specified or invalid\n");
555 return -EINVAL;
556 }
557
558 ret = imx_ldb_register(drm, channel);
559 if (ret)
560 return ret;
561 }
562
563 dev_set_drvdata(dev, imx_ldb);
564
565 return 0;
566}
567
568static void imx_ldb_unbind(struct device *dev, struct device *master,
569 void *data)
570{
571 struct imx_ldb *imx_ldb = dev_get_drvdata(dev);
572 int i;
573
574 for (i = 0; i < 2; i++) {
575 struct imx_ldb_channel *channel = &imx_ldb->channel[i];
576
577 if (!channel->connector.funcs)
578 continue;
579
580 channel->connector.funcs->destroy(&channel->connector);
581 channel->encoder.funcs->destroy(&channel->encoder);
582 }
583}
584
585static const struct component_ops imx_ldb_ops = {
586 .bind = imx_ldb_bind,
587 .unbind = imx_ldb_unbind,
588};
589
590static int imx_ldb_probe(struct platform_device *pdev)
591{
592 return component_add(&pdev->dev, &imx_ldb_ops);
593}
594
595static int imx_ldb_remove(struct platform_device *pdev)
596{
597 component_del(&pdev->dev, &imx_ldb_ops);
598 return 0;
599}
600
601static struct platform_driver imx_ldb_driver = {
602 .probe = imx_ldb_probe,
603 .remove = imx_ldb_remove,
604 .driver = {
605 .of_match_table = imx_ldb_dt_ids,
606 .name = DRIVER_NAME,
607 },
608};
609
610module_platform_driver(imx_ldb_driver);
611
612MODULE_DESCRIPTION("i.MX LVDS driver");
613MODULE_AUTHOR("Sascha Hauer, Pengutronix");
614MODULE_LICENSE("GPL");
615MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
new file mode 100644
index 000000000000..64b54d7f996c
--- /dev/null
+++ b/drivers/gpu/drm/imx/imx-tve.c
@@ -0,0 +1,735 @@
1/*
2 * i.MX drm driver - Television Encoder (TVEv2)
3 *
4 * Copyright (C) 2013 Philipp Zabel, Pengutronix
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301, USA.
19 */
20
21#include <linux/clk.h>
22#include <linux/clk-provider.h>
23#include <linux/component.h>
24#include <linux/module.h>
25#include <linux/i2c.h>
26#include <linux/regmap.h>
27#include <linux/regulator/consumer.h>
28#include <linux/spinlock.h>
29#include <linux/videodev2.h>
30#include <drm/drmP.h>
31#include <drm/drm_fb_helper.h>
32#include <drm/drm_crtc_helper.h>
33#include <video/imx-ipu-v3.h>
34
35#include "imx-drm.h"
36
37#define TVE_COM_CONF_REG 0x00
38#define TVE_TVDAC0_CONT_REG 0x28
39#define TVE_TVDAC1_CONT_REG 0x2c
40#define TVE_TVDAC2_CONT_REG 0x30
41#define TVE_CD_CONT_REG 0x34
42#define TVE_INT_CONT_REG 0x64
43#define TVE_STAT_REG 0x68
44#define TVE_TST_MODE_REG 0x6c
45#define TVE_MV_CONT_REG 0xdc
46
47/* TVE_COM_CONF_REG */
48#define TVE_SYNC_CH_2_EN BIT(22)
49#define TVE_SYNC_CH_1_EN BIT(21)
50#define TVE_SYNC_CH_0_EN BIT(20)
51#define TVE_TV_OUT_MODE_MASK (0x7 << 12)
52#define TVE_TV_OUT_DISABLE (0x0 << 12)
53#define TVE_TV_OUT_CVBS_0 (0x1 << 12)
54#define TVE_TV_OUT_CVBS_2 (0x2 << 12)
55#define TVE_TV_OUT_CVBS_0_2 (0x3 << 12)
56#define TVE_TV_OUT_SVIDEO_0_1 (0x4 << 12)
57#define TVE_TV_OUT_SVIDEO_0_1_CVBS2_2 (0x5 << 12)
58#define TVE_TV_OUT_YPBPR (0x6 << 12)
59#define TVE_TV_OUT_RGB (0x7 << 12)
60#define TVE_TV_STAND_MASK (0xf << 8)
61#define TVE_TV_STAND_HD_1080P30 (0xc << 8)
62#define TVE_P2I_CONV_EN BIT(7)
63#define TVE_INP_VIDEO_FORM BIT(6)
64#define TVE_INP_YCBCR_422 (0x0 << 6)
65#define TVE_INP_YCBCR_444 (0x1 << 6)
66#define TVE_DATA_SOURCE_MASK (0x3 << 4)
67#define TVE_DATA_SOURCE_BUS1 (0x0 << 4)
68#define TVE_DATA_SOURCE_BUS2 (0x1 << 4)
69#define TVE_DATA_SOURCE_EXT (0x2 << 4)
70#define TVE_DATA_SOURCE_TESTGEN (0x3 << 4)
71#define TVE_IPU_CLK_EN_OFS 3
72#define TVE_IPU_CLK_EN BIT(3)
73#define TVE_DAC_SAMP_RATE_OFS 1
74#define TVE_DAC_SAMP_RATE_WIDTH 2
75#define TVE_DAC_SAMP_RATE_MASK (0x3 << 1)
76#define TVE_DAC_FULL_RATE (0x0 << 1)
77#define TVE_DAC_DIV2_RATE (0x1 << 1)
78#define TVE_DAC_DIV4_RATE (0x2 << 1)
79#define TVE_EN BIT(0)
80
81/* TVE_TVDACx_CONT_REG */
82#define TVE_TVDAC_GAIN_MASK (0x3f << 0)
83
84/* TVE_CD_CONT_REG */
85#define TVE_CD_CH_2_SM_EN BIT(22)
86#define TVE_CD_CH_1_SM_EN BIT(21)
87#define TVE_CD_CH_0_SM_EN BIT(20)
88#define TVE_CD_CH_2_LM_EN BIT(18)
89#define TVE_CD_CH_1_LM_EN BIT(17)
90#define TVE_CD_CH_0_LM_EN BIT(16)
91#define TVE_CD_CH_2_REF_LVL BIT(10)
92#define TVE_CD_CH_1_REF_LVL BIT(9)
93#define TVE_CD_CH_0_REF_LVL BIT(8)
94#define TVE_CD_EN BIT(0)
95
96/* TVE_INT_CONT_REG */
97#define TVE_FRAME_END_IEN BIT(13)
98#define TVE_CD_MON_END_IEN BIT(2)
99#define TVE_CD_SM_IEN BIT(1)
100#define TVE_CD_LM_IEN BIT(0)
101
102/* TVE_TST_MODE_REG */
103#define TVE_TVDAC_TEST_MODE_MASK (0x7 << 0)
104
105#define con_to_tve(x) container_of(x, struct imx_tve, connector)
106#define enc_to_tve(x) container_of(x, struct imx_tve, encoder)
107
108enum {
109 TVE_MODE_TVOUT,
110 TVE_MODE_VGA,
111};
112
113struct imx_tve {
114 struct drm_connector connector;
115 struct drm_encoder encoder;
116 struct device *dev;
117 spinlock_t lock; /* register lock */
118 bool enabled;
119 int mode;
120
121 struct regmap *regmap;
122 struct regulator *dac_reg;
123 struct i2c_adapter *ddc;
124 struct clk *clk;
125 struct clk *di_sel_clk;
126 struct clk_hw clk_hw_di;
127 struct clk *di_clk;
128 int vsync_pin;
129 int hsync_pin;
130};
131
132static void tve_lock(void *__tve)
133__acquires(&tve->lock)
134{
135 struct imx_tve *tve = __tve;
136
137 spin_lock(&tve->lock);
138}
139
140static void tve_unlock(void *__tve)
141__releases(&tve->lock)
142{
143 struct imx_tve *tve = __tve;
144
145 spin_unlock(&tve->lock);
146}
147
148static void tve_enable(struct imx_tve *tve)
149{
150 int ret;
151
152 if (!tve->enabled) {
153 tve->enabled = true;
154 clk_prepare_enable(tve->clk);
155 ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
156 TVE_IPU_CLK_EN | TVE_EN,
157 TVE_IPU_CLK_EN | TVE_EN);
158 }
159
160 /* clear interrupt status register */
161 regmap_write(tve->regmap, TVE_STAT_REG, 0xffffffff);
162
163 /* cable detection irq disabled in VGA mode, enabled in TVOUT mode */
164 if (tve->mode == TVE_MODE_VGA)
165 regmap_write(tve->regmap, TVE_INT_CONT_REG, 0);
166 else
167 regmap_write(tve->regmap, TVE_INT_CONT_REG,
168 TVE_CD_SM_IEN |
169 TVE_CD_LM_IEN |
170 TVE_CD_MON_END_IEN);
171}
172
173static void tve_disable(struct imx_tve *tve)
174{
175 int ret;
176
177 if (tve->enabled) {
178 tve->enabled = false;
179 ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
180 TVE_IPU_CLK_EN | TVE_EN, 0);
181 clk_disable_unprepare(tve->clk);
182 }
183}
184
185static int tve_setup_tvout(struct imx_tve *tve)
186{
187 return -ENOTSUPP;
188}
189
190static int tve_setup_vga(struct imx_tve *tve)
191{
192 unsigned int mask;
193 unsigned int val;
194 int ret;
195
196 /* set gain to (1 + 10/128) to provide 0.7V peak-to-peak amplitude */
197 ret = regmap_update_bits(tve->regmap, TVE_TVDAC0_CONT_REG,
198 TVE_TVDAC_GAIN_MASK, 0x0a);
199 ret = regmap_update_bits(tve->regmap, TVE_TVDAC1_CONT_REG,
200 TVE_TVDAC_GAIN_MASK, 0x0a);
201 ret = regmap_update_bits(tve->regmap, TVE_TVDAC2_CONT_REG,
202 TVE_TVDAC_GAIN_MASK, 0x0a);
203
204 /* set configuration register */
205 mask = TVE_DATA_SOURCE_MASK | TVE_INP_VIDEO_FORM;
206 val = TVE_DATA_SOURCE_BUS2 | TVE_INP_YCBCR_444;
207 mask |= TVE_TV_STAND_MASK | TVE_P2I_CONV_EN;
208 val |= TVE_TV_STAND_HD_1080P30 | 0;
209 mask |= TVE_TV_OUT_MODE_MASK | TVE_SYNC_CH_0_EN;
210 val |= TVE_TV_OUT_RGB | TVE_SYNC_CH_0_EN;
211 ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, mask, val);
212 if (ret < 0) {
213 dev_err(tve->dev, "failed to set configuration: %d\n", ret);
214 return ret;
215 }
216
217 /* set test mode (as documented) */
218 ret = regmap_update_bits(tve->regmap, TVE_TST_MODE_REG,
219 TVE_TVDAC_TEST_MODE_MASK, 1);
220
221 return 0;
222}
223
224static enum drm_connector_status imx_tve_connector_detect(
225 struct drm_connector *connector, bool force)
226{
227 return connector_status_connected;
228}
229
230static int imx_tve_connector_get_modes(struct drm_connector *connector)
231{
232 struct imx_tve *tve = con_to_tve(connector);
233 struct edid *edid;
234 int ret = 0;
235
236 if (!tve->ddc)
237 return 0;
238
239 edid = drm_get_edid(connector, tve->ddc);
240 if (edid) {
241 drm_mode_connector_update_edid_property(connector, edid);
242 ret = drm_add_edid_modes(connector, edid);
243 kfree(edid);
244 }
245
246 return ret;
247}
248
249static int imx_tve_connector_mode_valid(struct drm_connector *connector,
250 struct drm_display_mode *mode)
251{
252 struct imx_tve *tve = con_to_tve(connector);
253 unsigned long rate;
254
255 /* pixel clock with 2x oversampling */
256 rate = clk_round_rate(tve->clk, 2000UL * mode->clock) / 2000;
257 if (rate == mode->clock)
258 return MODE_OK;
259
260 /* pixel clock without oversampling */
261 rate = clk_round_rate(tve->clk, 1000UL * mode->clock) / 1000;
262 if (rate == mode->clock)
263 return MODE_OK;
264
265 dev_warn(tve->dev, "ignoring mode %dx%d\n",
266 mode->hdisplay, mode->vdisplay);
267
268 return MODE_BAD;
269}
270
271static struct drm_encoder *imx_tve_connector_best_encoder(
272 struct drm_connector *connector)
273{
274 struct imx_tve *tve = con_to_tve(connector);
275
276 return &tve->encoder;
277}
278
279static void imx_tve_encoder_dpms(struct drm_encoder *encoder, int mode)
280{
281 struct imx_tve *tve = enc_to_tve(encoder);
282 int ret;
283
284 ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
285 TVE_TV_OUT_MODE_MASK, TVE_TV_OUT_DISABLE);
286 if (ret < 0)
287 dev_err(tve->dev, "failed to disable TVOUT: %d\n", ret);
288}
289
290static bool imx_tve_encoder_mode_fixup(struct drm_encoder *encoder,
291 const struct drm_display_mode *mode,
292 struct drm_display_mode *adjusted_mode)
293{
294 return true;
295}
296
297static void imx_tve_encoder_prepare(struct drm_encoder *encoder)
298{
299 struct imx_tve *tve = enc_to_tve(encoder);
300
301 tve_disable(tve);
302
303 switch (tve->mode) {
304 case TVE_MODE_VGA:
305 imx_drm_panel_format_pins(encoder, IPU_PIX_FMT_GBR24,
306 tve->hsync_pin, tve->vsync_pin);
307 break;
308 case TVE_MODE_TVOUT:
309 imx_drm_panel_format(encoder, V4L2_PIX_FMT_YUV444);
310 break;
311 }
312}
313
314static void imx_tve_encoder_mode_set(struct drm_encoder *encoder,
315 struct drm_display_mode *mode,
316 struct drm_display_mode *adjusted_mode)
317{
318 struct imx_tve *tve = enc_to_tve(encoder);
319 unsigned long rounded_rate;
320 unsigned long rate;
321 int div = 1;
322 int ret;
323
324 /*
325 * FIXME
326 * we should try 4k * mode->clock first,
327 * and enable 4x oversampling for lower resolutions
328 */
329 rate = 2000UL * mode->clock;
330 clk_set_rate(tve->clk, rate);
331 rounded_rate = clk_get_rate(tve->clk);
332 if (rounded_rate >= rate)
333 div = 2;
334 clk_set_rate(tve->di_clk, rounded_rate / div);
335
336 ret = clk_set_parent(tve->di_sel_clk, tve->di_clk);
337 if (ret < 0) {
338 dev_err(tve->dev, "failed to set di_sel parent to tve_di: %d\n",
339 ret);
340 }
341
342 if (tve->mode == TVE_MODE_VGA)
343 tve_setup_vga(tve);
344 else
345 tve_setup_tvout(tve);
346}
347
348static void imx_tve_encoder_commit(struct drm_encoder *encoder)
349{
350 struct imx_tve *tve = enc_to_tve(encoder);
351
352 tve_enable(tve);
353}
354
355static void imx_tve_encoder_disable(struct drm_encoder *encoder)
356{
357 struct imx_tve *tve = enc_to_tve(encoder);
358
359 tve_disable(tve);
360}
361
362static struct drm_connector_funcs imx_tve_connector_funcs = {
363 .dpms = drm_helper_connector_dpms,
364 .fill_modes = drm_helper_probe_single_connector_modes,
365 .detect = imx_tve_connector_detect,
366 .destroy = imx_drm_connector_destroy,
367};
368
369static struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = {
370 .get_modes = imx_tve_connector_get_modes,
371 .best_encoder = imx_tve_connector_best_encoder,
372 .mode_valid = imx_tve_connector_mode_valid,
373};
374
375static struct drm_encoder_funcs imx_tve_encoder_funcs = {
376 .destroy = imx_drm_encoder_destroy,
377};
378
379static struct drm_encoder_helper_funcs imx_tve_encoder_helper_funcs = {
380 .dpms = imx_tve_encoder_dpms,
381 .mode_fixup = imx_tve_encoder_mode_fixup,
382 .prepare = imx_tve_encoder_prepare,
383 .mode_set = imx_tve_encoder_mode_set,
384 .commit = imx_tve_encoder_commit,
385 .disable = imx_tve_encoder_disable,
386};
387
388static irqreturn_t imx_tve_irq_handler(int irq, void *data)
389{
390 struct imx_tve *tve = data;
391 unsigned int val;
392
393 regmap_read(tve->regmap, TVE_STAT_REG, &val);
394
395 /* clear interrupt status register */
396 regmap_write(tve->regmap, TVE_STAT_REG, 0xffffffff);
397
398 return IRQ_HANDLED;
399}
400
401static unsigned long clk_tve_di_recalc_rate(struct clk_hw *hw,
402 unsigned long parent_rate)
403{
404 struct imx_tve *tve = container_of(hw, struct imx_tve, clk_hw_di);
405 unsigned int val;
406 int ret;
407
408 ret = regmap_read(tve->regmap, TVE_COM_CONF_REG, &val);
409 if (ret < 0)
410 return 0;
411
412 switch (val & TVE_DAC_SAMP_RATE_MASK) {
413 case TVE_DAC_DIV4_RATE:
414 return parent_rate / 4;
415 case TVE_DAC_DIV2_RATE:
416 return parent_rate / 2;
417 case TVE_DAC_FULL_RATE:
418 default:
419 return parent_rate;
420 }
421
422 return 0;
423}
424
425static long clk_tve_di_round_rate(struct clk_hw *hw, unsigned long rate,
426 unsigned long *prate)
427{
428 unsigned long div;
429
430 div = *prate / rate;
431 if (div >= 4)
432 return *prate / 4;
433 else if (div >= 2)
434 return *prate / 2;
435 return *prate;
436}
437
438static int clk_tve_di_set_rate(struct clk_hw *hw, unsigned long rate,
439 unsigned long parent_rate)
440{
441 struct imx_tve *tve = container_of(hw, struct imx_tve, clk_hw_di);
442 unsigned long div;
443 u32 val;
444 int ret;
445
446 div = parent_rate / rate;
447 if (div >= 4)
448 val = TVE_DAC_DIV4_RATE;
449 else if (div >= 2)
450 val = TVE_DAC_DIV2_RATE;
451 else
452 val = TVE_DAC_FULL_RATE;
453
454 ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
455 TVE_DAC_SAMP_RATE_MASK, val);
456
457 if (ret < 0) {
458 dev_err(tve->dev, "failed to set divider: %d\n", ret);
459 return ret;
460 }
461
462 return 0;
463}
464
465static struct clk_ops clk_tve_di_ops = {
466 .round_rate = clk_tve_di_round_rate,
467 .set_rate = clk_tve_di_set_rate,
468 .recalc_rate = clk_tve_di_recalc_rate,
469};
470
471static int tve_clk_init(struct imx_tve *tve, void __iomem *base)
472{
473 const char *tve_di_parent[1];
474 struct clk_init_data init = {
475 .name = "tve_di",
476 .ops = &clk_tve_di_ops,
477 .num_parents = 1,
478 .flags = 0,
479 };
480
481 tve_di_parent[0] = __clk_get_name(tve->clk);
482 init.parent_names = (const char **)&tve_di_parent;
483
484 tve->clk_hw_di.init = &init;
485 tve->di_clk = clk_register(tve->dev, &tve->clk_hw_di);
486 if (IS_ERR(tve->di_clk)) {
487 dev_err(tve->dev, "failed to register TVE output clock: %ld\n",
488 PTR_ERR(tve->di_clk));
489 return PTR_ERR(tve->di_clk);
490 }
491
492 return 0;
493}
494
495static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve)
496{
497 int encoder_type;
498 int ret;
499
500 encoder_type = tve->mode == TVE_MODE_VGA ?
501 DRM_MODE_ENCODER_DAC : DRM_MODE_ENCODER_TVDAC;
502
503 ret = imx_drm_encoder_parse_of(drm, &tve->encoder,
504 tve->dev->of_node);
505 if (ret)
506 return ret;
507
508 drm_encoder_helper_add(&tve->encoder, &imx_tve_encoder_helper_funcs);
509 drm_encoder_init(drm, &tve->encoder, &imx_tve_encoder_funcs,
510 encoder_type);
511
512 drm_connector_helper_add(&tve->connector,
513 &imx_tve_connector_helper_funcs);
514 drm_connector_init(drm, &tve->connector, &imx_tve_connector_funcs,
515 DRM_MODE_CONNECTOR_VGA);
516
517 drm_mode_connector_attach_encoder(&tve->connector, &tve->encoder);
518
519 return 0;
520}
521
522static bool imx_tve_readable_reg(struct device *dev, unsigned int reg)
523{
524 return (reg % 4 == 0) && (reg <= 0xdc);
525}
526
527static struct regmap_config tve_regmap_config = {
528 .reg_bits = 32,
529 .val_bits = 32,
530 .reg_stride = 4,
531
532 .readable_reg = imx_tve_readable_reg,
533
534 .lock = tve_lock,
535 .unlock = tve_unlock,
536
537 .max_register = 0xdc,
538};
539
540static const char * const imx_tve_modes[] = {
541 [TVE_MODE_TVOUT] = "tvout",
542 [TVE_MODE_VGA] = "vga",
543};
544
545static const int of_get_tve_mode(struct device_node *np)
546{
547 const char *bm;
548 int ret, i;
549
550 ret = of_property_read_string(np, "fsl,tve-mode", &bm);
551 if (ret < 0)
552 return ret;
553
554 for (i = 0; i < ARRAY_SIZE(imx_tve_modes); i++)
555 if (!strcasecmp(bm, imx_tve_modes[i]))
556 return i;
557
558 return -EINVAL;
559}
560
561static int imx_tve_bind(struct device *dev, struct device *master, void *data)
562{
563 struct platform_device *pdev = to_platform_device(dev);
564 struct drm_device *drm = data;
565 struct device_node *np = dev->of_node;
566 struct device_node *ddc_node;
567 struct imx_tve *tve;
568 struct resource *res;
569 void __iomem *base;
570 unsigned int val;
571 int irq;
572 int ret;
573
574 tve = devm_kzalloc(dev, sizeof(*tve), GFP_KERNEL);
575 if (!tve)
576 return -ENOMEM;
577
578 tve->dev = dev;
579 spin_lock_init(&tve->lock);
580
581 ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
582 if (ddc_node) {
583 tve->ddc = of_find_i2c_adapter_by_node(ddc_node);
584 of_node_put(ddc_node);
585 }
586
587 tve->mode = of_get_tve_mode(np);
588 if (tve->mode != TVE_MODE_VGA) {
589 dev_err(dev, "only VGA mode supported, currently\n");
590 return -EINVAL;
591 }
592
593 if (tve->mode == TVE_MODE_VGA) {
594 ret = of_property_read_u32(np, "fsl,hsync-pin",
595 &tve->hsync_pin);
596
597 if (ret < 0) {
598 dev_err(dev, "failed to get vsync pin\n");
599 return ret;
600 }
601
602 ret |= of_property_read_u32(np, "fsl,vsync-pin",
603 &tve->vsync_pin);
604
605 if (ret < 0) {
606 dev_err(dev, "failed to get vsync pin\n");
607 return ret;
608 }
609 }
610
611 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
612 base = devm_ioremap_resource(dev, res);
613 if (IS_ERR(base))
614 return PTR_ERR(base);
615
616 tve_regmap_config.lock_arg = tve;
617 tve->regmap = devm_regmap_init_mmio_clk(dev, "tve", base,
618 &tve_regmap_config);
619 if (IS_ERR(tve->regmap)) {
620 dev_err(dev, "failed to init regmap: %ld\n",
621 PTR_ERR(tve->regmap));
622 return PTR_ERR(tve->regmap);
623 }
624
625 irq = platform_get_irq(pdev, 0);
626 if (irq < 0) {
627 dev_err(dev, "failed to get irq\n");
628 return irq;
629 }
630
631 ret = devm_request_threaded_irq(dev, irq, NULL,
632 imx_tve_irq_handler, IRQF_ONESHOT,
633 "imx-tve", tve);
634 if (ret < 0) {
635 dev_err(dev, "failed to request irq: %d\n", ret);
636 return ret;
637 }
638
639 tve->dac_reg = devm_regulator_get(dev, "dac");
640 if (!IS_ERR(tve->dac_reg)) {
641 regulator_set_voltage(tve->dac_reg, 2750000, 2750000);
642 ret = regulator_enable(tve->dac_reg);
643 if (ret)
644 return ret;
645 }
646
647 tve->clk = devm_clk_get(dev, "tve");
648 if (IS_ERR(tve->clk)) {
649 dev_err(dev, "failed to get high speed tve clock: %ld\n",
650 PTR_ERR(tve->clk));
651 return PTR_ERR(tve->clk);
652 }
653
654 /* this is the IPU DI clock input selector, can be parented to tve_di */
655 tve->di_sel_clk = devm_clk_get(dev, "di_sel");
656 if (IS_ERR(tve->di_sel_clk)) {
657 dev_err(dev, "failed to get ipu di mux clock: %ld\n",
658 PTR_ERR(tve->di_sel_clk));
659 return PTR_ERR(tve->di_sel_clk);
660 }
661
662 ret = tve_clk_init(tve, base);
663 if (ret < 0)
664 return ret;
665
666 ret = regmap_read(tve->regmap, TVE_COM_CONF_REG, &val);
667 if (ret < 0) {
668 dev_err(dev, "failed to read configuration register: %d\n", ret);
669 return ret;
670 }
671 if (val != 0x00100000) {
672 dev_err(dev, "configuration register default value indicates this is not a TVEv2\n");
673 return -ENODEV;
674 }
675
676 /* disable cable detection for VGA mode */
677 ret = regmap_write(tve->regmap, TVE_CD_CONT_REG, 0);
678
679 ret = imx_tve_register(drm, tve);
680 if (ret)
681 return ret;
682
683 dev_set_drvdata(dev, tve);
684
685 return 0;
686}
687
688static void imx_tve_unbind(struct device *dev, struct device *master,
689 void *data)
690{
691 struct imx_tve *tve = dev_get_drvdata(dev);
692
693 tve->connector.funcs->destroy(&tve->connector);
694 tve->encoder.funcs->destroy(&tve->encoder);
695
696 if (!IS_ERR(tve->dac_reg))
697 regulator_disable(tve->dac_reg);
698}
699
700static const struct component_ops imx_tve_ops = {
701 .bind = imx_tve_bind,
702 .unbind = imx_tve_unbind,
703};
704
705static int imx_tve_probe(struct platform_device *pdev)
706{
707 return component_add(&pdev->dev, &imx_tve_ops);
708}
709
710static int imx_tve_remove(struct platform_device *pdev)
711{
712 component_del(&pdev->dev, &imx_tve_ops);
713 return 0;
714}
715
716static const struct of_device_id imx_tve_dt_ids[] = {
717 { .compatible = "fsl,imx53-tve", },
718 { /* sentinel */ }
719};
720
721static struct platform_driver imx_tve_driver = {
722 .probe = imx_tve_probe,
723 .remove = imx_tve_remove,
724 .driver = {
725 .of_match_table = imx_tve_dt_ids,
726 .name = "imx-tve",
727 },
728};
729
730module_platform_driver(imx_tve_driver);
731
732MODULE_DESCRIPTION("i.MX Television Encoder driver");
733MODULE_AUTHOR("Philipp Zabel, Pengutronix");
734MODULE_LICENSE("GPL");
735MODULE_ALIAS("platform:imx-tve");
diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
new file mode 100644
index 000000000000..11e84a251773
--- /dev/null
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -0,0 +1,518 @@
1/*
2 * i.MX IPUv3 Graphics driver
3 *
4 * Copyright (C) 2011 Sascha Hauer, Pengutronix
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301, USA.
19 */
20#include <linux/component.h>
21#include <linux/module.h>
22#include <linux/export.h>
23#include <linux/device.h>
24#include <linux/platform_device.h>
25#include <drm/drmP.h>
26#include <drm/drm_crtc_helper.h>
27#include <linux/fb.h>
28#include <linux/clk.h>
29#include <linux/errno.h>
30#include <drm/drm_gem_cma_helper.h>
31#include <drm/drm_fb_cma_helper.h>
32
33#include <video/imx-ipu-v3.h>
34#include "imx-drm.h"
35#include "ipuv3-plane.h"
36
37#define DRIVER_DESC "i.MX IPUv3 Graphics"
38
39struct ipu_crtc {
40 struct device *dev;
41 struct drm_crtc base;
42 struct imx_drm_crtc *imx_crtc;
43
44 /* plane[0] is the full plane, plane[1] is the partial plane */
45 struct ipu_plane *plane[2];
46
47 struct ipu_dc *dc;
48 struct ipu_di *di;
49 int enabled;
50 struct drm_pending_vblank_event *page_flip_event;
51 struct drm_framebuffer *newfb;
52 int irq;
53 u32 interface_pix_fmt;
54 unsigned long di_clkflags;
55 int di_hsync_pin;
56 int di_vsync_pin;
57};
58
59#define to_ipu_crtc(x) container_of(x, struct ipu_crtc, base)
60
61static void ipu_fb_enable(struct ipu_crtc *ipu_crtc)
62{
63 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
64
65 if (ipu_crtc->enabled)
66 return;
67
68 ipu_dc_enable(ipu);
69 ipu_plane_enable(ipu_crtc->plane[0]);
70 /* Start DC channel and DI after IDMAC */
71 ipu_dc_enable_channel(ipu_crtc->dc);
72 ipu_di_enable(ipu_crtc->di);
73
74 ipu_crtc->enabled = 1;
75}
76
77static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
78{
79 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
80
81 if (!ipu_crtc->enabled)
82 return;
83
84 /* Stop DC channel and DI before IDMAC */
85 ipu_dc_disable_channel(ipu_crtc->dc);
86 ipu_di_disable(ipu_crtc->di);
87 ipu_plane_disable(ipu_crtc->plane[0]);
88 ipu_dc_disable(ipu);
89
90 ipu_crtc->enabled = 0;
91}
92
93static void ipu_crtc_dpms(struct drm_crtc *crtc, int mode)
94{
95 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
96
97 dev_dbg(ipu_crtc->dev, "%s mode: %d\n", __func__, mode);
98
99 switch (mode) {
100 case DRM_MODE_DPMS_ON:
101 ipu_fb_enable(ipu_crtc);
102 break;
103 case DRM_MODE_DPMS_STANDBY:
104 case DRM_MODE_DPMS_SUSPEND:
105 case DRM_MODE_DPMS_OFF:
106 ipu_fb_disable(ipu_crtc);
107 break;
108 }
109}
110
111static int ipu_page_flip(struct drm_crtc *crtc,
112 struct drm_framebuffer *fb,
113 struct drm_pending_vblank_event *event,
114 uint32_t page_flip_flags)
115{
116 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
117 int ret;
118
119 if (ipu_crtc->newfb)
120 return -EBUSY;
121
122 ret = imx_drm_crtc_vblank_get(ipu_crtc->imx_crtc);
123 if (ret) {
124 dev_dbg(ipu_crtc->dev, "failed to acquire vblank counter\n");
125 list_del(&event->base.link);
126
127 return ret;
128 }
129
130 ipu_crtc->newfb = fb;
131 ipu_crtc->page_flip_event = event;
132 crtc->primary->fb = fb;
133
134 return 0;
135}
136
137static const struct drm_crtc_funcs ipu_crtc_funcs = {
138 .set_config = drm_crtc_helper_set_config,
139 .destroy = drm_crtc_cleanup,
140 .page_flip = ipu_page_flip,
141};
142
143static int ipu_crtc_mode_set(struct drm_crtc *crtc,
144 struct drm_display_mode *orig_mode,
145 struct drm_display_mode *mode,
146 int x, int y,
147 struct drm_framebuffer *old_fb)
148{
149 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
150 int ret;
151 struct ipu_di_signal_cfg sig_cfg = {};
152 u32 out_pixel_fmt;
153
154 dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
155 mode->hdisplay);
156 dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__,
157 mode->vdisplay);
158
159 out_pixel_fmt = ipu_crtc->interface_pix_fmt;
160
161 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
162 sig_cfg.interlaced = 1;
163 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
164 sig_cfg.Hsync_pol = 1;
165 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
166 sig_cfg.Vsync_pol = 1;
167
168 sig_cfg.enable_pol = 1;
169 sig_cfg.clk_pol = 0;
170 sig_cfg.width = mode->hdisplay;
171 sig_cfg.height = mode->vdisplay;
172 sig_cfg.pixel_fmt = out_pixel_fmt;
173 sig_cfg.h_start_width = mode->htotal - mode->hsync_end;
174 sig_cfg.h_sync_width = mode->hsync_end - mode->hsync_start;
175 sig_cfg.h_end_width = mode->hsync_start - mode->hdisplay;
176
177 sig_cfg.v_start_width = mode->vtotal - mode->vsync_end;
178 sig_cfg.v_sync_width = mode->vsync_end - mode->vsync_start;
179 sig_cfg.v_end_width = mode->vsync_start - mode->vdisplay;
180 sig_cfg.pixelclock = mode->clock * 1000;
181 sig_cfg.clkflags = ipu_crtc->di_clkflags;
182
183 sig_cfg.v_to_h_sync = 0;
184
185 sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin;
186 sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin;
187
188 ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, sig_cfg.interlaced,
189 out_pixel_fmt, mode->hdisplay);
190 if (ret) {
191 dev_err(ipu_crtc->dev,
192 "initializing display controller failed with %d\n",
193 ret);
194 return ret;
195 }
196
197 ret = ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg);
198 if (ret) {
199 dev_err(ipu_crtc->dev,
200 "initializing panel failed with %d\n", ret);
201 return ret;
202 }
203
204 return ipu_plane_mode_set(ipu_crtc->plane[0], crtc, mode,
205 crtc->primary->fb,
206 0, 0, mode->hdisplay, mode->vdisplay,
207 x, y, mode->hdisplay, mode->vdisplay);
208}
209
210static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc)
211{
212 unsigned long flags;
213 struct drm_device *drm = ipu_crtc->base.dev;
214
215 spin_lock_irqsave(&drm->event_lock, flags);
216 if (ipu_crtc->page_flip_event)
217 drm_send_vblank_event(drm, -1, ipu_crtc->page_flip_event);
218 ipu_crtc->page_flip_event = NULL;
219 imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc);
220 spin_unlock_irqrestore(&drm->event_lock, flags);
221}
222
223static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
224{
225 struct ipu_crtc *ipu_crtc = dev_id;
226
227 imx_drm_handle_vblank(ipu_crtc->imx_crtc);
228
229 if (ipu_crtc->newfb) {
230 struct ipu_plane *plane = ipu_crtc->plane[0];
231
232 ipu_crtc->newfb = NULL;
233 ipu_plane_set_base(plane, ipu_crtc->base.primary->fb,
234 plane->x, plane->y);
235 ipu_crtc_handle_pageflip(ipu_crtc);
236 }
237
238 return IRQ_HANDLED;
239}
240
241static bool ipu_crtc_mode_fixup(struct drm_crtc *crtc,
242 const struct drm_display_mode *mode,
243 struct drm_display_mode *adjusted_mode)
244{
245 return true;
246}
247
248static void ipu_crtc_prepare(struct drm_crtc *crtc)
249{
250 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
251
252 ipu_fb_disable(ipu_crtc);
253}
254
255static void ipu_crtc_commit(struct drm_crtc *crtc)
256{
257 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
258
259 ipu_fb_enable(ipu_crtc);
260}
261
262static struct drm_crtc_helper_funcs ipu_helper_funcs = {
263 .dpms = ipu_crtc_dpms,
264 .mode_fixup = ipu_crtc_mode_fixup,
265 .mode_set = ipu_crtc_mode_set,
266 .prepare = ipu_crtc_prepare,
267 .commit = ipu_crtc_commit,
268};
269
270static int ipu_enable_vblank(struct drm_crtc *crtc)
271{
272 return 0;
273}
274
275static void ipu_disable_vblank(struct drm_crtc *crtc)
276{
277 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
278
279 ipu_crtc->page_flip_event = NULL;
280 ipu_crtc->newfb = NULL;
281}
282
283static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
284 u32 pixfmt, int hsync_pin, int vsync_pin)
285{
286 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
287
288 ipu_crtc->interface_pix_fmt = pixfmt;
289 ipu_crtc->di_hsync_pin = hsync_pin;
290 ipu_crtc->di_vsync_pin = vsync_pin;
291
292 switch (encoder_type) {
293 case DRM_MODE_ENCODER_DAC:
294 case DRM_MODE_ENCODER_TVDAC:
295 case DRM_MODE_ENCODER_LVDS:
296 ipu_crtc->di_clkflags = IPU_DI_CLKMODE_SYNC |
297 IPU_DI_CLKMODE_EXT;
298 break;
299 case DRM_MODE_ENCODER_TMDS:
300 case DRM_MODE_ENCODER_NONE:
301 ipu_crtc->di_clkflags = 0;
302 break;
303 }
304
305 return 0;
306}
307
308static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = {
309 .enable_vblank = ipu_enable_vblank,
310 .disable_vblank = ipu_disable_vblank,
311 .set_interface_pix_fmt = ipu_set_interface_pix_fmt,
312 .crtc_funcs = &ipu_crtc_funcs,
313 .crtc_helper_funcs = &ipu_helper_funcs,
314};
315
316static void ipu_put_resources(struct ipu_crtc *ipu_crtc)
317{
318 if (!IS_ERR_OR_NULL(ipu_crtc->dc))
319 ipu_dc_put(ipu_crtc->dc);
320 if (!IS_ERR_OR_NULL(ipu_crtc->di))
321 ipu_di_put(ipu_crtc->di);
322}
323
324static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
325 struct ipu_client_platformdata *pdata)
326{
327 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
328 int ret;
329
330 ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc);
331 if (IS_ERR(ipu_crtc->dc)) {
332 ret = PTR_ERR(ipu_crtc->dc);
333 goto err_out;
334 }
335
336 ipu_crtc->di = ipu_di_get(ipu, pdata->di);
337 if (IS_ERR(ipu_crtc->di)) {
338 ret = PTR_ERR(ipu_crtc->di);
339 goto err_out;
340 }
341
342 return 0;
343err_out:
344 ipu_put_resources(ipu_crtc);
345
346 return ret;
347}
348
349static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
350 struct ipu_client_platformdata *pdata, struct drm_device *drm)
351{
352 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
353 int dp = -EINVAL;
354 int ret;
355 int id;
356
357 ret = ipu_get_resources(ipu_crtc, pdata);
358 if (ret) {
359 dev_err(ipu_crtc->dev, "getting resources failed with %d.\n",
360 ret);
361 return ret;
362 }
363
364 ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc,
365 &ipu_crtc_helper_funcs, ipu_crtc->dev->of_node);
366 if (ret) {
367 dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret);
368 goto err_put_resources;
369 }
370
371 if (pdata->dp >= 0)
372 dp = IPU_DP_FLOW_SYNC_BG;
373 id = imx_drm_crtc_id(ipu_crtc->imx_crtc);
374 ipu_crtc->plane[0] = ipu_plane_init(ipu_crtc->base.dev, ipu,
375 pdata->dma[0], dp, BIT(id), true);
376 ret = ipu_plane_get_resources(ipu_crtc->plane[0]);
377 if (ret) {
378 dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n",
379 ret);
380 goto err_remove_crtc;
381 }
382
383 /* If this crtc is using the DP, add an overlay plane */
384 if (pdata->dp >= 0 && pdata->dma[1] > 0) {
385 ipu_crtc->plane[1] = ipu_plane_init(ipu_crtc->base.dev, ipu,
386 pdata->dma[1],
387 IPU_DP_FLOW_SYNC_FG,
388 BIT(id), false);
389 if (IS_ERR(ipu_crtc->plane[1]))
390 ipu_crtc->plane[1] = NULL;
391 }
392
393 ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]);
394 ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0,
395 "imx_drm", ipu_crtc);
396 if (ret < 0) {
397 dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
398 goto err_put_plane_res;
399 }
400
401 return 0;
402
403err_put_plane_res:
404 ipu_plane_put_resources(ipu_crtc->plane[0]);
405err_remove_crtc:
406 imx_drm_remove_crtc(ipu_crtc->imx_crtc);
407err_put_resources:
408 ipu_put_resources(ipu_crtc);
409
410 return ret;
411}
412
413static struct device_node *ipu_drm_get_port_by_id(struct device_node *parent,
414 int port_id)
415{
416 struct device_node *port;
417 int id, ret;
418
419 port = of_get_child_by_name(parent, "port");
420 while (port) {
421 ret = of_property_read_u32(port, "reg", &id);
422 if (!ret && id == port_id)
423 return port;
424
425 do {
426 port = of_get_next_child(parent, port);
427 if (!port)
428 return NULL;
429 } while (of_node_cmp(port->name, "port"));
430 }
431
432 return NULL;
433}
434
435static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
436{
437 struct ipu_client_platformdata *pdata = dev->platform_data;
438 struct drm_device *drm = data;
439 struct ipu_crtc *ipu_crtc;
440 int ret;
441
442 ipu_crtc = devm_kzalloc(dev, sizeof(*ipu_crtc), GFP_KERNEL);
443 if (!ipu_crtc)
444 return -ENOMEM;
445
446 ipu_crtc->dev = dev;
447
448 ret = ipu_crtc_init(ipu_crtc, pdata, drm);
449 if (ret)
450 return ret;
451
452 dev_set_drvdata(dev, ipu_crtc);
453
454 return 0;
455}
456
457static void ipu_drm_unbind(struct device *dev, struct device *master,
458 void *data)
459{
460 struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev);
461
462 imx_drm_remove_crtc(ipu_crtc->imx_crtc);
463
464 ipu_plane_put_resources(ipu_crtc->plane[0]);
465 ipu_put_resources(ipu_crtc);
466}
467
468static const struct component_ops ipu_crtc_ops = {
469 .bind = ipu_drm_bind,
470 .unbind = ipu_drm_unbind,
471};
472
473static int ipu_drm_probe(struct platform_device *pdev)
474{
475 struct device *dev = &pdev->dev;
476 struct ipu_client_platformdata *pdata = dev->platform_data;
477 int ret;
478
479 if (!dev->platform_data)
480 return -EINVAL;
481
482 if (!dev->of_node) {
483 /* Associate crtc device with the corresponding DI port node */
484 dev->of_node = ipu_drm_get_port_by_id(dev->parent->of_node,
485 pdata->di + 2);
486 if (!dev->of_node) {
487 dev_err(dev, "missing port@%d node in %s\n",
488 pdata->di + 2, dev->parent->of_node->full_name);
489 return -ENODEV;
490 }
491 }
492
493 ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
494 if (ret)
495 return ret;
496
497 return component_add(dev, &ipu_crtc_ops);
498}
499
500static int ipu_drm_remove(struct platform_device *pdev)
501{
502 component_del(&pdev->dev, &ipu_crtc_ops);
503 return 0;
504}
505
506static struct platform_driver ipu_drm_driver = {
507 .driver = {
508 .name = "imx-ipuv3-crtc",
509 },
510 .probe = ipu_drm_probe,
511 .remove = ipu_drm_remove,
512};
513module_platform_driver(ipu_drm_driver);
514
515MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
516MODULE_DESCRIPTION(DRIVER_DESC);
517MODULE_LICENSE("GPL");
518MODULE_ALIAS("platform:imx-ipuv3-crtc");
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
new file mode 100644
index 000000000000..944962b692bb
--- /dev/null
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -0,0 +1,363 @@
1/*
2 * i.MX IPUv3 DP Overlay Planes
3 *
4 * Copyright (C) 2013 Philipp Zabel, Pengutronix
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <drm/drmP.h>
17#include <drm/drm_fb_cma_helper.h>
18#include <drm/drm_gem_cma_helper.h>
19
20#include "video/imx-ipu-v3.h"
21#include "ipuv3-plane.h"
22
23#define to_ipu_plane(x) container_of(x, struct ipu_plane, base)
24
25static const uint32_t ipu_plane_formats[] = {
26 DRM_FORMAT_XRGB1555,
27 DRM_FORMAT_XBGR1555,
28 DRM_FORMAT_ARGB8888,
29 DRM_FORMAT_XRGB8888,
30 DRM_FORMAT_ABGR8888,
31 DRM_FORMAT_XBGR8888,
32 DRM_FORMAT_YUYV,
33 DRM_FORMAT_YVYU,
34 DRM_FORMAT_YUV420,
35 DRM_FORMAT_YVU420,
36};
37
38int ipu_plane_irq(struct ipu_plane *ipu_plane)
39{
40 return ipu_idmac_channel_irq(ipu_plane->ipu, ipu_plane->ipu_ch,
41 IPU_IRQ_EOF);
42}
43
44static int calc_vref(struct drm_display_mode *mode)
45{
46 unsigned long htotal, vtotal;
47
48 htotal = mode->htotal;
49 vtotal = mode->vtotal;
50
51 if (!htotal || !vtotal)
52 return 60;
53
54 return DIV_ROUND_UP(mode->clock * 1000, vtotal * htotal);
55}
56
57static inline int calc_bandwidth(int width, int height, unsigned int vref)
58{
59 return width * height * vref;
60}
61
62int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
63 int x, int y)
64{
65 struct drm_gem_cma_object *cma_obj;
66 unsigned long eba;
67
68 cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
69 if (!cma_obj) {
70 DRM_DEBUG_KMS("entry is null.\n");
71 return -EFAULT;
72 }
73
74 dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d",
75 &cma_obj->paddr, x, y);
76
77 ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]);
78
79 eba = cma_obj->paddr + fb->offsets[0] +
80 fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x;
81 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
82 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
83
84 /* cache offsets for subsequent pageflips */
85 ipu_plane->x = x;
86 ipu_plane->y = y;
87
88 return 0;
89}
90
91int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
92 struct drm_display_mode *mode,
93 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
94 unsigned int crtc_w, unsigned int crtc_h,
95 uint32_t src_x, uint32_t src_y,
96 uint32_t src_w, uint32_t src_h)
97{
98 struct device *dev = ipu_plane->base.dev->dev;
99 int ret;
100
101 /* no scaling */
102 if (src_w != crtc_w || src_h != crtc_h)
103 return -EINVAL;
104
105 /* clip to crtc bounds */
106 if (crtc_x < 0) {
107 if (-crtc_x > crtc_w)
108 return -EINVAL;
109 src_x += -crtc_x;
110 src_w -= -crtc_x;
111 crtc_w -= -crtc_x;
112 crtc_x = 0;
113 }
114 if (crtc_y < 0) {
115 if (-crtc_y > crtc_h)
116 return -EINVAL;
117 src_y += -crtc_y;
118 src_h -= -crtc_y;
119 crtc_h -= -crtc_y;
120 crtc_y = 0;
121 }
122 if (crtc_x + crtc_w > mode->hdisplay) {
123 if (crtc_x > mode->hdisplay)
124 return -EINVAL;
125 crtc_w = mode->hdisplay - crtc_x;
126 src_w = crtc_w;
127 }
128 if (crtc_y + crtc_h > mode->vdisplay) {
129 if (crtc_y > mode->vdisplay)
130 return -EINVAL;
131 crtc_h = mode->vdisplay - crtc_y;
132 src_h = crtc_h;
133 }
134 /* full plane minimum width is 13 pixels */
135 if (crtc_w < 13 && (ipu_plane->dp_flow != IPU_DP_FLOW_SYNC_FG))
136 return -EINVAL;
137 if (crtc_h < 2)
138 return -EINVAL;
139
140 switch (ipu_plane->dp_flow) {
141 case IPU_DP_FLOW_SYNC_BG:
142 ret = ipu_dp_setup_channel(ipu_plane->dp,
143 IPUV3_COLORSPACE_RGB,
144 IPUV3_COLORSPACE_RGB);
145 if (ret) {
146 dev_err(dev,
147 "initializing display processor failed with %d\n",
148 ret);
149 return ret;
150 }
151 ipu_dp_set_global_alpha(ipu_plane->dp, 1, 0, 1);
152 break;
153 case IPU_DP_FLOW_SYNC_FG:
154 ipu_dp_setup_channel(ipu_plane->dp,
155 ipu_drm_fourcc_to_colorspace(fb->pixel_format),
156 IPUV3_COLORSPACE_UNKNOWN);
157 ipu_dp_set_window_pos(ipu_plane->dp, crtc_x, crtc_y);
158 break;
159 }
160
161 ret = ipu_dmfc_init_channel(ipu_plane->dmfc, crtc_w);
162 if (ret) {
163 dev_err(dev, "initializing dmfc channel failed with %d\n", ret);
164 return ret;
165 }
166
167 ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc,
168 calc_bandwidth(crtc_w, crtc_h,
169 calc_vref(mode)), 64);
170 if (ret) {
171 dev_err(dev, "allocating dmfc bandwidth failed with %d\n", ret);
172 return ret;
173 }
174
175 ipu_cpmem_zero(ipu_plane->ipu_ch);
176 ipu_cpmem_set_resolution(ipu_plane->ipu_ch, src_w, src_h);
177 ret = ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->pixel_format);
178 if (ret < 0) {
179 dev_err(dev, "unsupported pixel format 0x%08x\n",
180 fb->pixel_format);
181 return ret;
182 }
183 ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
184
185 ret = ipu_plane_set_base(ipu_plane, fb, src_x, src_y);
186 if (ret < 0)
187 return ret;
188
189 return 0;
190}
191
192void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
193{
194 if (!IS_ERR_OR_NULL(ipu_plane->dp))
195 ipu_dp_put(ipu_plane->dp);
196 if (!IS_ERR_OR_NULL(ipu_plane->dmfc))
197 ipu_dmfc_put(ipu_plane->dmfc);
198 if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch))
199 ipu_idmac_put(ipu_plane->ipu_ch);
200}
201
202int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
203{
204 int ret;
205
206 ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma);
207 if (IS_ERR(ipu_plane->ipu_ch)) {
208 ret = PTR_ERR(ipu_plane->ipu_ch);
209 DRM_ERROR("failed to get idmac channel: %d\n", ret);
210 return ret;
211 }
212
213 ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma);
214 if (IS_ERR(ipu_plane->dmfc)) {
215 ret = PTR_ERR(ipu_plane->dmfc);
216 DRM_ERROR("failed to get dmfc: ret %d\n", ret);
217 goto err_out;
218 }
219
220 if (ipu_plane->dp_flow >= 0) {
221 ipu_plane->dp = ipu_dp_get(ipu_plane->ipu, ipu_plane->dp_flow);
222 if (IS_ERR(ipu_plane->dp)) {
223 ret = PTR_ERR(ipu_plane->dp);
224 DRM_ERROR("failed to get dp flow: %d\n", ret);
225 goto err_out;
226 }
227 }
228
229 return 0;
230err_out:
231 ipu_plane_put_resources(ipu_plane);
232
233 return ret;
234}
235
236void ipu_plane_enable(struct ipu_plane *ipu_plane)
237{
238 if (ipu_plane->dp)
239 ipu_dp_enable(ipu_plane->ipu);
240 ipu_dmfc_enable_channel(ipu_plane->dmfc);
241 ipu_idmac_enable_channel(ipu_plane->ipu_ch);
242 if (ipu_plane->dp)
243 ipu_dp_enable_channel(ipu_plane->dp);
244
245 ipu_plane->enabled = true;
246}
247
248void ipu_plane_disable(struct ipu_plane *ipu_plane)
249{
250 ipu_plane->enabled = false;
251
252 ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50);
253
254 if (ipu_plane->dp)
255 ipu_dp_disable_channel(ipu_plane->dp);
256 ipu_idmac_disable_channel(ipu_plane->ipu_ch);
257 ipu_dmfc_disable_channel(ipu_plane->dmfc);
258 if (ipu_plane->dp)
259 ipu_dp_disable(ipu_plane->ipu);
260}
261
262/*
263 * drm_plane API
264 */
265
266static int ipu_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
267 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
268 unsigned int crtc_w, unsigned int crtc_h,
269 uint32_t src_x, uint32_t src_y,
270 uint32_t src_w, uint32_t src_h)
271{
272 struct ipu_plane *ipu_plane = to_ipu_plane(plane);
273 int ret = 0;
274
275 DRM_DEBUG_KMS("plane - %p\n", plane);
276
277 if (!ipu_plane->enabled)
278 ret = ipu_plane_get_resources(ipu_plane);
279 if (ret < 0)
280 return ret;
281
282 ret = ipu_plane_mode_set(ipu_plane, crtc, &crtc->hwmode, fb,
283 crtc_x, crtc_y, crtc_w, crtc_h,
284 src_x >> 16, src_y >> 16, src_w >> 16, src_h >> 16);
285 if (ret < 0) {
286 ipu_plane_put_resources(ipu_plane);
287 return ret;
288 }
289
290 if (crtc != plane->crtc)
291 dev_info(plane->dev->dev, "crtc change: %p -> %p\n",
292 plane->crtc, crtc);
293 plane->crtc = crtc;
294
295 if (!ipu_plane->enabled)
296 ipu_plane_enable(ipu_plane);
297
298 return 0;
299}
300
301static int ipu_disable_plane(struct drm_plane *plane)
302{
303 struct ipu_plane *ipu_plane = to_ipu_plane(plane);
304
305 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
306
307 if (ipu_plane->enabled)
308 ipu_plane_disable(ipu_plane);
309
310 ipu_plane_put_resources(ipu_plane);
311
312 return 0;
313}
314
315static void ipu_plane_destroy(struct drm_plane *plane)
316{
317 struct ipu_plane *ipu_plane = to_ipu_plane(plane);
318
319 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
320
321 ipu_disable_plane(plane);
322 drm_plane_cleanup(plane);
323 kfree(ipu_plane);
324}
325
326static struct drm_plane_funcs ipu_plane_funcs = {
327 .update_plane = ipu_update_plane,
328 .disable_plane = ipu_disable_plane,
329 .destroy = ipu_plane_destroy,
330};
331
332struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
333 int dma, int dp, unsigned int possible_crtcs,
334 bool priv)
335{
336 struct ipu_plane *ipu_plane;
337 int ret;
338
339 DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
340 dma, dp, possible_crtcs);
341
342 ipu_plane = kzalloc(sizeof(*ipu_plane), GFP_KERNEL);
343 if (!ipu_plane) {
344 DRM_ERROR("failed to allocate plane\n");
345 return ERR_PTR(-ENOMEM);
346 }
347
348 ipu_plane->ipu = ipu;
349 ipu_plane->dma = dma;
350 ipu_plane->dp_flow = dp;
351
352 ret = drm_plane_init(dev, &ipu_plane->base, possible_crtcs,
353 &ipu_plane_funcs, ipu_plane_formats,
354 ARRAY_SIZE(ipu_plane_formats),
355 priv);
356 if (ret) {
357 DRM_ERROR("failed to initialize plane\n");
358 kfree(ipu_plane);
359 return ERR_PTR(ret);
360 }
361
362 return ipu_plane;
363}
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.h b/drivers/gpu/drm/imx/ipuv3-plane.h
new file mode 100644
index 000000000000..c0aae5bcb5d4
--- /dev/null
+++ b/drivers/gpu/drm/imx/ipuv3-plane.h
@@ -0,0 +1,55 @@
1#ifndef __IPUV3_PLANE_H__
2#define __IPUV3_PLANE_H__
3
4#include <drm/drm_crtc.h> /* drm_plane */
5
6struct drm_plane;
7struct drm_device;
8struct ipu_soc;
9struct drm_crtc;
10struct drm_framebuffer;
11
12struct ipuv3_channel;
13struct dmfc_channel;
14struct ipu_dp;
15
16struct ipu_plane {
17 struct drm_plane base;
18
19 struct ipu_soc *ipu;
20 struct ipuv3_channel *ipu_ch;
21 struct dmfc_channel *dmfc;
22 struct ipu_dp *dp;
23
24 int dma;
25 int dp_flow;
26
27 int x;
28 int y;
29
30 bool enabled;
31};
32
33struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
34 int dma, int dp, unsigned int possible_crtcs,
35 bool priv);
36
37/* Init IDMAC, DMFC, DP */
38int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc,
39 struct drm_display_mode *mode,
40 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
41 unsigned int crtc_w, unsigned int crtc_h,
42 uint32_t src_x, uint32_t src_y, uint32_t src_w,
43 uint32_t src_h);
44
45void ipu_plane_enable(struct ipu_plane *plane);
46void ipu_plane_disable(struct ipu_plane *plane);
47int ipu_plane_set_base(struct ipu_plane *plane, struct drm_framebuffer *fb,
48 int x, int y);
49
50int ipu_plane_get_resources(struct ipu_plane *plane);
51void ipu_plane_put_resources(struct ipu_plane *plane);
52
53int ipu_plane_irq(struct ipu_plane *plane);
54
55#endif
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
new file mode 100644
index 000000000000..8a76a5c1c34b
--- /dev/null
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -0,0 +1,295 @@
1/*
2 * i.MX drm driver - parallel display implementation
3 *
4 * Copyright (C) 2012 Sascha Hauer, Pengutronix
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301, USA.
19 */
20
21#include <linux/component.h>
22#include <linux/module.h>
23#include <drm/drmP.h>
24#include <drm/drm_fb_helper.h>
25#include <drm/drm_crtc_helper.h>
26#include <drm/drm_panel.h>
27#include <linux/videodev2.h>
28#include <video/of_display_timing.h>
29
30#include "imx-drm.h"
31
32#define con_to_imxpd(x) container_of(x, struct imx_parallel_display, connector)
33#define enc_to_imxpd(x) container_of(x, struct imx_parallel_display, encoder)
34
35struct imx_parallel_display {
36 struct drm_connector connector;
37 struct drm_encoder encoder;
38 struct device *dev;
39 void *edid;
40 int edid_len;
41 u32 interface_pix_fmt;
42 int mode_valid;
43 struct drm_display_mode mode;
44 struct drm_panel *panel;
45};
46
47static enum drm_connector_status imx_pd_connector_detect(
48 struct drm_connector *connector, bool force)
49{
50 return connector_status_connected;
51}
52
53static int imx_pd_connector_get_modes(struct drm_connector *connector)
54{
55 struct imx_parallel_display *imxpd = con_to_imxpd(connector);
56 struct device_node *np = imxpd->dev->of_node;
57 int num_modes = 0;
58
59 if (imxpd->panel && imxpd->panel->funcs &&
60 imxpd->panel->funcs->get_modes) {
61 num_modes = imxpd->panel->funcs->get_modes(imxpd->panel);
62 if (num_modes > 0)
63 return num_modes;
64 }
65
66 if (imxpd->edid) {
67 drm_mode_connector_update_edid_property(connector, imxpd->edid);
68 num_modes = drm_add_edid_modes(connector, imxpd->edid);
69 }
70
71 if (imxpd->mode_valid) {
72 struct drm_display_mode *mode = drm_mode_create(connector->dev);
73
74 if (!mode)
75 return -EINVAL;
76 drm_mode_copy(mode, &imxpd->mode);
77 mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
78 drm_mode_probed_add(connector, mode);
79 num_modes++;
80 }
81
82 if (np) {
83 struct drm_display_mode *mode = drm_mode_create(connector->dev);
84
85 if (!mode)
86 return -EINVAL;
87 of_get_drm_display_mode(np, &imxpd->mode, OF_USE_NATIVE_MODE);
88 drm_mode_copy(mode, &imxpd->mode);
89 mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
90 drm_mode_probed_add(connector, mode);
91 num_modes++;
92 }
93
94 return num_modes;
95}
96
97static struct drm_encoder *imx_pd_connector_best_encoder(
98 struct drm_connector *connector)
99{
100 struct imx_parallel_display *imxpd = con_to_imxpd(connector);
101
102 return &imxpd->encoder;
103}
104
105static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode)
106{
107 struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
108
109 if (mode != DRM_MODE_DPMS_ON)
110 drm_panel_disable(imxpd->panel);
111 else
112 drm_panel_enable(imxpd->panel);
113}
114
115static bool imx_pd_encoder_mode_fixup(struct drm_encoder *encoder,
116 const struct drm_display_mode *mode,
117 struct drm_display_mode *adjusted_mode)
118{
119 return true;
120}
121
122static void imx_pd_encoder_prepare(struct drm_encoder *encoder)
123{
124 struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
125
126 imx_drm_panel_format(encoder, imxpd->interface_pix_fmt);
127}
128
129static void imx_pd_encoder_commit(struct drm_encoder *encoder)
130{
131}
132
133static void imx_pd_encoder_mode_set(struct drm_encoder *encoder,
134 struct drm_display_mode *mode,
135 struct drm_display_mode *adjusted_mode)
136{
137}
138
139static void imx_pd_encoder_disable(struct drm_encoder *encoder)
140{
141}
142
143static struct drm_connector_funcs imx_pd_connector_funcs = {
144 .dpms = drm_helper_connector_dpms,
145 .fill_modes = drm_helper_probe_single_connector_modes,
146 .detect = imx_pd_connector_detect,
147 .destroy = imx_drm_connector_destroy,
148};
149
150static struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = {
151 .get_modes = imx_pd_connector_get_modes,
152 .best_encoder = imx_pd_connector_best_encoder,
153};
154
155static struct drm_encoder_funcs imx_pd_encoder_funcs = {
156 .destroy = imx_drm_encoder_destroy,
157};
158
159static struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = {
160 .dpms = imx_pd_encoder_dpms,
161 .mode_fixup = imx_pd_encoder_mode_fixup,
162 .prepare = imx_pd_encoder_prepare,
163 .commit = imx_pd_encoder_commit,
164 .mode_set = imx_pd_encoder_mode_set,
165 .disable = imx_pd_encoder_disable,
166};
167
168static int imx_pd_register(struct drm_device *drm,
169 struct imx_parallel_display *imxpd)
170{
171 int ret;
172
173 ret = imx_drm_encoder_parse_of(drm, &imxpd->encoder,
174 imxpd->dev->of_node);
175 if (ret)
176 return ret;
177
178 /* set the connector's dpms to OFF so that
179 * drm_helper_connector_dpms() won't return
180 * immediately since the current state is ON
181 * at this point.
182 */
183 imxpd->connector.dpms = DRM_MODE_DPMS_OFF;
184
185 drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs);
186 drm_encoder_init(drm, &imxpd->encoder, &imx_pd_encoder_funcs,
187 DRM_MODE_ENCODER_NONE);
188
189 drm_connector_helper_add(&imxpd->connector,
190 &imx_pd_connector_helper_funcs);
191 drm_connector_init(drm, &imxpd->connector, &imx_pd_connector_funcs,
192 DRM_MODE_CONNECTOR_VGA);
193
194 if (imxpd->panel)
195 drm_panel_attach(imxpd->panel, &imxpd->connector);
196
197 drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder);
198
199 imxpd->connector.encoder = &imxpd->encoder;
200
201 return 0;
202}
203
204static int imx_pd_bind(struct device *dev, struct device *master, void *data)
205{
206 struct drm_device *drm = data;
207 struct device_node *np = dev->of_node;
208 struct device_node *panel_node;
209 const u8 *edidp;
210 struct imx_parallel_display *imxpd;
211 int ret;
212 const char *fmt;
213
214 imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL);
215 if (!imxpd)
216 return -ENOMEM;
217
218 edidp = of_get_property(np, "edid", &imxpd->edid_len);
219 if (edidp)
220 imxpd->edid = kmemdup(edidp, imxpd->edid_len, GFP_KERNEL);
221
222 ret = of_property_read_string(np, "interface-pix-fmt", &fmt);
223 if (!ret) {
224 if (!strcmp(fmt, "rgb24"))
225 imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB24;
226 else if (!strcmp(fmt, "rgb565"))
227 imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB565;
228 else if (!strcmp(fmt, "bgr666"))
229 imxpd->interface_pix_fmt = V4L2_PIX_FMT_BGR666;
230 else if (!strcmp(fmt, "lvds666"))
231 imxpd->interface_pix_fmt =
232 v4l2_fourcc('L', 'V', 'D', '6');
233 }
234
235 panel_node = of_parse_phandle(np, "fsl,panel", 0);
236 if (panel_node)
237 imxpd->panel = of_drm_find_panel(panel_node);
238
239 imxpd->dev = dev;
240
241 ret = imx_pd_register(drm, imxpd);
242 if (ret)
243 return ret;
244
245 dev_set_drvdata(dev, imxpd);
246
247 return 0;
248}
249
250static void imx_pd_unbind(struct device *dev, struct device *master,
251 void *data)
252{
253 struct imx_parallel_display *imxpd = dev_get_drvdata(dev);
254
255 imxpd->encoder.funcs->destroy(&imxpd->encoder);
256 imxpd->connector.funcs->destroy(&imxpd->connector);
257}
258
259static const struct component_ops imx_pd_ops = {
260 .bind = imx_pd_bind,
261 .unbind = imx_pd_unbind,
262};
263
264static int imx_pd_probe(struct platform_device *pdev)
265{
266 return component_add(&pdev->dev, &imx_pd_ops);
267}
268
269static int imx_pd_remove(struct platform_device *pdev)
270{
271 component_del(&pdev->dev, &imx_pd_ops);
272 return 0;
273}
274
275static const struct of_device_id imx_pd_dt_ids[] = {
276 { .compatible = "fsl,imx-parallel-display", },
277 { /* sentinel */ }
278};
279MODULE_DEVICE_TABLE(of, imx_pd_dt_ids);
280
281static struct platform_driver imx_pd_driver = {
282 .probe = imx_pd_probe,
283 .remove = imx_pd_remove,
284 .driver = {
285 .of_match_table = imx_pd_dt_ids,
286 .name = "imx-parallel-display",
287 },
288};
289
290module_platform_driver(imx_pd_driver);
291
292MODULE_DESCRIPTION("i.MX parallel display driver");
293MODULE_AUTHOR("Sascha Hauer, Pengutronix");
294MODULE_LICENSE("GPL");
295MODULE_ALIAS("platform:imx-parallel-display");