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