Merge tag 'drm-intel-fixes-2014-06-17' of git://anongit.freedesktop.org/drm-intel...
[linux-drm-fsl-dcu.git] / drivers / tty / vt / vt.c
index 3c00dcb3b145a3460ee5ba54fbc4eb05ce839cd0..b33b00b386de92c7101d1c50c5547aa42a35c76d 100644 (file)
@@ -735,7 +735,7 @@ static void visual_init(struct vc_data *vc, int num, int init)
        vc->vc_num = num;
        vc->vc_display_fg = &master_display_fg;
        vc->vc_uni_pagedir_loc = &vc->vc_uni_pagedir;
-       vc->vc_uni_pagedir = 0;
+       vc->vc_uni_pagedir = NULL;
        vc->vc_hi_font_mask = 0;
        vc->vc_complement_mask = 0;
        vc->vc_can_do_color = 0;
@@ -1231,6 +1231,52 @@ static void default_attr(struct vc_data *vc)
        vc->vc_color = vc->vc_def_color;
 }
 
+struct rgb { u8 r; u8 g; u8 b; };
+
+struct rgb rgb_from_256(int i)
+{
+       struct rgb c;
+       if (i < 8) {            /* Standard colours. */
+               c.r = i&1 ? 0xaa : 0x00;
+               c.g = i&2 ? 0xaa : 0x00;
+               c.b = i&4 ? 0xaa : 0x00;
+       } else if (i < 16) {
+               c.r = i&1 ? 0xff : 0x55;
+               c.g = i&2 ? 0xff : 0x55;
+               c.b = i&4 ? 0xff : 0x55;
+       } else if (i < 232) {   /* 6x6x6 colour cube. */
+               c.r = (i - 16) / 36 * 85 / 2;
+               c.g = (i - 16) / 6 % 6 * 85 / 2;
+               c.b = (i - 16) % 6 * 85 / 2;
+       } else                  /* Grayscale ramp. */
+               c.r = c.g = c.b = i * 10 - 2312;
+       return c;
+}
+
+static void rgb_foreground(struct vc_data *vc, struct rgb c)
+{
+       u8 hue, max = c.r;
+       if (c.g > max)
+               max = c.g;
+       if (c.b > max)
+               max = c.b;
+       hue = (c.r > max/2 ? 4 : 0)
+           | (c.g > max/2 ? 2 : 0)
+           | (c.b > max/2 ? 1 : 0);
+       if (hue == 7 && max <= 0x55)
+               hue = 0, vc->vc_intensity = 2;
+       else
+               vc->vc_intensity = (max > 0xaa) + 1;
+       vc->vc_color = (vc->vc_color & 0xf0) | hue;
+}
+
+static void rgb_background(struct vc_data *vc, struct rgb c)
+{
+       /* For backgrounds, err on the dark side. */
+       vc->vc_color = (vc->vc_color & 0x0f)
+               | (c.r&0x80) >> 1 | (c.g&0x80) >> 2 | (c.b&0x80) >> 3;
+}
+
 /* console_lock is held */
 static void csi_m(struct vc_data *vc)
 {
@@ -1302,8 +1348,7 @@ static void csi_m(struct vc_data *vc)
                        case 27:
                                vc->vc_reverse = 0;
                                break;
-                       case 38:
-                       case 48: /* ITU T.416
+                       case 38: /* ITU T.416
                                  * Higher colour modes.
                                  * They break the usual properties of SGR codes
                                  * and thus need to be detected and ignored by
@@ -1315,15 +1360,41 @@ static void csi_m(struct vc_data *vc)
                                i++;
                                if (i > vc->vc_npar)
                                        break;
-                               if (vc->vc_par[i] == 5)      /* 256 colours */
-                                       i++;                 /* ubiquitous */
-                               else if (vc->vc_par[i] == 2) /* 24 bit colours */
-                                       i += 3;              /* extremely rare */
+                               if (vc->vc_par[i] == 5 &&  /* 256 colours */
+                                   i < vc->vc_npar) {     /* ubiquitous */
+                                       i++;
+                                       rgb_foreground(vc,
+                                               rgb_from_256(vc->vc_par[i]));
+                               } else if (vc->vc_par[i] == 2 &&  /* 24 bit */
+                                          i <= vc->vc_npar + 3) {/* extremely rare */
+                                       struct rgb c = {r:vc->vc_par[i+1],
+                                                       g:vc->vc_par[i+2],
+                                                       b:vc->vc_par[i+3]};
+                                       rgb_foreground(vc, c);
+                                       i += 3;
+                               }
                                /* Subcommands 3 (CMY) and 4 (CMYK) are so insane
-                                * that detecting them is not worth the few extra
-                                * bytes of kernel's size.
+                                * there's no point in supporting them.
                                 */
                                break;
+                       case 48:
+                               i++;
+                               if (i > vc->vc_npar)
+                                       break;
+                               if (vc->vc_par[i] == 5 &&  /* 256 colours */
+                                   i < vc->vc_npar) {
+                                       i++;
+                                       rgb_background(vc,
+                                               rgb_from_256(vc->vc_par[i]));
+                               } else if (vc->vc_par[i] == 2 && /* 24 bit */
+                                          i <= vc->vc_npar + 3) {
+                                       struct rgb c = {r:vc->vc_par[i+1],
+                                                       g:vc->vc_par[i+2],
+                                                       b:vc->vc_par[i+3]};
+                                       rgb_background(vc, c);
+                                       i += 3;
+                               }
+                               break;
                        case 39:
                                vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
                                break;