spi/topcliff-pch: Fix Kconfig dependencies
[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 #define DSS_SUBSYS_NAME "HDMI"
17
18 #include <linux/kernel.h>
19 #include <linux/err.h>
20 #include <video/omapdss.h>
21
22 #include "hdmi.h"
23
24 static const struct hdmi_config cea_timings[] = {
25         {
26                 { 640, 480, 25200000, 96, 16, 48, 2, 10, 33,
27                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
28                         false, },
29                 { 1, HDMI_HDMI },
30         },
31         {
32                 { 720, 480, 27027000, 62, 16, 60, 6, 9, 30,
33                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
34                         false, },
35                 { 2, HDMI_HDMI },
36         },
37         {
38                 { 1280, 720, 74250000, 40, 110, 220, 5, 5, 20,
39                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
40                         false, },
41                 { 4, HDMI_HDMI },
42         },
43         {
44                 { 1920, 540, 74250000, 44, 88, 148, 5, 2, 15,
45                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
46                         true, },
47                 { 5, HDMI_HDMI },
48         },
49         {
50                 { 1440, 240, 27027000, 124, 38, 114, 3, 4, 15,
51                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
52                         true, },
53                 { 6, HDMI_HDMI },
54         },
55         {
56                 { 1920, 1080, 148500000, 44, 88, 148, 5, 4, 36,
57                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
58                         false, },
59                 { 16, HDMI_HDMI },
60         },
61         {
62                 { 720, 576, 27000000, 64, 12, 68, 5, 5, 39,
63                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
64                         false, },
65                 { 17, HDMI_HDMI },
66         },
67         {
68                 { 1280, 720, 74250000, 40, 440, 220, 5, 5, 20,
69                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
70                         false, },
71                 { 19, HDMI_HDMI },
72         },
73         {
74                 { 1920, 540, 74250000, 44, 528, 148, 5, 2, 15,
75                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
76                         true, },
77                 { 20, HDMI_HDMI },
78         },
79         {
80                 { 1440, 288, 27000000, 126, 24, 138, 3, 2, 19,
81                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
82                         true, },
83                 { 21, HDMI_HDMI },
84         },
85         {
86                 { 1440, 576, 54000000, 128, 24, 136, 5, 5, 39,
87                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
88                         false, },
89                 { 29, HDMI_HDMI },
90         },
91         {
92                 { 1920, 1080, 148500000, 44, 528, 148, 5, 4, 36,
93                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
94                         false, },
95                 { 31, HDMI_HDMI },
96         },
97         {
98                 { 1920, 1080, 74250000, 44, 638, 148, 5, 4, 36,
99                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
100                         false, },
101                 { 32, HDMI_HDMI },
102         },
103         {
104                 { 2880, 480, 108108000, 248, 64, 240, 6, 9, 30,
105                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
106                         false, },
107                 { 35, HDMI_HDMI },
108         },
109         {
110                 { 2880, 576, 108000000, 256, 48, 272, 5, 5, 39,
111                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
112                         false, },
113                 { 37, HDMI_HDMI },
114         },
115 };
116
117 static const struct hdmi_config vesa_timings[] = {
118 /* VESA From Here */
119         {
120                 { 640, 480, 25175000, 96, 16, 48, 2, 11, 31,
121                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
122                         false, },
123                 { 4, HDMI_DVI },
124         },
125         {
126                 { 800, 600, 40000000, 128, 40, 88, 4, 1, 23,
127                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
128                         false, },
129                 { 9, HDMI_DVI },
130         },
131         {
132                 { 848, 480, 33750000, 112, 16, 112, 8, 6, 23,
133                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
134                         false, },
135                 { 0xE, HDMI_DVI },
136         },
137         {
138                 { 1280, 768, 79500000, 128, 64, 192, 7, 3, 20,
139                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
140                         false, },
141                 { 0x17, HDMI_DVI },
142         },
143         {
144                 { 1280, 800, 83500000, 128, 72, 200, 6, 3, 22,
145                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
146                         false, },
147                 { 0x1C, HDMI_DVI },
148         },
149         {
150                 { 1360, 768, 85500000, 112, 64, 256, 6, 3, 18,
151                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
152                         false, },
153                 { 0x27, HDMI_DVI },
154         },
155         {
156                 { 1280, 960, 108000000, 112, 96, 312, 3, 1, 36,
157                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
158                         false, },
159                 { 0x20, HDMI_DVI },
160         },
161         {
162                 { 1280, 1024, 108000000, 112, 48, 248, 3, 1, 38,
163                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
164                         false, },
165                 { 0x23, HDMI_DVI },
166         },
167         {
168                 { 1024, 768, 65000000, 136, 24, 160, 6, 3, 29,
169                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
170                         false, },
171                 { 0x10, HDMI_DVI },
172         },
173         {
174                 { 1400, 1050, 121750000, 144, 88, 232, 4, 3, 32,
175                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
176                         false, },
177                 { 0x2A, HDMI_DVI },
178         },
179         {
180                 { 1440, 900, 106500000, 152, 80, 232, 6, 3, 25,
181                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
182                         false, },
183                 { 0x2F, HDMI_DVI },
184         },
185         {
186                 { 1680, 1050, 146250000, 176 , 104, 280, 6, 3, 30,
187                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
188                         false, },
189                 { 0x3A, HDMI_DVI },
190         },
191         {
192                 { 1366, 768, 85500000, 143, 70, 213, 3, 3, 24,
193                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
194                         false, },
195                 { 0x51, HDMI_DVI },
196         },
197         {
198                 { 1920, 1080, 148500000, 44, 148, 80, 5, 4, 36,
199                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
200                         false, },
201                 { 0x52, HDMI_DVI },
202         },
203         {
204                 { 1280, 768, 68250000, 32, 48, 80, 7, 3, 12,
205                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
206                         false, },
207                 { 0x16, HDMI_DVI },
208         },
209         {
210                 { 1400, 1050, 101000000, 32, 48, 80, 4, 3, 23,
211                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
212                         false, },
213                 { 0x29, HDMI_DVI },
214         },
215         {
216                 { 1680, 1050, 119000000, 32, 48, 80, 6, 3, 21,
217                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
218                         false, },
219                 { 0x39, HDMI_DVI },
220         },
221         {
222                 { 1280, 800, 79500000, 32, 48, 80, 6, 3, 14,
223                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
224                         false, },
225                 { 0x1B, HDMI_DVI },
226         },
227         {
228                 { 1280, 720, 74250000, 40, 110, 220, 5, 5, 20,
229                         OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
230                         false, },
231                 { 0x55, HDMI_DVI },
232         },
233         {
234                 { 1920, 1200, 154000000, 32, 48, 80, 6, 3, 26,
235                         OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
236                         false, },
237                 { 0x44, HDMI_DVI },
238         },
239 };
240
241 const struct hdmi_config *hdmi_default_timing(void)
242 {
243         return &vesa_timings[0];
244 }
245
246 static const struct hdmi_config *hdmi_find_timing(int code,
247                         const struct hdmi_config *timings_arr, int len)
248 {
249         int i;
250
251         for (i = 0; i < len; i++) {
252                 if (timings_arr[i].cm.code == code)
253                         return &timings_arr[i];
254         }
255
256         return NULL;
257 }
258
259 const struct hdmi_config *hdmi_get_timings(int mode, int code)
260 {
261         const struct hdmi_config *arr;
262         int len;
263
264         if (mode == HDMI_DVI) {
265                 arr = vesa_timings;
266                 len = ARRAY_SIZE(vesa_timings);
267         } else {
268                 arr = cea_timings;
269                 len = ARRAY_SIZE(cea_timings);
270         }
271
272         return hdmi_find_timing(code, arr, len);
273 }
274
275 static bool hdmi_timings_compare(struct omap_video_timings *timing1,
276                         const struct omap_video_timings *timing2)
277 {
278         int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
279
280         if ((DIV_ROUND_CLOSEST(timing2->pixelclock, 1000000) ==
281                         DIV_ROUND_CLOSEST(timing1->pixelclock, 1000000)) &&
282                 (timing2->x_res == timing1->x_res) &&
283                 (timing2->y_res == timing1->y_res)) {
284
285                 timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
286                 timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
287                 timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
288                 timing1_vsync = timing1->vfp + timing1->vsw + timing1->vbp;
289
290                 DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
291                         "timing2_hsync = %d timing2_vsync = %d\n",
292                         timing1_hsync, timing1_vsync,
293                         timing2_hsync, timing2_vsync);
294
295                 if ((timing1_hsync == timing2_hsync) &&
296                         (timing1_vsync == timing2_vsync)) {
297                         return true;
298                 }
299         }
300         return false;
301 }
302
303 struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
304 {
305         int i;
306         struct hdmi_cm cm = {-1};
307         DSSDBG("hdmi_get_code\n");
308
309         for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
310                 if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
311                         cm = cea_timings[i].cm;
312                         goto end;
313                 }
314         }
315         for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
316                 if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
317                         cm = vesa_timings[i].cm;
318                         goto end;
319                 }
320         }
321
322 end:
323         return cm;
324 }
325
326 #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
327 int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
328 {
329         u32 deep_color;
330         bool deep_color_correct = false;
331
332         if (n == NULL || cts == NULL)
333                 return -EINVAL;
334
335         /* TODO: When implemented, query deep color mode here. */
336         deep_color = 100;
337
338         /*
339          * When using deep color, the default N value (as in the HDMI
340          * specification) yields to an non-integer CTS. Hence, we
341          * modify it while keeping the restrictions described in
342          * section 7.2.1 of the HDMI 1.4a specification.
343          */
344         switch (sample_freq) {
345         case 32000:
346         case 48000:
347         case 96000:
348         case 192000:
349                 if (deep_color == 125)
350                         if (pclk == 27027 || pclk == 74250)
351                                 deep_color_correct = true;
352                 if (deep_color == 150)
353                         if (pclk == 27027)
354                                 deep_color_correct = true;
355                 break;
356         case 44100:
357         case 88200:
358         case 176400:
359                 if (deep_color == 125)
360                         if (pclk == 27027)
361                                 deep_color_correct = true;
362                 break;
363         default:
364                 return -EINVAL;
365         }
366
367         if (deep_color_correct) {
368                 switch (sample_freq) {
369                 case 32000:
370                         *n = 8192;
371                         break;
372                 case 44100:
373                         *n = 12544;
374                         break;
375                 case 48000:
376                         *n = 8192;
377                         break;
378                 case 88200:
379                         *n = 25088;
380                         break;
381                 case 96000:
382                         *n = 16384;
383                         break;
384                 case 176400:
385                         *n = 50176;
386                         break;
387                 case 192000:
388                         *n = 32768;
389                         break;
390                 default:
391                         return -EINVAL;
392                 }
393         } else {
394                 switch (sample_freq) {
395                 case 32000:
396                         *n = 4096;
397                         break;
398                 case 44100:
399                         *n = 6272;
400                         break;
401                 case 48000:
402                         *n = 6144;
403                         break;
404                 case 88200:
405                         *n = 12544;
406                         break;
407                 case 96000:
408                         *n = 12288;
409                         break;
410                 case 176400:
411                         *n = 25088;
412                         break;
413                 case 192000:
414                         *n = 24576;
415                         break;
416                 default:
417                         return -EINVAL;
418                 }
419         }
420         /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
421         *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
422
423         return 0;
424 }
425 #endif