blob: f4faa14213e593d3d4314a0956addb219d03a1ee [file] [log] [blame]
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001/*
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +03002 * DesignWare High-Definition Multimedia Interface (HDMI) driver
3 *
4 * Copyright (C) 2013-2015 Mentor Graphics Inc.
Fabio Estevam9aaf8802013-11-29 08:46:32 -02005 * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +03006 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Fabio Estevam9aaf8802013-11-29 08:46:32 -02007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
Fabio Estevam9aaf8802013-11-29 08:46:32 -020013 */
Andy Yanb21f4b62014-12-05 14:26:31 +080014#include <linux/module.h>
Fabio Estevam9aaf8802013-11-29 08:46:32 -020015#include <linux/irq.h>
16#include <linux/delay.h>
17#include <linux/err.h>
18#include <linux/clk.h>
Sachin Kamat5a819ed2014-01-28 10:33:16 +053019#include <linux/hdmi.h>
Russell King6bcf4952015-02-02 11:01:08 +000020#include <linux/mutex.h>
Fabio Estevam9aaf8802013-11-29 08:46:32 -020021#include <linux/of_device.h>
Russell Kingb90120a2015-03-27 12:59:58 +000022#include <linux/spinlock.h>
Fabio Estevam9aaf8802013-11-29 08:46:32 -020023
Andy Yan3d1b35a2014-12-05 14:25:05 +080024#include <drm/drm_of.h>
Fabio Estevam9aaf8802013-11-29 08:46:32 -020025#include <drm/drmP.h>
Mark Yao2c5b2cc2015-11-30 18:33:40 +080026#include <drm/drm_atomic_helper.h>
Fabio Estevam9aaf8802013-11-29 08:46:32 -020027#include <drm/drm_crtc_helper.h>
28#include <drm/drm_edid.h>
29#include <drm/drm_encoder_slave.h>
Andy Yanb21f4b62014-12-05 14:26:31 +080030#include <drm/bridge/dw_hdmi.h>
Fabio Estevam9aaf8802013-11-29 08:46:32 -020031
Thierry Reding248a86f2015-11-24 17:52:58 +010032#include "dw-hdmi.h"
33#include "dw-hdmi-audio.h"
Fabio Estevam9aaf8802013-11-29 08:46:32 -020034
35#define HDMI_EDID_LEN 512
36
37#define RGB 0
38#define YCBCR444 1
39#define YCBCR422_16BITS 2
40#define YCBCR422_8BITS 3
41#define XVYCC444 4
42
43enum hdmi_datamap {
44 RGB444_8B = 0x01,
45 RGB444_10B = 0x03,
46 RGB444_12B = 0x05,
47 RGB444_16B = 0x07,
48 YCbCr444_8B = 0x09,
49 YCbCr444_10B = 0x0B,
50 YCbCr444_12B = 0x0D,
51 YCbCr444_16B = 0x0F,
52 YCbCr422_8B = 0x16,
53 YCbCr422_10B = 0x14,
54 YCbCr422_12B = 0x12,
55};
56
Fabio Estevam9aaf8802013-11-29 08:46:32 -020057static const u16 csc_coeff_default[3][4] = {
58 { 0x2000, 0x0000, 0x0000, 0x0000 },
59 { 0x0000, 0x2000, 0x0000, 0x0000 },
60 { 0x0000, 0x0000, 0x2000, 0x0000 }
61};
62
63static const u16 csc_coeff_rgb_out_eitu601[3][4] = {
64 { 0x2000, 0x6926, 0x74fd, 0x010e },
65 { 0x2000, 0x2cdd, 0x0000, 0x7e9a },
66 { 0x2000, 0x0000, 0x38b4, 0x7e3b }
67};
68
69static const u16 csc_coeff_rgb_out_eitu709[3][4] = {
70 { 0x2000, 0x7106, 0x7a02, 0x00a7 },
71 { 0x2000, 0x3264, 0x0000, 0x7e6d },
72 { 0x2000, 0x0000, 0x3b61, 0x7e25 }
73};
74
75static const u16 csc_coeff_rgb_in_eitu601[3][4] = {
76 { 0x2591, 0x1322, 0x074b, 0x0000 },
77 { 0x6535, 0x2000, 0x7acc, 0x0200 },
78 { 0x6acd, 0x7534, 0x2000, 0x0200 }
79};
80
81static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
82 { 0x2dc5, 0x0d9b, 0x049e, 0x0000 },
83 { 0x62f0, 0x2000, 0x7d11, 0x0200 },
84 { 0x6756, 0x78ab, 0x2000, 0x0200 }
85};
86
87struct hdmi_vmode {
Fabio Estevam9aaf8802013-11-29 08:46:32 -020088 bool mdataenablepolarity;
89
90 unsigned int mpixelclock;
91 unsigned int mpixelrepetitioninput;
92 unsigned int mpixelrepetitionoutput;
93};
94
95struct hdmi_data_info {
96 unsigned int enc_in_format;
97 unsigned int enc_out_format;
98 unsigned int enc_color_depth;
99 unsigned int colorimetry;
100 unsigned int pix_repet_factor;
101 unsigned int hdcp_enable;
102 struct hdmi_vmode video_mode;
103};
104
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +0300105struct dw_hdmi_i2c {
106 struct i2c_adapter adap;
107
108 struct mutex lock; /* used to serialize data transfers */
109 struct completion cmp;
110 u8 stat;
111
112 u8 slave_reg;
113 bool is_regaddr;
114};
115
Andy Yanb21f4b62014-12-05 14:26:31 +0800116struct dw_hdmi {
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200117 struct drm_connector connector;
Laurent Pinchart70c963e2017-01-17 10:28:54 +0200118 struct drm_bridge bridge;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200119
Andy Yanb21f4b62014-12-05 14:26:31 +0800120 enum dw_hdmi_devtype dev_type;
Laurent Pinchartbe41fc52017-01-17 10:29:05 +0200121 unsigned int version;
122
123 struct platform_device *audio;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200124 struct device *dev;
125 struct clk *isfr_clk;
126 struct clk *iahb_clk;
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +0300127 struct dw_hdmi_i2c *i2c;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200128
129 struct hdmi_data_info hdmi_data;
Andy Yanb21f4b62014-12-05 14:26:31 +0800130 const struct dw_hdmi_plat_data *plat_data;
131
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200132 int vic;
133
134 u8 edid[HDMI_EDID_LEN];
135 bool cable_plugin;
136
137 bool phy_enabled;
138 struct drm_display_mode previous_mode;
139
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200140 struct i2c_adapter *ddc;
141 void __iomem *regs;
Russell King05b13422015-07-21 15:35:52 +0100142 bool sink_is_hdmi;
Russell Kingf709ec02015-07-21 16:09:39 +0100143 bool sink_has_audio;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200144
Russell Kingb872a8e2015-06-05 12:22:46 +0100145 struct mutex mutex; /* for state below and previous_mode */
Russell King381f05a2015-06-05 15:25:08 +0100146 enum drm_connector_force force; /* mutex-protected force state */
Russell Kingb872a8e2015-06-05 12:22:46 +0100147 bool disabled; /* DRM has disabled our bridge */
Russell King381f05a2015-06-05 15:25:08 +0100148 bool bridge_is_on; /* indicates the bridge is on */
Russell Kingaeac23b2015-06-05 13:46:22 +0100149 bool rxsense; /* rxsense state */
150 u8 phy_mask; /* desired phy int mask settings */
Russell Kingb872a8e2015-06-05 12:22:46 +0100151
Russell Kingb90120a2015-03-27 12:59:58 +0000152 spinlock_t audio_lock;
Russell King6bcf4952015-02-02 11:01:08 +0000153 struct mutex audio_mutex;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200154 unsigned int sample_rate;
Russell Kingb90120a2015-03-27 12:59:58 +0000155 unsigned int audio_cts;
156 unsigned int audio_n;
157 bool audio_enable;
Andy Yan0cd9d142014-12-05 14:28:24 +0800158
159 void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
160 u8 (*read)(struct dw_hdmi *hdmi, int offset);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200161};
162
Russell Kingaeac23b2015-06-05 13:46:22 +0100163#define HDMI_IH_PHY_STAT0_RX_SENSE \
164 (HDMI_IH_PHY_STAT0_RX_SENSE0 | HDMI_IH_PHY_STAT0_RX_SENSE1 | \
165 HDMI_IH_PHY_STAT0_RX_SENSE2 | HDMI_IH_PHY_STAT0_RX_SENSE3)
166
167#define HDMI_PHY_RX_SENSE \
168 (HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \
169 HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3)
170
Andy Yan0cd9d142014-12-05 14:28:24 +0800171static void dw_hdmi_writel(struct dw_hdmi *hdmi, u8 val, int offset)
172{
173 writel(val, hdmi->regs + (offset << 2));
174}
175
176static u8 dw_hdmi_readl(struct dw_hdmi *hdmi, int offset)
177{
178 return readl(hdmi->regs + (offset << 2));
179}
180
181static void dw_hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200182{
183 writeb(val, hdmi->regs + offset);
184}
185
Andy Yan0cd9d142014-12-05 14:28:24 +0800186static u8 dw_hdmi_readb(struct dw_hdmi *hdmi, int offset)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200187{
188 return readb(hdmi->regs + offset);
189}
190
Andy Yan0cd9d142014-12-05 14:28:24 +0800191static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
192{
193 hdmi->write(hdmi, val, offset);
194}
195
196static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset)
197{
198 return hdmi->read(hdmi, offset);
199}
200
Andy Yanb21f4b62014-12-05 14:26:31 +0800201static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
Russell King812bc612013-11-04 12:42:02 +0000202{
203 u8 val = hdmi_readb(hdmi, reg) & ~mask;
Fabio Estevamb44ab1b2014-04-28 08:01:07 -0300204
Russell King812bc612013-11-04 12:42:02 +0000205 val |= data & mask;
206 hdmi_writeb(hdmi, val, reg);
207}
208
Andy Yanb21f4b62014-12-05 14:26:31 +0800209static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
Andy Yanb5878332014-12-05 14:23:52 +0800210 u8 shift, u8 mask)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200211{
Russell King812bc612013-11-04 12:42:02 +0000212 hdmi_modb(hdmi, data << shift, mask, reg);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200213}
214
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +0300215static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi)
216{
217 /* Software reset */
218 hdmi_writeb(hdmi, 0x00, HDMI_I2CM_SOFTRSTZ);
219
220 /* Set Standard Mode speed (determined to be 100KHz on iMX6) */
221 hdmi_writeb(hdmi, 0x00, HDMI_I2CM_DIV);
222
223 /* Set done, not acknowledged and arbitration interrupt polarities */
224 hdmi_writeb(hdmi, HDMI_I2CM_INT_DONE_POL, HDMI_I2CM_INT);
225 hdmi_writeb(hdmi, HDMI_I2CM_CTLINT_NAC_POL | HDMI_I2CM_CTLINT_ARB_POL,
226 HDMI_I2CM_CTLINT);
227
228 /* Clear DONE and ERROR interrupts */
229 hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
230 HDMI_IH_I2CM_STAT0);
231
232 /* Mute DONE and ERROR interrupts */
233 hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
234 HDMI_IH_MUTE_I2CM_STAT0);
235}
236
237static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi,
238 unsigned char *buf, unsigned int length)
239{
240 struct dw_hdmi_i2c *i2c = hdmi->i2c;
241 int stat;
242
243 if (!i2c->is_regaddr) {
244 dev_dbg(hdmi->dev, "set read register address to 0\n");
245 i2c->slave_reg = 0x00;
246 i2c->is_regaddr = true;
247 }
248
249 while (length--) {
250 reinit_completion(&i2c->cmp);
251
252 hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS);
253 hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ,
254 HDMI_I2CM_OPERATION);
255
256 stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
257 if (!stat)
258 return -EAGAIN;
259
260 /* Check for error condition on the bus */
261 if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR)
262 return -EIO;
263
264 *buf++ = hdmi_readb(hdmi, HDMI_I2CM_DATAI);
265 }
266
267 return 0;
268}
269
270static int dw_hdmi_i2c_write(struct dw_hdmi *hdmi,
271 unsigned char *buf, unsigned int length)
272{
273 struct dw_hdmi_i2c *i2c = hdmi->i2c;
274 int stat;
275
276 if (!i2c->is_regaddr) {
277 /* Use the first write byte as register address */
278 i2c->slave_reg = buf[0];
279 length--;
280 buf++;
281 i2c->is_regaddr = true;
282 }
283
284 while (length--) {
285 reinit_completion(&i2c->cmp);
286
287 hdmi_writeb(hdmi, *buf++, HDMI_I2CM_DATAO);
288 hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS);
289 hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_WRITE,
290 HDMI_I2CM_OPERATION);
291
292 stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
293 if (!stat)
294 return -EAGAIN;
295
296 /* Check for error condition on the bus */
297 if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR)
298 return -EIO;
299 }
300
301 return 0;
302}
303
304static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap,
305 struct i2c_msg *msgs, int num)
306{
307 struct dw_hdmi *hdmi = i2c_get_adapdata(adap);
308 struct dw_hdmi_i2c *i2c = hdmi->i2c;
309 u8 addr = msgs[0].addr;
310 int i, ret = 0;
311
312 dev_dbg(hdmi->dev, "xfer: num: %d, addr: %#x\n", num, addr);
313
314 for (i = 0; i < num; i++) {
315 if (msgs[i].addr != addr) {
316 dev_warn(hdmi->dev,
317 "unsupported transfer, changed slave address\n");
318 return -EOPNOTSUPP;
319 }
320
321 if (msgs[i].len == 0) {
322 dev_dbg(hdmi->dev,
323 "unsupported transfer %d/%d, no data\n",
324 i + 1, num);
325 return -EOPNOTSUPP;
326 }
327 }
328
329 mutex_lock(&i2c->lock);
330
331 /* Unmute DONE and ERROR interrupts */
332 hdmi_writeb(hdmi, 0x00, HDMI_IH_MUTE_I2CM_STAT0);
333
334 /* Set slave device address taken from the first I2C message */
335 hdmi_writeb(hdmi, addr, HDMI_I2CM_SLAVE);
336
337 /* Set slave device register address on transfer */
338 i2c->is_regaddr = false;
339
340 for (i = 0; i < num; i++) {
341 dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n",
342 i + 1, num, msgs[i].len, msgs[i].flags);
343
344 if (msgs[i].flags & I2C_M_RD)
345 ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf, msgs[i].len);
346 else
347 ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf, msgs[i].len);
348
349 if (ret < 0)
350 break;
351 }
352
353 if (!ret)
354 ret = num;
355
356 /* Mute DONE and ERROR interrupts */
357 hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
358 HDMI_IH_MUTE_I2CM_STAT0);
359
360 mutex_unlock(&i2c->lock);
361
362 return ret;
363}
364
365static u32 dw_hdmi_i2c_func(struct i2c_adapter *adapter)
366{
367 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
368}
369
370static const struct i2c_algorithm dw_hdmi_algorithm = {
371 .master_xfer = dw_hdmi_i2c_xfer,
372 .functionality = dw_hdmi_i2c_func,
373};
374
375static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi)
376{
377 struct i2c_adapter *adap;
378 struct dw_hdmi_i2c *i2c;
379 int ret;
380
381 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
382 if (!i2c)
383 return ERR_PTR(-ENOMEM);
384
385 mutex_init(&i2c->lock);
386 init_completion(&i2c->cmp);
387
388 adap = &i2c->adap;
389 adap->class = I2C_CLASS_DDC;
390 adap->owner = THIS_MODULE;
391 adap->dev.parent = hdmi->dev;
392 adap->algo = &dw_hdmi_algorithm;
393 strlcpy(adap->name, "DesignWare HDMI", sizeof(adap->name));
394 i2c_set_adapdata(adap, hdmi);
395
396 ret = i2c_add_adapter(adap);
397 if (ret) {
398 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
399 devm_kfree(hdmi->dev, i2c);
400 return ERR_PTR(ret);
401 }
402
403 hdmi->i2c = i2c;
404
405 dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
406
407 return adap;
408}
409
Russell King351e1352015-01-31 14:50:23 +0000410static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
411 unsigned int n)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200412{
Russell King622494a2015-02-02 10:55:38 +0000413 /* Must be set/cleared first */
414 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200415
416 /* nshift factor = 0 */
Russell King812bc612013-11-04 12:42:02 +0000417 hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200418
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200419 hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
420 HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
Russell King622494a2015-02-02 10:55:38 +0000421 hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
422 hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
423
424 hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3);
425 hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
426 hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200427}
428
Russell Kingb195fbd2015-07-22 11:28:16 +0100429static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200430{
431 unsigned int n = (128 * freq) / 1000;
Russell Kingd0c96d12015-07-22 10:35:41 +0100432 unsigned int mult = 1;
433
434 while (freq > 48000) {
435 mult *= 2;
436 freq /= 2;
437 }
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200438
439 switch (freq) {
440 case 32000:
Russell King426701d2015-07-22 10:39:27 +0100441 if (pixel_clk == 25175000)
Russell Kingb195fbd2015-07-22 11:28:16 +0100442 n = 4576;
Russell King426701d2015-07-22 10:39:27 +0100443 else if (pixel_clk == 27027000)
Russell Kingb195fbd2015-07-22 11:28:16 +0100444 n = 4096;
Russell King426701d2015-07-22 10:39:27 +0100445 else if (pixel_clk == 74176000 || pixel_clk == 148352000)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200446 n = 11648;
447 else
448 n = 4096;
Russell Kingd0c96d12015-07-22 10:35:41 +0100449 n *= mult;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200450 break;
451
452 case 44100:
Russell King426701d2015-07-22 10:39:27 +0100453 if (pixel_clk == 25175000)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200454 n = 7007;
Russell King426701d2015-07-22 10:39:27 +0100455 else if (pixel_clk == 74176000)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200456 n = 17836;
Russell King426701d2015-07-22 10:39:27 +0100457 else if (pixel_clk == 148352000)
Russell Kingb195fbd2015-07-22 11:28:16 +0100458 n = 8918;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200459 else
460 n = 6272;
Russell Kingd0c96d12015-07-22 10:35:41 +0100461 n *= mult;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200462 break;
463
464 case 48000:
Russell King426701d2015-07-22 10:39:27 +0100465 if (pixel_clk == 25175000)
Russell Kingb195fbd2015-07-22 11:28:16 +0100466 n = 6864;
Russell King426701d2015-07-22 10:39:27 +0100467 else if (pixel_clk == 27027000)
Russell Kingb195fbd2015-07-22 11:28:16 +0100468 n = 6144;
Russell King426701d2015-07-22 10:39:27 +0100469 else if (pixel_clk == 74176000)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200470 n = 11648;
Russell King426701d2015-07-22 10:39:27 +0100471 else if (pixel_clk == 148352000)
Russell Kingb195fbd2015-07-22 11:28:16 +0100472 n = 5824;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200473 else
474 n = 6144;
Russell Kingd0c96d12015-07-22 10:35:41 +0100475 n *= mult;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200476 break;
477
478 default:
479 break;
480 }
481
482 return n;
483}
484
Andy Yanb21f4b62014-12-05 14:26:31 +0800485static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
Russell Kingb195fbd2015-07-22 11:28:16 +0100486 unsigned long pixel_clk, unsigned int sample_rate)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200487{
Russell Kingdfbdaf52015-07-22 16:54:37 +0100488 unsigned long ftdms = pixel_clk;
Russell Kingf879b382015-03-27 12:53:29 +0000489 unsigned int n, cts;
Russell Kingdfbdaf52015-07-22 16:54:37 +0100490 u64 tmp;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200491
Russell Kingb195fbd2015-07-22 11:28:16 +0100492 n = hdmi_compute_n(sample_rate, pixel_clk);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200493
Russell Kingdfbdaf52015-07-22 16:54:37 +0100494 /*
495 * Compute the CTS value from the N value. Note that CTS and N
496 * can be up to 20 bits in total, so we need 64-bit math. Also
497 * note that our TDMS clock is not fully accurate; it is accurate
498 * to kHz. This can introduce an unnecessary remainder in the
499 * calculation below, so we don't try to warn about that.
500 */
501 tmp = (u64)ftdms * n;
502 do_div(tmp, 128 * sample_rate);
503 cts = tmp;
504
505 dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n",
506 __func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000,
507 n, cts);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200508
Russell Kingb90120a2015-03-27 12:59:58 +0000509 spin_lock_irq(&hdmi->audio_lock);
510 hdmi->audio_n = n;
511 hdmi->audio_cts = cts;
512 hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
513 spin_unlock_irq(&hdmi->audio_lock);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200514}
515
Andy Yanb21f4b62014-12-05 14:26:31 +0800516static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200517{
Russell King6bcf4952015-02-02 11:01:08 +0000518 mutex_lock(&hdmi->audio_mutex);
Russell Kingb195fbd2015-07-22 11:28:16 +0100519 hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate);
Russell King6bcf4952015-02-02 11:01:08 +0000520 mutex_unlock(&hdmi->audio_mutex);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200521}
522
Andy Yanb21f4b62014-12-05 14:26:31 +0800523static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200524{
Russell King6bcf4952015-02-02 11:01:08 +0000525 mutex_lock(&hdmi->audio_mutex);
Russell Kingf879b382015-03-27 12:53:29 +0000526 hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
Russell Kingb195fbd2015-07-22 11:28:16 +0100527 hdmi->sample_rate);
Russell King6bcf4952015-02-02 11:01:08 +0000528 mutex_unlock(&hdmi->audio_mutex);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200529}
530
Russell Kingb5814ff2015-03-27 12:50:58 +0000531void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
532{
533 mutex_lock(&hdmi->audio_mutex);
534 hdmi->sample_rate = rate;
535 hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
Russell Kingb195fbd2015-07-22 11:28:16 +0100536 hdmi->sample_rate);
Russell Kingb5814ff2015-03-27 12:50:58 +0000537 mutex_unlock(&hdmi->audio_mutex);
538}
539EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
540
Russell Kingb90120a2015-03-27 12:59:58 +0000541void dw_hdmi_audio_enable(struct dw_hdmi *hdmi)
542{
543 unsigned long flags;
544
545 spin_lock_irqsave(&hdmi->audio_lock, flags);
546 hdmi->audio_enable = true;
547 hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
548 spin_unlock_irqrestore(&hdmi->audio_lock, flags);
549}
550EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable);
551
552void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
553{
554 unsigned long flags;
555
556 spin_lock_irqsave(&hdmi->audio_lock, flags);
557 hdmi->audio_enable = false;
558 hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0);
559 spin_unlock_irqrestore(&hdmi->audio_lock, flags);
560}
561EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
562
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200563/*
564 * this submodule is responsible for the video data synchronization.
565 * for example, for RGB 4:4:4 input, the data map is defined as
566 * pin{47~40} <==> R[7:0]
567 * pin{31~24} <==> G[7:0]
568 * pin{15~8} <==> B[7:0]
569 */
Andy Yanb21f4b62014-12-05 14:26:31 +0800570static void hdmi_video_sample(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200571{
572 int color_format = 0;
573 u8 val;
574
575 if (hdmi->hdmi_data.enc_in_format == RGB) {
576 if (hdmi->hdmi_data.enc_color_depth == 8)
577 color_format = 0x01;
578 else if (hdmi->hdmi_data.enc_color_depth == 10)
579 color_format = 0x03;
580 else if (hdmi->hdmi_data.enc_color_depth == 12)
581 color_format = 0x05;
582 else if (hdmi->hdmi_data.enc_color_depth == 16)
583 color_format = 0x07;
584 else
585 return;
586 } else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
587 if (hdmi->hdmi_data.enc_color_depth == 8)
588 color_format = 0x09;
589 else if (hdmi->hdmi_data.enc_color_depth == 10)
590 color_format = 0x0B;
591 else if (hdmi->hdmi_data.enc_color_depth == 12)
592 color_format = 0x0D;
593 else if (hdmi->hdmi_data.enc_color_depth == 16)
594 color_format = 0x0F;
595 else
596 return;
597 } else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
598 if (hdmi->hdmi_data.enc_color_depth == 8)
599 color_format = 0x16;
600 else if (hdmi->hdmi_data.enc_color_depth == 10)
601 color_format = 0x14;
602 else if (hdmi->hdmi_data.enc_color_depth == 12)
603 color_format = 0x12;
604 else
605 return;
606 }
607
608 val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
609 ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
610 HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
611 hdmi_writeb(hdmi, val, HDMI_TX_INVID0);
612
613 /* Enable TX stuffing: When DE is inactive, fix the output data to 0 */
614 val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
615 HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
616 HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
617 hdmi_writeb(hdmi, val, HDMI_TX_INSTUFFING);
618 hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA0);
619 hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA1);
620 hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA0);
621 hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA1);
622 hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA0);
623 hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1);
624}
625
Andy Yanb21f4b62014-12-05 14:26:31 +0800626static int is_color_space_conversion(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200627{
Fabio Estevamba92b222014-02-06 10:12:03 -0200628 return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200629}
630
Andy Yanb21f4b62014-12-05 14:26:31 +0800631static int is_color_space_decimation(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200632{
Fabio Estevamba92b222014-02-06 10:12:03 -0200633 if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
634 return 0;
635 if (hdmi->hdmi_data.enc_in_format == RGB ||
636 hdmi->hdmi_data.enc_in_format == YCBCR444)
637 return 1;
638 return 0;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200639}
640
Andy Yanb21f4b62014-12-05 14:26:31 +0800641static int is_color_space_interpolation(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200642{
Fabio Estevamba92b222014-02-06 10:12:03 -0200643 if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
644 return 0;
645 if (hdmi->hdmi_data.enc_out_format == RGB ||
646 hdmi->hdmi_data.enc_out_format == YCBCR444)
647 return 1;
648 return 0;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200649}
650
Andy Yanb21f4b62014-12-05 14:26:31 +0800651static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200652{
653 const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
Russell Kingc082f9d2013-11-04 12:10:40 +0000654 unsigned i;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200655 u32 csc_scale = 1;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200656
657 if (is_color_space_conversion(hdmi)) {
658 if (hdmi->hdmi_data.enc_out_format == RGB) {
Gulsah Kose256a38b2014-03-09 20:11:07 +0200659 if (hdmi->hdmi_data.colorimetry ==
660 HDMI_COLORIMETRY_ITU_601)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200661 csc_coeff = &csc_coeff_rgb_out_eitu601;
662 else
663 csc_coeff = &csc_coeff_rgb_out_eitu709;
664 } else if (hdmi->hdmi_data.enc_in_format == RGB) {
Gulsah Kose256a38b2014-03-09 20:11:07 +0200665 if (hdmi->hdmi_data.colorimetry ==
666 HDMI_COLORIMETRY_ITU_601)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200667 csc_coeff = &csc_coeff_rgb_in_eitu601;
668 else
669 csc_coeff = &csc_coeff_rgb_in_eitu709;
670 csc_scale = 0;
671 }
672 }
673
Russell Kingc082f9d2013-11-04 12:10:40 +0000674 /* The CSC registers are sequential, alternating MSB then LSB */
675 for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
676 u16 coeff_a = (*csc_coeff)[0][i];
677 u16 coeff_b = (*csc_coeff)[1][i];
678 u16 coeff_c = (*csc_coeff)[2][i];
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200679
Andy Yanb5878332014-12-05 14:23:52 +0800680 hdmi_writeb(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
Russell Kingc082f9d2013-11-04 12:10:40 +0000681 hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
682 hdmi_writeb(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
683 hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
Andy Yanb5878332014-12-05 14:23:52 +0800684 hdmi_writeb(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
Russell Kingc082f9d2013-11-04 12:10:40 +0000685 hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
686 }
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200687
Russell King812bc612013-11-04 12:42:02 +0000688 hdmi_modb(hdmi, csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK,
689 HDMI_CSC_SCALE);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200690}
691
Andy Yanb21f4b62014-12-05 14:26:31 +0800692static void hdmi_video_csc(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200693{
694 int color_depth = 0;
695 int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
696 int decimation = 0;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200697
698 /* YCC422 interpolation to 444 mode */
699 if (is_color_space_interpolation(hdmi))
700 interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1;
701 else if (is_color_space_decimation(hdmi))
702 decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
703
704 if (hdmi->hdmi_data.enc_color_depth == 8)
705 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
706 else if (hdmi->hdmi_data.enc_color_depth == 10)
707 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
708 else if (hdmi->hdmi_data.enc_color_depth == 12)
709 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
710 else if (hdmi->hdmi_data.enc_color_depth == 16)
711 color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
712 else
713 return;
714
715 /* Configure the CSC registers */
716 hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
Russell King812bc612013-11-04 12:42:02 +0000717 hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
718 HDMI_CSC_SCALE);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200719
Andy Yanb21f4b62014-12-05 14:26:31 +0800720 dw_hdmi_update_csc_coeffs(hdmi);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200721}
722
723/*
724 * HDMI video packetizer is used to packetize the data.
725 * for example, if input is YCC422 mode or repeater is used,
726 * data should be repacked this module can be bypassed.
727 */
Andy Yanb21f4b62014-12-05 14:26:31 +0800728static void hdmi_video_packetize(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200729{
730 unsigned int color_depth = 0;
731 unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit;
732 unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP;
733 struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
Russell Kingbebdf662013-11-04 12:55:30 +0000734 u8 val, vp_conf;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200735
Andy Yanb5878332014-12-05 14:23:52 +0800736 if (hdmi_data->enc_out_format == RGB ||
737 hdmi_data->enc_out_format == YCBCR444) {
738 if (!hdmi_data->enc_color_depth) {
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200739 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
Andy Yanb5878332014-12-05 14:23:52 +0800740 } else if (hdmi_data->enc_color_depth == 8) {
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200741 color_depth = 4;
742 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
Andy Yanb5878332014-12-05 14:23:52 +0800743 } else if (hdmi_data->enc_color_depth == 10) {
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200744 color_depth = 5;
Andy Yanb5878332014-12-05 14:23:52 +0800745 } else if (hdmi_data->enc_color_depth == 12) {
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200746 color_depth = 6;
Andy Yanb5878332014-12-05 14:23:52 +0800747 } else if (hdmi_data->enc_color_depth == 16) {
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200748 color_depth = 7;
Andy Yanb5878332014-12-05 14:23:52 +0800749 } else {
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200750 return;
Andy Yanb5878332014-12-05 14:23:52 +0800751 }
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200752 } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
753 if (!hdmi_data->enc_color_depth ||
754 hdmi_data->enc_color_depth == 8)
755 remap_size = HDMI_VP_REMAP_YCC422_16bit;
756 else if (hdmi_data->enc_color_depth == 10)
757 remap_size = HDMI_VP_REMAP_YCC422_20bit;
758 else if (hdmi_data->enc_color_depth == 12)
759 remap_size = HDMI_VP_REMAP_YCC422_24bit;
760 else
761 return;
762 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
Andy Yanb5878332014-12-05 14:23:52 +0800763 } else {
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200764 return;
Andy Yanb5878332014-12-05 14:23:52 +0800765 }
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200766
767 /* set the packetizer registers */
768 val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
769 HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
770 ((hdmi_data->pix_repet_factor <<
771 HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
772 HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
773 hdmi_writeb(hdmi, val, HDMI_VP_PR_CD);
774
Russell King812bc612013-11-04 12:42:02 +0000775 hdmi_modb(hdmi, HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE,
776 HDMI_VP_STUFF_PR_STUFFING_MASK, HDMI_VP_STUFF);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200777
778 /* Data from pixel repeater block */
779 if (hdmi_data->pix_repet_factor > 1) {
Russell Kingbebdf662013-11-04 12:55:30 +0000780 vp_conf = HDMI_VP_CONF_PR_EN_ENABLE |
781 HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200782 } else { /* data from packetizer block */
Russell Kingbebdf662013-11-04 12:55:30 +0000783 vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
784 HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200785 }
786
Russell Kingbebdf662013-11-04 12:55:30 +0000787 hdmi_modb(hdmi, vp_conf,
788 HDMI_VP_CONF_PR_EN_MASK |
789 HDMI_VP_CONF_BYPASS_SELECT_MASK, HDMI_VP_CONF);
790
Russell King812bc612013-11-04 12:42:02 +0000791 hdmi_modb(hdmi, 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET,
792 HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, HDMI_VP_STUFF);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200793
794 hdmi_writeb(hdmi, remap_size, HDMI_VP_REMAP);
795
796 if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
Russell Kingbebdf662013-11-04 12:55:30 +0000797 vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
798 HDMI_VP_CONF_PP_EN_ENABLE |
799 HDMI_VP_CONF_YCC422_EN_DISABLE;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200800 } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
Russell Kingbebdf662013-11-04 12:55:30 +0000801 vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
802 HDMI_VP_CONF_PP_EN_DISABLE |
803 HDMI_VP_CONF_YCC422_EN_ENABLE;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200804 } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
Russell Kingbebdf662013-11-04 12:55:30 +0000805 vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
806 HDMI_VP_CONF_PP_EN_DISABLE |
807 HDMI_VP_CONF_YCC422_EN_DISABLE;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200808 } else {
809 return;
810 }
811
Russell Kingbebdf662013-11-04 12:55:30 +0000812 hdmi_modb(hdmi, vp_conf,
813 HDMI_VP_CONF_BYPASS_EN_MASK | HDMI_VP_CONF_PP_EN_ENMASK |
814 HDMI_VP_CONF_YCC422_EN_MASK, HDMI_VP_CONF);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200815
Russell King812bc612013-11-04 12:42:02 +0000816 hdmi_modb(hdmi, HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
817 HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE,
818 HDMI_VP_STUFF_PP_STUFFING_MASK |
819 HDMI_VP_STUFF_YCC422_STUFFING_MASK, HDMI_VP_STUFF);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200820
Russell King812bc612013-11-04 12:42:02 +0000821 hdmi_modb(hdmi, output_select, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
822 HDMI_VP_CONF);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200823}
824
Andy Yanb21f4b62014-12-05 14:26:31 +0800825static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi,
Andy Yanb5878332014-12-05 14:23:52 +0800826 unsigned char bit)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200827{
Russell King812bc612013-11-04 12:42:02 +0000828 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET,
829 HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200830}
831
Andy Yanb21f4b62014-12-05 14:26:31 +0800832static inline void hdmi_phy_test_enable(struct dw_hdmi *hdmi,
Andy Yanb5878332014-12-05 14:23:52 +0800833 unsigned char bit)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200834{
Russell King812bc612013-11-04 12:42:02 +0000835 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET,
836 HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200837}
838
Andy Yanb21f4b62014-12-05 14:26:31 +0800839static inline void hdmi_phy_test_clock(struct dw_hdmi *hdmi,
Andy Yanb5878332014-12-05 14:23:52 +0800840 unsigned char bit)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200841{
Russell King812bc612013-11-04 12:42:02 +0000842 hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET,
843 HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200844}
845
Andy Yanb21f4b62014-12-05 14:26:31 +0800846static inline void hdmi_phy_test_din(struct dw_hdmi *hdmi,
Andy Yanb5878332014-12-05 14:23:52 +0800847 unsigned char bit)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200848{
849 hdmi_writeb(hdmi, bit, HDMI_PHY_TST1);
850}
851
Andy Yanb21f4b62014-12-05 14:26:31 +0800852static inline void hdmi_phy_test_dout(struct dw_hdmi *hdmi,
Andy Yanb5878332014-12-05 14:23:52 +0800853 unsigned char bit)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200854{
855 hdmi_writeb(hdmi, bit, HDMI_PHY_TST2);
856}
857
Andy Yanb21f4b62014-12-05 14:26:31 +0800858static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200859{
Andy Yana4d3b8b2014-12-05 14:31:09 +0800860 u32 val;
861
862 while ((val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3) == 0) {
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200863 if (msec-- == 0)
864 return false;
Emil Renner Berthing0e6bcf32014-03-30 00:21:21 +0100865 udelay(1000);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200866 }
Andy Yana4d3b8b2014-12-05 14:31:09 +0800867 hdmi_writeb(hdmi, val, HDMI_IH_I2CMPHY_STAT0);
868
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200869 return true;
870}
871
Laurent Pinchartcc7e9622017-01-17 10:28:51 +0200872static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
Andy Yanb5878332014-12-05 14:23:52 +0800873 unsigned char addr)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200874{
875 hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0);
876 hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
877 hdmi_writeb(hdmi, (unsigned char)(data >> 8),
Andy Yanb5878332014-12-05 14:23:52 +0800878 HDMI_PHY_I2CM_DATAO_1_ADDR);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200879 hdmi_writeb(hdmi, (unsigned char)(data >> 0),
Andy Yanb5878332014-12-05 14:23:52 +0800880 HDMI_PHY_I2CM_DATAO_0_ADDR);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200881 hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
Andy Yanb5878332014-12-05 14:23:52 +0800882 HDMI_PHY_I2CM_OPERATION_ADDR);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200883 hdmi_phy_wait_i2c_done(hdmi, 1000);
884}
885
Russell King2fada102015-07-28 12:21:34 +0100886static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200887{
Russell King2fada102015-07-28 12:21:34 +0100888 hdmi_mask_writeb(hdmi, !enable, HDMI_PHY_CONF0,
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200889 HDMI_PHY_CONF0_PDZ_OFFSET,
890 HDMI_PHY_CONF0_PDZ_MASK);
891}
892
Andy Yanb21f4b62014-12-05 14:26:31 +0800893static void dw_hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, u8 enable)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200894{
895 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
896 HDMI_PHY_CONF0_ENTMDS_OFFSET,
897 HDMI_PHY_CONF0_ENTMDS_MASK);
898}
899
Laurent Pinchartf4104e82017-01-17 10:29:02 +0200900static void dw_hdmi_phy_enable_svsret(struct dw_hdmi *hdmi, u8 enable)
Andy Yand346c142014-12-05 14:31:53 +0800901{
902 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
Laurent Pinchartf4104e82017-01-17 10:29:02 +0200903 HDMI_PHY_CONF0_SVSRET_OFFSET,
904 HDMI_PHY_CONF0_SVSRET_MASK);
Andy Yand346c142014-12-05 14:31:53 +0800905}
906
Andy Yanb21f4b62014-12-05 14:26:31 +0800907static void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200908{
909 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
910 HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET,
911 HDMI_PHY_CONF0_GEN2_PDDQ_MASK);
912}
913
Andy Yanb21f4b62014-12-05 14:26:31 +0800914static void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200915{
916 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
917 HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET,
918 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK);
919}
920
Andy Yanb21f4b62014-12-05 14:26:31 +0800921static void dw_hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, u8 enable)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200922{
923 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
924 HDMI_PHY_CONF0_SELDATAENPOL_OFFSET,
925 HDMI_PHY_CONF0_SELDATAENPOL_MASK);
926}
927
Andy Yanb21f4b62014-12-05 14:26:31 +0800928static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200929{
930 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
931 HDMI_PHY_CONF0_SELDIPIF_OFFSET,
932 HDMI_PHY_CONF0_SELDIPIF_MASK);
933}
934
Kieran Bingham1acc6bd2017-01-17 10:29:01 +0200935static int hdmi_phy_configure(struct dw_hdmi *hdmi, int cscon)
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200936{
937 u8 val, msec;
Russell King39cc1532015-03-31 18:34:11 +0100938 const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
939 const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
940 const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
941 const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200942
Russell King39cc1532015-03-31 18:34:11 +0100943 /* PLL/MPLL Cfg - always match on final entry */
944 for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
945 if (hdmi->hdmi_data.video_mode.mpixelclock <=
946 mpll_config->mpixelclock)
947 break;
948
949 for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
950 if (hdmi->hdmi_data.video_mode.mpixelclock <=
951 curr_ctrl->mpixelclock)
952 break;
953
954 for (; phy_config->mpixelclock != ~0UL; phy_config++)
955 if (hdmi->hdmi_data.video_mode.mpixelclock <=
956 phy_config->mpixelclock)
957 break;
958
959 if (mpll_config->mpixelclock == ~0UL ||
960 curr_ctrl->mpixelclock == ~0UL ||
961 phy_config->mpixelclock == ~0UL) {
962 dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
963 hdmi->hdmi_data.video_mode.mpixelclock);
964 return -EINVAL;
965 }
966
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200967 /* Enable csc path */
968 if (cscon)
969 val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
970 else
971 val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS;
972
973 hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL);
974
975 /* gen2 tx power off */
Andy Yanb21f4b62014-12-05 14:26:31 +0800976 dw_hdmi_phy_gen2_txpwron(hdmi, 0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200977
978 /* gen2 pddq */
Andy Yanb21f4b62014-12-05 14:26:31 +0800979 dw_hdmi_phy_gen2_pddq(hdmi, 1);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200980
981 /* PHY reset */
982 hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
983 hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
984
985 hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
986
987 hdmi_phy_test_clear(hdmi, 1);
988 hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
Andy Yanb5878332014-12-05 14:23:52 +0800989 HDMI_PHY_I2CM_SLAVE_ADDR);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200990 hdmi_phy_test_clear(hdmi, 0);
991
Kieran Bingham1acc6bd2017-01-17 10:29:01 +0200992 hdmi_phy_i2c_write(hdmi, mpll_config->res[0].cpce, 0x06);
993 hdmi_phy_i2c_write(hdmi, mpll_config->res[0].gmp, 0x15);
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200994
Russell King3e46f152013-11-04 11:24:00 +0000995 /* CURRCTRL */
Kieran Bingham1acc6bd2017-01-17 10:29:01 +0200996 hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[0], 0x10);
Russell King3e46f152013-11-04 11:24:00 +0000997
Fabio Estevam9aaf8802013-11-29 08:46:32 -0200998 hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
999 hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
Andy Yanaaa757a2014-12-05 14:25:50 +08001000
Russell King39cc1532015-03-31 18:34:11 +01001001 hdmi_phy_i2c_write(hdmi, phy_config->term, 0x19); /* TXTERM */
1002 hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr, 0x09); /* CKSYMTXCTRL */
1003 hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr, 0x0E); /* VLEVCTRL */
Yakir Yang034705a2015-03-31 23:56:10 -04001004
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001005 /* REMOVE CLK TERM */
1006 hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */
1007
Russell King2fada102015-07-28 12:21:34 +01001008 dw_hdmi_phy_enable_powerdown(hdmi, false);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001009
1010 /* toggle TMDS enable */
Andy Yanb21f4b62014-12-05 14:26:31 +08001011 dw_hdmi_phy_enable_tmds(hdmi, 0);
1012 dw_hdmi_phy_enable_tmds(hdmi, 1);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001013
1014 /* gen2 tx power on */
Andy Yanb21f4b62014-12-05 14:26:31 +08001015 dw_hdmi_phy_gen2_txpwron(hdmi, 1);
1016 dw_hdmi_phy_gen2_pddq(hdmi, 0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001017
Andy Yan12b9f202015-01-07 15:48:27 +08001018 if (hdmi->dev_type == RK3288_HDMI)
Laurent Pinchartf4104e82017-01-17 10:29:02 +02001019 dw_hdmi_phy_enable_svsret(hdmi, 1);
Andy Yan12b9f202015-01-07 15:48:27 +08001020
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001021 /*Wait for PHY PLL lock */
1022 msec = 5;
1023 do {
1024 val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
1025 if (!val)
1026 break;
1027
1028 if (msec == 0) {
1029 dev_err(hdmi->dev, "PHY PLL not locked\n");
1030 return -ETIMEDOUT;
1031 }
1032
1033 udelay(1000);
1034 msec--;
1035 } while (1);
1036
1037 return 0;
1038}
1039
Andy Yanb21f4b62014-12-05 14:26:31 +08001040static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001041{
1042 int i, ret;
Russell King05b13422015-07-21 15:35:52 +01001043 bool cscon;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001044
1045 /*check csc whether needed activated in HDMI mode */
Russell King05b13422015-07-21 15:35:52 +01001046 cscon = hdmi->sink_is_hdmi && is_color_space_conversion(hdmi);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001047
1048 /* HDMI Phy spec says to do the phy initialization sequence twice */
1049 for (i = 0; i < 2; i++) {
Andy Yanb21f4b62014-12-05 14:26:31 +08001050 dw_hdmi_phy_sel_data_en_pol(hdmi, 1);
1051 dw_hdmi_phy_sel_interface_control(hdmi, 0);
1052 dw_hdmi_phy_enable_tmds(hdmi, 0);
Russell King2fada102015-07-28 12:21:34 +01001053 dw_hdmi_phy_enable_powerdown(hdmi, true);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001054
1055 /* Enable CSC */
Kieran Bingham1acc6bd2017-01-17 10:29:01 +02001056 ret = hdmi_phy_configure(hdmi, cscon);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001057 if (ret)
1058 return ret;
1059 }
1060
1061 hdmi->phy_enabled = true;
1062 return 0;
1063}
1064
Andy Yanb21f4b62014-12-05 14:26:31 +08001065static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001066{
Russell King812bc612013-11-04 12:42:02 +00001067 u8 de;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001068
1069 if (hdmi->hdmi_data.video_mode.mdataenablepolarity)
1070 de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH;
1071 else
1072 de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW;
1073
1074 /* disable rx detect */
Russell King812bc612013-11-04 12:42:02 +00001075 hdmi_modb(hdmi, HDMI_A_HDCPCFG0_RXDETECT_DISABLE,
1076 HDMI_A_HDCPCFG0_RXDETECT_MASK, HDMI_A_HDCPCFG0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001077
Russell King812bc612013-11-04 12:42:02 +00001078 hdmi_modb(hdmi, de, HDMI_A_VIDPOLCFG_DATAENPOL_MASK, HDMI_A_VIDPOLCFG);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001079
Russell King812bc612013-11-04 12:42:02 +00001080 hdmi_modb(hdmi, HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE,
1081 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001082}
1083
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001084static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001085{
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001086 struct hdmi_avi_infoframe frame;
1087 u8 val;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001088
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001089 /* Initialise info frame from DRM mode */
1090 drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001091
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001092 if (hdmi->hdmi_data.enc_out_format == YCBCR444)
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001093 frame.colorspace = HDMI_COLORSPACE_YUV444;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001094 else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001095 frame.colorspace = HDMI_COLORSPACE_YUV422;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001096 else
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001097 frame.colorspace = HDMI_COLORSPACE_RGB;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001098
1099 /* Set up colorimetry */
1100 if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001101 frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
Sachin Kamat5a819ed2014-01-28 10:33:16 +05301102 if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001103 frame.extended_colorimetry =
1104 HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
Sachin Kamat5a819ed2014-01-28 10:33:16 +05301105 else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001106 frame.extended_colorimetry =
1107 HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001108 } else if (hdmi->hdmi_data.enc_out_format != RGB) {
Russell Kingd083c312015-03-27 23:14:16 +00001109 frame.colorimetry = hdmi->hdmi_data.colorimetry;
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001110 frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001111 } else { /* Carries no data */
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001112 frame.colorimetry = HDMI_COLORIMETRY_NONE;
1113 frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001114 }
1115
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001116 frame.scan_mode = HDMI_SCAN_MODE_NONE;
1117
1118 /*
1119 * The Designware IP uses a different byte format from standard
1120 * AVI info frames, though generally the bits are in the correct
1121 * bytes.
1122 */
1123
1124 /*
Jose Abreub0118e72016-08-29 10:30:51 +01001125 * AVI data byte 1 differences: Colorspace in bits 0,1 rather than 5,6,
1126 * scan info in bits 4,5 rather than 0,1 and active aspect present in
1127 * bit 6 rather than 4.
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001128 */
Jose Abreub0118e72016-08-29 10:30:51 +01001129 val = (frame.scan_mode & 3) << 4 | (frame.colorspace & 3);
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001130 if (frame.active_aspect & 15)
1131 val |= HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT;
1132 if (frame.top_bar || frame.bottom_bar)
1133 val |= HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR;
1134 if (frame.left_bar || frame.right_bar)
1135 val |= HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR;
1136 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0);
1137
1138 /* AVI data byte 2 differences: none */
1139 val = ((frame.colorimetry & 0x3) << 6) |
1140 ((frame.picture_aspect & 0x3) << 4) |
1141 (frame.active_aspect & 0xf);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001142 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF1);
1143
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001144 /* AVI data byte 3 differences: none */
1145 val = ((frame.extended_colorimetry & 0x7) << 4) |
1146 ((frame.quantization_range & 0x3) << 2) |
1147 (frame.nups & 0x3);
1148 if (frame.itc)
1149 val |= HDMI_FC_AVICONF2_IT_CONTENT_VALID;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001150 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF2);
1151
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001152 /* AVI data byte 4 differences: none */
1153 val = frame.video_code & 0x7f;
1154 hdmi_writeb(hdmi, val, HDMI_FC_AVIVID);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001155
1156 /* AVI Data Byte 5- set up input and output pixel repetition */
1157 val = (((hdmi->hdmi_data.video_mode.mpixelrepetitioninput + 1) <<
1158 HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET) &
1159 HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK) |
1160 ((hdmi->hdmi_data.video_mode.mpixelrepetitionoutput <<
1161 HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET) &
1162 HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK);
1163 hdmi_writeb(hdmi, val, HDMI_FC_PRCONF);
1164
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001165 /*
1166 * AVI data byte 5 differences: content type in 0,1 rather than 4,5,
1167 * ycc range in bits 2,3 rather than 6,7
1168 */
1169 val = ((frame.ycc_quantization_range & 0x3) << 2) |
1170 (frame.content_type & 0x3);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001171 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF3);
1172
1173 /* AVI Data Bytes 6-13 */
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001174 hdmi_writeb(hdmi, frame.top_bar & 0xff, HDMI_FC_AVIETB0);
1175 hdmi_writeb(hdmi, (frame.top_bar >> 8) & 0xff, HDMI_FC_AVIETB1);
1176 hdmi_writeb(hdmi, frame.bottom_bar & 0xff, HDMI_FC_AVISBB0);
1177 hdmi_writeb(hdmi, (frame.bottom_bar >> 8) & 0xff, HDMI_FC_AVISBB1);
1178 hdmi_writeb(hdmi, frame.left_bar & 0xff, HDMI_FC_AVIELB0);
1179 hdmi_writeb(hdmi, (frame.left_bar >> 8) & 0xff, HDMI_FC_AVIELB1);
1180 hdmi_writeb(hdmi, frame.right_bar & 0xff, HDMI_FC_AVISRB0);
1181 hdmi_writeb(hdmi, (frame.right_bar >> 8) & 0xff, HDMI_FC_AVISRB1);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001182}
1183
Andy Yanb21f4b62014-12-05 14:26:31 +08001184static void hdmi_av_composer(struct dw_hdmi *hdmi,
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001185 const struct drm_display_mode *mode)
1186{
1187 u8 inv_val;
1188 struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
1189 int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
Russell Kinge80b9f42015-07-21 11:08:25 +01001190 unsigned int vdisplay;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001191
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001192 vmode->mpixelclock = mode->clock * 1000;
1193
1194 dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
1195
1196 /* Set up HDMI_FC_INVIDCONF */
1197 inv_val = (hdmi->hdmi_data.hdcp_enable ?
1198 HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
1199 HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
1200
Russell Kingb91eee82015-03-27 23:27:17 +00001201 inv_val |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001202 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
Russell Kingb91eee82015-03-27 23:27:17 +00001203 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001204
Russell Kingb91eee82015-03-27 23:27:17 +00001205 inv_val |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001206 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
Russell Kingb91eee82015-03-27 23:27:17 +00001207 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001208
1209 inv_val |= (vmode->mdataenablepolarity ?
1210 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
1211 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
1212
1213 if (hdmi->vic == 39)
1214 inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH;
1215 else
Russell Kingb91eee82015-03-27 23:27:17 +00001216 inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001217 HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH :
Russell Kingb91eee82015-03-27 23:27:17 +00001218 HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001219
Russell Kingb91eee82015-03-27 23:27:17 +00001220 inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001221 HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
Russell Kingb91eee82015-03-27 23:27:17 +00001222 HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001223
Russell King05b13422015-07-21 15:35:52 +01001224 inv_val |= hdmi->sink_is_hdmi ?
1225 HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
1226 HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001227
1228 hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF);
1229
Russell Kinge80b9f42015-07-21 11:08:25 +01001230 vdisplay = mode->vdisplay;
1231 vblank = mode->vtotal - mode->vdisplay;
1232 v_de_vs = mode->vsync_start - mode->vdisplay;
1233 vsync_len = mode->vsync_end - mode->vsync_start;
1234
1235 /*
1236 * When we're setting an interlaced mode, we need
1237 * to adjust the vertical timing to suit.
1238 */
1239 if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
1240 vdisplay /= 2;
1241 vblank /= 2;
1242 v_de_vs /= 2;
1243 vsync_len /= 2;
1244 }
1245
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001246 /* Set up horizontal active pixel width */
1247 hdmi_writeb(hdmi, mode->hdisplay >> 8, HDMI_FC_INHACTV1);
1248 hdmi_writeb(hdmi, mode->hdisplay, HDMI_FC_INHACTV0);
1249
1250 /* Set up vertical active lines */
Russell Kinge80b9f42015-07-21 11:08:25 +01001251 hdmi_writeb(hdmi, vdisplay >> 8, HDMI_FC_INVACTV1);
1252 hdmi_writeb(hdmi, vdisplay, HDMI_FC_INVACTV0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001253
1254 /* Set up horizontal blanking pixel region width */
1255 hblank = mode->htotal - mode->hdisplay;
1256 hdmi_writeb(hdmi, hblank >> 8, HDMI_FC_INHBLANK1);
1257 hdmi_writeb(hdmi, hblank, HDMI_FC_INHBLANK0);
1258
1259 /* Set up vertical blanking pixel region width */
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001260 hdmi_writeb(hdmi, vblank, HDMI_FC_INVBLANK);
1261
1262 /* Set up HSYNC active edge delay width (in pixel clks) */
1263 h_de_hs = mode->hsync_start - mode->hdisplay;
1264 hdmi_writeb(hdmi, h_de_hs >> 8, HDMI_FC_HSYNCINDELAY1);
1265 hdmi_writeb(hdmi, h_de_hs, HDMI_FC_HSYNCINDELAY0);
1266
1267 /* Set up VSYNC active edge delay (in lines) */
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001268 hdmi_writeb(hdmi, v_de_vs, HDMI_FC_VSYNCINDELAY);
1269
1270 /* Set up HSYNC active pulse width (in pixel clks) */
1271 hsync_len = mode->hsync_end - mode->hsync_start;
1272 hdmi_writeb(hdmi, hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1);
1273 hdmi_writeb(hdmi, hsync_len, HDMI_FC_HSYNCINWIDTH0);
1274
1275 /* Set up VSYNC active edge delay (in lines) */
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001276 hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH);
1277}
1278
Andy Yanb21f4b62014-12-05 14:26:31 +08001279static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001280{
1281 if (!hdmi->phy_enabled)
1282 return;
1283
Andy Yanb21f4b62014-12-05 14:26:31 +08001284 dw_hdmi_phy_enable_tmds(hdmi, 0);
Russell King2fada102015-07-28 12:21:34 +01001285 dw_hdmi_phy_enable_powerdown(hdmi, true);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001286
1287 hdmi->phy_enabled = false;
1288}
1289
1290/* HDMI Initialization Step B.4 */
Andy Yanb21f4b62014-12-05 14:26:31 +08001291static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001292{
1293 u8 clkdis;
1294
1295 /* control period minimum duration */
1296 hdmi_writeb(hdmi, 12, HDMI_FC_CTRLDUR);
1297 hdmi_writeb(hdmi, 32, HDMI_FC_EXCTRLDUR);
1298 hdmi_writeb(hdmi, 1, HDMI_FC_EXCTRLSPAC);
1299
1300 /* Set to fill TMDS data channels */
1301 hdmi_writeb(hdmi, 0x0B, HDMI_FC_CH0PREAM);
1302 hdmi_writeb(hdmi, 0x16, HDMI_FC_CH1PREAM);
1303 hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM);
1304
1305 /* Enable pixel clock and tmds data path */
1306 clkdis = 0x7F;
1307 clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
1308 hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
1309
1310 clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
1311 hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
1312
1313 /* Enable csc path */
1314 if (is_color_space_conversion(hdmi)) {
1315 clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
1316 hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
1317 }
1318}
1319
Andy Yanb21f4b62014-12-05 14:26:31 +08001320static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001321{
Russell King812bc612013-11-04 12:42:02 +00001322 hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001323}
1324
1325/* Workaround to clear the overflow condition */
Andy Yanb21f4b62014-12-05 14:26:31 +08001326static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001327{
Laurent Pinchartbe41fc52017-01-17 10:29:05 +02001328 unsigned int count;
1329 unsigned int i;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001330 u8 val;
1331
Laurent Pinchartbe41fc52017-01-17 10:29:05 +02001332 /*
1333 * Under some circumstances the Frame Composer arithmetic unit can miss
1334 * an FC register write due to being busy processing the previous one.
1335 * The issue can be worked around by issuing a TMDS software reset and
1336 * then write one of the FC registers several times.
1337 *
1338 * The number of iterations matters and depends on the HDMI TX revision
1339 * (and possibly on the platform). So far only i.MX6Q (v1.30a) and
1340 * i.MX6DL (v1.31a) have been identified as needing the workaround, with
1341 * 4 and 1 iterations respectively.
1342 */
1343
1344 switch (hdmi->version) {
1345 case 0x130a:
1346 count = 4;
1347 break;
1348 case 0x131a:
1349 count = 1;
1350 break;
1351 default:
1352 return;
1353 }
1354
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001355 /* TMDS software reset */
1356 hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
1357
1358 val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF);
Laurent Pinchartbe41fc52017-01-17 10:29:05 +02001359 for (i = 0; i < count; i++)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001360 hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
1361}
1362
Andy Yanb21f4b62014-12-05 14:26:31 +08001363static void hdmi_enable_overflow_interrupts(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001364{
1365 hdmi_writeb(hdmi, 0, HDMI_FC_MASK2);
1366 hdmi_writeb(hdmi, 0, HDMI_IH_MUTE_FC_STAT2);
1367}
1368
Andy Yanb21f4b62014-12-05 14:26:31 +08001369static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001370{
1371 hdmi_writeb(hdmi, HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK,
1372 HDMI_IH_MUTE_FC_STAT2);
1373}
1374
Andy Yanb21f4b62014-12-05 14:26:31 +08001375static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001376{
1377 int ret;
1378
1379 hdmi_disable_overflow_interrupts(hdmi);
1380
1381 hdmi->vic = drm_match_cea_mode(mode);
1382
1383 if (!hdmi->vic) {
1384 dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n");
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001385 } else {
1386 dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001387 }
1388
1389 if ((hdmi->vic == 6) || (hdmi->vic == 7) ||
Andy Yanb5878332014-12-05 14:23:52 +08001390 (hdmi->vic == 21) || (hdmi->vic == 22) ||
1391 (hdmi->vic == 2) || (hdmi->vic == 3) ||
1392 (hdmi->vic == 17) || (hdmi->vic == 18))
Sachin Kamat5a819ed2014-01-28 10:33:16 +05301393 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001394 else
Sachin Kamat5a819ed2014-01-28 10:33:16 +05301395 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001396
Russell Kingd10ca822015-07-21 11:25:00 +01001397 hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001398 hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
1399
1400 /* TODO: Get input format from IPU (via FB driver interface) */
1401 hdmi->hdmi_data.enc_in_format = RGB;
1402
1403 hdmi->hdmi_data.enc_out_format = RGB;
1404
1405 hdmi->hdmi_data.enc_color_depth = 8;
1406 hdmi->hdmi_data.pix_repet_factor = 0;
1407 hdmi->hdmi_data.hdcp_enable = 0;
1408 hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
1409
1410 /* HDMI Initialization Step B.1 */
1411 hdmi_av_composer(hdmi, mode);
1412
1413 /* HDMI Initializateion Step B.2 */
Andy Yanb21f4b62014-12-05 14:26:31 +08001414 ret = dw_hdmi_phy_init(hdmi);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001415 if (ret)
1416 return ret;
1417
1418 /* HDMI Initialization Step B.3 */
Andy Yanb21f4b62014-12-05 14:26:31 +08001419 dw_hdmi_enable_video_path(hdmi);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001420
Russell Kingf709ec02015-07-21 16:09:39 +01001421 if (hdmi->sink_has_audio) {
1422 dev_dbg(hdmi->dev, "sink has audio support\n");
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001423
1424 /* HDMI Initialization Step E - Configure audio */
1425 hdmi_clk_regenerator_update_pixel_clock(hdmi);
1426 hdmi_enable_audio_clk(hdmi);
Russell Kingf709ec02015-07-21 16:09:39 +01001427 }
1428
1429 /* not for DVI mode */
1430 if (hdmi->sink_is_hdmi) {
1431 dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001432
1433 /* HDMI Initialization Step F - Configure AVI InfoFrame */
Russell Kingd4ac4cb2015-03-27 20:06:50 +00001434 hdmi_config_AVI(hdmi, mode);
Russell King05b13422015-07-21 15:35:52 +01001435 } else {
1436 dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001437 }
1438
1439 hdmi_video_packetize(hdmi);
1440 hdmi_video_csc(hdmi);
1441 hdmi_video_sample(hdmi);
1442 hdmi_tx_hdcp_config(hdmi);
1443
Andy Yanb21f4b62014-12-05 14:26:31 +08001444 dw_hdmi_clear_overflow(hdmi);
Russell King05b13422015-07-21 15:35:52 +01001445 if (hdmi->cable_plugin && hdmi->sink_is_hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001446 hdmi_enable_overflow_interrupts(hdmi);
1447
1448 return 0;
1449}
1450
1451/* Wait until we are registered to enable interrupts */
Andy Yanb21f4b62014-12-05 14:26:31 +08001452static int dw_hdmi_fb_registered(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001453{
1454 hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
1455 HDMI_PHY_I2CM_INT_ADDR);
1456
1457 hdmi_writeb(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
1458 HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
1459 HDMI_PHY_I2CM_CTLINT_ADDR);
1460
1461 /* enable cable hot plug irq */
Russell Kingaeac23b2015-06-05 13:46:22 +01001462 hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001463
1464 /* Clear Hotplug interrupts */
Russell Kingaeac23b2015-06-05 13:46:22 +01001465 hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
1466 HDMI_IH_PHY_STAT0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001467
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001468 return 0;
1469}
1470
Andy Yanb21f4b62014-12-05 14:26:31 +08001471static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001472{
1473 u8 ih_mute;
1474
1475 /*
1476 * Boot up defaults are:
1477 * HDMI_IH_MUTE = 0x03 (disabled)
1478 * HDMI_IH_MUTE_* = 0x00 (enabled)
1479 *
1480 * Disable top level interrupt bits in HDMI block
1481 */
1482 ih_mute = hdmi_readb(hdmi, HDMI_IH_MUTE) |
1483 HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
1484 HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
1485
1486 hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
1487
1488 /* by default mask all interrupts */
1489 hdmi_writeb(hdmi, 0xff, HDMI_VP_MASK);
1490 hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK0);
1491 hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK1);
1492 hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK2);
1493 hdmi_writeb(hdmi, 0xff, HDMI_PHY_MASK0);
1494 hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_INT_ADDR);
1495 hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_CTLINT_ADDR);
1496 hdmi_writeb(hdmi, 0xff, HDMI_AUD_INT);
1497 hdmi_writeb(hdmi, 0xff, HDMI_AUD_SPDIFINT);
1498 hdmi_writeb(hdmi, 0xff, HDMI_AUD_HBR_MASK);
1499 hdmi_writeb(hdmi, 0xff, HDMI_GP_MASK);
1500 hdmi_writeb(hdmi, 0xff, HDMI_A_APIINTMSK);
1501 hdmi_writeb(hdmi, 0xff, HDMI_CEC_MASK);
1502 hdmi_writeb(hdmi, 0xff, HDMI_I2CM_INT);
1503 hdmi_writeb(hdmi, 0xff, HDMI_I2CM_CTLINT);
1504
1505 /* Disable interrupts in the IH_MUTE_* registers */
1506 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT0);
1507 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT1);
1508 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT2);
1509 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AS_STAT0);
1510 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_PHY_STAT0);
1511 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CM_STAT0);
1512 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_CEC_STAT0);
1513 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_VP_STAT0);
1514 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CMPHY_STAT0);
1515 hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
1516
1517 /* Enable top level interrupt bits in HDMI block */
1518 ih_mute &= ~(HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
1519 HDMI_IH_MUTE_MUTE_ALL_INTERRUPT);
1520 hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
1521}
1522
Andy Yanb21f4b62014-12-05 14:26:31 +08001523static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001524{
Russell King381f05a2015-06-05 15:25:08 +01001525 hdmi->bridge_is_on = true;
Andy Yanb21f4b62014-12-05 14:26:31 +08001526 dw_hdmi_setup(hdmi, &hdmi->previous_mode);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001527}
1528
Andy Yanb21f4b62014-12-05 14:26:31 +08001529static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001530{
Andy Yanb21f4b62014-12-05 14:26:31 +08001531 dw_hdmi_phy_disable(hdmi);
Russell King381f05a2015-06-05 15:25:08 +01001532 hdmi->bridge_is_on = false;
1533}
1534
1535static void dw_hdmi_update_power(struct dw_hdmi *hdmi)
1536{
1537 int force = hdmi->force;
1538
1539 if (hdmi->disabled) {
1540 force = DRM_FORCE_OFF;
1541 } else if (force == DRM_FORCE_UNSPECIFIED) {
Russell Kingaeac23b2015-06-05 13:46:22 +01001542 if (hdmi->rxsense)
Russell King381f05a2015-06-05 15:25:08 +01001543 force = DRM_FORCE_ON;
1544 else
1545 force = DRM_FORCE_OFF;
1546 }
1547
1548 if (force == DRM_FORCE_OFF) {
1549 if (hdmi->bridge_is_on)
1550 dw_hdmi_poweroff(hdmi);
1551 } else {
1552 if (!hdmi->bridge_is_on)
1553 dw_hdmi_poweron(hdmi);
1554 }
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001555}
1556
Russell Kingaeac23b2015-06-05 13:46:22 +01001557/*
1558 * Adjust the detection of RXSENSE according to whether we have a forced
1559 * connection mode enabled, or whether we have been disabled. There is
1560 * no point processing RXSENSE interrupts if we have a forced connection
1561 * state, or DRM has us disabled.
1562 *
1563 * We also disable rxsense interrupts when we think we're disconnected
1564 * to avoid floating TDMS signals giving false rxsense interrupts.
1565 *
1566 * Note: we still need to listen for HPD interrupts even when DRM has us
1567 * disabled so that we can detect a connect event.
1568 */
1569static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
1570{
1571 u8 old_mask = hdmi->phy_mask;
1572
1573 if (hdmi->force || hdmi->disabled || !hdmi->rxsense)
1574 hdmi->phy_mask |= HDMI_PHY_RX_SENSE;
1575 else
1576 hdmi->phy_mask &= ~HDMI_PHY_RX_SENSE;
1577
1578 if (old_mask != hdmi->phy_mask)
1579 hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0);
1580}
1581
Andy Yanb21f4b62014-12-05 14:26:31 +08001582static enum drm_connector_status
1583dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001584{
Andy Yanb21f4b62014-12-05 14:26:31 +08001585 struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
Russell Kingd94905e2013-11-03 22:23:24 +00001586 connector);
Russell King98dbead2014-04-18 10:46:45 +01001587
Russell King381f05a2015-06-05 15:25:08 +01001588 mutex_lock(&hdmi->mutex);
1589 hdmi->force = DRM_FORCE_UNSPECIFIED;
1590 dw_hdmi_update_power(hdmi);
Russell Kingaeac23b2015-06-05 13:46:22 +01001591 dw_hdmi_update_phy_mask(hdmi);
Russell King381f05a2015-06-05 15:25:08 +01001592 mutex_unlock(&hdmi->mutex);
1593
Russell King98dbead2014-04-18 10:46:45 +01001594 return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
1595 connector_status_connected : connector_status_disconnected;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001596}
1597
Andy Yanb21f4b62014-12-05 14:26:31 +08001598static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001599{
Andy Yanb21f4b62014-12-05 14:26:31 +08001600 struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001601 connector);
1602 struct edid *edid;
Doug Anderson6c7e66e2015-06-04 11:04:36 -07001603 int ret = 0;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001604
1605 if (!hdmi->ddc)
1606 return 0;
1607
1608 edid = drm_get_edid(connector, hdmi->ddc);
1609 if (edid) {
1610 dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
1611 edid->width_cm, edid->height_cm);
1612
Russell King05b13422015-07-21 15:35:52 +01001613 hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
Russell Kingf709ec02015-07-21 16:09:39 +01001614 hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001615 drm_mode_connector_update_edid_property(connector, edid);
1616 ret = drm_add_edid_modes(connector, edid);
Russell Kingf5ce4052013-11-07 16:06:01 +00001617 /* Store the ELD */
1618 drm_edid_to_eld(connector, edid);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001619 kfree(edid);
1620 } else {
1621 dev_dbg(hdmi->dev, "failed to get edid\n");
1622 }
1623
Doug Anderson6c7e66e2015-06-04 11:04:36 -07001624 return ret;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001625}
1626
Andy Yan632d0352014-12-05 14:30:21 +08001627static enum drm_mode_status
1628dw_hdmi_connector_mode_valid(struct drm_connector *connector,
1629 struct drm_display_mode *mode)
1630{
1631 struct dw_hdmi *hdmi = container_of(connector,
1632 struct dw_hdmi, connector);
1633 enum drm_mode_status mode_status = MODE_OK;
1634
Russell King8add4192015-07-22 11:14:00 +01001635 /* We don't support double-clocked modes */
1636 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
1637 return MODE_BAD;
1638
Andy Yan632d0352014-12-05 14:30:21 +08001639 if (hdmi->plat_data->mode_valid)
1640 mode_status = hdmi->plat_data->mode_valid(connector, mode);
1641
1642 return mode_status;
1643}
1644
Russell King381f05a2015-06-05 15:25:08 +01001645static void dw_hdmi_connector_force(struct drm_connector *connector)
1646{
1647 struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
1648 connector);
1649
1650 mutex_lock(&hdmi->mutex);
1651 hdmi->force = connector->force;
1652 dw_hdmi_update_power(hdmi);
Russell Kingaeac23b2015-06-05 13:46:22 +01001653 dw_hdmi_update_phy_mask(hdmi);
Russell King381f05a2015-06-05 15:25:08 +01001654 mutex_unlock(&hdmi->mutex);
1655}
1656
Ville Syrjälädae91e42015-12-15 12:21:02 +01001657static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
Mark Yao2c5b2cc2015-11-30 18:33:40 +08001658 .dpms = drm_atomic_helper_connector_dpms,
1659 .fill_modes = drm_helper_probe_single_connector_modes,
1660 .detect = dw_hdmi_connector_detect,
Marek Vasutfdd83262016-10-05 16:31:33 +02001661 .destroy = drm_connector_cleanup,
Mark Yao2c5b2cc2015-11-30 18:33:40 +08001662 .force = dw_hdmi_connector_force,
1663 .reset = drm_atomic_helper_connector_reset,
1664 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1665 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1666};
1667
Ville Syrjälädae91e42015-12-15 12:21:02 +01001668static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
Andy Yanb21f4b62014-12-05 14:26:31 +08001669 .get_modes = dw_hdmi_connector_get_modes,
Andy Yan632d0352014-12-05 14:30:21 +08001670 .mode_valid = dw_hdmi_connector_mode_valid,
Boris Brezillonc2a441f2016-06-07 13:48:15 +02001671 .best_encoder = drm_atomic_helper_best_encoder,
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001672};
1673
Laurent Pinchartd2ae94a2017-01-17 10:28:59 +02001674static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
1675{
1676 struct dw_hdmi *hdmi = bridge->driver_private;
1677 struct drm_encoder *encoder = bridge->encoder;
1678 struct drm_connector *connector = &hdmi->connector;
1679
1680 connector->interlace_allowed = 1;
1681 connector->polled = DRM_CONNECTOR_POLL_HPD;
1682
1683 drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs);
1684
1685 drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs,
1686 DRM_MODE_CONNECTOR_HDMIA);
1687
1688 drm_mode_connector_attach_encoder(connector, encoder);
1689
1690 return 0;
1691}
1692
Laurent Pinchartfd30b382017-01-17 10:28:58 +02001693static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
1694 struct drm_display_mode *orig_mode,
1695 struct drm_display_mode *mode)
1696{
1697 struct dw_hdmi *hdmi = bridge->driver_private;
1698
1699 mutex_lock(&hdmi->mutex);
1700
1701 /* Store the display mode for plugin/DKMS poweron events */
1702 memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
1703
1704 mutex_unlock(&hdmi->mutex);
1705}
1706
1707static void dw_hdmi_bridge_disable(struct drm_bridge *bridge)
1708{
1709 struct dw_hdmi *hdmi = bridge->driver_private;
1710
1711 mutex_lock(&hdmi->mutex);
1712 hdmi->disabled = true;
1713 dw_hdmi_update_power(hdmi);
1714 dw_hdmi_update_phy_mask(hdmi);
1715 mutex_unlock(&hdmi->mutex);
1716}
1717
1718static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
1719{
1720 struct dw_hdmi *hdmi = bridge->driver_private;
1721
1722 mutex_lock(&hdmi->mutex);
1723 hdmi->disabled = false;
1724 dw_hdmi_update_power(hdmi);
1725 dw_hdmi_update_phy_mask(hdmi);
1726 mutex_unlock(&hdmi->mutex);
1727}
1728
Ville Syrjälädae91e42015-12-15 12:21:02 +01001729static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
Laurent Pinchartd2ae94a2017-01-17 10:28:59 +02001730 .attach = dw_hdmi_bridge_attach,
Andy Yanb21f4b62014-12-05 14:26:31 +08001731 .enable = dw_hdmi_bridge_enable,
1732 .disable = dw_hdmi_bridge_disable,
Andy Yanb21f4b62014-12-05 14:26:31 +08001733 .mode_set = dw_hdmi_bridge_mode_set,
Andy Yan3d1b35a2014-12-05 14:25:05 +08001734};
1735
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +03001736static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi)
1737{
1738 struct dw_hdmi_i2c *i2c = hdmi->i2c;
1739 unsigned int stat;
1740
1741 stat = hdmi_readb(hdmi, HDMI_IH_I2CM_STAT0);
1742 if (!stat)
1743 return IRQ_NONE;
1744
1745 hdmi_writeb(hdmi, stat, HDMI_IH_I2CM_STAT0);
1746
1747 i2c->stat = stat;
1748
1749 complete(&i2c->cmp);
1750
1751 return IRQ_HANDLED;
1752}
1753
Andy Yanb21f4b62014-12-05 14:26:31 +08001754static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
Russell Kingd94905e2013-11-03 22:23:24 +00001755{
Andy Yanb21f4b62014-12-05 14:26:31 +08001756 struct dw_hdmi *hdmi = dev_id;
Russell Kingd94905e2013-11-03 22:23:24 +00001757 u8 intr_stat;
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +03001758 irqreturn_t ret = IRQ_NONE;
1759
1760 if (hdmi->i2c)
1761 ret = dw_hdmi_i2c_irq(hdmi);
Russell Kingd94905e2013-11-03 22:23:24 +00001762
1763 intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +03001764 if (intr_stat) {
Russell Kingd94905e2013-11-03 22:23:24 +00001765 hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +03001766 return IRQ_WAKE_THREAD;
1767 }
Russell Kingd94905e2013-11-03 22:23:24 +00001768
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +03001769 return ret;
Russell Kingd94905e2013-11-03 22:23:24 +00001770}
1771
Andy Yanb21f4b62014-12-05 14:26:31 +08001772static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001773{
Andy Yanb21f4b62014-12-05 14:26:31 +08001774 struct dw_hdmi *hdmi = dev_id;
Russell Kingaeac23b2015-06-05 13:46:22 +01001775 u8 intr_stat, phy_int_pol, phy_pol_mask, phy_stat;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001776
1777 intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001778 phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0);
Russell Kingaeac23b2015-06-05 13:46:22 +01001779 phy_stat = hdmi_readb(hdmi, HDMI_PHY_STAT0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001780
Russell Kingaeac23b2015-06-05 13:46:22 +01001781 phy_pol_mask = 0;
1782 if (intr_stat & HDMI_IH_PHY_STAT0_HPD)
1783 phy_pol_mask |= HDMI_PHY_HPD;
1784 if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE0)
1785 phy_pol_mask |= HDMI_PHY_RX_SENSE0;
1786 if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE1)
1787 phy_pol_mask |= HDMI_PHY_RX_SENSE1;
1788 if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE2)
1789 phy_pol_mask |= HDMI_PHY_RX_SENSE2;
1790 if (intr_stat & HDMI_IH_PHY_STAT0_RX_SENSE3)
1791 phy_pol_mask |= HDMI_PHY_RX_SENSE3;
1792
1793 if (phy_pol_mask)
1794 hdmi_modb(hdmi, ~phy_int_pol, phy_pol_mask, HDMI_PHY_POL0);
1795
1796 /*
1797 * RX sense tells us whether the TDMS transmitters are detecting
1798 * load - in other words, there's something listening on the
1799 * other end of the link. Use this to decide whether we should
1800 * power on the phy as HPD may be toggled by the sink to merely
1801 * ask the source to re-read the EDID.
1802 */
1803 if (intr_stat &
1804 (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) {
Russell Kingb872a8e2015-06-05 12:22:46 +01001805 mutex_lock(&hdmi->mutex);
Russell Kingaeac23b2015-06-05 13:46:22 +01001806 if (!hdmi->disabled && !hdmi->force) {
1807 /*
1808 * If the RX sense status indicates we're disconnected,
1809 * clear the software rxsense status.
1810 */
1811 if (!(phy_stat & HDMI_PHY_RX_SENSE))
1812 hdmi->rxsense = false;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001813
Russell Kingaeac23b2015-06-05 13:46:22 +01001814 /*
1815 * Only set the software rxsense status when both
1816 * rxsense and hpd indicates we're connected.
1817 * This avoids what seems to be bad behaviour in
1818 * at least iMX6S versions of the phy.
1819 */
1820 if (phy_stat & HDMI_PHY_HPD)
1821 hdmi->rxsense = true;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001822
Russell Kingaeac23b2015-06-05 13:46:22 +01001823 dw_hdmi_update_power(hdmi);
1824 dw_hdmi_update_phy_mask(hdmi);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001825 }
Russell Kingb872a8e2015-06-05 12:22:46 +01001826 mutex_unlock(&hdmi->mutex);
Russell Kingaeac23b2015-06-05 13:46:22 +01001827 }
1828
1829 if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
1830 dev_dbg(hdmi->dev, "EVENT=%s\n",
1831 phy_int_pol & HDMI_PHY_HPD ? "plugin" : "plugout");
Laurent Pinchartba5d7e62017-01-17 10:28:56 +02001832 if (hdmi->bridge.dev)
1833 drm_helper_hpd_irq_event(hdmi->bridge.dev);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001834 }
1835
1836 hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
Russell Kingaeac23b2015-06-05 13:46:22 +01001837 hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
1838 HDMI_IH_MUTE_PHY_STAT0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001839
1840 return IRQ_HANDLED;
1841}
1842
Laurent Pinchart69497eb2017-01-17 10:29:00 +02001843static struct dw_hdmi *
1844__dw_hdmi_probe(struct platform_device *pdev,
1845 const struct dw_hdmi_plat_data *plat_data)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001846{
Laurent Pinchartc6081192017-01-17 10:28:57 +02001847 struct device *dev = &pdev->dev;
Russell King17b50012013-11-03 11:23:34 +00001848 struct device_node *np = dev->of_node;
Russell King7ed6c662013-11-07 16:01:45 +00001849 struct platform_device_info pdevinfo;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001850 struct device_node *ddc_node;
Andy Yanb21f4b62014-12-05 14:26:31 +08001851 struct dw_hdmi *hdmi;
Laurent Pinchartc6081192017-01-17 10:28:57 +02001852 struct resource *iores;
1853 int irq;
Andy Yan3d1b35a2014-12-05 14:25:05 +08001854 int ret;
Andy Yan0cd9d142014-12-05 14:28:24 +08001855 u32 val = 1;
Laurent Pinchart0527e122017-01-17 10:29:03 +02001856 u8 prod_id0;
1857 u8 prod_id1;
Kuninori Morimoto2761ba62016-11-08 01:00:57 +00001858 u8 config0;
Laurent Pinchart0c674942017-01-17 10:29:04 +02001859 u8 config3;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001860
Russell King17b50012013-11-03 11:23:34 +00001861 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001862 if (!hdmi)
Laurent Pinchart69497eb2017-01-17 10:29:00 +02001863 return ERR_PTR(-ENOMEM);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001864
Andy Yan3d1b35a2014-12-05 14:25:05 +08001865 hdmi->plat_data = plat_data;
Russell King17b50012013-11-03 11:23:34 +00001866 hdmi->dev = dev;
Andy Yan3d1b35a2014-12-05 14:25:05 +08001867 hdmi->dev_type = plat_data->dev_type;
Russell King40678382013-11-07 15:35:06 +00001868 hdmi->sample_rate = 48000;
Russell Kingb872a8e2015-06-05 12:22:46 +01001869 hdmi->disabled = true;
Russell Kingaeac23b2015-06-05 13:46:22 +01001870 hdmi->rxsense = true;
1871 hdmi->phy_mask = (u8)~(HDMI_PHY_HPD | HDMI_PHY_RX_SENSE);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001872
Russell Kingb872a8e2015-06-05 12:22:46 +01001873 mutex_init(&hdmi->mutex);
Russell King6bcf4952015-02-02 11:01:08 +00001874 mutex_init(&hdmi->audio_mutex);
Russell Kingb90120a2015-03-27 12:59:58 +00001875 spin_lock_init(&hdmi->audio_lock);
Russell King6bcf4952015-02-02 11:01:08 +00001876
Andy Yan0cd9d142014-12-05 14:28:24 +08001877 of_property_read_u32(np, "reg-io-width", &val);
1878
1879 switch (val) {
1880 case 4:
1881 hdmi->write = dw_hdmi_writel;
1882 hdmi->read = dw_hdmi_readl;
1883 break;
1884 case 1:
1885 hdmi->write = dw_hdmi_writeb;
1886 hdmi->read = dw_hdmi_readb;
1887 break;
1888 default:
1889 dev_err(dev, "reg-io-width must be 1 or 4\n");
Laurent Pinchart69497eb2017-01-17 10:29:00 +02001890 return ERR_PTR(-EINVAL);
Andy Yan0cd9d142014-12-05 14:28:24 +08001891 }
1892
Philipp Zabelb5d45902014-03-05 10:20:56 +01001893 ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001894 if (ddc_node) {
Vladimir Zapolskiy9f04a1f2016-08-16 23:26:43 +03001895 hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001896 of_node_put(ddc_node);
Andy Yanc2c38482014-12-05 14:24:28 +08001897 if (!hdmi->ddc) {
1898 dev_dbg(hdmi->dev, "failed to read ddc node\n");
Laurent Pinchart69497eb2017-01-17 10:29:00 +02001899 return ERR_PTR(-EPROBE_DEFER);
Andy Yanc2c38482014-12-05 14:24:28 +08001900 }
1901
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001902 } else {
1903 dev_dbg(hdmi->dev, "no ddc property found\n");
1904 }
1905
Laurent Pinchartc6081192017-01-17 10:28:57 +02001906 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Russell King17b50012013-11-03 11:23:34 +00001907 hdmi->regs = devm_ioremap_resource(dev, iores);
Vladimir Zapolskiy9f04a1f2016-08-16 23:26:43 +03001908 if (IS_ERR(hdmi->regs)) {
1909 ret = PTR_ERR(hdmi->regs);
1910 goto err_res;
1911 }
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001912
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001913 hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
1914 if (IS_ERR(hdmi->isfr_clk)) {
1915 ret = PTR_ERR(hdmi->isfr_clk);
Andy Yanb5878332014-12-05 14:23:52 +08001916 dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret);
Vladimir Zapolskiy9f04a1f2016-08-16 23:26:43 +03001917 goto err_res;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001918 }
1919
1920 ret = clk_prepare_enable(hdmi->isfr_clk);
1921 if (ret) {
Andy Yanb5878332014-12-05 14:23:52 +08001922 dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret);
Vladimir Zapolskiy9f04a1f2016-08-16 23:26:43 +03001923 goto err_res;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001924 }
1925
1926 hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb");
1927 if (IS_ERR(hdmi->iahb_clk)) {
1928 ret = PTR_ERR(hdmi->iahb_clk);
Andy Yanb5878332014-12-05 14:23:52 +08001929 dev_err(hdmi->dev, "Unable to get HDMI iahb clk: %d\n", ret);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001930 goto err_isfr;
1931 }
1932
1933 ret = clk_prepare_enable(hdmi->iahb_clk);
1934 if (ret) {
Andy Yanb5878332014-12-05 14:23:52 +08001935 dev_err(hdmi->dev, "Cannot enable HDMI iahb clock: %d\n", ret);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001936 goto err_isfr;
1937 }
1938
1939 /* Product and revision IDs */
Laurent Pinchartbe41fc52017-01-17 10:29:05 +02001940 hdmi->version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
1941 | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
Laurent Pinchart0527e122017-01-17 10:29:03 +02001942 prod_id0 = hdmi_readb(hdmi, HDMI_PRODUCT_ID0);
1943 prod_id1 = hdmi_readb(hdmi, HDMI_PRODUCT_ID1);
1944
1945 if (prod_id0 != HDMI_PRODUCT_ID0_HDMI_TX ||
1946 (prod_id1 & ~HDMI_PRODUCT_ID1_HDCP) != HDMI_PRODUCT_ID1_HDMI_TX) {
1947 dev_err(dev, "Unsupported HDMI controller (%04x:%02x:%02x)\n",
Laurent Pinchartbe41fc52017-01-17 10:29:05 +02001948 hdmi->version, prod_id0, prod_id1);
Laurent Pinchart0527e122017-01-17 10:29:03 +02001949 ret = -ENODEV;
1950 goto err_iahb;
1951 }
1952
1953 dev_info(dev, "Detected HDMI TX controller v%x.%03x %s HDCP\n",
Laurent Pinchartbe41fc52017-01-17 10:29:05 +02001954 hdmi->version >> 12, hdmi->version & 0xfff,
Laurent Pinchart0527e122017-01-17 10:29:03 +02001955 prod_id1 & HDMI_PRODUCT_ID1_HDCP ? "with" : "without");
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001956
1957 initialize_hdmi_ih_mutes(hdmi);
1958
Laurent Pinchartc6081192017-01-17 10:28:57 +02001959 irq = platform_get_irq(pdev, 0);
Laurent Pinchart69497eb2017-01-17 10:29:00 +02001960 if (irq < 0) {
1961 ret = irq;
Laurent Pinchartc6081192017-01-17 10:28:57 +02001962 goto err_iahb;
Laurent Pinchart69497eb2017-01-17 10:29:00 +02001963 }
Laurent Pinchartc6081192017-01-17 10:28:57 +02001964
Philipp Zabel639a2022015-01-07 13:43:50 +01001965 ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
1966 dw_hdmi_irq, IRQF_SHARED,
1967 dev_name(dev), hdmi);
1968 if (ret)
Fabio Estevamb33ef612015-01-27 10:54:12 -02001969 goto err_iahb;
Philipp Zabel639a2022015-01-07 13:43:50 +01001970
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001971 /*
1972 * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
1973 * N and cts values before enabling phy
1974 */
1975 hdmi_init_clk_regenerator(hdmi);
1976
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +03001977 /* If DDC bus is not specified, try to register HDMI I2C bus */
1978 if (!hdmi->ddc) {
1979 hdmi->ddc = dw_hdmi_i2c_adapter(hdmi);
1980 if (IS_ERR(hdmi->ddc))
1981 hdmi->ddc = NULL;
1982 }
1983
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001984 /*
1985 * Configure registers related to HDMI interrupt
1986 * generation before registering IRQ.
1987 */
Russell Kingaeac23b2015-06-05 13:46:22 +01001988 hdmi_writeb(hdmi, HDMI_PHY_HPD | HDMI_PHY_RX_SENSE, HDMI_PHY_POL0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001989
1990 /* Clear Hotplug interrupts */
Russell Kingaeac23b2015-06-05 13:46:22 +01001991 hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
1992 HDMI_IH_PHY_STAT0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001993
Laurent Pinchart69497eb2017-01-17 10:29:00 +02001994 hdmi->bridge.driver_private = hdmi;
1995 hdmi->bridge.funcs = &dw_hdmi_bridge_funcs;
1996 hdmi->bridge.of_node = pdev->dev.of_node;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001997
Laurent Pinchart69497eb2017-01-17 10:29:00 +02001998 ret = dw_hdmi_fb_registered(hdmi);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02001999 if (ret)
2000 goto err_iahb;
2001
Russell Kingd94905e2013-11-03 22:23:24 +00002002 /* Unmute interrupts */
Russell Kingaeac23b2015-06-05 13:46:22 +01002003 hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
2004 HDMI_IH_MUTE_PHY_STAT0);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02002005
Russell King7ed6c662013-11-07 16:01:45 +00002006 memset(&pdevinfo, 0, sizeof(pdevinfo));
2007 pdevinfo.parent = dev;
2008 pdevinfo.id = PLATFORM_DEVID_AUTO;
2009
Kuninori Morimoto2761ba62016-11-08 01:00:57 +00002010 config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
Laurent Pinchart0c674942017-01-17 10:29:04 +02002011 config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
Kuninori Morimoto2761ba62016-11-08 01:00:57 +00002012
Laurent Pinchart0c674942017-01-17 10:29:04 +02002013 if (config3 & HDMI_CONFIG3_AHBAUDDMA) {
Kuninori Morimoto2761ba62016-11-08 01:00:57 +00002014 struct dw_hdmi_audio_data audio;
2015
Russell King7ed6c662013-11-07 16:01:45 +00002016 audio.phys = iores->start;
2017 audio.base = hdmi->regs;
2018 audio.irq = irq;
2019 audio.hdmi = hdmi;
Russell Kingf5ce4052013-11-07 16:06:01 +00002020 audio.eld = hdmi->connector.eld;
Russell King7ed6c662013-11-07 16:01:45 +00002021
2022 pdevinfo.name = "dw-hdmi-ahb-audio";
2023 pdevinfo.data = &audio;
2024 pdevinfo.size_data = sizeof(audio);
2025 pdevinfo.dma_mask = DMA_BIT_MASK(32);
2026 hdmi->audio = platform_device_register_full(&pdevinfo);
Kuninori Morimoto2761ba62016-11-08 01:00:57 +00002027 } else if (config0 & HDMI_CONFIG0_I2S) {
2028 struct dw_hdmi_i2s_audio_data audio;
2029
2030 audio.hdmi = hdmi;
2031 audio.write = hdmi_writeb;
2032 audio.read = hdmi_readb;
2033
2034 pdevinfo.name = "dw-hdmi-i2s-audio";
2035 pdevinfo.data = &audio;
2036 pdevinfo.size_data = sizeof(audio);
2037 pdevinfo.dma_mask = DMA_BIT_MASK(32);
2038 hdmi->audio = platform_device_register_full(&pdevinfo);
Russell King7ed6c662013-11-07 16:01:45 +00002039 }
2040
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +03002041 /* Reset HDMI DDC I2C master controller and mute I2CM interrupts */
2042 if (hdmi->i2c)
2043 dw_hdmi_i2c_init(hdmi);
2044
Laurent Pinchartc6081192017-01-17 10:28:57 +02002045 platform_set_drvdata(pdev, hdmi);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02002046
Laurent Pinchart69497eb2017-01-17 10:29:00 +02002047 return hdmi;
Fabio Estevam9aaf8802013-11-29 08:46:32 -02002048
2049err_iahb:
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +03002050 if (hdmi->i2c) {
2051 i2c_del_adapter(&hdmi->i2c->adap);
2052 hdmi->ddc = NULL;
2053 }
2054
Fabio Estevam9aaf8802013-11-29 08:46:32 -02002055 clk_disable_unprepare(hdmi->iahb_clk);
2056err_isfr:
2057 clk_disable_unprepare(hdmi->isfr_clk);
Vladimir Zapolskiy9f04a1f2016-08-16 23:26:43 +03002058err_res:
2059 i2c_put_adapter(hdmi->ddc);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02002060
Laurent Pinchart69497eb2017-01-17 10:29:00 +02002061 return ERR_PTR(ret);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02002062}
2063
Laurent Pinchart69497eb2017-01-17 10:29:00 +02002064static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
Fabio Estevam9aaf8802013-11-29 08:46:32 -02002065{
Russell King7ed6c662013-11-07 16:01:45 +00002066 if (hdmi->audio && !IS_ERR(hdmi->audio))
2067 platform_device_unregister(hdmi->audio);
2068
Russell Kingd94905e2013-11-03 22:23:24 +00002069 /* Disable all interrupts */
2070 hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
2071
Fabio Estevam9aaf8802013-11-29 08:46:32 -02002072 clk_disable_unprepare(hdmi->iahb_clk);
2073 clk_disable_unprepare(hdmi->isfr_clk);
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +03002074
2075 if (hdmi->i2c)
2076 i2c_del_adapter(&hdmi->i2c->adap);
2077 else
2078 i2c_put_adapter(hdmi->ddc);
Russell King17b50012013-11-03 11:23:34 +00002079}
Laurent Pinchart69497eb2017-01-17 10:29:00 +02002080
2081/* -----------------------------------------------------------------------------
2082 * Probe/remove API, used from platforms based on the DRM bridge API.
2083 */
2084int dw_hdmi_probe(struct platform_device *pdev,
2085 const struct dw_hdmi_plat_data *plat_data)
2086{
2087 struct dw_hdmi *hdmi;
2088 int ret;
2089
2090 hdmi = __dw_hdmi_probe(pdev, plat_data);
2091 if (IS_ERR(hdmi))
2092 return PTR_ERR(hdmi);
2093
2094 ret = drm_bridge_add(&hdmi->bridge);
2095 if (ret < 0) {
2096 __dw_hdmi_remove(hdmi);
2097 return ret;
2098 }
2099
2100 return 0;
2101}
2102EXPORT_SYMBOL_GPL(dw_hdmi_probe);
2103
2104void dw_hdmi_remove(struct platform_device *pdev)
2105{
2106 struct dw_hdmi *hdmi = platform_get_drvdata(pdev);
2107
2108 drm_bridge_remove(&hdmi->bridge);
2109
2110 __dw_hdmi_remove(hdmi);
2111}
2112EXPORT_SYMBOL_GPL(dw_hdmi_remove);
2113
2114/* -----------------------------------------------------------------------------
2115 * Bind/unbind API, used from platforms based on the component framework.
2116 */
2117int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder,
2118 const struct dw_hdmi_plat_data *plat_data)
2119{
2120 struct dw_hdmi *hdmi;
2121 int ret;
2122
2123 hdmi = __dw_hdmi_probe(pdev, plat_data);
2124 if (IS_ERR(hdmi))
2125 return PTR_ERR(hdmi);
2126
2127 ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL);
2128 if (ret) {
2129 dw_hdmi_remove(pdev);
2130 DRM_ERROR("Failed to initialize bridge with drm\n");
2131 return ret;
2132 }
2133
2134 return 0;
2135}
2136EXPORT_SYMBOL_GPL(dw_hdmi_bind);
2137
2138void dw_hdmi_unbind(struct device *dev)
2139{
2140 struct dw_hdmi *hdmi = dev_get_drvdata(dev);
2141
2142 __dw_hdmi_remove(hdmi);
2143}
Andy Yanb21f4b62014-12-05 14:26:31 +08002144EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
Fabio Estevam9aaf8802013-11-29 08:46:32 -02002145
2146MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
Andy Yan3d1b35a2014-12-05 14:25:05 +08002147MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
2148MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
Vladimir Zapolskiy3efc2fa2016-08-24 08:46:37 +03002149MODULE_AUTHOR("Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>");
Andy Yanb21f4b62014-12-05 14:26:31 +08002150MODULE_DESCRIPTION("DW HDMI transmitter driver");
Fabio Estevam9aaf8802013-11-29 08:46:32 -02002151MODULE_LICENSE("GPL");
Andy Yanb21f4b62014-12-05 14:26:31 +08002152MODULE_ALIAS("platform:dw-hdmi");