Linux Audio

Check our new training course

Loading...
v4.6
  1/*
  2 * Copyright © 2010 Intel Corporation
  3 *
  4 * Permission is hereby granted, free of charge, to any person obtaining a
  5 * copy of this software and associated documentation files (the "Software"),
  6 * to deal in the Software without restriction, including without limitation
  7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8 * and/or sell copies of the Software, and to permit persons to whom the
  9 * Software is furnished to do so, subject to the following conditions:
 10 *
 11 * The above copyright notice and this permission notice (including the next
 12 * paragraph) shall be included in all copies or substantial portions of the
 13 * Software.
 14 *
 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 21 * DEALINGS IN THE SOFTWARE.
 22 *
 23 * Authors:
 24 * Jackie Li<yaodong.li@intel.com>
 25 */
 26
 
 27#include <linux/freezer.h>
 
 28#include <video/mipi_display.h>
 29
 
 30#include "mdfld_dsi_output.h"
 31#include "mdfld_dsi_pkg_sender.h"
 32#include "mdfld_dsi_dpi.h"
 33
 34#define MDFLD_DSI_READ_MAX_COUNT		5000
 35
 36enum {
 37	MDFLD_DSI_PANEL_MODE_SLEEP = 0x1,
 38};
 39
 40enum {
 41	MDFLD_DSI_PKG_SENDER_FREE = 0x0,
 42	MDFLD_DSI_PKG_SENDER_BUSY = 0x1,
 43};
 44
 45static const char *const dsi_errors[] = {
 46	"RX SOT Error",
 47	"RX SOT Sync Error",
 48	"RX EOT Sync Error",
 49	"RX Escape Mode Entry Error",
 50	"RX LP TX Sync Error",
 51	"RX HS Receive Timeout Error",
 52	"RX False Control Error",
 53	"RX ECC Single Bit Error",
 54	"RX ECC Multibit Error",
 55	"RX Checksum Error",
 56	"RX DSI Data Type Not Recognised",
 57	"RX DSI VC ID Invalid",
 58	"TX False Control Error",
 59	"TX ECC Single Bit Error",
 60	"TX ECC Multibit Error",
 61	"TX Checksum Error",
 62	"TX DSI Data Type Not Recognised",
 63	"TX DSI VC ID invalid",
 64	"High Contention",
 65	"Low contention",
 66	"DPI FIFO Under run",
 67	"HS TX Timeout",
 68	"LP RX Timeout",
 69	"Turn Around ACK Timeout",
 70	"ACK With No Error",
 71	"RX Invalid TX Length",
 72	"RX Prot Violation",
 73	"HS Generic Write FIFO Full",
 74	"LP Generic Write FIFO Full",
 75	"Generic Read Data Avail"
 76	"Special Packet Sent",
 77	"Tearing Effect",
 78};
 79
 80static inline int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender,
 81						u32 mask)
 82{
 83	struct drm_device *dev = sender->dev;
 84	u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg;
 85	int retry = 0xffff;
 86
 87	while (retry--) {
 88		if ((mask & REG_READ(gen_fifo_stat_reg)) == mask)
 89			return 0;
 90		udelay(100);
 91	}
 92	DRM_ERROR("fifo is NOT empty 0x%08x\n", REG_READ(gen_fifo_stat_reg));
 93	return -EIO;
 94}
 95
 96static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
 97{
 98	return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(10) | BIT(18) |
 99						BIT(26) | BIT(27) | BIT(28)));
100}
101
102static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
103{
104	return wait_for_gen_fifo_empty(sender, (BIT(10) | BIT(26)));
105}
106
107static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
108{
109	return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(18)));
110}
111
112static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask)
113{
114	u32 intr_stat_reg = sender->mipi_intr_stat_reg;
115	struct drm_device *dev = sender->dev;
116
117	dev_dbg(sender->dev->dev, "Handling error 0x%08x\n", mask);
118
119	switch (mask) {
120	case BIT(0):
121	case BIT(1):
122	case BIT(2):
123	case BIT(3):
124	case BIT(4):
125	case BIT(5):
126	case BIT(6):
127	case BIT(7):
128	case BIT(8):
129	case BIT(9):
130	case BIT(10):
131	case BIT(11):
132	case BIT(12):
133	case BIT(13):
134		dev_dbg(sender->dev->dev, "No Action required\n");
135		break;
136	case BIT(14):
137		/*wait for all fifo empty*/
138		/*wait_for_all_fifos_empty(sender)*/
139		break;
140	case BIT(15):
141		dev_dbg(sender->dev->dev, "No Action required\n");
142		break;
143	case BIT(16):
144		break;
145	case BIT(17):
146		break;
147	case BIT(18):
148	case BIT(19):
149		dev_dbg(sender->dev->dev, "High/Low contention detected\n");
150		/*wait for contention recovery time*/
151		/*mdelay(10);*/
152		/*wait for all fifo empty*/
153		if (0)
154			wait_for_all_fifos_empty(sender);
155		break;
156	case BIT(20):
157		dev_dbg(sender->dev->dev, "No Action required\n");
158		break;
159	case BIT(21):
160		/*wait for all fifo empty*/
161		/*wait_for_all_fifos_empty(sender);*/
162		break;
163	case BIT(22):
164		break;
165	case BIT(23):
166	case BIT(24):
167	case BIT(25):
168	case BIT(26):
169	case BIT(27):
170		dev_dbg(sender->dev->dev, "HS Gen fifo full\n");
171		REG_WRITE(intr_stat_reg, mask);
172		wait_for_hs_fifos_empty(sender);
173		break;
174	case BIT(28):
175		dev_dbg(sender->dev->dev, "LP Gen fifo full\n");
176		REG_WRITE(intr_stat_reg, mask);
177		wait_for_lp_fifos_empty(sender);
178		break;
179	case BIT(29):
180	case BIT(30):
181	case BIT(31):
182		dev_dbg(sender->dev->dev, "No Action required\n");
183		break;
184	}
185
186	if (mask & REG_READ(intr_stat_reg))
187		dev_dbg(sender->dev->dev,
188				"Cannot clean interrupt 0x%08x\n", mask);
189	return 0;
190}
191
192static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender)
193{
194	struct drm_device *dev = sender->dev;
195	u32 intr_stat_reg = sender->mipi_intr_stat_reg;
196	u32 mask;
197	u32 intr_stat;
198	int i;
199	int err = 0;
200
201	intr_stat = REG_READ(intr_stat_reg);
202
203	for (i = 0; i < 32; i++) {
204		mask = (0x00000001UL) << i;
205		if (intr_stat & mask) {
206			dev_dbg(sender->dev->dev, "[DSI]: %s\n", dsi_errors[i]);
207			err = handle_dsi_error(sender, mask);
208			if (err)
209				DRM_ERROR("Cannot handle error\n");
210		}
211	}
212	return err;
213}
214
215static int send_short_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
216			u8 cmd, u8 param, bool hs)
217{
218	struct drm_device *dev = sender->dev;
219	u32 ctrl_reg;
220	u32 val;
221	u8 virtual_channel = 0;
222
223	if (hs) {
224		ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
225
226		/* FIXME: wait_for_hs_fifos_empty(sender); */
227	} else {
228		ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
229
230		/* FIXME: wait_for_lp_fifos_empty(sender); */
231	}
232
233	val = FLD_VAL(param, 23, 16) | FLD_VAL(cmd, 15, 8) |
234		FLD_VAL(virtual_channel, 7, 6) | FLD_VAL(data_type, 5, 0);
235
236	REG_WRITE(ctrl_reg, val);
237
238	return 0;
239}
240
241static int send_long_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
242			u8 *data, int len, bool hs)
243{
244	struct drm_device *dev = sender->dev;
245	u32 ctrl_reg;
246	u32 data_reg;
247	u32 val;
248	u8 *p;
249	u8 b1, b2, b3, b4;
250	u8 virtual_channel = 0;
251	int i;
252
253	if (hs) {
254		ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
255		data_reg = sender->mipi_hs_gen_data_reg;
256
257		/* FIXME: wait_for_hs_fifos_empty(sender); */
258	} else {
259		ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
260		data_reg = sender->mipi_lp_gen_data_reg;
261
262		/* FIXME: wait_for_lp_fifos_empty(sender); */
263	}
264
265	p = data;
266	for (i = 0; i < len / 4; i++) {
267		b1 = *p++;
268		b2 = *p++;
269		b3 = *p++;
270		b4 = *p++;
271
272		REG_WRITE(data_reg, b4 << 24 | b3 << 16 | b2 << 8 | b1);
273	}
274
275	i = len % 4;
276	if (i) {
277		b1 = 0; b2 = 0; b3 = 0;
278
279		switch (i) {
280		case 3:
281			b1 = *p++;
282			b2 = *p++;
283			b3 = *p++;
284			break;
285		case 2:
286			b1 = *p++;
287			b2 = *p++;
288			break;
289		case 1:
290			b1 = *p++;
291			break;
292		}
293
294		REG_WRITE(data_reg, b3 << 16 | b2 << 8 | b1);
295	}
296
297	val = FLD_VAL(len, 23, 8) | FLD_VAL(virtual_channel, 7, 6) |
298		FLD_VAL(data_type, 5, 0);
299
300	REG_WRITE(ctrl_reg, val);
301
302	return 0;
303}
304
305static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
306			u8 *data, u16 len)
307{
308	u8 cmd;
309
310	switch (data_type) {
311	case MIPI_DSI_DCS_SHORT_WRITE:
312	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
313	case MIPI_DSI_DCS_LONG_WRITE:
314		cmd = *data;
315		break;
316	default:
317		return 0;
318	}
319
320	/*this prevents other package sending while doing msleep*/
321	sender->status = MDFLD_DSI_PKG_SENDER_BUSY;
322
323	/*wait for 120 milliseconds in case exit_sleep_mode just be sent*/
324	if (unlikely(cmd == MIPI_DCS_ENTER_SLEEP_MODE)) {
325		/*TODO: replace it with msleep later*/
326		mdelay(120);
327	}
328
329	if (unlikely(cmd == MIPI_DCS_EXIT_SLEEP_MODE)) {
330		/*TODO: replace it with msleep later*/
331		mdelay(120);
332	}
333	return 0;
334}
335
336static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
337			u8 *data, u16 len)
338{
339	u8 cmd;
340
341	switch (data_type) {
342	case MIPI_DSI_DCS_SHORT_WRITE:
343	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
344	case MIPI_DSI_DCS_LONG_WRITE:
345		cmd = *data;
346		break;
347	default:
348		return 0;
349	}
350
351	/*update panel status*/
352	if (unlikely(cmd == MIPI_DCS_ENTER_SLEEP_MODE)) {
353		sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP;
354		/*TODO: replace it with msleep later*/
355		mdelay(120);
356	} else if (unlikely(cmd == MIPI_DCS_EXIT_SLEEP_MODE)) {
357		sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP;
358		/*TODO: replace it with msleep later*/
359		mdelay(120);
360	} else if (unlikely(cmd == MIPI_DCS_SOFT_RESET)) {
361		/*TODO: replace it with msleep later*/
362		mdelay(5);
363	}
364
365	sender->status = MDFLD_DSI_PKG_SENDER_FREE;
366
367	return 0;
368}
369
370static int send_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
371		u8 *data, u16 len, bool hs)
372{
373	int ret;
374
375	/*handle DSI error*/
376	ret = dsi_error_handler(sender);
377	if (ret) {
378		DRM_ERROR("Error handling failed\n");
379		return -EAGAIN;
380	}
381
382	/* send pkg */
383	if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) {
384		DRM_ERROR("sender is busy\n");
385		return -EAGAIN;
386	}
387
388	ret = send_pkg_prepare(sender, data_type, data, len);
389	if (ret) {
390		DRM_ERROR("send_pkg_prepare error\n");
391		return ret;
392	}
393
394	switch (data_type) {
395	case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
396	case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
397	case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
398	case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
399	case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
400	case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
401	case MIPI_DSI_DCS_SHORT_WRITE:
402	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
403	case MIPI_DSI_DCS_READ:
404		ret = send_short_pkg(sender, data_type, data[0], data[1], hs);
405		break;
406	case MIPI_DSI_GENERIC_LONG_WRITE:
407	case MIPI_DSI_DCS_LONG_WRITE:
408		ret = send_long_pkg(sender, data_type, data, len, hs);
409		break;
410	}
411
412	send_pkg_done(sender, data_type, data, len);
413
414	/*FIXME: should I query complete and fifo empty here?*/
415
416	return ret;
417}
418
419int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
420			u32 len, bool hs)
421{
422	unsigned long flags;
423
424	if (!sender || !data || !len) {
425		DRM_ERROR("Invalid parameters\n");
426		return -EINVAL;
427	}
428
429	spin_lock_irqsave(&sender->lock, flags);
430	send_pkg(sender, MIPI_DSI_DCS_LONG_WRITE, data, len, hs);
431	spin_unlock_irqrestore(&sender->lock, flags);
432
433	return 0;
434}
435
436int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
437			u8 param, u8 param_num, bool hs)
438{
439	u8 data[2];
440	unsigned long flags;
441	u8 data_type;
442
443	if (!sender) {
444		DRM_ERROR("Invalid parameter\n");
445		return -EINVAL;
446	}
447
448	data[0] = cmd;
449
450	if (param_num) {
451		data_type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
452		data[1] = param;
453	} else {
454		data_type = MIPI_DSI_DCS_SHORT_WRITE;
455		data[1] = 0;
456	}
457
458	spin_lock_irqsave(&sender->lock, flags);
459	send_pkg(sender, data_type, data, sizeof(data), hs);
460	spin_unlock_irqrestore(&sender->lock, flags);
461
462	return 0;
463}
464
465int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0,
466			u8 param1, u8 param_num, bool hs)
467{
468	u8 data[2];
469	unsigned long flags;
470	u8 data_type;
471
472	if (!sender || param_num > 2) {
473		DRM_ERROR("Invalid parameter\n");
474		return -EINVAL;
475	}
476
477	switch (param_num) {
478	case 0:
479		data_type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
480		data[0] = 0;
481		data[1] = 0;
482		break;
483	case 1:
484		data_type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
485		data[0] = param0;
486		data[1] = 0;
487		break;
488	case 2:
489		data_type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
490		data[0] = param0;
491		data[1] = param1;
492		break;
493	}
494
495	spin_lock_irqsave(&sender->lock, flags);
496	send_pkg(sender, data_type, data, sizeof(data), hs);
497	spin_unlock_irqrestore(&sender->lock, flags);
498
499	return 0;
500}
501
502int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
503			u32 len, bool hs)
504{
505	unsigned long flags;
506
507	if (!sender || !data || !len) {
508		DRM_ERROR("Invalid parameters\n");
509		return -EINVAL;
510	}
511
512	spin_lock_irqsave(&sender->lock, flags);
513	send_pkg(sender, MIPI_DSI_GENERIC_LONG_WRITE, data, len, hs);
514	spin_unlock_irqrestore(&sender->lock, flags);
515
516	return 0;
517}
518
519static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
520			u8 *data, u16 len, u32 *data_out, u16 len_out, bool hs)
521{
522	unsigned long flags;
523	struct drm_device *dev = sender->dev;
524	int i;
525	u32 gen_data_reg;
526	int retry = MDFLD_DSI_READ_MAX_COUNT;
527
528	if (!sender || !data_out || !len_out) {
529		DRM_ERROR("Invalid parameters\n");
530		return -EINVAL;
531	}
 
 
532
533	/**
534	 * do reading.
535	 * 0) send out generic read request
536	 * 1) polling read data avail interrupt
537	 * 2) read data
538	 */
539	spin_lock_irqsave(&sender->lock, flags);
540
541	REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
542
543	if ((REG_READ(sender->mipi_intr_stat_reg) & BIT(29)))
544		DRM_ERROR("Can NOT clean read data valid interrupt\n");
545
546	/*send out read request*/
547	send_pkg(sender, data_type, data, len, hs);
548
549	/*polling read data avail interrupt*/
550	while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & BIT(29))) {
551		udelay(100);
552		retry--;
553	}
554
555	if (!retry) {
556		spin_unlock_irqrestore(&sender->lock, flags);
557		return -ETIMEDOUT;
558	}
559
560	REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
561
562	/*read data*/
563	if (hs)
564		gen_data_reg = sender->mipi_hs_gen_data_reg;
565	else
566		gen_data_reg = sender->mipi_lp_gen_data_reg;
567
568	for (i = 0; i < len_out; i++)
569		*(data_out + i) = REG_READ(gen_data_reg);
570
571	spin_unlock_irqrestore(&sender->lock, flags);
572
573	return 0;
574}
575
576int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
577		u32 *data, u16 len, bool hs)
578{
579	if (!sender || !data || !len) {
580		DRM_ERROR("Invalid parameters\n");
581		return -EINVAL;
582	}
583
584	return __read_panel_data(sender, MIPI_DSI_DCS_READ, &cmd, 1,
585				data, len, hs);
586}
587
588int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
589								int pipe)
590{
591	struct mdfld_dsi_pkg_sender *pkg_sender;
592	struct mdfld_dsi_config *dsi_config =
593				mdfld_dsi_get_config(dsi_connector);
594	struct drm_device *dev = dsi_config->dev;
595	struct drm_psb_private *dev_priv = dev->dev_private;
596	const struct psb_offset *map = &dev_priv->regmap[pipe];
597	u32 mipi_val = 0;
598
599	if (!dsi_connector) {
600		DRM_ERROR("Invalid parameter\n");
601		return -EINVAL;
602	}
603
604	pkg_sender = dsi_connector->pkg_sender;
605
606	if (!pkg_sender || IS_ERR(pkg_sender)) {
607		pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender),
608								GFP_KERNEL);
609		if (!pkg_sender) {
610			DRM_ERROR("Create DSI pkg sender failed\n");
611			return -ENOMEM;
612		}
613		dsi_connector->pkg_sender = (void *)pkg_sender;
614	}
615
616	pkg_sender->dev = dev;
617	pkg_sender->dsi_connector = dsi_connector;
618	pkg_sender->pipe = pipe;
619	pkg_sender->pkg_num = 0;
620	pkg_sender->panel_mode = 0;
621	pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;
622
623	/*init regs*/
624	/* FIXME: should just copy the regmap ptr ? */
625	pkg_sender->dpll_reg = map->dpll;
626	pkg_sender->dspcntr_reg = map->cntr;
627	pkg_sender->pipeconf_reg = map->conf;
628	pkg_sender->dsplinoff_reg = map->linoff;
629	pkg_sender->dspsurf_reg = map->surf;
630	pkg_sender->pipestat_reg = map->status;
631
632	pkg_sender->mipi_intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
633	pkg_sender->mipi_lp_gen_data_reg = MIPI_LP_GEN_DATA_REG(pipe);
634	pkg_sender->mipi_hs_gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
635	pkg_sender->mipi_lp_gen_ctrl_reg = MIPI_LP_GEN_CTRL_REG(pipe);
636	pkg_sender->mipi_hs_gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
637	pkg_sender->mipi_gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
638	pkg_sender->mipi_data_addr_reg = MIPI_DATA_ADD_REG(pipe);
639	pkg_sender->mipi_data_len_reg = MIPI_DATA_LEN_REG(pipe);
640	pkg_sender->mipi_cmd_addr_reg = MIPI_CMD_ADD_REG(pipe);
641	pkg_sender->mipi_cmd_len_reg = MIPI_CMD_LEN_REG(pipe);
642
643	/*init lock*/
644	spin_lock_init(&pkg_sender->lock);
645
646	if (mdfld_get_panel_type(dev, pipe) != TC35876X) {
647		/**
648		 * For video mode, don't enable DPI timing output here,
649		 * will init the DPI timing output during mode setting.
650		 */
651		mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
652
653		if (pipe == 0)
654			mipi_val |= 0x2;
655
656		REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi_val);
657		REG_READ(MIPI_PORT_CONTROL(pipe));
658
659		/* do dsi controller init */
660		mdfld_dsi_controller_init(dsi_config, pipe);
661	}
662
663	return 0;
664}
665
666void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender)
667{
668	if (!sender || IS_ERR(sender))
669		return;
670
671	/*free*/
672	kfree(sender);
673}
674
675
v5.9
  1/*
  2 * Copyright © 2010 Intel Corporation
  3 *
  4 * Permission is hereby granted, free of charge, to any person obtaining a
  5 * copy of this software and associated documentation files (the "Software"),
  6 * to deal in the Software without restriction, including without limitation
  7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8 * and/or sell copies of the Software, and to permit persons to whom the
  9 * Software is furnished to do so, subject to the following conditions:
 10 *
 11 * The above copyright notice and this permission notice (including the next
 12 * paragraph) shall be included in all copies or substantial portions of the
 13 * Software.
 14 *
 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 21 * DEALINGS IN THE SOFTWARE.
 22 *
 23 * Authors:
 24 * Jackie Li<yaodong.li@intel.com>
 25 */
 26
 27#include <linux/delay.h>
 28#include <linux/freezer.h>
 29
 30#include <video/mipi_display.h>
 31
 32#include "mdfld_dsi_dpi.h"
 33#include "mdfld_dsi_output.h"
 34#include "mdfld_dsi_pkg_sender.h"
 
 35
 36#define MDFLD_DSI_READ_MAX_COUNT		5000
 37
 38enum {
 39	MDFLD_DSI_PANEL_MODE_SLEEP = 0x1,
 40};
 41
 42enum {
 43	MDFLD_DSI_PKG_SENDER_FREE = 0x0,
 44	MDFLD_DSI_PKG_SENDER_BUSY = 0x1,
 45};
 46
 47static const char *const dsi_errors[] = {
 48	"RX SOT Error",
 49	"RX SOT Sync Error",
 50	"RX EOT Sync Error",
 51	"RX Escape Mode Entry Error",
 52	"RX LP TX Sync Error",
 53	"RX HS Receive Timeout Error",
 54	"RX False Control Error",
 55	"RX ECC Single Bit Error",
 56	"RX ECC Multibit Error",
 57	"RX Checksum Error",
 58	"RX DSI Data Type Not Recognised",
 59	"RX DSI VC ID Invalid",
 60	"TX False Control Error",
 61	"TX ECC Single Bit Error",
 62	"TX ECC Multibit Error",
 63	"TX Checksum Error",
 64	"TX DSI Data Type Not Recognised",
 65	"TX DSI VC ID invalid",
 66	"High Contention",
 67	"Low contention",
 68	"DPI FIFO Under run",
 69	"HS TX Timeout",
 70	"LP RX Timeout",
 71	"Turn Around ACK Timeout",
 72	"ACK With No Error",
 73	"RX Invalid TX Length",
 74	"RX Prot Violation",
 75	"HS Generic Write FIFO Full",
 76	"LP Generic Write FIFO Full",
 77	"Generic Read Data Avail",
 78	"Special Packet Sent",
 79	"Tearing Effect",
 80};
 81
 82static inline int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender,
 83						u32 mask)
 84{
 85	struct drm_device *dev = sender->dev;
 86	u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg;
 87	int retry = 0xffff;
 88
 89	while (retry--) {
 90		if ((mask & REG_READ(gen_fifo_stat_reg)) == mask)
 91			return 0;
 92		udelay(100);
 93	}
 94	DRM_ERROR("fifo is NOT empty 0x%08x\n", REG_READ(gen_fifo_stat_reg));
 95	return -EIO;
 96}
 97
 98static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
 99{
100	return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(10) | BIT(18) |
101						BIT(26) | BIT(27) | BIT(28)));
102}
103
104static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
105{
106	return wait_for_gen_fifo_empty(sender, (BIT(10) | BIT(26)));
107}
108
109static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
110{
111	return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(18)));
112}
113
114static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask)
115{
116	u32 intr_stat_reg = sender->mipi_intr_stat_reg;
117	struct drm_device *dev = sender->dev;
118
119	dev_dbg(sender->dev->dev, "Handling error 0x%08x\n", mask);
120
121	switch (mask) {
122	case BIT(0):
123	case BIT(1):
124	case BIT(2):
125	case BIT(3):
126	case BIT(4):
127	case BIT(5):
128	case BIT(6):
129	case BIT(7):
130	case BIT(8):
131	case BIT(9):
132	case BIT(10):
133	case BIT(11):
134	case BIT(12):
135	case BIT(13):
136		dev_dbg(sender->dev->dev, "No Action required\n");
137		break;
138	case BIT(14):
139		/*wait for all fifo empty*/
140		/*wait_for_all_fifos_empty(sender)*/
141		break;
142	case BIT(15):
143		dev_dbg(sender->dev->dev, "No Action required\n");
144		break;
145	case BIT(16):
146		break;
147	case BIT(17):
148		break;
149	case BIT(18):
150	case BIT(19):
151		dev_dbg(sender->dev->dev, "High/Low contention detected\n");
152		/*wait for contention recovery time*/
153		/*mdelay(10);*/
154		/*wait for all fifo empty*/
155		if (0)
156			wait_for_all_fifos_empty(sender);
157		break;
158	case BIT(20):
159		dev_dbg(sender->dev->dev, "No Action required\n");
160		break;
161	case BIT(21):
162		/*wait for all fifo empty*/
163		/*wait_for_all_fifos_empty(sender);*/
164		break;
165	case BIT(22):
166		break;
167	case BIT(23):
168	case BIT(24):
169	case BIT(25):
170	case BIT(26):
171	case BIT(27):
172		dev_dbg(sender->dev->dev, "HS Gen fifo full\n");
173		REG_WRITE(intr_stat_reg, mask);
174		wait_for_hs_fifos_empty(sender);
175		break;
176	case BIT(28):
177		dev_dbg(sender->dev->dev, "LP Gen fifo full\n");
178		REG_WRITE(intr_stat_reg, mask);
179		wait_for_lp_fifos_empty(sender);
180		break;
181	case BIT(29):
182	case BIT(30):
183	case BIT(31):
184		dev_dbg(sender->dev->dev, "No Action required\n");
185		break;
186	}
187
188	if (mask & REG_READ(intr_stat_reg))
189		dev_dbg(sender->dev->dev,
190				"Cannot clean interrupt 0x%08x\n", mask);
191	return 0;
192}
193
194static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender)
195{
196	struct drm_device *dev = sender->dev;
197	u32 intr_stat_reg = sender->mipi_intr_stat_reg;
198	u32 mask;
199	u32 intr_stat;
200	int i;
201	int err = 0;
202
203	intr_stat = REG_READ(intr_stat_reg);
204
205	for (i = 0; i < 32; i++) {
206		mask = (0x00000001UL) << i;
207		if (intr_stat & mask) {
208			dev_dbg(sender->dev->dev, "[DSI]: %s\n", dsi_errors[i]);
209			err = handle_dsi_error(sender, mask);
210			if (err)
211				DRM_ERROR("Cannot handle error\n");
212		}
213	}
214	return err;
215}
216
217static int send_short_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
218			u8 cmd, u8 param, bool hs)
219{
220	struct drm_device *dev = sender->dev;
221	u32 ctrl_reg;
222	u32 val;
223	u8 virtual_channel = 0;
224
225	if (hs) {
226		ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
227
228		/* FIXME: wait_for_hs_fifos_empty(sender); */
229	} else {
230		ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
231
232		/* FIXME: wait_for_lp_fifos_empty(sender); */
233	}
234
235	val = FLD_VAL(param, 23, 16) | FLD_VAL(cmd, 15, 8) |
236		FLD_VAL(virtual_channel, 7, 6) | FLD_VAL(data_type, 5, 0);
237
238	REG_WRITE(ctrl_reg, val);
239
240	return 0;
241}
242
243static int send_long_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
244			u8 *data, int len, bool hs)
245{
246	struct drm_device *dev = sender->dev;
247	u32 ctrl_reg;
248	u32 data_reg;
249	u32 val;
250	u8 *p;
251	u8 b1, b2, b3, b4;
252	u8 virtual_channel = 0;
253	int i;
254
255	if (hs) {
256		ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
257		data_reg = sender->mipi_hs_gen_data_reg;
258
259		/* FIXME: wait_for_hs_fifos_empty(sender); */
260	} else {
261		ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
262		data_reg = sender->mipi_lp_gen_data_reg;
263
264		/* FIXME: wait_for_lp_fifos_empty(sender); */
265	}
266
267	p = data;
268	for (i = 0; i < len / 4; i++) {
269		b1 = *p++;
270		b2 = *p++;
271		b3 = *p++;
272		b4 = *p++;
273
274		REG_WRITE(data_reg, b4 << 24 | b3 << 16 | b2 << 8 | b1);
275	}
276
277	i = len % 4;
278	if (i) {
279		b1 = 0; b2 = 0; b3 = 0;
280
281		switch (i) {
282		case 3:
283			b1 = *p++;
284			b2 = *p++;
285			b3 = *p++;
286			break;
287		case 2:
288			b1 = *p++;
289			b2 = *p++;
290			break;
291		case 1:
292			b1 = *p++;
293			break;
294		}
295
296		REG_WRITE(data_reg, b3 << 16 | b2 << 8 | b1);
297	}
298
299	val = FLD_VAL(len, 23, 8) | FLD_VAL(virtual_channel, 7, 6) |
300		FLD_VAL(data_type, 5, 0);
301
302	REG_WRITE(ctrl_reg, val);
303
304	return 0;
305}
306
307static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
308			u8 *data, u16 len)
309{
310	u8 cmd;
311
312	switch (data_type) {
313	case MIPI_DSI_DCS_SHORT_WRITE:
314	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
315	case MIPI_DSI_DCS_LONG_WRITE:
316		cmd = *data;
317		break;
318	default:
319		return 0;
320	}
321
322	/*this prevents other package sending while doing msleep*/
323	sender->status = MDFLD_DSI_PKG_SENDER_BUSY;
324
325	/*wait for 120 milliseconds in case exit_sleep_mode just be sent*/
326	if (unlikely(cmd == MIPI_DCS_ENTER_SLEEP_MODE)) {
327		/*TODO: replace it with msleep later*/
328		mdelay(120);
329	}
330
331	if (unlikely(cmd == MIPI_DCS_EXIT_SLEEP_MODE)) {
332		/*TODO: replace it with msleep later*/
333		mdelay(120);
334	}
335	return 0;
336}
337
338static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
339			u8 *data, u16 len)
340{
341	u8 cmd;
342
343	switch (data_type) {
344	case MIPI_DSI_DCS_SHORT_WRITE:
345	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
346	case MIPI_DSI_DCS_LONG_WRITE:
347		cmd = *data;
348		break;
349	default:
350		return 0;
351	}
352
353	/*update panel status*/
354	if (unlikely(cmd == MIPI_DCS_ENTER_SLEEP_MODE)) {
355		sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP;
356		/*TODO: replace it with msleep later*/
357		mdelay(120);
358	} else if (unlikely(cmd == MIPI_DCS_EXIT_SLEEP_MODE)) {
359		sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP;
360		/*TODO: replace it with msleep later*/
361		mdelay(120);
362	} else if (unlikely(cmd == MIPI_DCS_SOFT_RESET)) {
363		/*TODO: replace it with msleep later*/
364		mdelay(5);
365	}
366
367	sender->status = MDFLD_DSI_PKG_SENDER_FREE;
368
369	return 0;
370}
371
372static int send_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
373		u8 *data, u16 len, bool hs)
374{
375	int ret;
376
377	/*handle DSI error*/
378	ret = dsi_error_handler(sender);
379	if (ret) {
380		DRM_ERROR("Error handling failed\n");
381		return -EAGAIN;
382	}
383
384	/* send pkg */
385	if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) {
386		DRM_ERROR("sender is busy\n");
387		return -EAGAIN;
388	}
389
390	ret = send_pkg_prepare(sender, data_type, data, len);
391	if (ret) {
392		DRM_ERROR("send_pkg_prepare error\n");
393		return ret;
394	}
395
396	switch (data_type) {
397	case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
398	case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
399	case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
400	case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
401	case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
402	case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
403	case MIPI_DSI_DCS_SHORT_WRITE:
404	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
405	case MIPI_DSI_DCS_READ:
406		ret = send_short_pkg(sender, data_type, data[0], data[1], hs);
407		break;
408	case MIPI_DSI_GENERIC_LONG_WRITE:
409	case MIPI_DSI_DCS_LONG_WRITE:
410		ret = send_long_pkg(sender, data_type, data, len, hs);
411		break;
412	}
413
414	send_pkg_done(sender, data_type, data, len);
415
416	/*FIXME: should I query complete and fifo empty here?*/
417
418	return ret;
419}
420
421int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
422			u32 len, bool hs)
423{
424	unsigned long flags;
425
426	if (!sender || !data || !len) {
427		DRM_ERROR("Invalid parameters\n");
428		return -EINVAL;
429	}
430
431	spin_lock_irqsave(&sender->lock, flags);
432	send_pkg(sender, MIPI_DSI_DCS_LONG_WRITE, data, len, hs);
433	spin_unlock_irqrestore(&sender->lock, flags);
434
435	return 0;
436}
437
438int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
439			u8 param, u8 param_num, bool hs)
440{
441	u8 data[2];
442	unsigned long flags;
443	u8 data_type;
444
445	if (!sender) {
446		DRM_ERROR("Invalid parameter\n");
447		return -EINVAL;
448	}
449
450	data[0] = cmd;
451
452	if (param_num) {
453		data_type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
454		data[1] = param;
455	} else {
456		data_type = MIPI_DSI_DCS_SHORT_WRITE;
457		data[1] = 0;
458	}
459
460	spin_lock_irqsave(&sender->lock, flags);
461	send_pkg(sender, data_type, data, sizeof(data), hs);
462	spin_unlock_irqrestore(&sender->lock, flags);
463
464	return 0;
465}
466
467int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0,
468			u8 param1, u8 param_num, bool hs)
469{
470	u8 data[2];
471	unsigned long flags;
472	u8 data_type;
473
474	if (!sender || param_num > 2) {
475		DRM_ERROR("Invalid parameter\n");
476		return -EINVAL;
477	}
478
479	switch (param_num) {
480	case 0:
481		data_type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
482		data[0] = 0;
483		data[1] = 0;
484		break;
485	case 1:
486		data_type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
487		data[0] = param0;
488		data[1] = 0;
489		break;
490	case 2:
491		data_type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
492		data[0] = param0;
493		data[1] = param1;
494		break;
495	}
496
497	spin_lock_irqsave(&sender->lock, flags);
498	send_pkg(sender, data_type, data, sizeof(data), hs);
499	spin_unlock_irqrestore(&sender->lock, flags);
500
501	return 0;
502}
503
504int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
505			u32 len, bool hs)
506{
507	unsigned long flags;
508
509	if (!sender || !data || !len) {
510		DRM_ERROR("Invalid parameters\n");
511		return -EINVAL;
512	}
513
514	spin_lock_irqsave(&sender->lock, flags);
515	send_pkg(sender, MIPI_DSI_GENERIC_LONG_WRITE, data, len, hs);
516	spin_unlock_irqrestore(&sender->lock, flags);
517
518	return 0;
519}
520
521static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
522			u8 *data, u16 len, u32 *data_out, u16 len_out, bool hs)
523{
524	unsigned long flags;
525	struct drm_device *dev;
526	int i;
527	u32 gen_data_reg;
528	int retry = MDFLD_DSI_READ_MAX_COUNT;
529
530	if (!sender || !data_out || !len_out) {
531		DRM_ERROR("Invalid parameters\n");
532		return -EINVAL;
533	}
534
535	dev = sender->dev;
536
537	/**
538	 * do reading.
539	 * 0) send out generic read request
540	 * 1) polling read data avail interrupt
541	 * 2) read data
542	 */
543	spin_lock_irqsave(&sender->lock, flags);
544
545	REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
546
547	if ((REG_READ(sender->mipi_intr_stat_reg) & BIT(29)))
548		DRM_ERROR("Can NOT clean read data valid interrupt\n");
549
550	/*send out read request*/
551	send_pkg(sender, data_type, data, len, hs);
552
553	/*polling read data avail interrupt*/
554	while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & BIT(29))) {
555		udelay(100);
556		retry--;
557	}
558
559	if (!retry) {
560		spin_unlock_irqrestore(&sender->lock, flags);
561		return -ETIMEDOUT;
562	}
563
564	REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
565
566	/*read data*/
567	if (hs)
568		gen_data_reg = sender->mipi_hs_gen_data_reg;
569	else
570		gen_data_reg = sender->mipi_lp_gen_data_reg;
571
572	for (i = 0; i < len_out; i++)
573		*(data_out + i) = REG_READ(gen_data_reg);
574
575	spin_unlock_irqrestore(&sender->lock, flags);
576
577	return 0;
578}
579
580int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
581		u32 *data, u16 len, bool hs)
582{
583	if (!sender || !data || !len) {
584		DRM_ERROR("Invalid parameters\n");
585		return -EINVAL;
586	}
587
588	return __read_panel_data(sender, MIPI_DSI_DCS_READ, &cmd, 1,
589				data, len, hs);
590}
591
592int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
593								int pipe)
594{
595	struct mdfld_dsi_pkg_sender *pkg_sender;
596	struct mdfld_dsi_config *dsi_config =
597				mdfld_dsi_get_config(dsi_connector);
598	struct drm_device *dev = dsi_config->dev;
599	struct drm_psb_private *dev_priv = dev->dev_private;
600	const struct psb_offset *map = &dev_priv->regmap[pipe];
601	u32 mipi_val = 0;
602
603	if (!dsi_connector) {
604		DRM_ERROR("Invalid parameter\n");
605		return -EINVAL;
606	}
607
608	pkg_sender = dsi_connector->pkg_sender;
609
610	if (!pkg_sender || IS_ERR(pkg_sender)) {
611		pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender),
612								GFP_KERNEL);
613		if (!pkg_sender) {
614			DRM_ERROR("Create DSI pkg sender failed\n");
615			return -ENOMEM;
616		}
617		dsi_connector->pkg_sender = (void *)pkg_sender;
618	}
619
620	pkg_sender->dev = dev;
621	pkg_sender->dsi_connector = dsi_connector;
622	pkg_sender->pipe = pipe;
623	pkg_sender->pkg_num = 0;
624	pkg_sender->panel_mode = 0;
625	pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;
626
627	/*init regs*/
628	/* FIXME: should just copy the regmap ptr ? */
629	pkg_sender->dpll_reg = map->dpll;
630	pkg_sender->dspcntr_reg = map->cntr;
631	pkg_sender->pipeconf_reg = map->conf;
632	pkg_sender->dsplinoff_reg = map->linoff;
633	pkg_sender->dspsurf_reg = map->surf;
634	pkg_sender->pipestat_reg = map->status;
635
636	pkg_sender->mipi_intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
637	pkg_sender->mipi_lp_gen_data_reg = MIPI_LP_GEN_DATA_REG(pipe);
638	pkg_sender->mipi_hs_gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
639	pkg_sender->mipi_lp_gen_ctrl_reg = MIPI_LP_GEN_CTRL_REG(pipe);
640	pkg_sender->mipi_hs_gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
641	pkg_sender->mipi_gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
642	pkg_sender->mipi_data_addr_reg = MIPI_DATA_ADD_REG(pipe);
643	pkg_sender->mipi_data_len_reg = MIPI_DATA_LEN_REG(pipe);
644	pkg_sender->mipi_cmd_addr_reg = MIPI_CMD_ADD_REG(pipe);
645	pkg_sender->mipi_cmd_len_reg = MIPI_CMD_LEN_REG(pipe);
646
647	/*init lock*/
648	spin_lock_init(&pkg_sender->lock);
649
650	if (mdfld_get_panel_type(dev, pipe) != TC35876X) {
651		/**
652		 * For video mode, don't enable DPI timing output here,
653		 * will init the DPI timing output during mode setting.
654		 */
655		mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
656
657		if (pipe == 0)
658			mipi_val |= 0x2;
659
660		REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi_val);
661		REG_READ(MIPI_PORT_CONTROL(pipe));
662
663		/* do dsi controller init */
664		mdfld_dsi_controller_init(dsi_config, pipe);
665	}
666
667	return 0;
668}
669
670void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender)
671{
672	if (!sender || IS_ERR(sender))
673		return;
674
675	/*free*/
676	kfree(sender);
677}
678
679