@@ -347,25 +347,47 @@ static void kmb_setup_mode_config(struct drm_device *drm)
static irqreturn_t handle_lcd_irq(struct drm_device *dev)
{
unsigned long status, val;
+ int plane_id;
struct kmb_drm_private *dev_p = to_kmb(dev);
status = kmb_read_lcd(dev_p, LCD_INT_STATUS);
if (status & LCD_INT_EOF) {
- /*To DO - handle EOF interrupt? */
- kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_EOF);
+ /* TODO - handle EOF interrupt? */
+ kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_EOF);
+
+ /* When disabling/enabling LCD layers, the change takes effect
+ * immediately and does not wait for EOF (end of frame).
+ * When kmb_plane_atomic_disable is called, mark the plane as
+ * disabled but actually disable the plane when EOF irq is
+ * being handled.
+ */
+ for (plane_id = LAYER_0; plane_id < KMB_MAX_PLANES;
+ plane_id++) {
+ if (plane_status[plane_id].disable) {
+ kmb_clr_bitmask_lcd(dev_p,
+ LCD_LAYERn_DMA_CFG(plane_id),
+ LCD_DMA_LAYER_ENABLE);
+
+ kmb_clr_bitmask_lcd(dev_p, LCD_CONTROL,
+ plane_status[plane_id].ctrl);
+
+ plane_status[plane_id].disable = false;
+ }
+ }
}
+
if (status & LCD_INT_LINE_CMP) {
/* clear line compare interrupt */
- kmb_write_lcd(dev_p, LCD_INT_CLEAR,
- LCD_INT_LINE_CMP);
+ kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_LINE_CMP);
}
+
if (status & LCD_INT_LAYER) {
/* Clear layer interrupts */
- kmb_write_lcd(dev->dev_private, LCD_INT_CLEAR, LCD_INT_LAYER);
+ kmb_write_lcd(dev_p, LCD_INT_CLEAR, LCD_INT_LAYER);
}
if (status & LCD_INT_VERT_COMP) {
- /* read VSTATUS */
+ /* Read VSTATUS */
val = kmb_read_lcd(dev_p, LCD_VSTATUS);
val = (val & LCD_VSTATUS_VERTICAL_STATUS_MASK);
switch (val) {
@@ -382,7 +404,7 @@ static irqreturn_t handle_lcd_irq(struct drm_device *dev)
}
/* Clear all interrupts */
- kmb_set_bitmask_lcd(dev->dev_private, LCD_INT_CLEAR, ~0x0);
+ kmb_set_bitmask_lcd(dev_p, LCD_INT_CLEAR, 1);
return IRQ_HANDLED;
}
@@ -19,6 +19,7 @@
#define crtc_to_kmb_priv(x) container_of(x, struct kmb_drm_private, crtc)
+
struct kmb_drm_private {
struct drm_device drm;
void __iomem *lcd_mmio;
@@ -21,6 +21,8 @@
#include "kmb_plane.h"
#include "kmb_regs.h"
+struct layer_status plane_status[KMB_MAX_PLANES];
+
const uint32_t layer_irqs[] = {
LCD_INT_VL0,
LCD_INT_VL1,
@@ -62,34 +64,24 @@ static void kmb_plane_atomic_disable(struct drm_plane *plane,
struct drm_plane_state *state)
{
struct kmb_plane *kmb_plane = to_kmb_plane(plane);
- int ctrl = 0;
- struct kmb_drm_private *dev_p;
- int plane_id;
-
- dev_p = to_kmb(plane->dev);
- plane_id = kmb_plane->id;
+ int plane_id = kmb_plane->id;
switch (plane_id) {
case LAYER_0:
- ctrl = LCD_CTRL_VL1_ENABLE;
+ plane_status[plane_id].ctrl = LCD_CTRL_VL1_ENABLE;
break;
case LAYER_1:
- ctrl = LCD_CTRL_VL2_ENABLE;
+ plane_status[plane_id].ctrl = LCD_CTRL_VL2_ENABLE;
break;
case LAYER_2:
- ctrl = LCD_CTRL_GL1_ENABLE;
+ plane_status[plane_id].ctrl = LCD_CTRL_GL1_ENABLE;
break;
case LAYER_3:
- ctrl = LCD_CTRL_GL2_ENABLE;
+ plane_status[plane_id].ctrl = LCD_CTRL_GL2_ENABLE;
break;
}
- kmb_clr_bitmask_lcd(dev_p, LCD_LAYERn_DMA_CFG(plane_id),
- LCD_DMA_LAYER_ENABLE);
- kmb_clr_bitmask_lcd(dev_p, LCD_CONTROL, ctrl);
- DRM_DEBUG("%s : %d lcd_ctrl = 0x%x lcd_int_enable=0x%x\n",
- __func__, __LINE__, kmb_read_lcd(dev_p, LCD_CONTROL),
- kmb_read_lcd(dev_p, LCD_INT_ENABLE));
+ plane_status[plane_id].disable = true;
}
unsigned int set_pixel_format(u32 format)
@@ -41,9 +41,11 @@ enum layer_id {
LAYER_1,
LAYER_2,
LAYER_3,
- KMB_MAX_PLANES,
+// KMB_MAX_PLANES,
};
+#define KMB_MAX_PLANES 1
+
enum sub_plane_id {
Y_PLANE,
U_PLANE,
@@ -105,6 +107,13 @@ static const u32 csc_coef_lcd[] = {
-179, 125, -226
};
+struct layer_status {
+ bool disable;
+ u32 ctrl;
+};
+
+extern struct layer_status plane_status[KMB_MAX_PLANES];
+
struct kmb_plane *kmb_plane_init(struct drm_device *drm);
void kmb_plane_destroy(struct drm_plane *plane);
#endif /* __KMB_PLANE_H__ */