Commit 982f8ad6 authored by Edmund Dea's avatar Edmund Dea Committed by Maarten Lankhorst

drm/kmb: Disable change of plane parameters

Due to HW limitations, KMB cannot change height, width, or
pixel format after initial plane configuration.

v2: removed memset disp_cfg as it is already zero.

Fixes: 7f7b96a8 ("drm/kmb: Add support for KeemBay Display")
Signed-off-by: default avatarEdmund Dea <edmund.j.dea@intel.com>
Signed-off-by: default avatarAnitha Chrisanthus <anitha.chrisanthus@intel.com>
Acked-by: default avatarSam Ravnborg <sam@ravnborg.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20211013233632.471892-4-anitha.chrisanthus@intel.comSigned-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
parent 13047a09
...@@ -57,6 +57,7 @@ struct kmb_drm_private { ...@@ -57,6 +57,7 @@ struct kmb_drm_private {
spinlock_t irq_lock; spinlock_t irq_lock;
int irq_lcd; int irq_lcd;
int sys_clk_mhz; int sys_clk_mhz;
struct disp_cfg init_disp_cfg[KMB_MAX_PLANES];
struct layer_status plane_status[KMB_MAX_PLANES]; struct layer_status plane_status[KMB_MAX_PLANES];
int kmb_under_flow; int kmb_under_flow;
int kmb_flush_done; int kmb_flush_done;
......
...@@ -67,8 +67,21 @@ static const u32 kmb_formats_v[] = { ...@@ -67,8 +67,21 @@ static const u32 kmb_formats_v[] = {
static unsigned int check_pixel_format(struct drm_plane *plane, u32 format) static unsigned int check_pixel_format(struct drm_plane *plane, u32 format)
{ {
struct kmb_drm_private *kmb;
struct kmb_plane *kmb_plane = to_kmb_plane(plane);
int i; int i;
int plane_id = kmb_plane->id;
struct disp_cfg init_disp_cfg;
kmb = to_kmb(plane->dev);
init_disp_cfg = kmb->init_disp_cfg[plane_id];
/* Due to HW limitations, changing pixel format after initial
* plane configuration is not supported.
*/
if (init_disp_cfg.format && init_disp_cfg.format != format) {
drm_dbg(&kmb->drm, "Cannot change format after initial plane configuration");
return -EINVAL;
}
for (i = 0; i < plane->format_count; i++) { for (i = 0; i < plane->format_count; i++) {
if (plane->format_types[i] == format) if (plane->format_types[i] == format)
return 0; return 0;
...@@ -81,11 +94,17 @@ static int kmb_plane_atomic_check(struct drm_plane *plane, ...@@ -81,11 +94,17 @@ static int kmb_plane_atomic_check(struct drm_plane *plane,
{ {
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
plane); plane);
struct kmb_drm_private *kmb;
struct kmb_plane *kmb_plane = to_kmb_plane(plane);
int plane_id = kmb_plane->id;
struct disp_cfg init_disp_cfg;
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
int ret; int ret;
struct drm_crtc_state *crtc_state; struct drm_crtc_state *crtc_state;
bool can_position; bool can_position;
kmb = to_kmb(plane->dev);
init_disp_cfg = kmb->init_disp_cfg[plane_id];
fb = new_plane_state->fb; fb = new_plane_state->fb;
if (!fb || !new_plane_state->crtc) if (!fb || !new_plane_state->crtc)
return 0; return 0;
...@@ -99,6 +118,16 @@ static int kmb_plane_atomic_check(struct drm_plane *plane, ...@@ -99,6 +118,16 @@ static int kmb_plane_atomic_check(struct drm_plane *plane,
new_plane_state->crtc_w < KMB_FB_MIN_WIDTH || new_plane_state->crtc_w < KMB_FB_MIN_WIDTH ||
new_plane_state->crtc_h < KMB_FB_MIN_HEIGHT) new_plane_state->crtc_h < KMB_FB_MIN_HEIGHT)
return -EINVAL; return -EINVAL;
/* Due to HW limitations, changing plane height or width after
* initial plane configuration is not supported.
*/
if ((init_disp_cfg.width && init_disp_cfg.height) &&
(init_disp_cfg.width != fb->width ||
init_disp_cfg.height != fb->height)) {
drm_dbg(&kmb->drm, "Cannot change plane height or width after initial configuration");
return -EINVAL;
}
can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY); can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
crtc_state = crtc_state =
drm_atomic_get_existing_crtc_state(state, drm_atomic_get_existing_crtc_state(state,
...@@ -335,6 +364,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane, ...@@ -335,6 +364,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
unsigned char plane_id; unsigned char plane_id;
int num_planes; int num_planes;
static dma_addr_t addr[MAX_SUB_PLANES]; static dma_addr_t addr[MAX_SUB_PLANES];
struct disp_cfg *init_disp_cfg;
if (!plane || !new_plane_state || !old_plane_state) if (!plane || !new_plane_state || !old_plane_state)
return; return;
...@@ -357,7 +387,8 @@ static void kmb_plane_atomic_update(struct drm_plane *plane, ...@@ -357,7 +387,8 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
} }
spin_unlock_irq(&kmb->irq_lock); spin_unlock_irq(&kmb->irq_lock);
src_w = (new_plane_state->src_w >> 16); init_disp_cfg = &kmb->init_disp_cfg[plane_id];
src_w = new_plane_state->src_w >> 16;
src_h = new_plane_state->src_h >> 16; src_h = new_plane_state->src_h >> 16;
crtc_x = new_plane_state->crtc_x; crtc_x = new_plane_state->crtc_x;
crtc_y = new_plane_state->crtc_y; crtc_y = new_plane_state->crtc_y;
...@@ -500,6 +531,16 @@ static void kmb_plane_atomic_update(struct drm_plane *plane, ...@@ -500,6 +531,16 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
/* Enable DMA */ /* Enable DMA */
kmb_write_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id), dma_cfg); kmb_write_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id), dma_cfg);
/* Save initial display config */
if (!init_disp_cfg->width ||
!init_disp_cfg->height ||
!init_disp_cfg->format) {
init_disp_cfg->width = width;
init_disp_cfg->height = height;
init_disp_cfg->format = fb->format->format;
}
drm_dbg(&kmb->drm, "dma_cfg=0x%x LCD_DMA_CFG=0x%x\n", dma_cfg, drm_dbg(&kmb->drm, "dma_cfg=0x%x LCD_DMA_CFG=0x%x\n", dma_cfg,
kmb_read_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id))); kmb_read_lcd(kmb, LCD_LAYERn_DMA_CFG(plane_id)));
......
...@@ -63,6 +63,12 @@ struct layer_status { ...@@ -63,6 +63,12 @@ struct layer_status {
u32 ctrl; u32 ctrl;
}; };
struct disp_cfg {
unsigned int width;
unsigned int height;
unsigned int format;
};
struct kmb_plane *kmb_plane_init(struct drm_device *drm); struct kmb_plane *kmb_plane_init(struct drm_device *drm);
void kmb_plane_destroy(struct drm_plane *plane); void kmb_plane_destroy(struct drm_plane *plane);
#endif /* __KMB_PLANE_H__ */ #endif /* __KMB_PLANE_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment