Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d51f6c0 authored by james qian wang (Arm Technology China)'s avatar james qian wang (Arm Technology China) Committed by Liviu Dudau
Browse files

drm/komeda: Add writeback support

Komeda driver uses a individual component to describe the HW's writeback
caps, but drivers doesn't define a new structure and still uses the
existing "struct komeda_layer" to describe this new component.
The detailed changes as follow:

1. Initialize wb_layer according to HW and report it to CORE.
2. CORE exposes wb_layer as a resource to KMS by private_obj.
3. Report writeback supporting by add a wb_connector to KMS, and then
   wb_connector will take act as a component resources user,
   so the func komeda_wb_encoder_atomic_check claims komeda resources
   (scaler and wb_layer) accroding to its state configuration to the
   wb_connector. and the wb_state configuration will be validated on the
   specific component resources to see if the caps of component can
   meet the requirement of wb_connector. if not check failed.
4. Update irq_handler to notify the completion of writeback.

NOTE:
This change doesn't add scaling writeback support, that support will
be added in the future after the scaler support.

v2: Rebase
v3: Rebase and constify the d71_wb_layer_funcs
v4: Addressed Ayan's comments

Depends on:
- https://patchwork.freedesktop.org/series/59915/



Signed-off-by: default avatarJames Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
Acked-by: default avatarAyan Kumar Halder <ayan.halder@arm.com>
Signed-off-by: default avatarLiviu Dudau <liviu.dudau@arm.com>
parent 52d2d44e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ komeda-y := \
	komeda_kms.o \
	komeda_crtc.o \
	komeda_plane.o \
	komeda_wb_connector.o \
	komeda_private_obj.o

komeda-y += \
+89 −1
Original line number Diff line number Diff line
@@ -288,10 +288,98 @@ static int d71_layer_init(struct d71_dev *d71,
	return 0;
}

static void d71_wb_layer_update(struct komeda_component *c,
				struct komeda_component_state *state)
{
	struct komeda_layer_state *st = to_layer_st(state);
	struct drm_connector_state *conn_st = state->wb_conn->state;
	struct drm_framebuffer *fb = conn_st->writeback_job->fb;
	struct komeda_fb *kfb = to_kfb(fb);
	u32 __iomem *reg = c->reg;
	u32 ctrl = L_EN | LW_OFM, mask = L_EN | LW_OFM | LW_TBU_EN;
	int i;

	for (i = 0; i < fb->format->num_planes; i++) {
		malidp_write32(reg + i * LAYER_PER_PLANE_REGS, BLK_P0_PTR_LOW,
			       lower_32_bits(st->addr[i]));
		malidp_write32(reg + i * LAYER_PER_PLANE_REGS, BLK_P0_PTR_HIGH,
			       upper_32_bits(st->addr[i]));

		malidp_write32(reg + i * LAYER_PER_PLANE_REGS, BLK_P0_STRIDE,
			       fb->pitches[i] & 0xFFFF);
	}

	malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
	malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
	malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(&state->inputs[0]));
	malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl);
}

static void d71_wb_layer_dump(struct komeda_component *c, struct seq_file *sf)
{
	u32 v[12], i;

	dump_block_header(sf, c->reg);

	get_values_from_reg(c->reg, 0x80, 1, v);
	seq_printf(sf, "LW_INPUT_ID0:\t\t0x%X\n", v[0]);

	get_values_from_reg(c->reg, 0xD0, 3, v);
	seq_printf(sf, "LW_CONTROL:\t\t0x%X\n", v[0]);
	seq_printf(sf, "LW_PROG_LINE:\t\t0x%X\n", v[1]);
	seq_printf(sf, "LW_FORMAT:\t\t0x%X\n", v[2]);

	get_values_from_reg(c->reg, 0xE0, 1, v);
	seq_printf(sf, "LW_IN_SIZE:\t\t0x%X\n", v[0]);

	for (i = 0; i < 2; i++) {
		get_values_from_reg(c->reg, 0x100 + i * 0x10, 3, v);
		seq_printf(sf, "LW_P%u_PTR_LOW:\t\t0x%X\n", i, v[0]);
		seq_printf(sf, "LW_P%u_PTR_HIGH:\t\t0x%X\n", i, v[1]);
		seq_printf(sf, "LW_P%u_STRIDE:\t\t0x%X\n", i, v[2]);
	}

	get_values_from_reg(c->reg, 0x130, 12, v);
	for (i = 0; i < 12; i++)
		seq_printf(sf, "LW_RGB_YUV_COEFF%u:\t0x%X\n", i, v[i]);
}

static void d71_wb_layer_disable(struct komeda_component *c)
{
	malidp_write32(c->reg, BLK_INPUT_ID0, 0);
	malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);
}

static const struct komeda_component_funcs d71_wb_layer_funcs = {
	.update		= d71_wb_layer_update,
	.disable	= d71_wb_layer_disable,
	.dump_register	= d71_wb_layer_dump,
};

static int d71_wb_layer_init(struct d71_dev *d71,
			     struct block_header *blk, u32 __iomem *reg)
{
	DRM_DEBUG("Detect D71_Wb_Layer.\n");
	struct komeda_component *c;
	struct komeda_layer *wb_layer;
	u32 pipe_id, layer_id;

	get_resources_id(blk->block_info, &pipe_id, &layer_id);

	c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*wb_layer),
				 layer_id, BLOCK_INFO_INPUT_ID(blk->block_info),
				 &d71_wb_layer_funcs,
				 1, get_valid_inputs(blk), 0, reg,
				 "LPU%d_LAYER_WR", pipe_id);
	if (IS_ERR(c)) {
		DRM_ERROR("Failed to add wb_layer component\n");
		return PTR_ERR(c);
	}

	wb_layer = to_layer(c);
	wb_layer->layer_type = KOMEDA_FMT_WB_LAYER;

	set_range(&wb_layer->hsize_in, D71_MIN_LINE_SIZE, d71->max_line_size);
	set_range(&wb_layer->vsize_in, D71_MIN_VERTICAL_SIZE, d71->max_vsize);

	return 0;
}
+15 −0
Original line number Diff line number Diff line
@@ -165,6 +165,15 @@ void komeda_crtc_handle_event(struct komeda_crtc *kcrtc,
	if (events & KOMEDA_EVENT_VSYNC)
		drm_crtc_handle_vblank(crtc);

	if (events & KOMEDA_EVENT_EOW) {
		struct komeda_wb_connector *wb_conn = kcrtc->wb_conn;

		if (wb_conn)
			drm_writeback_signal_completion(&wb_conn->base, 0);
		else
			DRM_WARN("CRTC[%d]: EOW happen but no wb_connector.\n",
				 drm_crtc_index(&kcrtc->base));
	}
	/* will handle it together with the write back support */
	if (events & KOMEDA_EVENT_EOW)
		DRM_DEBUG("EOW.\n");
@@ -201,6 +210,8 @@ komeda_crtc_do_flush(struct drm_crtc *crtc,
	struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(crtc->state);
	struct komeda_dev *mdev = kcrtc->base.dev->dev_private;
	struct komeda_pipeline *master = kcrtc->master;
	struct komeda_wb_connector *wb_conn = kcrtc->wb_conn;
	struct drm_connector_state *conn_st;

	DRM_DEBUG_ATOMIC("CRTC%d_FLUSH: active_pipes: 0x%x, affected: 0x%x.\n",
			 drm_crtc_index(crtc),
@@ -210,6 +221,10 @@ komeda_crtc_do_flush(struct drm_crtc *crtc,
	if (has_bit(master->id, kcrtc_st->affected_pipes))
		komeda_pipeline_update(master, old->state);

	conn_st = wb_conn ? wb_conn->base.base.state : NULL;
	if (conn_st && conn_st->writeback_job)
		drm_writeback_queue_job(&wb_conn->base, conn_st);

	/* step 2: notify the HW to kickoff the update */
	mdev->funcs->flush(mdev, master->id, kcrtc_st->active_pipes);
}
+19 −0
Original line number Diff line number Diff line
@@ -165,3 +165,22 @@ komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane)

	return obj->paddr + offset;
}

/* if the fb can be supported by a specific layer */
bool komeda_fb_is_layer_supported(struct komeda_fb *kfb, u32 layer_type)
{
	struct drm_framebuffer *fb = &kfb->base;
	struct komeda_dev *mdev = fb->dev->dev_private;
	const struct komeda_format_caps *caps;
	u32 fourcc = fb->format->format;
	u64 modifier = fb->modifier;

	caps = komeda_get_format_caps(&mdev->fmt_tbl, fourcc, modifier);
	if (!caps)
		return false;

	if (!(caps->supported_layer_types & layer_type))
		return false;

	return true;
}
+4 −0
Original line number Diff line number Diff line
@@ -188,6 +188,10 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
	if (err)
		goto cleanup_mode_config;

	err = komeda_kms_add_wb_connectors(kms, mdev);
	if (err)
		goto cleanup_mode_config;

	err = component_bind_all(mdev->dev, kms);
	if (err)
		goto cleanup_mode_config;
Loading