static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb, u32 ch, u32 y, u32 in_h, u32 fmt) { struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0); struct drm_format_name_buf format_name; u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en; u32 stride = fb->pitches[0]; u32 addr = (u32)obj->paddr + y * stride; DRM_DEBUG_DRIVER("rdma%d: (y=%d, height=%d), stride=%d, paddr=0x%x\n", ch + 1, y, in_h, stride, (u32)obj->paddr); DRM_DEBUG_DRIVER("addr=0x%x, fb:%dx%d, pixel_format=%d(%s)\n", addr, fb->width, fb->height, fmt, drm_get_format_name(fb->pixel_format, &format_name)); /* get reg offset */ reg_ctrl = RD_CH_CTRL(ch); reg_addr = RD_CH_ADDR(ch); reg_size = RD_CH_SIZE(ch); reg_stride = RD_CH_STRIDE(ch); reg_space = RD_CH_SPACE(ch); reg_en = RD_CH_EN(ch); /* * TODO: set rotation */ writel((fmt << 16) & 0x1f0000, base + reg_ctrl); writel(addr, base + reg_addr); writel((in_h << 16) | stride, base + reg_size); writel(stride, base + reg_stride); writel(in_h * stride, base + reg_space); writel(ADE_ENABLE, base + reg_en); ade_update_reload_bit(base, RDMA_OFST + ch, 0); }
/** * drm_atomic_plane_check - check plane state * @plane: plane to check * @state: plane state to check * * Provides core sanity checks for plane state. * * RETURNS: * Zero on success, error code on failure */ static int drm_atomic_plane_check(struct drm_plane *plane, struct drm_plane_state *state) { unsigned int fb_width, fb_height; int ret; /* either *both* CRTC and FB must be set, or neither */ if (WARN_ON(state->crtc && !state->fb)) { DRM_DEBUG_ATOMIC("CRTC set but no FB\n"); return -EINVAL; } else if (WARN_ON(state->fb && !state->crtc)) { DRM_DEBUG_ATOMIC("FB set but no CRTC\n"); return -EINVAL; } /* if disabled, we don't care about the rest of the state: */ if (!state->crtc) return 0; /* Check whether this plane is usable on this CRTC */ if (!(plane->possible_crtcs & drm_crtc_mask(state->crtc))) { DRM_DEBUG_ATOMIC("Invalid crtc for plane\n"); return -EINVAL; } /* Check whether this plane supports the fb pixel format. */ ret = drm_plane_check_pixel_format(plane, state->fb->pixel_format); if (ret) { DRM_DEBUG_ATOMIC("Invalid pixel format %s\n", drm_get_format_name(state->fb->pixel_format)); return ret; } /* Give drivers some help against integer overflows */ if (state->crtc_w > INT_MAX || state->crtc_x > INT_MAX - (int32_t) state->crtc_w || state->crtc_h > INT_MAX || state->crtc_y > INT_MAX - (int32_t) state->crtc_h) { DRM_DEBUG_ATOMIC("Invalid CRTC coordinates %ux%u+%d+%d\n", state->crtc_w, state->crtc_h, state->crtc_x, state->crtc_y); return -ERANGE; } fb_width = state->fb->width << 16; fb_height = state->fb->height << 16; /* Make sure source coordinates are inside the fb. */ if (state->src_w > fb_width || state->src_x > fb_width - state->src_w || state->src_h > fb_height || state->src_y > fb_height - state->src_h) { DRM_DEBUG_ATOMIC("Invalid source coordinates " "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", state->src_w >> 16, ((state->src_w & 0xffff) * 15625) >> 10, state->src_h >> 16, ((state->src_h & 0xffff) * 15625) >> 10, state->src_x >> 16, ((state->src_x & 0xffff) * 15625) >> 10, state->src_y >> 16, ((state->src_y & 0xffff) * 15625) >> 10); return -ENOSPC; }
static int tinydrm_fbdev_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct tinydrm_device *tdev = drm_to_tinydrm(helper->dev); int ret; ret = drm_fbdev_cma_create_with_funcs(helper, sizes, tdev->fb_funcs); if (ret) return ret; strncpy(helper->fbdev->fix.id, helper->dev->driver->name, 16); tdev->fbdev_helper = helper; if (fbdefio_delay) { unsigned long delay; delay = msecs_to_jiffies(fbdefio_delay); helper->fbdev->fbdefio->delay = delay ? delay : 1; } DRM_DEBUG_KMS("fbdev: [FB:%d] pixel_format=%s, fbdefio->delay=%ums\n", helper->fb->base.id, drm_get_format_name(helper->fb->pixel_format), jiffies_to_msecs(helper->fbdev->fbdefio->delay)); return 0; }
static int malidp_mw_encoder_atomic_check(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state) { struct malidp_mw_connector_state *mw_state = to_mw_state(conn_state); struct malidp_drm *malidp = encoder->dev->dev_private; struct drm_framebuffer *fb; int i, n_planes; if (!conn_state->writeback_job || !conn_state->writeback_job->fb) return 0; fb = conn_state->writeback_job->fb; if ((fb->width != crtc_state->mode.hdisplay) || (fb->height != crtc_state->mode.vdisplay)) { DRM_DEBUG_KMS("Invalid framebuffer size %ux%u\n", fb->width, fb->height); return -EINVAL; } if (fb->modifier) { DRM_DEBUG_KMS("Writeback framebuffer does not support modifiers\n"); return -EINVAL; } mw_state->format = malidp_hw_get_format_id(&malidp->dev->hw->map, SE_MEMWRITE, fb->format->format, !!fb->modifier); if (mw_state->format == MALIDP_INVALID_FORMAT_ID) { struct drm_format_name_buf format_name; DRM_DEBUG_KMS("Invalid pixel format %s\n", drm_get_format_name(fb->format->format, &format_name)); return -EINVAL; } n_planes = drm_format_num_planes(fb->format->format); for (i = 0; i < n_planes; i++) { struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, i); /* memory write buffers are never rotated */ u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 0); if (fb->pitches[i] & (alignment - 1)) { DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n", fb->pitches[i], i); return -EINVAL; } mw_state->pitches[i] = fb->pitches[i]; mw_state->addrs[i] = obj->paddr + fb->offsets[i]; } mw_state->n_planes = n_planes; if (fb->format->is_yuv) mw_state->rgb2yuv_coeffs = rgb2yuv_coeffs_bt709_limited; return 0; }
/** * tinydrm_fb_create - tinydrm .fb_create() helper * @drm: DRM device * @file_priv: DRM file info * @mode_cmd: metadata from the userspace fb creation request * * Helper for the &drm_mode_config_funcs->fb_create callback. * It sets up a &drm_framebuffer backed by the &drm_gem_cma_object buffer * object provided in @mode_cmd. */ struct drm_framebuffer * tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd) { struct tinydrm_device *tdev = drm_to_tinydrm(drm); struct drm_framebuffer *fb; fb = drm_fb_cma_create_with_funcs(drm, file_priv, mode_cmd, tdev->fb_funcs); if (!IS_ERR(fb)) DRM_DEBUG_KMS("[FB:%d] pixel_format: %s\n", fb->base.id, drm_get_format_name(fb->pixel_format)); return fb; }
static int __setplane_check(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int32_t crtc_x, int32_t crtc_y, uint32_t crtc_w, uint32_t crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { int ret; /* Check whether this plane is usable on this CRTC */ if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) { DRM_DEBUG_KMS("Invalid crtc for plane\n"); return -EINVAL; } /* Check whether this plane supports the fb pixel format. */ ret = drm_plane_check_pixel_format(plane, fb->format->format, fb->modifier); if (ret) { struct drm_format_name_buf format_name; DRM_DEBUG_KMS("Invalid pixel format %s, modifier 0x%llx\n", drm_get_format_name(fb->format->format, &format_name), fb->modifier); return ret; } /* Give drivers some help against integer overflows */ if (crtc_w > INT_MAX || crtc_x > INT_MAX - (int32_t) crtc_w || crtc_h > INT_MAX || crtc_y > INT_MAX - (int32_t) crtc_h) { DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", crtc_w, crtc_h, crtc_x, crtc_y); return -ERANGE; } ret = drm_framebuffer_check_src_coords(src_x, src_y, src_w, src_h, fb); if (ret) return ret; return 0; }
static int intel_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { struct drm_crtc *crtc = state->crtc; struct intel_crtc *intel_crtc; struct intel_crtc_state *crtc_state; struct intel_plane *intel_plane = to_intel_plane(plane); struct intel_plane_state *intel_state = to_intel_plane_state(state); struct drm_crtc_state *drm_crtc_state; int ret; crtc = crtc ? crtc : plane->state->crtc; intel_crtc = to_intel_crtc(crtc); /* * Both crtc and plane->crtc could be NULL if we're updating a * property while the plane is disabled. We don't actually have * anything driver-specific we need to test in that case, so * just return success. */ if (!crtc) return 0; drm_crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc); if (WARN_ON(!drm_crtc_state)) return -EINVAL; crtc_state = to_intel_crtc_state(drm_crtc_state); /* * The original src/dest coordinates are stored in state->base, but * we want to keep another copy internal to our driver that we can * clip/modify ourselves. */ intel_state->src.x1 = state->src_x; intel_state->src.y1 = state->src_y; intel_state->src.x2 = state->src_x + state->src_w; intel_state->src.y2 = state->src_y + state->src_h; intel_state->dst.x1 = state->crtc_x; intel_state->dst.y1 = state->crtc_y; intel_state->dst.x2 = state->crtc_x + state->crtc_w; intel_state->dst.y2 = state->crtc_y + state->crtc_h; /* Clip all planes to CRTC size, or 0x0 if CRTC is disabled */ intel_state->clip.x1 = 0; intel_state->clip.y1 = 0; intel_state->clip.x2 = crtc_state->base.enable ? crtc_state->pipe_src_w : 0; intel_state->clip.y2 = crtc_state->base.enable ? crtc_state->pipe_src_h : 0; if (state->fb && intel_rotation_90_or_270(state->rotation)) { if (!(state->fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || state->fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) { DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n"); return -EINVAL; } /* * 90/270 is not allowed with RGB64 16:16:16:16, * RGB 16-bit 5:6:5, and Indexed 8-bit. * TBD: Add RGB64 case once its added in supported format list. */ switch (state->fb->pixel_format) { case DRM_FORMAT_C8: case DRM_FORMAT_RGB565: DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", drm_get_format_name(state->fb->pixel_format)); return -EINVAL; default: break; } } intel_state->visible = false; ret = intel_plane->check_plane(plane, crtc_state, intel_state); if (ret) return ret; return intel_plane_atomic_calc_changes(&crtc_state->base, state); }
/** * drm_atomic_plane_check - check plane state * @old_plane_state: old plane state to check * @new_plane_state: new plane state to check * * Provides core sanity checks for plane state. * * RETURNS: * Zero on success, error code on failure */ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state, const struct drm_plane_state *new_plane_state) { struct drm_plane *plane = new_plane_state->plane; struct drm_crtc *crtc = new_plane_state->crtc; const struct drm_framebuffer *fb = new_plane_state->fb; unsigned int fb_width, fb_height; struct drm_mode_rect *clips; uint32_t num_clips; int ret; /* either *both* CRTC and FB must be set, or neither */ if (crtc && !fb) { DRM_DEBUG_ATOMIC("[PLANE:%d:%s] CRTC set but no FB\n", plane->base.id, plane->name); return -EINVAL; } else if (fb && !crtc) { DRM_DEBUG_ATOMIC("[PLANE:%d:%s] FB set but no CRTC\n", plane->base.id, plane->name); return -EINVAL; } /* if disabled, we don't care about the rest of the state: */ if (!crtc) return 0; /* Check whether this plane is usable on this CRTC */ if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) { DRM_DEBUG_ATOMIC("Invalid [CRTC:%d:%s] for [PLANE:%d:%s]\n", crtc->base.id, crtc->name, plane->base.id, plane->name); return -EINVAL; } /* Check whether this plane supports the fb pixel format. */ ret = drm_plane_check_pixel_format(plane, fb->format->format, fb->modifier); if (ret) { struct drm_format_name_buf format_name; DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid pixel format %s, modifier 0x%llx\n", plane->base.id, plane->name, drm_get_format_name(fb->format->format, &format_name), fb->modifier); return ret; } /* Give drivers some help against integer overflows */ if (new_plane_state->crtc_w > INT_MAX || new_plane_state->crtc_x > INT_MAX - (int32_t) new_plane_state->crtc_w || new_plane_state->crtc_h > INT_MAX || new_plane_state->crtc_y > INT_MAX - (int32_t) new_plane_state->crtc_h) { DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid CRTC coordinates %ux%u+%d+%d\n", plane->base.id, plane->name, new_plane_state->crtc_w, new_plane_state->crtc_h, new_plane_state->crtc_x, new_plane_state->crtc_y); return -ERANGE; } fb_width = fb->width << 16; fb_height = fb->height << 16; /* Make sure source coordinates are inside the fb. */ if (new_plane_state->src_w > fb_width || new_plane_state->src_x > fb_width - new_plane_state->src_w || new_plane_state->src_h > fb_height || new_plane_state->src_y > fb_height - new_plane_state->src_h) { DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid source coordinates " "%u.%06ux%u.%06u+%u.%06u+%u.%06u (fb %ux%u)\n", plane->base.id, plane->name, new_plane_state->src_w >> 16, ((new_plane_state->src_w & 0xffff) * 15625) >> 10, new_plane_state->src_h >> 16, ((new_plane_state->src_h & 0xffff) * 15625) >> 10, new_plane_state->src_x >> 16, ((new_plane_state->src_x & 0xffff) * 15625) >> 10, new_plane_state->src_y >> 16, ((new_plane_state->src_y & 0xffff) * 15625) >> 10, fb->width, fb->height); return -ENOSPC; }
/** * drm_fb_get_bpp_depth - get the bpp/depth values for format * @format: pixel format (DRM_FORMAT_*) * @depth: storage for the depth value * @bpp: storage for the bpp value * * This only supports RGB formats here for compat with code that doesn't use * pixel formats directly yet. */ void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp) { char *format_name; switch (format) { case DRM_FORMAT_C8: case DRM_FORMAT_RGB332: case DRM_FORMAT_BGR233: *depth = 8; *bpp = 8; break; case DRM_FORMAT_XRGB1555: case DRM_FORMAT_XBGR1555: case DRM_FORMAT_RGBX5551: case DRM_FORMAT_BGRX5551: case DRM_FORMAT_ARGB1555: case DRM_FORMAT_ABGR1555: case DRM_FORMAT_RGBA5551: case DRM_FORMAT_BGRA5551: *depth = 15; *bpp = 16; break; case DRM_FORMAT_RGB565: case DRM_FORMAT_BGR565: *depth = 16; *bpp = 16; break; case DRM_FORMAT_RGB888: case DRM_FORMAT_BGR888: *depth = 24; *bpp = 24; break; case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XBGR8888: case DRM_FORMAT_RGBX8888: case DRM_FORMAT_BGRX8888: *depth = 24; *bpp = 32; break; case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_RGBX1010102: case DRM_FORMAT_BGRX1010102: case DRM_FORMAT_ARGB2101010: case DRM_FORMAT_ABGR2101010: case DRM_FORMAT_RGBA1010102: case DRM_FORMAT_BGRA1010102: *depth = 30; *bpp = 32; break; case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ABGR8888: case DRM_FORMAT_RGBA8888: case DRM_FORMAT_BGRA8888: *depth = 32; *bpp = 32; break; default: format_name = drm_get_format_name(format); DRM_DEBUG_KMS("unsupported pixel format %s\n", format_name); kfree(format_name); *depth = 0; *bpp = 0; break; } }