static int xvip_dma_stop_streaming(struct vb2_queue *vq) { struct xvip_dma *dma = vb2_get_drv_priv(vq); struct xvip_pipeline *pipe = to_xvip_pipeline(&dma->video.entity); struct xilinx_vdma_config config; /* Stop the pipeline. */ xvip_pipeline_set_stream(pipe, false); /* Stop and reset the DMA engine. */ dmaengine_device_control(dma->dma, DMA_TERMINATE_ALL, 0); config.reset = 1; dmaengine_device_control(dma->dma, DMA_SLAVE_CONFIG, (unsigned long)&config); /* Cleanup the pipeline and mark it as being stopped. */ xvip_pipeline_cleanup(pipe); media_entity_pipeline_stop(&dma->video.entity); return 0; }
static int xvip_dma_set_format(struct file *file, void *fh, struct v4l2_format *format) { struct v4l2_fh *vfh = file->private_data; struct xvip_dma *dma = to_xvip_dma(vfh->vdev); const struct xvip_video_format *info; struct xilinx_vdma_config config; int ret; __xvip_dma_try_format(dma, &format->fmt.pix, &info); mutex_lock(&dma->lock); if (vb2_is_streaming(&dma->queue)) { ret = -EBUSY; goto done; } dma->format = format->fmt.pix; dma->fmtinfo = info; /* Configure the DMA engine. */ memset(&config, 0, sizeof(config)); config.park = 1; config.park_frm = 0; config.vsize = dma->format.height; config.hsize = dma->format.width * info->bpp; config.stride = dma->format.bytesperline; config.ext_fsync = 2; dmaengine_device_control(dma->dma, DMA_SLAVE_CONFIG, (unsigned long)&config); ret = 0; done: mutex_unlock(&dma->lock); return ret; }
/* 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; }
/* set plane dpms */ void xilinx_drm_plane_dpms(struct drm_plane *base_plane, int dpms) { struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane); struct xilinx_drm_plane_manager *manager = plane->manager; struct xilinx_vdma_config dma_config; DRM_DEBUG_KMS("plane->id: %d\n", plane->id); DRM_DEBUG_KMS("dpms: %d -> %d\n", plane->dpms, dpms); if (plane->dpms == dpms) return; plane->dpms = dpms; switch (dpms) { case DRM_MODE_DPMS_ON: /* start vdma engine */ dma_async_issue_pending(plane->vdma.chan); if (plane->rgb2yuv) xilinx_rgb2yuv_enable(plane->rgb2yuv); if (plane->cresample) xilinx_cresample_enable(plane->cresample); /* enable osd */ if (manager->osd) { xilinx_osd_disable_rue(manager->osd); xilinx_osd_layer_set_priority(plane->osd_layer, plane->prio); xilinx_osd_layer_set_alpha(plane->osd_layer, 1, plane->alpha); xilinx_osd_layer_enable(plane->osd_layer); if (plane->priv) { /* set background color as black */ xilinx_osd_set_color(manager->osd, 0x0, 0x0, 0x0); xilinx_osd_enable(manager->osd); } xilinx_osd_enable_rue(manager->osd); } break; default: /* disable/reset osd */ if (manager->osd) { xilinx_osd_disable_rue(manager->osd); xilinx_osd_layer_set_dimension(plane->osd_layer, 0, 0, 0, 0); xilinx_osd_layer_disable(plane->osd_layer); if (plane->priv) xilinx_osd_reset(manager->osd); xilinx_osd_enable_rue(manager->osd); } if (plane->cresample) { xilinx_cresample_disable(plane->cresample); xilinx_cresample_reset(plane->cresample); } if (plane->rgb2yuv) { xilinx_rgb2yuv_disable(plane->rgb2yuv); xilinx_rgb2yuv_reset(plane->rgb2yuv); } /* reset vdma */ dma_config.reset = 1; dmaengine_device_control(plane->vdma.chan, DMA_SLAVE_CONFIG, (unsigned long)&dma_config); /* stop vdma engine and release descriptors */ dmaengine_terminate_all(plane->vdma.chan); break; } }