brintos

brintos / linux-shallow public Read only

0
0
Text · 31.4 KiB · 5f05647 Raw
1227 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * i.MX8 NWL MIPI DSI host driver4 *5 * Copyright (C) 2017 NXP6 * Copyright (C) 2020 Purism SPC7 */8 9#include <linux/bitfield.h>10#include <linux/bits.h>11#include <linux/clk.h>12#include <linux/irq.h>13#include <linux/math64.h>14#include <linux/mfd/syscon.h>15#include <linux/media-bus-format.h>16#include <linux/module.h>17#include <linux/mux/consumer.h>18#include <linux/of.h>19#include <linux/phy/phy.h>20#include <linux/platform_device.h>21#include <linux/regmap.h>22#include <linux/reset.h>23#include <linux/sys_soc.h>24#include <linux/time64.h>25 26#include <drm/drm_atomic_state_helper.h>27#include <drm/drm_bridge.h>28#include <drm/drm_mipi_dsi.h>29#include <drm/drm_of.h>30#include <drm/drm_print.h>31 32#include <video/mipi_display.h>33 34#include "nwl-dsi.h"35 36#define DRV_NAME "nwl-dsi"37 38/* i.MX8 NWL quirks */39/* i.MX8MQ errata E11418 */40#define E11418_HS_MODE_QUIRK	BIT(0)41 42#define NWL_DSI_MIPI_FIFO_TIMEOUT msecs_to_jiffies(500)43 44enum transfer_direction {45	DSI_PACKET_SEND,46	DSI_PACKET_RECEIVE,47};48 49#define NWL_DSI_ENDPOINT_LCDIF 050#define NWL_DSI_ENDPOINT_DCSS 151 52struct nwl_dsi_transfer {53	const struct mipi_dsi_msg *msg;54	struct mipi_dsi_packet packet;55	struct completion completed;56 57	int status; /* status of transmission */58	enum transfer_direction direction;59	bool need_bta;60	u8 cmd;61	u16 rx_word_count;62	size_t tx_len; /* in bytes */63	size_t rx_len; /* in bytes */64};65 66struct nwl_dsi {67	struct drm_bridge bridge;68	struct mipi_dsi_host dsi_host;69	struct device *dev;70	struct phy *phy;71	union phy_configure_opts phy_cfg;72	unsigned int quirks;73 74	struct regmap *regmap;75	int irq;76	/*77	 * The DSI host controller needs this reset sequence according to NWL:78	 * 1. Deassert pclk reset to get access to DSI regs79	 * 2. Configure DSI Host and DPHY and enable DPHY80	 * 3. Deassert ESC and BYTE resets to allow host TX operations)81	 * 4. Send DSI cmds to configure peripheral (handled by panel drv)82	 * 5. Deassert DPI reset so DPI receives pixels and starts sending83	 *    DSI data84	 *85	 * TODO: Since panel_bridges do their DSI setup in enable we86	 * currently have 4. and 5. swapped.87	 */88	struct reset_control *rst_byte;89	struct reset_control *rst_esc;90	struct reset_control *rst_dpi;91	struct reset_control *rst_pclk;92	struct mux_control *mux;93 94	/* DSI clocks */95	struct clk *phy_ref_clk;96	struct clk *rx_esc_clk;97	struct clk *tx_esc_clk;98	struct clk *core_clk;99	/*100	 * hardware bug: the i.MX8MQ needs this clock on during reset101	 * even when not using LCDIF.102	 */103	struct clk *lcdif_clk;104 105	/* dsi lanes */106	u32 lanes;107	enum mipi_dsi_pixel_format format;108	struct drm_display_mode mode;109	unsigned long dsi_mode_flags;110	int error;111 112	struct nwl_dsi_transfer *xfer;113};114 115static const struct regmap_config nwl_dsi_regmap_config = {116	.reg_bits = 16,117	.val_bits = 32,118	.reg_stride = 4,119	.max_register = NWL_DSI_IRQ_MASK2,120	.name = DRV_NAME,121};122 123static inline struct nwl_dsi *bridge_to_dsi(struct drm_bridge *bridge)124{125	return container_of(bridge, struct nwl_dsi, bridge);126}127 128static int nwl_dsi_clear_error(struct nwl_dsi *dsi)129{130	int ret = dsi->error;131 132	dsi->error = 0;133	return ret;134}135 136static void nwl_dsi_write(struct nwl_dsi *dsi, unsigned int reg, u32 val)137{138	int ret;139 140	if (dsi->error)141		return;142 143	ret = regmap_write(dsi->regmap, reg, val);144	if (ret < 0) {145		DRM_DEV_ERROR(dsi->dev,146			      "Failed to write NWL DSI reg 0x%x: %d\n", reg,147			      ret);148		dsi->error = ret;149	}150}151 152static u32 nwl_dsi_read(struct nwl_dsi *dsi, u32 reg)153{154	unsigned int val;155	int ret;156 157	if (dsi->error)158		return 0;159 160	ret = regmap_read(dsi->regmap, reg, &val);161	if (ret < 0) {162		DRM_DEV_ERROR(dsi->dev, "Failed to read NWL DSI reg 0x%x: %d\n",163			      reg, ret);164		dsi->error = ret;165	}166	return val;167}168 169static int nwl_dsi_get_dpi_pixel_format(enum mipi_dsi_pixel_format format)170{171	switch (format) {172	case MIPI_DSI_FMT_RGB565:173		return NWL_DSI_PIXEL_FORMAT_16;174	case MIPI_DSI_FMT_RGB666:175		return NWL_DSI_PIXEL_FORMAT_18L;176	case MIPI_DSI_FMT_RGB666_PACKED:177		return NWL_DSI_PIXEL_FORMAT_18;178	case MIPI_DSI_FMT_RGB888:179		return NWL_DSI_PIXEL_FORMAT_24;180	default:181		return -EINVAL;182	}183}184 185/*186 * ps2bc - Picoseconds to byte clock cycles187 */188static u32 ps2bc(struct nwl_dsi *dsi, unsigned long long ps)189{190	u32 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);191 192	return DIV64_U64_ROUND_UP(ps * dsi->mode.clock * bpp,193				  dsi->lanes * 8ULL * NSEC_PER_SEC);194}195 196/*197 * ui2bc - UI time periods to byte clock cycles198 */199static u32 ui2bc(unsigned int ui)200{201	return DIV_ROUND_UP(ui, BITS_PER_BYTE);202}203 204/*205 * us2bc - micro seconds to lp clock cycles206 */207static u32 us2lp(u32 lp_clk_rate, unsigned long us)208{209	return DIV_ROUND_UP(us * lp_clk_rate, USEC_PER_SEC);210}211 212static int nwl_dsi_config_host(struct nwl_dsi *dsi)213{214	u32 cycles;215	struct phy_configure_opts_mipi_dphy *cfg = &dsi->phy_cfg.mipi_dphy;216 217	if (dsi->lanes < 1 || dsi->lanes > 4)218		return -EINVAL;219 220	DRM_DEV_DEBUG_DRIVER(dsi->dev, "DSI Lanes %d\n", dsi->lanes);221	nwl_dsi_write(dsi, NWL_DSI_CFG_NUM_LANES, dsi->lanes - 1);222 223	if (dsi->dsi_mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) {224		nwl_dsi_write(dsi, NWL_DSI_CFG_NONCONTINUOUS_CLK, 0x01);225		nwl_dsi_write(dsi, NWL_DSI_CFG_AUTOINSERT_EOTP, 0x01);226	} else {227		nwl_dsi_write(dsi, NWL_DSI_CFG_NONCONTINUOUS_CLK, 0x00);228		nwl_dsi_write(dsi, NWL_DSI_CFG_AUTOINSERT_EOTP, 0x00);229	}230 231	/* values in byte clock cycles */232	cycles = ui2bc(cfg->clk_pre);233	DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_t_pre: 0x%x\n", cycles);234	nwl_dsi_write(dsi, NWL_DSI_CFG_T_PRE, cycles);235	cycles = ps2bc(dsi, cfg->lpx + cfg->clk_prepare + cfg->clk_zero);236	DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_tx_gap (pre): 0x%x\n", cycles);237	cycles += ui2bc(cfg->clk_pre);238	DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_t_post: 0x%x\n", cycles);239	nwl_dsi_write(dsi, NWL_DSI_CFG_T_POST, cycles);240	cycles = ps2bc(dsi, cfg->hs_exit);241	DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_tx_gap: 0x%x\n", cycles);242	nwl_dsi_write(dsi, NWL_DSI_CFG_TX_GAP, cycles);243 244	nwl_dsi_write(dsi, NWL_DSI_CFG_EXTRA_CMDS_AFTER_EOTP, 0x01);245	nwl_dsi_write(dsi, NWL_DSI_CFG_HTX_TO_COUNT, 0x00);246	nwl_dsi_write(dsi, NWL_DSI_CFG_LRX_H_TO_COUNT, 0x00);247	nwl_dsi_write(dsi, NWL_DSI_CFG_BTA_H_TO_COUNT, 0x00);248	/* In LP clock cycles */249	cycles = us2lp(cfg->lp_clk_rate, cfg->wakeup);250	DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_twakeup: 0x%x\n", cycles);251	nwl_dsi_write(dsi, NWL_DSI_CFG_TWAKEUP, cycles);252 253	return nwl_dsi_clear_error(dsi);254}255 256static int nwl_dsi_config_dpi(struct nwl_dsi *dsi)257{258	u32 mode;259	int color_format;260	bool burst_mode;261	int hfront_porch, hback_porch, vfront_porch, vback_porch;262	int hsync_len, vsync_len;263 264	hfront_porch = dsi->mode.hsync_start - dsi->mode.hdisplay;265	hsync_len = dsi->mode.hsync_end - dsi->mode.hsync_start;266	hback_porch = dsi->mode.htotal - dsi->mode.hsync_end;267 268	vfront_porch = dsi->mode.vsync_start - dsi->mode.vdisplay;269	vsync_len = dsi->mode.vsync_end - dsi->mode.vsync_start;270	vback_porch = dsi->mode.vtotal - dsi->mode.vsync_end;271 272	DRM_DEV_DEBUG_DRIVER(dsi->dev, "hfront_porch = %d\n", hfront_porch);273	DRM_DEV_DEBUG_DRIVER(dsi->dev, "hback_porch = %d\n", hback_porch);274	DRM_DEV_DEBUG_DRIVER(dsi->dev, "hsync_len = %d\n", hsync_len);275	DRM_DEV_DEBUG_DRIVER(dsi->dev, "hdisplay = %d\n", dsi->mode.hdisplay);276	DRM_DEV_DEBUG_DRIVER(dsi->dev, "vfront_porch = %d\n", vfront_porch);277	DRM_DEV_DEBUG_DRIVER(dsi->dev, "vback_porch = %d\n", vback_porch);278	DRM_DEV_DEBUG_DRIVER(dsi->dev, "vsync_len = %d\n", vsync_len);279	DRM_DEV_DEBUG_DRIVER(dsi->dev, "vactive = %d\n", dsi->mode.vdisplay);280	DRM_DEV_DEBUG_DRIVER(dsi->dev, "clock = %d kHz\n", dsi->mode.clock);281 282	color_format = nwl_dsi_get_dpi_pixel_format(dsi->format);283	if (color_format < 0) {284		DRM_DEV_ERROR(dsi->dev, "Invalid color format 0x%x\n",285			      dsi->format);286		return color_format;287	}288	DRM_DEV_DEBUG_DRIVER(dsi->dev, "pixel fmt = %d\n", dsi->format);289 290	nwl_dsi_write(dsi, NWL_DSI_INTERFACE_COLOR_CODING, NWL_DSI_DPI_24_BIT);291	nwl_dsi_write(dsi, NWL_DSI_PIXEL_FORMAT, color_format);292	nwl_dsi_write(dsi, NWL_DSI_VSYNC_POLARITY,293		      dsi->mode.flags & DRM_MODE_FLAG_PVSYNC ?294		      NWL_DSI_VSYNC_POLARITY_ACTIVE_HIGH :295		      NWL_DSI_VSYNC_POLARITY_ACTIVE_LOW);296	nwl_dsi_write(dsi, NWL_DSI_HSYNC_POLARITY,297		      dsi->mode.flags & DRM_MODE_FLAG_PHSYNC ?298		      NWL_DSI_HSYNC_POLARITY_ACTIVE_HIGH :299		      NWL_DSI_HSYNC_POLARITY_ACTIVE_LOW);300 301	burst_mode = (dsi->dsi_mode_flags & MIPI_DSI_MODE_VIDEO_BURST) &&302		     !(dsi->dsi_mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE);303 304	if (burst_mode) {305		nwl_dsi_write(dsi, NWL_DSI_VIDEO_MODE, NWL_DSI_VM_BURST_MODE);306		nwl_dsi_write(dsi, NWL_DSI_PIXEL_FIFO_SEND_LEVEL, 256);307	} else {308		mode = ((dsi->dsi_mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) ?309				NWL_DSI_VM_BURST_MODE_WITH_SYNC_PULSES :310				NWL_DSI_VM_NON_BURST_MODE_WITH_SYNC_EVENTS);311		nwl_dsi_write(dsi, NWL_DSI_VIDEO_MODE, mode);312		nwl_dsi_write(dsi, NWL_DSI_PIXEL_FIFO_SEND_LEVEL,313			      dsi->mode.hdisplay);314	}315 316	nwl_dsi_write(dsi, NWL_DSI_HFP, hfront_porch);317	nwl_dsi_write(dsi, NWL_DSI_HBP, hback_porch);318	nwl_dsi_write(dsi, NWL_DSI_HSA, hsync_len);319 320	nwl_dsi_write(dsi, NWL_DSI_ENABLE_MULT_PKTS, 0x0);321	nwl_dsi_write(dsi, NWL_DSI_BLLP_MODE, 0x1);322	nwl_dsi_write(dsi, NWL_DSI_USE_NULL_PKT_BLLP, 0x0);323	nwl_dsi_write(dsi, NWL_DSI_VC, 0x0);324 325	nwl_dsi_write(dsi, NWL_DSI_PIXEL_PAYLOAD_SIZE, dsi->mode.hdisplay);326	nwl_dsi_write(dsi, NWL_DSI_VACTIVE, dsi->mode.vdisplay - 1);327	nwl_dsi_write(dsi, NWL_DSI_VBP, vback_porch);328	nwl_dsi_write(dsi, NWL_DSI_VFP, vfront_porch);329 330	return nwl_dsi_clear_error(dsi);331}332 333static int nwl_dsi_init_interrupts(struct nwl_dsi *dsi)334{335	u32 irq_enable = ~(u32)(NWL_DSI_TX_PKT_DONE_MASK |336				NWL_DSI_RX_PKT_HDR_RCVD_MASK |337				NWL_DSI_TX_FIFO_OVFLW_MASK |338				NWL_DSI_HS_TX_TIMEOUT_MASK);339 340	nwl_dsi_write(dsi, NWL_DSI_IRQ_MASK, irq_enable);341	nwl_dsi_write(dsi, NWL_DSI_IRQ_MASK2, 0x7);342 343	return nwl_dsi_clear_error(dsi);344}345 346static int nwl_dsi_host_attach(struct mipi_dsi_host *dsi_host,347			       struct mipi_dsi_device *device)348{349	struct nwl_dsi *dsi = container_of(dsi_host, struct nwl_dsi, dsi_host);350	struct device *dev = dsi->dev;351 352	DRM_DEV_INFO(dev, "lanes=%u, format=0x%x flags=0x%lx\n", device->lanes,353		     device->format, device->mode_flags);354 355	if (device->lanes < 1 || device->lanes > 4)356		return -EINVAL;357 358	dsi->lanes = device->lanes;359	dsi->format = device->format;360	dsi->dsi_mode_flags = device->mode_flags;361 362	return 0;363}364 365static bool nwl_dsi_read_packet(struct nwl_dsi *dsi, u32 status)366{367	struct device *dev = dsi->dev;368	struct nwl_dsi_transfer *xfer = dsi->xfer;369	int err;370	u8 *payload = xfer->msg->rx_buf;371	u32 val;372	u16 word_count;373	u8 channel;374	u8 data_type;375 376	xfer->status = 0;377 378	if (xfer->rx_word_count == 0) {379		if (!(status & NWL_DSI_RX_PKT_HDR_RCVD))380			return false;381		/* Get the RX header and parse it */382		val = nwl_dsi_read(dsi, NWL_DSI_RX_PKT_HEADER);383		err = nwl_dsi_clear_error(dsi);384		if (err)385			xfer->status = err;386		word_count = NWL_DSI_WC(val);387		channel = NWL_DSI_RX_VC(val);388		data_type = NWL_DSI_RX_DT(val);389 390		if (channel != xfer->msg->channel) {391			DRM_DEV_ERROR(dev,392				      "[%02X] Channel mismatch (%u != %u)\n",393				      xfer->cmd, channel, xfer->msg->channel);394			xfer->status = -EINVAL;395			return true;396		}397 398		switch (data_type) {399		case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:400		case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:401			if (xfer->msg->rx_len > 1) {402				/* read second byte */403				payload[1] = word_count >> 8;404				++xfer->rx_len;405			}406			fallthrough;407		case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:408		case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:409			if (xfer->msg->rx_len > 0) {410				/* read first byte */411				payload[0] = word_count & 0xff;412				++xfer->rx_len;413			}414			xfer->status = xfer->rx_len;415			return true;416		case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:417			word_count &= 0xff;418			DRM_DEV_ERROR(dev, "[%02X] DSI error report: 0x%02x\n",419				      xfer->cmd, word_count);420			xfer->status = -EPROTO;421			return true;422		}423 424		if (word_count > xfer->msg->rx_len) {425			DRM_DEV_ERROR(dev,426				"[%02X] Receive buffer too small: %zu (< %u)\n",427				xfer->cmd, xfer->msg->rx_len, word_count);428			xfer->status = -EINVAL;429			return true;430		}431 432		xfer->rx_word_count = word_count;433	} else {434		/* Set word_count from previous header read */435		word_count = xfer->rx_word_count;436	}437 438	/* If RX payload is not yet received, wait for it */439	if (!(status & NWL_DSI_RX_PKT_PAYLOAD_DATA_RCVD))440		return false;441 442	/* Read the RX payload */443	while (word_count >= 4) {444		val = nwl_dsi_read(dsi, NWL_DSI_RX_PAYLOAD);445		payload[0] = (val >> 0) & 0xff;446		payload[1] = (val >> 8) & 0xff;447		payload[2] = (val >> 16) & 0xff;448		payload[3] = (val >> 24) & 0xff;449		payload += 4;450		xfer->rx_len += 4;451		word_count -= 4;452	}453 454	if (word_count > 0) {455		val = nwl_dsi_read(dsi, NWL_DSI_RX_PAYLOAD);456		switch (word_count) {457		case 3:458			payload[2] = (val >> 16) & 0xff;459			++xfer->rx_len;460			fallthrough;461		case 2:462			payload[1] = (val >> 8) & 0xff;463			++xfer->rx_len;464			fallthrough;465		case 1:466			payload[0] = (val >> 0) & 0xff;467			++xfer->rx_len;468			break;469		}470	}471 472	xfer->status = xfer->rx_len;473	err = nwl_dsi_clear_error(dsi);474	if (err)475		xfer->status = err;476 477	return true;478}479 480static void nwl_dsi_finish_transmission(struct nwl_dsi *dsi, u32 status)481{482	struct nwl_dsi_transfer *xfer = dsi->xfer;483	bool end_packet = false;484 485	if (!xfer)486		return;487 488	if (xfer->direction == DSI_PACKET_SEND &&489	    status & NWL_DSI_TX_PKT_DONE) {490		xfer->status = xfer->tx_len;491		end_packet = true;492	} else if (status & NWL_DSI_DPHY_DIRECTION &&493		   ((status & (NWL_DSI_RX_PKT_HDR_RCVD |494			       NWL_DSI_RX_PKT_PAYLOAD_DATA_RCVD)))) {495		end_packet = nwl_dsi_read_packet(dsi, status);496	}497 498	if (end_packet)499		complete(&xfer->completed);500}501 502static void nwl_dsi_begin_transmission(struct nwl_dsi *dsi)503{504	struct nwl_dsi_transfer *xfer = dsi->xfer;505	struct mipi_dsi_packet *pkt = &xfer->packet;506	const u8 *payload;507	size_t length;508	u16 word_count;509	u8 hs_mode;510	u32 val;511	u32 hs_workaround = 0;512 513	/* Send the payload, if any */514	length = pkt->payload_length;515	payload = pkt->payload;516 517	while (length >= 4) {518		val = *(u32 *)payload;519		hs_workaround |= !(val & 0xFFFF00);520		nwl_dsi_write(dsi, NWL_DSI_TX_PAYLOAD, val);521		payload += 4;522		length -= 4;523	}524	/* Send the rest of the payload */525	val = 0;526	switch (length) {527	case 3:528		val |= payload[2] << 16;529		fallthrough;530	case 2:531		val |= payload[1] << 8;532		hs_workaround |= !(val & 0xFFFF00);533		fallthrough;534	case 1:535		val |= payload[0];536		nwl_dsi_write(dsi, NWL_DSI_TX_PAYLOAD, val);537		break;538	}539	xfer->tx_len = pkt->payload_length;540 541	/*542	 * Send the header543	 * header[0] = Virtual Channel + Data Type544	 * header[1] = Word Count LSB (LP) or first param (SP)545	 * header[2] = Word Count MSB (LP) or second param (SP)546	 */547	word_count = pkt->header[1] | (pkt->header[2] << 8);548	if (hs_workaround && (dsi->quirks & E11418_HS_MODE_QUIRK)) {549		DRM_DEV_DEBUG_DRIVER(dsi->dev,550				     "Using hs mode workaround for cmd 0x%x\n",551				     xfer->cmd);552		hs_mode = 1;553	} else {554		hs_mode = (xfer->msg->flags & MIPI_DSI_MSG_USE_LPM) ? 0 : 1;555	}556	val = NWL_DSI_WC(word_count) | NWL_DSI_TX_VC(xfer->msg->channel) |557	      NWL_DSI_TX_DT(xfer->msg->type) | NWL_DSI_HS_SEL(hs_mode) |558	      NWL_DSI_BTA_TX(xfer->need_bta);559	nwl_dsi_write(dsi, NWL_DSI_PKT_CONTROL, val);560 561	/* Send packet command */562	nwl_dsi_write(dsi, NWL_DSI_SEND_PACKET, 0x1);563}564 565static ssize_t nwl_dsi_host_transfer(struct mipi_dsi_host *dsi_host,566				     const struct mipi_dsi_msg *msg)567{568	struct nwl_dsi *dsi = container_of(dsi_host, struct nwl_dsi, dsi_host);569	struct nwl_dsi_transfer xfer;570	ssize_t ret = 0;571 572	/* Create packet to be sent */573	dsi->xfer = &xfer;574	ret = mipi_dsi_create_packet(&xfer.packet, msg);575	if (ret < 0) {576		dsi->xfer = NULL;577		return ret;578	}579 580	if ((msg->type & MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM ||581	     msg->type & MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM ||582	     msg->type & MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM ||583	     msg->type & MIPI_DSI_DCS_READ) &&584	    msg->rx_len > 0 && msg->rx_buf)585		xfer.direction = DSI_PACKET_RECEIVE;586	else587		xfer.direction = DSI_PACKET_SEND;588 589	xfer.need_bta = (xfer.direction == DSI_PACKET_RECEIVE);590	xfer.need_bta |= (msg->flags & MIPI_DSI_MSG_REQ_ACK) ? 1 : 0;591	xfer.msg = msg;592	xfer.status = -ETIMEDOUT;593	xfer.rx_word_count = 0;594	xfer.rx_len = 0;595	xfer.cmd = 0x00;596	if (msg->tx_len > 0)597		xfer.cmd = ((u8 *)(msg->tx_buf))[0];598	init_completion(&xfer.completed);599 600	ret = clk_prepare_enable(dsi->rx_esc_clk);601	if (ret < 0) {602		DRM_DEV_ERROR(dsi->dev, "Failed to enable rx_esc clk: %zd\n",603			      ret);604		return ret;605	}606	DRM_DEV_DEBUG_DRIVER(dsi->dev, "Enabled rx_esc clk @%lu Hz\n",607			     clk_get_rate(dsi->rx_esc_clk));608 609	/* Initiate the DSI packet transmision */610	nwl_dsi_begin_transmission(dsi);611 612	if (!wait_for_completion_timeout(&xfer.completed,613					 NWL_DSI_MIPI_FIFO_TIMEOUT)) {614		DRM_DEV_ERROR(dsi_host->dev, "[%02X] DSI transfer timed out\n",615			      xfer.cmd);616		ret = -ETIMEDOUT;617	} else {618		ret = xfer.status;619	}620 621	clk_disable_unprepare(dsi->rx_esc_clk);622 623	return ret;624}625 626static const struct mipi_dsi_host_ops nwl_dsi_host_ops = {627	.attach = nwl_dsi_host_attach,628	.transfer = nwl_dsi_host_transfer,629};630 631static irqreturn_t nwl_dsi_irq_handler(int irq, void *data)632{633	u32 irq_status;634	struct nwl_dsi *dsi = data;635 636	irq_status = nwl_dsi_read(dsi, NWL_DSI_IRQ_STATUS);637 638	if (irq_status & NWL_DSI_TX_FIFO_OVFLW)639		DRM_DEV_ERROR_RATELIMITED(dsi->dev, "tx fifo overflow\n");640 641	if (irq_status & NWL_DSI_HS_TX_TIMEOUT)642		DRM_DEV_ERROR_RATELIMITED(dsi->dev, "HS tx timeout\n");643 644	if (irq_status & NWL_DSI_TX_PKT_DONE ||645	    irq_status & NWL_DSI_RX_PKT_HDR_RCVD ||646	    irq_status & NWL_DSI_RX_PKT_PAYLOAD_DATA_RCVD)647		nwl_dsi_finish_transmission(dsi, irq_status);648 649	return IRQ_HANDLED;650}651 652static int nwl_dsi_mode_set(struct nwl_dsi *dsi)653{654	struct device *dev = dsi->dev;655	union phy_configure_opts *phy_cfg = &dsi->phy_cfg;656	int ret;657 658	if (!dsi->lanes) {659		DRM_DEV_ERROR(dev, "Need DSI lanes: %d\n", dsi->lanes);660		return -EINVAL;661	}662 663	ret = phy_init(dsi->phy);664	if (ret < 0) {665		DRM_DEV_ERROR(dev, "Failed to init DSI phy: %d\n", ret);666		return ret;667	}668 669	ret = phy_set_mode(dsi->phy, PHY_MODE_MIPI_DPHY);670	if (ret < 0) {671		DRM_DEV_ERROR(dev, "Failed to set DSI phy mode: %d\n", ret);672		goto uninit_phy;673	}674 675	ret = phy_configure(dsi->phy, phy_cfg);676	if (ret < 0) {677		DRM_DEV_ERROR(dev, "Failed to configure DSI phy: %d\n", ret);678		goto uninit_phy;679	}680 681	ret = clk_prepare_enable(dsi->tx_esc_clk);682	if (ret < 0) {683		DRM_DEV_ERROR(dsi->dev, "Failed to enable tx_esc clk: %d\n",684			      ret);685		goto uninit_phy;686	}687	DRM_DEV_DEBUG_DRIVER(dsi->dev, "Enabled tx_esc clk @%lu Hz\n",688			     clk_get_rate(dsi->tx_esc_clk));689 690	ret = nwl_dsi_config_host(dsi);691	if (ret < 0) {692		DRM_DEV_ERROR(dev, "Failed to set up DSI: %d", ret);693		goto disable_clock;694	}695 696	ret = nwl_dsi_config_dpi(dsi);697	if (ret < 0) {698		DRM_DEV_ERROR(dev, "Failed to set up DPI: %d", ret);699		goto disable_clock;700	}701 702	ret = phy_power_on(dsi->phy);703	if (ret < 0) {704		DRM_DEV_ERROR(dev, "Failed to power on DPHY (%d)\n", ret);705		goto disable_clock;706	}707 708	ret = nwl_dsi_init_interrupts(dsi);709	if (ret < 0)710		goto power_off_phy;711 712	return ret;713 714power_off_phy:715	phy_power_off(dsi->phy);716disable_clock:717	clk_disable_unprepare(dsi->tx_esc_clk);718uninit_phy:719	phy_exit(dsi->phy);720 721	return ret;722}723 724static int nwl_dsi_disable(struct nwl_dsi *dsi)725{726	struct device *dev = dsi->dev;727 728	DRM_DEV_DEBUG_DRIVER(dev, "Disabling clocks and phy\n");729 730	phy_power_off(dsi->phy);731	phy_exit(dsi->phy);732 733	/* Disabling the clock before the phy breaks enabling dsi again */734	clk_disable_unprepare(dsi->tx_esc_clk);735 736	return 0;737}738 739static void740nwl_dsi_bridge_atomic_disable(struct drm_bridge *bridge,741			      struct drm_bridge_state *old_bridge_state)742{743	struct nwl_dsi *dsi = bridge_to_dsi(bridge);744	int ret;745 746	nwl_dsi_disable(dsi);747 748	ret = reset_control_assert(dsi->rst_dpi);749	if (ret < 0) {750		DRM_DEV_ERROR(dsi->dev, "Failed to assert DPI: %d\n", ret);751		return;752	}753	ret = reset_control_assert(dsi->rst_byte);754	if (ret < 0) {755		DRM_DEV_ERROR(dsi->dev, "Failed to assert ESC: %d\n", ret);756		return;757	}758	ret = reset_control_assert(dsi->rst_esc);759	if (ret < 0) {760		DRM_DEV_ERROR(dsi->dev, "Failed to assert BYTE: %d\n", ret);761		return;762	}763	ret = reset_control_assert(dsi->rst_pclk);764	if (ret < 0) {765		DRM_DEV_ERROR(dsi->dev, "Failed to assert PCLK: %d\n", ret);766		return;767	}768 769	clk_disable_unprepare(dsi->core_clk);770	clk_disable_unprepare(dsi->lcdif_clk);771 772	pm_runtime_put(dsi->dev);773}774 775static int nwl_dsi_get_dphy_params(struct nwl_dsi *dsi,776				   const struct drm_display_mode *mode,777				   union phy_configure_opts *phy_opts)778{779	unsigned long rate;780	int ret;781 782	if (dsi->lanes < 1 || dsi->lanes > 4)783		return -EINVAL;784 785	/*786	 * So far the DPHY spec minimal timings work for both mixel787	 * dphy and nwl dsi host788	 */789	ret = phy_mipi_dphy_get_default_config(mode->clock * 1000,790		mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes,791		&phy_opts->mipi_dphy);792	if (ret < 0)793		return ret;794 795	rate = clk_get_rate(dsi->tx_esc_clk);796	DRM_DEV_DEBUG_DRIVER(dsi->dev, "LP clk is @%lu Hz\n", rate);797	phy_opts->mipi_dphy.lp_clk_rate = rate;798 799	return 0;800}801 802static enum drm_mode_status803nwl_dsi_bridge_mode_valid(struct drm_bridge *bridge,804			  const struct drm_display_info *info,805			  const struct drm_display_mode *mode)806{807	struct nwl_dsi *dsi = bridge_to_dsi(bridge);808	int bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);809 810	if (mode->clock * bpp > 15000000 * dsi->lanes)811		return MODE_CLOCK_HIGH;812 813	if (mode->clock * bpp < 80000 * dsi->lanes)814		return MODE_CLOCK_LOW;815 816	return MODE_OK;817}818 819static int nwl_dsi_bridge_atomic_check(struct drm_bridge *bridge,820				       struct drm_bridge_state *bridge_state,821				       struct drm_crtc_state *crtc_state,822				       struct drm_connector_state *conn_state)823{824	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;825 826	/* At least LCDIF + NWL needs active high sync */827	adjusted_mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);828	adjusted_mode->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);829 830	/*831	 * Do a full modeset if crtc_state->active is changed to be true.832	 * This ensures our ->mode_set() is called to get the DSI controller833	 * and the PHY ready to send DCS commands, when only the connector's834	 * DPMS is brought out of "Off" status.835	 */836	if (crtc_state->active_changed && crtc_state->active)837		crtc_state->mode_changed = true;838 839	return 0;840}841 842static void843nwl_dsi_bridge_mode_set(struct drm_bridge *bridge,844			const struct drm_display_mode *mode,845			const struct drm_display_mode *adjusted_mode)846{847	struct nwl_dsi *dsi = bridge_to_dsi(bridge);848	struct device *dev = dsi->dev;849	union phy_configure_opts new_cfg;850	unsigned long phy_ref_rate;851	int ret;852 853	ret = nwl_dsi_get_dphy_params(dsi, adjusted_mode, &new_cfg);854	if (ret < 0)855		return;856 857	phy_ref_rate = clk_get_rate(dsi->phy_ref_clk);858	DRM_DEV_DEBUG_DRIVER(dev, "PHY at ref rate: %lu\n", phy_ref_rate);859	/* Save the new desired phy config */860	memcpy(&dsi->phy_cfg, &new_cfg, sizeof(new_cfg));861 862	drm_mode_copy(&dsi->mode, adjusted_mode);863	drm_mode_debug_printmodeline(adjusted_mode);864 865	if (pm_runtime_resume_and_get(dev) < 0)866		return;867 868	if (clk_prepare_enable(dsi->lcdif_clk) < 0)869		goto runtime_put;870	if (clk_prepare_enable(dsi->core_clk) < 0)871		goto runtime_put;872 873	/* Step 1 from DSI reset-out instructions */874	ret = reset_control_deassert(dsi->rst_pclk);875	if (ret < 0) {876		DRM_DEV_ERROR(dev, "Failed to deassert PCLK: %d\n", ret);877		goto runtime_put;878	}879 880	/* Step 2 from DSI reset-out instructions */881	nwl_dsi_mode_set(dsi);882 883	/* Step 3 from DSI reset-out instructions */884	ret = reset_control_deassert(dsi->rst_esc);885	if (ret < 0) {886		DRM_DEV_ERROR(dev, "Failed to deassert ESC: %d\n", ret);887		goto runtime_put;888	}889	ret = reset_control_deassert(dsi->rst_byte);890	if (ret < 0) {891		DRM_DEV_ERROR(dev, "Failed to deassert BYTE: %d\n", ret);892		goto runtime_put;893	}894 895	return;896 897runtime_put:898	pm_runtime_put_sync(dev);899}900 901static void902nwl_dsi_bridge_atomic_enable(struct drm_bridge *bridge,903			     struct drm_bridge_state *old_bridge_state)904{905	struct nwl_dsi *dsi = bridge_to_dsi(bridge);906	int ret;907 908	/* Step 5 from DSI reset-out instructions */909	ret = reset_control_deassert(dsi->rst_dpi);910	if (ret < 0)911		DRM_DEV_ERROR(dsi->dev, "Failed to deassert DPI: %d\n", ret);912}913 914static int nwl_dsi_bridge_attach(struct drm_bridge *bridge,915				 enum drm_bridge_attach_flags flags)916{917	struct nwl_dsi *dsi = bridge_to_dsi(bridge);918	struct drm_bridge *panel_bridge;919 920	panel_bridge = devm_drm_of_get_bridge(dsi->dev, dsi->dev->of_node, 1, 0);921	if (IS_ERR(panel_bridge))922		return PTR_ERR(panel_bridge);923 924	return drm_bridge_attach(bridge->encoder, panel_bridge, bridge, flags);925}926 927static u32 *nwl_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,928						 struct drm_bridge_state *bridge_state,929						 struct drm_crtc_state *crtc_state,930						 struct drm_connector_state *conn_state,931						 u32 output_fmt,932						 unsigned int *num_input_fmts)933{934	u32 *input_fmts, input_fmt;935 936	*num_input_fmts = 0;937 938	switch (output_fmt) {939	/* If MEDIA_BUS_FMT_FIXED is tested, return default bus format */940	case MEDIA_BUS_FMT_FIXED:941		input_fmt = MEDIA_BUS_FMT_RGB888_1X24;942		break;943	case MEDIA_BUS_FMT_RGB888_1X24:944	case MEDIA_BUS_FMT_RGB666_1X18:945	case MEDIA_BUS_FMT_RGB565_1X16:946		input_fmt = output_fmt;947		break;948	default:949		return NULL;950	}951 952	input_fmts = kcalloc(1, sizeof(*input_fmts), GFP_KERNEL);953	if (!input_fmts)954		return NULL;955	input_fmts[0] = input_fmt;956	*num_input_fmts = 1;957 958	return input_fmts;959}960 961static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = {962	.atomic_duplicate_state	= drm_atomic_helper_bridge_duplicate_state,963	.atomic_destroy_state	= drm_atomic_helper_bridge_destroy_state,964	.atomic_reset		= drm_atomic_helper_bridge_reset,965	.atomic_check		= nwl_dsi_bridge_atomic_check,966	.atomic_enable		= nwl_dsi_bridge_atomic_enable,967	.atomic_disable		= nwl_dsi_bridge_atomic_disable,968	.atomic_get_input_bus_fmts = nwl_bridge_atomic_get_input_bus_fmts,969	.mode_set		= nwl_dsi_bridge_mode_set,970	.mode_valid		= nwl_dsi_bridge_mode_valid,971	.attach			= nwl_dsi_bridge_attach,972};973 974static int nwl_dsi_parse_dt(struct nwl_dsi *dsi)975{976	struct platform_device *pdev = to_platform_device(dsi->dev);977	struct clk *clk;978	void __iomem *base;979	int ret;980 981	dsi->phy = devm_phy_get(dsi->dev, "dphy");982	if (IS_ERR(dsi->phy)) {983		ret = PTR_ERR(dsi->phy);984		if (ret != -EPROBE_DEFER)985			DRM_DEV_ERROR(dsi->dev, "Could not get PHY: %d\n", ret);986		return ret;987	}988 989	clk = devm_clk_get(dsi->dev, "lcdif");990	if (IS_ERR(clk)) {991		ret = PTR_ERR(clk);992		DRM_DEV_ERROR(dsi->dev, "Failed to get lcdif clock: %d\n",993			      ret);994		return ret;995	}996	dsi->lcdif_clk = clk;997 998	clk = devm_clk_get(dsi->dev, "core");999	if (IS_ERR(clk)) {1000		ret = PTR_ERR(clk);1001		DRM_DEV_ERROR(dsi->dev, "Failed to get core clock: %d\n",1002			      ret);1003		return ret;1004	}1005	dsi->core_clk = clk;1006 1007	clk = devm_clk_get(dsi->dev, "phy_ref");1008	if (IS_ERR(clk)) {1009		ret = PTR_ERR(clk);1010		DRM_DEV_ERROR(dsi->dev, "Failed to get phy_ref clock: %d\n",1011			      ret);1012		return ret;1013	}1014	dsi->phy_ref_clk = clk;1015 1016	clk = devm_clk_get(dsi->dev, "rx_esc");1017	if (IS_ERR(clk)) {1018		ret = PTR_ERR(clk);1019		DRM_DEV_ERROR(dsi->dev, "Failed to get rx_esc clock: %d\n",1020			      ret);1021		return ret;1022	}1023	dsi->rx_esc_clk = clk;1024 1025	clk = devm_clk_get(dsi->dev, "tx_esc");1026	if (IS_ERR(clk)) {1027		ret = PTR_ERR(clk);1028		DRM_DEV_ERROR(dsi->dev, "Failed to get tx_esc clock: %d\n",1029			      ret);1030		return ret;1031	}1032	dsi->tx_esc_clk = clk;1033 1034	dsi->mux = devm_mux_control_get(dsi->dev, NULL);1035	if (IS_ERR(dsi->mux)) {1036		ret = PTR_ERR(dsi->mux);1037		if (ret != -EPROBE_DEFER)1038			DRM_DEV_ERROR(dsi->dev, "Failed to get mux: %d\n", ret);1039		return ret;1040	}1041 1042	base = devm_platform_ioremap_resource(pdev, 0);1043	if (IS_ERR(base))1044		return PTR_ERR(base);1045 1046	dsi->regmap =1047		devm_regmap_init_mmio(dsi->dev, base, &nwl_dsi_regmap_config);1048	if (IS_ERR(dsi->regmap)) {1049		ret = PTR_ERR(dsi->regmap);1050		DRM_DEV_ERROR(dsi->dev, "Failed to create NWL DSI regmap: %d\n",1051			      ret);1052		return ret;1053	}1054 1055	dsi->irq = platform_get_irq(pdev, 0);1056	if (dsi->irq < 0) {1057		DRM_DEV_ERROR(dsi->dev, "Failed to get device IRQ: %d\n",1058			      dsi->irq);1059		return dsi->irq;1060	}1061 1062	dsi->rst_pclk = devm_reset_control_get_exclusive(dsi->dev, "pclk");1063	if (IS_ERR(dsi->rst_pclk)) {1064		DRM_DEV_ERROR(dsi->dev, "Failed to get pclk reset: %ld\n",1065			      PTR_ERR(dsi->rst_pclk));1066		return PTR_ERR(dsi->rst_pclk);1067	}1068	dsi->rst_byte = devm_reset_control_get_exclusive(dsi->dev, "byte");1069	if (IS_ERR(dsi->rst_byte)) {1070		DRM_DEV_ERROR(dsi->dev, "Failed to get byte reset: %ld\n",1071			      PTR_ERR(dsi->rst_byte));1072		return PTR_ERR(dsi->rst_byte);1073	}1074	dsi->rst_esc = devm_reset_control_get_exclusive(dsi->dev, "esc");1075	if (IS_ERR(dsi->rst_esc)) {1076		DRM_DEV_ERROR(dsi->dev, "Failed to get esc reset: %ld\n",1077			      PTR_ERR(dsi->rst_esc));1078		return PTR_ERR(dsi->rst_esc);1079	}1080	dsi->rst_dpi = devm_reset_control_get_exclusive(dsi->dev, "dpi");1081	if (IS_ERR(dsi->rst_dpi)) {1082		DRM_DEV_ERROR(dsi->dev, "Failed to get dpi reset: %ld\n",1083			      PTR_ERR(dsi->rst_dpi));1084		return PTR_ERR(dsi->rst_dpi);1085	}1086	return 0;1087}1088 1089static int nwl_dsi_select_input(struct nwl_dsi *dsi)1090{1091	struct device_node *remote;1092	u32 use_dcss = 1;1093	int ret;1094 1095	remote = of_graph_get_remote_node(dsi->dev->of_node, 0,1096					  NWL_DSI_ENDPOINT_LCDIF);1097	if (remote) {1098		use_dcss = 0;1099	} else {1100		remote = of_graph_get_remote_node(dsi->dev->of_node, 0,1101						  NWL_DSI_ENDPOINT_DCSS);1102		if (!remote) {1103			DRM_DEV_ERROR(dsi->dev,1104				      "No valid input endpoint found\n");1105			return -EINVAL;1106		}1107	}1108 1109	DRM_DEV_INFO(dsi->dev, "Using %s as input source\n",1110		     (use_dcss) ? "DCSS" : "LCDIF");1111	ret = mux_control_try_select(dsi->mux, use_dcss);1112	if (ret < 0)1113		DRM_DEV_ERROR(dsi->dev, "Failed to select input: %d\n", ret);1114 1115	of_node_put(remote);1116	return ret;1117}1118 1119static int nwl_dsi_deselect_input(struct nwl_dsi *dsi)1120{1121	int ret;1122 1123	ret = mux_control_deselect(dsi->mux);1124	if (ret < 0)1125		DRM_DEV_ERROR(dsi->dev, "Failed to deselect input: %d\n", ret);1126 1127	return ret;1128}1129 1130static const struct drm_bridge_timings nwl_dsi_timings = {1131	.input_bus_flags = DRM_BUS_FLAG_DE_LOW,1132};1133 1134static const struct of_device_id nwl_dsi_dt_ids[] = {1135	{ .compatible = "fsl,imx8mq-nwl-dsi", },1136	{ /* sentinel */ }1137};1138MODULE_DEVICE_TABLE(of, nwl_dsi_dt_ids);1139 1140static const struct soc_device_attribute nwl_dsi_quirks_match[] = {1141	{ .soc_id = "i.MX8MQ", .revision = "2.0",1142	  .data = (void *)E11418_HS_MODE_QUIRK },1143	{ /* sentinel. */ }1144};1145 1146static int nwl_dsi_probe(struct platform_device *pdev)1147{1148	struct device *dev = &pdev->dev;1149	const struct soc_device_attribute *attr;1150	struct nwl_dsi *dsi;1151	int ret;1152 1153	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);1154	if (!dsi)1155		return -ENOMEM;1156 1157	dsi->dev = dev;1158 1159	ret = nwl_dsi_parse_dt(dsi);1160	if (ret)1161		return ret;1162 1163	ret = devm_request_irq(dev, dsi->irq, nwl_dsi_irq_handler, 0,1164			       dev_name(dev), dsi);1165	if (ret < 0) {1166		DRM_DEV_ERROR(dev, "Failed to request IRQ %d: %d\n", dsi->irq,1167			      ret);1168		return ret;1169	}1170 1171	dsi->dsi_host.ops = &nwl_dsi_host_ops;1172	dsi->dsi_host.dev = dev;1173	ret = mipi_dsi_host_register(&dsi->dsi_host);1174	if (ret) {1175		DRM_DEV_ERROR(dev, "Failed to register MIPI host: %d\n", ret);1176		return ret;1177	}1178 1179	attr = soc_device_match(nwl_dsi_quirks_match);1180	if (attr)1181		dsi->quirks = (uintptr_t)attr->data;1182 1183	dsi->bridge.driver_private = dsi;1184	dsi->bridge.funcs = &nwl_dsi_bridge_funcs;1185	dsi->bridge.of_node = dev->of_node;1186	dsi->bridge.timings = &nwl_dsi_timings;1187 1188	dev_set_drvdata(dev, dsi);1189	pm_runtime_enable(dev);1190 1191	ret = nwl_dsi_select_input(dsi);1192	if (ret < 0) {1193		pm_runtime_disable(dev);1194		mipi_dsi_host_unregister(&dsi->dsi_host);1195		return ret;1196	}1197 1198	drm_bridge_add(&dsi->bridge);1199	return 0;1200}1201 1202static void nwl_dsi_remove(struct platform_device *pdev)1203{1204	struct nwl_dsi *dsi = platform_get_drvdata(pdev);1205 1206	nwl_dsi_deselect_input(dsi);1207	mipi_dsi_host_unregister(&dsi->dsi_host);1208	drm_bridge_remove(&dsi->bridge);1209	pm_runtime_disable(&pdev->dev);1210}1211 1212static struct platform_driver nwl_dsi_driver = {1213	.probe		= nwl_dsi_probe,1214	.remove_new	= nwl_dsi_remove,1215	.driver		= {1216		.of_match_table = nwl_dsi_dt_ids,1217		.name	= DRV_NAME,1218	},1219};1220 1221module_platform_driver(nwl_dsi_driver);1222 1223MODULE_AUTHOR("NXP Semiconductor");1224MODULE_AUTHOR("Purism SPC");1225MODULE_DESCRIPTION("Northwest Logic MIPI-DSI driver");1226MODULE_LICENSE("GPL"); /* GPLv2 or later */1227