GNU Linux-libre 4.14.294-gnu1
[releases.git] / drivers / gpu / drm / msm / hdmi / hdmi_connector.c
1 /*
2  * Copyright (C) 2013 Red Hat
3  * Author: Rob Clark <robdclark@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published by
7  * the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <linux/gpio.h>
19 #include <linux/pinctrl/consumer.h>
20
21 #include "msm_kms.h"
22 #include "hdmi.h"
23
24 struct hdmi_connector {
25         struct drm_connector base;
26         struct hdmi *hdmi;
27         struct work_struct hpd_work;
28 };
29 #define to_hdmi_connector(x) container_of(x, struct hdmi_connector, base)
30
31 static void msm_hdmi_phy_reset(struct hdmi *hdmi)
32 {
33         unsigned int val;
34
35         val = hdmi_read(hdmi, REG_HDMI_PHY_CTRL);
36
37         if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
38                 /* pull low */
39                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
40                                 val & ~HDMI_PHY_CTRL_SW_RESET);
41         } else {
42                 /* pull high */
43                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
44                                 val | HDMI_PHY_CTRL_SW_RESET);
45         }
46
47         if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
48                 /* pull low */
49                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
50                                 val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
51         } else {
52                 /* pull high */
53                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
54                                 val | HDMI_PHY_CTRL_SW_RESET_PLL);
55         }
56
57         msleep(100);
58
59         if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
60                 /* pull high */
61                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
62                                 val | HDMI_PHY_CTRL_SW_RESET);
63         } else {
64                 /* pull low */
65                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
66                                 val & ~HDMI_PHY_CTRL_SW_RESET);
67         }
68
69         if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
70                 /* pull high */
71                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
72                                 val | HDMI_PHY_CTRL_SW_RESET_PLL);
73         } else {
74                 /* pull low */
75                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
76                                 val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
77         }
78 }
79
80 static int gpio_config(struct hdmi *hdmi, bool on)
81 {
82         struct device *dev = &hdmi->pdev->dev;
83         const struct hdmi_platform_config *config = hdmi->config;
84         int ret, i;
85
86         if (on) {
87                 for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
88                         struct hdmi_gpio_data gpio = config->gpios[i];
89
90                         if (gpio.num != -1) {
91                                 ret = gpio_request(gpio.num, gpio.label);
92                                 if (ret) {
93                                         dev_err(dev,
94                                                 "'%s'(%d) gpio_request failed: %d\n",
95                                                 gpio.label, gpio.num, ret);
96                                         goto err;
97                                 }
98
99                                 if (gpio.output) {
100                                         gpio_direction_output(gpio.num,
101                                                               gpio.value);
102                                 } else {
103                                         gpio_direction_input(gpio.num);
104                                         gpio_set_value_cansleep(gpio.num,
105                                                                 gpio.value);
106                                 }
107                         }
108                 }
109
110                 DBG("gpio on");
111         } else {
112                 for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
113                         struct hdmi_gpio_data gpio = config->gpios[i];
114
115                         if (gpio.num == -1)
116                                 continue;
117
118                         if (gpio.output) {
119                                 int value = gpio.value ? 0 : 1;
120
121                                 gpio_set_value_cansleep(gpio.num, value);
122                         }
123
124                         gpio_free(gpio.num);
125                 };
126
127                 DBG("gpio off");
128         }
129
130         return 0;
131 err:
132         while (i--) {
133                 if (config->gpios[i].num != -1)
134                         gpio_free(config->gpios[i].num);
135         }
136
137         return ret;
138 }
139
140 static void enable_hpd_clocks(struct hdmi *hdmi, bool enable)
141 {
142         const struct hdmi_platform_config *config = hdmi->config;
143         struct device *dev = &hdmi->pdev->dev;
144         int i, ret;
145
146         if (enable) {
147                 for (i = 0; i < config->hpd_clk_cnt; i++) {
148                         if (config->hpd_freq && config->hpd_freq[i]) {
149                                 ret = clk_set_rate(hdmi->hpd_clks[i],
150                                                    config->hpd_freq[i]);
151                                 if (ret)
152                                         dev_warn(dev,
153                                                  "failed to set clk %s (%d)\n",
154                                                  config->hpd_clk_names[i], ret);
155                         }
156
157                         ret = clk_prepare_enable(hdmi->hpd_clks[i]);
158                         if (ret) {
159                                 dev_err(dev,
160                                         "failed to enable hpd clk: %s (%d)\n",
161                                         config->hpd_clk_names[i], ret);
162                         }
163                 }
164         } else {
165                 for (i = config->hpd_clk_cnt - 1; i >= 0; i--)
166                         clk_disable_unprepare(hdmi->hpd_clks[i]);
167         }
168 }
169
170 static int hpd_enable(struct hdmi_connector *hdmi_connector)
171 {
172         struct hdmi *hdmi = hdmi_connector->hdmi;
173         const struct hdmi_platform_config *config = hdmi->config;
174         struct device *dev = &hdmi->pdev->dev;
175         uint32_t hpd_ctrl;
176         int i, ret;
177         unsigned long flags;
178
179         for (i = 0; i < config->hpd_reg_cnt; i++) {
180                 ret = regulator_enable(hdmi->hpd_regs[i]);
181                 if (ret) {
182                         dev_err(dev, "failed to enable hpd regulator: %s (%d)\n",
183                                         config->hpd_reg_names[i], ret);
184                         goto fail;
185                 }
186         }
187
188         ret = pinctrl_pm_select_default_state(dev);
189         if (ret) {
190                 dev_err(dev, "pinctrl state chg failed: %d\n", ret);
191                 goto fail;
192         }
193
194         ret = gpio_config(hdmi, true);
195         if (ret) {
196                 dev_err(dev, "failed to configure GPIOs: %d\n", ret);
197                 goto fail;
198         }
199
200         pm_runtime_get_sync(dev);
201         enable_hpd_clocks(hdmi, true);
202
203         msm_hdmi_set_mode(hdmi, false);
204         msm_hdmi_phy_reset(hdmi);
205         msm_hdmi_set_mode(hdmi, true);
206
207         hdmi_write(hdmi, REG_HDMI_USEC_REFTIMER, 0x0001001b);
208
209         /* enable HPD events: */
210         hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL,
211                         HDMI_HPD_INT_CTRL_INT_CONNECT |
212                         HDMI_HPD_INT_CTRL_INT_EN);
213
214         /* set timeout to 4.1ms (max) for hardware debounce */
215         spin_lock_irqsave(&hdmi->reg_lock, flags);
216         hpd_ctrl = hdmi_read(hdmi, REG_HDMI_HPD_CTRL);
217         hpd_ctrl |= HDMI_HPD_CTRL_TIMEOUT(0x1fff);
218
219         /* Toggle HPD circuit to trigger HPD sense */
220         hdmi_write(hdmi, REG_HDMI_HPD_CTRL,
221                         ~HDMI_HPD_CTRL_ENABLE & hpd_ctrl);
222         hdmi_write(hdmi, REG_HDMI_HPD_CTRL,
223                         HDMI_HPD_CTRL_ENABLE | hpd_ctrl);
224         spin_unlock_irqrestore(&hdmi->reg_lock, flags);
225
226         return 0;
227
228 fail:
229         return ret;
230 }
231
232 static void hdp_disable(struct hdmi_connector *hdmi_connector)
233 {
234         struct hdmi *hdmi = hdmi_connector->hdmi;
235         const struct hdmi_platform_config *config = hdmi->config;
236         struct device *dev = &hdmi->pdev->dev;
237         int i, ret = 0;
238
239         /* Disable HPD interrupt */
240         hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0);
241
242         msm_hdmi_set_mode(hdmi, false);
243
244         enable_hpd_clocks(hdmi, false);
245         pm_runtime_put_autosuspend(dev);
246
247         ret = gpio_config(hdmi, false);
248         if (ret)
249                 dev_warn(dev, "failed to unconfigure GPIOs: %d\n", ret);
250
251         ret = pinctrl_pm_select_sleep_state(dev);
252         if (ret)
253                 dev_warn(dev, "pinctrl state chg failed: %d\n", ret);
254
255         for (i = 0; i < config->hpd_reg_cnt; i++) {
256                 ret = regulator_disable(hdmi->hpd_regs[i]);
257                 if (ret)
258                         dev_warn(dev, "failed to disable hpd regulator: %s (%d)\n",
259                                         config->hpd_reg_names[i], ret);
260         }
261 }
262
263 static void
264 msm_hdmi_hotplug_work(struct work_struct *work)
265 {
266         struct hdmi_connector *hdmi_connector =
267                 container_of(work, struct hdmi_connector, hpd_work);
268         struct drm_connector *connector = &hdmi_connector->base;
269         drm_helper_hpd_irq_event(connector->dev);
270 }
271
272 void msm_hdmi_connector_irq(struct drm_connector *connector)
273 {
274         struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
275         struct hdmi *hdmi = hdmi_connector->hdmi;
276         uint32_t hpd_int_status, hpd_int_ctrl;
277
278         /* Process HPD: */
279         hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
280         hpd_int_ctrl   = hdmi_read(hdmi, REG_HDMI_HPD_INT_CTRL);
281
282         if ((hpd_int_ctrl & HDMI_HPD_INT_CTRL_INT_EN) &&
283                         (hpd_int_status & HDMI_HPD_INT_STATUS_INT)) {
284                 bool detected = !!(hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED);
285
286                 /* ack & disable (temporarily) HPD events: */
287                 hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL,
288                         HDMI_HPD_INT_CTRL_INT_ACK);
289
290                 DBG("status=%04x, ctrl=%04x", hpd_int_status, hpd_int_ctrl);
291
292                 /* detect disconnect if we are connected or visa versa: */
293                 hpd_int_ctrl = HDMI_HPD_INT_CTRL_INT_EN;
294                 if (!detected)
295                         hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
296                 hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
297
298                 queue_work(hdmi->workq, &hdmi_connector->hpd_work);
299         }
300 }
301
302 static enum drm_connector_status detect_reg(struct hdmi *hdmi)
303 {
304         uint32_t hpd_int_status;
305
306         pm_runtime_get_sync(&hdmi->pdev->dev);
307         enable_hpd_clocks(hdmi, true);
308
309         hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
310
311         enable_hpd_clocks(hdmi, false);
312         pm_runtime_put_autosuspend(&hdmi->pdev->dev);
313
314         return (hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED) ?
315                         connector_status_connected : connector_status_disconnected;
316 }
317
318 #define HPD_GPIO_INDEX  2
319 static enum drm_connector_status detect_gpio(struct hdmi *hdmi)
320 {
321         const struct hdmi_platform_config *config = hdmi->config;
322         struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
323
324         return gpio_get_value(hpd_gpio.num) ?
325                         connector_status_connected :
326                         connector_status_disconnected;
327 }
328
329 static enum drm_connector_status hdmi_connector_detect(
330                 struct drm_connector *connector, bool force)
331 {
332         struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
333         struct hdmi *hdmi = hdmi_connector->hdmi;
334         const struct hdmi_platform_config *config = hdmi->config;
335         struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
336         enum drm_connector_status stat_gpio, stat_reg;
337         int retry = 20;
338
339         /*
340          * some platforms may not have hpd gpio. Rely only on the status
341          * provided by REG_HDMI_HPD_INT_STATUS in this case.
342          */
343         if (hpd_gpio.num == -1)
344                 return detect_reg(hdmi);
345
346         do {
347                 stat_gpio = detect_gpio(hdmi);
348                 stat_reg  = detect_reg(hdmi);
349
350                 if (stat_gpio == stat_reg)
351                         break;
352
353                 mdelay(10);
354         } while (--retry);
355
356         /* the status we get from reading gpio seems to be more reliable,
357          * so trust that one the most if we didn't manage to get hdmi and
358          * gpio status to agree:
359          */
360         if (stat_gpio != stat_reg) {
361                 DBG("HDMI_HPD_INT_STATUS tells us: %d", stat_reg);
362                 DBG("hpd gpio tells us: %d", stat_gpio);
363         }
364
365         return stat_gpio;
366 }
367
368 static void hdmi_connector_destroy(struct drm_connector *connector)
369 {
370         struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
371
372         hdp_disable(hdmi_connector);
373
374         drm_connector_cleanup(connector);
375
376         kfree(hdmi_connector);
377 }
378
379 static int msm_hdmi_connector_get_modes(struct drm_connector *connector)
380 {
381         struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
382         struct hdmi *hdmi = hdmi_connector->hdmi;
383         struct edid *edid;
384         uint32_t hdmi_ctrl;
385         int ret = 0;
386
387         hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
388         hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
389
390         edid = drm_get_edid(connector, hdmi->i2c);
391
392         hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
393
394         hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
395         drm_mode_connector_update_edid_property(connector, edid);
396
397         if (edid) {
398                 ret = drm_add_edid_modes(connector, edid);
399                 kfree(edid);
400         }
401
402         return ret;
403 }
404
405 static int msm_hdmi_connector_mode_valid(struct drm_connector *connector,
406                                  struct drm_display_mode *mode)
407 {
408         struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
409         struct hdmi *hdmi = hdmi_connector->hdmi;
410         const struct hdmi_platform_config *config = hdmi->config;
411         struct msm_drm_private *priv = connector->dev->dev_private;
412         struct msm_kms *kms = priv->kms;
413         long actual, requested;
414
415         requested = 1000 * mode->clock;
416         actual = kms->funcs->round_pixclk(kms,
417                         requested, hdmi_connector->hdmi->encoder);
418
419         /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
420          * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
421          * instead):
422          */
423         if (config->pwr_clk_cnt > 0)
424                 actual = clk_round_rate(hdmi->pwr_clks[0], actual);
425
426         DBG("requested=%ld, actual=%ld", requested, actual);
427
428         if (actual != requested)
429                 return MODE_CLOCK_RANGE;
430
431         return 0;
432 }
433
434 static const struct drm_connector_funcs hdmi_connector_funcs = {
435         .detect = hdmi_connector_detect,
436         .fill_modes = drm_helper_probe_single_connector_modes,
437         .destroy = hdmi_connector_destroy,
438         .reset = drm_atomic_helper_connector_reset,
439         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
440         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
441 };
442
443 static const struct drm_connector_helper_funcs msm_hdmi_connector_helper_funcs = {
444         .get_modes = msm_hdmi_connector_get_modes,
445         .mode_valid = msm_hdmi_connector_mode_valid,
446 };
447
448 /* initialize connector */
449 struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
450 {
451         struct drm_connector *connector = NULL;
452         struct hdmi_connector *hdmi_connector;
453         int ret;
454
455         hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
456         if (!hdmi_connector)
457                 return ERR_PTR(-ENOMEM);
458
459         hdmi_connector->hdmi = hdmi;
460         INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);
461
462         connector = &hdmi_connector->base;
463
464         drm_connector_init(hdmi->dev, connector, &hdmi_connector_funcs,
465                         DRM_MODE_CONNECTOR_HDMIA);
466         drm_connector_helper_add(connector, &msm_hdmi_connector_helper_funcs);
467
468         connector->polled = DRM_CONNECTOR_POLL_CONNECT |
469                         DRM_CONNECTOR_POLL_DISCONNECT;
470
471         connector->interlace_allowed = 0;
472         connector->doublescan_allowed = 0;
473
474         ret = hpd_enable(hdmi_connector);
475         if (ret) {
476                 dev_err(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
477                 return ERR_PTR(ret);
478         }
479
480         drm_mode_connector_attach_encoder(connector, hdmi->encoder);
481
482         return connector;
483 }