Port Panel fitting changes for HDMI from Gingerbread.
authorMohan Kandra <mohan.b.kandra@intel.com>
Tue, 14 Feb 2012 22:06:40 +0000 (14:06 -0800)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 3 Jul 2012 09:30:10 +0000 (12:30 +0300)
Panel fit hardware configuration dependent on required output HDMI mode.

OTM_HDMI: r2979

Signed-off-by: Arun Kannan <arun.kannan@intel.com>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
drivers/staging/mrst/drv/otm_hdmi/ipil/common/ipil_internal.h
drivers/staging/mrst/drv/otm_hdmi/ipil/common/otm_ipil_main.c
drivers/staging/mrst/drv/otm_hdmi/pil/specific/mfld/ps_hdmi_tablet.c

index 90dfe01..9dbd3d2 100644 (file)
 #define IPIL_PFIT_PIPE_SHIFT           29
 #define IPIL_PFIT_PIPE_SELECT_B                (1 << IPIL_PFIT_PIPE_SHIFT)
 #define IPIL_PFIT_SCALING_AUTO         (0 << 26)
+#define IPIL_PFIT_SCALING_PROGRAM      (1 << 26)
 #define IPIL_PFIT_SCALING_PILLARBOX    (1 << 27)
 #define IPIL_PFIT_SCALING_LETTERBOX    (3 << 26)
+#define IPIL_PFIT_FRACTIONAL_VALUE     (1 << 12)
+#define IPIL_PFIT_VERT_SCALE_SHIFT     16
+#define IPIL_PFIT_HORIZ_SCALE_SHIFT    0
+#define IPIL_PFIT_VERT_MSB_SHIFT       28
+#define IPIL_PFIT_HORIZ_MSB_SHIFT      12
 
 #define IPIL_PWR_GATE_EN       (1 << 30)
 #define IPIL_PIPECONF_PLL_LOCK (1<<29)
index 43c5e92..f85b771 100644 (file)
@@ -294,6 +294,49 @@ otm_hdmi_ret_t ipil_hdmi_disable_all_infoframes(hdmi_device_t *dev)
        return ips_hdmi_disable_all_infoframes(dev);
 }
 
+static void pfit_landscape(int hsrc_sz, int vsrc_sz,
+                       int hdst_sz, int vdst_sz)
+{
+       int hmsb, vmsb, hratio, vratio;
+
+       hdmi_write32(IPIL_PFIT_CONTROL,
+                       IPIL_PFIT_ENABLE |
+                       IPIL_PFIT_PIPE_SELECT_B |
+                       IPIL_PFIT_SCALING_PROGRAM);
+
+       /* handling scaling up and down */
+       if (hsrc_sz >= hdst_sz) {
+               /* scaling down: msb = 1 */
+               hratio = IPIL_PFIT_FRACTIONAL_VALUE * (hsrc_sz - hdst_sz) /
+                                                       (hdst_sz + 1);
+               hmsb = 1;
+       } else {
+               /* scaling up: msb = 0 */
+               hratio = IPIL_PFIT_FRACTIONAL_VALUE * (hsrc_sz + 1) /
+                                                       (hdst_sz + 1);
+               hmsb = 0;
+       }
+       if (vsrc_sz >= vdst_sz) {
+               /* scaling down: msb = 1 */
+               vratio = IPIL_PFIT_FRACTIONAL_VALUE * (vsrc_sz - vdst_sz) /
+                                                       (vdst_sz + 1);
+               vmsb = 1;
+       } else {
+               /* scaling up: msb = 0 */
+               vratio = IPIL_PFIT_FRACTIONAL_VALUE * (vsrc_sz + 1) /
+                                                       (vdst_sz + 1);
+               vmsb = 0;
+       }
+
+       pr_debug("\nhdisp = %d, vdisp = %d\n", hdst_sz, vdst_sz);
+       pr_debug("\nhratio = %d, vratio = %d\n", hratio, vratio);
+       hdmi_write32(IPIL_PFIT_PGM_RATIOS,
+               vmsb << IPIL_PFIT_VERT_MSB_SHIFT |
+               hmsb << IPIL_PFIT_HORIZ_MSB_SHIFT |
+               vratio << IPIL_PFIT_VERT_SCALE_SHIFT |
+               hratio << IPIL_PFIT_HORIZ_SCALE_SHIFT);
+}
+
 /*
  * Description: programs hdmi pipe src and size of the input.
  *
@@ -323,62 +366,117 @@ otm_hdmi_ret_t ipil_hdmi_crtc_mode_set_program_dspregs(hdmi_device_t *dev,
        }
 
        /*
-        * TODO: update these values based on scaling type,
-        * rotation and HDMI mode.
+        * Frame buffer size may beyond active region in case of
+        * panning mode.
         */
-       sprite_width = fb_width;
-       sprite_height = fb_height;
-       src_image_hor = fb_width;
-       src_image_vert = fb_height;
-       sprite_pos_x = 0;
-       sprite_pos_y = 0;
+       sprite_width = min(fb_width, adjusted_mode->width);
+       sprite_height = min(fb_height, adjusted_mode->height);
 
-       /*
-        * pipesrc and dspsize control the size that is scaled from,
-        * which should always be the user's requested size.
-        */
        switch (scalingtype) {
        case IPIL_TIMING_SCALE_NONE:
        case IPIL_TIMING_SCALE_CENTER:
-               /* TODO: implement this */
+               /*
+                * This mode is used to support centering the screen
+                * by setting reg in DISPLAY controller
+                */
+               src_image_hor = adjusted_mode->width;
+               src_image_vert = adjusted_mode->height;
+               sprite_pos_x = (src_image_hor - sprite_width) / 2;
+               sprite_pos_y = (src_image_vert - sprite_height) / 2;
+
+               hdmi_write32(IPIL_PFIT_CONTROL,
+                               hdmi_read32(IPIL_PFIT_CONTROL) &
+                                               ~IPIL_PFIT_ENABLE);
                break;
 
        case IPIL_TIMING_SCALE_FULLSCREEN:
-               if ((adjusted_mode->width != sprite_width) ||
-                       (adjusted_mode->height != sprite_height))
-                       hdmi_write32(IPIL_PFIT_CONTROL,
-                               IPIL_PFIT_ENABLE |
-                               IPIL_PFIT_PIPE_SELECT_B |
-                               IPIL_PFIT_SCALING_AUTO);
+               src_image_hor = sprite_width;
+               src_image_vert = sprite_height;
+               sprite_pos_x = 0;
+               sprite_pos_y = 0;
 
+               if ((adjusted_mode->width > sprite_width) ||
+                       (adjusted_mode->height > sprite_height))
+                       hdmi_write32(IPIL_PFIT_CONTROL,
+                                       IPIL_PFIT_ENABLE |
+                                       IPIL_PFIT_PIPE_SELECT_B |
+                                       IPIL_PFIT_SCALING_AUTO);
                break;
 
        case IPIL_TIMING_SCALE_ASPECT:
+               sprite_pos_x = 0;
+               sprite_pos_y = 0;
+               sprite_height = fb_height;
+               sprite_width = fb_width;
+               src_image_hor = fb_width;
+               src_image_vert = fb_height;
+
+               /* Use panel fitting when the display does not match
+                * with the framebuffer size */
                if ((adjusted_mode->width != fb_width) ||
-                       (adjusted_mode->height != fb_height)) {
-                       if ((adjusted_mode->width * fb_height) ==
-                           (fb_width * adjusted_mode->height))
-                               hdmi_write32(IPIL_PFIT_CONTROL,
-                                       IPIL_PFIT_ENABLE |
-                                       IPIL_PFIT_PIPE_SELECT_B);
-                       else if ((adjusted_mode->width *
-                               fb_height) > (fb_width *
-                               adjusted_mode->height))
-                               hdmi_write32(IPIL_PFIT_CONTROL,
-                                       IPIL_PFIT_ENABLE |
-                                       IPIL_PFIT_PIPE_SELECT_B |
-                                       IPIL_PFIT_SCALING_PILLARBOX);
-                       else
-                               hdmi_write32(IPIL_PFIT_CONTROL,
-                                       IPIL_PFIT_ENABLE |
-                                       IPIL_PFIT_PIPE_SELECT_B |
-                                       IPIL_PFIT_SCALING_LETTERBOX);
+                   (adjusted_mode->height != fb_height)) {
+                       if (fb_width > fb_height) {
+                               pr_debug("[hdmi]: Landscape mode...\n");
+                               /* Landscape mode: program ratios is
+                                * used because 480p does not work with
+                                * auto */
+                               if (adjusted_mode->height == 480)
+                                       pfit_landscape(sprite_width,
+                                               sprite_height,
+                                               adjusted_mode->width,
+                                               adjusted_mode->height);
+                               else
+                                       hdmi_write32(IPIL_PFIT_CONTROL,
+                                               IPIL_PFIT_ENABLE |
+                                               IPIL_PFIT_PIPE_SELECT_B |
+                                               IPIL_PFIT_SCALING_AUTO);
+                       } else {
+                               /* Portrait mode */
+                               pr_debug("[hdmi]: Portrait mode...\n");
+                               if (adjusted_mode->height == 768 &&
+                                       adjusted_mode->width == 1024) {
+                                       src_image_hor = adjusted_mode->width *
+                                                       fb_height /
+                                                       adjusted_mode->height;
+                                       src_image_vert = fb_height;
+                                       sprite_pos_x = (src_image_hor -
+                                                               fb_width) / 2;
+                                       hdmi_write32(IPIL_PFIT_CONTROL,
+                                               IPIL_PFIT_ENABLE |
+                                               IPIL_PFIT_PIPE_SELECT_B |
+                                               IPIL_PFIT_SCALING_AUTO);
+                               } else
+                                       hdmi_write32(IPIL_PFIT_CONTROL,
+                                               IPIL_PFIT_ENABLE |
+                                               IPIL_PFIT_PIPE_SELECT_B |
+                                               IPIL_PFIT_SCALING_PILLARBOX);
+                       }
+               } else {
+                       /* Disable panel fitting */
+                       hdmi_write32(IPIL_PFIT_CONTROL, 0);
                }
+
                break;
 
        default:
+               /* Android will not change mode, however ,we have tools
+               to change HDMI timing so there is some cases frame
+               buffer no change ,but timing changed mode setting, in
+               this case. mode information for source size is not
+               right, so here use fb information for source/sprite
+               size*/
+
+               /* The defined sprite rectangle must always be
+               completely contained within the displayable area of the
+               screen image (frame buffer). */
+               sprite_pos_x = 0;
+               sprite_pos_y = 0;
+               sprite_height = fb_height;
+               sprite_width = fb_width;
+               src_image_hor = fb_width;
+               src_image_vert = fb_height;
                if ((adjusted_mode->width != fb_width) ||
-                       (adjusted_mode->height != fb_height))
+                               (adjusted_mode->height != fb_height))
                        hdmi_write32(IPIL_PFIT_CONTROL,
                                        IPIL_PFIT_ENABLE |
                                        IPIL_PFIT_PIPE_SELECT_B);
@@ -386,14 +484,19 @@ otm_hdmi_ret_t ipil_hdmi_crtc_mode_set_program_dspregs(hdmi_device_t *dev,
                break;
        }
 
+       pr_debug("Sprite position: (%d, %d)\n", sprite_pos_x,
+                       sprite_pos_y);
+       pr_debug("Sprite size: %d x %d\n", sprite_width,
+                       sprite_height);
+       pr_debug("Pipe source image size: %d x %d\n",
+                       src_image_hor, src_image_vert);
+
+       hdmi_write32(IPIL_DSPBPOS, (sprite_pos_y << 16) | sprite_pos_x);
        hdmi_write32(IPIL_DSPBSIZE, ((sprite_height - 1) << 16) |
                                 (sprite_width - 1));
-
        hdmi_write32(IPIL_PIPEBSRC, ((src_image_hor - 1) << 16) |
                                (src_image_vert - 1));
 
-       hdmi_write32(IPIL_DSPBPOS, (sprite_pos_y << 16) | sprite_pos_x);
-
        return OTM_HDMI_SUCCESS;
 }
 
index 04adcbf..a7be6d4 100644 (file)
@@ -64,7 +64,7 @@
 #include "hdmi_internal.h"
 #include "ps_hdmi.h"
 
-#define PS_PREF_SCALINGTYPE IPIL_TIMING_SCALE_FULLSCREEN
+#define PS_PREF_SCALINGTYPE IPIL_TIMING_SCALE_ASPECT
 
 /*
  * Description: fetches the preferred scaling type for a aprticular platfrom.