aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2
diff options
context:
space:
mode:
authorArchit Taneja <archit@ti.com>2013-09-17 02:13:15 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2013-10-09 05:42:37 -0400
commit08d83e4e172176f8a66697ffb26eaa5ac5c2ef03 (patch)
tree700c97cdcc56188e8aa1c0aca2b7663f2100ba3d /drivers/video/omap2
parentc8a0d959b776f6799b995941ee0c2f8c67110fe8 (diff)
omapdss: HDMI: move common functions to a separate file
The OMAP4 HDMI encoder driver(hdmi4.c) contains timings tables, and helper functions which can be used as is by the OMAP5/DRA7x encoder driver. Move these to hdmi_common.c so that it's not replicated in the future. Signed-off-by: Archit Taneja <archit@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video/omap2')
-rw-r--r--drivers/video/omap2/dss/Makefile4
-rw-r--r--drivers/video/omap2/dss/hdmi.h11
-rw-r--r--drivers/video/omap2/dss/hdmi4.c438
-rw-r--r--drivers/video/omap2/dss/hdmi4_core.c4
-rw-r--r--drivers/video/omap2/dss/hdmi4_core.h2
-rw-r--r--drivers/video/omap2/dss/hdmi_common.c423
6 files changed, 447 insertions, 435 deletions
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index f87ca3216a1f..d3aa91bdd6a8 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -10,6 +10,6 @@ omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
10omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o 10omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
11omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o 11omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
12omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o 12omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
13omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi_wp.o hdmi_pll.o hdmi_phy.o \ 13omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi_common.o hdmi_wp.o hdmi_pll.o \
14 hdmi4_core.o 14 hdmi_phy.o hdmi4_core.o
15ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG 15ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h
index b92d981063dc..b0493768a5d7 100644
--- a/drivers/video/omap2/dss/hdmi.h
+++ b/drivers/video/omap2/dss/hdmi.h
@@ -423,13 +423,22 @@ void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp);
423void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s); 423void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s);
424int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy); 424int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy);
425 425
426/* HDMI common funcs */
427const struct hdmi_config *hdmi_default_timing(void);
428const struct hdmi_config *hdmi_get_timings(int mode, int code);
429struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing);
430
426#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) 431#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
427int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts); 432int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts);
428int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable); 433int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable);
429int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable); 434int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable);
430void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp, 435void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
431 struct hdmi_audio_format *aud_fmt); 436 struct hdmi_audio_format *aud_fmt);
432void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp, 437void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp,
433 struct hdmi_audio_dma *aud_dma); 438 struct hdmi_audio_dma *aud_dma);
439static inline bool hdmi_mode_has_audio(int mode)
440{
441 return mode == HDMI_HDMI ? true : false;
442}
434#endif 443#endif
435#endif 444#endif
diff --git a/drivers/video/omap2/dss/hdmi4.c b/drivers/video/omap2/dss/hdmi4.c
index ab43069c10ed..e14009614338 100644
--- a/drivers/video/omap2/dss/hdmi4.c
+++ b/drivers/video/omap2/dss/hdmi4.c
@@ -57,237 +57,6 @@ static struct {
57 struct omap_dss_device output; 57 struct omap_dss_device output;
58} hdmi; 58} hdmi;
59 59
60/*
61 * Logic for the below structure :
62 * user enters the CEA or VESA timings by specifying the HDMI/DVI code.
63 * There is a correspondence between CEA/VESA timing and code, please
64 * refer to section 6.3 in HDMI 1.3 specification for timing code.
65 *
66 * In the below structure, cea_vesa_timings corresponds to all OMAP4
67 * supported CEA and VESA timing values.code_cea corresponds to the CEA
68 * code, It is used to get the timing from cea_vesa_timing array.Similarly
69 * with code_vesa. Code_index is used for back mapping, that is once EDID
70 * is read from the TV, EDID is parsed to find the timing values and then
71 * map it to corresponding CEA or VESA index.
72 */
73
74static const struct hdmi_config cea_timings[] = {
75 {
76 { 640, 480, 25200, 96, 16, 48, 2, 10, 33,
77 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
78 false, },
79 { 1, HDMI_HDMI },
80 },
81 {
82 { 720, 480, 27027, 62, 16, 60, 6, 9, 30,
83 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
84 false, },
85 { 2, HDMI_HDMI },
86 },
87 {
88 { 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
89 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
90 false, },
91 { 4, HDMI_HDMI },
92 },
93 {
94 { 1920, 540, 74250, 44, 88, 148, 5, 2, 15,
95 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
96 true, },
97 { 5, HDMI_HDMI },
98 },
99 {
100 { 1440, 240, 27027, 124, 38, 114, 3, 4, 15,
101 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
102 true, },
103 { 6, HDMI_HDMI },
104 },
105 {
106 { 1920, 1080, 148500, 44, 88, 148, 5, 4, 36,
107 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
108 false, },
109 { 16, HDMI_HDMI },
110 },
111 {
112 { 720, 576, 27000, 64, 12, 68, 5, 5, 39,
113 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
114 false, },
115 { 17, HDMI_HDMI },
116 },
117 {
118 { 1280, 720, 74250, 40, 440, 220, 5, 5, 20,
119 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
120 false, },
121 { 19, HDMI_HDMI },
122 },
123 {
124 { 1920, 540, 74250, 44, 528, 148, 5, 2, 15,
125 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
126 true, },
127 { 20, HDMI_HDMI },
128 },
129 {
130 { 1440, 288, 27000, 126, 24, 138, 3, 2, 19,
131 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
132 true, },
133 { 21, HDMI_HDMI },
134 },
135 {
136 { 1440, 576, 54000, 128, 24, 136, 5, 5, 39,
137 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
138 false, },
139 { 29, HDMI_HDMI },
140 },
141 {
142 { 1920, 1080, 148500, 44, 528, 148, 5, 4, 36,
143 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
144 false, },
145 { 31, HDMI_HDMI },
146 },
147 {
148 { 1920, 1080, 74250, 44, 638, 148, 5, 4, 36,
149 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
150 false, },
151 { 32, HDMI_HDMI },
152 },
153 {
154 { 2880, 480, 108108, 248, 64, 240, 6, 9, 30,
155 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
156 false, },
157 { 35, HDMI_HDMI },
158 },
159 {
160 { 2880, 576, 108000, 256, 48, 272, 5, 5, 39,
161 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
162 false, },
163 { 37, HDMI_HDMI },
164 },
165};
166
167static const struct hdmi_config vesa_timings[] = {
168/* VESA From Here */
169 {
170 { 640, 480, 25175, 96, 16, 48, 2, 11, 31,
171 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
172 false, },
173 { 4, HDMI_DVI },
174 },
175 {
176 { 800, 600, 40000, 128, 40, 88, 4, 1, 23,
177 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
178 false, },
179 { 9, HDMI_DVI },
180 },
181 {
182 { 848, 480, 33750, 112, 16, 112, 8, 6, 23,
183 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
184 false, },
185 { 0xE, HDMI_DVI },
186 },
187 {
188 { 1280, 768, 79500, 128, 64, 192, 7, 3, 20,
189 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
190 false, },
191 { 0x17, HDMI_DVI },
192 },
193 {
194 { 1280, 800, 83500, 128, 72, 200, 6, 3, 22,
195 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
196 false, },
197 { 0x1C, HDMI_DVI },
198 },
199 {
200 { 1360, 768, 85500, 112, 64, 256, 6, 3, 18,
201 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
202 false, },
203 { 0x27, HDMI_DVI },
204 },
205 {
206 { 1280, 960, 108000, 112, 96, 312, 3, 1, 36,
207 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
208 false, },
209 { 0x20, HDMI_DVI },
210 },
211 {
212 { 1280, 1024, 108000, 112, 48, 248, 3, 1, 38,
213 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
214 false, },
215 { 0x23, HDMI_DVI },
216 },
217 {
218 { 1024, 768, 65000, 136, 24, 160, 6, 3, 29,
219 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
220 false, },
221 { 0x10, HDMI_DVI },
222 },
223 {
224 { 1400, 1050, 121750, 144, 88, 232, 4, 3, 32,
225 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
226 false, },
227 { 0x2A, HDMI_DVI },
228 },
229 {
230 { 1440, 900, 106500, 152, 80, 232, 6, 3, 25,
231 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
232 false, },
233 { 0x2F, HDMI_DVI },
234 },
235 {
236 { 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30,
237 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
238 false, },
239 { 0x3A, HDMI_DVI },
240 },
241 {
242 { 1366, 768, 85500, 143, 70, 213, 3, 3, 24,
243 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
244 false, },
245 { 0x51, HDMI_DVI },
246 },
247 {
248 { 1920, 1080, 148500, 44, 148, 80, 5, 4, 36,
249 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
250 false, },
251 { 0x52, HDMI_DVI },
252 },
253 {
254 { 1280, 768, 68250, 32, 48, 80, 7, 3, 12,
255 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
256 false, },
257 { 0x16, HDMI_DVI },
258 },
259 {
260 { 1400, 1050, 101000, 32, 48, 80, 4, 3, 23,
261 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
262 false, },
263 { 0x29, HDMI_DVI },
264 },
265 {
266 { 1680, 1050, 119000, 32, 48, 80, 6, 3, 21,
267 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
268 false, },
269 { 0x39, HDMI_DVI },
270 },
271 {
272 { 1280, 800, 79500, 32, 48, 80, 6, 3, 14,
273 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
274 false, },
275 { 0x1B, HDMI_DVI },
276 },
277 {
278 { 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
279 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
280 false, },
281 { 0x55, HDMI_DVI },
282 },
283 {
284 { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26,
285 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
286 false, },
287 { 0x44, HDMI_DVI },
288 },
289};
290
291static int hdmi_runtime_get(void) 60static int hdmi_runtime_get(void)
292{ 61{
293 int r; 62 int r;
@@ -335,86 +104,6 @@ static int hdmi_init_regulator(void)
335 return 0; 104 return 0;
336} 105}
337 106
338static const struct hdmi_config *hdmi_find_timing(
339 const struct hdmi_config *timings_arr,
340 int len)
341{
342 int i;
343
344 for (i = 0; i < len; i++) {
345 if (timings_arr[i].cm.code == hdmi.cfg.cm.code)
346 return &timings_arr[i];
347 }
348 return NULL;
349}
350
351static const struct hdmi_config *hdmi_get_timings(void)
352{
353 const struct hdmi_config *arr;
354 int len;
355
356 if (hdmi.cfg.cm.mode == HDMI_DVI) {
357 arr = vesa_timings;
358 len = ARRAY_SIZE(vesa_timings);
359 } else {
360 arr = cea_timings;
361 len = ARRAY_SIZE(cea_timings);
362 }
363
364 return hdmi_find_timing(arr, len);
365}
366
367static bool hdmi_timings_compare(struct omap_video_timings *timing1,
368 const struct omap_video_timings *timing2)
369{
370 int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
371
372 if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) ==
373 DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
374 (timing2->x_res == timing1->x_res) &&
375 (timing2->y_res == timing1->y_res)) {
376
377 timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
378 timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
379 timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
380 timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
381
382 DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
383 "timing2_hsync = %d timing2_vsync = %d\n",
384 timing1_hsync, timing1_vsync,
385 timing2_hsync, timing2_vsync);
386
387 if ((timing1_hsync == timing2_hsync) &&
388 (timing1_vsync == timing2_vsync)) {
389 return true;
390 }
391 }
392 return false;
393}
394
395static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
396{
397 int i;
398 struct hdmi_cm cm = {-1};
399 DSSDBG("hdmi_get_code\n");
400
401 for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
402 if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
403 cm = cea_timings[i].cm;
404 goto end;
405 }
406 }
407 for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
408 if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
409 cm = vesa_timings[i].cm;
410 goto end;
411 }
412 }
413
414end: return cm;
415
416}
417
418static int hdmi_power_on_core(struct omap_dss_device *dssdev) 107static int hdmi_power_on_core(struct omap_dss_device *dssdev)
419{ 108{
420 int r; 109 int r;
@@ -550,7 +239,7 @@ static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
550 cm = hdmi_get_code(timings); 239 cm = hdmi_get_code(timings);
551 hdmi.cfg.cm = cm; 240 hdmi.cfg.cm = cm;
552 241
553 t = hdmi_get_timings(); 242 t = hdmi_get_timings(cm.mode, cm.code);
554 if (t != NULL) { 243 if (t != NULL) {
555 hdmi.cfg = *t; 244 hdmi.cfg = *t;
556 245
@@ -564,10 +253,11 @@ static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
564 struct omap_video_timings *timings) 253 struct omap_video_timings *timings)
565{ 254{
566 const struct hdmi_config *cfg; 255 const struct hdmi_config *cfg;
256 struct hdmi_cm cm = hdmi.cfg.cm;
567 257
568 cfg = hdmi_get_timings(); 258 cfg = hdmi_get_timings(cm.mode, cm.code);
569 if (cfg == NULL) 259 if (cfg == NULL)
570 cfg = &vesa_timings[0]; 260 cfg = hdmi_default_timing();
571 261
572 memcpy(timings, &cfg->timings, sizeof(cfg->timings)); 262 memcpy(timings, &cfg->timings, sizeof(cfg->timings));
573} 263}
@@ -695,117 +385,6 @@ static int hdmi_get_clocks(struct platform_device *pdev)
695 return 0; 385 return 0;
696} 386}
697 387
698#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
699int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)
700{
701 u32 deep_color;
702 bool deep_color_correct = false;
703 u32 pclk = hdmi.cfg.timings.pixel_clock;
704
705 if (n == NULL || cts == NULL)
706 return -EINVAL;
707
708 /* TODO: When implemented, query deep color mode here. */
709 deep_color = 100;
710
711 /*
712 * When using deep color, the default N value (as in the HDMI
713 * specification) yields to an non-integer CTS. Hence, we
714 * modify it while keeping the restrictions described in
715 * section 7.2.1 of the HDMI 1.4a specification.
716 */
717 switch (sample_freq) {
718 case 32000:
719 case 48000:
720 case 96000:
721 case 192000:
722 if (deep_color == 125)
723 if (pclk == 27027 || pclk == 74250)
724 deep_color_correct = true;
725 if (deep_color == 150)
726 if (pclk == 27027)
727 deep_color_correct = true;
728 break;
729 case 44100:
730 case 88200:
731 case 176400:
732 if (deep_color == 125)
733 if (pclk == 27027)
734 deep_color_correct = true;
735 break;
736 default:
737 return -EINVAL;
738 }
739
740 if (deep_color_correct) {
741 switch (sample_freq) {
742 case 32000:
743 *n = 8192;
744 break;
745 case 44100:
746 *n = 12544;
747 break;
748 case 48000:
749 *n = 8192;
750 break;
751 case 88200:
752 *n = 25088;
753 break;
754 case 96000:
755 *n = 16384;
756 break;
757 case 176400:
758 *n = 50176;
759 break;
760 case 192000:
761 *n = 32768;
762 break;
763 default:
764 return -EINVAL;
765 }
766 } else {
767 switch (sample_freq) {
768 case 32000:
769 *n = 4096;
770 break;
771 case 44100:
772 *n = 6272;
773 break;
774 case 48000:
775 *n = 6144;
776 break;
777 case 88200:
778 *n = 12544;
779 break;
780 case 96000:
781 *n = 12288;
782 break;
783 case 176400:
784 *n = 25088;
785 break;
786 case 192000:
787 *n = 24576;
788 break;
789 default:
790 return -EINVAL;
791 }
792 }
793 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
794 *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
795
796 return 0;
797}
798
799static bool hdmi_mode_has_audio(void)
800{
801 if (hdmi.cfg.cm.mode == HDMI_HDMI)
802 return true;
803 else
804 return false;
805}
806
807#endif
808
809static int hdmi_connect(struct omap_dss_device *dssdev, 388static int hdmi_connect(struct omap_dss_device *dssdev,
810 struct omap_dss_device *dst) 389 struct omap_dss_device *dst)
811{ 390{
@@ -878,7 +457,7 @@ static int hdmi_audio_enable(struct omap_dss_device *dssdev)
878 457
879 mutex_lock(&hdmi.lock); 458 mutex_lock(&hdmi.lock);
880 459
881 if (!hdmi_mode_has_audio()) { 460 if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
882 r = -EPERM; 461 r = -EPERM;
883 goto err; 462 goto err;
884 } 463 }
@@ -916,7 +495,7 @@ static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
916 495
917 mutex_lock(&hdmi.lock); 496 mutex_lock(&hdmi.lock);
918 497
919 r = hdmi_mode_has_audio(); 498 r = hdmi_mode_has_audio(hdmi.cfg.cm.mode);
920 499
921 mutex_unlock(&hdmi.lock); 500 mutex_unlock(&hdmi.lock);
922 return r; 501 return r;
@@ -926,15 +505,16 @@ static int hdmi_audio_config(struct omap_dss_device *dssdev,
926 struct omap_dss_audio *audio) 505 struct omap_dss_audio *audio)
927{ 506{
928 int r; 507 int r;
508 u32 pclk = hdmi.cfg.timings.pixel_clock;
929 509
930 mutex_lock(&hdmi.lock); 510 mutex_lock(&hdmi.lock);
931 511
932 if (!hdmi_mode_has_audio()) { 512 if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
933 r = -EPERM; 513 r = -EPERM;
934 goto err; 514 goto err;
935 } 515 }
936 516
937 r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, audio); 517 r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, audio, pclk);
938 if (r) 518 if (r)
939 goto err; 519 goto err;
940 520
diff --git a/drivers/video/omap2/dss/hdmi4_core.c b/drivers/video/omap2/dss/hdmi4_core.c
index 3f7fc572be10..5dd5e5489b41 100644
--- a/drivers/video/omap2/dss/hdmi4_core.c
+++ b/drivers/video/omap2/dss/hdmi4_core.c
@@ -789,7 +789,7 @@ static void hdmi_core_audio_infoframe_cfg(struct hdmi_core_data *core,
789} 789}
790 790
791int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, 791int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
792 struct omap_dss_audio *audio) 792 struct omap_dss_audio *audio, u32 pclk)
793{ 793{
794 struct hdmi_audio_format audio_format; 794 struct hdmi_audio_format audio_format;
795 struct hdmi_audio_dma audio_dma; 795 struct hdmi_audio_dma audio_dma;
@@ -856,7 +856,7 @@ int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
856 return -EINVAL; 856 return -EINVAL;
857 } 857 }
858 858
859 err = hdmi_compute_acr(fs_nr, &n, &cts); 859 err = hdmi_compute_acr(pclk, fs_nr, &n, &cts);
860 860
861 /* Audio clock regeneration settings */ 861 /* Audio clock regeneration settings */
862 acore.n = n; 862 acore.n = n;
diff --git a/drivers/video/omap2/dss/hdmi4_core.h b/drivers/video/omap2/dss/hdmi4_core.h
index 1181b4c1a068..bb646896fa82 100644
--- a/drivers/video/omap2/dss/hdmi4_core.h
+++ b/drivers/video/omap2/dss/hdmi4_core.h
@@ -269,7 +269,7 @@ int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core);
269int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp); 269int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp);
270void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp); 270void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp);
271int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, 271int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
272 struct omap_dss_audio *audio); 272 struct omap_dss_audio *audio, u32 pclk);
273int hdmi4_audio_get_dma_port(u32 *offset, u32 *size); 273int hdmi4_audio_get_dma_port(u32 *offset, u32 *size);
274#endif 274#endif
275 275
diff --git a/drivers/video/omap2/dss/hdmi_common.c b/drivers/video/omap2/dss/hdmi_common.c
new file mode 100644
index 000000000000..6f727c858857
--- /dev/null
+++ b/drivers/video/omap2/dss/hdmi_common.c
@@ -0,0 +1,423 @@
1
2/*
3 * Logic for the below structure :
4 * user enters the CEA or VESA timings by specifying the HDMI/DVI code.
5 * There is a correspondence between CEA/VESA timing and code, please
6 * refer to section 6.3 in HDMI 1.3 specification for timing code.
7 *
8 * In the below structure, cea_vesa_timings corresponds to all OMAP4
9 * supported CEA and VESA timing values.code_cea corresponds to the CEA
10 * code, It is used to get the timing from cea_vesa_timing array.Similarly
11 * with code_vesa. Code_index is used for back mapping, that is once EDID
12 * is read from the TV, EDID is parsed to find the timing values and then
13 * map it to corresponding CEA or VESA index.
14 */
15
16#include <linux/kernel.h>
17#include <linux/err.h>
18#include <video/omapdss.h>
19
20#include "hdmi.h"
21
22static const struct hdmi_config cea_timings[] = {
23 {
24 { 640, 480, 25200, 96, 16, 48, 2, 10, 33,
25 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
26 false, },
27 { 1, HDMI_HDMI },
28 },
29 {
30 { 720, 480, 27027, 62, 16, 60, 6, 9, 30,
31 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
32 false, },
33 { 2, HDMI_HDMI },
34 },
35 {
36 { 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
37 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
38 false, },
39 { 4, HDMI_HDMI },
40 },
41 {
42 { 1920, 540, 74250, 44, 88, 148, 5, 2, 15,
43 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
44 true, },
45 { 5, HDMI_HDMI },
46 },
47 {
48 { 1440, 240, 27027, 124, 38, 114, 3, 4, 15,
49 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
50 true, },
51 { 6, HDMI_HDMI },
52 },
53 {
54 { 1920, 1080, 148500, 44, 88, 148, 5, 4, 36,
55 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
56 false, },
57 { 16, HDMI_HDMI },
58 },
59 {
60 { 720, 576, 27000, 64, 12, 68, 5, 5, 39,
61 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
62 false, },
63 { 17, HDMI_HDMI },
64 },
65 {
66 { 1280, 720, 74250, 40, 440, 220, 5, 5, 20,
67 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
68 false, },
69 { 19, HDMI_HDMI },
70 },
71 {
72 { 1920, 540, 74250, 44, 528, 148, 5, 2, 15,
73 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
74 true, },
75 { 20, HDMI_HDMI },
76 },
77 {
78 { 1440, 288, 27000, 126, 24, 138, 3, 2, 19,
79 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
80 true, },
81 { 21, HDMI_HDMI },
82 },
83 {
84 { 1440, 576, 54000, 128, 24, 136, 5, 5, 39,
85 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
86 false, },
87 { 29, HDMI_HDMI },
88 },
89 {
90 { 1920, 1080, 148500, 44, 528, 148, 5, 4, 36,
91 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
92 false, },
93 { 31, HDMI_HDMI },
94 },
95 {
96 { 1920, 1080, 74250, 44, 638, 148, 5, 4, 36,
97 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
98 false, },
99 { 32, HDMI_HDMI },
100 },
101 {
102 { 2880, 480, 108108, 248, 64, 240, 6, 9, 30,
103 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
104 false, },
105 { 35, HDMI_HDMI },
106 },
107 {
108 { 2880, 576, 108000, 256, 48, 272, 5, 5, 39,
109 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
110 false, },
111 { 37, HDMI_HDMI },
112 },
113};
114
115static const struct hdmi_config vesa_timings[] = {
116/* VESA From Here */
117 {
118 { 640, 480, 25175, 96, 16, 48, 2, 11, 31,
119 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
120 false, },
121 { 4, HDMI_DVI },
122 },
123 {
124 { 800, 600, 40000, 128, 40, 88, 4, 1, 23,
125 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
126 false, },
127 { 9, HDMI_DVI },
128 },
129 {
130 { 848, 480, 33750, 112, 16, 112, 8, 6, 23,
131 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
132 false, },
133 { 0xE, HDMI_DVI },
134 },
135 {
136 { 1280, 768, 79500, 128, 64, 192, 7, 3, 20,
137 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
138 false, },
139 { 0x17, HDMI_DVI },
140 },
141 {
142 { 1280, 800, 83500, 128, 72, 200, 6, 3, 22,
143 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
144 false, },
145 { 0x1C, HDMI_DVI },
146 },
147 {
148 { 1360, 768, 85500, 112, 64, 256, 6, 3, 18,
149 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
150 false, },
151 { 0x27, HDMI_DVI },
152 },
153 {
154 { 1280, 960, 108000, 112, 96, 312, 3, 1, 36,
155 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
156 false, },
157 { 0x20, HDMI_DVI },
158 },
159 {
160 { 1280, 1024, 108000, 112, 48, 248, 3, 1, 38,
161 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
162 false, },
163 { 0x23, HDMI_DVI },
164 },
165 {
166 { 1024, 768, 65000, 136, 24, 160, 6, 3, 29,
167 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
168 false, },
169 { 0x10, HDMI_DVI },
170 },
171 {
172 { 1400, 1050, 121750, 144, 88, 232, 4, 3, 32,
173 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
174 false, },
175 { 0x2A, HDMI_DVI },
176 },
177 {
178 { 1440, 900, 106500, 152, 80, 232, 6, 3, 25,
179 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
180 false, },
181 { 0x2F, HDMI_DVI },
182 },
183 {
184 { 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30,
185 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
186 false, },
187 { 0x3A, HDMI_DVI },
188 },
189 {
190 { 1366, 768, 85500, 143, 70, 213, 3, 3, 24,
191 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
192 false, },
193 { 0x51, HDMI_DVI },
194 },
195 {
196 { 1920, 1080, 148500, 44, 148, 80, 5, 4, 36,
197 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
198 false, },
199 { 0x52, HDMI_DVI },
200 },
201 {
202 { 1280, 768, 68250, 32, 48, 80, 7, 3, 12,
203 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
204 false, },
205 { 0x16, HDMI_DVI },
206 },
207 {
208 { 1400, 1050, 101000, 32, 48, 80, 4, 3, 23,
209 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
210 false, },
211 { 0x29, HDMI_DVI },
212 },
213 {
214 { 1680, 1050, 119000, 32, 48, 80, 6, 3, 21,
215 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
216 false, },
217 { 0x39, HDMI_DVI },
218 },
219 {
220 { 1280, 800, 79500, 32, 48, 80, 6, 3, 14,
221 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
222 false, },
223 { 0x1B, HDMI_DVI },
224 },
225 {
226 { 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
227 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
228 false, },
229 { 0x55, HDMI_DVI },
230 },
231 {
232 { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26,
233 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
234 false, },
235 { 0x44, HDMI_DVI },
236 },
237};
238
239const struct hdmi_config *hdmi_default_timing(void)
240{
241 return &vesa_timings[0];
242}
243
244static const struct hdmi_config *hdmi_find_timing(int code,
245 const struct hdmi_config *timings_arr, int len)
246{
247 int i;
248
249 for (i = 0; i < len; i++) {
250 if (timings_arr[i].cm.code == code)
251 return &timings_arr[i];
252 }
253
254 return NULL;
255}
256
257const struct hdmi_config *hdmi_get_timings(int mode, int code)
258{
259 const struct hdmi_config *arr;
260 int len;
261
262 if (mode == HDMI_DVI) {
263 arr = vesa_timings;
264 len = ARRAY_SIZE(vesa_timings);
265 } else {
266 arr = cea_timings;
267 len = ARRAY_SIZE(cea_timings);
268 }
269
270 return hdmi_find_timing(code, arr, len);
271}
272
273static bool hdmi_timings_compare(struct omap_video_timings *timing1,
274 const struct omap_video_timings *timing2)
275{
276 int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
277
278 if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) ==
279 DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
280 (timing2->x_res == timing1->x_res) &&
281 (timing2->y_res == timing1->y_res)) {
282
283 timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
284 timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
285 timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
286 timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
287
288 DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
289 "timing2_hsync = %d timing2_vsync = %d\n",
290 timing1_hsync, timing1_vsync,
291 timing2_hsync, timing2_vsync);
292
293 if ((timing1_hsync == timing2_hsync) &&
294 (timing1_vsync == timing2_vsync)) {
295 return true;
296 }
297 }
298 return false;
299}
300
301struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
302{
303 int i;
304 struct hdmi_cm cm = {-1};
305 DSSDBG("hdmi_get_code\n");
306
307 for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
308 if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
309 cm = cea_timings[i].cm;
310 goto end;
311 }
312 }
313 for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
314 if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
315 cm = vesa_timings[i].cm;
316 goto end;
317 }
318 }
319
320end:
321 return cm;
322}
323
324#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
325int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
326{
327 u32 deep_color;
328 bool deep_color_correct = false;
329
330 if (n == NULL || cts == NULL)
331 return -EINVAL;
332
333 /* TODO: When implemented, query deep color mode here. */
334 deep_color = 100;
335
336 /*
337 * When using deep color, the default N value (as in the HDMI
338 * specification) yields to an non-integer CTS. Hence, we
339 * modify it while keeping the restrictions described in
340 * section 7.2.1 of the HDMI 1.4a specification.
341 */
342 switch (sample_freq) {
343 case 32000:
344 case 48000:
345 case 96000:
346 case 192000:
347 if (deep_color == 125)
348 if (pclk == 27027 || pclk == 74250)
349 deep_color_correct = true;
350 if (deep_color == 150)
351 if (pclk == 27027)
352 deep_color_correct = true;
353 break;
354 case 44100:
355 case 88200:
356 case 176400:
357 if (deep_color == 125)
358 if (pclk == 27027)
359 deep_color_correct = true;
360 break;
361 default:
362 return -EINVAL;
363 }
364
365 if (deep_color_correct) {
366 switch (sample_freq) {
367 case 32000:
368 *n = 8192;
369 break;
370 case 44100:
371 *n = 12544;
372 break;
373 case 48000:
374 *n = 8192;
375 break;
376 case 88200:
377 *n = 25088;
378 break;
379 case 96000:
380 *n = 16384;
381 break;
382 case 176400:
383 *n = 50176;
384 break;
385 case 192000:
386 *n = 32768;
387 break;
388 default:
389 return -EINVAL;
390 }
391 } else {
392 switch (sample_freq) {
393 case 32000:
394 *n = 4096;
395 break;
396 case 44100:
397 *n = 6272;
398 break;
399 case 48000:
400 *n = 6144;
401 break;
402 case 88200:
403 *n = 12544;
404 break;
405 case 96000:
406 *n = 12288;
407 break;
408 case 176400:
409 *n = 25088;
410 break;
411 case 192000:
412 *n = 24576;
413 break;
414 default:
415 return -EINVAL;
416 }
417 }
418 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
419 *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
420
421 return 0;
422}
423#endif