brintos

brintos / linux-shallow public Read only

0
0
Text · 18.4 KiB · 2ad3355 Raw
685 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.4 * Author: James.Qian.Wang <james.qian.wang@arm.com>5 *6 */7#include <linux/clk.h>8#include <linux/of.h>9#include <linux/pm_runtime.h>10#include <linux/spinlock.h>11 12#include <drm/drm_atomic.h>13#include <drm/drm_atomic_helper.h>14#include <drm/drm_print.h>15#include <drm/drm_vblank.h>16#include <drm/drm_simple_kms_helper.h>17#include <drm/drm_bridge.h>18 19#include "komeda_dev.h"20#include "komeda_kms.h"21 22void komeda_crtc_get_color_config(struct drm_crtc_state *crtc_st,23				  u32 *color_depths, u32 *color_formats)24{25	struct drm_connector *conn;26	struct drm_connector_state *conn_st;27	u32 conn_color_formats = ~0u;28	int i, min_bpc = 31, conn_bpc = 0;29 30	for_each_new_connector_in_state(crtc_st->state, conn, conn_st, i) {31		if (conn_st->crtc != crtc_st->crtc)32			continue;33 34		conn_bpc = conn->display_info.bpc ? conn->display_info.bpc : 8;35		conn_color_formats &= conn->display_info.color_formats;36 37		if (conn_bpc < min_bpc)38			min_bpc = conn_bpc;39	}40 41	/* connector doesn't config any color_format, use RGB444 as default */42	if (!conn_color_formats)43		conn_color_formats = DRM_COLOR_FORMAT_RGB444;44 45	*color_depths = GENMASK(min_bpc, 0);46	*color_formats = conn_color_formats;47}48 49static void komeda_crtc_update_clock_ratio(struct komeda_crtc_state *kcrtc_st)50{51	u64 pxlclk, aclk;52 53	if (!kcrtc_st->base.active) {54		kcrtc_st->clock_ratio = 0;55		return;56	}57 58	pxlclk = kcrtc_st->base.adjusted_mode.crtc_clock * 1000ULL;59	aclk = komeda_crtc_get_aclk(kcrtc_st);60 61	kcrtc_st->clock_ratio = div64_u64(aclk << 32, pxlclk);62}63 64/**65 * komeda_crtc_atomic_check - build display output data flow66 * @crtc: DRM crtc67 * @state: the crtc state object68 *69 * crtc_atomic_check is the final check stage, so beside build a display data70 * pipeline according to the crtc_state, but still needs to release or disable71 * the unclaimed pipeline resources.72 *73 * RETURNS:74 * Zero for success or -errno75 */76static int77komeda_crtc_atomic_check(struct drm_crtc *crtc,78			 struct drm_atomic_state *state)79{80	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,81									  crtc);82	struct komeda_crtc *kcrtc = to_kcrtc(crtc);83	struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(crtc_state);84	int err;85 86	if (drm_atomic_crtc_needs_modeset(crtc_state))87		komeda_crtc_update_clock_ratio(kcrtc_st);88 89	if (crtc_state->active) {90		err = komeda_build_display_data_flow(kcrtc, kcrtc_st);91		if (err)92			return err;93	}94 95	/* release unclaimed pipeline resources */96	err = komeda_release_unclaimed_resources(kcrtc->slave, kcrtc_st);97	if (err)98		return err;99 100	err = komeda_release_unclaimed_resources(kcrtc->master, kcrtc_st);101	if (err)102		return err;103 104	return 0;105}106 107/* For active a crtc, mainly need two parts of preparation108 * 1. adjust display operation mode.109 * 2. enable needed clk110 */111static int112komeda_crtc_prepare(struct komeda_crtc *kcrtc)113{114	struct komeda_dev *mdev = kcrtc->base.dev->dev_private;115	struct komeda_pipeline *master = kcrtc->master;116	struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(kcrtc->base.state);117	struct drm_display_mode *mode = &kcrtc_st->base.adjusted_mode;118	u32 new_mode;119	int err;120 121	mutex_lock(&mdev->lock);122 123	new_mode = mdev->dpmode | BIT(master->id);124	if (WARN_ON(new_mode == mdev->dpmode)) {125		err = 0;126		goto unlock;127	}128 129	err = mdev->funcs->change_opmode(mdev, new_mode);130	if (err) {131		DRM_ERROR("failed to change opmode: 0x%x -> 0x%x.\n,",132			  mdev->dpmode, new_mode);133		goto unlock;134	}135 136	mdev->dpmode = new_mode;137	/* Only need to enable aclk on single display mode, but no need to138	 * enable aclk it on dual display mode, since the dual mode always139	 * switch from single display mode, the aclk already enabled, no need140	 * to enable it again.141	 */142	if (new_mode != KOMEDA_MODE_DUAL_DISP) {143		err = clk_set_rate(mdev->aclk, komeda_crtc_get_aclk(kcrtc_st));144		if (err)145			DRM_ERROR("failed to set aclk.\n");146		err = clk_prepare_enable(mdev->aclk);147		if (err)148			DRM_ERROR("failed to enable aclk.\n");149	}150 151	err = clk_set_rate(master->pxlclk, mode->crtc_clock * 1000);152	if (err)153		DRM_ERROR("failed to set pxlclk for pipe%d\n", master->id);154	err = clk_prepare_enable(master->pxlclk);155	if (err)156		DRM_ERROR("failed to enable pxl clk for pipe%d.\n", master->id);157 158unlock:159	mutex_unlock(&mdev->lock);160 161	return err;162}163 164static int165komeda_crtc_unprepare(struct komeda_crtc *kcrtc)166{167	struct komeda_dev *mdev = kcrtc->base.dev->dev_private;168	struct komeda_pipeline *master = kcrtc->master;169	u32 new_mode;170	int err;171 172	mutex_lock(&mdev->lock);173 174	new_mode = mdev->dpmode & (~BIT(master->id));175 176	if (WARN_ON(new_mode == mdev->dpmode)) {177		err = 0;178		goto unlock;179	}180 181	err = mdev->funcs->change_opmode(mdev, new_mode);182	if (err) {183		DRM_ERROR("failed to change opmode: 0x%x -> 0x%x.\n,",184			  mdev->dpmode, new_mode);185		goto unlock;186	}187 188	mdev->dpmode = new_mode;189 190	clk_disable_unprepare(master->pxlclk);191	if (new_mode == KOMEDA_MODE_INACTIVE)192		clk_disable_unprepare(mdev->aclk);193 194unlock:195	mutex_unlock(&mdev->lock);196 197	return err;198}199 200void komeda_crtc_handle_event(struct komeda_crtc   *kcrtc,201			      struct komeda_events *evts)202{203	struct drm_crtc *crtc = &kcrtc->base;204	u32 events = evts->pipes[kcrtc->master->id];205 206	if (events & KOMEDA_EVENT_VSYNC)207		drm_crtc_handle_vblank(crtc);208 209	if (events & KOMEDA_EVENT_EOW) {210		struct komeda_wb_connector *wb_conn = kcrtc->wb_conn;211 212		if (wb_conn)213			drm_writeback_signal_completion(&wb_conn->base, 0);214		else215			DRM_WARN("CRTC[%d]: EOW happen but no wb_connector.\n",216				 drm_crtc_index(&kcrtc->base));217	}218	/* will handle it together with the write back support */219	if (events & KOMEDA_EVENT_EOW)220		DRM_DEBUG("EOW.\n");221 222	if (events & KOMEDA_EVENT_FLIP) {223		unsigned long flags;224		struct drm_pending_vblank_event *event;225 226		spin_lock_irqsave(&crtc->dev->event_lock, flags);227		if (kcrtc->disable_done) {228			complete_all(kcrtc->disable_done);229			kcrtc->disable_done = NULL;230		} else if (crtc->state->event) {231			event = crtc->state->event;232			/*233			 * Consume event before notifying drm core that flip234			 * happened.235			 */236			crtc->state->event = NULL;237			drm_crtc_send_vblank_event(crtc, event);238		} else {239			DRM_WARN("CRTC[%d]: FLIP happened but no pending commit.\n",240				 drm_crtc_index(&kcrtc->base));241		}242		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);243	}244}245 246static void247komeda_crtc_do_flush(struct drm_crtc *crtc,248		     struct drm_crtc_state *old)249{250	struct komeda_crtc *kcrtc = to_kcrtc(crtc);251	struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(crtc->state);252	struct komeda_dev *mdev = kcrtc->base.dev->dev_private;253	struct komeda_pipeline *master = kcrtc->master;254	struct komeda_pipeline *slave = kcrtc->slave;255	struct komeda_wb_connector *wb_conn = kcrtc->wb_conn;256	struct drm_connector_state *conn_st;257 258	DRM_DEBUG_ATOMIC("CRTC%d_FLUSH: active_pipes: 0x%x, affected: 0x%x.\n",259			 drm_crtc_index(crtc),260			 kcrtc_st->active_pipes, kcrtc_st->affected_pipes);261 262	/* step 1: update the pipeline/component state to HW */263	if (has_bit(master->id, kcrtc_st->affected_pipes))264		komeda_pipeline_update(master, old->state);265 266	if (slave && has_bit(slave->id, kcrtc_st->affected_pipes))267		komeda_pipeline_update(slave, old->state);268 269	conn_st = wb_conn ? wb_conn->base.base.state : NULL;270	if (conn_st && conn_st->writeback_job)271		drm_writeback_queue_job(&wb_conn->base, conn_st);272 273	/* step 2: notify the HW to kickoff the update */274	mdev->funcs->flush(mdev, master->id, kcrtc_st->active_pipes);275}276 277static void278komeda_crtc_atomic_enable(struct drm_crtc *crtc,279			  struct drm_atomic_state *state)280{281	struct drm_crtc_state *old = drm_atomic_get_old_crtc_state(state,282								   crtc);283	pm_runtime_get_sync(crtc->dev->dev);284	komeda_crtc_prepare(to_kcrtc(crtc));285	drm_crtc_vblank_on(crtc);286	WARN_ON(drm_crtc_vblank_get(crtc));287	komeda_crtc_do_flush(crtc, old);288}289 290void291komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,292					 struct completion *input_flip_done)293{294	struct drm_device *drm = kcrtc->base.dev;295	struct komeda_dev *mdev = kcrtc->master->mdev;296	struct completion *flip_done;297	struct completion temp;298 299	/* if caller doesn't send a flip_done, use a private flip_done */300	if (input_flip_done) {301		flip_done = input_flip_done;302	} else {303		init_completion(&temp);304		kcrtc->disable_done = &temp;305		flip_done = &temp;306	}307 308	mdev->funcs->flush(mdev, kcrtc->master->id, 0);309 310	/* wait the flip take affect.*/311	if (wait_for_completion_timeout(flip_done, HZ) == 0) {312		DRM_ERROR("wait pipe%d flip done timeout\n", kcrtc->master->id);313		if (!input_flip_done) {314			unsigned long flags;315 316			spin_lock_irqsave(&drm->event_lock, flags);317			kcrtc->disable_done = NULL;318			spin_unlock_irqrestore(&drm->event_lock, flags);319		}320	}321}322 323static void324komeda_crtc_atomic_disable(struct drm_crtc *crtc,325			   struct drm_atomic_state *state)326{327	struct drm_crtc_state *old = drm_atomic_get_old_crtc_state(state,328								   crtc);329	struct komeda_crtc *kcrtc = to_kcrtc(crtc);330	struct komeda_crtc_state *old_st = to_kcrtc_st(old);331	struct komeda_pipeline *master = kcrtc->master;332	struct komeda_pipeline *slave  = kcrtc->slave;333	struct completion *disable_done;334	bool needs_phase2 = false;335 336	DRM_DEBUG_ATOMIC("CRTC%d_DISABLE: active_pipes: 0x%x, affected: 0x%x\n",337			 drm_crtc_index(crtc),338			 old_st->active_pipes, old_st->affected_pipes);339 340	if (slave && has_bit(slave->id, old_st->active_pipes))341		komeda_pipeline_disable(slave, old->state);342 343	if (has_bit(master->id, old_st->active_pipes))344		needs_phase2 = komeda_pipeline_disable(master, old->state);345 346	/* crtc_disable has two scenarios according to the state->active switch.347	 * 1. active -> inactive348	 *    this commit is a disable commit. and the commit will be finished349	 *    or done after the disable operation. on this case we can directly350	 *    use the crtc->state->event to tracking the HW disable operation.351	 * 2. active -> active352	 *    the crtc->commit is not for disable, but a modeset operation when353	 *    crtc is active, such commit actually has been completed by 3354	 *    DRM operations:355	 *    crtc_disable, update_planes(crtc_flush), crtc_enable356	 *    so on this case the crtc->commit is for the whole process.357	 *    we can not use it for tracing the disable, we need a temporary358	 *    flip_done for tracing the disable. and crtc->state->event for359	 *    the crtc_enable operation.360	 *    That's also the reason why skip modeset commit in361	 *    komeda_crtc_atomic_flush()362	 */363	disable_done = (needs_phase2 || crtc->state->active) ?364		       NULL : &crtc->state->commit->flip_done;365 366	/* wait phase 1 disable done */367	komeda_crtc_flush_and_wait_for_flip_done(kcrtc, disable_done);368 369	/* phase 2 */370	if (needs_phase2) {371		komeda_pipeline_disable(kcrtc->master, old->state);372 373		disable_done = crtc->state->active ?374			       NULL : &crtc->state->commit->flip_done;375 376		komeda_crtc_flush_and_wait_for_flip_done(kcrtc, disable_done);377	}378 379	drm_crtc_vblank_put(crtc);380	drm_crtc_vblank_off(crtc);381	komeda_crtc_unprepare(kcrtc);382	pm_runtime_put(crtc->dev->dev);383}384 385static void386komeda_crtc_atomic_flush(struct drm_crtc *crtc,387			 struct drm_atomic_state *state)388{389	struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,390									  crtc);391	struct drm_crtc_state *old = drm_atomic_get_old_crtc_state(state,392								   crtc);393	/* commit with modeset will be handled in enable/disable */394	if (drm_atomic_crtc_needs_modeset(crtc_state))395		return;396 397	komeda_crtc_do_flush(crtc, old);398}399 400/* Returns the minimum frequency of the aclk rate (main engine clock) in Hz */401static unsigned long402komeda_calc_min_aclk_rate(struct komeda_crtc *kcrtc,403			  unsigned long pxlclk)404{405	/* Once dual-link one display pipeline drives two display outputs,406	 * the aclk needs run on the double rate of pxlclk407	 */408	if (kcrtc->master->dual_link)409		return pxlclk * 2;410	else411		return pxlclk;412}413 414/* Get current aclk rate that specified by state */415unsigned long komeda_crtc_get_aclk(struct komeda_crtc_state *kcrtc_st)416{417	struct drm_crtc *crtc = kcrtc_st->base.crtc;418	struct komeda_dev *mdev = crtc->dev->dev_private;419	unsigned long pxlclk = kcrtc_st->base.adjusted_mode.crtc_clock * 1000;420	unsigned long min_aclk;421 422	min_aclk = komeda_calc_min_aclk_rate(to_kcrtc(crtc), pxlclk);423 424	return clk_round_rate(mdev->aclk, min_aclk);425}426 427static enum drm_mode_status428komeda_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *m)429{430	struct komeda_dev *mdev = crtc->dev->dev_private;431	struct komeda_crtc *kcrtc = to_kcrtc(crtc);432	struct komeda_pipeline *master = kcrtc->master;433	unsigned long min_pxlclk, min_aclk;434 435	if (m->flags & DRM_MODE_FLAG_INTERLACE)436		return MODE_NO_INTERLACE;437 438	min_pxlclk = m->clock * 1000;439	if (master->dual_link)440		min_pxlclk /= 2;441 442	if (min_pxlclk != clk_round_rate(master->pxlclk, min_pxlclk)) {443		DRM_DEBUG_ATOMIC("pxlclk doesn't support %lu Hz\n", min_pxlclk);444 445		return MODE_NOCLOCK;446	}447 448	min_aclk = komeda_calc_min_aclk_rate(to_kcrtc(crtc), min_pxlclk);449	if (clk_round_rate(mdev->aclk, min_aclk) < min_aclk) {450		DRM_DEBUG_ATOMIC("engine clk can't satisfy the requirement of %s-clk: %lu.\n",451				 m->name, min_pxlclk);452 453		return MODE_CLOCK_HIGH;454	}455 456	return MODE_OK;457}458 459static bool komeda_crtc_mode_fixup(struct drm_crtc *crtc,460				   const struct drm_display_mode *m,461				   struct drm_display_mode *adjusted_mode)462{463	struct komeda_crtc *kcrtc = to_kcrtc(crtc);464	unsigned long clk_rate;465 466	drm_mode_set_crtcinfo(adjusted_mode, 0);467	/* In dual link half the horizontal settings */468	if (kcrtc->master->dual_link) {469		adjusted_mode->crtc_clock /= 2;470		adjusted_mode->crtc_hdisplay /= 2;471		adjusted_mode->crtc_hsync_start /= 2;472		adjusted_mode->crtc_hsync_end /= 2;473		adjusted_mode->crtc_htotal /= 2;474	}475 476	clk_rate = adjusted_mode->crtc_clock * 1000;477	/* crtc_clock will be used as the komeda output pixel clock */478	adjusted_mode->crtc_clock = clk_round_rate(kcrtc->master->pxlclk,479						   clk_rate) / 1000;480 481	return true;482}483 484static const struct drm_crtc_helper_funcs komeda_crtc_helper_funcs = {485	.atomic_check	= komeda_crtc_atomic_check,486	.atomic_flush	= komeda_crtc_atomic_flush,487	.atomic_enable	= komeda_crtc_atomic_enable,488	.atomic_disable	= komeda_crtc_atomic_disable,489	.mode_valid	= komeda_crtc_mode_valid,490	.mode_fixup	= komeda_crtc_mode_fixup,491};492 493static void komeda_crtc_reset(struct drm_crtc *crtc)494{495	struct komeda_crtc_state *state;496 497	if (crtc->state)498		__drm_atomic_helper_crtc_destroy_state(crtc->state);499 500	kfree(to_kcrtc_st(crtc->state));501	crtc->state = NULL;502 503	state = kzalloc(sizeof(*state), GFP_KERNEL);504	if (state)505		__drm_atomic_helper_crtc_reset(crtc, &state->base);506}507 508static struct drm_crtc_state *509komeda_crtc_atomic_duplicate_state(struct drm_crtc *crtc)510{511	struct komeda_crtc_state *old = to_kcrtc_st(crtc->state);512	struct komeda_crtc_state *new;513 514	new = kzalloc(sizeof(*new), GFP_KERNEL);515	if (!new)516		return NULL;517 518	__drm_atomic_helper_crtc_duplicate_state(crtc, &new->base);519 520	new->affected_pipes = old->active_pipes;521	new->clock_ratio = old->clock_ratio;522	new->max_slave_zorder = old->max_slave_zorder;523 524	return &new->base;525}526 527static void komeda_crtc_atomic_destroy_state(struct drm_crtc *crtc,528					     struct drm_crtc_state *state)529{530	__drm_atomic_helper_crtc_destroy_state(state);531	kfree(to_kcrtc_st(state));532}533 534static int komeda_crtc_vblank_enable(struct drm_crtc *crtc)535{536	struct komeda_dev *mdev = crtc->dev->dev_private;537	struct komeda_crtc *kcrtc = to_kcrtc(crtc);538 539	mdev->funcs->on_off_vblank(mdev, kcrtc->master->id, true);540	return 0;541}542 543static void komeda_crtc_vblank_disable(struct drm_crtc *crtc)544{545	struct komeda_dev *mdev = crtc->dev->dev_private;546	struct komeda_crtc *kcrtc = to_kcrtc(crtc);547 548	mdev->funcs->on_off_vblank(mdev, kcrtc->master->id, false);549}550 551static const struct drm_crtc_funcs komeda_crtc_funcs = {552	.destroy		= drm_crtc_cleanup,553	.set_config		= drm_atomic_helper_set_config,554	.page_flip		= drm_atomic_helper_page_flip,555	.reset			= komeda_crtc_reset,556	.atomic_duplicate_state	= komeda_crtc_atomic_duplicate_state,557	.atomic_destroy_state	= komeda_crtc_atomic_destroy_state,558	.enable_vblank		= komeda_crtc_vblank_enable,559	.disable_vblank		= komeda_crtc_vblank_disable,560};561 562int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms,563			   struct komeda_dev *mdev)564{565	struct komeda_crtc *crtc;566	struct komeda_pipeline *master;567	char str[16];568	int i;569 570	kms->n_crtcs = 0;571 572	for (i = 0; i < mdev->n_pipelines; i++) {573		crtc = &kms->crtcs[kms->n_crtcs];574		master = mdev->pipelines[i];575 576		crtc->master = master;577		crtc->slave  = komeda_pipeline_get_slave(master);578 579		if (crtc->slave)580			sprintf(str, "pipe-%d", crtc->slave->id);581		else582			sprintf(str, "None");583 584		DRM_INFO("CRTC-%d: master(pipe-%d) slave(%s).\n",585			 kms->n_crtcs, master->id, str);586 587		kms->n_crtcs++;588	}589 590	return 0;591}592 593static struct drm_plane *594get_crtc_primary(struct komeda_kms_dev *kms, struct komeda_crtc *crtc)595{596	struct komeda_plane *kplane;597	struct drm_plane *plane;598 599	drm_for_each_plane(plane, &kms->base) {600		if (plane->type != DRM_PLANE_TYPE_PRIMARY)601			continue;602 603		kplane = to_kplane(plane);604		/* only master can be primary */605		if (kplane->layer->base.pipeline == crtc->master)606			return plane;607	}608 609	return NULL;610}611 612static int komeda_attach_bridge(struct device *dev,613				struct komeda_pipeline *pipe,614				struct drm_encoder *encoder)615{616	struct drm_bridge *bridge;617	int err;618 619	bridge = devm_drm_of_get_bridge(dev, pipe->of_node,620					KOMEDA_OF_PORT_OUTPUT, 0);621	if (IS_ERR(bridge))622		return dev_err_probe(dev, PTR_ERR(bridge), "remote bridge not found for pipe: %s\n",623				     of_node_full_name(pipe->of_node));624 625	err = drm_bridge_attach(encoder, bridge, NULL, 0);626	if (err)627		dev_err(dev, "bridge_attach() failed for pipe: %s\n",628			of_node_full_name(pipe->of_node));629 630	return err;631}632 633static int komeda_crtc_add(struct komeda_kms_dev *kms,634			   struct komeda_crtc *kcrtc)635{636	struct drm_crtc *crtc = &kcrtc->base;637	struct drm_device *base = &kms->base;638	struct komeda_pipeline *pipe = kcrtc->master;639	struct drm_encoder *encoder = &kcrtc->encoder;640	int err;641 642	err = drm_crtc_init_with_planes(base, crtc,643					get_crtc_primary(kms, kcrtc), NULL,644					&komeda_crtc_funcs, NULL);645	if (err)646		return err;647 648	drm_crtc_helper_add(crtc, &komeda_crtc_helper_funcs);649 650	crtc->port = pipe->of_output_port;651 652	/* Construct an encoder for each pipeline and attach it to the remote653	 * bridge654	 */655	kcrtc->encoder.possible_crtcs = drm_crtc_mask(crtc);656	err = drm_simple_encoder_init(base, encoder, DRM_MODE_ENCODER_TMDS);657	if (err)658		return err;659 660	if (pipe->of_output_links[0]) {661		err = komeda_attach_bridge(base->dev, pipe, encoder);662		if (err)663			return err;664	}665 666	drm_crtc_enable_color_mgmt(crtc, 0, true, KOMEDA_COLOR_LUT_SIZE);667 668	komeda_pipeline_dump(pipe);669 670	return 0;671}672 673int komeda_kms_add_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev)674{675	int i, err;676 677	for (i = 0; i < kms->n_crtcs; i++) {678		err = komeda_crtc_add(kms, &kms->crtcs[i]);679		if (err)680			return err;681	}682 683	return 0;684}685