]> Pileus Git - ~andy/linux/blob - drivers/video/omap2/dss/hdmi.c
Merge tag 'fbdev-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux
[~andy/linux] / drivers / video / omap2 / dss / hdmi.c
1 /*
2  * hdmi.c
3  *
4  * HDMI interface DSS driver setting for TI's OMAP4 family of processor.
5  * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
6  * Authors: Yong Zhi
7  *      Mythri pk <mythripk@ti.com>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License version 2 as published by
11  * the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along with
19  * this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #define DSS_SUBSYS_NAME "HDMI"
23
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/err.h>
27 #include <linux/io.h>
28 #include <linux/interrupt.h>
29 #include <linux/mutex.h>
30 #include <linux/delay.h>
31 #include <linux/string.h>
32 #include <linux/platform_device.h>
33 #include <linux/pm_runtime.h>
34 #include <linux/clk.h>
35 #include <linux/gpio.h>
36 #include <linux/regulator/consumer.h>
37 #include <video/omapdss.h>
38
39 #include "ti_hdmi.h"
40 #include "dss.h"
41 #include "dss_features.h"
42
43 #define HDMI_WP                 0x0
44 #define HDMI_CORE_SYS           0x400
45 #define HDMI_CORE_AV            0x900
46 #define HDMI_PLLCTRL            0x200
47 #define HDMI_PHY                0x300
48
49 /* HDMI EDID Length move this */
50 #define HDMI_EDID_MAX_LENGTH                    256
51 #define EDID_TIMING_DESCRIPTOR_SIZE             0x12
52 #define EDID_DESCRIPTOR_BLOCK0_ADDRESS          0x36
53 #define EDID_DESCRIPTOR_BLOCK1_ADDRESS          0x80
54 #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR      4
55 #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR      4
56
57 #define HDMI_DEFAULT_REGN 16
58 #define HDMI_DEFAULT_REGM2 1
59
60 static struct {
61         struct mutex lock;
62         struct platform_device *pdev;
63
64         struct hdmi_ip_data ip_data;
65
66         struct clk *sys_clk;
67         struct regulator *vdda_hdmi_dac_reg;
68
69         bool core_enabled;
70
71         struct omap_dss_device output;
72 } hdmi;
73
74 /*
75  * Logic for the below structure :
76  * user enters the CEA or VESA timings by specifying the HDMI/DVI code.
77  * There is a correspondence between CEA/VESA timing and code, please
78  * refer to section 6.3 in HDMI 1.3 specification for timing code.
79  *
80  * In the below structure, cea_vesa_timings corresponds to all OMAP4
81  * supported CEA and VESA timing values.code_cea corresponds to the CEA
82  * code, It is used to get the timing from cea_vesa_timing array.Similarly
83  * with code_vesa. Code_index is used for back mapping, that is once EDID
84  * is read from the TV, EDID is parsed to find the timing values and then
85  * map it to corresponding CEA or VESA index.
86  */
87
88 static const struct hdmi_config cea_timings[] = {
89         {
90                 { 640, 480, 25200, 96, 16, 48, 2, 10, 33,
91                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
92                         false, },
93                 { 1, HDMI_HDMI },
94         },
95         {
96                 { 720, 480, 27027, 62, 16, 60, 6, 9, 30,
97                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
98                         false, },
99                 { 2, HDMI_HDMI },
100         },
101         {
102                 { 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
103                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
104                         false, },
105                 { 4, HDMI_HDMI },
106         },
107         {
108                 { 1920, 540, 74250, 44, 88, 148, 5, 2, 15,
109                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
110                         true, },
111                 { 5, HDMI_HDMI },
112         },
113         {
114                 { 1440, 240, 27027, 124, 38, 114, 3, 4, 15,
115                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
116                         true, },
117                 { 6, HDMI_HDMI },
118         },
119         {
120                 { 1920, 1080, 148500, 44, 88, 148, 5, 4, 36,
121                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
122                         false, },
123                 { 16, HDMI_HDMI },
124         },
125         {
126                 { 720, 576, 27000, 64, 12, 68, 5, 5, 39,
127                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
128                         false, },
129                 { 17, HDMI_HDMI },
130         },
131         {
132                 { 1280, 720, 74250, 40, 440, 220, 5, 5, 20,
133                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
134                         false, },
135                 { 19, HDMI_HDMI },
136         },
137         {
138                 { 1920, 540, 74250, 44, 528, 148, 5, 2, 15,
139                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
140                         true, },
141                 { 20, HDMI_HDMI },
142         },
143         {
144                 { 1440, 288, 27000, 126, 24, 138, 3, 2, 19,
145                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
146                         true, },
147                 { 21, HDMI_HDMI },
148         },
149         {
150                 { 1440, 576, 54000, 128, 24, 136, 5, 5, 39,
151                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
152                         false, },
153                 { 29, HDMI_HDMI },
154         },
155         {
156                 { 1920, 1080, 148500, 44, 528, 148, 5, 4, 36,
157                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
158                         false, },
159                 { 31, HDMI_HDMI },
160         },
161         {
162                 { 1920, 1080, 74250, 44, 638, 148, 5, 4, 36,
163                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
164                         false, },
165                 { 32, HDMI_HDMI },
166         },
167         {
168                 { 2880, 480, 108108, 248, 64, 240, 6, 9, 30,
169                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
170                         false, },
171                 { 35, HDMI_HDMI },
172         },
173         {
174                 { 2880, 576, 108000, 256, 48, 272, 5, 5, 39,
175                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
176                         false, },
177                 { 37, HDMI_HDMI },
178         },
179 };
180
181 static const struct hdmi_config vesa_timings[] = {
182 /* VESA From Here */
183         {
184                 { 640, 480, 25175, 96, 16, 48, 2, 11, 31,
185                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
186                         false, },
187                 { 4, HDMI_DVI },
188         },
189         {
190                 { 800, 600, 40000, 128, 40, 88, 4, 1, 23,
191                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
192                         false, },
193                 { 9, HDMI_DVI },
194         },
195         {
196                 { 848, 480, 33750, 112, 16, 112, 8, 6, 23,
197                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
198                         false, },
199                 { 0xE, HDMI_DVI },
200         },
201         {
202                 { 1280, 768, 79500, 128, 64, 192, 7, 3, 20,
203                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
204                         false, },
205                 { 0x17, HDMI_DVI },
206         },
207         {
208                 { 1280, 800, 83500, 128, 72, 200, 6, 3, 22,
209                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
210                         false, },
211                 { 0x1C, HDMI_DVI },
212         },
213         {
214                 { 1360, 768, 85500, 112, 64, 256, 6, 3, 18,
215                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
216                         false, },
217                 { 0x27, HDMI_DVI },
218         },
219         {
220                 { 1280, 960, 108000, 112, 96, 312, 3, 1, 36,
221                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
222                         false, },
223                 { 0x20, HDMI_DVI },
224         },
225         {
226                 { 1280, 1024, 108000, 112, 48, 248, 3, 1, 38,
227                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
228                         false, },
229                 { 0x23, HDMI_DVI },
230         },
231         {
232                 { 1024, 768, 65000, 136, 24, 160, 6, 3, 29,
233                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
234                         false, },
235                 { 0x10, HDMI_DVI },
236         },
237         {
238                 { 1400, 1050, 121750, 144, 88, 232, 4, 3, 32,
239                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
240                         false, },
241                 { 0x2A, HDMI_DVI },
242         },
243         {
244                 { 1440, 900, 106500, 152, 80, 232, 6, 3, 25,
245                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
246                         false, },
247                 { 0x2F, HDMI_DVI },
248         },
249         {
250                 { 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30,
251                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
252                         false, },
253                 { 0x3A, HDMI_DVI },
254         },
255         {
256                 { 1366, 768, 85500, 143, 70, 213, 3, 3, 24,
257                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
258                         false, },
259                 { 0x51, HDMI_DVI },
260         },
261         {
262                 { 1920, 1080, 148500, 44, 148, 80, 5, 4, 36,
263                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
264                         false, },
265                 { 0x52, HDMI_DVI },
266         },
267         {
268                 { 1280, 768, 68250, 32, 48, 80, 7, 3, 12,
269                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
270                         false, },
271                 { 0x16, HDMI_DVI },
272         },
273         {
274                 { 1400, 1050, 101000, 32, 48, 80, 4, 3, 23,
275                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
276                         false, },
277                 { 0x29, HDMI_DVI },
278         },
279         {
280                 { 1680, 1050, 119000, 32, 48, 80, 6, 3, 21,
281                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
282                         false, },
283                 { 0x39, HDMI_DVI },
284         },
285         {
286                 { 1280, 800, 79500, 32, 48, 80, 6, 3, 14,
287                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
288                         false, },
289                 { 0x1B, HDMI_DVI },
290         },
291         {
292                 { 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
293                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
294                         false, },
295                 { 0x55, HDMI_DVI },
296         },
297         {
298                 { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26,
299                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
300                         false, },
301                 { 0x44, HDMI_DVI },
302         },
303 };
304
305 static int hdmi_runtime_get(void)
306 {
307         int r;
308
309         DSSDBG("hdmi_runtime_get\n");
310
311         r = pm_runtime_get_sync(&hdmi.pdev->dev);
312         WARN_ON(r < 0);
313         if (r < 0)
314                 return r;
315
316         return 0;
317 }
318
319 static void hdmi_runtime_put(void)
320 {
321         int r;
322
323         DSSDBG("hdmi_runtime_put\n");
324
325         r = pm_runtime_put_sync(&hdmi.pdev->dev);
326         WARN_ON(r < 0 && r != -ENOSYS);
327 }
328
329 static int hdmi_init_regulator(void)
330 {
331         struct regulator *reg;
332
333         if (hdmi.vdda_hdmi_dac_reg != NULL)
334                 return 0;
335
336         reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
337
338         /* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */
339         if (IS_ERR(reg))
340                 reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC");
341
342         if (IS_ERR(reg)) {
343                 DSSERR("can't get VDDA_HDMI_DAC regulator\n");
344                 return PTR_ERR(reg);
345         }
346
347         hdmi.vdda_hdmi_dac_reg = reg;
348
349         return 0;
350 }
351
352 static const struct hdmi_config *hdmi_find_timing(
353                                         const struct hdmi_config *timings_arr,
354                                         int len)
355 {
356         int i;
357
358         for (i = 0; i < len; i++) {
359                 if (timings_arr[i].cm.code == hdmi.ip_data.cfg.cm.code)
360                         return &timings_arr[i];
361         }
362         return NULL;
363 }
364
365 static const struct hdmi_config *hdmi_get_timings(void)
366 {
367        const struct hdmi_config *arr;
368        int len;
369
370        if (hdmi.ip_data.cfg.cm.mode == HDMI_DVI) {
371                arr = vesa_timings;
372                len = ARRAY_SIZE(vesa_timings);
373        } else {
374                arr = cea_timings;
375                len = ARRAY_SIZE(cea_timings);
376        }
377
378        return hdmi_find_timing(arr, len);
379 }
380
381 static bool hdmi_timings_compare(struct omap_video_timings *timing1,
382                                 const struct omap_video_timings *timing2)
383 {
384         int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
385
386         if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) ==
387                         DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
388                 (timing2->x_res == timing1->x_res) &&
389                 (timing2->y_res == timing1->y_res)) {
390
391                 timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
392                 timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
393                 timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
394                 timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
395
396                 DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
397                         "timing2_hsync = %d timing2_vsync = %d\n",
398                         timing1_hsync, timing1_vsync,
399                         timing2_hsync, timing2_vsync);
400
401                 if ((timing1_hsync == timing2_hsync) &&
402                         (timing1_vsync == timing2_vsync)) {
403                         return true;
404                 }
405         }
406         return false;
407 }
408
409 static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
410 {
411         int i;
412         struct hdmi_cm cm = {-1};
413         DSSDBG("hdmi_get_code\n");
414
415         for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
416                 if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
417                         cm = cea_timings[i].cm;
418                         goto end;
419                 }
420         }
421         for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
422                 if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
423                         cm = vesa_timings[i].cm;
424                         goto end;
425                 }
426         }
427
428 end:    return cm;
429
430 }
431
432 static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
433                 struct hdmi_pll_info *pi)
434 {
435         unsigned long clkin, refclk;
436         u32 mf;
437
438         clkin = clk_get_rate(hdmi.sys_clk) / 10000;
439         /*
440          * Input clock is predivided by N + 1
441          * out put of which is reference clk
442          */
443
444         pi->regn = HDMI_DEFAULT_REGN;
445
446         refclk = clkin / pi->regn;
447
448         pi->regm2 = HDMI_DEFAULT_REGM2;
449
450         /*
451          * multiplier is pixel_clk/ref_clk
452          * Multiplying by 100 to avoid fractional part removal
453          */
454         pi->regm = phy * pi->regm2 / refclk;
455
456         /*
457          * fractional multiplier is remainder of the difference between
458          * multiplier and actual phy(required pixel clock thus should be
459          * multiplied by 2^18(262144) divided by the reference clock
460          */
461         mf = (phy - pi->regm / pi->regm2 * refclk) * 262144;
462         pi->regmf = pi->regm2 * mf / refclk;
463
464         /*
465          * Dcofreq should be set to 1 if required pixel clock
466          * is greater than 1000MHz
467          */
468         pi->dcofreq = phy > 1000 * 100;
469         pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
470
471         /* Set the reference clock to sysclk reference */
472         pi->refsel = HDMI_REFSEL_SYSCLK;
473
474         DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
475         DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
476 }
477
478 static int hdmi_power_on_core(struct omap_dss_device *dssdev)
479 {
480         int r;
481
482         r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
483         if (r)
484                 return r;
485
486         r = hdmi_runtime_get();
487         if (r)
488                 goto err_runtime_get;
489
490         /* Make selection of HDMI in DSS */
491         dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
492
493         hdmi.core_enabled = true;
494
495         return 0;
496
497 err_runtime_get:
498         regulator_disable(hdmi.vdda_hdmi_dac_reg);
499
500         return r;
501 }
502
503 static void hdmi_power_off_core(struct omap_dss_device *dssdev)
504 {
505         hdmi.core_enabled = false;
506
507         hdmi_runtime_put();
508         regulator_disable(hdmi.vdda_hdmi_dac_reg);
509 }
510
511 static int hdmi_power_on_full(struct omap_dss_device *dssdev)
512 {
513         int r;
514         struct omap_video_timings *p;
515         struct omap_overlay_manager *mgr = hdmi.output.manager;
516         unsigned long phy;
517
518         r = hdmi_power_on_core(dssdev);
519         if (r)
520                 return r;
521
522         dss_mgr_disable(mgr);
523
524         p = &hdmi.ip_data.cfg.timings;
525
526         DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
527
528         phy = p->pixel_clock;
529
530         hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
531
532         hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
533
534         /* config the PLL and PHY hdmi_set_pll_pwrfirst */
535         r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
536         if (r) {
537                 DSSDBG("Failed to lock PLL\n");
538                 goto err_pll_enable;
539         }
540
541         r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
542         if (r) {
543                 DSSDBG("Failed to start PHY\n");
544                 goto err_phy_enable;
545         }
546
547         hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
548
549         /* bypass TV gamma table */
550         dispc_enable_gamma_table(0);
551
552         /* tv size */
553         dss_mgr_set_timings(mgr, p);
554
555         r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
556         if (r)
557                 goto err_vid_enable;
558
559         r = dss_mgr_enable(mgr);
560         if (r)
561                 goto err_mgr_enable;
562
563         return 0;
564
565 err_mgr_enable:
566         hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
567 err_vid_enable:
568         hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
569 err_phy_enable:
570         hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
571 err_pll_enable:
572         hdmi_power_off_core(dssdev);
573         return -EIO;
574 }
575
576 static void hdmi_power_off_full(struct omap_dss_device *dssdev)
577 {
578         struct omap_overlay_manager *mgr = hdmi.output.manager;
579
580         dss_mgr_disable(mgr);
581
582         hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
583         hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
584         hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
585
586         hdmi_power_off_core(dssdev);
587 }
588
589 static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
590                                         struct omap_video_timings *timings)
591 {
592         struct hdmi_cm cm;
593
594         cm = hdmi_get_code(timings);
595         if (cm.code == -1) {
596                 return -EINVAL;
597         }
598
599         return 0;
600
601 }
602
603 static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
604                 struct omap_video_timings *timings)
605 {
606         struct hdmi_cm cm;
607         const struct hdmi_config *t;
608
609         mutex_lock(&hdmi.lock);
610
611         cm = hdmi_get_code(timings);
612         hdmi.ip_data.cfg.cm = cm;
613
614         t = hdmi_get_timings();
615         if (t != NULL) {
616                 hdmi.ip_data.cfg = *t;
617
618                 dispc_set_tv_pclk(t->timings.pixel_clock * 1000);
619         }
620
621         mutex_unlock(&hdmi.lock);
622 }
623
624 static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
625                 struct omap_video_timings *timings)
626 {
627         const struct hdmi_config *cfg;
628
629         cfg = hdmi_get_timings();
630         if (cfg == NULL)
631                 cfg = &vesa_timings[0];
632
633         memcpy(timings, &cfg->timings, sizeof(cfg->timings));
634 }
635
636 static void hdmi_dump_regs(struct seq_file *s)
637 {
638         mutex_lock(&hdmi.lock);
639
640         if (hdmi_runtime_get()) {
641                 mutex_unlock(&hdmi.lock);
642                 return;
643         }
644
645         hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
646         hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
647         hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s);
648         hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s);
649
650         hdmi_runtime_put();
651         mutex_unlock(&hdmi.lock);
652 }
653
654 static int read_edid(u8 *buf, int len)
655 {
656         int r;
657
658         mutex_lock(&hdmi.lock);
659
660         r = hdmi_runtime_get();
661         BUG_ON(r);
662
663         r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len);
664
665         hdmi_runtime_put();
666         mutex_unlock(&hdmi.lock);
667
668         return r;
669 }
670
671 static int hdmi_display_enable(struct omap_dss_device *dssdev)
672 {
673         struct omap_dss_device *out = &hdmi.output;
674         int r = 0;
675
676         DSSDBG("ENTER hdmi_display_enable\n");
677
678         mutex_lock(&hdmi.lock);
679
680         if (out == NULL || out->manager == NULL) {
681                 DSSERR("failed to enable display: no output/manager\n");
682                 r = -ENODEV;
683                 goto err0;
684         }
685
686         r = hdmi_power_on_full(dssdev);
687         if (r) {
688                 DSSERR("failed to power on device\n");
689                 goto err0;
690         }
691
692         mutex_unlock(&hdmi.lock);
693         return 0;
694
695 err0:
696         mutex_unlock(&hdmi.lock);
697         return r;
698 }
699
700 static void hdmi_display_disable(struct omap_dss_device *dssdev)
701 {
702         DSSDBG("Enter hdmi_display_disable\n");
703
704         mutex_lock(&hdmi.lock);
705
706         hdmi_power_off_full(dssdev);
707
708         mutex_unlock(&hdmi.lock);
709 }
710
711 static int hdmi_core_enable(struct omap_dss_device *dssdev)
712 {
713         int r = 0;
714
715         DSSDBG("ENTER omapdss_hdmi_core_enable\n");
716
717         mutex_lock(&hdmi.lock);
718
719         r = hdmi_power_on_core(dssdev);
720         if (r) {
721                 DSSERR("failed to power on device\n");
722                 goto err0;
723         }
724
725         mutex_unlock(&hdmi.lock);
726         return 0;
727
728 err0:
729         mutex_unlock(&hdmi.lock);
730         return r;
731 }
732
733 static void hdmi_core_disable(struct omap_dss_device *dssdev)
734 {
735         DSSDBG("Enter omapdss_hdmi_core_disable\n");
736
737         mutex_lock(&hdmi.lock);
738
739         hdmi_power_off_core(dssdev);
740
741         mutex_unlock(&hdmi.lock);
742 }
743
744 static int hdmi_get_clocks(struct platform_device *pdev)
745 {
746         struct clk *clk;
747
748         clk = devm_clk_get(&pdev->dev, "sys_clk");
749         if (IS_ERR(clk)) {
750                 DSSERR("can't get sys_clk\n");
751                 return PTR_ERR(clk);
752         }
753
754         hdmi.sys_clk = clk;
755
756         return 0;
757 }
758
759 #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
760 int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)
761 {
762         u32 deep_color;
763         bool deep_color_correct = false;
764         u32 pclk = hdmi.ip_data.cfg.timings.pixel_clock;
765
766         if (n == NULL || cts == NULL)
767                 return -EINVAL;
768
769         /* TODO: When implemented, query deep color mode here. */
770         deep_color = 100;
771
772         /*
773          * When using deep color, the default N value (as in the HDMI
774          * specification) yields to an non-integer CTS. Hence, we
775          * modify it while keeping the restrictions described in
776          * section 7.2.1 of the HDMI 1.4a specification.
777          */
778         switch (sample_freq) {
779         case 32000:
780         case 48000:
781         case 96000:
782         case 192000:
783                 if (deep_color == 125)
784                         if (pclk == 27027 || pclk == 74250)
785                                 deep_color_correct = true;
786                 if (deep_color == 150)
787                         if (pclk == 27027)
788                                 deep_color_correct = true;
789                 break;
790         case 44100:
791         case 88200:
792         case 176400:
793                 if (deep_color == 125)
794                         if (pclk == 27027)
795                                 deep_color_correct = true;
796                 break;
797         default:
798                 return -EINVAL;
799         }
800
801         if (deep_color_correct) {
802                 switch (sample_freq) {
803                 case 32000:
804                         *n = 8192;
805                         break;
806                 case 44100:
807                         *n = 12544;
808                         break;
809                 case 48000:
810                         *n = 8192;
811                         break;
812                 case 88200:
813                         *n = 25088;
814                         break;
815                 case 96000:
816                         *n = 16384;
817                         break;
818                 case 176400:
819                         *n = 50176;
820                         break;
821                 case 192000:
822                         *n = 32768;
823                         break;
824                 default:
825                         return -EINVAL;
826                 }
827         } else {
828                 switch (sample_freq) {
829                 case 32000:
830                         *n = 4096;
831                         break;
832                 case 44100:
833                         *n = 6272;
834                         break;
835                 case 48000:
836                         *n = 6144;
837                         break;
838                 case 88200:
839                         *n = 12544;
840                         break;
841                 case 96000:
842                         *n = 12288;
843                         break;
844                 case 176400:
845                         *n = 25088;
846                         break;
847                 case 192000:
848                         *n = 24576;
849                         break;
850                 default:
851                         return -EINVAL;
852                 }
853         }
854         /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
855         *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
856
857         return 0;
858 }
859
860 static bool hdmi_mode_has_audio(void)
861 {
862         if (hdmi.ip_data.cfg.cm.mode == HDMI_HDMI)
863                 return true;
864         else
865                 return false;
866 }
867
868 #endif
869
870 static int hdmi_connect(struct omap_dss_device *dssdev,
871                 struct omap_dss_device *dst)
872 {
873         struct omap_overlay_manager *mgr;
874         int r;
875
876         dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
877
878         r = hdmi_init_regulator();
879         if (r)
880                 return r;
881
882         mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
883         if (!mgr)
884                 return -ENODEV;
885
886         r = dss_mgr_connect(mgr, dssdev);
887         if (r)
888                 return r;
889
890         r = omapdss_output_set_device(dssdev, dst);
891         if (r) {
892                 DSSERR("failed to connect output to new device: %s\n",
893                                 dst->name);
894                 dss_mgr_disconnect(mgr, dssdev);
895                 return r;
896         }
897
898         return 0;
899 }
900
901 static void hdmi_disconnect(struct omap_dss_device *dssdev,
902                 struct omap_dss_device *dst)
903 {
904         WARN_ON(dst != dssdev->dst);
905
906         if (dst != dssdev->dst)
907                 return;
908
909         omapdss_output_unset_device(dssdev);
910
911         if (dssdev->manager)
912                 dss_mgr_disconnect(dssdev->manager, dssdev);
913 }
914
915 static int hdmi_read_edid(struct omap_dss_device *dssdev,
916                 u8 *edid, int len)
917 {
918         bool need_enable;
919         int r;
920
921         need_enable = hdmi.core_enabled == false;
922
923         if (need_enable) {
924                 r = hdmi_core_enable(dssdev);
925                 if (r)
926                         return r;
927         }
928
929         r = read_edid(edid, len);
930
931         if (need_enable)
932                 hdmi_core_disable(dssdev);
933
934         return r;
935 }
936
937 #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
938 static int hdmi_audio_enable(struct omap_dss_device *dssdev)
939 {
940         int r;
941
942         mutex_lock(&hdmi.lock);
943
944         if (!hdmi_mode_has_audio()) {
945                 r = -EPERM;
946                 goto err;
947         }
948
949
950         r = hdmi.ip_data.ops->audio_enable(&hdmi.ip_data);
951         if (r)
952                 goto err;
953
954         mutex_unlock(&hdmi.lock);
955         return 0;
956
957 err:
958         mutex_unlock(&hdmi.lock);
959         return r;
960 }
961
962 static void hdmi_audio_disable(struct omap_dss_device *dssdev)
963 {
964         hdmi.ip_data.ops->audio_disable(&hdmi.ip_data);
965 }
966
967 static int hdmi_audio_start(struct omap_dss_device *dssdev)
968 {
969         return hdmi.ip_data.ops->audio_start(&hdmi.ip_data);
970 }
971
972 static void hdmi_audio_stop(struct omap_dss_device *dssdev)
973 {
974         hdmi.ip_data.ops->audio_stop(&hdmi.ip_data);
975 }
976
977 static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
978 {
979         bool r;
980
981         mutex_lock(&hdmi.lock);
982
983         r = hdmi_mode_has_audio();
984
985         mutex_unlock(&hdmi.lock);
986         return r;
987 }
988
989 static int hdmi_audio_config(struct omap_dss_device *dssdev,
990                 struct omap_dss_audio *audio)
991 {
992         int r;
993
994         mutex_lock(&hdmi.lock);
995
996         if (!hdmi_mode_has_audio()) {
997                 r = -EPERM;
998                 goto err;
999         }
1000
1001         r = hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio);
1002         if (r)
1003                 goto err;
1004
1005         mutex_unlock(&hdmi.lock);
1006         return 0;
1007
1008 err:
1009         mutex_unlock(&hdmi.lock);
1010         return r;
1011 }
1012 #else
1013 static int hdmi_audio_enable(struct omap_dss_device *dssdev)
1014 {
1015         return -EPERM;
1016 }
1017
1018 static void hdmi_audio_disable(struct omap_dss_device *dssdev)
1019 {
1020 }
1021
1022 static int hdmi_audio_start(struct omap_dss_device *dssdev)
1023 {
1024         return -EPERM;
1025 }
1026
1027 static void hdmi_audio_stop(struct omap_dss_device *dssdev)
1028 {
1029 }
1030
1031 static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
1032 {
1033         return false;
1034 }
1035
1036 static int hdmi_audio_config(struct omap_dss_device *dssdev,
1037                 struct omap_dss_audio *audio)
1038 {
1039         return -EPERM;
1040 }
1041 #endif
1042
1043 static const struct omapdss_hdmi_ops hdmi_ops = {
1044         .connect                = hdmi_connect,
1045         .disconnect             = hdmi_disconnect,
1046
1047         .enable                 = hdmi_display_enable,
1048         .disable                = hdmi_display_disable,
1049
1050         .check_timings          = hdmi_display_check_timing,
1051         .set_timings            = hdmi_display_set_timing,
1052         .get_timings            = hdmi_display_get_timings,
1053
1054         .read_edid              = hdmi_read_edid,
1055
1056         .audio_enable           = hdmi_audio_enable,
1057         .audio_disable          = hdmi_audio_disable,
1058         .audio_start            = hdmi_audio_start,
1059         .audio_stop             = hdmi_audio_stop,
1060         .audio_supported        = hdmi_audio_supported,
1061         .audio_config           = hdmi_audio_config,
1062 };
1063
1064 static void hdmi_init_output(struct platform_device *pdev)
1065 {
1066         struct omap_dss_device *out = &hdmi.output;
1067
1068         out->dev = &pdev->dev;
1069         out->id = OMAP_DSS_OUTPUT_HDMI;
1070         out->output_type = OMAP_DISPLAY_TYPE_HDMI;
1071         out->name = "hdmi.0";
1072         out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
1073         out->ops.hdmi = &hdmi_ops;
1074         out->owner = THIS_MODULE;
1075
1076         omapdss_register_output(out);
1077 }
1078
1079 static void __exit hdmi_uninit_output(struct platform_device *pdev)
1080 {
1081         struct omap_dss_device *out = &hdmi.output;
1082
1083         omapdss_unregister_output(out);
1084 }
1085
1086 /* HDMI HW IP initialisation */
1087 static int omapdss_hdmihw_probe(struct platform_device *pdev)
1088 {
1089         struct resource *res;
1090         int r;
1091
1092         hdmi.pdev = pdev;
1093
1094         mutex_init(&hdmi.lock);
1095         mutex_init(&hdmi.ip_data.lock);
1096
1097         res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
1098
1099         /* Base address taken from platform */
1100         hdmi.ip_data.base_wp = devm_ioremap_resource(&pdev->dev, res);
1101         if (IS_ERR(hdmi.ip_data.base_wp))
1102                 return PTR_ERR(hdmi.ip_data.base_wp);
1103
1104         hdmi.ip_data.irq = platform_get_irq(pdev, 0);
1105         if (hdmi.ip_data.irq < 0) {
1106                 DSSERR("platform_get_irq failed\n");
1107                 return -ENODEV;
1108         }
1109
1110         r = hdmi_get_clocks(pdev);
1111         if (r) {
1112                 DSSERR("can't get clocks\n");
1113                 return r;
1114         }
1115
1116         pm_runtime_enable(&pdev->dev);
1117
1118         hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS;
1119         hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
1120         hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
1121         hdmi.ip_data.phy_offset = HDMI_PHY;
1122
1123         hdmi_init_output(pdev);
1124
1125         dss_debugfs_create_file("hdmi", hdmi_dump_regs);
1126
1127         return 0;
1128 }
1129
1130 static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
1131 {
1132         hdmi_uninit_output(pdev);
1133
1134         pm_runtime_disable(&pdev->dev);
1135
1136         return 0;
1137 }
1138
1139 static int hdmi_runtime_suspend(struct device *dev)
1140 {
1141         clk_disable_unprepare(hdmi.sys_clk);
1142
1143         dispc_runtime_put();
1144
1145         return 0;
1146 }
1147
1148 static int hdmi_runtime_resume(struct device *dev)
1149 {
1150         int r;
1151
1152         r = dispc_runtime_get();
1153         if (r < 0)
1154                 return r;
1155
1156         clk_prepare_enable(hdmi.sys_clk);
1157
1158         return 0;
1159 }
1160
1161 static const struct dev_pm_ops hdmi_pm_ops = {
1162         .runtime_suspend = hdmi_runtime_suspend,
1163         .runtime_resume = hdmi_runtime_resume,
1164 };
1165
1166 static struct platform_driver omapdss_hdmihw_driver = {
1167         .probe          = omapdss_hdmihw_probe,
1168         .remove         = __exit_p(omapdss_hdmihw_remove),
1169         .driver         = {
1170                 .name   = "omapdss_hdmi",
1171                 .owner  = THIS_MODULE,
1172                 .pm     = &hdmi_pm_ops,
1173         },
1174 };
1175
1176 int __init hdmi_init_platform_driver(void)
1177 {
1178         return platform_driver_register(&omapdss_hdmihw_driver);
1179 }
1180
1181 void __exit hdmi_uninit_platform_driver(void)
1182 {
1183         platform_driver_unregister(&omapdss_hdmihw_driver);
1184 }