static int ipu_drm_set_base(struct drm_crtc *crtc, int x, int y) { struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); struct drm_gem_cma_object *cma_obj; struct drm_framebuffer *fb = crtc->fb; unsigned long phys; cma_obj = drm_fb_cma_get_gem_obj(fb, 0); if (!cma_obj) { DRM_LOG_KMS("entry is null.\n"); return -EFAULT; } phys = cma_obj->paddr; phys += x * (fb->bits_per_pixel >> 3); phys += y * fb->pitches[0]; dev_dbg(ipu_crtc->dev, "%s: phys: 0x%lx\n", __func__, phys); dev_dbg(ipu_crtc->dev, "%s: xy: %dx%d\n", __func__, x, y); ipu_cpmem_set_stride(ipu_get_cpmem(ipu_crtc->ipu_ch), fb->pitches[0]); ipu_cpmem_set_buffer(ipu_get_cpmem(ipu_crtc->ipu_ch), 0, phys); return 0; }
void ipu_cpmem_set_high_priority(struct ipuv3_channel *channel) { struct ipu_soc *ipu = channel->ipu; struct ipu_ch_param __iomem *p = ipu_get_cpmem(channel); u32 val; if (ipu->ipu_type == IPUV3EX) ipu_ch_param_write_field(p, IPU_FIELD_ID, 1); val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(channel->num)); val |= 1 << (channel->num % 32); ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(channel->num)); };
static int ipu_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *orig_mode, struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *old_fb) { struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); struct drm_framebuffer *fb = ipu_crtc->base.fb; int ret; struct ipu_di_signal_cfg sig_cfg = {}; u32 out_pixel_fmt; struct ipu_ch_param __iomem *cpmem = ipu_get_cpmem(ipu_crtc->ipu_ch); int bpp; u32 v4l2_fmt; dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__, mode->hdisplay); dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__, mode->vdisplay); ipu_ch_param_zero(cpmem); switch (fb->pixel_format) { case DRM_FORMAT_XRGB8888: case DRM_FORMAT_ARGB8888: v4l2_fmt = V4L2_PIX_FMT_RGB32; bpp = 32; break; case DRM_FORMAT_RGB565: v4l2_fmt = V4L2_PIX_FMT_RGB565; bpp = 16; break; case DRM_FORMAT_RGB888: v4l2_fmt = V4L2_PIX_FMT_RGB24; bpp = 24; break; default: dev_err(ipu_crtc->dev, "unsupported pixel format 0x%08x\n", fb->pixel_format); return -EINVAL; } out_pixel_fmt = ipu_crtc->interface_pix_fmt; if (mode->flags & DRM_MODE_FLAG_INTERLACE) sig_cfg.interlaced = 1; if (mode->flags & DRM_MODE_FLAG_PHSYNC) sig_cfg.Hsync_pol = 1; if (mode->flags & DRM_MODE_FLAG_PVSYNC) sig_cfg.Vsync_pol = 1; sig_cfg.enable_pol = 1; sig_cfg.clk_pol = 0; sig_cfg.width = mode->hdisplay; sig_cfg.height = mode->vdisplay; sig_cfg.pixel_fmt = out_pixel_fmt; sig_cfg.h_start_width = mode->htotal - mode->hsync_end; sig_cfg.h_sync_width = mode->hsync_end - mode->hsync_start; sig_cfg.h_end_width = mode->hsync_start - mode->hdisplay; sig_cfg.v_start_width = mode->vtotal - mode->vsync_end; sig_cfg.v_sync_width = mode->vsync_end - mode->vsync_start; sig_cfg.v_end_width = mode->vsync_start - mode->vdisplay; sig_cfg.pixelclock = mode->clock * 1000; sig_cfg.clkflags = ipu_crtc->di_clkflags; sig_cfg.v_to_h_sync = 0; if (ipu_crtc->dp) { ret = ipu_dp_setup_channel(ipu_crtc->dp, IPUV3_COLORSPACE_RGB, IPUV3_COLORSPACE_RGB); if (ret) { dev_err(ipu_crtc->dev, "initializing display processor failed with %d\n", ret); return ret; } ipu_dp_set_global_alpha(ipu_crtc->dp, 1, 0, 1); } ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, sig_cfg.interlaced, out_pixel_fmt, mode->hdisplay); if (ret) { dev_err(ipu_crtc->dev, "initializing display controller failed with %d\n", ret); return ret; } ret = ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg); if (ret) { dev_err(ipu_crtc->dev, "initializing panel failed with %d\n", ret); return ret; } ipu_cpmem_set_resolution(cpmem, mode->hdisplay, mode->vdisplay); ipu_cpmem_set_fmt(cpmem, v4l2_fmt); ipu_cpmem_set_high_priority(ipu_crtc->ipu_ch); ret = ipu_dmfc_init_channel(ipu_crtc->dmfc, mode->hdisplay); if (ret) { dev_err(ipu_crtc->dev, "initializing dmfc channel failed with %d\n", ret); return ret; } ret = ipu_dmfc_alloc_bandwidth(ipu_crtc->dmfc, calc_bandwidth(mode, calc_vref(mode)), 64); if (ret) { dev_err(ipu_crtc->dev, "allocating dmfc bandwidth failed with %d\n", ret); return ret; } ipu_drm_set_base(crtc, x, y); return 0; }