]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blobdiff - drivers/video/tegra/dc/edid.c
video: tegra: dc: enable YUV 1000/1001 modes
[sojka/nv-tegra/linux-3.10.git] / drivers / video / tegra / dc / edid.c
index a71731cf9befb1019fac5a8c889d51af025c7972..060271941a3591739472bb6c075e4d40d75f37e8 100644 (file)
@@ -625,31 +625,41 @@ int tegra_edid_get_monspecs(struct tegra_edid *edid, struct fb_monspecs *specs)
 
 #ifdef CONFIG_ARCH_TEGRA_21x_SOC
        /* T210 supports fractional divider and hence can support the * 1000 / 1001 modes.
-          For now, only enable support for 24, 30 and 60 Hz modes */
+          For now, only enable support for 24, 30 and 60 Hz modes. */
        {
-               struct fb_videomode *m;
-               struct fb_videomode frac_modes[10];
-               u8 frac_n = 0;
-
-               for (j = 0; j < specs->modedb_len; ++j) {
-                       if ((tegra_dc_calc_fb_refresh(&specs->modedb[j]) == 24000 ||
-                           tegra_dc_calc_fb_refresh(&specs->modedb[j]) == 30000 ||
-                           tegra_dc_calc_fb_refresh(&specs->modedb[j]) == 60000) &&
-                       frac_n < ARRAY_SIZE(frac_modes)) {
-                               memcpy(&frac_modes[frac_n], &specs->modedb[j], sizeof(struct fb_videomode));
-                               frac_modes[frac_n].pixclock = frac_modes[frac_n].pixclock * 1000 / 1001;
-                               frac_modes[frac_n].vmode |= FB_VMODE_1000DIV1001;
-                               frac_n++;
+               const int max_modes = 50;
+               struct fb_videomode *frac_modes, *m;
+               int frac_n = 0;
+               frac_modes = kzalloc(sizeof(struct fb_videomode) * max_modes,
+                                    GFP_KERNEL);
+
+               if (frac_modes) {
+                       for (j = 0; j < specs->modedb_len; ++j) {
+                               int rate = tegra_dc_calc_fb_refresh(&specs->modedb[j]);
+                               if ((rate == 24000 ||
+                                    rate == 30000 ||
+                                   (rate > (60000 - 20) && rate < (60000 + 20))) &&
+                                   frac_n < max_modes) {
+                                       memcpy(&frac_modes[frac_n], &specs->modedb[j], sizeof(struct fb_videomode));
+                                       frac_modes[frac_n].pixclock = frac_modes[frac_n].pixclock * 1000 / 1001;
+                                       frac_modes[frac_n].vmode |= FB_VMODE_1000DIV1001;
+                                       frac_n++;
+                               }
+                       }
+
+                       if (frac_n == max_modes)
+                               pr_warn("Hit fractional mode limit %d!\n", frac_n);
+
+                       m = kzalloc((specs->modedb_len + frac_n) * sizeof(struct fb_videomode), GFP_KERNEL);
+                       if (m) {
+                               memcpy(m, specs->modedb, specs->modedb_len * sizeof(struct fb_videomode));
+                               memcpy(&m[specs->modedb_len], frac_modes, frac_n * sizeof(struct fb_videomode));
+                               kfree(specs->modedb);
+                               specs->modedb = m;
+                               specs->modedb_len += frac_n;
                        }
-               }
 
-               m = kzalloc((specs->modedb_len + frac_n) * sizeof(struct fb_videomode), GFP_KERNEL);
-               if (m) {
-                       memcpy(m, specs->modedb, specs->modedb_len * sizeof(struct fb_videomode));
-                       memcpy(&m[specs->modedb_len], frac_modes, frac_n * sizeof(struct fb_videomode));
-                       kfree(specs->modedb);
-                       specs->modedb = m;
-                       specs->modedb_len += frac_n;
+                       kfree(frac_modes);
                }
        }
 #endif