diff --git a/drivers/gpu/drm/loongson/loongson_connector.c b/drivers/gpu/drm/loongson/loongson_connector.c
index 6bba574..db37476 100644
--- a/drivers/gpu/drm/loongson/loongson_connector.c
+++ b/drivers/gpu/drm/loongson/loongson_connector.c
@@ -193,6 +193,8 @@ static int loongson_vga_mode_valid(struct drm_connector *connector,
 				 struct drm_display_mode *mode)
 {
 	int id, locked;
+	int conn_count = 0;
+	struct drm_connector *conn;
 	struct drm_device *dev = connector->dev;
 	struct loongson_drm_device *ldev = (struct loongson_drm_device*)dev->dev_private;
 
@@ -200,12 +202,23 @@ static int loongson_vga_mode_valid(struct drm_connector *connector,
 	id = drm_connector_index(connector);
 	if (locked) mutex_unlock(&dev->mode_config.mutex);
 
-	if (mode->hdisplay % 64)
-		return MODE_BAD;
-	if (mode->hdisplay > ldev->crtc_vbios[id]->crtc_max_weight)
+	list_for_each_entry(conn, &dev->mode_config.connector_list, head) {
+		if (conn->status == connector_status_connected)
+			conn_count++;
+	}
+
+	if (mode->hdisplay > ldev->crtc_vbios[id]->crtc_max_width)
 		return MODE_BAD;
 	if (mode->vdisplay > ldev->crtc_vbios[id]->crtc_max_height)
 		return MODE_BAD;
+	if ((mode->hdisplay % 64) && (ldev->num_crtc > 1)) {
+		if (conn_count > 1)
+			return MODE_BAD;
+		if (!ldev->lfbdev || !ldev->mode_info[id].crtc->base.fb)
+			return MODE_BAD;
+		if (ldev->mode_info[id].crtc->base.fb == &ldev->lfbdev->lfb)
+			return MODE_BAD;
+	}
 
 	return MODE_OK;
 }
diff --git a/drivers/gpu/drm/loongson/loongson_crtc.c b/drivers/gpu/drm/loongson/loongson_crtc.c
index b96a576..877a4fa 100644
--- a/drivers/gpu/drm/loongson/loongson_crtc.c
+++ b/drivers/gpu/drm/loongson/loongson_crtc.c
@@ -98,6 +98,7 @@ static int loongson_crtc_do_set_base(struct drm_crtc *crtc,
 	struct loongson_drm_device *ldev = crtc->dev->dev_private;
 	struct loongson_crtc *loongson_crtc = to_loongson_crtc(crtc);
 
+	crtc_count = 0;
 	list_for_each_entry(crtci, &dev->mode_config.crtc_list, head) {
 		if (crtci->enabled)
 			crtc_count++;
@@ -132,10 +133,10 @@ static int loongson_crtc_do_set_base(struct drm_crtc *crtc,
 	} else if(ldev->mode_info[0].connector->base.status == connector_status_connected
 			&& ldev->mode_info[1].connector->base.status == connector_status_connected
 			&& loongson_fb->base.width == crtc->mode.hdisplay && loongson_fb->base.height == crtc->mode.vdisplay && x == 0 && y == 0) {
-		DRM_DEBUG("use clone mode\n");
+		DRM_DEBUG("use dual-clone mode\n");
 		ldev->clone_mode = true;
 	} else {
-		DRM_DEBUG("use non-clone mode\n");
+		DRM_DEBUG("use dual-expand mode\n");
 		ldev->clone_mode = false;
 	}
 
@@ -185,7 +186,7 @@ static int loongson_crtc_do_set_base(struct drm_crtc *crtc,
 		case 32:
 		default:
 			writel(0x00100104, base + LS_FB_CFG_DVO0_REG);
-			writel(crtc->fb->pitches[0], base + LS_FB_STRI_DVO0_REG);
+			writel((width * 4 + 255) & ~255, base + LS_FB_STRI_DVO0_REG);
 			crtc_address = (u32)gpu_addr + y * pitch + ALIGN(x, 64) * 4;
 			break;
 		}
@@ -212,7 +213,7 @@ static int loongson_crtc_do_set_base(struct drm_crtc *crtc,
 			case 32:
 			default:
 				writel(0x00100104, base + LS_FB_CFG_DVO1_REG);
-				writel(crtc->fb->pitches[0], base + LS_FB_STRI_DVO1_REG);
+				writel((width * 4 + 255) & ~255, base + LS_FB_STRI_DVO1_REG);
 				crtc_address = (u32)gpu_addr + y * pitch + ALIGN(x, 64) * 4;
 				break;
 			}
@@ -237,7 +238,7 @@ static int loongson_crtc_do_set_base(struct drm_crtc *crtc,
 			case 32:
 			default:
 				writel(0x00100304, base + LS_FB_CFG_DVO1_REG);
-				writel(crtc->fb->pitches[0], base + LS_FB_STRI_DVO1_REG);
+				writel((width * 4 + 255) & ~255, base + LS_FB_STRI_DVO1_REG);
 				crtc_address = (u32)gpu_addr + y * pitch + ALIGN(x, 64) * 4;
 				break;
 			}
@@ -247,8 +248,6 @@ static int loongson_crtc_do_set_base(struct drm_crtc *crtc,
 
 	mdelay(10); /* Wait config registers to be stable */
 	loongson_set_start_address(crtc, (u32)crtc_address);
-	ldev->cursor_crtc_id = ldev->num_crtc;
-	ldev->cursor_showed = false;
 
 	return 0;
 }
@@ -589,8 +588,7 @@ static int loongson_crtc_mode_set(struct drm_crtc *crtc,
 		writel(0x40000000 | (vse << 16) | vss, base + LS_FB_VSYNC_DVO1_REG);
 		mutex_unlock(&loongson_reglock);
 	}
-	ldev->cursor_crtc_id = ldev->num_crtc;
-	ldev->cursor_showed = false;
+
 	return 0;
 }
 
@@ -610,7 +608,7 @@ static void loongson_crtc_dpms(struct drm_crtc *crtc, int mode)
  	struct loongson_drm_device *ldev = dev->dev_private;
  	struct loongson_crtc *loongson_crtc = to_loongson_crtc(crtc);
 
-	if (ldev->inited == false || ldev->clone_mode == true)
+	if (!ldev->inited)
 		return;
 
 	base = ldev->rmmio;
@@ -626,7 +624,10 @@ static void loongson_crtc_dpms(struct drm_crtc *crtc, int mode)
 			mutex_unlock(&loongson_reglock);
 		} else {
 			val = readl(base + LS_FB_CFG_DVO1_REG);
-			val |= (1 << 8);
+			if (!ldev->clone_mode)
+				val |= (1 << 8);
+			else
+				val |= (3 << 8);
 			mutex_lock(&loongson_reglock);
 			writel(val, base + LS_FB_CFG_DVO1_REG);
 			mutex_unlock(&loongson_reglock);
diff --git a/drivers/gpu/drm/loongson/loongson_cursor.c b/drivers/gpu/drm/loongson/loongson_cursor.c
index c35c5eb..d81cddf 100644
--- a/drivers/gpu/drm/loongson/loongson_cursor.c
+++ b/drivers/gpu/drm/loongson/loongson_cursor.c
@@ -29,9 +29,6 @@ static void loongson_hide_cursor(struct drm_crtc *crtc)
 	base = ldev->rmmio;
 	tmp = readl(base + LS_FB_CUR_CFG_REG);
 	tmp &= ~0xff;
-	mutex_lock(&loongson_reglock);
-	writel(tmp | 0x00, base + LS_FB_CUR_CFG_REG);
-	mutex_unlock(&loongson_reglock);
 	if (ldev->clone_mode == true) {
 		mutex_lock(&loongson_reglock);
 		writel(tmp | 0x00, base + LS_FB_CUR_CFG_REG);
@@ -69,7 +66,7 @@ static void loongson_show_cursor(struct drm_crtc *crtc)
 		ldev->cursor_crtc_id = 0;
 		ldev->cursor_showed = true;
 	} else {
-		if ((ldev->cursor_crtc_id == crtc_id) ||(ldev->cursor_crtc_id == ldev->num_crtc)) {
+		if (ldev->cursor_crtc_id == crtc_id) {
 			mutex_lock(&loongson_reglock);
 			if(crtc_id == 0){
 				writel(0x00050202, base + LS_FB_CUR_CFG_REG);
@@ -79,7 +76,7 @@ static void loongson_show_cursor(struct drm_crtc *crtc)
 			mutex_unlock(&loongson_reglock);
 
 			ldev->cursor_showed = true;
-			ldev->cursor_crtc_id == crtc_id;
+			ldev->cursor_crtc_id = crtc_id;
 		}
 	}
 }
@@ -209,10 +206,10 @@ int loongson_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
 	 * && xorign/ yorign > 0, it means the cursor is in the framebuffer
 	 * but not in curren review */
 	if ((x < 0 && xorign > 0) || (y < 0 && yorign > 0)) {
-		if(ldev->cursor_crtc_id == crtc_id && ldev->clone_mode == false)
+		if(ldev->cursor_crtc_id == crtc_id && !ldev->clone_mode)
 		 /*the cursor is not show, so hide if the (x,y) is in active crtc*/
 			loongson_hide_cursor(crtc);
-		return 0 ;
+		return 0;
 	}
 
 	if (x < 0)
@@ -225,13 +222,9 @@ int loongson_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
 	mutex_lock(&loongson_reglock);
 	writel(tmp, base + LS_FB_CUR_LOC_ADDR_REG);
 	mutex_unlock(&loongson_reglock);
-	tmp = readl(base + LS_FB_CUR_CFG_REG);
-	tmp &= ~0xff;
-	if (ldev->cursor_crtc_id != crtc_id && ldev->clone_mode == false) {
+	if (ldev->cursor_crtc_id != crtc_id && !ldev->clone_mode) {
 		ldev->cursor_crtc_id = crtc_id;
-		if (ldev->cursor_showed) {
-			ldev->cursor_showed = false;
-		}
+		ldev->cursor_showed = false;
 	}
 	if (!ldev->cursor_showed)
 		loongson_show_cursor(crtc);
diff --git a/drivers/gpu/drm/loongson/loongson_fb.c b/drivers/gpu/drm/loongson/loongson_fb.c
index ebd6415..4075159 100644
--- a/drivers/gpu/drm/loongson/loongson_fb.c
+++ b/drivers/gpu/drm/loongson/loongson_fb.c
@@ -322,11 +322,39 @@ err_sysram:
 
 void loongson_fb_output_poll_changed(struct loongson_drm_device *ldev)
 {
-	if (ldev->lfbdev)
+	uint32_t id, val, locked;
+	volatile void *base;
+	struct drm_connector *conn;
+
+	if (ldev->lfbdev) {
+		id = 0;
+		base = ldev->rmmio;
+
 		drm_fb_helper_hotplug_event(&ldev->lfbdev->helper);
+		locked = mutex_trylock(&ldev->dev->mode_config.mutex);
+		list_for_each_entry(conn, &ldev->dev->mode_config.connector_list, head) {
+			if (conn->status == connector_status_disconnected) {
+				if (id) {
+					val = readl(base + LS_FB_CFG_DVO0_REG);
+					val &= ~(1 << 9);
+					mutex_lock(&loongson_reglock);
+					writel(val, base + LS_FB_CFG_DVO0_REG);
+					mutex_unlock(&loongson_reglock);
+				} else {
+					val = readl(base + LS_FB_CFG_DVO1_REG);
+					val &= ~(1 << 9);
+					mutex_lock(&loongson_reglock);
+					writel(val, base + LS_FB_CFG_DVO1_REG);
+					mutex_unlock(&loongson_reglock);
+				}
+				ldev->clone_mode = false;
+			}
+			id++;
+		}
+		if (locked) mutex_unlock(&ldev->dev->mode_config.mutex);
+	}
 }
 
-
 /**
  * loongson_fbdev_destory
  *
diff --git a/drivers/gpu/drm/loongson/loongson_vbios.c b/drivers/gpu/drm/loongson/loongson_vbios.c
index 188d8b5..51b0cc8 100644
--- a/drivers/gpu/drm/loongson/loongson_vbios.c
+++ b/drivers/gpu/drm/loongson/loongson_vbios.c
@@ -101,7 +101,7 @@ void *loongson_vbios_default(void)
 	crtc_vbios[0]->next_crtc_offset = sizeof(struct loongson_vbios) + sizeof(struct loongson_vbios_crtc);
 	crtc_vbios[0]->crtc_id = 0;
 	crtc_vbios[0]->crtc_version = default_version;
-	crtc_vbios[0]->crtc_max_weight = 2048;
+	crtc_vbios[0]->crtc_max_width = 2048;
 	crtc_vbios[0]->crtc_max_height = 2048;
 	crtc_vbios[0]->connector_id = 0;
 	crtc_vbios[0]->phy_num = 1;
@@ -110,7 +110,7 @@ void *loongson_vbios_default(void)
 	crtc_vbios[1]->next_crtc_offset = NULL;
 	crtc_vbios[1]->crtc_id = 1;
 	crtc_vbios[1]->crtc_version = default_version;
-	crtc_vbios[1]->crtc_max_weight = 2048;
+	crtc_vbios[1]->crtc_max_width = 2048;
 	crtc_vbios[1]->crtc_max_height = 2048;
 	crtc_vbios[1]->connector_id = 1;
 	crtc_vbios[1]->phy_num = 1;
@@ -215,7 +215,7 @@ int loongson_vbios_init(struct loongson_drm_device *ldev){
 	}
 
 	/*get connector struct points*/
-	ldev->connector_vbios [0] = (struct loongson_vbios_connector *)(vbios_start + vbios->connector_offset);
+	ldev->connector_vbios[0] = (struct loongson_vbios_connector *)(vbios_start + vbios->connector_offset);
 	if(vbios->connector_num > 1){
 		for(i = 1;i < vbios->connector_num; i++)
 			ldev->connector_vbios[i] = (struct loongson_vbios_connector *)(vbios_start + ldev->connector_vbios[i - 1]->next_connector_offset);
@@ -245,8 +245,8 @@ int loongson_vbios_information_display(struct loongson_drm_device *ldev)
 	DRM_INFO("PHY num: %d\n", ldev->vbios->phy_num);
 	DRM_INFO("================================CRTC INFO=====================================\n");
 	for(i=0;i<ldev->vbios->crtc_num;i++){
-		DRM_INFO("CRTC-%d: max_weight=%d, max_height=%d\n",
-				ldev->crtc_vbios[i]->crtc_id,ldev->crtc_vbios[i]->crtc_max_weight,ldev->crtc_vbios[i]->crtc_max_height);
+		DRM_INFO("CRTC-%d: max_width=%d, max_height=%d\n",
+				ldev->crtc_vbios[i]->crtc_id,ldev->crtc_vbios[i]->crtc_max_width,ldev->crtc_vbios[i]->crtc_max_height);
 		DRM_INFO("CRTC-%d type is %s\n",
 				ldev->crtc_vbios[i]->crtc_id,crtc_version_name[ldev->crtc_vbios[i]->crtc_version]);
 		DRM_INFO("Bind connector id is %d\n",ldev->crtc_vbios[i]->connector_id);
diff --git a/drivers/gpu/drm/loongson/loongson_vbios.h b/drivers/gpu/drm/loongson/loongson_vbios.h
index a25a071..43ea4fb 100644
--- a/drivers/gpu/drm/loongson/loongson_vbios.h
+++ b/drivers/gpu/drm/loongson/loongson_vbios.h
@@ -25,7 +25,7 @@ struct loongson_vbios_crtc {
 	uint32_t crtc_id;
 	enum loongson_crtc_version crtc_version;
 	uint32_t crtc_max_freq;
-	uint32_t crtc_max_weight;
+	uint32_t crtc_max_width;
 	uint32_t crtc_max_height;
 	uint32_t connector_id;
 	uint32_t phy_num;
