Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next
[cascardo/linux.git] / drivers / video / omap2 / dss / hdmi_common.c
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
22 static 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
115 static 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
239 const struct hdmi_config *hdmi_default_timing(void)
240 {
241         return &vesa_timings[0];
242 }
243
244 static 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
257 const 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
273 static 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 = timing1->vfp + timing1->vsw + timing1->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
301 struct 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
320 end:
321         return cm;
322 }
323
324 #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
325 int 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