vout: add dummy_panel display mode [1/1]
authorEvoke Zhang <evoke.zhang@amlogic.com>
Thu, 21 Feb 2019 04:23:45 +0000 (12:23 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Wed, 27 Feb 2019 07:52:33 +0000 (23:52 -0800)
PD#SWPL-5017

Problem:
need support dummy lcd for viu1

Solution:
add dummp_panel display mode.
when need viu1 + viu2 -> encl, and show viu2 data,
you can use below setting:
echo dump_panel >/sys/class/display/mode
echo panel >/sys/class/display2/mode

Verify:
x301

Change-Id: I8a7fb52e2272fc8f71d682424ff20dc37f02b726
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
drivers/amlogic/media/vout/lcd/lcd_debug.c
drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c
drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c
drivers/amlogic/media/vout/vout_serve/vout_func.c
drivers/amlogic/media/vout/vout_serve/vout_func.h
drivers/amlogic/media/vout/vout_serve/vout_serve.c
include/linux/amlogic/media/vout/vinfo.h

index dff5254..561d2e4 100644 (file)
@@ -516,12 +516,13 @@ static int lcd_info_print(char *buf, int offset)
        n = lcd_debug_info_len(len + offset);
        len += snprintf((buf+len), n,
                "driver version: %s\n"
-               "panel_type: %s, chip: %d, mode: %s, status: %d\n"
+               "panel_type: %s, chip: %d, mode: %s, status: %d, viu_sel: %d\n"
                "key_valid: %d, config_load: %d\n"
                "fr_auto_policy: %d\n",
                lcd_drv->version,
                pconf->lcd_propname, lcd_drv->data->chip_type,
-               lcd_mode_mode_to_str(lcd_drv->lcd_mode), lcd_drv->lcd_status,
+               lcd_mode_mode_to_str(lcd_drv->lcd_mode),
+               lcd_drv->lcd_status, lcd_drv->viu_sel,
                lcd_drv->lcd_key_valid, lcd_drv->lcd_config_load,
                lcd_drv->fr_auto_policy);
 
index 4f67604..8a64ba6 100644 (file)
@@ -131,7 +131,8 @@ static int lcd_vout_clr_state(int index)
        struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
 
        lcd_vout_state &= ~(1 << index);
-       lcd_drv->viu_sel = LCD_VIU_SEL_NONE;
+       if (lcd_drv->viu_sel == index)
+               lcd_drv->viu_sel = LCD_VIU_SEL_NONE;
 
        return 0;
 }
index ebd7b8d..abd0899 100644 (file)
@@ -389,7 +389,8 @@ static int lcd_vout_clr_state(int index)
        struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
 
        lcd_vout_state &= ~(1 << index);
-       lcd_drv->viu_sel = LCD_VIU_SEL_NONE;
+       if (lcd_drv->viu_sel == index)
+               lcd_drv->viu_sel = LCD_VIU_SEL_NONE;
 
        return 0;
 }
index c8661b3..0ea80a6 100644 (file)
@@ -245,6 +245,19 @@ void vout_func_update_viu(int index)
        if (clk_bit < 0xff)
                vout_func_vcbus_setb(VPU_VENCX_CLK_CTRL, clk_sel, clk_bit, 1);
 
+       /* special setting for dummy mode */
+       if (index == 1) {
+               if (vinfo->mode == VMODE_DUMMY_LCD) {
+                       /* viu1 use encl_vsync */
+                       vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, 0, 4, 2);
+                       vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, 1, 20, 1);
+                       vout_func_vcbus_setb(VPP_WRBAK_CTRL, 1, 11, 1);
+               } else {
+                       vout_func_vcbus_setb(VPU_VIU_VENC_MUX_CTRL, 0, 20, 1);
+                       vout_func_vcbus_setb(VPP_WRBAK_CTRL, 0, 11, 1);
+               }
+       }
+
 #if 0
        VOUTPR("%s: %d, mux_sel=%d, clk_sel=%d\n",
                __func__, index, mux_sel, clk_sel);
index 524f1e7..1aa1c6a 100644 (file)
@@ -36,6 +36,7 @@
 #define VPU_VENCX_CLK_CTRL                         0x2785
 #define VPP_POSTBLEND_H_SIZE                       0x1d21
 #define VPP2_POSTBLEND_H_SIZE                      0x1921
+#define VPP_WRBAK_CTRL                             0x1df9
 
 struct vout_cdev_s {
        dev_t         devno;
index abb27c1..ea168f8 100644 (file)
@@ -129,6 +129,24 @@ static struct vinfo_s nulldisp_vinfo[] = {
                .viu_mux           = VIU_MUX_MAX,
                .vout_device       = NULL,
        },
+       {
+               .name              = "dummy_panel",
+               .mode              = VMODE_DUMMY_LCD,
+               .width             = 1920,
+               .height            = 1080,
+               .field_height      = 1080,
+               .aspect_ratio_num  = 16,
+               .aspect_ratio_den  = 9,
+               .sync_duration_num = 60,
+               .sync_duration_den = 1,
+               .video_clk         = 148500000,
+               .htotal            = 2200,
+               .vtotal            = 1125,
+               .fr_adj_type       = VOUT_FR_ADJ_NONE,
+               .viu_color_fmt     = COLOR_FMT_RGB444,
+               .viu_mux           = VIU_MUX_MAX,
+               .vout_device       = NULL,
+       },
 };
 
 static struct vinfo_s *nulldisp_get_current_info(void)
@@ -379,6 +397,41 @@ static ssize_t vout_mode_store(struct class *class,
        return count;
 }
 
+static ssize_t vout_dummy_store(struct class *class,
+               struct class_attribute *attr, const char *buf, size_t count)
+{
+       unsigned int tmp[4], sync_duration;
+       enum vmode_e mode;
+       int ret;
+
+       mutex_lock(&vout_serve_mutex);
+       mode = VMODE_DUMMY_LCD;
+       ret = sscanf(buf, "%d %d %d %d", &tmp[0], &tmp[1], &tmp[2], &tmp[3]);
+       if (ret == 2) {
+               nulldisp_vinfo[2].width = tmp[0];
+               nulldisp_vinfo[2].height = tmp[1];
+               nulldisp_vinfo[2].field_height = tmp[1];
+               VOUTPR("set dummy size: %d x %d\n", tmp[0], tmp[1]);
+               vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode);
+       } else if (ret == 4) {
+               nulldisp_vinfo[2].width = tmp[0];
+               nulldisp_vinfo[2].height = tmp[1];
+               nulldisp_vinfo[2].field_height = tmp[1];
+               nulldisp_vinfo[2].sync_duration_num = tmp[2];
+               nulldisp_vinfo[2].sync_duration_den = tmp[3];
+               sync_duration = (tmp[2] * 100) / tmp[3];
+               VOUTPR("set dummy size: %d x %d, frame_rate: %d.%02dHz\n",
+                       tmp[0], tmp[1],
+                       (sync_duration / 100), (sync_duration % 100));
+               vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode);
+       } else {
+               VOUTERR("invalid data\n");
+       }
+       mutex_unlock(&vout_serve_mutex);
+
+       return count;
+}
+
 static ssize_t vout_axis_show(struct class *class,
                struct class_attribute *attr, char *buf)
 {
@@ -555,6 +608,7 @@ static ssize_t vout_vinfo_show(struct class *class,
 
 static struct class_attribute vout_class_attrs[] = {
        __ATTR(mode,      0644, vout_mode_show, vout_mode_store),
+       __ATTR(dummy,      0644, NULL, vout_dummy_store),
        __ATTR(axis,      0644, vout_axis_show, vout_axis_store),
        __ATTR(fr_policy, 0644,
                vout_fr_policy_show, vout_fr_policy_store),
index 96cbf12..6ef397b 100644 (file)
@@ -23,7 +23,7 @@
 /* the MSB is represent vmode set by vmode_init */
 #define        VMODE_INIT_BIT_MASK     0x8000
 #define        VMODE_MODE_BIT_MASK     0xff
-#define VMODE_NULL_DISP_MAX    2
+#define VMODE_NULL_DISP_MAX    3
 
 enum vmode_e {
        VMODE_HDMI = 0,
@@ -31,6 +31,7 @@ enum vmode_e {
        VMODE_LCD,
        VMODE_NULL, /* null mode is used as temporary witch mode state */
        VMODE_INVALID,
+       VMODE_DUMMY_LCD,
        VMODE_MAX,
        VMODE_INIT_NULL,
        VMODE_MASK = 0xFF,