/* mode set a plane */ int xilinx_drm_plane_mode_set(struct drm_plane *base_plane, struct drm_framebuffer *fb, int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane); struct drm_gem_cma_object *obj; size_t offset; unsigned int hsub, vsub, i; DRM_DEBUG_KMS("plane->id: %d\n", plane->id); if (fb->pixel_format != plane->format) { DRM_ERROR("unsupported pixel format %08x\n", fb->pixel_format); return -EINVAL; } /* configure cresample */ if (plane->cresample) xilinx_cresample_configure(plane->cresample, crtc_w, crtc_h); /* configure rgb2yuv */ if (plane->rgb2yuv) xilinx_rgb2yuv_configure(plane->rgb2yuv, crtc_w, crtc_h); DRM_DEBUG_KMS("h: %d(%d), v: %d(%d)\n", src_w, crtc_x, src_h, crtc_y); DRM_DEBUG_KMS("bpp: %d\n", fb->bits_per_pixel / 8); hsub = drm_format_horz_chroma_subsampling(fb->pixel_format); vsub = drm_format_vert_chroma_subsampling(fb->pixel_format); for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { unsigned int width = src_w / (i ? hsub : 1); unsigned int height = src_h / (i ? vsub : 1); unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, i); obj = xilinx_drm_fb_get_gem_obj(fb, i); if (!obj) { DRM_ERROR("failed to get a gem obj for fb\n"); return -EINVAL; } plane->dma[i].xt.numf = height; plane->dma[i].sgl[0].size = width * cpp; plane->dma[i].sgl[0].icg = fb->pitches[i] - plane->dma[i].sgl[0].size; offset = src_x * cpp + src_y * fb->pitches[i]; offset += fb->offsets[i]; plane->dma[i].xt.src_start = obj->paddr + offset; plane->dma[i].xt.frame_size = 1; plane->dma[i].xt.dir = DMA_MEM_TO_DEV; plane->dma[i].xt.src_sgl = true; plane->dma[i].xt.dst_sgl = false; plane->dma[i].is_active = true; } for (; i < MAX_NUM_SUB_PLANES; i++) plane->dma[i].is_active = false; /* set OSD dimensions */ if (plane->manager->osd) { xilinx_osd_disable_rue(plane->manager->osd); xilinx_osd_layer_set_dimension(plane->osd_layer, crtc_x, crtc_y, src_w, src_h); xilinx_osd_enable_rue(plane->manager->osd); } if (plane->manager->dp_sub) { int ret; ret = xilinx_drm_dp_sub_layer_check_size(plane->manager->dp_sub, plane->dp_layer, src_w, src_h); if (ret) return ret; } return 0; }
/* mode set a plane */ int xilinx_drm_plane_mode_set(struct drm_plane *base_plane, struct drm_framebuffer *fb, int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane); struct drm_gem_cma_object *obj; size_t offset; DRM_DEBUG_KMS("plane->id: %d\n", plane->id); if (fb->pixel_format != plane->format) { DRM_ERROR("unsupported pixel format %08x\n", fb->pixel_format); return -EINVAL; } /* configure cresample */ if (plane->cresample) xilinx_cresample_configure(plane->cresample, crtc_w, crtc_h); /* configure rgb2yuv */ if (plane->rgb2yuv) xilinx_rgb2yuv_configure(plane->rgb2yuv, crtc_w, crtc_h); obj = drm_fb_cma_get_gem_obj(fb, 0); if (!obj) { DRM_ERROR("failed to get a gem obj for fb\n"); return -EINVAL; } DRM_DEBUG_KMS("h: %d(%d), v: %d(%d), paddr: %p\n", src_w, crtc_x, src_h, crtc_y, (void *)obj->paddr); DRM_DEBUG_KMS("bpp: %d\n", fb->bits_per_pixel / 8); /* configure dma desc */ plane->dma.xt.numf = src_h; plane->dma.sgl[0].size = src_w * fb->bits_per_pixel / 8; plane->dma.sgl[0].icg = fb->pitches[0] - plane->dma.sgl[0].size; offset = src_x * fb->bits_per_pixel / 8 + src_y * fb->pitches[0]; plane->dma.xt.src_start = obj->paddr + offset; plane->dma.xt.frame_size = 1; plane->dma.xt.dir = DMA_MEM_TO_DEV; plane->dma.xt.src_sgl = true; plane->dma.xt.dst_sgl = false; /* set OSD dimensions */ if (plane->manager->osd) { xilinx_osd_disable_rue(plane->manager->osd); /* if a plane is private, it's for crtc */ if (plane->priv) xilinx_osd_set_dimension(plane->manager->osd, crtc_w, crtc_h); xilinx_osd_layer_set_dimension(plane->osd_layer, crtc_x, crtc_y, src_w, src_h); xilinx_osd_enable_rue(plane->manager->osd); } return 0; }
/* set new mode in crtc pipe */ static int xilinx_drm_crtc_mode_set(struct drm_crtc *base_crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc); struct videomode vm; long diff; int ret; /* set pixel clock */ ret = clk_set_rate(crtc->pixel_clock, adjusted_mode->clock * 1000); if (ret) { DRM_ERROR("failed to set a pixel clock\n"); return ret; } diff = clk_get_rate(crtc->pixel_clock) - adjusted_mode->clock * 1000; if (abs(diff) > (adjusted_mode->clock * 1000) / 20) DRM_INFO("actual pixel clock rate(%d) is off by %ld\n", adjusted_mode->clock, diff); /* set video timing */ vm.hactive = adjusted_mode->hdisplay; vm.hfront_porch = adjusted_mode->hsync_start - adjusted_mode->hdisplay; vm.hback_porch = adjusted_mode->htotal - adjusted_mode->hsync_end; vm.hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start; vm.vactive = adjusted_mode->vdisplay; vm.vfront_porch = adjusted_mode->vsync_start - adjusted_mode->vdisplay; vm.vback_porch = adjusted_mode->vtotal - adjusted_mode->vsync_end; vm.vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start; xilinx_vtc_config_sig(crtc->vtc, &vm); /* configure cresample and rgb2yuv */ if (crtc->cresample) xilinx_cresample_configure(crtc->cresample, adjusted_mode->hdisplay, adjusted_mode->vdisplay); if (crtc->rgb2yuv) xilinx_rgb2yuv_configure(crtc->rgb2yuv, adjusted_mode->hdisplay, adjusted_mode->vdisplay); /* configure a plane: vdma and osd layer */ ret = xilinx_drm_plane_mode_set(crtc->priv_plane, base_crtc->fb, 0, 0, adjusted_mode->hdisplay, adjusted_mode->vdisplay, x, y, adjusted_mode->hdisplay, adjusted_mode->vdisplay); if (ret) { DRM_ERROR("failed to mode set a plane\n"); return ret; } return 0; }
/* mode set a plane */ int xilinx_drm_plane_mode_set(struct drm_plane *base_plane, struct drm_framebuffer *fb, int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane); struct drm_gem_cma_object *obj; DRM_DEBUG_KMS("plane->id: %d\n", plane->id); if (fb->pixel_format != plane->format) { DRM_ERROR("unsupported pixel format %08x\n", fb->pixel_format); return -EINVAL; } /* configure cresample */ if (plane->cresample) xilinx_cresample_configure(plane->cresample, crtc_w, crtc_h); /* configure rgb2yuv */ if (plane->rgb2yuv) xilinx_rgb2yuv_configure(plane->rgb2yuv, crtc_w, crtc_h); obj = drm_fb_cma_get_gem_obj(fb, 0); if (!obj) { DRM_ERROR("failed to get a gem obj for fb\n"); return -EINVAL; } plane->x = src_x; plane->y = src_y; plane->bpp = fb->bits_per_pixel / 8; plane->paddr = obj->paddr; DRM_DEBUG_KMS("h: %d(%d), v: %d(%d), paddr: %p\n", src_w, crtc_x, src_h, crtc_y, (void *)obj->paddr); DRM_DEBUG_KMS("bpp: %d\n", plane->bpp); /* configure vdma desc */ plane->vdma.dma_config.hsize = src_w * plane->bpp; plane->vdma.dma_config.vsize = src_h; plane->vdma.dma_config.stride = fb->pitches[0]; plane->vdma.dma_config.park = 1; plane->vdma.dma_config.park_frm = 0; dmaengine_device_control(plane->vdma.chan, DMA_SLAVE_CONFIG, (unsigned long)&plane->vdma.dma_config); /* set OSD dimensions */ if (plane->manager->osd) { xilinx_osd_disable_rue(plane->manager->osd); /* if a plane is private, it's for crtc */ if (plane->priv) xilinx_osd_set_dimension(plane->manager->osd, crtc_w, crtc_h); xilinx_osd_layer_set_dimension(plane->osd_layer, crtc_x, crtc_y, src_w, src_h); xilinx_osd_enable_rue(plane->manager->osd); } return 0; }