1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
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
60static 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 int ct_cp_hpd_gpio;
70 int ls_oe_gpio;
71 int hpd_gpio;
72
73 bool core_enabled;
74
75 struct omap_dss_device output;
76} hdmi;
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92static const struct hdmi_config cea_timings[] = {
93 {
94 { 640, 480, 25200, 96, 16, 48, 2, 10, 33,
95 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
96 false, },
97 { 1, HDMI_HDMI },
98 },
99 {
100 { 720, 480, 27027, 62, 16, 60, 6, 9, 30,
101 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
102 false, },
103 { 2, HDMI_HDMI },
104 },
105 {
106 { 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
107 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
108 false, },
109 { 4, HDMI_HDMI },
110 },
111 {
112 { 1920, 540, 74250, 44, 88, 148, 5, 2, 15,
113 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
114 true, },
115 { 5, HDMI_HDMI },
116 },
117 {
118 { 1440, 240, 27027, 124, 38, 114, 3, 4, 15,
119 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
120 true, },
121 { 6, HDMI_HDMI },
122 },
123 {
124 { 1920, 1080, 148500, 44, 88, 148, 5, 4, 36,
125 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
126 false, },
127 { 16, HDMI_HDMI },
128 },
129 {
130 { 720, 576, 27000, 64, 12, 68, 5, 5, 39,
131 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
132 false, },
133 { 17, HDMI_HDMI },
134 },
135 {
136 { 1280, 720, 74250, 40, 440, 220, 5, 5, 20,
137 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
138 false, },
139 { 19, HDMI_HDMI },
140 },
141 {
142 { 1920, 540, 74250, 44, 528, 148, 5, 2, 15,
143 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
144 true, },
145 { 20, HDMI_HDMI },
146 },
147 {
148 { 1440, 288, 27000, 126, 24, 138, 3, 2, 19,
149 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
150 true, },
151 { 21, HDMI_HDMI },
152 },
153 {
154 { 1440, 576, 54000, 128, 24, 136, 5, 5, 39,
155 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
156 false, },
157 { 29, HDMI_HDMI },
158 },
159 {
160 { 1920, 1080, 148500, 44, 528, 148, 5, 4, 36,
161 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
162 false, },
163 { 31, HDMI_HDMI },
164 },
165 {
166 { 1920, 1080, 74250, 44, 638, 148, 5, 4, 36,
167 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
168 false, },
169 { 32, HDMI_HDMI },
170 },
171 {
172 { 2880, 480, 108108, 248, 64, 240, 6, 9, 30,
173 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
174 false, },
175 { 35, HDMI_HDMI },
176 },
177 {
178 { 2880, 576, 108000, 256, 48, 272, 5, 5, 39,
179 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
180 false, },
181 { 37, HDMI_HDMI },
182 },
183};
184
185static const struct hdmi_config vesa_timings[] = {
186
187 {
188 { 640, 480, 25175, 96, 16, 48, 2, 11, 31,
189 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
190 false, },
191 { 4, HDMI_DVI },
192 },
193 {
194 { 800, 600, 40000, 128, 40, 88, 4, 1, 23,
195 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
196 false, },
197 { 9, HDMI_DVI },
198 },
199 {
200 { 848, 480, 33750, 112, 16, 112, 8, 6, 23,
201 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
202 false, },
203 { 0xE, HDMI_DVI },
204 },
205 {
206 { 1280, 768, 79500, 128, 64, 192, 7, 3, 20,
207 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
208 false, },
209 { 0x17, HDMI_DVI },
210 },
211 {
212 { 1280, 800, 83500, 128, 72, 200, 6, 3, 22,
213 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
214 false, },
215 { 0x1C, HDMI_DVI },
216 },
217 {
218 { 1360, 768, 85500, 112, 64, 256, 6, 3, 18,
219 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
220 false, },
221 { 0x27, HDMI_DVI },
222 },
223 {
224 { 1280, 960, 108000, 112, 96, 312, 3, 1, 36,
225 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
226 false, },
227 { 0x20, HDMI_DVI },
228 },
229 {
230 { 1280, 1024, 108000, 112, 48, 248, 3, 1, 38,
231 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
232 false, },
233 { 0x23, HDMI_DVI },
234 },
235 {
236 { 1024, 768, 65000, 136, 24, 160, 6, 3, 29,
237 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
238 false, },
239 { 0x10, HDMI_DVI },
240 },
241 {
242 { 1400, 1050, 121750, 144, 88, 232, 4, 3, 32,
243 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
244 false, },
245 { 0x2A, HDMI_DVI },
246 },
247 {
248 { 1440, 900, 106500, 152, 80, 232, 6, 3, 25,
249 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
250 false, },
251 { 0x2F, HDMI_DVI },
252 },
253 {
254 { 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30,
255 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
256 false, },
257 { 0x3A, HDMI_DVI },
258 },
259 {
260 { 1366, 768, 85500, 143, 70, 213, 3, 3, 24,
261 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
262 false, },
263 { 0x51, HDMI_DVI },
264 },
265 {
266 { 1920, 1080, 148500, 44, 148, 80, 5, 4, 36,
267 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
268 false, },
269 { 0x52, HDMI_DVI },
270 },
271 {
272 { 1280, 768, 68250, 32, 48, 80, 7, 3, 12,
273 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
274 false, },
275 { 0x16, HDMI_DVI },
276 },
277 {
278 { 1400, 1050, 101000, 32, 48, 80, 4, 3, 23,
279 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
280 false, },
281 { 0x29, HDMI_DVI },
282 },
283 {
284 { 1680, 1050, 119000, 32, 48, 80, 6, 3, 21,
285 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
286 false, },
287 { 0x39, HDMI_DVI },
288 },
289 {
290 { 1280, 800, 79500, 32, 48, 80, 6, 3, 14,
291 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
292 false, },
293 { 0x1B, HDMI_DVI },
294 },
295 {
296 { 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
297 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
298 false, },
299 { 0x55, HDMI_DVI },
300 },
301 {
302 { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26,
303 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
304 false, },
305 { 0x44, HDMI_DVI },
306 },
307};
308
309static int hdmi_runtime_get(void)
310{
311 int r;
312
313 DSSDBG("hdmi_runtime_get\n");
314
315 r = pm_runtime_get_sync(&hdmi.pdev->dev);
316 WARN_ON(r < 0);
317 if (r < 0)
318 return r;
319
320 return 0;
321}
322
323static void hdmi_runtime_put(void)
324{
325 int r;
326
327 DSSDBG("hdmi_runtime_put\n");
328
329 r = pm_runtime_put_sync(&hdmi.pdev->dev);
330 WARN_ON(r < 0 && r != -ENOSYS);
331}
332
333static int hdmi_init_regulator(void)
334{
335 struct regulator *reg;
336
337 if (hdmi.vdda_hdmi_dac_reg != NULL)
338 return 0;
339
340 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
341
342
343 if (IS_ERR(reg))
344 reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC");
345
346 if (IS_ERR(reg)) {
347 DSSERR("can't get VDDA_HDMI_DAC regulator\n");
348 return PTR_ERR(reg);
349 }
350
351 hdmi.vdda_hdmi_dac_reg = reg;
352
353 return 0;
354}
355
356static int hdmi_init_display(struct omap_dss_device *dssdev)
357{
358 int r;
359
360 struct gpio gpios[] = {
361 { hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" },
362 { hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" },
363 { hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" },
364 };
365
366 DSSDBG("init_display\n");
367
368 dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
369
370 r = hdmi_init_regulator();
371 if (r)
372 return r;
373
374 r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
375 if (r)
376 return r;
377
378 return 0;
379}
380
381static void hdmi_uninit_display(struct omap_dss_device *dssdev)
382{
383 DSSDBG("uninit_display\n");
384
385 gpio_free(hdmi.ct_cp_hpd_gpio);
386 gpio_free(hdmi.ls_oe_gpio);
387 gpio_free(hdmi.hpd_gpio);
388}
389
390static const struct hdmi_config *hdmi_find_timing(
391 const struct hdmi_config *timings_arr,
392 int len)
393{
394 int i;
395
396 for (i = 0; i < len; i++) {
397 if (timings_arr[i].cm.code == hdmi.ip_data.cfg.cm.code)
398 return &timings_arr[i];
399 }
400 return NULL;
401}
402
403static const struct hdmi_config *hdmi_get_timings(void)
404{
405 const struct hdmi_config *arr;
406 int len;
407
408 if (hdmi.ip_data.cfg.cm.mode == HDMI_DVI) {
409 arr = vesa_timings;
410 len = ARRAY_SIZE(vesa_timings);
411 } else {
412 arr = cea_timings;
413 len = ARRAY_SIZE(cea_timings);
414 }
415
416 return hdmi_find_timing(arr, len);
417}
418
419static bool hdmi_timings_compare(struct omap_video_timings *timing1,
420 const struct omap_video_timings *timing2)
421{
422 int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
423
424 if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) ==
425 DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
426 (timing2->x_res == timing1->x_res) &&
427 (timing2->y_res == timing1->y_res)) {
428
429 timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
430 timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
431 timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
432 timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
433
434 DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
435 "timing2_hsync = %d timing2_vsync = %d\n",
436 timing1_hsync, timing1_vsync,
437 timing2_hsync, timing2_vsync);
438
439 if ((timing1_hsync == timing2_hsync) &&
440 (timing1_vsync == timing2_vsync)) {
441 return true;
442 }
443 }
444 return false;
445}
446
447static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
448{
449 int i;
450 struct hdmi_cm cm = {-1};
451 DSSDBG("hdmi_get_code\n");
452
453 for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
454 if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
455 cm = cea_timings[i].cm;
456 goto end;
457 }
458 }
459 for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
460 if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
461 cm = vesa_timings[i].cm;
462 goto end;
463 }
464 }
465
466end: return cm;
467
468}
469
470static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
471 struct hdmi_pll_info *pi)
472{
473 unsigned long clkin, refclk;
474 u32 mf;
475
476 clkin = clk_get_rate(hdmi.sys_clk) / 10000;
477
478
479
480
481
482 pi->regn = HDMI_DEFAULT_REGN;
483
484 refclk = clkin / pi->regn;
485
486 pi->regm2 = HDMI_DEFAULT_REGM2;
487
488
489
490
491
492 pi->regm = phy * pi->regm2 / refclk;
493
494
495
496
497
498
499 mf = (phy - pi->regm / pi->regm2 * refclk) * 262144;
500 pi->regmf = pi->regm2 * mf / refclk;
501
502
503
504
505
506 pi->dcofreq = phy > 1000 * 100;
507 pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
508
509
510 pi->refsel = HDMI_REFSEL_SYSCLK;
511
512 DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
513 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
514}
515
516static int hdmi_power_on_core(struct omap_dss_device *dssdev)
517{
518 int r;
519
520 if (gpio_is_valid(hdmi.ct_cp_hpd_gpio))
521 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
522 if (gpio_is_valid(hdmi.ls_oe_gpio))
523 gpio_set_value(hdmi.ls_oe_gpio, 1);
524
525
526 udelay(300);
527
528 r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
529 if (r)
530 goto err_vdac_enable;
531
532 r = hdmi_runtime_get();
533 if (r)
534 goto err_runtime_get;
535
536
537 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
538
539 hdmi.core_enabled = true;
540
541 return 0;
542
543err_runtime_get:
544 regulator_disable(hdmi.vdda_hdmi_dac_reg);
545err_vdac_enable:
546 if (gpio_is_valid(hdmi.ct_cp_hpd_gpio))
547 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
548 if (gpio_is_valid(hdmi.ls_oe_gpio))
549 gpio_set_value(hdmi.ls_oe_gpio, 0);
550 return r;
551}
552
553static void hdmi_power_off_core(struct omap_dss_device *dssdev)
554{
555 hdmi.core_enabled = false;
556
557 hdmi_runtime_put();
558 regulator_disable(hdmi.vdda_hdmi_dac_reg);
559 if (gpio_is_valid(hdmi.ct_cp_hpd_gpio))
560 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
561 if (gpio_is_valid(hdmi.ls_oe_gpio))
562 gpio_set_value(hdmi.ls_oe_gpio, 0);
563}
564
565static int hdmi_power_on_full(struct omap_dss_device *dssdev)
566{
567 int r;
568 struct omap_video_timings *p;
569 struct omap_overlay_manager *mgr = hdmi.output.manager;
570 unsigned long phy;
571
572 r = hdmi_power_on_core(dssdev);
573 if (r)
574 return r;
575
576 dss_mgr_disable(mgr);
577
578 p = &hdmi.ip_data.cfg.timings;
579
580 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
581
582 phy = p->pixel_clock;
583
584 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
585
586 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
587
588
589 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
590 if (r) {
591 DSSDBG("Failed to lock PLL\n");
592 goto err_pll_enable;
593 }
594
595 r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
596 if (r) {
597 DSSDBG("Failed to start PHY\n");
598 goto err_phy_enable;
599 }
600
601 hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
602
603
604 dispc_enable_gamma_table(0);
605
606
607 dss_mgr_set_timings(mgr, p);
608
609 r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
610 if (r)
611 goto err_vid_enable;
612
613 r = dss_mgr_enable(mgr);
614 if (r)
615 goto err_mgr_enable;
616
617 return 0;
618
619err_mgr_enable:
620 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
621err_vid_enable:
622 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
623err_phy_enable:
624 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
625err_pll_enable:
626 hdmi_power_off_core(dssdev);
627 return -EIO;
628}
629
630static void hdmi_power_off_full(struct omap_dss_device *dssdev)
631{
632 struct omap_overlay_manager *mgr = hdmi.output.manager;
633
634 dss_mgr_disable(mgr);
635
636 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
637 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
638 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
639
640 hdmi_power_off_core(dssdev);
641}
642
643int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
644 struct omap_video_timings *timings)
645{
646 struct hdmi_cm cm;
647
648 cm = hdmi_get_code(timings);
649 if (cm.code == -1) {
650 return -EINVAL;
651 }
652
653 return 0;
654
655}
656
657void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
658 struct omap_video_timings *timings)
659{
660 struct hdmi_cm cm;
661 const struct hdmi_config *t;
662
663 mutex_lock(&hdmi.lock);
664
665 cm = hdmi_get_code(timings);
666 hdmi.ip_data.cfg.cm = cm;
667
668 t = hdmi_get_timings();
669 if (t != NULL)
670 hdmi.ip_data.cfg = *t;
671
672 dispc_set_tv_pclk(t->timings.pixel_clock * 1000);
673
674 mutex_unlock(&hdmi.lock);
675}
676
677static void omapdss_hdmi_display_get_timings(struct omap_dss_device *dssdev,
678 struct omap_video_timings *timings)
679{
680 const struct hdmi_config *cfg;
681
682 cfg = hdmi_get_timings();
683 if (cfg == NULL)
684 cfg = &vesa_timings[0];
685
686 memcpy(timings, &cfg->timings, sizeof(cfg->timings));
687}
688
689static void hdmi_dump_regs(struct seq_file *s)
690{
691 mutex_lock(&hdmi.lock);
692
693 if (hdmi_runtime_get()) {
694 mutex_unlock(&hdmi.lock);
695 return;
696 }
697
698 hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
699 hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
700 hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s);
701 hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s);
702
703 hdmi_runtime_put();
704 mutex_unlock(&hdmi.lock);
705}
706
707int omapdss_hdmi_read_edid(u8 *buf, int len)
708{
709 int r;
710
711 mutex_lock(&hdmi.lock);
712
713 r = hdmi_runtime_get();
714 BUG_ON(r);
715
716 r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len);
717
718 hdmi_runtime_put();
719 mutex_unlock(&hdmi.lock);
720
721 return r;
722}
723
724bool omapdss_hdmi_detect(void)
725{
726 int r;
727
728 mutex_lock(&hdmi.lock);
729
730 r = hdmi_runtime_get();
731 BUG_ON(r);
732
733 r = gpio_get_value(hdmi.hpd_gpio);
734
735 hdmi_runtime_put();
736 mutex_unlock(&hdmi.lock);
737
738 return r == 1;
739}
740
741int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
742{
743 struct omap_dss_device *out = &hdmi.output;
744 int r = 0;
745
746 DSSDBG("ENTER hdmi_display_enable\n");
747
748 mutex_lock(&hdmi.lock);
749
750 if (out == NULL || out->manager == NULL) {
751 DSSERR("failed to enable display: no output/manager\n");
752 r = -ENODEV;
753 goto err0;
754 }
755
756 r = hdmi_power_on_full(dssdev);
757 if (r) {
758 DSSERR("failed to power on device\n");
759 goto err0;
760 }
761
762 mutex_unlock(&hdmi.lock);
763 return 0;
764
765err0:
766 mutex_unlock(&hdmi.lock);
767 return r;
768}
769
770void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
771{
772 DSSDBG("Enter hdmi_display_disable\n");
773
774 mutex_lock(&hdmi.lock);
775
776 hdmi_power_off_full(dssdev);
777
778 mutex_unlock(&hdmi.lock);
779}
780
781int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev)
782{
783 int r = 0;
784
785 DSSDBG("ENTER omapdss_hdmi_core_enable\n");
786
787 mutex_lock(&hdmi.lock);
788
789 r = hdmi_power_on_core(dssdev);
790 if (r) {
791 DSSERR("failed to power on device\n");
792 goto err0;
793 }
794
795 mutex_unlock(&hdmi.lock);
796 return 0;
797
798err0:
799 mutex_unlock(&hdmi.lock);
800 return r;
801}
802
803void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev)
804{
805 DSSDBG("Enter omapdss_hdmi_core_disable\n");
806
807 mutex_lock(&hdmi.lock);
808
809 hdmi_power_off_core(dssdev);
810
811 mutex_unlock(&hdmi.lock);
812}
813
814static int hdmi_get_clocks(struct platform_device *pdev)
815{
816 struct clk *clk;
817
818 clk = devm_clk_get(&pdev->dev, "sys_clk");
819 if (IS_ERR(clk)) {
820 DSSERR("can't get sys_clk\n");
821 return PTR_ERR(clk);
822 }
823
824 hdmi.sys_clk = clk;
825
826 return 0;
827}
828
829#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
830int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)
831{
832 u32 deep_color;
833 bool deep_color_correct = false;
834 u32 pclk = hdmi.ip_data.cfg.timings.pixel_clock;
835
836 if (n == NULL || cts == NULL)
837 return -EINVAL;
838
839
840 deep_color = 100;
841
842
843
844
845
846
847
848 switch (sample_freq) {
849 case 32000:
850 case 48000:
851 case 96000:
852 case 192000:
853 if (deep_color == 125)
854 if (pclk == 27027 || pclk == 74250)
855 deep_color_correct = true;
856 if (deep_color == 150)
857 if (pclk == 27027)
858 deep_color_correct = true;
859 break;
860 case 44100:
861 case 88200:
862 case 176400:
863 if (deep_color == 125)
864 if (pclk == 27027)
865 deep_color_correct = true;
866 break;
867 default:
868 return -EINVAL;
869 }
870
871 if (deep_color_correct) {
872 switch (sample_freq) {
873 case 32000:
874 *n = 8192;
875 break;
876 case 44100:
877 *n = 12544;
878 break;
879 case 48000:
880 *n = 8192;
881 break;
882 case 88200:
883 *n = 25088;
884 break;
885 case 96000:
886 *n = 16384;
887 break;
888 case 176400:
889 *n = 50176;
890 break;
891 case 192000:
892 *n = 32768;
893 break;
894 default:
895 return -EINVAL;
896 }
897 } else {
898 switch (sample_freq) {
899 case 32000:
900 *n = 4096;
901 break;
902 case 44100:
903 *n = 6272;
904 break;
905 case 48000:
906 *n = 6144;
907 break;
908 case 88200:
909 *n = 12544;
910 break;
911 case 96000:
912 *n = 12288;
913 break;
914 case 176400:
915 *n = 25088;
916 break;
917 case 192000:
918 *n = 24576;
919 break;
920 default:
921 return -EINVAL;
922 }
923 }
924
925 *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
926
927 return 0;
928}
929
930int hdmi_audio_enable(void)
931{
932 DSSDBG("audio_enable\n");
933
934 return hdmi.ip_data.ops->audio_enable(&hdmi.ip_data);
935}
936
937void hdmi_audio_disable(void)
938{
939 DSSDBG("audio_disable\n");
940
941 hdmi.ip_data.ops->audio_disable(&hdmi.ip_data);
942}
943
944int hdmi_audio_start(void)
945{
946 DSSDBG("audio_start\n");
947
948 return hdmi.ip_data.ops->audio_start(&hdmi.ip_data);
949}
950
951void hdmi_audio_stop(void)
952{
953 DSSDBG("audio_stop\n");
954
955 hdmi.ip_data.ops->audio_stop(&hdmi.ip_data);
956}
957
958bool hdmi_mode_has_audio(void)
959{
960 if (hdmi.ip_data.cfg.cm.mode == HDMI_HDMI)
961 return true;
962 else
963 return false;
964}
965
966int hdmi_audio_config(struct omap_dss_audio *audio)
967{
968 return hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio);
969}
970
971#endif
972
973static struct omap_dss_device *hdmi_find_dssdev(struct platform_device *pdev)
974{
975 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
976 const char *def_disp_name = omapdss_get_default_display_name();
977 struct omap_dss_device *def_dssdev;
978 int i;
979
980 def_dssdev = NULL;
981
982 for (i = 0; i < pdata->num_devices; ++i) {
983 struct omap_dss_device *dssdev = pdata->devices[i];
984
985 if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
986 continue;
987
988 if (def_dssdev == NULL)
989 def_dssdev = dssdev;
990
991 if (def_disp_name != NULL &&
992 strcmp(dssdev->name, def_disp_name) == 0) {
993 def_dssdev = dssdev;
994 break;
995 }
996 }
997
998 return def_dssdev;
999}
1000
1001static int hdmi_probe_pdata(struct platform_device *pdev)
1002{
1003 struct omap_dss_device *plat_dssdev;
1004 struct omap_dss_device *dssdev;
1005 struct omap_dss_hdmi_data *priv;
1006 int r;
1007
1008 plat_dssdev = hdmi_find_dssdev(pdev);
1009
1010 if (!plat_dssdev)
1011 return 0;
1012
1013 dssdev = dss_alloc_and_init_device(&pdev->dev);
1014 if (!dssdev)
1015 return -ENOMEM;
1016
1017 dss_copy_device_pdata(dssdev, plat_dssdev);
1018
1019 priv = dssdev->data;
1020
1021 hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
1022 hdmi.ls_oe_gpio = priv->ls_oe_gpio;
1023 hdmi.hpd_gpio = priv->hpd_gpio;
1024
1025 r = hdmi_init_display(dssdev);
1026 if (r) {
1027 DSSERR("device %s init failed: %d\n", dssdev->name, r);
1028 dss_put_device(dssdev);
1029 return r;
1030 }
1031
1032 r = omapdss_output_set_device(&hdmi.output, dssdev);
1033 if (r) {
1034 DSSERR("failed to connect output to new device: %s\n",
1035 dssdev->name);
1036 dss_put_device(dssdev);
1037 return r;
1038 }
1039
1040 r = dss_add_device(dssdev);
1041 if (r) {
1042 DSSERR("device %s register failed: %d\n", dssdev->name, r);
1043 omapdss_output_unset_device(&hdmi.output);
1044 hdmi_uninit_display(dssdev);
1045 dss_put_device(dssdev);
1046 return r;
1047 }
1048
1049 return 0;
1050}
1051
1052static int hdmi_connect(struct omap_dss_device *dssdev,
1053 struct omap_dss_device *dst)
1054{
1055 struct omap_overlay_manager *mgr;
1056 int r;
1057
1058 dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
1059
1060 r = hdmi_init_regulator();
1061 if (r)
1062 return r;
1063
1064 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
1065 if (!mgr)
1066 return -ENODEV;
1067
1068 r = dss_mgr_connect(mgr, dssdev);
1069 if (r)
1070 return r;
1071
1072 r = omapdss_output_set_device(dssdev, dst);
1073 if (r) {
1074 DSSERR("failed to connect output to new device: %s\n",
1075 dst->name);
1076 dss_mgr_disconnect(mgr, dssdev);
1077 return r;
1078 }
1079
1080 return 0;
1081}
1082
1083static void hdmi_disconnect(struct omap_dss_device *dssdev,
1084 struct omap_dss_device *dst)
1085{
1086 WARN_ON(dst != dssdev->device);
1087
1088 if (dst != dssdev->device)
1089 return;
1090
1091 omapdss_output_unset_device(dssdev);
1092
1093 if (dssdev->manager)
1094 dss_mgr_disconnect(dssdev->manager, dssdev);
1095}
1096
1097static int hdmi_read_edid(struct omap_dss_device *dssdev,
1098 u8 *edid, int len)
1099{
1100 bool need_enable;
1101 int r;
1102
1103 need_enable = hdmi.core_enabled == false;
1104
1105 if (need_enable) {
1106 r = omapdss_hdmi_core_enable(dssdev);
1107 if (r)
1108 return r;
1109 }
1110
1111 r = omapdss_hdmi_read_edid(edid, len);
1112
1113 if (need_enable)
1114 omapdss_hdmi_core_disable(dssdev);
1115
1116 return r;
1117}
1118
1119#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
1120static int omapdss_hdmi_audio_enable(struct omap_dss_device *dssdev)
1121{
1122 int r;
1123
1124 mutex_lock(&hdmi.lock);
1125
1126 if (!hdmi_mode_has_audio()) {
1127 r = -EPERM;
1128 goto err;
1129 }
1130
1131 r = hdmi_audio_enable();
1132 if (r)
1133 goto err;
1134
1135 mutex_unlock(&hdmi.lock);
1136 return 0;
1137
1138err:
1139 mutex_unlock(&hdmi.lock);
1140 return r;
1141}
1142
1143static void omapdss_hdmi_audio_disable(struct omap_dss_device *dssdev)
1144{
1145 hdmi_audio_disable();
1146}
1147
1148static int omapdss_hdmi_audio_start(struct omap_dss_device *dssdev)
1149{
1150 return hdmi_audio_start();
1151}
1152
1153static void omapdss_hdmi_audio_stop(struct omap_dss_device *dssdev)
1154{
1155 hdmi_audio_stop();
1156}
1157
1158static bool omapdss_hdmi_audio_supported(struct omap_dss_device *dssdev)
1159{
1160 bool r;
1161
1162 mutex_lock(&hdmi.lock);
1163
1164 r = hdmi_mode_has_audio();
1165
1166 mutex_unlock(&hdmi.lock);
1167 return r;
1168}
1169
1170static int omapdss_hdmi_audio_config(struct omap_dss_device *dssdev,
1171 struct omap_dss_audio *audio)
1172{
1173 int r;
1174
1175 mutex_lock(&hdmi.lock);
1176
1177 if (!hdmi_mode_has_audio()) {
1178 r = -EPERM;
1179 goto err;
1180 }
1181
1182 r = hdmi_audio_config(audio);
1183 if (r)
1184 goto err;
1185
1186 mutex_unlock(&hdmi.lock);
1187 return 0;
1188
1189err:
1190 mutex_unlock(&hdmi.lock);
1191 return r;
1192}
1193#else
1194static int omapdss_hdmi_audio_enable(struct omap_dss_device *dssdev)
1195{
1196 return -EPERM;
1197}
1198
1199static void omapdss_hdmi_audio_disable(struct omap_dss_device *dssdev)
1200{
1201}
1202
1203static int omapdss_hdmi_audio_start(struct omap_dss_device *dssdev)
1204{
1205 return -EPERM;
1206}
1207
1208static void omapdss_hdmi_audio_stop(struct omap_dss_device *dssdev)
1209{
1210}
1211
1212static bool omapdss_hdmi_audio_supported(struct omap_dss_device *dssdev)
1213{
1214 return false;
1215}
1216
1217static int omapdss_hdmi_audio_config(struct omap_dss_device *dssdev,
1218 struct omap_dss_audio *audio)
1219{
1220 return -EPERM;
1221}
1222#endif
1223
1224static const struct omapdss_hdmi_ops hdmi_ops = {
1225 .connect = hdmi_connect,
1226 .disconnect = hdmi_disconnect,
1227
1228 .enable = omapdss_hdmi_display_enable,
1229 .disable = omapdss_hdmi_display_disable,
1230
1231 .check_timings = omapdss_hdmi_display_check_timing,
1232 .set_timings = omapdss_hdmi_display_set_timing,
1233 .get_timings = omapdss_hdmi_display_get_timings,
1234
1235 .read_edid = hdmi_read_edid,
1236
1237 .audio_enable = omapdss_hdmi_audio_enable,
1238 .audio_disable = omapdss_hdmi_audio_disable,
1239 .audio_start = omapdss_hdmi_audio_start,
1240 .audio_stop = omapdss_hdmi_audio_stop,
1241 .audio_supported = omapdss_hdmi_audio_supported,
1242 .audio_config = omapdss_hdmi_audio_config,
1243};
1244
1245static void hdmi_init_output(struct platform_device *pdev)
1246{
1247 struct omap_dss_device *out = &hdmi.output;
1248
1249 out->dev = &pdev->dev;
1250 out->id = OMAP_DSS_OUTPUT_HDMI;
1251 out->output_type = OMAP_DISPLAY_TYPE_HDMI;
1252 out->name = "hdmi.0";
1253 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
1254 out->ops.hdmi = &hdmi_ops;
1255 out->owner = THIS_MODULE;
1256
1257 omapdss_register_output(out);
1258}
1259
1260static void __exit hdmi_uninit_output(struct platform_device *pdev)
1261{
1262 struct omap_dss_device *out = &hdmi.output;
1263
1264 omapdss_unregister_output(out);
1265}
1266
1267
1268static int omapdss_hdmihw_probe(struct platform_device *pdev)
1269{
1270 struct resource *res;
1271 int r;
1272
1273 hdmi.pdev = pdev;
1274
1275 mutex_init(&hdmi.lock);
1276 mutex_init(&hdmi.ip_data.lock);
1277
1278 res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
1279
1280
1281 hdmi.ip_data.base_wp = devm_ioremap_resource(&pdev->dev, res);
1282 if (IS_ERR(hdmi.ip_data.base_wp))
1283 return PTR_ERR(hdmi.ip_data.base_wp);
1284
1285 hdmi.ip_data.irq = platform_get_irq(pdev, 0);
1286 if (hdmi.ip_data.irq < 0) {
1287 DSSERR("platform_get_irq failed\n");
1288 return -ENODEV;
1289 }
1290
1291 r = hdmi_get_clocks(pdev);
1292 if (r) {
1293 DSSERR("can't get clocks\n");
1294 return r;
1295 }
1296
1297 pm_runtime_enable(&pdev->dev);
1298
1299 hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS;
1300 hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
1301 hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
1302 hdmi.ip_data.phy_offset = HDMI_PHY;
1303
1304 hdmi.ct_cp_hpd_gpio = -1;
1305 hdmi.ls_oe_gpio = -1;
1306 hdmi.hpd_gpio = -1;
1307
1308 hdmi_init_output(pdev);
1309
1310 r = hdmi_panel_init();
1311 if (r) {
1312 DSSERR("can't init panel\n");
1313 return r;
1314 }
1315
1316 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
1317
1318 if (pdev->dev.platform_data) {
1319 r = hdmi_probe_pdata(pdev);
1320 if (r)
1321 goto err_probe;
1322 }
1323
1324 return 0;
1325
1326err_probe:
1327 hdmi_panel_exit();
1328 hdmi_uninit_output(pdev);
1329 pm_runtime_disable(&pdev->dev);
1330 return r;
1331}
1332
1333static int __exit hdmi_remove_child(struct device *dev, void *data)
1334{
1335 struct omap_dss_device *dssdev = to_dss_device(dev);
1336 hdmi_uninit_display(dssdev);
1337 return 0;
1338}
1339
1340static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
1341{
1342 device_for_each_child(&pdev->dev, NULL, hdmi_remove_child);
1343
1344 dss_unregister_child_devices(&pdev->dev);
1345
1346 hdmi_panel_exit();
1347
1348 hdmi_uninit_output(pdev);
1349
1350 pm_runtime_disable(&pdev->dev);
1351
1352 return 0;
1353}
1354
1355static int hdmi_runtime_suspend(struct device *dev)
1356{
1357 clk_disable_unprepare(hdmi.sys_clk);
1358
1359 dispc_runtime_put();
1360
1361 return 0;
1362}
1363
1364static int hdmi_runtime_resume(struct device *dev)
1365{
1366 int r;
1367
1368 r = dispc_runtime_get();
1369 if (r < 0)
1370 return r;
1371
1372 clk_prepare_enable(hdmi.sys_clk);
1373
1374 return 0;
1375}
1376
1377static const struct dev_pm_ops hdmi_pm_ops = {
1378 .runtime_suspend = hdmi_runtime_suspend,
1379 .runtime_resume = hdmi_runtime_resume,
1380};
1381
1382static struct platform_driver omapdss_hdmihw_driver = {
1383 .probe = omapdss_hdmihw_probe,
1384 .remove = __exit_p(omapdss_hdmihw_remove),
1385 .driver = {
1386 .name = "omapdss_hdmi",
1387 .owner = THIS_MODULE,
1388 .pm = &hdmi_pm_ops,
1389 },
1390};
1391
1392int __init hdmi_init_platform_driver(void)
1393{
1394 return platform_driver_register(&omapdss_hdmihw_driver);
1395}
1396
1397void __exit hdmi_uninit_platform_driver(void)
1398{
1399 platform_driver_unregister(&omapdss_hdmihw_driver);
1400}
1401