]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blob - drivers/video/tegra/dc/hdmi_state_machine.c
video: tegra: dc: tag vrr modes using vmode
[sojka/nv-tegra/linux-3.10.git] / drivers / video / tegra / dc / hdmi_state_machine.c
1 /*
2  * hdmi_state_machine.c
3  *
4  * HDMI library support functions for Nvidia Tegra processors.
5  *
6  * Copyright (C) 2012-2013 Google - http://www.google.com/
7  * Copyright (C) 2013-2016 NVIDIA CORPORATION. All rights reserved.
8  * Authors:     John Grossman <johngro@google.com>
9  * Authors:     Mike J. Chen <mjchen@google.com>
10  *
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License version 2 as published by
13  * the Free Software Foundation.
14  *
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18  * more details.
19  *
20  * You should have received a copy of the GNU General Public License along with
21  * this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23
24 #include <linux/kernel.h>
25 #include <mach/dc.h>
26 #include <mach/fb.h>
27 #ifdef CONFIG_SWITCH
28 #include <linux/switch.h>
29 #endif
30 #include <video/tegrafb.h>
31 #include "dc_priv.h"
32
33 #ifdef CONFIG_ADF_TEGRA
34 #include "tegra_adf.h"
35 #endif
36
37 #include "hdmi_state_machine.h"
38
39 /************************************************************
40  *
41  * state machine internal constants
42  *
43  ************************************************************/
44 #define MAX_EDID_READ_ATTEMPTS 5
45 #define HDMI_EDID_MAX_LENGTH 512
46
47 /* how long of an HPD drop before we consider it gone for good.
48  * this is mostly a preference to work around monitors users
49  * reported that occasionally drop HPD.
50  */
51 #define HPD_STABILIZE_MS 40
52 #define HPD_DROP_TIMEOUT_MS 1500
53 #define CHECK_PLUG_STATE_DELAY_MS 10
54 #define CHECK_EDID_DELAY_MS 60
55
56 /************************************************************
57  *
58  * state machine internal state
59  *
60  ************************************************************/
61 static DEFINE_RT_MUTEX(work_lock);
62 static struct hdmi_state_machine_worker_data {
63         struct delayed_work dwork;
64         struct tegra_dc_hdmi_data *hdmi;
65         int shutdown;
66         int state;
67         int edid_reads;
68         int pending_hpd_evt;
69 } work_state;
70
71 /************************************************************
72  *
73  * state machine internal methods
74  *
75  ************************************************************/
76 static void hdmi_state_machine_sched_work_l(int resched_time)
77 {
78         cancel_delayed_work(&work_state.dwork);
79         if ((resched_time >= 0) && !work_state.shutdown)
80                 queue_delayed_work(system_nrt_wq,
81                                 &work_state.dwork,
82                                 msecs_to_jiffies(resched_time));
83 }
84
85 static const char * const state_names[] = {
86         "Reset",
87         "Check Plug",
88         "Check EDID",
89         "Disabled",
90         "Enabled",
91         "Wait for HPD reassert",
92         "Recheck EDID",
93         "Takeover from bootloader",
94 };
95
96 static void hdmi_state_machine_set_state_l(int target_state, int resched_time)
97 {
98         rt_mutex_lock(&work_lock);
99
100         pr_info("%s: switching from state %d (%s) to state %d (%s)\n",
101                 __func__, work_state.state, state_names[work_state.state],
102                 target_state, state_names[target_state]);
103         work_state.state = target_state;
104
105         /* If virtual edid is active, schedule immediately. However, keep
106          * the possible negative value to maintain the transition behavior.
107          */
108         if (work_state.hdmi->dc->vedid && resched_time > 0)
109                 resched_time = 0;
110
111         /* If the pending_hpd_evt flag is already set, don't bother to
112          * reschedule the state machine worker.  We should be able to assert
113          * that there is a worker callback already scheduled, and that it is
114          * scheduled to run immediately.  This is particularly important when
115          * making the transition to the steady state ENABLED or DISABLED states.
116          * If an HPD event occurs while the worker is in flight, after the
117          * worker checks the state of the pending HPD flag, and then the state
118          * machine transitions to ENABLE or DISABLED, the system would end up
119          * canceling the callback to handle the HPD event were it not for this
120          * check.
121          */
122         if (!work_state.pending_hpd_evt)
123                 hdmi_state_machine_sched_work_l(resched_time);
124
125         rt_mutex_unlock(&work_lock);
126 }
127
128 static void hdmi_state_machine_handle_hpd_l(int cur_hpd)
129 {
130         int tgt_state, timeout;
131
132         if ((HDMI_STATE_DONE_ENABLED == work_state.state) && !cur_hpd) {
133                 /* Did HPD drop while we were in DONE_ENABLED?  If so, hold
134                  * steady and wait to see if it comes back.
135                  */
136                 tegra_nvhdcp_set_plug(work_state.hdmi->nvhdcp, 0);
137                 tgt_state = HDMI_STATE_DONE_WAIT_FOR_HPD_REASSERT;
138                 timeout = HPD_DROP_TIMEOUT_MS;
139         } else
140         if (HDMI_STATE_DONE_WAIT_FOR_HPD_REASSERT == work_state.state &&
141                 cur_hpd) {
142                 /* Looks like HPD dropped and eventually came back.  Re-read the
143                  * EDID and reset the system only if the EDID has changed.
144                  */
145                 work_state.edid_reads = 0;
146                 tgt_state = HDMI_STATE_DONE_RECHECK_EDID;
147                 timeout = CHECK_EDID_DELAY_MS;
148         } else
149         if (HDMI_STATE_DONE_ENABLED == work_state.state && cur_hpd) {
150                 /* Looks like HPD dropped but came back quickly, ignore it.
151                  */
152                 pr_info("%s: ignoring bouncing hpd\n", __func__);
153                 return;
154         } else
155         if (HDMI_STATE_INIT_FROM_BOOTLOADER == work_state.state && cur_hpd) {
156                 /* We follow the same protocol as HDMI_STATE_RESET in the
157                  * last branch here, but avoid actually entering that state so
158                  * we do not actively disable HDMI.  Worker will check HPD
159                  * level again when it's woke up after 40ms.
160                  */
161                 tgt_state = HDMI_STATE_CHECK_PLUG_STATE;
162                 timeout = HPD_STABILIZE_MS;
163         } else {
164                 /* Looks like there was HPD activity while we were neither
165                  * waiting for it to go away during steady state output, nor
166                  * looking for it to come back after such an event.  Wait until
167                  * HPD has been steady for at least 40 mSec, then restart the
168                  * state machine.
169                  */
170                 tgt_state = HDMI_STATE_RESET;
171                 timeout = HPD_STABILIZE_MS;
172         }
173
174         hdmi_state_machine_set_state_l(tgt_state, timeout);
175 }
176
177 /************************************************************
178  *
179  * internal state handlers and dispatch table
180  *
181  ************************************************************/
182 static void hdmi_disable_l(struct tegra_dc_hdmi_data *hdmi)
183 {
184         /* If the hotplug_state is controlled by the hotplug debug node,
185          * the value of dc->connected is changed directly. This affects
186          * the behavior of this function, as the state machine does not
187          * expect dc->connected to be changed externally. In that case,
188          * use a cached value which is only modified by the state machine.
189          */
190         bool was_connected;
191         if (hdmi->dc->out->hotplug_state == TEGRA_HPD_STATE_NORMAL)
192                 was_connected = hdmi->dc->connected;
193         else
194                 was_connected = hdmi->connected_cache;
195 #ifdef CONFIG_SWITCH
196         switch_set_state(&hdmi->audio_switch, 0);
197         pr_info("%s: audio_switch 0\n", __func__);
198         switch_set_state(&hdmi->hpd_switch, 0);
199         pr_info("%s: hpd_switch 0\n", __func__);
200 #endif
201         tegra_nvhdcp_set_plug(hdmi->nvhdcp, 0);
202         if (was_connected) {
203                 pr_info("HDMI from connected to disconnected\n");
204                 tegra_dc_disable(hdmi->dc);
205         }
206         hdmi->dc->connected = false;
207         hdmi->connected_cache = false;
208 #ifdef CONFIG_ADF_TEGRA
209         tegra_adf_process_hotplug_disconnected(hdmi->dc->adf);
210 #else
211         tegra_fb_update_monspecs(hdmi->dc->fb, NULL, NULL);
212 #endif
213 #ifdef CONFIG_TEGRA_DC_EXTENSIONS
214         if (was_connected)
215                 tegra_dc_ext_process_hotplug(hdmi->dc->ndev->id, false);
216         else
217                 pr_info("%s: skipping redundant disconnect\n", __func__);
218 #endif
219 }
220
221 static void handle_reset_l(struct tegra_dc_hdmi_data *hdmi)
222 {
223         /* Were we just reset?  If so, shut everything down, then schedule a
224          * check of the plug state in the near future.
225          */
226         hdmi_disable_l(hdmi);
227         hdmi_state_machine_set_state_l(HDMI_STATE_CHECK_PLUG_STATE,
228                                        CHECK_PLUG_STATE_DELAY_MS);
229 }
230
231 static void handle_check_plug_state_l(struct tegra_dc_hdmi_data *hdmi)
232 {
233         if (tegra_dc_hpd(work_state.hdmi->dc)) {
234                 /* Looks like there is something plugged in.
235                  * Get ready to read the sink's EDID information.
236                  */
237                 work_state.edid_reads = 0;
238
239                 hdmi_state_machine_set_state_l(HDMI_STATE_CHECK_EDID,
240                                                CHECK_EDID_DELAY_MS);
241         } else {
242                 /* nothing plugged in, so we are finished.  Go to the
243                  * DONE_DISABLED state and stay there until the next HPD event.
244                  * */
245                 hdmi_disable_l(hdmi);
246                 hdmi_state_machine_set_state_l(HDMI_STATE_DONE_DISABLED, -1);
247         }
248 }
249
250 static void handle_check_edid_l(struct tegra_dc_hdmi_data *hdmi)
251 {
252         struct fb_monspecs specs;
253 #ifdef CONFIG_SWITCH
254         int state;
255 #endif
256
257         memset(&specs, 0, sizeof(specs));
258 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
259         /* Set default videomode on dc before enabling it*/
260         tegra_dc_set_default_videomode(hdmi->dc);
261 #endif
262
263         if (!tegra_dc_hpd(work_state.hdmi->dc)) {
264                 /* hpd dropped - stop EDID read */
265                 pr_info("hpd == 0, aborting EDID read\n");
266                 goto end_disabled;
267         }
268
269         if (tegra_edid_get_monspecs(hdmi->edid, &specs)) {
270                 /* Failed to read EDID.  If we still have retry attempts left,
271                  * schedule another attempt.  Otherwise give up and just go to
272                  * the disabled state.
273                  */
274                 work_state.edid_reads++;
275                 if (work_state.edid_reads >= MAX_EDID_READ_ATTEMPTS) {
276                         pr_info("Failed to read EDID after %d times. Giving up.\n",
277                                 work_state.edid_reads);
278                         goto end_disabled;
279                 } else {
280                         hdmi_state_machine_set_state_l(HDMI_STATE_CHECK_EDID,
281                                                        CHECK_EDID_DELAY_MS);
282                 }
283
284                 return;
285         }
286
287         if (tegra_edid_get_eld(hdmi->edid, &hdmi->eld) < 0) {
288                 pr_err("error populating eld\n");
289                 goto end_disabled;
290         }
291         hdmi->eld_retrieved = true;
292
293         pr_info("panel size %d by %d\n", specs.max_x, specs.max_y);
294
295         /* monitors like to lie about these but they are still useful for
296          * detecting aspect ratios
297          */
298         hdmi->dc->out->h_size = specs.max_x * 10;
299         hdmi->dc->out->v_size = specs.max_y * 10;
300
301         hdmi->dvi = !(specs.misc & FB_MISC_HDMI);
302
303 #ifdef CONFIG_ADF_TEGRA
304         tegra_adf_process_hotplug_connected(hdmi->dc->adf, &specs);
305 #endif
306 #ifdef CONFIG_TEGRA_DC_EXTENSIONS
307         tegra_fb_update_monspecs(hdmi->dc->fb, &specs,
308                 tegra_dc_hdmi_mode_filter);
309 #endif
310 #ifdef CONFIG_SWITCH
311         state = tegra_edid_audio_supported(hdmi->edid) ? 1 : 0;
312         switch_set_state(&hdmi->audio_switch, state);
313         pr_info("%s: audio_switch %d\n", __func__, state);
314         switch_set_state(&hdmi->hpd_switch, 1);
315         pr_info("Display connected, hpd_switch 1\n");
316 #endif
317         hdmi->dc->connected = true;
318         hdmi->connected_cache = true;
319
320 #ifdef CONFIG_TEGRA_DC_EXTENSIONS
321         tegra_dc_ext_process_hotplug(hdmi->dc->ndev->id, true);
322 #endif
323
324         if (unlikely(tegra_is_clk_enabled(hdmi->clk))) {
325                 /* the only time this should happen is on boot, where the
326                  * sequence is that hdmi is enabled before EDID is read.
327                  * hdmi_enable() doesn't have EDID information yet so can't
328                  * setup audio and infoframes, so we have to do so here.
329                  */
330                 pr_info("%s: setting audio and infoframes\n", __func__);
331                 tegra_dc_io_start(hdmi->dc);
332                 tegra_dc_hdmi_setup_audio_and_infoframes(hdmi->dc);
333                 tegra_dc_io_end(hdmi->dc);
334         }
335
336         hdmi_state_machine_set_state_l(HDMI_STATE_DONE_ENABLED, -1);
337
338         return;
339
340 end_disabled:
341         hdmi->eld_retrieved = false;
342         hdmi_disable_l(hdmi);
343         hdmi_state_machine_set_state_l(HDMI_STATE_DONE_DISABLED, -1);
344 }
345
346 static void handle_wait_for_hpd_reassert_l(struct tegra_dc_hdmi_data *hdmi)
347 {
348         /* Looks like HPD dropped and really did stay low.  Go ahead and reset
349          * the system.
350          */
351         hdmi_state_machine_set_state_l(HDMI_STATE_RESET, 0);
352 }
353
354 /* returns bytes read, or negative error */
355 static int read_edid_into_buffer(struct tegra_dc_hdmi_data *hdmi,
356                                  u8 *edid_data, size_t edid_data_len)
357 {
358         int err, i;
359         int extension_blocks;
360         int max_ext_blocks = (edid_data_len / 128) - 1;
361
362         err = tegra_edid_read_block(hdmi->edid, 0, edid_data);
363         if (err) {
364                 pr_err("tegra_edid_read_block(0) returned err %d\n", err);
365                 return err;
366         }
367         extension_blocks = edid_data[0x7e];
368         pr_info("%s: extension_blocks = %d, max_ext_blocks = %d\n",
369                 __func__, extension_blocks, max_ext_blocks);
370         if (extension_blocks > max_ext_blocks)
371                 extension_blocks = max_ext_blocks;
372         for (i = 1; i <= extension_blocks; i++) {
373                 err = tegra_edid_read_block(hdmi->edid, i, edid_data + i * 128);
374                 if (err) {
375                         pr_err("tegra_edid_read_block(%d) returned err %d\n",
376                                 i, err);
377                         return err;
378                 }
379         }
380         return i * 128;
381 }
382
383 /* re-read the edid and check to see if it has changed.  Return 0 on a
384  * successful E-EDID read, or a non-zero error code on failure.  If we succeed,
385  * set match to 1 if the old E-EDID matches the new E-EDID.  Otherwise, set
386  * match to 0. */
387 static int hdmi_recheck_edid(struct tegra_dc_hdmi_data *hdmi, int *match)
388 {
389         int ret;
390         u8 tmp[HDMI_EDID_MAX_LENGTH] = {0};
391
392         ret = read_edid_into_buffer(hdmi, tmp, sizeof(tmp));
393         pr_info("%s: read_edid_into_buffer() returned %d\n", __func__, ret);
394         if (ret > 0) {
395                 struct tegra_dc_edid *data = tegra_edid_get_data(hdmi->edid);
396                 pr_info("old edid len = %ld\n", (long int)data->len);
397                 *match = ((ret == data->len) &&
398                           !memcmp(tmp, data->buf, data->len));
399                 if (*match == 0) {
400                         print_hex_dump(KERN_INFO, "tmp :", DUMP_PREFIX_ADDRESS,
401                                        16, 4, tmp, ret, true);
402                         print_hex_dump(KERN_INFO, "data:", DUMP_PREFIX_ADDRESS,
403                                        16, 4, data->buf, data->len, true);
404                 }
405                 tegra_edid_put_data(data);
406                 ret = 0;
407         }
408
409         return ret;
410 }
411
412 static void handle_recheck_edid_l(struct tegra_dc_hdmi_data *hdmi)
413 {
414         int match, tgt_state, timeout;
415
416         tgt_state = HDMI_STATE_RESET;
417         timeout = 0;
418
419         if (hdmi_recheck_edid(hdmi, &match)) {
420                 /* Failed to read EDID.  If we still have retry attempts left,
421                  * schedule another attempt.  Otherwise give up and reset;
422                  */
423                 work_state.edid_reads++;
424                 if (work_state.edid_reads >= MAX_EDID_READ_ATTEMPTS) {
425                         pr_info("Failed to read EDID after %d times. Giving up.\n",
426                                 work_state.edid_reads);
427                 } else {
428                         tgt_state = HDMI_STATE_DONE_RECHECK_EDID;
429                         timeout = CHECK_EDID_DELAY_MS;
430                 }
431         } else {
432                 /* Successful read!  If the EDID is unchanged, just go back to
433                  * the DONE_ENABLED state and do nothing.  If something changed,
434                  * just reset the whole system.
435                  */
436                 if (match) {
437                         pr_info("No EDID change after HPD bounce, taking no action.\n");
438                         tgt_state = HDMI_STATE_DONE_ENABLED;
439                         if (tegra_is_clk_enabled(hdmi->dc->clk)) {
440                                 tegra_nvhdcp_set_plug(hdmi->nvhdcp, 0);
441                                 tegra_nvhdcp_set_plug(hdmi->nvhdcp, 1);
442                         } else {
443                                 pr_info("dc powergated, skipping hdcp reset\n");
444                         }
445                         timeout = -1;
446                 } else {
447                         pr_info("EDID change after HPD bounce, resetting\n");
448                 }
449         }
450
451         hdmi_state_machine_set_state_l(tgt_state, timeout);
452 }
453
454 typedef void (*dispatch_func_t)(struct tegra_dc_hdmi_data *hdmi);
455 static const dispatch_func_t state_machine_dispatch[] = {
456         handle_reset_l,                 /* STATE_RESET */
457         handle_check_plug_state_l,      /* STATE_CHECK_PLUG_STATE */
458         handle_check_edid_l,            /* STATE_CHECK_EDID */
459         NULL,                           /* STATE_DONE_DISABLED */
460         NULL,                           /* STATE_DONE_ENABLED */
461         handle_wait_for_hpd_reassert_l, /* STATE_DONE_WAIT_FOR_HPD_REASSERT */
462         handle_recheck_edid_l,          /* STATE_DONE_RECHECK_EDID */
463         NULL,                           /* STATE_INIT_FROM_BOOTLOADER */
464 };
465
466 /************************************************************
467  *
468  * main state machine worker function
469  *
470  ************************************************************/
471 static void hdmi_state_machine_worker(struct work_struct *work)
472 {
473         int pending_hpd_evt, cur_hpd;
474
475         /* Observe and clear the pending flag and latch the current HPD state.
476          */
477         rt_mutex_lock(&work_lock);
478         pending_hpd_evt = work_state.pending_hpd_evt;
479         work_state.pending_hpd_evt = 0;
480         rt_mutex_unlock(&work_lock);
481         cur_hpd = tegra_dc_hpd(work_state.hdmi->dc);
482
483         pr_info("%s (tid %p): state %d (%s), hpd %d, pending_hpd_evt %d\n",
484                 __func__, current, work_state.state,
485                 state_names[work_state.state], cur_hpd, pending_hpd_evt);
486
487         if (pending_hpd_evt) {
488                 /* If we were woken up because of HPD activity, just schedule
489                  * the next appropriate task and get out.
490                  */
491                 hdmi_state_machine_handle_hpd_l(cur_hpd);
492         } else if (work_state.state < ARRAY_SIZE(state_machine_dispatch)) {
493                 dispatch_func_t func = state_machine_dispatch[work_state.state];
494
495                 if (NULL == func)
496                         pr_warn("NULL state machine handler while in state %d; how did we end up here?",
497                                 work_state.state);
498                 else
499                         func(work_state.hdmi);
500         } else {
501                 pr_warn("hdmi state machine worker scheduled unexpected state %d",
502                         work_state.state);
503         }
504 }
505
506 /************************************************************
507  *
508  * state machine API implementation
509  *
510  ************************************************************/
511 void hdmi_state_machine_init(struct tegra_dc_hdmi_data *hdmi)
512 {
513         work_state.hdmi = hdmi;
514         work_state.state = HDMI_STATE_INIT_FROM_BOOTLOADER;
515         work_state.pending_hpd_evt = 1;
516         work_state.edid_reads = 0;
517         work_state.shutdown = 0;
518         INIT_DELAYED_WORK(&work_state.dwork, hdmi_state_machine_worker);
519 }
520
521 void hdmi_state_machine_shutdown(void)
522 {
523         work_state.shutdown = 1;
524         cancel_delayed_work_sync(&work_state.dwork);
525 }
526
527 void hdmi_state_machine_set_pending_hpd(void)
528 {
529         rt_mutex_lock(&work_lock);
530
531         /* We always schedule work any time there is a pending HPD event */
532         work_state.pending_hpd_evt = 1;
533         hdmi_state_machine_sched_work_l(0);
534
535         rt_mutex_unlock(&work_lock);
536 }
537
538 int hdmi_state_machine_get_state(void)
539 {
540         int ret;
541
542         rt_mutex_lock(&work_lock);
543         ret = work_state.state;
544         rt_mutex_unlock(&work_lock);
545
546         return ret;
547 }