Merge tag 'mac80211-for-davem-2016-07-06' of git://git.kernel.org/pub/scm/linux/kerne...
[cascardo/linux.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 int hpd_enable(struct hdmi_connector *hdmi_connector)
141 {
142         struct hdmi *hdmi = hdmi_connector->hdmi;
143         const struct hdmi_platform_config *config = hdmi->config;
144         struct device *dev = &hdmi->pdev->dev;
145         uint32_t hpd_ctrl;
146         int i, ret;
147         unsigned long flags;
148
149         for (i = 0; i < config->hpd_reg_cnt; i++) {
150                 ret = regulator_enable(hdmi->hpd_regs[i]);
151                 if (ret) {
152                         dev_err(dev, "failed to enable hpd regulator: %s (%d)\n",
153                                         config->hpd_reg_names[i], ret);
154                         goto fail;
155                 }
156         }
157
158         ret = pinctrl_pm_select_default_state(dev);
159         if (ret) {
160                 dev_err(dev, "pinctrl state chg failed: %d\n", ret);
161                 goto fail;
162         }
163
164         ret = gpio_config(hdmi, true);
165         if (ret) {
166                 dev_err(dev, "failed to configure GPIOs: %d\n", ret);
167                 goto fail;
168         }
169
170         for (i = 0; i < config->hpd_clk_cnt; i++) {
171                 if (config->hpd_freq && config->hpd_freq[i]) {
172                         ret = clk_set_rate(hdmi->hpd_clks[i],
173                                         config->hpd_freq[i]);
174                         if (ret)
175                                 dev_warn(dev, "failed to set clk %s (%d)\n",
176                                                 config->hpd_clk_names[i], ret);
177                 }
178
179                 ret = clk_prepare_enable(hdmi->hpd_clks[i]);
180                 if (ret) {
181                         dev_err(dev, "failed to enable hpd clk: %s (%d)\n",
182                                         config->hpd_clk_names[i], ret);
183                         goto fail;
184                 }
185         }
186
187         msm_hdmi_set_mode(hdmi, false);
188         msm_hdmi_phy_reset(hdmi);
189         msm_hdmi_set_mode(hdmi, true);
190
191         hdmi_write(hdmi, REG_HDMI_USEC_REFTIMER, 0x0001001b);
192
193         /* enable HPD events: */
194         hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL,
195                         HDMI_HPD_INT_CTRL_INT_CONNECT |
196                         HDMI_HPD_INT_CTRL_INT_EN);
197
198         /* set timeout to 4.1ms (max) for hardware debounce */
199         spin_lock_irqsave(&hdmi->reg_lock, flags);
200         hpd_ctrl = hdmi_read(hdmi, REG_HDMI_HPD_CTRL);
201         hpd_ctrl |= HDMI_HPD_CTRL_TIMEOUT(0x1fff);
202
203         /* Toggle HPD circuit to trigger HPD sense */
204         hdmi_write(hdmi, REG_HDMI_HPD_CTRL,
205                         ~HDMI_HPD_CTRL_ENABLE & hpd_ctrl);
206         hdmi_write(hdmi, REG_HDMI_HPD_CTRL,
207                         HDMI_HPD_CTRL_ENABLE | hpd_ctrl);
208         spin_unlock_irqrestore(&hdmi->reg_lock, flags);
209
210         return 0;
211
212 fail:
213         return ret;
214 }
215
216 static void hdp_disable(struct hdmi_connector *hdmi_connector)
217 {
218         struct hdmi *hdmi = hdmi_connector->hdmi;
219         const struct hdmi_platform_config *config = hdmi->config;
220         struct device *dev = &hdmi->pdev->dev;
221         int i, ret = 0;
222
223         /* Disable HPD interrupt */
224         hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0);
225
226         msm_hdmi_set_mode(hdmi, false);
227
228         for (i = 0; i < config->hpd_clk_cnt; i++)
229                 clk_disable_unprepare(hdmi->hpd_clks[i]);
230
231         ret = gpio_config(hdmi, false);
232         if (ret)
233                 dev_warn(dev, "failed to unconfigure GPIOs: %d\n", ret);
234
235         ret = pinctrl_pm_select_sleep_state(dev);
236         if (ret)
237                 dev_warn(dev, "pinctrl state chg failed: %d\n", ret);
238
239         for (i = 0; i < config->hpd_reg_cnt; i++) {
240                 ret = regulator_disable(hdmi->hpd_regs[i]);
241                 if (ret)
242                         dev_warn(dev, "failed to disable hpd regulator: %s (%d)\n",
243                                         config->hpd_reg_names[i], ret);
244         }
245 }
246
247 static void
248 msm_hdmi_hotplug_work(struct work_struct *work)
249 {
250         struct hdmi_connector *hdmi_connector =
251                 container_of(work, struct hdmi_connector, hpd_work);
252         struct drm_connector *connector = &hdmi_connector->base;
253         drm_helper_hpd_irq_event(connector->dev);
254 }
255
256 void msm_hdmi_connector_irq(struct drm_connector *connector)
257 {
258         struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
259         struct hdmi *hdmi = hdmi_connector->hdmi;
260         uint32_t hpd_int_status, hpd_int_ctrl;
261
262         /* Process HPD: */
263         hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
264         hpd_int_ctrl   = hdmi_read(hdmi, REG_HDMI_HPD_INT_CTRL);
265
266         if ((hpd_int_ctrl & HDMI_HPD_INT_CTRL_INT_EN) &&
267                         (hpd_int_status & HDMI_HPD_INT_STATUS_INT)) {
268                 bool detected = !!(hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED);
269
270                 /* ack & disable (temporarily) HPD events: */
271                 hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL,
272                         HDMI_HPD_INT_CTRL_INT_ACK);
273
274                 DBG("status=%04x, ctrl=%04x", hpd_int_status, hpd_int_ctrl);
275
276                 /* detect disconnect if we are connected or visa versa: */
277                 hpd_int_ctrl = HDMI_HPD_INT_CTRL_INT_EN;
278                 if (!detected)
279                         hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
280                 hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
281
282                 queue_work(hdmi->workq, &hdmi_connector->hpd_work);
283         }
284 }
285
286 static enum drm_connector_status detect_reg(struct hdmi *hdmi)
287 {
288         uint32_t hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
289         return (hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED) ?
290                         connector_status_connected : connector_status_disconnected;
291 }
292
293 #define HPD_GPIO_INDEX  2
294 static enum drm_connector_status detect_gpio(struct hdmi *hdmi)
295 {
296         const struct hdmi_platform_config *config = hdmi->config;
297         struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
298
299         return gpio_get_value(hpd_gpio.num) ?
300                         connector_status_connected :
301                         connector_status_disconnected;
302 }
303
304 static enum drm_connector_status hdmi_connector_detect(
305                 struct drm_connector *connector, bool force)
306 {
307         struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
308         struct hdmi *hdmi = hdmi_connector->hdmi;
309         const struct hdmi_platform_config *config = hdmi->config;
310         struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
311         enum drm_connector_status stat_gpio, stat_reg;
312         int retry = 20;
313
314         /*
315          * some platforms may not have hpd gpio. Rely only on the status
316          * provided by REG_HDMI_HPD_INT_STATUS in this case.
317          */
318         if (hpd_gpio.num == -1)
319                 return detect_reg(hdmi);
320
321         do {
322                 stat_gpio = detect_gpio(hdmi);
323                 stat_reg  = detect_reg(hdmi);
324
325                 if (stat_gpio == stat_reg)
326                         break;
327
328                 mdelay(10);
329         } while (--retry);
330
331         /* the status we get from reading gpio seems to be more reliable,
332          * so trust that one the most if we didn't manage to get hdmi and
333          * gpio status to agree:
334          */
335         if (stat_gpio != stat_reg) {
336                 DBG("HDMI_HPD_INT_STATUS tells us: %d", stat_reg);
337                 DBG("hpd gpio tells us: %d", stat_gpio);
338         }
339
340         return stat_gpio;
341 }
342
343 static void hdmi_connector_destroy(struct drm_connector *connector)
344 {
345         struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
346
347         hdp_disable(hdmi_connector);
348
349         drm_connector_cleanup(connector);
350
351         kfree(hdmi_connector);
352 }
353
354 static int msm_hdmi_connector_get_modes(struct drm_connector *connector)
355 {
356         struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
357         struct hdmi *hdmi = hdmi_connector->hdmi;
358         struct edid *edid;
359         uint32_t hdmi_ctrl;
360         int ret = 0;
361
362         hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
363         hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
364
365         edid = drm_get_edid(connector, hdmi->i2c);
366
367         hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
368
369         hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
370         drm_mode_connector_update_edid_property(connector, edid);
371
372         if (edid) {
373                 ret = drm_add_edid_modes(connector, edid);
374                 kfree(edid);
375         }
376
377         return ret;
378 }
379
380 static int msm_hdmi_connector_mode_valid(struct drm_connector *connector,
381                                  struct drm_display_mode *mode)
382 {
383         struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
384         struct hdmi *hdmi = hdmi_connector->hdmi;
385         const struct hdmi_platform_config *config = hdmi->config;
386         struct msm_drm_private *priv = connector->dev->dev_private;
387         struct msm_kms *kms = priv->kms;
388         long actual, requested;
389
390         requested = 1000 * mode->clock;
391         actual = kms->funcs->round_pixclk(kms,
392                         requested, hdmi_connector->hdmi->encoder);
393
394         /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
395          * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
396          * instead):
397          */
398         if (config->pwr_clk_cnt > 0)
399                 actual = clk_round_rate(hdmi->pwr_clks[0], actual);
400
401         DBG("requested=%ld, actual=%ld", requested, actual);
402
403         if (actual != requested)
404                 return MODE_CLOCK_RANGE;
405
406         return 0;
407 }
408
409 static struct drm_encoder *
410 msm_hdmi_connector_best_encoder(struct drm_connector *connector)
411 {
412         struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
413         return hdmi_connector->hdmi->encoder;
414 }
415
416 static const struct drm_connector_funcs hdmi_connector_funcs = {
417         .dpms = drm_atomic_helper_connector_dpms,
418         .detect = hdmi_connector_detect,
419         .fill_modes = drm_helper_probe_single_connector_modes,
420         .destroy = hdmi_connector_destroy,
421         .reset = drm_atomic_helper_connector_reset,
422         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
423         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
424 };
425
426 static const struct drm_connector_helper_funcs msm_hdmi_connector_helper_funcs = {
427         .get_modes = msm_hdmi_connector_get_modes,
428         .mode_valid = msm_hdmi_connector_mode_valid,
429         .best_encoder = msm_hdmi_connector_best_encoder,
430 };
431
432 /* initialize connector */
433 struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
434 {
435         struct drm_connector *connector = NULL;
436         struct hdmi_connector *hdmi_connector;
437         int ret;
438
439         hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
440         if (!hdmi_connector)
441                 return ERR_PTR(-ENOMEM);
442
443         hdmi_connector->hdmi = hdmi;
444         INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);
445
446         connector = &hdmi_connector->base;
447
448         drm_connector_init(hdmi->dev, connector, &hdmi_connector_funcs,
449                         DRM_MODE_CONNECTOR_HDMIA);
450         drm_connector_helper_add(connector, &msm_hdmi_connector_helper_funcs);
451
452         connector->polled = DRM_CONNECTOR_POLL_CONNECT |
453                         DRM_CONNECTOR_POLL_DISCONNECT;
454
455         connector->interlace_allowed = 0;
456         connector->doublescan_allowed = 0;
457
458         ret = hpd_enable(hdmi_connector);
459         if (ret) {
460                 dev_err(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
461                 return ERR_PTR(ret);
462         }
463
464         drm_mode_connector_attach_encoder(connector, hdmi->encoder);
465
466         return connector;
467 }