aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-01-20 19:17:16 -0500
committerDave Airlie <airlied@redhat.com>2015-01-20 19:17:16 -0500
commitfc83975348ebce07793e6b9f780edc3cbcffa9fc (patch)
tree0fc7972c181cebed1c344852bb8b1a96607d3b15 /drivers/gpu
parentb2eb0489809cf0b824357b6fa85aab1aabe3f063 (diff)
parentd50141d8072e5322ee0518a8c967b5c9caf463d2 (diff)
Merge tag 'imx-drm-next-2015-01-09' of git://git.pengutronix.de/git/pza/linux into drm-next
imx-drm mode fixup support, imx-hdmi bridge conversion and imx-drm cleanup - Implement mode_fixup for a DI vertical timing limitation - Use generic DRM OF helpers in DRM core - Convert imx-hdmi to dw_hdmi drm_bridge and add rockchip driver - Add DC use counter to fix multi-display support - Simplify handling of DI clock flags - A few small fixes and cleanup * tag 'imx-drm-next-2015-01-09' of git://git.pengutronix.de/git/pza/linux: (26 commits) imx-drm: core: handling of DI clock flags to ipu_crtc_mode_set() gpu: ipu-di: Switch to DIV_ROUND_CLOSEST for DI clock divider calc gpu: ipu-v3: Use videomode in struct ipu_di_signal_cfg imx-drm: encoder prepare/mode_set must use adjusted mode imx-drm: ipuv3-crtc: Implement mode_fixup drm_modes: add drm_display_mode_to_videomode gpu: ipu-di: remove some non-functional code gpu: ipu-di: Add ipu_di_adjust_videomode() drm: rockchip: export functions needed by rockchip dw_hdmi bridge driver drm: bridge/dw_hdmi: request interrupt only after initializing the mutes drm: bridge/dw_hdmi: add rockchip rk3288 support dt-bindings: Add documentation for rockchip dw hdmi drm: bridge/dw_hdmi: add function dw_hdmi_phy_enable_spare drm: bridge/dw_hdmi: clear i2cmphy_stat0 reg in hdmi_phy_wait_i2c_done drm: bridge/dw_hdmi: add mode_valid support drm: bridge/dw_hdmi: add support for multi-byte register width access dt-bindings: add document for dw_hdmi drm: imx: imx-hdmi: move imx-hdmi to bridge/dw_hdmi drm: imx: imx-hdmi: split phy configuration to platform driver drm: imx: imx-hdmi: convert imx-hdmi to drm_bridge mode ...
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/bridge/Kconfig5
-rw-r--r--drivers/gpu/drm/bridge/Makefile1
-rw-r--r--drivers/gpu/drm/bridge/dw_hdmi.c (renamed from drivers/gpu/drm/imx/imx-hdmi.c)724
-rw-r--r--drivers/gpu/drm/bridge/dw_hdmi.h (renamed from drivers/gpu/drm/imx/imx-hdmi.h)4
-rw-r--r--drivers/gpu/drm/drm_modes.c40
-rw-r--r--drivers/gpu/drm/imx/Kconfig1
-rw-r--r--drivers/gpu/drm/imx/Makefile2
-rw-r--r--drivers/gpu/drm/imx/dw_hdmi-imx.c258
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c87
-rw-r--r--drivers/gpu/drm/imx/imx-drm.h2
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c8
-rw-r--r--drivers/gpu/drm/imx/imx-tve.c4
-rw-r--r--drivers/gpu/drm/imx/ipuv3-crtc.c78
-rw-r--r--drivers/gpu/drm/imx/parallel-display.c7
-rw-r--r--drivers/gpu/drm/rockchip/Kconfig10
-rw-r--r--drivers/gpu/drm/rockchip/Makefile2
-rw-r--r--drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c341
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c1
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c1
-rw-r--r--drivers/gpu/ipu-v3/ipu-dc.c25
-rw-r--r--drivers/gpu/ipu-v3/ipu-di.c121
21 files changed, 1170 insertions, 552 deletions
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 884923f982d9..b70f3c8d4e8a 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -3,3 +3,8 @@ config DRM_PTN3460
3 depends on DRM 3 depends on DRM
4 select DRM_KMS_HELPER 4 select DRM_KMS_HELPER
5 ---help--- 5 ---help---
6
7config DRM_DW_HDMI
8 tristate
9 depends on DRM
10 select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index b4733e1fbd2e..d8a8cfd12fbb 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -1,3 +1,4 @@
1ccflags-y := -Iinclude/drm 1ccflags-y := -Iinclude/drm
2 2
3obj-$(CONFIG_DRM_PTN3460) += ptn3460.o 3obj-$(CONFIG_DRM_PTN3460) += ptn3460.o
4obj-$(CONFIG_DRM_DW_HDMI) += dw_hdmi.o
diff --git a/drivers/gpu/drm/imx/imx-hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index ddc53e039530..6ea000504173 100644
--- a/drivers/gpu/drm/imx/imx-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -6,31 +6,26 @@
6 * the Free Software Foundation; either version 2 of the License, or 6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version. 7 * (at your option) any later version.
8 * 8 *
9 * SH-Mobile High-Definition Multimedia Interface (HDMI) driver 9 * Designware High-Definition Multimedia Interface (HDMI) driver
10 * for SLISHDMI13T and SLIPHDMIT IP cores
11 * 10 *
12 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> 11 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
13 */ 12 */
14 13#include <linux/module.h>
15#include <linux/component.h>
16#include <linux/irq.h> 14#include <linux/irq.h>
17#include <linux/delay.h> 15#include <linux/delay.h>
18#include <linux/err.h> 16#include <linux/err.h>
19#include <linux/clk.h> 17#include <linux/clk.h>
20#include <linux/hdmi.h> 18#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> 19#include <linux/of_device.h>
25 20
21#include <drm/drm_of.h>
26#include <drm/drmP.h> 22#include <drm/drmP.h>
27#include <drm/drm_crtc_helper.h> 23#include <drm/drm_crtc_helper.h>
28#include <drm/drm_edid.h> 24#include <drm/drm_edid.h>
29#include <drm/drm_encoder_slave.h> 25#include <drm/drm_encoder_slave.h>
30#include <video/imx-ipu-v3.h> 26#include <drm/bridge/dw_hdmi.h>
31 27
32#include "imx-hdmi.h" 28#include "dw_hdmi.h"
33#include "imx-drm.h"
34 29
35#define HDMI_EDID_LEN 512 30#define HDMI_EDID_LEN 512
36 31
@@ -54,11 +49,6 @@ enum hdmi_datamap {
54 YCbCr422_12B = 0x12, 49 YCbCr422_12B = 0x12,
55}; 50};
56 51
57enum imx_hdmi_devtype {
58 IMX6Q_HDMI,
59 IMX6DL_HDMI,
60};
61
62static const u16 csc_coeff_default[3][4] = { 52static const u16 csc_coeff_default[3][4] = {
63 { 0x2000, 0x0000, 0x0000, 0x0000 }, 53 { 0x2000, 0x0000, 0x0000, 0x0000 },
64 { 0x0000, 0x2000, 0x0000, 0x0000 }, 54 { 0x0000, 0x2000, 0x0000, 0x0000 },
@@ -111,16 +101,19 @@ struct hdmi_data_info {
111 struct hdmi_vmode video_mode; 101 struct hdmi_vmode video_mode;
112}; 102};
113 103
114struct imx_hdmi { 104struct dw_hdmi {
115 struct drm_connector connector; 105 struct drm_connector connector;
116 struct drm_encoder encoder; 106 struct drm_encoder *encoder;
107 struct drm_bridge *bridge;
117 108
118 enum imx_hdmi_devtype dev_type; 109 enum dw_hdmi_devtype dev_type;
119 struct device *dev; 110 struct device *dev;
120 struct clk *isfr_clk; 111 struct clk *isfr_clk;
121 struct clk *iahb_clk; 112 struct clk *iahb_clk;
122 113
123 struct hdmi_data_info hdmi_data; 114 struct hdmi_data_info hdmi_data;
115 const struct dw_hdmi_plat_data *plat_data;
116
124 int vic; 117 int vic;
125 118
126 u8 edid[HDMI_EDID_LEN]; 119 u8 edid[HDMI_EDID_LEN];
@@ -135,26 +128,42 @@ struct imx_hdmi {
135 128
136 unsigned int sample_rate; 129 unsigned int sample_rate;
137 int ratio; 130 int ratio;
131
132 void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
133 u8 (*read)(struct dw_hdmi *hdmi, int offset);
138}; 134};
139 135
140static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi *hdmi, int ipu_di) 136static void dw_hdmi_writel(struct dw_hdmi *hdmi, u8 val, int offset)
141{ 137{
142 regmap_update_bits(hdmi->regmap, IOMUXC_GPR3, 138 writel(val, hdmi->regs + (offset << 2));
143 IMX6Q_GPR3_HDMI_MUX_CTL_MASK,
144 ipu_di << IMX6Q_GPR3_HDMI_MUX_CTL_SHIFT);
145} 139}
146 140
147static inline void hdmi_writeb(struct imx_hdmi *hdmi, u8 val, int offset) 141static u8 dw_hdmi_readl(struct dw_hdmi *hdmi, int offset)
142{
143 return readl(hdmi->regs + (offset << 2));
144}
145
146static void dw_hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
148{ 147{
149 writeb(val, hdmi->regs + offset); 148 writeb(val, hdmi->regs + offset);
150} 149}
151 150
152static inline u8 hdmi_readb(struct imx_hdmi *hdmi, int offset) 151static u8 dw_hdmi_readb(struct dw_hdmi *hdmi, int offset)
153{ 152{
154 return readb(hdmi->regs + offset); 153 return readb(hdmi->regs + offset);
155} 154}
156 155
157static void hdmi_modb(struct imx_hdmi *hdmi, u8 data, u8 mask, unsigned reg) 156static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
157{
158 hdmi->write(hdmi, val, offset);
159}
160
161static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset)
162{
163 return hdmi->read(hdmi, offset);
164}
165
166static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
158{ 167{
159 u8 val = hdmi_readb(hdmi, reg) & ~mask; 168 u8 val = hdmi_readb(hdmi, reg) & ~mask;
160 169
@@ -162,13 +171,13 @@ static void hdmi_modb(struct imx_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
162 hdmi_writeb(hdmi, val, reg); 171 hdmi_writeb(hdmi, val, reg);
163} 172}
164 173
165static void hdmi_mask_writeb(struct imx_hdmi *hdmi, u8 data, unsigned int reg, 174static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
166 u8 shift, u8 mask) 175 u8 shift, u8 mask)
167{ 176{
168 hdmi_modb(hdmi, data << shift, mask, reg); 177 hdmi_modb(hdmi, data << shift, mask, reg);
169} 178}
170 179
171static void hdmi_set_clock_regenerator_n(struct imx_hdmi *hdmi, 180static void hdmi_set_clock_regenerator_n(struct dw_hdmi *hdmi,
172 unsigned int value) 181 unsigned int value)
173{ 182{
174 hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1); 183 hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1);
@@ -179,7 +188,7 @@ static void hdmi_set_clock_regenerator_n(struct imx_hdmi *hdmi,
179 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3); 188 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
180} 189}
181 190
182static void hdmi_regenerate_cts(struct imx_hdmi *hdmi, unsigned int cts) 191static void hdmi_regenerate_cts(struct dw_hdmi *hdmi, unsigned int cts)
183{ 192{
184 /* Must be set/cleared first */ 193 /* Must be set/cleared first */
185 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); 194 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
@@ -326,8 +335,8 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
326 return (cts * ratio) / 100; 335 return (cts * ratio) / 100;
327} 336}
328 337
329static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi, 338static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
330 unsigned long pixel_clk) 339 unsigned long pixel_clk)
331{ 340{
332 unsigned int clk_n, clk_cts; 341 unsigned int clk_n, clk_cts;
333 342
@@ -338,7 +347,7 @@ static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi,
338 347
339 if (!clk_cts) { 348 if (!clk_cts) {
340 dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n", 349 dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
341 __func__, pixel_clk); 350 __func__, pixel_clk);
342 return; 351 return;
343 } 352 }
344 353
@@ -350,12 +359,12 @@ static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi,
350 hdmi_regenerate_cts(hdmi, clk_cts); 359 hdmi_regenerate_cts(hdmi, clk_cts);
351} 360}
352 361
353static void hdmi_init_clk_regenerator(struct imx_hdmi *hdmi) 362static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
354{ 363{
355 hdmi_set_clk_regenerator(hdmi, 74250000); 364 hdmi_set_clk_regenerator(hdmi, 74250000);
356} 365}
357 366
358static void hdmi_clk_regenerator_update_pixel_clock(struct imx_hdmi *hdmi) 367static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
359{ 368{
360 hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock); 369 hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
361} 370}
@@ -367,7 +376,7 @@ static void hdmi_clk_regenerator_update_pixel_clock(struct imx_hdmi *hdmi)
367 * pin{31~24} <==> G[7:0] 376 * pin{31~24} <==> G[7:0]
368 * pin{15~8} <==> B[7:0] 377 * pin{15~8} <==> B[7:0]
369 */ 378 */
370static void hdmi_video_sample(struct imx_hdmi *hdmi) 379static void hdmi_video_sample(struct dw_hdmi *hdmi)
371{ 380{
372 int color_format = 0; 381 int color_format = 0;
373 u8 val; 382 u8 val;
@@ -423,12 +432,12 @@ static void hdmi_video_sample(struct imx_hdmi *hdmi)
423 hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1); 432 hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1);
424} 433}
425 434
426static int is_color_space_conversion(struct imx_hdmi *hdmi) 435static int is_color_space_conversion(struct dw_hdmi *hdmi)
427{ 436{
428 return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format; 437 return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
429} 438}
430 439
431static int is_color_space_decimation(struct imx_hdmi *hdmi) 440static int is_color_space_decimation(struct dw_hdmi *hdmi)
432{ 441{
433 if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS) 442 if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
434 return 0; 443 return 0;
@@ -438,7 +447,7 @@ static int is_color_space_decimation(struct imx_hdmi *hdmi)
438 return 0; 447 return 0;
439} 448}
440 449
441static int is_color_space_interpolation(struct imx_hdmi *hdmi) 450static int is_color_space_interpolation(struct dw_hdmi *hdmi)
442{ 451{
443 if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS) 452 if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
444 return 0; 453 return 0;
@@ -448,7 +457,7 @@ static int is_color_space_interpolation(struct imx_hdmi *hdmi)
448 return 0; 457 return 0;
449} 458}
450 459
451static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi) 460static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
452{ 461{
453 const u16 (*csc_coeff)[3][4] = &csc_coeff_default; 462 const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
454 unsigned i; 463 unsigned i;
@@ -477,13 +486,11 @@ static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi)
477 u16 coeff_b = (*csc_coeff)[1][i]; 486 u16 coeff_b = (*csc_coeff)[1][i];
478 u16 coeff_c = (*csc_coeff)[2][i]; 487 u16 coeff_c = (*csc_coeff)[2][i];
479 488
480 hdmi_writeb(hdmi, coeff_a & 0xff, 489 hdmi_writeb(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
481 HDMI_CSC_COEF_A1_LSB + i * 2);
482 hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2); 490 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); 491 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); 492 hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
485 hdmi_writeb(hdmi, coeff_c & 0xff, 493 hdmi_writeb(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
486 HDMI_CSC_COEF_C1_LSB + i * 2);
487 hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2); 494 hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
488 } 495 }
489 496
@@ -491,7 +498,7 @@ static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi)
491 HDMI_CSC_SCALE); 498 HDMI_CSC_SCALE);
492} 499}
493 500
494static void hdmi_video_csc(struct imx_hdmi *hdmi) 501static void hdmi_video_csc(struct dw_hdmi *hdmi)
495{ 502{
496 int color_depth = 0; 503 int color_depth = 0;
497 int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE; 504 int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
@@ -519,7 +526,7 @@ static void hdmi_video_csc(struct imx_hdmi *hdmi)
519 hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK, 526 hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
520 HDMI_CSC_SCALE); 527 HDMI_CSC_SCALE);
521 528
522 imx_hdmi_update_csc_coeffs(hdmi); 529 dw_hdmi_update_csc_coeffs(hdmi);
523} 530}
524 531
525/* 532/*
@@ -527,7 +534,7 @@ static void hdmi_video_csc(struct imx_hdmi *hdmi)
527 * for example, if input is YCC422 mode or repeater is used, 534 * for example, if input is YCC422 mode or repeater is used,
528 * data should be repacked this module can be bypassed. 535 * data should be repacked this module can be bypassed.
529 */ 536 */
530static void hdmi_video_packetize(struct imx_hdmi *hdmi) 537static void hdmi_video_packetize(struct dw_hdmi *hdmi)
531{ 538{
532 unsigned int color_depth = 0; 539 unsigned int color_depth = 0;
533 unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit; 540 unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit;
@@ -535,21 +542,22 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi)
535 struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data; 542 struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
536 u8 val, vp_conf; 543 u8 val, vp_conf;
537 544
538 if (hdmi_data->enc_out_format == RGB 545 if (hdmi_data->enc_out_format == RGB ||
539 || hdmi_data->enc_out_format == YCBCR444) { 546 hdmi_data->enc_out_format == YCBCR444) {
540 if (!hdmi_data->enc_color_depth) 547 if (!hdmi_data->enc_color_depth) {
541 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; 548 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
542 else if (hdmi_data->enc_color_depth == 8) { 549 } else if (hdmi_data->enc_color_depth == 8) {
543 color_depth = 4; 550 color_depth = 4;
544 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; 551 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
545 } else if (hdmi_data->enc_color_depth == 10) 552 } else if (hdmi_data->enc_color_depth == 10) {
546 color_depth = 5; 553 color_depth = 5;
547 else if (hdmi_data->enc_color_depth == 12) 554 } else if (hdmi_data->enc_color_depth == 12) {
548 color_depth = 6; 555 color_depth = 6;
549 else if (hdmi_data->enc_color_depth == 16) 556 } else if (hdmi_data->enc_color_depth == 16) {
550 color_depth = 7; 557 color_depth = 7;
551 else 558 } else {
552 return; 559 return;
560 }
553 } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) { 561 } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
554 if (!hdmi_data->enc_color_depth || 562 if (!hdmi_data->enc_color_depth ||
555 hdmi_data->enc_color_depth == 8) 563 hdmi_data->enc_color_depth == 8)
@@ -561,8 +569,9 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi)
561 else 569 else
562 return; 570 return;
563 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422; 571 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
564 } else 572 } else {
565 return; 573 return;
574 }
566 575
567 /* set the packetizer registers */ 576 /* set the packetizer registers */
568 val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) & 577 val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
@@ -622,182 +631,132 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi)
622 HDMI_VP_CONF); 631 HDMI_VP_CONF);
623} 632}
624 633
625static inline void hdmi_phy_test_clear(struct imx_hdmi *hdmi, 634static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
626 unsigned char bit) 635 unsigned char bit)
627{ 636{
628 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET, 637 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET,
629 HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0); 638 HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
630} 639}
631 640
632static inline void hdmi_phy_test_enable(struct imx_hdmi *hdmi, 641static inline void hdmi_phy_test_enable(struct dw_hdmi *hdmi,
633 unsigned char bit) 642 unsigned char bit)
634{ 643{
635 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET, 644 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET,
636 HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0); 645 HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0);
637} 646}
638 647
639static inline void hdmi_phy_test_clock(struct imx_hdmi *hdmi, 648static inline void hdmi_phy_test_clock(struct dw_hdmi *hdmi,
640 unsigned char bit) 649 unsigned char bit)
641{ 650{
642 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET, 651 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET,
643 HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0); 652 HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0);
644} 653}
645 654
646static inline void hdmi_phy_test_din(struct imx_hdmi *hdmi, 655static inline void hdmi_phy_test_din(struct dw_hdmi *hdmi,
647 unsigned char bit) 656 unsigned char bit)
648{ 657{
649 hdmi_writeb(hdmi, bit, HDMI_PHY_TST1); 658 hdmi_writeb(hdmi, bit, HDMI_PHY_TST1);
650} 659}
651 660
652static inline void hdmi_phy_test_dout(struct imx_hdmi *hdmi, 661static inline void hdmi_phy_test_dout(struct dw_hdmi *hdmi,
653 unsigned char bit) 662 unsigned char bit)
654{ 663{
655 hdmi_writeb(hdmi, bit, HDMI_PHY_TST2); 664 hdmi_writeb(hdmi, bit, HDMI_PHY_TST2);
656} 665}
657 666
658static bool hdmi_phy_wait_i2c_done(struct imx_hdmi *hdmi, int msec) 667static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
659{ 668{
660 while ((hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3) == 0) { 669 u32 val;
670
671 while ((val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3) == 0) {
661 if (msec-- == 0) 672 if (msec-- == 0)
662 return false; 673 return false;
663 udelay(1000); 674 udelay(1000);
664 } 675 }
676 hdmi_writeb(hdmi, val, HDMI_IH_I2CMPHY_STAT0);
677
665 return true; 678 return true;
666} 679}
667 680
668static void __hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data, 681static void __hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
669 unsigned char addr) 682 unsigned char addr)
670{ 683{
671 hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0); 684 hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0);
672 hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR); 685 hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
673 hdmi_writeb(hdmi, (unsigned char)(data >> 8), 686 hdmi_writeb(hdmi, (unsigned char)(data >> 8),
674 HDMI_PHY_I2CM_DATAO_1_ADDR); 687 HDMI_PHY_I2CM_DATAO_1_ADDR);
675 hdmi_writeb(hdmi, (unsigned char)(data >> 0), 688 hdmi_writeb(hdmi, (unsigned char)(data >> 0),
676 HDMI_PHY_I2CM_DATAO_0_ADDR); 689 HDMI_PHY_I2CM_DATAO_0_ADDR);
677 hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE, 690 hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
678 HDMI_PHY_I2CM_OPERATION_ADDR); 691 HDMI_PHY_I2CM_OPERATION_ADDR);
679 hdmi_phy_wait_i2c_done(hdmi, 1000); 692 hdmi_phy_wait_i2c_done(hdmi, 1000);
680} 693}
681 694
682static int hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data, 695static int hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
683 unsigned char addr) 696 unsigned char addr)
684{ 697{
685 __hdmi_phy_i2c_write(hdmi, data, addr); 698 __hdmi_phy_i2c_write(hdmi, data, addr);
686 return 0; 699 return 0;
687} 700}
688 701
689static void imx_hdmi_phy_enable_power(struct imx_hdmi *hdmi, u8 enable) 702static void dw_hdmi_phy_enable_power(struct dw_hdmi *hdmi, u8 enable)
690{ 703{
691 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 704 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
692 HDMI_PHY_CONF0_PDZ_OFFSET, 705 HDMI_PHY_CONF0_PDZ_OFFSET,
693 HDMI_PHY_CONF0_PDZ_MASK); 706 HDMI_PHY_CONF0_PDZ_MASK);
694} 707}
695 708
696static void imx_hdmi_phy_enable_tmds(struct imx_hdmi *hdmi, u8 enable) 709static void dw_hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, u8 enable)
697{ 710{
698 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 711 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
699 HDMI_PHY_CONF0_ENTMDS_OFFSET, 712 HDMI_PHY_CONF0_ENTMDS_OFFSET,
700 HDMI_PHY_CONF0_ENTMDS_MASK); 713 HDMI_PHY_CONF0_ENTMDS_MASK);
701} 714}
702 715
703static void imx_hdmi_phy_gen2_pddq(struct imx_hdmi *hdmi, u8 enable) 716static void dw_hdmi_phy_enable_spare(struct dw_hdmi *hdmi, u8 enable)
717{
718 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
719 HDMI_PHY_CONF0_SPARECTRL_OFFSET,
720 HDMI_PHY_CONF0_SPARECTRL_MASK);
721}
722
723static void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable)
704{ 724{
705 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 725 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
706 HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET, 726 HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET,
707 HDMI_PHY_CONF0_GEN2_PDDQ_MASK); 727 HDMI_PHY_CONF0_GEN2_PDDQ_MASK);
708} 728}
709 729
710static void imx_hdmi_phy_gen2_txpwron(struct imx_hdmi *hdmi, u8 enable) 730static void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable)
711{ 731{
712 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 732 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
713 HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET, 733 HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET,
714 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK); 734 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK);
715} 735}
716 736
717static void imx_hdmi_phy_sel_data_en_pol(struct imx_hdmi *hdmi, u8 enable) 737static void dw_hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, u8 enable)
718{ 738{
719 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 739 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
720 HDMI_PHY_CONF0_SELDATAENPOL_OFFSET, 740 HDMI_PHY_CONF0_SELDATAENPOL_OFFSET,
721 HDMI_PHY_CONF0_SELDATAENPOL_MASK); 741 HDMI_PHY_CONF0_SELDATAENPOL_MASK);
722} 742}
723 743
724static void imx_hdmi_phy_sel_interface_control(struct imx_hdmi *hdmi, u8 enable) 744static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
725{ 745{
726 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 746 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
727 HDMI_PHY_CONF0_SELDIPIF_OFFSET, 747 HDMI_PHY_CONF0_SELDIPIF_OFFSET,
728 HDMI_PHY_CONF0_SELDIPIF_MASK); 748 HDMI_PHY_CONF0_SELDIPIF_MASK);
729} 749}
730 750
731enum { 751static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
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) 752 unsigned char res, int cscon)
798{ 753{
799 unsigned res_idx, i; 754 unsigned res_idx, i;
800 u8 val, msec; 755 u8 val, msec;
756 const struct dw_hdmi_mpll_config *mpll_config =
757 hdmi->plat_data->mpll_cfg;
758 const struct dw_hdmi_curr_ctrl *curr_ctrl = hdmi->plat_data->cur_ctr;
759 const struct dw_hdmi_sym_term *sym_term = hdmi->plat_data->sym_term;
801 760
802 if (prep) 761 if (prep)
803 return -EINVAL; 762 return -EINVAL;
@@ -805,13 +764,13 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
805 switch (res) { 764 switch (res) {
806 case 0: /* color resolution 0 is 8 bit colour depth */ 765 case 0: /* color resolution 0 is 8 bit colour depth */
807 case 8: 766 case 8:
808 res_idx = RES_8; 767 res_idx = DW_HDMI_RES_8;
809 break; 768 break;
810 case 10: 769 case 10:
811 res_idx = RES_10; 770 res_idx = DW_HDMI_RES_10;
812 break; 771 break;
813 case 12: 772 case 12:
814 res_idx = RES_12; 773 res_idx = DW_HDMI_RES_12;
815 break; 774 break;
816 default: 775 default:
817 return -EINVAL; 776 return -EINVAL;
@@ -826,10 +785,10 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
826 hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL); 785 hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL);
827 786
828 /* gen2 tx power off */ 787 /* gen2 tx power off */
829 imx_hdmi_phy_gen2_txpwron(hdmi, 0); 788 dw_hdmi_phy_gen2_txpwron(hdmi, 0);
830 789
831 /* gen2 pddq */ 790 /* gen2 pddq */
832 imx_hdmi_phy_gen2_pddq(hdmi, 1); 791 dw_hdmi_phy_gen2_pddq(hdmi, 1);
833 792
834 /* PHY reset */ 793 /* PHY reset */
835 hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ); 794 hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
@@ -839,11 +798,11 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
839 798
840 hdmi_phy_test_clear(hdmi, 1); 799 hdmi_phy_test_clear(hdmi, 1);
841 hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2, 800 hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
842 HDMI_PHY_I2CM_SLAVE_ADDR); 801 HDMI_PHY_I2CM_SLAVE_ADDR);
843 hdmi_phy_test_clear(hdmi, 0); 802 hdmi_phy_test_clear(hdmi, 0);
844 803
845 /* PLL/MPLL Cfg - always match on final entry */ 804 /* PLL/MPLL Cfg - always match on final entry */
846 for (i = 0; i < ARRAY_SIZE(mpll_config) - 1; i++) 805 for (i = 0; mpll_config[i].mpixelclock != (~0UL); i++)
847 if (hdmi->hdmi_data.video_mode.mpixelclock <= 806 if (hdmi->hdmi_data.video_mode.mpixelclock <=
848 mpll_config[i].mpixelclock) 807 mpll_config[i].mpixelclock)
849 break; 808 break;
@@ -851,15 +810,14 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
851 hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06); 810 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); 811 hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
853 812
854 for (i = 0; i < ARRAY_SIZE(curr_ctrl); i++) 813 for (i = 0; curr_ctrl[i].mpixelclock != (~0UL); i++)
855 if (hdmi->hdmi_data.video_mode.mpixelclock <= 814 if (hdmi->hdmi_data.video_mode.mpixelclock <=
856 curr_ctrl[i].mpixelclock) 815 curr_ctrl[i].mpixelclock)
857 break; 816 break;
858 817
859 if (i >= ARRAY_SIZE(curr_ctrl)) { 818 if (curr_ctrl[i].mpixelclock == (~0UL)) {
860 dev_err(hdmi->dev, 819 dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
861 "Pixel clock %d - unsupported by HDMI\n", 820 hdmi->hdmi_data.video_mode.mpixelclock);
862 hdmi->hdmi_data.video_mode.mpixelclock);
863 return -EINVAL; 821 return -EINVAL;
864 } 822 }
865 823
@@ -868,24 +826,34 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
868 826
869 hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */ 827 hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
870 hdmi_phy_i2c_write(hdmi, 0x0006, 0x17); 828 hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
829
830 for (i = 0; sym_term[i].mpixelclock != (~0UL); i++)
831 if (hdmi->hdmi_data.video_mode.mpixelclock <=
832 sym_term[i].mpixelclock)
833 break;
834
871 /* RESISTANCE TERM 133Ohm Cfg */ 835 /* RESISTANCE TERM 133Ohm Cfg */
872 hdmi_phy_i2c_write(hdmi, 0x0005, 0x19); /* TXTERM */ 836 hdmi_phy_i2c_write(hdmi, sym_term[i].term, 0x19); /* TXTERM */
873 /* PREEMP Cgf 0.00 */ 837 /* PREEMP Cgf 0.00 */
874 hdmi_phy_i2c_write(hdmi, 0x800d, 0x09); /* CKSYMTXCTRL */ 838 hdmi_phy_i2c_write(hdmi, sym_term[i].sym_ctr, 0x09); /* CKSYMTXCTRL */
839
875 /* TX/CK LVL 10 */ 840 /* TX/CK LVL 10 */
876 hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E); /* VLEVCTRL */ 841 hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E); /* VLEVCTRL */
877 /* REMOVE CLK TERM */ 842 /* REMOVE CLK TERM */
878 hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */ 843 hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */
879 844
880 imx_hdmi_phy_enable_power(hdmi, 1); 845 dw_hdmi_phy_enable_power(hdmi, 1);
881 846
882 /* toggle TMDS enable */ 847 /* toggle TMDS enable */
883 imx_hdmi_phy_enable_tmds(hdmi, 0); 848 dw_hdmi_phy_enable_tmds(hdmi, 0);
884 imx_hdmi_phy_enable_tmds(hdmi, 1); 849 dw_hdmi_phy_enable_tmds(hdmi, 1);
885 850
886 /* gen2 tx power on */ 851 /* gen2 tx power on */
887 imx_hdmi_phy_gen2_txpwron(hdmi, 1); 852 dw_hdmi_phy_gen2_txpwron(hdmi, 1);
888 imx_hdmi_phy_gen2_pddq(hdmi, 0); 853 dw_hdmi_phy_gen2_pddq(hdmi, 0);
854
855 if (hdmi->dev_type == RK3288_HDMI)
856 dw_hdmi_phy_enable_spare(hdmi, 1);
889 857
890 /*Wait for PHY PLL lock */ 858 /*Wait for PHY PLL lock */
891 msec = 5; 859 msec = 5;
@@ -906,7 +874,7 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
906 return 0; 874 return 0;
907} 875}
908 876
909static int imx_hdmi_phy_init(struct imx_hdmi *hdmi) 877static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
910{ 878{
911 int i, ret; 879 int i, ret;
912 bool cscon = false; 880 bool cscon = false;
@@ -917,10 +885,10 @@ static int imx_hdmi_phy_init(struct imx_hdmi *hdmi)
917 885
918 /* HDMI Phy spec says to do the phy initialization sequence twice */ 886 /* HDMI Phy spec says to do the phy initialization sequence twice */
919 for (i = 0; i < 2; i++) { 887 for (i = 0; i < 2; i++) {
920 imx_hdmi_phy_sel_data_en_pol(hdmi, 1); 888 dw_hdmi_phy_sel_data_en_pol(hdmi, 1);
921 imx_hdmi_phy_sel_interface_control(hdmi, 0); 889 dw_hdmi_phy_sel_interface_control(hdmi, 0);
922 imx_hdmi_phy_enable_tmds(hdmi, 0); 890 dw_hdmi_phy_enable_tmds(hdmi, 0);
923 imx_hdmi_phy_enable_power(hdmi, 0); 891 dw_hdmi_phy_enable_power(hdmi, 0);
924 892
925 /* Enable CSC */ 893 /* Enable CSC */
926 ret = hdmi_phy_configure(hdmi, 0, 8, cscon); 894 ret = hdmi_phy_configure(hdmi, 0, 8, cscon);
@@ -932,7 +900,7 @@ static int imx_hdmi_phy_init(struct imx_hdmi *hdmi)
932 return 0; 900 return 0;
933} 901}
934 902
935static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi) 903static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
936{ 904{
937 u8 de; 905 u8 de;
938 906
@@ -951,7 +919,7 @@ static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi)
951 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1); 919 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
952} 920}
953 921
954static void hdmi_config_AVI(struct imx_hdmi *hdmi) 922static void hdmi_config_AVI(struct dw_hdmi *hdmi)
955{ 923{
956 u8 val, pix_fmt, under_scan; 924 u8 val, pix_fmt, under_scan;
957 u8 act_ratio, coded_ratio, colorimetry, ext_colorimetry; 925 u8 act_ratio, coded_ratio, colorimetry, ext_colorimetry;
@@ -1045,7 +1013,7 @@ static void hdmi_config_AVI(struct imx_hdmi *hdmi)
1045 hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB1); 1013 hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB1);
1046} 1014}
1047 1015
1048static void hdmi_av_composer(struct imx_hdmi *hdmi, 1016static void hdmi_av_composer(struct dw_hdmi *hdmi,
1049 const struct drm_display_mode *mode) 1017 const struct drm_display_mode *mode)
1050{ 1018{
1051 u8 inv_val; 1019 u8 inv_val;
@@ -1129,19 +1097,19 @@ static void hdmi_av_composer(struct imx_hdmi *hdmi,
1129 hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH); 1097 hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH);
1130} 1098}
1131 1099
1132static void imx_hdmi_phy_disable(struct imx_hdmi *hdmi) 1100static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
1133{ 1101{
1134 if (!hdmi->phy_enabled) 1102 if (!hdmi->phy_enabled)
1135 return; 1103 return;
1136 1104
1137 imx_hdmi_phy_enable_tmds(hdmi, 0); 1105 dw_hdmi_phy_enable_tmds(hdmi, 0);
1138 imx_hdmi_phy_enable_power(hdmi, 0); 1106 dw_hdmi_phy_enable_power(hdmi, 0);
1139 1107
1140 hdmi->phy_enabled = false; 1108 hdmi->phy_enabled = false;
1141} 1109}
1142 1110
1143/* HDMI Initialization Step B.4 */ 1111/* HDMI Initialization Step B.4 */
1144static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi) 1112static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
1145{ 1113{
1146 u8 clkdis; 1114 u8 clkdis;
1147 1115
@@ -1170,13 +1138,13 @@ static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi)
1170 } 1138 }
1171} 1139}
1172 1140
1173static void hdmi_enable_audio_clk(struct imx_hdmi *hdmi) 1141static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi)
1174{ 1142{
1175 hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS); 1143 hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
1176} 1144}
1177 1145
1178/* Workaround to clear the overflow condition */ 1146/* Workaround to clear the overflow condition */
1179static void imx_hdmi_clear_overflow(struct imx_hdmi *hdmi) 1147static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
1180{ 1148{
1181 int count; 1149 int count;
1182 u8 val; 1150 u8 val;
@@ -1194,19 +1162,19 @@ static void imx_hdmi_clear_overflow(struct imx_hdmi *hdmi)
1194 hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF); 1162 hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
1195} 1163}
1196 1164
1197static void hdmi_enable_overflow_interrupts(struct imx_hdmi *hdmi) 1165static void hdmi_enable_overflow_interrupts(struct dw_hdmi *hdmi)
1198{ 1166{
1199 hdmi_writeb(hdmi, 0, HDMI_FC_MASK2); 1167 hdmi_writeb(hdmi, 0, HDMI_FC_MASK2);
1200 hdmi_writeb(hdmi, 0, HDMI_IH_MUTE_FC_STAT2); 1168 hdmi_writeb(hdmi, 0, HDMI_IH_MUTE_FC_STAT2);
1201} 1169}
1202 1170
1203static void hdmi_disable_overflow_interrupts(struct imx_hdmi *hdmi) 1171static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi)
1204{ 1172{
1205 hdmi_writeb(hdmi, HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK, 1173 hdmi_writeb(hdmi, HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK,
1206 HDMI_IH_MUTE_FC_STAT2); 1174 HDMI_IH_MUTE_FC_STAT2);
1207} 1175}
1208 1176
1209static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct drm_display_mode *mode) 1177static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
1210{ 1178{
1211 int ret; 1179 int ret;
1212 1180
@@ -1223,21 +1191,21 @@ static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct drm_display_mode *mode)
1223 } 1191 }
1224 1192
1225 if ((hdmi->vic == 6) || (hdmi->vic == 7) || 1193 if ((hdmi->vic == 6) || (hdmi->vic == 7) ||
1226 (hdmi->vic == 21) || (hdmi->vic == 22) || 1194 (hdmi->vic == 21) || (hdmi->vic == 22) ||
1227 (hdmi->vic == 2) || (hdmi->vic == 3) || 1195 (hdmi->vic == 2) || (hdmi->vic == 3) ||
1228 (hdmi->vic == 17) || (hdmi->vic == 18)) 1196 (hdmi->vic == 17) || (hdmi->vic == 18))
1229 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601; 1197 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
1230 else 1198 else
1231 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709; 1199 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
1232 1200
1233 if ((hdmi->vic == 10) || (hdmi->vic == 11) || 1201 if ((hdmi->vic == 10) || (hdmi->vic == 11) ||
1234 (hdmi->vic == 12) || (hdmi->vic == 13) || 1202 (hdmi->vic == 12) || (hdmi->vic == 13) ||
1235 (hdmi->vic == 14) || (hdmi->vic == 15) || 1203 (hdmi->vic == 14) || (hdmi->vic == 15) ||
1236 (hdmi->vic == 25) || (hdmi->vic == 26) || 1204 (hdmi->vic == 25) || (hdmi->vic == 26) ||
1237 (hdmi->vic == 27) || (hdmi->vic == 28) || 1205 (hdmi->vic == 27) || (hdmi->vic == 28) ||
1238 (hdmi->vic == 29) || (hdmi->vic == 30) || 1206 (hdmi->vic == 29) || (hdmi->vic == 30) ||
1239 (hdmi->vic == 35) || (hdmi->vic == 36) || 1207 (hdmi->vic == 35) || (hdmi->vic == 36) ||
1240 (hdmi->vic == 37) || (hdmi->vic == 38)) 1208 (hdmi->vic == 37) || (hdmi->vic == 38))
1241 hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 1; 1209 hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 1;
1242 else 1210 else
1243 hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; 1211 hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
@@ -1258,17 +1226,17 @@ static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct drm_display_mode *mode)
1258 hdmi_av_composer(hdmi, mode); 1226 hdmi_av_composer(hdmi, mode);
1259 1227
1260 /* HDMI Initializateion Step B.2 */ 1228 /* HDMI Initializateion Step B.2 */
1261 ret = imx_hdmi_phy_init(hdmi); 1229 ret = dw_hdmi_phy_init(hdmi);
1262 if (ret) 1230 if (ret)
1263 return ret; 1231 return ret;
1264 1232
1265 /* HDMI Initialization Step B.3 */ 1233 /* HDMI Initialization Step B.3 */
1266 imx_hdmi_enable_video_path(hdmi); 1234 dw_hdmi_enable_video_path(hdmi);
1267 1235
1268 /* not for DVI mode */ 1236 /* not for DVI mode */
1269 if (hdmi->hdmi_data.video_mode.mdvi) 1237 if (hdmi->hdmi_data.video_mode.mdvi) {
1270 dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); 1238 dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
1271 else { 1239 } else {
1272 dev_dbg(hdmi->dev, "%s CEA mode\n", __func__); 1240 dev_dbg(hdmi->dev, "%s CEA mode\n", __func__);
1273 1241
1274 /* HDMI Initialization Step E - Configure audio */ 1242 /* HDMI Initialization Step E - Configure audio */
@@ -1284,7 +1252,7 @@ static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct drm_display_mode *mode)
1284 hdmi_video_sample(hdmi); 1252 hdmi_video_sample(hdmi);
1285 hdmi_tx_hdcp_config(hdmi); 1253 hdmi_tx_hdcp_config(hdmi);
1286 1254
1287 imx_hdmi_clear_overflow(hdmi); 1255 dw_hdmi_clear_overflow(hdmi);
1288 if (hdmi->cable_plugin && !hdmi->hdmi_data.video_mode.mdvi) 1256 if (hdmi->cable_plugin && !hdmi->hdmi_data.video_mode.mdvi)
1289 hdmi_enable_overflow_interrupts(hdmi); 1257 hdmi_enable_overflow_interrupts(hdmi);
1290 1258
@@ -1292,7 +1260,7 @@ static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct drm_display_mode *mode)
1292} 1260}
1293 1261
1294/* Wait until we are registered to enable interrupts */ 1262/* Wait until we are registered to enable interrupts */
1295static int imx_hdmi_fb_registered(struct imx_hdmi *hdmi) 1263static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
1296{ 1264{
1297 hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL, 1265 hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
1298 HDMI_PHY_I2CM_INT_ADDR); 1266 HDMI_PHY_I2CM_INT_ADDR);
@@ -1310,7 +1278,7 @@ static int imx_hdmi_fb_registered(struct imx_hdmi *hdmi)
1310 return 0; 1278 return 0;
1311} 1279}
1312 1280
1313static void initialize_hdmi_ih_mutes(struct imx_hdmi *hdmi) 1281static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)
1314{ 1282{
1315 u8 ih_mute; 1283 u8 ih_mute;
1316 1284
@@ -1362,29 +1330,73 @@ static void initialize_hdmi_ih_mutes(struct imx_hdmi *hdmi)
1362 hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE); 1330 hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
1363} 1331}
1364 1332
1365static void imx_hdmi_poweron(struct imx_hdmi *hdmi) 1333static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
1334{
1335 dw_hdmi_setup(hdmi, &hdmi->previous_mode);
1336}
1337
1338static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
1339{
1340 dw_hdmi_phy_disable(hdmi);
1341}
1342
1343static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
1344 struct drm_display_mode *orig_mode,
1345 struct drm_display_mode *mode)
1346{
1347 struct dw_hdmi *hdmi = bridge->driver_private;
1348
1349 dw_hdmi_setup(hdmi, mode);
1350
1351 /* Store the display mode for plugin/DKMS poweron events */
1352 memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
1353}
1354
1355static bool dw_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,
1356 const struct drm_display_mode *mode,
1357 struct drm_display_mode *adjusted_mode)
1358{
1359 return true;
1360}
1361
1362static void dw_hdmi_bridge_disable(struct drm_bridge *bridge)
1366{ 1363{
1367 imx_hdmi_setup(hdmi, &hdmi->previous_mode); 1364 struct dw_hdmi *hdmi = bridge->driver_private;
1365
1366 dw_hdmi_poweroff(hdmi);
1367}
1368
1369static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
1370{
1371 struct dw_hdmi *hdmi = bridge->driver_private;
1372
1373 dw_hdmi_poweron(hdmi);
1368} 1374}
1369 1375
1370static void imx_hdmi_poweroff(struct imx_hdmi *hdmi) 1376static void dw_hdmi_bridge_destroy(struct drm_bridge *bridge)
1371{ 1377{
1372 imx_hdmi_phy_disable(hdmi); 1378 drm_bridge_cleanup(bridge);
1379 kfree(bridge);
1373} 1380}
1374 1381
1375static enum drm_connector_status imx_hdmi_connector_detect(struct drm_connector 1382static void dw_hdmi_bridge_nop(struct drm_bridge *bridge)
1376 *connector, bool force)
1377{ 1383{
1378 struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi, 1384 /* do nothing */
1385}
1386
1387static enum drm_connector_status
1388dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
1389{
1390 struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
1379 connector); 1391 connector);
1380 1392
1381 return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ? 1393 return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
1382 connector_status_connected : connector_status_disconnected; 1394 connector_status_connected : connector_status_disconnected;
1383} 1395}
1384 1396
1385static int imx_hdmi_connector_get_modes(struct drm_connector *connector) 1397static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
1386{ 1398{
1387 struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi, 1399 struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
1388 connector); 1400 connector);
1389 struct edid *edid; 1401 struct edid *edid;
1390 int ret; 1402 int ret;
@@ -1407,94 +1419,61 @@ static int imx_hdmi_connector_get_modes(struct drm_connector *connector)
1407 return 0; 1419 return 0;
1408} 1420}
1409 1421
1410static struct drm_encoder *imx_hdmi_connector_best_encoder(struct drm_connector 1422static enum drm_mode_status
1411 *connector) 1423dw_hdmi_connector_mode_valid(struct drm_connector *connector,
1412{ 1424 struct drm_display_mode *mode)
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{ 1425{
1423 struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder); 1426 struct dw_hdmi *hdmi = container_of(connector,
1427 struct dw_hdmi, connector);
1428 enum drm_mode_status mode_status = MODE_OK;
1424 1429
1425 imx_hdmi_setup(hdmi, mode); 1430 if (hdmi->plat_data->mode_valid)
1431 mode_status = hdmi->plat_data->mode_valid(connector, mode);
1426 1432
1427 /* Store the display mode for plugin/DKMS poweron events */ 1433 return mode_status;
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} 1434}
1451 1435
1452static void imx_hdmi_encoder_prepare(struct drm_encoder *encoder) 1436static struct drm_encoder *dw_hdmi_connector_best_encoder(struct drm_connector
1437 *connector)
1453{ 1438{
1454 struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder); 1439 struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
1440 connector);
1455 1441
1456 imx_hdmi_poweroff(hdmi); 1442 return hdmi->encoder;
1457 imx_drm_panel_format(encoder, V4L2_PIX_FMT_RGB24);
1458} 1443}
1459 1444
1460static void imx_hdmi_encoder_commit(struct drm_encoder *encoder) 1445static void dw_hdmi_connector_destroy(struct drm_connector *connector)
1461{ 1446{
1462 struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder); 1447 drm_connector_unregister(connector);
1463 int mux = imx_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder); 1448 drm_connector_cleanup(connector);
1464
1465 imx_hdmi_set_ipu_di_mux(hdmi, mux);
1466
1467 imx_hdmi_poweron(hdmi);
1468} 1449}
1469 1450
1470static struct drm_encoder_funcs imx_hdmi_encoder_funcs = { 1451static struct drm_connector_funcs dw_hdmi_connector_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, 1452 .dpms = drm_helper_connector_dpms,
1485 .fill_modes = drm_helper_probe_single_connector_modes, 1453 .fill_modes = drm_helper_probe_single_connector_modes,
1486 .detect = imx_hdmi_connector_detect, 1454 .detect = dw_hdmi_connector_detect,
1487 .destroy = imx_drm_connector_destroy, 1455 .destroy = dw_hdmi_connector_destroy,
1456};
1457
1458static struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
1459 .get_modes = dw_hdmi_connector_get_modes,
1460 .mode_valid = dw_hdmi_connector_mode_valid,
1461 .best_encoder = dw_hdmi_connector_best_encoder,
1488}; 1462};
1489 1463
1490static struct drm_connector_helper_funcs imx_hdmi_connector_helper_funcs = { 1464struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
1491 .get_modes = imx_hdmi_connector_get_modes, 1465 .enable = dw_hdmi_bridge_enable,
1492 .best_encoder = imx_hdmi_connector_best_encoder, 1466 .disable = dw_hdmi_bridge_disable,
1467 .pre_enable = dw_hdmi_bridge_nop,
1468 .post_disable = dw_hdmi_bridge_nop,
1469 .mode_set = dw_hdmi_bridge_mode_set,
1470 .mode_fixup = dw_hdmi_bridge_mode_fixup,
1471 .destroy = dw_hdmi_bridge_destroy,
1493}; 1472};
1494 1473
1495static irqreturn_t imx_hdmi_hardirq(int irq, void *dev_id) 1474static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
1496{ 1475{
1497 struct imx_hdmi *hdmi = dev_id; 1476 struct dw_hdmi *hdmi = dev_id;
1498 u8 intr_stat; 1477 u8 intr_stat;
1499 1478
1500 intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0); 1479 intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
@@ -1504,9 +1483,9 @@ static irqreturn_t imx_hdmi_hardirq(int irq, void *dev_id)
1504 return intr_stat ? IRQ_WAKE_THREAD : IRQ_NONE; 1483 return intr_stat ? IRQ_WAKE_THREAD : IRQ_NONE;
1505} 1484}
1506 1485
1507static irqreturn_t imx_hdmi_irq(int irq, void *dev_id) 1486static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
1508{ 1487{
1509 struct imx_hdmi *hdmi = dev_id; 1488 struct dw_hdmi *hdmi = dev_id;
1510 u8 intr_stat; 1489 u8 intr_stat;
1511 u8 phy_int_pol; 1490 u8 phy_int_pol;
1512 1491
@@ -1520,14 +1499,14 @@ static irqreturn_t imx_hdmi_irq(int irq, void *dev_id)
1520 1499
1521 hdmi_modb(hdmi, 0, HDMI_PHY_HPD, HDMI_PHY_POL0); 1500 hdmi_modb(hdmi, 0, HDMI_PHY_HPD, HDMI_PHY_POL0);
1522 1501
1523 imx_hdmi_poweron(hdmi); 1502 dw_hdmi_poweron(hdmi);
1524 } else { 1503 } else {
1525 dev_dbg(hdmi->dev, "EVENT=plugout\n"); 1504 dev_dbg(hdmi->dev, "EVENT=plugout\n");
1526 1505
1527 hdmi_modb(hdmi, HDMI_PHY_HPD, HDMI_PHY_HPD, 1506 hdmi_modb(hdmi, HDMI_PHY_HPD, HDMI_PHY_HPD,
1528 HDMI_PHY_POL0); 1507 HDMI_PHY_POL0);
1529 1508
1530 imx_hdmi_poweroff(hdmi); 1509 dw_hdmi_poweroff(hdmi);
1531 } 1510 }
1532 drm_helper_hpd_irq_event(hdmi->connector.dev); 1511 drm_helper_hpd_irq_event(hdmi->connector.dev);
1533 } 1512 }
@@ -1538,147 +1517,140 @@ static irqreturn_t imx_hdmi_irq(int irq, void *dev_id)
1538 return IRQ_HANDLED; 1517 return IRQ_HANDLED;
1539} 1518}
1540 1519
1541static int imx_hdmi_register(struct drm_device *drm, struct imx_hdmi *hdmi) 1520static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
1542{ 1521{
1522 struct drm_encoder *encoder = hdmi->encoder;
1523 struct drm_bridge *bridge;
1543 int ret; 1524 int ret;
1544 1525
1545 ret = imx_drm_encoder_parse_of(drm, &hdmi->encoder, 1526 bridge = devm_kzalloc(drm->dev, sizeof(*bridge), GFP_KERNEL);
1546 hdmi->dev->of_node); 1527 if (!bridge) {
1547 if (ret) 1528 DRM_ERROR("Failed to allocate drm bridge\n");
1548 return ret; 1529 return -ENOMEM;
1530 }
1549 1531
1550 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD; 1532 hdmi->bridge = bridge;
1533 bridge->driver_private = hdmi;
1551 1534
1552 drm_encoder_helper_add(&hdmi->encoder, &imx_hdmi_encoder_helper_funcs); 1535 ret = drm_bridge_init(drm, bridge, &dw_hdmi_bridge_funcs);
1553 drm_encoder_init(drm, &hdmi->encoder, &imx_hdmi_encoder_funcs, 1536 if (ret) {
1554 DRM_MODE_ENCODER_TMDS); 1537 DRM_ERROR("Failed to initialize bridge with drm\n");
1538 return -EINVAL;
1539 }
1540
1541 encoder->bridge = bridge;
1542 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
1555 1543
1556 drm_connector_helper_add(&hdmi->connector, 1544 drm_connector_helper_add(&hdmi->connector,
1557 &imx_hdmi_connector_helper_funcs); 1545 &dw_hdmi_connector_helper_funcs);
1558 drm_connector_init(drm, &hdmi->connector, &imx_hdmi_connector_funcs, 1546 drm_connector_init(drm, &hdmi->connector, &dw_hdmi_connector_funcs,
1559 DRM_MODE_CONNECTOR_HDMIA); 1547 DRM_MODE_CONNECTOR_HDMIA);
1560 1548
1561 hdmi->connector.encoder = &hdmi->encoder; 1549 hdmi->connector.encoder = encoder;
1562 1550
1563 drm_mode_connector_attach_encoder(&hdmi->connector, &hdmi->encoder); 1551 drm_mode_connector_attach_encoder(&hdmi->connector, encoder);
1564 1552
1565 return 0; 1553 return 0;
1566} 1554}
1567 1555
1568static struct platform_device_id imx_hdmi_devtype[] = { 1556int dw_hdmi_bind(struct device *dev, struct device *master,
1569 { 1557 void *data, struct drm_encoder *encoder,
1570 .name = "imx6q-hdmi", 1558 struct resource *iores, int irq,
1571 .driver_data = IMX6Q_HDMI, 1559 const struct dw_hdmi_plat_data *plat_data)
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{ 1560{
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; 1561 struct drm_device *drm = data;
1592 struct device_node *np = dev->of_node; 1562 struct device_node *np = dev->of_node;
1593 struct device_node *ddc_node; 1563 struct device_node *ddc_node;
1594 struct imx_hdmi *hdmi; 1564 struct dw_hdmi *hdmi;
1595 struct resource *iores; 1565 int ret;
1596 int ret, irq; 1566 u32 val = 1;
1597 1567
1598 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); 1568 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
1599 if (!hdmi) 1569 if (!hdmi)
1600 return -ENOMEM; 1570 return -ENOMEM;
1601 1571
1572 hdmi->plat_data = plat_data;
1602 hdmi->dev = dev; 1573 hdmi->dev = dev;
1574 hdmi->dev_type = plat_data->dev_type;
1603 hdmi->sample_rate = 48000; 1575 hdmi->sample_rate = 48000;
1604 hdmi->ratio = 100; 1576 hdmi->ratio = 100;
1577 hdmi->encoder = encoder;
1605 1578
1606 if (of_id) { 1579 of_property_read_u32(np, "reg-io-width", &val);
1607 const struct platform_device_id *device_id = of_id->data;
1608 1580
1609 hdmi->dev_type = device_id->driver_data; 1581 switch (val) {
1582 case 4:
1583 hdmi->write = dw_hdmi_writel;
1584 hdmi->read = dw_hdmi_readl;
1585 break;
1586 case 1:
1587 hdmi->write = dw_hdmi_writeb;
1588 hdmi->read = dw_hdmi_readb;
1589 break;
1590 default:
1591 dev_err(dev, "reg-io-width must be 1 or 4\n");
1592 return -EINVAL;
1610 } 1593 }
1611 1594
1612 ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); 1595 ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
1613 if (ddc_node) { 1596 if (ddc_node) {
1614 hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node); 1597 hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
1615 if (!hdmi->ddc) 1598 of_node_put(ddc_node);
1599 if (!hdmi->ddc) {
1616 dev_dbg(hdmi->dev, "failed to read ddc node\n"); 1600 dev_dbg(hdmi->dev, "failed to read ddc node\n");
1601 return -EPROBE_DEFER;
1602 }
1617 1603
1618 of_node_put(ddc_node);
1619 } else { 1604 } else {
1620 dev_dbg(hdmi->dev, "no ddc property found\n"); 1605 dev_dbg(hdmi->dev, "no ddc property found\n");
1621 } 1606 }
1622 1607
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); 1608 hdmi->regs = devm_ioremap_resource(dev, iores);
1635 if (IS_ERR(hdmi->regs)) 1609 if (IS_ERR(hdmi->regs))
1636 return PTR_ERR(hdmi->regs); 1610 return PTR_ERR(hdmi->regs);
1637 1611
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"); 1612 hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
1643 if (IS_ERR(hdmi->isfr_clk)) { 1613 if (IS_ERR(hdmi->isfr_clk)) {
1644 ret = PTR_ERR(hdmi->isfr_clk); 1614 ret = PTR_ERR(hdmi->isfr_clk);
1645 dev_err(hdmi->dev, 1615 dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret);
1646 "Unable to get HDMI isfr clk: %d\n", ret);
1647 return ret; 1616 return ret;
1648 } 1617 }
1649 1618
1650 ret = clk_prepare_enable(hdmi->isfr_clk); 1619 ret = clk_prepare_enable(hdmi->isfr_clk);
1651 if (ret) { 1620 if (ret) {
1652 dev_err(hdmi->dev, 1621 dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret);
1653 "Cannot enable HDMI isfr clock: %d\n", ret);
1654 return ret; 1622 return ret;
1655 } 1623 }
1656 1624
1657 hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb"); 1625 hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb");
1658 if (IS_ERR(hdmi->iahb_clk)) { 1626 if (IS_ERR(hdmi->iahb_clk)) {
1659 ret = PTR_ERR(hdmi->iahb_clk); 1627 ret = PTR_ERR(hdmi->iahb_clk);
1660 dev_err(hdmi->dev, 1628 dev_err(hdmi->dev, "Unable to get HDMI iahb clk: %d\n", ret);
1661 "Unable to get HDMI iahb clk: %d\n", ret);
1662 goto err_isfr; 1629 goto err_isfr;
1663 } 1630 }
1664 1631
1665 ret = clk_prepare_enable(hdmi->iahb_clk); 1632 ret = clk_prepare_enable(hdmi->iahb_clk);
1666 if (ret) { 1633 if (ret) {
1667 dev_err(hdmi->dev, 1634 dev_err(hdmi->dev, "Cannot enable HDMI iahb clock: %d\n", ret);
1668 "Cannot enable HDMI iahb clock: %d\n", ret);
1669 goto err_isfr; 1635 goto err_isfr;
1670 } 1636 }
1671 1637
1672 /* Product and revision IDs */ 1638 /* Product and revision IDs */
1673 dev_info(dev, 1639 dev_info(dev,
1674 "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n", 1640 "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n",
1675 hdmi_readb(hdmi, HDMI_DESIGN_ID), 1641 hdmi_readb(hdmi, HDMI_DESIGN_ID),
1676 hdmi_readb(hdmi, HDMI_REVISION_ID), 1642 hdmi_readb(hdmi, HDMI_REVISION_ID),
1677 hdmi_readb(hdmi, HDMI_PRODUCT_ID0), 1643 hdmi_readb(hdmi, HDMI_PRODUCT_ID0),
1678 hdmi_readb(hdmi, HDMI_PRODUCT_ID1)); 1644 hdmi_readb(hdmi, HDMI_PRODUCT_ID1));
1679 1645
1680 initialize_hdmi_ih_mutes(hdmi); 1646 initialize_hdmi_ih_mutes(hdmi);
1681 1647
1648 ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
1649 dw_hdmi_irq, IRQF_SHARED,
1650 dev_name(dev), hdmi);
1651 if (ret)
1652 return ret;
1653
1682 /* 1654 /*
1683 * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator 1655 * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
1684 * N and cts values before enabling phy 1656 * N and cts values before enabling phy
@@ -1694,11 +1666,11 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data)
1694 /* Clear Hotplug interrupts */ 1666 /* Clear Hotplug interrupts */
1695 hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0); 1667 hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
1696 1668
1697 ret = imx_hdmi_fb_registered(hdmi); 1669 ret = dw_hdmi_fb_registered(hdmi);
1698 if (ret) 1670 if (ret)
1699 goto err_iahb; 1671 goto err_iahb;
1700 1672
1701 ret = imx_hdmi_register(drm, hdmi); 1673 ret = dw_hdmi_register(drm, hdmi);
1702 if (ret) 1674 if (ret)
1703 goto err_iahb; 1675 goto err_iahb;
1704 1676
@@ -1716,51 +1688,27 @@ err_isfr:
1716 1688
1717 return ret; 1689 return ret;
1718} 1690}
1691EXPORT_SYMBOL_GPL(dw_hdmi_bind);
1719 1692
1720static void imx_hdmi_unbind(struct device *dev, struct device *master, 1693void dw_hdmi_unbind(struct device *dev, struct device *master, void *data)
1721 void *data)
1722{ 1694{
1723 struct imx_hdmi *hdmi = dev_get_drvdata(dev); 1695 struct dw_hdmi *hdmi = dev_get_drvdata(dev);
1724 1696
1725 /* Disable all interrupts */ 1697 /* Disable all interrupts */
1726 hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0); 1698 hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
1727 1699
1728 hdmi->connector.funcs->destroy(&hdmi->connector); 1700 hdmi->connector.funcs->destroy(&hdmi->connector);
1729 hdmi->encoder.funcs->destroy(&hdmi->encoder); 1701 hdmi->encoder->funcs->destroy(hdmi->encoder);
1730 1702
1731 clk_disable_unprepare(hdmi->iahb_clk); 1703 clk_disable_unprepare(hdmi->iahb_clk);
1732 clk_disable_unprepare(hdmi->isfr_clk); 1704 clk_disable_unprepare(hdmi->isfr_clk);
1733 i2c_put_adapter(hdmi->ddc); 1705 i2c_put_adapter(hdmi->ddc);
1734} 1706}
1735 1707EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
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 1708
1763MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); 1709MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
1764MODULE_DESCRIPTION("i.MX6 HDMI transmitter driver"); 1710MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
1711MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
1712MODULE_DESCRIPTION("DW HDMI transmitter driver");
1765MODULE_LICENSE("GPL"); 1713MODULE_LICENSE("GPL");
1766MODULE_ALIAS("platform:imx-hdmi"); 1714MODULE_ALIAS("platform:dw-hdmi");
diff --git a/drivers/gpu/drm/imx/imx-hdmi.h b/drivers/gpu/drm/bridge/dw_hdmi.h
index 39b677689db6..175dbc89a824 100644
--- a/drivers/gpu/drm/imx/imx-hdmi.h
+++ b/drivers/gpu/drm/bridge/dw_hdmi.h
@@ -837,7 +837,8 @@ enum {
837 HDMI_PHY_CONF0_PDZ_OFFSET = 7, 837 HDMI_PHY_CONF0_PDZ_OFFSET = 7,
838 HDMI_PHY_CONF0_ENTMDS_MASK = 0x40, 838 HDMI_PHY_CONF0_ENTMDS_MASK = 0x40,
839 HDMI_PHY_CONF0_ENTMDS_OFFSET = 6, 839 HDMI_PHY_CONF0_ENTMDS_OFFSET = 6,
840 HDMI_PHY_CONF0_SPARECTRL = 0x20, 840 HDMI_PHY_CONF0_SPARECTRL_MASK = 0x20,
841 HDMI_PHY_CONF0_SPARECTRL_OFFSET = 5,
841 HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10, 842 HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10,
842 HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4, 843 HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4,
843 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8, 844 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8,
@@ -1029,4 +1030,5 @@ enum {
1029 HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2, 1030 HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2,
1030 HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0, 1031 HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0,
1031}; 1032};
1033
1032#endif /* __IMX_HDMI_H__ */ 1034#endif /* __IMX_HDMI_H__ */
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 5125aa91e66f..20d977a52c58 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -615,6 +615,46 @@ void drm_display_mode_from_videomode(const struct videomode *vm,
615} 615}
616EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode); 616EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
617 617
618/**
619 * drm_display_mode_to_videomode - fill in @vm using @dmode,
620 * @dmode: drm_display_mode structure to use as source
621 * @vm: videomode structure to use as destination
622 *
623 * Fills out @vm using the display mode specified in @dmode.
624 */
625void drm_display_mode_to_videomode(const struct drm_display_mode *dmode,
626 struct videomode *vm)
627{
628 vm->hactive = dmode->hdisplay;
629 vm->hfront_porch = dmode->hsync_start - dmode->hdisplay;
630 vm->hsync_len = dmode->hsync_end - dmode->hsync_start;
631 vm->hback_porch = dmode->htotal - dmode->hsync_end;
632
633 vm->vactive = dmode->vdisplay;
634 vm->vfront_porch = dmode->vsync_start - dmode->vdisplay;
635 vm->vsync_len = dmode->vsync_end - dmode->vsync_start;
636 vm->vback_porch = dmode->vtotal - dmode->vsync_end;
637
638 vm->pixelclock = dmode->clock * 1000;
639
640 vm->flags = 0;
641 if (dmode->flags & DRM_MODE_FLAG_PHSYNC)
642 vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
643 else if (dmode->flags & DRM_MODE_FLAG_NHSYNC)
644 vm->flags |= DISPLAY_FLAGS_HSYNC_LOW;
645 if (dmode->flags & DRM_MODE_FLAG_PVSYNC)
646 vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
647 else if (dmode->flags & DRM_MODE_FLAG_NVSYNC)
648 vm->flags |= DISPLAY_FLAGS_VSYNC_LOW;
649 if (dmode->flags & DRM_MODE_FLAG_INTERLACE)
650 vm->flags |= DISPLAY_FLAGS_INTERLACED;
651 if (dmode->flags & DRM_MODE_FLAG_DBLSCAN)
652 vm->flags |= DISPLAY_FLAGS_DOUBLESCAN;
653 if (dmode->flags & DRM_MODE_FLAG_DBLCLK)
654 vm->flags |= DISPLAY_FLAGS_DOUBLECLK;
655}
656EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode);
657
618#ifdef CONFIG_OF 658#ifdef CONFIG_OF
619/** 659/**
620 * of_get_drm_display_mode - get a drm_display_mode from devicetree 660 * of_get_drm_display_mode - get a drm_display_mode from devicetree
diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig
index ab31848e92cf..5d5e4092d40a 100644
--- a/drivers/gpu/drm/imx/Kconfig
+++ b/drivers/gpu/drm/imx/Kconfig
@@ -49,6 +49,7 @@ config DRM_IMX_IPUV3
49 49
50config DRM_IMX_HDMI 50config DRM_IMX_HDMI
51 tristate "Freescale i.MX DRM HDMI" 51 tristate "Freescale i.MX DRM HDMI"
52 select DRM_DW_HDMI
52 depends on DRM_IMX 53 depends on DRM_IMX
53 help 54 help
54 Choose this if you want to use HDMI on i.MX6. 55 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
index 582c438d8cbd..f3ecd8903d97 100644
--- a/drivers/gpu/drm/imx/Makefile
+++ b/drivers/gpu/drm/imx/Makefile
@@ -9,4 +9,4 @@ obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
9 9
10imx-ipuv3-crtc-objs := ipuv3-crtc.o ipuv3-plane.o 10imx-ipuv3-crtc-objs := ipuv3-crtc.o ipuv3-plane.o
11obj-$(CONFIG_DRM_IMX_IPUV3) += imx-ipuv3-crtc.o 11obj-$(CONFIG_DRM_IMX_IPUV3) += imx-ipuv3-crtc.o
12obj-$(CONFIG_DRM_IMX_HDMI) += imx-hdmi.o 12obj-$(CONFIG_DRM_IMX_HDMI) += dw_hdmi-imx.o
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
new file mode 100644
index 000000000000..121d30ca2d44
--- /dev/null
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -0,0 +1,258 @@
1/* Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
2 *
3 * derived from imx-hdmi.c(renamed to bridge/dw_hdmi.c now)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9#include <linux/module.h>
10#include <linux/platform_device.h>
11#include <linux/component.h>
12#include <linux/mfd/syscon.h>
13#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
14#include <drm/bridge/dw_hdmi.h>
15#include <video/imx-ipu-v3.h>
16#include <linux/regmap.h>
17#include <drm/drm_of.h>
18#include <drm/drmP.h>
19#include <drm/drm_crtc_helper.h>
20#include <drm/drm_edid.h>
21#include <drm/drm_encoder_slave.h>
22
23#include "imx-drm.h"
24
25struct imx_hdmi {
26 struct device *dev;
27 struct drm_encoder encoder;
28 struct regmap *regmap;
29};
30
31static const struct dw_hdmi_mpll_config imx_mpll_cfg[] = {
32 {
33 45250000, {
34 { 0x01e0, 0x0000 },
35 { 0x21e1, 0x0000 },
36 { 0x41e2, 0x0000 }
37 },
38 }, {
39 92500000, {
40 { 0x0140, 0x0005 },
41 { 0x2141, 0x0005 },
42 { 0x4142, 0x0005 },
43 },
44 }, {
45 148500000, {
46 { 0x00a0, 0x000a },
47 { 0x20a1, 0x000a },
48 { 0x40a2, 0x000a },
49 },
50 }, {
51 ~0UL, {
52 { 0x00a0, 0x000a },
53 { 0x2001, 0x000f },
54 { 0x4002, 0x000f },
55 },
56 }
57};
58
59static const struct dw_hdmi_curr_ctrl imx_cur_ctr[] = {
60 /* pixelclk bpp8 bpp10 bpp12 */
61 {
62 54000000, { 0x091c, 0x091c, 0x06dc },
63 }, {
64 58400000, { 0x091c, 0x06dc, 0x06dc },
65 }, {
66 72000000, { 0x06dc, 0x06dc, 0x091c },
67 }, {
68 74250000, { 0x06dc, 0x0b5c, 0x091c },
69 }, {
70 118800000, { 0x091c, 0x091c, 0x06dc },
71 }, {
72 216000000, { 0x06dc, 0x0b5c, 0x091c },
73 }
74};
75
76static const struct dw_hdmi_sym_term imx_sym_term[] = {
77 /*pixelclk symbol term*/
78 { 148500000, 0x800d, 0x0005 },
79 { ~0UL, 0x0000, 0x0000 }
80};
81
82static int dw_hdmi_imx_parse_dt(struct imx_hdmi *hdmi)
83{
84 struct device_node *np = hdmi->dev->of_node;
85
86 hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
87 if (IS_ERR(hdmi->regmap)) {
88 dev_err(hdmi->dev, "Unable to get gpr\n");
89 return PTR_ERR(hdmi->regmap);
90 }
91
92 return 0;
93}
94
95static void dw_hdmi_imx_encoder_disable(struct drm_encoder *encoder)
96{
97}
98
99static bool dw_hdmi_imx_encoder_mode_fixup(struct drm_encoder *encoder,
100 const struct drm_display_mode *mode,
101 struct drm_display_mode *adj_mode)
102{
103 return true;
104}
105
106static void dw_hdmi_imx_encoder_mode_set(struct drm_encoder *encoder,
107 struct drm_display_mode *mode,
108 struct drm_display_mode *adj_mode)
109{
110}
111
112static void dw_hdmi_imx_encoder_commit(struct drm_encoder *encoder)
113{
114 struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
115 int mux = imx_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);
116
117 regmap_update_bits(hdmi->regmap, IOMUXC_GPR3,
118 IMX6Q_GPR3_HDMI_MUX_CTL_MASK,
119 mux << IMX6Q_GPR3_HDMI_MUX_CTL_SHIFT);
120}
121
122static void dw_hdmi_imx_encoder_prepare(struct drm_encoder *encoder)
123{
124 imx_drm_panel_format(encoder, V4L2_PIX_FMT_RGB24);
125}
126
127static struct drm_encoder_helper_funcs dw_hdmi_imx_encoder_helper_funcs = {
128 .mode_fixup = dw_hdmi_imx_encoder_mode_fixup,
129 .mode_set = dw_hdmi_imx_encoder_mode_set,
130 .prepare = dw_hdmi_imx_encoder_prepare,
131 .commit = dw_hdmi_imx_encoder_commit,
132 .disable = dw_hdmi_imx_encoder_disable,
133};
134
135static struct drm_encoder_funcs dw_hdmi_imx_encoder_funcs = {
136 .destroy = drm_encoder_cleanup,
137};
138
139static struct dw_hdmi_plat_data imx6q_hdmi_drv_data = {
140 .mpll_cfg = imx_mpll_cfg,
141 .cur_ctr = imx_cur_ctr,
142 .sym_term = imx_sym_term,
143 .dev_type = IMX6Q_HDMI,
144};
145
146static struct dw_hdmi_plat_data imx6dl_hdmi_drv_data = {
147 .mpll_cfg = imx_mpll_cfg,
148 .cur_ctr = imx_cur_ctr,
149 .sym_term = imx_sym_term,
150 .dev_type = IMX6DL_HDMI,
151};
152
153static const struct of_device_id dw_hdmi_imx_dt_ids[] = {
154 { .compatible = "fsl,imx6q-hdmi",
155 .data = &imx6q_hdmi_drv_data
156 }, {
157 .compatible = "fsl,imx6dl-hdmi",
158 .data = &imx6dl_hdmi_drv_data
159 },
160 {},
161};
162MODULE_DEVICE_TABLE(of, dw_hdmi_imx_dt_ids);
163
164static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
165 void *data)
166{
167 struct platform_device *pdev = to_platform_device(dev);
168 const struct dw_hdmi_plat_data *plat_data;
169 const struct of_device_id *match;
170 struct drm_device *drm = data;
171 struct drm_encoder *encoder;
172 struct imx_hdmi *hdmi;
173 struct resource *iores;
174 int irq;
175 int ret;
176
177 if (!pdev->dev.of_node)
178 return -ENODEV;
179
180 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
181 if (!hdmi)
182 return -ENOMEM;
183
184 match = of_match_node(dw_hdmi_imx_dt_ids, pdev->dev.of_node);
185 plat_data = match->data;
186 hdmi->dev = &pdev->dev;
187 encoder = &hdmi->encoder;
188
189 irq = platform_get_irq(pdev, 0);
190 if (irq < 0)
191 return irq;
192
193 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
194 if (!iores)
195 return -ENXIO;
196
197 platform_set_drvdata(pdev, hdmi);
198
199 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
200 /*
201 * If we failed to find the CRTC(s) which this encoder is
202 * supposed to be connected to, it's because the CRTC has
203 * not been registered yet. Defer probing, and hope that
204 * the required CRTC is added later.
205 */
206 if (encoder->possible_crtcs == 0)
207 return -EPROBE_DEFER;
208
209 ret = dw_hdmi_imx_parse_dt(hdmi);
210 if (ret < 0)
211 return ret;
212
213 drm_encoder_helper_add(encoder, &dw_hdmi_imx_encoder_helper_funcs);
214 drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs,
215 DRM_MODE_ENCODER_TMDS);
216
217 return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
218}
219
220static void dw_hdmi_imx_unbind(struct device *dev, struct device *master,
221 void *data)
222{
223 return dw_hdmi_unbind(dev, master, data);
224}
225
226static const struct component_ops dw_hdmi_imx_ops = {
227 .bind = dw_hdmi_imx_bind,
228 .unbind = dw_hdmi_imx_unbind,
229};
230
231static int dw_hdmi_imx_probe(struct platform_device *pdev)
232{
233 return component_add(&pdev->dev, &dw_hdmi_imx_ops);
234}
235
236static int dw_hdmi_imx_remove(struct platform_device *pdev)
237{
238 component_del(&pdev->dev, &dw_hdmi_imx_ops);
239
240 return 0;
241}
242
243static struct platform_driver dw_hdmi_imx_platform_driver = {
244 .probe = dw_hdmi_imx_probe,
245 .remove = dw_hdmi_imx_remove,
246 .driver = {
247 .name = "dwhdmi-imx",
248 .of_match_table = dw_hdmi_imx_dt_ids,
249 },
250};
251
252module_platform_driver(dw_hdmi_imx_platform_driver);
253
254MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
255MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
256MODULE_DESCRIPTION("IMX6 Specific DW-HDMI Driver Extension");
257MODULE_LICENSE("GPL");
258MODULE_ALIAS("platform:dwhdmi-imx");
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index b250130debc8..a002f53aab0e 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -25,6 +25,7 @@
25#include <drm/drm_gem_cma_helper.h> 25#include <drm/drm_gem_cma_helper.h>
26#include <drm/drm_fb_cma_helper.h> 26#include <drm/drm_fb_cma_helper.h>
27#include <drm/drm_plane_helper.h> 27#include <drm/drm_plane_helper.h>
28#include <drm/drm_of.h>
28 29
29#include "imx-drm.h" 30#include "imx-drm.h"
30 31
@@ -46,7 +47,6 @@ struct imx_drm_crtc {
46 struct drm_crtc *crtc; 47 struct drm_crtc *crtc;
47 int pipe; 48 int pipe;
48 struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs; 49 struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs;
49 struct device_node *port;
50}; 50};
51 51
52static int legacyfb_depth = 16; 52static int legacyfb_depth = 16;
@@ -116,8 +116,7 @@ int imx_drm_panel_format_pins(struct drm_encoder *encoder,
116 helper = &imx_crtc->imx_drm_helper_funcs; 116 helper = &imx_crtc->imx_drm_helper_funcs;
117 if (helper->set_interface_pix_fmt) 117 if (helper->set_interface_pix_fmt)
118 return helper->set_interface_pix_fmt(encoder->crtc, 118 return helper->set_interface_pix_fmt(encoder->crtc,
119 encoder->encoder_type, interface_pix_fmt, 119 interface_pix_fmt, hsync_pin, vsync_pin);
120 hsync_pin, vsync_pin);
121 return 0; 120 return 0;
122} 121}
123EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins); 122EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);
@@ -365,9 +364,10 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
365 364
366 imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs; 365 imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs;
367 imx_drm_crtc->pipe = imxdrm->pipes++; 366 imx_drm_crtc->pipe = imxdrm->pipes++;
368 imx_drm_crtc->port = port;
369 imx_drm_crtc->crtc = crtc; 367 imx_drm_crtc->crtc = crtc;
370 368
369 crtc->port = port;
370
371 imxdrm->crtc[imx_drm_crtc->pipe] = imx_drm_crtc; 371 imxdrm->crtc[imx_drm_crtc->pipe] = imx_drm_crtc;
372 372
373 *new_crtc = imx_drm_crtc; 373 *new_crtc = imx_drm_crtc;
@@ -408,33 +408,28 @@ int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc)
408} 408}
409EXPORT_SYMBOL_GPL(imx_drm_remove_crtc); 409EXPORT_SYMBOL_GPL(imx_drm_remove_crtc);
410 410
411/* 411int imx_drm_encoder_parse_of(struct drm_device *drm,
412 * Find the DRM CRTC possible mask for the connected endpoint. 412 struct drm_encoder *encoder, struct device_node *np)
413 *
414 * The encoder possible masks are defined by their position in the
415 * mode_config crtc_list. This means that CRTCs must not be added
416 * or removed once the DRM device has been fully initialised.
417 */
418static uint32_t imx_drm_find_crtc_mask(struct imx_drm_device *imxdrm,
419 struct device_node *endpoint)
420{ 413{
421 struct device_node *port; 414 uint32_t crtc_mask = drm_of_find_possible_crtcs(drm, np);
422 unsigned i;
423 415
424 port = of_graph_get_remote_port(endpoint); 416 /*
425 if (!port) 417 * If we failed to find the CRTC(s) which this encoder is
426 return 0; 418 * supposed to be connected to, it's because the CRTC has
427 of_node_put(port); 419 * not been registered yet. Defer probing, and hope that
420 * the required CRTC is added later.
421 */
422 if (crtc_mask == 0)
423 return -EPROBE_DEFER;
428 424
429 for (i = 0; i < MAX_CRTC; i++) { 425 encoder->possible_crtcs = crtc_mask;
430 struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[i];
431 426
432 if (imx_drm_crtc && imx_drm_crtc->port == port) 427 /* FIXME: this is the mask of outputs which can clone this output. */
433 return drm_crtc_mask(imx_drm_crtc->crtc); 428 encoder->possible_clones = ~0;
434 }
435 429
436 return 0; 430 return 0;
437} 431}
432EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of);
438 433
439static struct device_node *imx_drm_of_get_next_endpoint( 434static struct device_node *imx_drm_of_get_next_endpoint(
440 const struct device_node *parent, struct device_node *prev) 435 const struct device_node *parent, struct device_node *prev)
@@ -445,48 +440,6 @@ static struct device_node *imx_drm_of_get_next_endpoint(
445 return node; 440 return node;
446} 441}
447 442
448int imx_drm_encoder_parse_of(struct drm_device *drm,
449 struct drm_encoder *encoder, struct device_node *np)
450{
451 struct imx_drm_device *imxdrm = drm->dev_private;
452 struct device_node *ep = NULL;
453 uint32_t crtc_mask = 0;
454 int i;
455
456 for (i = 0; ; i++) {
457 u32 mask;
458
459 ep = imx_drm_of_get_next_endpoint(np, ep);
460 if (!ep)
461 break;
462
463 mask = imx_drm_find_crtc_mask(imxdrm, ep);
464
465 /*
466 * If we failed to find the CRTC(s) which this encoder is
467 * supposed to be connected to, it's because the CRTC has
468 * not been registered yet. Defer probing, and hope that
469 * the required CRTC is added later.
470 */
471 if (mask == 0)
472 return -EPROBE_DEFER;
473
474 crtc_mask |= mask;
475 }
476
477 of_node_put(ep);
478 if (i == 0)
479 return -ENOENT;
480
481 encoder->possible_crtcs = crtc_mask;
482
483 /* FIXME: this is the mask of outputs which can clone this output. */
484 encoder->possible_clones = ~0;
485
486 return 0;
487}
488EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of);
489
490/* 443/*
491 * @node: device tree node containing encoder input ports 444 * @node: device tree node containing encoder input ports
492 * @encoder: drm_encoder 445 * @encoder: drm_encoder
@@ -510,7 +463,7 @@ int imx_drm_encoder_get_mux_id(struct device_node *node,
510 463
511 port = of_graph_get_remote_port(ep); 464 port = of_graph_get_remote_port(ep);
512 of_node_put(port); 465 of_node_put(port);
513 if (port == imx_crtc->port) { 466 if (port == imx_crtc->crtc->port) {
514 ret = of_graph_parse_endpoint(ep, &endpoint); 467 ret = of_graph_parse_endpoint(ep, &endpoint);
515 return ret ? ret : endpoint.port; 468 return ret ? ret : endpoint.port;
516 } 469 }
diff --git a/drivers/gpu/drm/imx/imx-drm.h b/drivers/gpu/drm/imx/imx-drm.h
index 7453ae00c412..3c559ccd6af0 100644
--- a/drivers/gpu/drm/imx/imx-drm.h
+++ b/drivers/gpu/drm/imx/imx-drm.h
@@ -17,7 +17,7 @@ int imx_drm_crtc_id(struct imx_drm_crtc *crtc);
17struct imx_drm_crtc_helper_funcs { 17struct imx_drm_crtc_helper_funcs {
18 int (*enable_vblank)(struct drm_crtc *crtc); 18 int (*enable_vblank)(struct drm_crtc *crtc);
19 void (*disable_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, 20 int (*set_interface_pix_fmt)(struct drm_crtc *crtc,
21 u32 pix_fmt, int hsync_pin, int vsync_pin); 21 u32 pix_fmt, int hsync_pin, int vsync_pin);
22 const struct drm_crtc_helper_funcs *crtc_helper_funcs; 22 const struct drm_crtc_helper_funcs *crtc_helper_funcs;
23 const struct drm_crtc_funcs *crtc_funcs; 23 const struct drm_crtc_funcs *crtc_funcs;
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index c60460043e24..1b86aac0b341 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -163,7 +163,7 @@ static void imx_ldb_encoder_prepare(struct drm_encoder *encoder)
163{ 163{
164 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); 164 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
165 struct imx_ldb *ldb = imx_ldb_ch->ldb; 165 struct imx_ldb *ldb = imx_ldb_ch->ldb;
166 struct drm_display_mode *mode = &encoder->crtc->mode; 166 struct drm_display_mode *mode = &encoder->crtc->hwmode;
167 u32 pixel_fmt; 167 u32 pixel_fmt;
168 unsigned long serial_clk; 168 unsigned long serial_clk;
169 unsigned long di_clk = mode->clock * 1000; 169 unsigned long di_clk = mode->clock * 1000;
@@ -241,8 +241,8 @@ static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
241} 241}
242 242
243static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder, 243static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
244 struct drm_display_mode *mode, 244 struct drm_display_mode *orig_mode,
245 struct drm_display_mode *adjusted_mode) 245 struct drm_display_mode *mode)
246{ 246{
247 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); 247 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
248 struct imx_ldb *ldb = imx_ldb_ch->ldb; 248 struct imx_ldb *ldb = imx_ldb_ch->ldb;
@@ -574,6 +574,8 @@ static void imx_ldb_unbind(struct device *dev, struct device *master,
574 574
575 channel->connector.funcs->destroy(&channel->connector); 575 channel->connector.funcs->destroy(&channel->connector);
576 channel->encoder.funcs->destroy(&channel->encoder); 576 channel->encoder.funcs->destroy(&channel->encoder);
577
578 kfree(channel->edid);
577 } 579 }
578} 580}
579 581
diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
index a729f4f7074c..b63601d04601 100644
--- a/drivers/gpu/drm/imx/imx-tve.c
+++ b/drivers/gpu/drm/imx/imx-tve.c
@@ -307,8 +307,8 @@ static void imx_tve_encoder_prepare(struct drm_encoder *encoder)
307} 307}
308 308
309static void imx_tve_encoder_mode_set(struct drm_encoder *encoder, 309static void imx_tve_encoder_mode_set(struct drm_encoder *encoder,
310 struct drm_display_mode *mode, 310 struct drm_display_mode *orig_mode,
311 struct drm_display_mode *adjusted_mode) 311 struct drm_display_mode *mode)
312{ 312{
313 struct imx_tve *tve = enc_to_tve(encoder); 313 struct imx_tve *tve = enc_to_tve(encoder);
314 unsigned long rounded_rate; 314 unsigned long rounded_rate;
diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
index ebee59cb96d8..98551e356e12 100644
--- a/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -46,7 +46,6 @@ struct ipu_crtc {
46 struct drm_framebuffer *newfb; 46 struct drm_framebuffer *newfb;
47 int irq; 47 int irq;
48 u32 interface_pix_fmt; 48 u32 interface_pix_fmt;
49 unsigned long di_clkflags;
50 int di_hsync_pin; 49 int di_hsync_pin;
51 int di_vsync_pin; 50 int di_vsync_pin;
52}; 51};
@@ -141,47 +140,51 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
141 int x, int y, 140 int x, int y,
142 struct drm_framebuffer *old_fb) 141 struct drm_framebuffer *old_fb)
143{ 142{
143 struct drm_device *dev = crtc->dev;
144 struct drm_encoder *encoder;
144 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 145 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
145 int ret;
146 struct ipu_di_signal_cfg sig_cfg = {}; 146 struct ipu_di_signal_cfg sig_cfg = {};
147 unsigned long encoder_types = 0;
147 u32 out_pixel_fmt; 148 u32 out_pixel_fmt;
149 int ret;
148 150
149 dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__, 151 dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
150 mode->hdisplay); 152 mode->hdisplay);
151 dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__, 153 dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__,
152 mode->vdisplay); 154 mode->vdisplay);
153 155
154 out_pixel_fmt = ipu_crtc->interface_pix_fmt; 156 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
157 if (encoder->crtc == crtc)
158 encoder_types |= BIT(encoder->encoder_type);
155 159
156 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 160 dev_dbg(ipu_crtc->dev, "%s: attached to encoder types 0x%lx\n",
157 sig_cfg.interlaced = 1; 161 __func__, encoder_types);
158 if (mode->flags & DRM_MODE_FLAG_PHSYNC) 162
159 sig_cfg.Hsync_pol = 1; 163 /*
160 if (mode->flags & DRM_MODE_FLAG_PVSYNC) 164 * If we have DAC, TVDAC or LDB, then we need the IPU DI clock
161 sig_cfg.Vsync_pol = 1; 165 * to be the same as the LDB DI clock.
166 */
167 if (encoder_types & (BIT(DRM_MODE_ENCODER_DAC) |
168 BIT(DRM_MODE_ENCODER_TVDAC) |
169 BIT(DRM_MODE_ENCODER_LVDS)))
170 sig_cfg.clkflags = IPU_DI_CLKMODE_SYNC | IPU_DI_CLKMODE_EXT;
171 else
172 sig_cfg.clkflags = 0;
173
174 out_pixel_fmt = ipu_crtc->interface_pix_fmt;
162 175
163 sig_cfg.enable_pol = 1; 176 sig_cfg.enable_pol = 1;
164 sig_cfg.clk_pol = 0; 177 sig_cfg.clk_pol = 0;
165 sig_cfg.width = mode->hdisplay;
166 sig_cfg.height = mode->vdisplay;
167 sig_cfg.pixel_fmt = out_pixel_fmt; 178 sig_cfg.pixel_fmt = out_pixel_fmt;
168 sig_cfg.h_start_width = mode->htotal - mode->hsync_end;
169 sig_cfg.h_sync_width = mode->hsync_end - mode->hsync_start;
170 sig_cfg.h_end_width = mode->hsync_start - mode->hdisplay;
171
172 sig_cfg.v_start_width = mode->vtotal - mode->vsync_end;
173 sig_cfg.v_sync_width = mode->vsync_end - mode->vsync_start;
174 sig_cfg.v_end_width = mode->vsync_start - mode->vdisplay;
175 sig_cfg.pixelclock = mode->clock * 1000;
176 sig_cfg.clkflags = ipu_crtc->di_clkflags;
177
178 sig_cfg.v_to_h_sync = 0; 179 sig_cfg.v_to_h_sync = 0;
179
180 sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin; 180 sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin;
181 sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin; 181 sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin;
182 182
183 ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, sig_cfg.interlaced, 183 drm_display_mode_to_videomode(mode, &sig_cfg.mode);
184 out_pixel_fmt, mode->hdisplay); 184
185 ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di,
186 mode->flags & DRM_MODE_FLAG_INTERLACE,
187 out_pixel_fmt, mode->hdisplay);
185 if (ret) { 188 if (ret) {
186 dev_err(ipu_crtc->dev, 189 dev_err(ipu_crtc->dev,
187 "initializing display controller failed with %d\n", 190 "initializing display controller failed with %d\n",
@@ -237,6 +240,18 @@ static bool ipu_crtc_mode_fixup(struct drm_crtc *crtc,
237 const struct drm_display_mode *mode, 240 const struct drm_display_mode *mode,
238 struct drm_display_mode *adjusted_mode) 241 struct drm_display_mode *adjusted_mode)
239{ 242{
243 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
244 struct videomode vm;
245 int ret;
246
247 drm_display_mode_to_videomode(adjusted_mode, &vm);
248
249 ret = ipu_di_adjust_videomode(ipu_crtc->di, &vm);
250 if (ret)
251 return false;
252
253 drm_display_mode_from_videomode(&vm, adjusted_mode);
254
240 return true; 255 return true;
241} 256}
242 257
@@ -275,7 +290,7 @@ static void ipu_disable_vblank(struct drm_crtc *crtc)
275 ipu_crtc->newfb = NULL; 290 ipu_crtc->newfb = NULL;
276} 291}
277 292
278static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type, 293static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc,
279 u32 pixfmt, int hsync_pin, int vsync_pin) 294 u32 pixfmt, int hsync_pin, int vsync_pin)
280{ 295{
281 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 296 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
@@ -284,19 +299,6 @@ static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
284 ipu_crtc->di_hsync_pin = hsync_pin; 299 ipu_crtc->di_hsync_pin = hsync_pin;
285 ipu_crtc->di_vsync_pin = vsync_pin; 300 ipu_crtc->di_vsync_pin = vsync_pin;
286 301
287 switch (encoder_type) {
288 case DRM_MODE_ENCODER_DAC:
289 case DRM_MODE_ENCODER_TVDAC:
290 case DRM_MODE_ENCODER_LVDS:
291 ipu_crtc->di_clkflags = IPU_DI_CLKMODE_SYNC |
292 IPU_DI_CLKMODE_EXT;
293 break;
294 case DRM_MODE_ENCODER_TMDS:
295 case DRM_MODE_ENCODER_NONE:
296 ipu_crtc->di_clkflags = 0;
297 break;
298 }
299
300 return 0; 302 return 0;
301} 303}
302 304
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index 796c3c1c170a..5e83e007080f 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -130,8 +130,8 @@ static void imx_pd_encoder_commit(struct drm_encoder *encoder)
130} 130}
131 131
132static void imx_pd_encoder_mode_set(struct drm_encoder *encoder, 132static void imx_pd_encoder_mode_set(struct drm_encoder *encoder,
133 struct drm_display_mode *mode, 133 struct drm_display_mode *orig_mode,
134 struct drm_display_mode *adjusted_mode) 134 struct drm_display_mode *mode)
135{ 135{
136} 136}
137 137
@@ -257,6 +257,8 @@ static void imx_pd_unbind(struct device *dev, struct device *master,
257 257
258 imxpd->encoder.funcs->destroy(&imxpd->encoder); 258 imxpd->encoder.funcs->destroy(&imxpd->encoder);
259 imxpd->connector.funcs->destroy(&imxpd->connector); 259 imxpd->connector.funcs->destroy(&imxpd->connector);
260
261 kfree(imxpd->edid);
260} 262}
261 263
262static const struct component_ops imx_pd_ops = { 264static const struct component_ops imx_pd_ops = {
@@ -272,6 +274,7 @@ static int imx_pd_probe(struct platform_device *pdev)
272static int imx_pd_remove(struct platform_device *pdev) 274static int imx_pd_remove(struct platform_device *pdev)
273{ 275{
274 component_del(&pdev->dev, &imx_pd_ops); 276 component_del(&pdev->dev, &imx_pd_ops);
277
275 return 0; 278 return 0;
276} 279}
277 280
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index ca9f085efa92..0d87bf6ddd96 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -15,3 +15,13 @@ config DRM_ROCKCHIP
15 management to userspace. This driver does not provide 15 management to userspace. This driver does not provide
16 2D or 3D acceleration; acceleration is performed by other 16 2D or 3D acceleration; acceleration is performed by other
17 IP found on the SoC. 17 IP found on the SoC.
18
19config ROCKCHIP_DW_HDMI
20 tristate "Rockchip specific extensions for Synopsys DW HDMI"
21 depends on DRM_ROCKCHIP
22 select DRM_DW_HDMI
23 help
24 This selects support for Rockchip SoC specific extensions
25 for the Synopsys DesignWare HDMI driver. If you want to
26 enable HDMI on RK3288 based SoC, you should selet this
27 option.
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index 2cb0672f57ed..f3d8a19c641f 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -5,4 +5,6 @@
5rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o rockchip_drm_fbdev.o \ 5rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o rockchip_drm_fbdev.o \
6 rockchip_drm_gem.o 6 rockchip_drm_gem.o
7 7
8obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
9
8obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_drm_vop.o 10obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_drm_vop.o
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
new file mode 100644
index 000000000000..d236faa05b19
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -0,0 +1,341 @@
1/*
2 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
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#include <linux/module.h>
11#include <linux/platform_device.h>
12#include <linux/mfd/syscon.h>
13#include <linux/regmap.h>
14#include <drm/drm_of.h>
15#include <drm/drmP.h>
16#include <drm/drm_crtc_helper.h>
17#include <drm/drm_edid.h>
18#include <drm/drm_encoder_slave.h>
19#include <drm/bridge/dw_hdmi.h>
20
21#include "rockchip_drm_drv.h"
22#include "rockchip_drm_vop.h"
23
24#define GRF_SOC_CON6 0x025c
25#define HDMI_SEL_VOP_LIT (1 << 4)
26
27struct rockchip_hdmi {
28 struct device *dev;
29 struct regmap *regmap;
30 struct drm_encoder encoder;
31};
32
33#define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x)
34
35static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = {
36 {
37 27000000, {
38 { 0x00b3, 0x0000},
39 { 0x2153, 0x0000},
40 { 0x40f3, 0x0000}
41 },
42 }, {
43 36000000, {
44 { 0x00b3, 0x0000},
45 { 0x2153, 0x0000},
46 { 0x40f3, 0x0000}
47 },
48 }, {
49 40000000, {
50 { 0x00b3, 0x0000},
51 { 0x2153, 0x0000},
52 { 0x40f3, 0x0000}
53 },
54 }, {
55 54000000, {
56 { 0x0072, 0x0001},
57 { 0x2142, 0x0001},
58 { 0x40a2, 0x0001},
59 },
60 }, {
61 65000000, {
62 { 0x0072, 0x0001},
63 { 0x2142, 0x0001},
64 { 0x40a2, 0x0001},
65 },
66 }, {
67 66000000, {
68 { 0x013e, 0x0003},
69 { 0x217e, 0x0002},
70 { 0x4061, 0x0002}
71 },
72 }, {
73 74250000, {
74 { 0x0072, 0x0001},
75 { 0x2145, 0x0002},
76 { 0x4061, 0x0002}
77 },
78 }, {
79 83500000, {
80 { 0x0072, 0x0001},
81 },
82 }, {
83 108000000, {
84 { 0x0051, 0x0002},
85 { 0x2145, 0x0002},
86 { 0x4061, 0x0002}
87 },
88 }, {
89 106500000, {
90 { 0x0051, 0x0002},
91 { 0x2145, 0x0002},
92 { 0x4061, 0x0002}
93 },
94 }, {
95 146250000, {
96 { 0x0051, 0x0002},
97 { 0x2145, 0x0002},
98 { 0x4061, 0x0002}
99 },
100 }, {
101 148500000, {
102 { 0x0051, 0x0003},
103 { 0x214c, 0x0003},
104 { 0x4064, 0x0003}
105 },
106 }, {
107 ~0UL, {
108 { 0x00a0, 0x000a },
109 { 0x2001, 0x000f },
110 { 0x4002, 0x000f },
111 },
112 }
113};
114
115static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = {
116 /* pixelclk bpp8 bpp10 bpp12 */
117 {
118 40000000, { 0x0018, 0x0018, 0x0018 },
119 }, {
120 65000000, { 0x0028, 0x0028, 0x0028 },
121 }, {
122 66000000, { 0x0038, 0x0038, 0x0038 },
123 }, {
124 74250000, { 0x0028, 0x0038, 0x0038 },
125 }, {
126 83500000, { 0x0028, 0x0038, 0x0038 },
127 }, {
128 146250000, { 0x0038, 0x0038, 0x0038 },
129 }, {
130 148500000, { 0x0000, 0x0038, 0x0038 },
131 }, {
132 ~0UL, { 0x0000, 0x0000, 0x0000},
133 }
134};
135
136static const struct dw_hdmi_sym_term rockchip_sym_term[] = {
137 /*pixelclk symbol term*/
138 { 74250000, 0x8009, 0x0004 },
139 { 148500000, 0x8029, 0x0004 },
140 { 297000000, 0x8039, 0x0005 },
141 { ~0UL, 0x0000, 0x0000 }
142};
143
144static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
145{
146 struct device_node *np = hdmi->dev->of_node;
147
148 hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
149 if (IS_ERR(hdmi->regmap)) {
150 dev_err(hdmi->dev, "Unable to get rockchip,grf\n");
151 return PTR_ERR(hdmi->regmap);
152 }
153
154 return 0;
155}
156
157static enum drm_mode_status
158dw_hdmi_rockchip_mode_valid(struct drm_connector *connector,
159 struct drm_display_mode *mode)
160{
161 const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg;
162 int pclk = mode->clock * 1000;
163 bool valid = false;
164 int i;
165
166 for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) {
167 if (pclk == mpll_cfg[i].mpixelclock) {
168 valid = true;
169 break;
170 }
171 }
172
173 return (valid) ? MODE_OK : MODE_BAD;
174}
175
176static struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = {
177 .destroy = drm_encoder_cleanup,
178};
179
180static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder)
181{
182}
183
184static bool
185dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder,
186 const struct drm_display_mode *mode,
187 struct drm_display_mode *adj_mode)
188{
189 return true;
190}
191
192static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder,
193 struct drm_display_mode *mode,
194 struct drm_display_mode *adj_mode)
195{
196}
197
198static void dw_hdmi_rockchip_encoder_commit(struct drm_encoder *encoder)
199{
200 struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
201 u32 val;
202 int mux;
203
204 mux = rockchip_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);
205 if (mux)
206 val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16);
207 else
208 val = HDMI_SEL_VOP_LIT << 16;
209
210 regmap_write(hdmi->regmap, GRF_SOC_CON6, val);
211 dev_dbg(hdmi->dev, "vop %s output to hdmi\n",
212 (mux) ? "LIT" : "BIG");
213}
214
215static void dw_hdmi_rockchip_encoder_prepare(struct drm_encoder *encoder)
216{
217 rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
218 ROCKCHIP_OUT_MODE_AAAA);
219}
220
221static struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = {
222 .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup,
223 .mode_set = dw_hdmi_rockchip_encoder_mode_set,
224 .prepare = dw_hdmi_rockchip_encoder_prepare,
225 .commit = dw_hdmi_rockchip_encoder_commit,
226 .disable = dw_hdmi_rockchip_encoder_disable,
227};
228
229static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = {
230 .mode_valid = dw_hdmi_rockchip_mode_valid,
231 .mpll_cfg = rockchip_mpll_cfg,
232 .cur_ctr = rockchip_cur_ctr,
233 .sym_term = rockchip_sym_term,
234 .dev_type = RK3288_HDMI,
235};
236
237static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
238 { .compatible = "rockchip,rk3288-dw-hdmi",
239 .data = &rockchip_hdmi_drv_data
240 },
241 {},
242};
243MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids);
244
245static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
246 void *data)
247{
248 struct platform_device *pdev = to_platform_device(dev);
249 const struct dw_hdmi_plat_data *plat_data;
250 const struct of_device_id *match;
251 struct drm_device *drm = data;
252 struct drm_encoder *encoder;
253 struct rockchip_hdmi *hdmi;
254 struct resource *iores;
255 int irq;
256 int ret;
257
258 if (!pdev->dev.of_node)
259 return -ENODEV;
260
261 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
262 if (!hdmi)
263 return -ENOMEM;
264
265 match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node);
266 plat_data = match->data;
267 hdmi->dev = &pdev->dev;
268 encoder = &hdmi->encoder;
269
270 irq = platform_get_irq(pdev, 0);
271 if (irq < 0)
272 return irq;
273
274 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
275 if (!iores)
276 return -ENXIO;
277
278 platform_set_drvdata(pdev, hdmi);
279
280 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
281 /*
282 * If we failed to find the CRTC(s) which this encoder is
283 * supposed to be connected to, it's because the CRTC has
284 * not been registered yet. Defer probing, and hope that
285 * the required CRTC is added later.
286 */
287 if (encoder->possible_crtcs == 0)
288 return -EPROBE_DEFER;
289
290 ret = rockchip_hdmi_parse_dt(hdmi);
291 if (ret) {
292 dev_err(hdmi->dev, "Unable to parse OF data\n");
293 return ret;
294 }
295
296 drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
297 drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
298 DRM_MODE_ENCODER_TMDS);
299
300 return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
301}
302
303static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
304 void *data)
305{
306 return dw_hdmi_unbind(dev, master, data);
307}
308
309static const struct component_ops dw_hdmi_rockchip_ops = {
310 .bind = dw_hdmi_rockchip_bind,
311 .unbind = dw_hdmi_rockchip_unbind,
312};
313
314static int dw_hdmi_rockchip_probe(struct platform_device *pdev)
315{
316 return component_add(&pdev->dev, &dw_hdmi_rockchip_ops);
317}
318
319static int dw_hdmi_rockchip_remove(struct platform_device *pdev)
320{
321 component_del(&pdev->dev, &dw_hdmi_rockchip_ops);
322
323 return 0;
324}
325
326static struct platform_driver dw_hdmi_rockchip_pltfm_driver = {
327 .probe = dw_hdmi_rockchip_probe,
328 .remove = dw_hdmi_rockchip_remove,
329 .driver = {
330 .name = "dwhdmi-rockchip",
331 .of_match_table = dw_hdmi_rockchip_dt_ids,
332 },
333};
334
335module_platform_driver(dw_hdmi_rockchip_pltfm_driver);
336
337MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
338MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
339MODULE_DESCRIPTION("Rockchip Specific DW-HDMI Driver Extension");
340MODULE_LICENSE("GPL");
341MODULE_ALIAS("platform:dwhdmi-rockchip");
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index a798c7c71f91..21a481b224eb 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -390,6 +390,7 @@ int rockchip_drm_encoder_get_mux_id(struct device_node *node,
390 390
391 return -EINVAL; 391 return -EINVAL;
392} 392}
393EXPORT_SYMBOL_GPL(rockchip_drm_encoder_get_mux_id);
393 394
394static int compare_of(struct device *dev, void *data) 395static int compare_of(struct device *dev, void *data)
395{ 396{
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index e7ca25b3fb38..9a5c571b95fc 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -735,6 +735,7 @@ int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc,
735 735
736 return 0; 736 return 0;
737} 737}
738EXPORT_SYMBOL_GPL(rockchip_drm_crtc_mode_config);
738 739
739static int vop_crtc_enable_vblank(struct drm_crtc *crtc) 740static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
740{ 741{
diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c
index 2326c752d89b..323203d0503a 100644
--- a/drivers/gpu/ipu-v3/ipu-dc.c
+++ b/drivers/gpu/ipu-v3/ipu-dc.c
@@ -114,6 +114,7 @@ struct ipu_dc_priv {
114 struct completion comp; 114 struct completion comp;
115 int dc_irq; 115 int dc_irq;
116 int dp_irq; 116 int dp_irq;
117 int use_count;
117}; 118};
118 119
119static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority) 120static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
@@ -232,7 +233,16 @@ EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
232 233
233void ipu_dc_enable(struct ipu_soc *ipu) 234void ipu_dc_enable(struct ipu_soc *ipu)
234{ 235{
235 ipu_module_enable(ipu, IPU_CONF_DC_EN); 236 struct ipu_dc_priv *priv = ipu->dc_priv;
237
238 mutex_lock(&priv->mutex);
239
240 if (!priv->use_count)
241 ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
242
243 priv->use_count++;
244
245 mutex_unlock(&priv->mutex);
236} 246}
237EXPORT_SYMBOL_GPL(ipu_dc_enable); 247EXPORT_SYMBOL_GPL(ipu_dc_enable);
238 248
@@ -294,7 +304,18 @@ EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
294 304
295void ipu_dc_disable(struct ipu_soc *ipu) 305void ipu_dc_disable(struct ipu_soc *ipu)
296{ 306{
297 ipu_module_disable(ipu, IPU_CONF_DC_EN); 307 struct ipu_dc_priv *priv = ipu->dc_priv;
308
309 mutex_lock(&priv->mutex);
310
311 priv->use_count--;
312 if (!priv->use_count)
313 ipu_module_disable(priv->ipu, IPU_CONF_DC_EN);
314
315 if (priv->use_count < 0)
316 priv->use_count = 0;
317
318 mutex_unlock(&priv->mutex);
298} 319}
299EXPORT_SYMBOL_GPL(ipu_dc_disable); 320EXPORT_SYMBOL_GPL(ipu_dc_disable);
300 321
diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
index c490ba4384fc..b61d6be97602 100644
--- a/drivers/gpu/ipu-v3/ipu-di.c
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -207,10 +207,10 @@ static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config,
207static void ipu_di_sync_config_interlaced(struct ipu_di *di, 207static void ipu_di_sync_config_interlaced(struct ipu_di *di,
208 struct ipu_di_signal_cfg *sig) 208 struct ipu_di_signal_cfg *sig)
209{ 209{
210 u32 h_total = sig->width + sig->h_sync_width + 210 u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
211 sig->h_start_width + sig->h_end_width; 211 sig->mode.hback_porch + sig->mode.hfront_porch;
212 u32 v_total = sig->height + sig->v_sync_width + 212 u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
213 sig->v_start_width + sig->v_end_width; 213 sig->mode.vback_porch + sig->mode.vfront_porch;
214 u32 reg; 214 u32 reg;
215 struct di_sync_config cfg[] = { 215 struct di_sync_config cfg[] = {
216 { 216 {
@@ -229,13 +229,13 @@ static void ipu_di_sync_config_interlaced(struct ipu_di *di,
229 }, { 229 }, {
230 .run_count = v_total / 2 - 1, 230 .run_count = v_total / 2 - 1,
231 .run_src = DI_SYNC_HSYNC, 231 .run_src = DI_SYNC_HSYNC,
232 .offset_count = sig->v_start_width, 232 .offset_count = sig->mode.vback_porch,
233 .offset_src = DI_SYNC_HSYNC, 233 .offset_src = DI_SYNC_HSYNC,
234 .repeat_count = 2, 234 .repeat_count = 2,
235 .cnt_clr_src = DI_SYNC_VSYNC, 235 .cnt_clr_src = DI_SYNC_VSYNC,
236 }, { 236 }, {
237 .run_src = DI_SYNC_HSYNC, 237 .run_src = DI_SYNC_HSYNC,
238 .repeat_count = sig->height / 2, 238 .repeat_count = sig->mode.vactive / 2,
239 .cnt_clr_src = 4, 239 .cnt_clr_src = 4,
240 }, { 240 }, {
241 .run_count = v_total - 1, 241 .run_count = v_total - 1,
@@ -249,9 +249,9 @@ static void ipu_di_sync_config_interlaced(struct ipu_di *di,
249 .cnt_clr_src = DI_SYNC_VSYNC, 249 .cnt_clr_src = DI_SYNC_VSYNC,
250 }, { 250 }, {
251 .run_src = DI_SYNC_CLK, 251 .run_src = DI_SYNC_CLK,
252 .offset_count = sig->h_start_width, 252 .offset_count = sig->mode.hback_porch,
253 .offset_src = DI_SYNC_CLK, 253 .offset_src = DI_SYNC_CLK,
254 .repeat_count = sig->width, 254 .repeat_count = sig->mode.hactive,
255 .cnt_clr_src = 5, 255 .cnt_clr_src = 5,
256 }, { 256 }, {
257 .run_count = v_total - 1, 257 .run_count = v_total - 1,
@@ -277,10 +277,10 @@ static void ipu_di_sync_config_interlaced(struct ipu_di *di,
277static void ipu_di_sync_config_noninterlaced(struct ipu_di *di, 277static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
278 struct ipu_di_signal_cfg *sig, int div) 278 struct ipu_di_signal_cfg *sig, int div)
279{ 279{
280 u32 h_total = sig->width + sig->h_sync_width + sig->h_start_width + 280 u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
281 sig->h_end_width; 281 sig->mode.hback_porch + sig->mode.hfront_porch;
282 u32 v_total = sig->height + sig->v_sync_width + sig->v_start_width + 282 u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
283 sig->v_end_width; 283 sig->mode.vback_porch + sig->mode.vfront_porch;
284 struct di_sync_config cfg[] = { 284 struct di_sync_config cfg[] = {
285 { 285 {
286 /* 1: INT_HSYNC */ 286 /* 1: INT_HSYNC */
@@ -294,27 +294,29 @@ static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
294 .offset_src = DI_SYNC_CLK, 294 .offset_src = DI_SYNC_CLK,
295 .cnt_polarity_gen_en = 1, 295 .cnt_polarity_gen_en = 1,
296 .cnt_polarity_trigger_src = DI_SYNC_CLK, 296 .cnt_polarity_trigger_src = DI_SYNC_CLK,
297 .cnt_down = sig->h_sync_width * 2, 297 .cnt_down = sig->mode.hsync_len * 2,
298 } , { 298 } , {
299 /* PIN3: VSYNC */ 299 /* PIN3: VSYNC */
300 .run_count = v_total - 1, 300 .run_count = v_total - 1,
301 .run_src = DI_SYNC_INT_HSYNC, 301 .run_src = DI_SYNC_INT_HSYNC,
302 .cnt_polarity_gen_en = 1, 302 .cnt_polarity_gen_en = 1,
303 .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC, 303 .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
304 .cnt_down = sig->v_sync_width * 2, 304 .cnt_down = sig->mode.vsync_len * 2,
305 } , { 305 } , {
306 /* 4: Line Active */ 306 /* 4: Line Active */
307 .run_src = DI_SYNC_HSYNC, 307 .run_src = DI_SYNC_HSYNC,
308 .offset_count = sig->v_sync_width + sig->v_start_width, 308 .offset_count = sig->mode.vsync_len +
309 sig->mode.vback_porch,
309 .offset_src = DI_SYNC_HSYNC, 310 .offset_src = DI_SYNC_HSYNC,
310 .repeat_count = sig->height, 311 .repeat_count = sig->mode.vactive,
311 .cnt_clr_src = DI_SYNC_VSYNC, 312 .cnt_clr_src = DI_SYNC_VSYNC,
312 } , { 313 } , {
313 /* 5: Pixel Active, referenced by DC */ 314 /* 5: Pixel Active, referenced by DC */
314 .run_src = DI_SYNC_CLK, 315 .run_src = DI_SYNC_CLK,
315 .offset_count = sig->h_sync_width + sig->h_start_width, 316 .offset_count = sig->mode.hsync_len +
317 sig->mode.hback_porch,
316 .offset_src = DI_SYNC_CLK, 318 .offset_src = DI_SYNC_CLK,
317 .repeat_count = sig->width, 319 .repeat_count = sig->mode.hactive,
318 .cnt_clr_src = 5, /* Line Active */ 320 .cnt_clr_src = 5, /* Line Active */
319 } , { 321 } , {
320 /* unused */ 322 /* unused */
@@ -339,9 +341,10 @@ static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
339 } , { 341 } , {
340 /* 3: Line Active */ 342 /* 3: Line Active */
341 .run_src = DI_SYNC_INT_HSYNC, 343 .run_src = DI_SYNC_INT_HSYNC,
342 .offset_count = sig->v_sync_width + sig->v_start_width, 344 .offset_count = sig->mode.vsync_len +
345 sig->mode.vback_porch,
343 .offset_src = DI_SYNC_INT_HSYNC, 346 .offset_src = DI_SYNC_INT_HSYNC,
344 .repeat_count = sig->height, 347 .repeat_count = sig->mode.vactive,
345 .cnt_clr_src = 3 /* VSYNC */, 348 .cnt_clr_src = 3 /* VSYNC */,
346 } , { 349 } , {
347 /* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */ 350 /* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */
@@ -351,13 +354,14 @@ static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
351 .offset_src = DI_SYNC_CLK, 354 .offset_src = DI_SYNC_CLK,
352 .cnt_polarity_gen_en = 1, 355 .cnt_polarity_gen_en = 1,
353 .cnt_polarity_trigger_src = DI_SYNC_CLK, 356 .cnt_polarity_trigger_src = DI_SYNC_CLK,
354 .cnt_down = sig->h_sync_width * 2, 357 .cnt_down = sig->mode.hsync_len * 2,
355 } , { 358 } , {
356 /* 5: Pixel Active signal to DC */ 359 /* 5: Pixel Active signal to DC */
357 .run_src = DI_SYNC_CLK, 360 .run_src = DI_SYNC_CLK,
358 .offset_count = sig->h_sync_width + sig->h_start_width, 361 .offset_count = sig->mode.hsync_len +
362 sig->mode.hback_porch,
359 .offset_src = DI_SYNC_CLK, 363 .offset_src = DI_SYNC_CLK,
360 .repeat_count = sig->width, 364 .repeat_count = sig->mode.hactive,
361 .cnt_clr_src = 4, /* Line Active */ 365 .cnt_clr_src = 4, /* Line Active */
362 } , { 366 } , {
363 /* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */ 367 /* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */
@@ -367,7 +371,7 @@ static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
367 .offset_src = DI_SYNC_INT_HSYNC, 371 .offset_src = DI_SYNC_INT_HSYNC,
368 .cnt_polarity_gen_en = 1, 372 .cnt_polarity_gen_en = 1,
369 .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC, 373 .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
370 .cnt_down = sig->v_sync_width * 2, 374 .cnt_down = sig->mode.vsync_len * 2,
371 } , { 375 } , {
372 /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */ 376 /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */
373 .run_count = h_total - 1, 377 .run_count = h_total - 1,
@@ -376,7 +380,7 @@ static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
376 .offset_src = DI_SYNC_CLK, 380 .offset_src = DI_SYNC_CLK,
377 .cnt_polarity_gen_en = 1, 381 .cnt_polarity_gen_en = 1,
378 .cnt_polarity_trigger_src = DI_SYNC_CLK, 382 .cnt_polarity_trigger_src = DI_SYNC_CLK,
379 .cnt_down = sig->h_sync_width * 2, 383 .cnt_down = sig->mode.hsync_len * 2,
380 } , { 384 } , {
381 /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */ 385 /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */
382 .run_count = v_total - 1, 386 .run_count = v_total - 1,
@@ -385,7 +389,7 @@ static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
385 .offset_src = DI_SYNC_INT_HSYNC, 389 .offset_src = DI_SYNC_INT_HSYNC,
386 .cnt_polarity_gen_en = 1, 390 .cnt_polarity_gen_en = 1,
387 .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC, 391 .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
388 .cnt_down = sig->v_sync_width * 2, 392 .cnt_down = sig->mode.vsync_len * 2,
389 } , { 393 } , {
390 /* unused */ 394 /* unused */
391 }, 395 },
@@ -433,10 +437,10 @@ static void ipu_di_config_clock(struct ipu_di *di,
433 unsigned long in_rate; 437 unsigned long in_rate;
434 unsigned div; 438 unsigned div;
435 439
436 clk_set_rate(clk, sig->pixelclock); 440 clk_set_rate(clk, sig->mode.pixelclock);
437 441
438 in_rate = clk_get_rate(clk); 442 in_rate = clk_get_rate(clk);
439 div = (in_rate + sig->pixelclock / 2) / sig->pixelclock; 443 div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
440 if (div == 0) 444 if (div == 0)
441 div = 1; 445 div = 1;
442 446
@@ -454,10 +458,10 @@ static void ipu_di_config_clock(struct ipu_di *di,
454 unsigned div, error; 458 unsigned div, error;
455 459
456 clkrate = clk_get_rate(di->clk_ipu); 460 clkrate = clk_get_rate(di->clk_ipu);
457 div = (clkrate + sig->pixelclock / 2) / sig->pixelclock; 461 div = DIV_ROUND_CLOSEST(clkrate, sig->mode.pixelclock);
458 rate = clkrate / div; 462 rate = clkrate / div;
459 463
460 error = rate / (sig->pixelclock / 1000); 464 error = rate / (sig->mode.pixelclock / 1000);
461 465
462 dev_dbg(di->ipu->dev, " IPU clock can give %lu with divider %u, error %d.%u%%\n", 466 dev_dbg(di->ipu->dev, " IPU clock can give %lu with divider %u, error %d.%u%%\n",
463 rate, div, (signed)(error - 1000) / 10, error % 10); 467 rate, div, (signed)(error - 1000) / 10, error % 10);
@@ -473,10 +477,10 @@ static void ipu_di_config_clock(struct ipu_di *di,
473 477
474 clk = di->clk_di; 478 clk = di->clk_di;
475 479
476 clk_set_rate(clk, sig->pixelclock); 480 clk_set_rate(clk, sig->mode.pixelclock);
477 481
478 in_rate = clk_get_rate(clk); 482 in_rate = clk_get_rate(clk);
479 div = (in_rate + sig->pixelclock / 2) / sig->pixelclock; 483 div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
480 if (div == 0) 484 if (div == 0)
481 div = 1; 485 div = 1;
482 486
@@ -504,35 +508,58 @@ static void ipu_di_config_clock(struct ipu_di *di,
504 ipu_di_write(di, val, DI_GENERAL); 508 ipu_di_write(di, val, DI_GENERAL);
505 509
506 dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n", 510 dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
507 sig->pixelclock, 511 sig->mode.pixelclock,
508 clk_get_rate(di->clk_ipu), 512 clk_get_rate(di->clk_ipu),
509 clk_get_rate(di->clk_di), 513 clk_get_rate(di->clk_di),
510 clk == di->clk_di ? "DI" : "IPU", 514 clk == di->clk_di ? "DI" : "IPU",
511 clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4)); 515 clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
512} 516}
513 517
518/*
519 * This function is called to adjust a video mode to IPU restrictions.
520 * It is meant to be called from drm crtc mode_fixup() methods.
521 */
522int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode)
523{
524 u32 diff;
525
526 if (mode->vfront_porch >= 2)
527 return 0;
528
529 diff = 2 - mode->vfront_porch;
530
531 if (mode->vback_porch >= diff) {
532 mode->vfront_porch = 2;
533 mode->vback_porch -= diff;
534 } else if (mode->vsync_len > diff) {
535 mode->vfront_porch = 2;
536 mode->vsync_len = mode->vsync_len - diff;
537 } else {
538 dev_warn(di->ipu->dev, "failed to adjust videomode\n");
539 return -EINVAL;
540 }
541
542 dev_warn(di->ipu->dev, "videomode adapted for IPU restrictions\n");
543 return 0;
544}
545EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode);
546
514int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig) 547int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
515{ 548{
516 u32 reg; 549 u32 reg;
517 u32 di_gen, vsync_cnt; 550 u32 di_gen, vsync_cnt;
518 u32 div; 551 u32 div;
519 u32 h_total, v_total;
520 552
521 dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n", 553 dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
522 di->id, sig->width, sig->height); 554 di->id, sig->mode.hactive, sig->mode.vactive);
523 555
524 if ((sig->v_sync_width == 0) || (sig->h_sync_width == 0)) 556 if ((sig->mode.vsync_len == 0) || (sig->mode.hsync_len == 0))
525 return -EINVAL; 557 return -EINVAL;
526 558
527 h_total = sig->width + sig->h_sync_width + sig->h_start_width +
528 sig->h_end_width;
529 v_total = sig->height + sig->v_sync_width + sig->v_start_width +
530 sig->v_end_width;
531
532 dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n", 559 dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
533 clk_get_rate(di->clk_ipu), 560 clk_get_rate(di->clk_ipu),
534 clk_get_rate(di->clk_di), 561 clk_get_rate(di->clk_di),
535 sig->pixelclock); 562 sig->mode.pixelclock);
536 563
537 mutex_lock(&di_mutex); 564 mutex_lock(&di_mutex);
538 565
@@ -551,7 +578,7 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
551 di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT; 578 di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT;
552 di_gen |= DI_GEN_DI_VSYNC_EXT; 579 di_gen |= DI_GEN_DI_VSYNC_EXT;
553 580
554 if (sig->interlaced) { 581 if (sig->mode.flags & DISPLAY_FLAGS_INTERLACED) {
555 ipu_di_sync_config_interlaced(di, sig); 582 ipu_di_sync_config_interlaced(di, sig);
556 583
557 /* set y_sel = 1 */ 584 /* set y_sel = 1 */
@@ -561,9 +588,9 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
561 588
562 vsync_cnt = 7; 589 vsync_cnt = 7;
563 590
564 if (sig->Hsync_pol) 591 if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH)
565 di_gen |= DI_GEN_POLARITY_3; 592 di_gen |= DI_GEN_POLARITY_3;
566 if (sig->Vsync_pol) 593 if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH)
567 di_gen |= DI_GEN_POLARITY_2; 594 di_gen |= DI_GEN_POLARITY_2;
568 } else { 595 } else {
569 ipu_di_sync_config_noninterlaced(di, sig, div); 596 ipu_di_sync_config_noninterlaced(di, sig, div);
@@ -577,7 +604,7 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
577 if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3)) 604 if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3))
578 vsync_cnt = 6; 605 vsync_cnt = 6;
579 606
580 if (sig->Hsync_pol) { 607 if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH) {
581 if (sig->hsync_pin == 2) 608 if (sig->hsync_pin == 2)
582 di_gen |= DI_GEN_POLARITY_2; 609 di_gen |= DI_GEN_POLARITY_2;
583 else if (sig->hsync_pin == 4) 610 else if (sig->hsync_pin == 4)
@@ -585,7 +612,7 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
585 else if (sig->hsync_pin == 7) 612 else if (sig->hsync_pin == 7)
586 di_gen |= DI_GEN_POLARITY_7; 613 di_gen |= DI_GEN_POLARITY_7;
587 } 614 }
588 if (sig->Vsync_pol) { 615 if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH) {
589 if (sig->vsync_pin == 3) 616 if (sig->vsync_pin == 3)
590 di_gen |= DI_GEN_POLARITY_3; 617 di_gen |= DI_GEN_POLARITY_3;
591 else if (sig->vsync_pin == 6) 618 else if (sig->vsync_pin == 6)