brintos

brintos / linux-shallow public Read only

0
0
Text · 19.7 KiB · 10febea Raw
814 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * RZ/G2L MIPI DSI Encoder Driver4 *5 * Copyright (C) 2022 Renesas Electronics Corporation6 */7#include <linux/clk.h>8#include <linux/delay.h>9#include <linux/io.h>10#include <linux/iopoll.h>11#include <linux/module.h>12#include <linux/of.h>13#include <linux/of_graph.h>14#include <linux/platform_device.h>15#include <linux/pm_runtime.h>16#include <linux/reset.h>17#include <linux/slab.h>18 19#include <drm/drm_atomic.h>20#include <drm/drm_atomic_helper.h>21#include <drm/drm_bridge.h>22#include <drm/drm_mipi_dsi.h>23#include <drm/drm_of.h>24#include <drm/drm_panel.h>25#include <drm/drm_probe_helper.h>26 27#include "rzg2l_mipi_dsi_regs.h"28 29struct rzg2l_mipi_dsi {30	struct device *dev;31	void __iomem *mmio;32 33	struct reset_control *rstc;34	struct reset_control *arstc;35	struct reset_control *prstc;36 37	struct mipi_dsi_host host;38	struct drm_bridge bridge;39	struct drm_bridge *next_bridge;40 41	struct clk *vclk;42 43	enum mipi_dsi_pixel_format format;44	unsigned int num_data_lanes;45	unsigned int lanes;46	unsigned long mode_flags;47};48 49static inline struct rzg2l_mipi_dsi *50bridge_to_rzg2l_mipi_dsi(struct drm_bridge *bridge)51{52	return container_of(bridge, struct rzg2l_mipi_dsi, bridge);53}54 55static inline struct rzg2l_mipi_dsi *56host_to_rzg2l_mipi_dsi(struct mipi_dsi_host *host)57{58	return container_of(host, struct rzg2l_mipi_dsi, host);59}60 61struct rzg2l_mipi_dsi_timings {62	unsigned long hsfreq_max;63	u32 t_init;64	u32 tclk_prepare;65	u32 ths_prepare;66	u32 tclk_zero;67	u32 tclk_pre;68	u32 tclk_post;69	u32 tclk_trail;70	u32 ths_zero;71	u32 ths_trail;72	u32 ths_exit;73	u32 tlpx;74};75 76static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = {77	{78		.hsfreq_max = 80000,79		.t_init = 79801,80		.tclk_prepare = 8,81		.ths_prepare = 13,82		.tclk_zero = 33,83		.tclk_pre = 24,84		.tclk_post = 94,85		.tclk_trail = 10,86		.ths_zero = 23,87		.ths_trail = 17,88		.ths_exit = 13,89		.tlpx = 6,90	},91	{92		.hsfreq_max = 125000,93		.t_init = 79801,94		.tclk_prepare = 8,95		.ths_prepare = 12,96		.tclk_zero = 33,97		.tclk_pre = 15,98		.tclk_post = 94,99		.tclk_trail = 10,100		.ths_zero = 23,101		.ths_trail = 17,102		.ths_exit = 13,103		.tlpx = 6,104	},105	{106		.hsfreq_max = 250000,107		.t_init = 79801,108		.tclk_prepare = 8,109		.ths_prepare = 12,110		.tclk_zero = 33,111		.tclk_pre = 13,112		.tclk_post = 94,113		.tclk_trail = 10,114		.ths_zero = 23,115		.ths_trail = 16,116		.ths_exit = 13,117		.tlpx = 6,118	},119	{120		.hsfreq_max = 360000,121		.t_init = 79801,122		.tclk_prepare = 8,123		.ths_prepare = 10,124		.tclk_zero = 33,125		.tclk_pre = 4,126		.tclk_post = 35,127		.tclk_trail = 7,128		.ths_zero = 16,129		.ths_trail = 9,130		.ths_exit = 13,131		.tlpx = 6,132	},133	{134		.hsfreq_max = 720000,135		.t_init = 79801,136		.tclk_prepare = 8,137		.ths_prepare = 9,138		.tclk_zero = 33,139		.tclk_pre = 4,140		.tclk_post = 35,141		.tclk_trail = 7,142		.ths_zero = 16,143		.ths_trail = 9,144		.ths_exit = 13,145		.tlpx = 6,146	},147	{148		.hsfreq_max = 1500000,149		.t_init = 79801,150		.tclk_prepare = 8,151		.ths_prepare = 9,152		.tclk_zero = 33,153		.tclk_pre = 4,154		.tclk_post = 35,155		.tclk_trail = 7,156		.ths_zero = 16,157		.ths_trail = 9,158		.ths_exit = 13,159		.tlpx = 6,160	},161};162 163static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)164{165	iowrite32(data, dsi->mmio + reg);166}167 168static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)169{170	iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg);171}172 173static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg)174{175	return ioread32(dsi->mmio + reg);176}177 178static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg)179{180	return ioread32(dsi->mmio + LINK_REG_OFFSET + reg);181}182 183/* -----------------------------------------------------------------------------184 * Hardware Setup185 */186 187static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi,188				    unsigned long hsfreq)189{190	const struct rzg2l_mipi_dsi_timings *dphy_timings;191	unsigned int i;192	u32 dphyctrl0;193	u32 dphytim0;194	u32 dphytim1;195	u32 dphytim2;196	u32 dphytim3;197	int ret;198 199	/* All DSI global operation timings are set with recommended setting */200	for (i = 0; i < ARRAY_SIZE(rzg2l_mipi_dsi_global_timings); ++i) {201		dphy_timings = &rzg2l_mipi_dsi_global_timings[i];202		if (hsfreq <= dphy_timings->hsfreq_max)203			break;204	}205 206	/* Initializing DPHY before accessing LINK */207	dphyctrl0 = DSIDPHYCTRL0_CAL_EN_HSRX_OFS | DSIDPHYCTRL0_CMN_MASTER_EN |208		    DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 | DSIDPHYCTRL0_EN_BGR;209 210	rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);211	usleep_range(20, 30);212 213	dphyctrl0 |= DSIDPHYCTRL0_EN_LDO1200;214	rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);215	usleep_range(10, 20);216 217	dphytim0 = DSIDPHYTIM0_TCLK_MISS(0) |218		   DSIDPHYTIM0_T_INIT(dphy_timings->t_init);219	dphytim1 = DSIDPHYTIM1_THS_PREPARE(dphy_timings->ths_prepare) |220		   DSIDPHYTIM1_TCLK_PREPARE(dphy_timings->tclk_prepare) |221		   DSIDPHYTIM1_THS_SETTLE(0) |222		   DSIDPHYTIM1_TCLK_SETTLE(0);223	dphytim2 = DSIDPHYTIM2_TCLK_TRAIL(dphy_timings->tclk_trail) |224		   DSIDPHYTIM2_TCLK_POST(dphy_timings->tclk_post) |225		   DSIDPHYTIM2_TCLK_PRE(dphy_timings->tclk_pre) |226		   DSIDPHYTIM2_TCLK_ZERO(dphy_timings->tclk_zero);227	dphytim3 = DSIDPHYTIM3_TLPX(dphy_timings->tlpx) |228		   DSIDPHYTIM3_THS_EXIT(dphy_timings->ths_exit) |229		   DSIDPHYTIM3_THS_TRAIL(dphy_timings->ths_trail) |230		   DSIDPHYTIM3_THS_ZERO(dphy_timings->ths_zero);231 232	rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM0, dphytim0);233	rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM1, dphytim1);234	rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM2, dphytim2);235	rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM3, dphytim3);236 237	ret = reset_control_deassert(dsi->rstc);238	if (ret < 0)239		return ret;240 241	udelay(1);242 243	return 0;244}245 246static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi)247{248	u32 dphyctrl0;249 250	dphyctrl0 = rzg2l_mipi_dsi_phy_read(dsi, DSIDPHYCTRL0);251 252	dphyctrl0 &= ~(DSIDPHYCTRL0_EN_LDO1200 | DSIDPHYCTRL0_EN_BGR);253	rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);254 255	reset_control_assert(dsi->rstc);256}257 258static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,259				  const struct drm_display_mode *mode)260{261	unsigned long hsfreq;262	unsigned int bpp;263	u32 txsetr;264	u32 clstptsetr;265	u32 lptrnstsetr;266	u32 clkkpt;267	u32 clkbfht;268	u32 clkstpt;269	u32 golpbkt;270	int ret;271 272	/*273	 * Relationship between hsclk and vclk must follow274	 * vclk * bpp = hsclk * 8 * lanes275	 * where vclk: video clock (Hz)276	 *       bpp: video pixel bit depth277	 *       hsclk: DSI HS Byte clock frequency (Hz)278	 *       lanes: number of data lanes279	 *280	 * hsclk(bit) = hsclk(byte) * 8281	 */282	bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);283	hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes);284 285	ret = pm_runtime_resume_and_get(dsi->dev);286	if (ret < 0)287		return ret;288 289	clk_set_rate(dsi->vclk, mode->clock * 1000);290 291	ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq);292	if (ret < 0)293		goto err_phy;294 295	/* Enable Data lanes and Clock lanes */296	txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN;297	rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr);298 299	/*300	 * Global timings characteristic depends on high speed Clock Frequency301	 * Currently MIPI DSI-IF just supports maximum FHD@60 with:302	 * - videoclock = 148.5 (MHz)303	 * - bpp: maximum 24bpp304	 * - data lanes: maximum 4 lanes305	 * Therefore maximum hsclk will be 891 Mbps.306	 */307	if (hsfreq > 445500) {308		clkkpt = 12;309		clkbfht = 15;310		clkstpt = 48;311		golpbkt = 75;312	} else if (hsfreq > 250000) {313		clkkpt = 7;314		clkbfht = 8;315		clkstpt = 27;316		golpbkt = 40;317	} else {318		clkkpt = 8;319		clkbfht = 6;320		clkstpt = 24;321		golpbkt = 29;322	}323 324	clstptsetr = CLSTPTSETR_CLKKPT(clkkpt) | CLSTPTSETR_CLKBFHT(clkbfht) |325		     CLSTPTSETR_CLKSTPT(clkstpt);326	rzg2l_mipi_dsi_link_write(dsi, CLSTPTSETR, clstptsetr);327 328	lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt);329	rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr);330 331	return 0;332 333err_phy:334	rzg2l_mipi_dsi_dphy_exit(dsi);335	pm_runtime_put(dsi->dev);336 337	return ret;338}339 340static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi)341{342	rzg2l_mipi_dsi_dphy_exit(dsi);343	pm_runtime_put(dsi->dev);344}345 346static void rzg2l_mipi_dsi_set_display_timing(struct rzg2l_mipi_dsi *dsi,347					      const struct drm_display_mode *mode)348{349	u32 vich1ppsetr;350	u32 vich1vssetr;351	u32 vich1vpsetr;352	u32 vich1hssetr;353	u32 vich1hpsetr;354	int dsi_format;355	u32 delay[2];356	u8 index;357 358	/* Configuration for Pixel Packet */359	dsi_format = mipi_dsi_pixel_format_to_bpp(dsi->format);360	switch (dsi_format) {361	case 24:362		vich1ppsetr = VICH1PPSETR_DT_RGB24;363		break;364	case 18:365		vich1ppsetr = VICH1PPSETR_DT_RGB18;366		break;367	}368 369	if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) &&370	    !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST))371		vich1ppsetr |= VICH1PPSETR_TXESYNC_PULSE;372 373	rzg2l_mipi_dsi_link_write(dsi, VICH1PPSETR, vich1ppsetr);374 375	/* Configuration for Video Parameters */376	vich1vssetr = VICH1VSSETR_VACTIVE(mode->vdisplay) |377		      VICH1VSSETR_VSA(mode->vsync_end - mode->vsync_start);378	vich1vssetr |= (mode->flags & DRM_MODE_FLAG_PVSYNC) ?379			VICH1VSSETR_VSPOL_HIGH : VICH1VSSETR_VSPOL_LOW;380 381	vich1vpsetr = VICH1VPSETR_VFP(mode->vsync_start - mode->vdisplay) |382		      VICH1VPSETR_VBP(mode->vtotal - mode->vsync_end);383 384	vich1hssetr = VICH1HSSETR_HACTIVE(mode->hdisplay) |385		      VICH1HSSETR_HSA(mode->hsync_end - mode->hsync_start);386	vich1hssetr |= (mode->flags & DRM_MODE_FLAG_PHSYNC) ?387			VICH1HSSETR_HSPOL_HIGH : VICH1HSSETR_HSPOL_LOW;388 389	vich1hpsetr = VICH1HPSETR_HFP(mode->hsync_start - mode->hdisplay) |390		      VICH1HPSETR_HBP(mode->htotal - mode->hsync_end);391 392	rzg2l_mipi_dsi_link_write(dsi, VICH1VSSETR, vich1vssetr);393	rzg2l_mipi_dsi_link_write(dsi, VICH1VPSETR, vich1vpsetr);394	rzg2l_mipi_dsi_link_write(dsi, VICH1HSSETR, vich1hssetr);395	rzg2l_mipi_dsi_link_write(dsi, VICH1HPSETR, vich1hpsetr);396 397	/*398	 * Configuration for Delay Value399	 * Delay value based on 2 ranges of video clock.400	 * 74.25MHz is videoclock of HD@60p or FHD@30p401	 */402	if (mode->clock > 74250) {403		delay[0] = 231;404		delay[1] = 216;405	} else {406		delay[0] = 220;407		delay[1] = 212;408	}409 410	if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)411		index = 0;412	else413		index = 1;414 415	rzg2l_mipi_dsi_link_write(dsi, VICH1SET1R,416				  VICH1SET1R_DLY(delay[index]));417}418 419static int rzg2l_mipi_dsi_start_hs_clock(struct rzg2l_mipi_dsi *dsi)420{421	bool is_clk_cont;422	u32 hsclksetr;423	u32 status;424	int ret;425 426	is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);427 428	/* Start HS clock */429	hsclksetr = HSCLKSETR_HSCLKRUN_HS | (is_clk_cont ?430					     HSCLKSETR_HSCLKMODE_CONT :431					     HSCLKSETR_HSCLKMODE_NON_CONT);432	rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, hsclksetr);433 434	if (is_clk_cont) {435		ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,436					status & PLSR_CLLP2HS,437					2000, 20000, false, dsi, PLSR);438		if (ret < 0) {439			dev_err(dsi->dev, "failed to start HS clock\n");440			return ret;441		}442	}443 444	dev_dbg(dsi->dev, "Start High Speed Clock with %s clock mode",445		is_clk_cont ? "continuous" : "non-continuous");446 447	return 0;448}449 450static int rzg2l_mipi_dsi_stop_hs_clock(struct rzg2l_mipi_dsi *dsi)451{452	bool is_clk_cont;453	u32 status;454	int ret;455 456	is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);457 458	/* Stop HS clock */459	rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR,460				  is_clk_cont ? HSCLKSETR_HSCLKMODE_CONT :461				  HSCLKSETR_HSCLKMODE_NON_CONT);462 463	if (is_clk_cont) {464		ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,465					status & PLSR_CLHS2LP,466					2000, 20000, false, dsi, PLSR);467		if (ret < 0) {468			dev_err(dsi->dev, "failed to stop HS clock\n");469			return ret;470		}471	}472 473	return 0;474}475 476static int rzg2l_mipi_dsi_start_video(struct rzg2l_mipi_dsi *dsi)477{478	u32 vich1set0r;479	u32 status;480	int ret;481 482	/* Configuration for Blanking sequence and start video input*/483	vich1set0r = VICH1SET0R_HFPNOLP | VICH1SET0R_HBPNOLP |484		     VICH1SET0R_HSANOLP | VICH1SET0R_VSTART;485	rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, vich1set0r);486 487	ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,488				status & VICH1SR_VIRDY,489				2000, 20000, false, dsi, VICH1SR);490	if (ret < 0)491		dev_err(dsi->dev, "Failed to start video signal input\n");492 493	return ret;494}495 496static int rzg2l_mipi_dsi_stop_video(struct rzg2l_mipi_dsi *dsi)497{498	u32 status;499	int ret;500 501	rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, VICH1SET0R_VSTPAFT);502	ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,503				(status & VICH1SR_STOP) && (!(status & VICH1SR_RUNNING)),504				2000, 20000, false, dsi, VICH1SR);505	if (ret < 0)506		goto err;507 508	ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,509				!(status & LINKSR_HSBUSY),510				2000, 20000, false, dsi, LINKSR);511	if (ret < 0)512		goto err;513 514	return 0;515 516err:517	dev_err(dsi->dev, "Failed to stop video signal input\n");518	return ret;519}520 521/* -----------------------------------------------------------------------------522 * Bridge523 */524 525static int rzg2l_mipi_dsi_attach(struct drm_bridge *bridge,526				 enum drm_bridge_attach_flags flags)527{528	struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);529 530	return drm_bridge_attach(bridge->encoder, dsi->next_bridge, bridge,531				 flags);532}533 534static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge,535					 struct drm_bridge_state *old_bridge_state)536{537	struct drm_atomic_state *state = old_bridge_state->base.state;538	struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);539	const struct drm_display_mode *mode;540	struct drm_connector *connector;541	struct drm_crtc *crtc;542	int ret;543 544	connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);545	crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;546	mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode;547 548	ret = rzg2l_mipi_dsi_startup(dsi, mode);549	if (ret < 0)550		return;551 552	rzg2l_mipi_dsi_set_display_timing(dsi, mode);553 554	ret = rzg2l_mipi_dsi_start_hs_clock(dsi);555	if (ret < 0)556		goto err_stop;557 558	ret = rzg2l_mipi_dsi_start_video(dsi);559	if (ret < 0)560		goto err_stop_clock;561 562	return;563 564err_stop_clock:565	rzg2l_mipi_dsi_stop_hs_clock(dsi);566err_stop:567	rzg2l_mipi_dsi_stop(dsi);568}569 570static void rzg2l_mipi_dsi_atomic_disable(struct drm_bridge *bridge,571					  struct drm_bridge_state *old_bridge_state)572{573	struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);574 575	rzg2l_mipi_dsi_stop_video(dsi);576	rzg2l_mipi_dsi_stop_hs_clock(dsi);577	rzg2l_mipi_dsi_stop(dsi);578}579 580static enum drm_mode_status581rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge,582				 const struct drm_display_info *info,583				 const struct drm_display_mode *mode)584{585	if (mode->clock > 148500)586		return MODE_CLOCK_HIGH;587 588	return MODE_OK;589}590 591static const struct drm_bridge_funcs rzg2l_mipi_dsi_bridge_ops = {592	.attach = rzg2l_mipi_dsi_attach,593	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,594	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,595	.atomic_reset = drm_atomic_helper_bridge_reset,596	.atomic_enable = rzg2l_mipi_dsi_atomic_enable,597	.atomic_disable = rzg2l_mipi_dsi_atomic_disable,598	.mode_valid = rzg2l_mipi_dsi_bridge_mode_valid,599};600 601/* -----------------------------------------------------------------------------602 * Host setting603 */604 605static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,606				      struct mipi_dsi_device *device)607{608	struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);609	int ret;610 611	if (device->lanes > dsi->num_data_lanes) {612		dev_err(dsi->dev,613			"Number of lines of device (%u) exceeds host (%u)\n",614			device->lanes, dsi->num_data_lanes);615		return -EINVAL;616	}617 618	switch (mipi_dsi_pixel_format_to_bpp(device->format)) {619	case 24:620	case 18:621		break;622	default:623		dev_err(dsi->dev, "Unsupported format 0x%04x\n", device->format);624		return -EINVAL;625	}626 627	dsi->lanes = device->lanes;628	dsi->format = device->format;629	dsi->mode_flags = device->mode_flags;630 631	dsi->next_bridge = devm_drm_of_get_bridge(dsi->dev, dsi->dev->of_node,632						  1, 0);633	if (IS_ERR(dsi->next_bridge)) {634		ret = PTR_ERR(dsi->next_bridge);635		dev_err(dsi->dev, "failed to get next bridge: %d\n", ret);636		return ret;637	}638 639	drm_bridge_add(&dsi->bridge);640 641	return 0;642}643 644static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host,645				      struct mipi_dsi_device *device)646{647	struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);648 649	drm_bridge_remove(&dsi->bridge);650 651	return 0;652}653 654static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = {655	.attach = rzg2l_mipi_dsi_host_attach,656	.detach = rzg2l_mipi_dsi_host_detach,657};658 659/* -----------------------------------------------------------------------------660 * Power Management661 */662 663static int __maybe_unused rzg2l_mipi_pm_runtime_suspend(struct device *dev)664{665	struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);666 667	reset_control_assert(dsi->prstc);668	reset_control_assert(dsi->arstc);669 670	return 0;671}672 673static int __maybe_unused rzg2l_mipi_pm_runtime_resume(struct device *dev)674{675	struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);676	int ret;677 678	ret = reset_control_deassert(dsi->arstc);679	if (ret < 0)680		return ret;681 682	ret = reset_control_deassert(dsi->prstc);683	if (ret < 0)684		reset_control_assert(dsi->arstc);685 686	return ret;687}688 689static const struct dev_pm_ops rzg2l_mipi_pm_ops = {690	SET_RUNTIME_PM_OPS(rzg2l_mipi_pm_runtime_suspend, rzg2l_mipi_pm_runtime_resume, NULL)691};692 693/* -----------------------------------------------------------------------------694 * Probe & Remove695 */696 697static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)698{699	unsigned int num_data_lanes;700	struct rzg2l_mipi_dsi *dsi;701	u32 txsetr;702	int ret;703 704	dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);705	if (!dsi)706		return -ENOMEM;707 708	platform_set_drvdata(pdev, dsi);709	dsi->dev = &pdev->dev;710 711	ret = drm_of_get_data_lanes_count_ep(dsi->dev->of_node, 1, 0, 1, 4);712	if (ret < 0)713		return dev_err_probe(dsi->dev, ret,714				     "missing or invalid data-lanes property\n");715 716	num_data_lanes = ret;717 718	dsi->mmio = devm_platform_ioremap_resource(pdev, 0);719	if (IS_ERR(dsi->mmio))720		return PTR_ERR(dsi->mmio);721 722	dsi->vclk = devm_clk_get(dsi->dev, "vclk");723	if (IS_ERR(dsi->vclk))724		return PTR_ERR(dsi->vclk);725 726	dsi->rstc = devm_reset_control_get_exclusive(dsi->dev, "rst");727	if (IS_ERR(dsi->rstc))728		return dev_err_probe(dsi->dev, PTR_ERR(dsi->rstc),729				     "failed to get rst\n");730 731	dsi->arstc = devm_reset_control_get_exclusive(dsi->dev, "arst");732	if (IS_ERR(dsi->arstc))733		return dev_err_probe(&pdev->dev, PTR_ERR(dsi->arstc),734				     "failed to get arst\n");735 736	dsi->prstc = devm_reset_control_get_exclusive(dsi->dev, "prst");737	if (IS_ERR(dsi->prstc))738		return dev_err_probe(dsi->dev, PTR_ERR(dsi->prstc),739				     "failed to get prst\n");740 741	platform_set_drvdata(pdev, dsi);742 743	pm_runtime_enable(dsi->dev);744 745	ret = pm_runtime_resume_and_get(dsi->dev);746	if (ret < 0)747		goto err_pm_disable;748 749	/*750	 * TXSETR register can be read only after DPHY init. But during probe751	 * mode->clock and format are not available. So initialize DPHY with752	 * timing parameters for 80Mbps.753	 */754	ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000);755	if (ret < 0)756		goto err_phy;757 758	txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR);759	dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes);760	rzg2l_mipi_dsi_dphy_exit(dsi);761	pm_runtime_put(dsi->dev);762 763	/* Initialize the DRM bridge. */764	dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops;765	dsi->bridge.of_node = dsi->dev->of_node;766 767	/* Init host device */768	dsi->host.dev = dsi->dev;769	dsi->host.ops = &rzg2l_mipi_dsi_host_ops;770	ret = mipi_dsi_host_register(&dsi->host);771	if (ret < 0)772		goto err_pm_disable;773 774	return 0;775 776err_phy:777	rzg2l_mipi_dsi_dphy_exit(dsi);778	pm_runtime_put(dsi->dev);779err_pm_disable:780	pm_runtime_disable(dsi->dev);781	return ret;782}783 784static void rzg2l_mipi_dsi_remove(struct platform_device *pdev)785{786	struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev);787 788	mipi_dsi_host_unregister(&dsi->host);789	pm_runtime_disable(&pdev->dev);790}791 792static const struct of_device_id rzg2l_mipi_dsi_of_table[] = {793	{ .compatible = "renesas,rzg2l-mipi-dsi" },794	{ /* sentinel */ }795};796 797MODULE_DEVICE_TABLE(of, rzg2l_mipi_dsi_of_table);798 799static struct platform_driver rzg2l_mipi_dsi_platform_driver = {800	.probe	= rzg2l_mipi_dsi_probe,801	.remove_new = rzg2l_mipi_dsi_remove,802	.driver	= {803		.name = "rzg2l-mipi-dsi",804		.pm = &rzg2l_mipi_pm_ops,805		.of_match_table = rzg2l_mipi_dsi_of_table,806	},807};808 809module_platform_driver(rzg2l_mipi_dsi_platform_driver);810 811MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");812MODULE_DESCRIPTION("Renesas RZ/G2L MIPI DSI Encoder Driver");813MODULE_LICENSE("GPL");814