| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Renesas SH-mobile MIPI DSI support | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of version 2 of the GNU General Public License as | 
					
						
							|  |  |  |  * published by the Free Software Foundation. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-08 20:34:43 -08:00
										 |  |  | #include <linux/bitmap.h>
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | #include <linux/clk.h>
 | 
					
						
							|  |  |  | #include <linux/delay.h>
 | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <linux/io.h>
 | 
					
						
							|  |  |  | #include <linux/platform_device.h>
 | 
					
						
							| 
									
										
										
										
											2010-12-27 10:23:05 +00:00
										 |  |  | #include <linux/pm_runtime.h>
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | #include <linux/slab.h>
 | 
					
						
							|  |  |  | #include <linux/string.h>
 | 
					
						
							|  |  |  | #include <linux/types.h>
 | 
					
						
							| 
									
										
										
										
											2011-07-03 16:17:28 -04:00
										 |  |  | #include <linux/module.h>
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <video/mipi_display.h>
 | 
					
						
							|  |  |  | #include <video/sh_mipi_dsi.h>
 | 
					
						
							|  |  |  | #include <video/sh_mobile_lcdc.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | #include "sh_mobile_lcdcfb.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-17 06:44:25 +00:00
										 |  |  | #define SYSCTRL		0x0000
 | 
					
						
							|  |  |  | #define SYSCONF		0x0004
 | 
					
						
							|  |  |  | #define TIMSET		0x0008
 | 
					
						
							|  |  |  | #define RESREQSET0	0x0018
 | 
					
						
							|  |  |  | #define RESREQSET1	0x001c
 | 
					
						
							|  |  |  | #define HSTTOVSET	0x0020
 | 
					
						
							|  |  |  | #define LPRTOVSET	0x0024
 | 
					
						
							|  |  |  | #define TATOVSET	0x0028
 | 
					
						
							|  |  |  | #define PRTOVSET	0x002c
 | 
					
						
							|  |  |  | #define DSICTRL		0x0030
 | 
					
						
							|  |  |  | #define DSIINTE		0x0060
 | 
					
						
							|  |  |  | #define PHYCTRL		0x0070
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | /* relative to linkbase */ | 
					
						
							|  |  |  | #define DTCTR		0x0000
 | 
					
						
							|  |  |  | #define VMCTR1		0x0020
 | 
					
						
							|  |  |  | #define VMCTR2		0x0024
 | 
					
						
							|  |  |  | #define VMLEN1		0x0028
 | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:05 -08:00
										 |  |  | #define VMLEN2		0x002c
 | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | #define CMTSRTREQ	0x0070
 | 
					
						
							|  |  |  | #define CMTSRTCTR	0x00d0
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */ | 
					
						
							|  |  |  | #define MAX_SH_MIPI_DSI 2
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct sh_mipi { | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | 	struct sh_mobile_lcdc_entity entity; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	void __iomem	*base; | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | 	void __iomem	*linkbase; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	struct clk	*dsit_clk; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:36 -08:00
										 |  |  | 	struct platform_device *pdev; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | #define to_sh_mipi(e)	container_of(e, struct sh_mipi, entity)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Protect the above array */ | 
					
						
							|  |  |  | static DEFINE_MUTEX(array_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct sh_mipi *sh_mipi_by_handle(int handle) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (handle >= ARRAY_SIZE(mipi_dsi) || handle < 0) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return mipi_dsi[handle]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd, | 
					
						
							|  |  |  | 			      u8 cmd, u8 param) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u32 data = (dsi_cmd << 24) | (cmd << 16) | (param << 8); | 
					
						
							|  |  |  | 	int cnt = 100; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* transmit a short packet to LCD panel */ | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | 	iowrite32(1 | data, mipi->linkbase + CMTSRTCTR); | 
					
						
							|  |  |  | 	iowrite32(1, mipi->linkbase + CMTSRTREQ); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | 	while ((ioread32(mipi->linkbase + CMTSRTREQ) & 1) && --cnt) | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		udelay(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return cnt ? 0 : -ETIMEDOUT; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define LCD_CHAN2MIPI(c) ((c) < LCDC_CHAN_MAINLCD || (c) > LCDC_CHAN_SUBLCD ? \
 | 
					
						
							|  |  |  | 				-EINVAL : (c) - 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int sh_mipi_dcs(int handle, u8 cmd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle)); | 
					
						
							|  |  |  | 	if (!mipi) | 
					
						
							|  |  |  | 		return -ENODEV; | 
					
						
							|  |  |  | 	return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE, cmd, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int sh_mipi_dcs_param(int handle, u8 cmd, u8 param) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle)); | 
					
						
							|  |  |  | 	if (!mipi) | 
					
						
							|  |  |  | 		return -ENODEV; | 
					
						
							|  |  |  | 	return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd, | 
					
						
							|  |  |  | 				  param); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * enable LCDC data tx, transition to LPS after completion of each HS | 
					
						
							|  |  |  | 	 * packet | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | 	iowrite32(0x00000002 | enable, mipi->linkbase + DTCTR); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void sh_mipi_shutdown(struct platform_device *pdev) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | 	struct sh_mipi *mipi = to_sh_mipi(platform_get_drvdata(pdev)); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	sh_mipi_dsi_enable(mipi, false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | static int sh_mipi_setup(struct sh_mipi *mipi, const struct fb_videomode *mode) | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	void __iomem *base = mipi->base; | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 	struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:34:55 -08:00
										 |  |  | 	u32 pctype, datatype, pixfmt, linelength, vmctr2; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:27 -08:00
										 |  |  | 	u32 tmp, top, bottom, delay, div; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:05 -08:00
										 |  |  | 	int bpp; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-03 07:20:04 +00:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Select data format. MIPI DSI is not hot-pluggable, so, we just use | 
					
						
							|  |  |  | 	 * the default videomode. If this ever becomes a problem, We'll have to | 
					
						
							|  |  |  | 	 * move this to mipi_display_on() above and use info->var.xres | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	switch (pdata->data_format) { | 
					
						
							|  |  |  | 	case MIPI_RGB888: | 
					
						
							|  |  |  | 		pctype = 0; | 
					
						
							|  |  |  | 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; | 
					
						
							|  |  |  | 		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		linelength = mode->xres * 3; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case MIPI_RGB565: | 
					
						
							|  |  |  | 		pctype = 1; | 
					
						
							|  |  |  | 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; | 
					
						
							|  |  |  | 		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		linelength = mode->xres * 2; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case MIPI_RGB666_LP: | 
					
						
							|  |  |  | 		pctype = 2; | 
					
						
							|  |  |  | 		datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; | 
					
						
							|  |  |  | 		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		linelength = mode->xres * 3; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case MIPI_RGB666: | 
					
						
							|  |  |  | 		pctype = 3; | 
					
						
							|  |  |  | 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; | 
					
						
							|  |  |  | 		pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		linelength = (mode->xres * 18 + 7) / 8; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case MIPI_BGR888: | 
					
						
							|  |  |  | 		pctype = 8; | 
					
						
							|  |  |  | 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; | 
					
						
							|  |  |  | 		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		linelength = mode->xres * 3; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case MIPI_BGR565: | 
					
						
							|  |  |  | 		pctype = 9; | 
					
						
							|  |  |  | 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; | 
					
						
							|  |  |  | 		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		linelength = mode->xres * 2; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case MIPI_BGR666_LP: | 
					
						
							|  |  |  | 		pctype = 0xa; | 
					
						
							|  |  |  | 		datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; | 
					
						
							|  |  |  | 		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		linelength = mode->xres * 3; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case MIPI_BGR666: | 
					
						
							|  |  |  | 		pctype = 0xb; | 
					
						
							|  |  |  | 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; | 
					
						
							|  |  |  | 		pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		linelength = (mode->xres * 18 + 7) / 8; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case MIPI_YUYV: | 
					
						
							|  |  |  | 		pctype = 4; | 
					
						
							|  |  |  | 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; | 
					
						
							|  |  |  | 		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		linelength = mode->xres * 2; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case MIPI_UYVY: | 
					
						
							|  |  |  | 		pctype = 5; | 
					
						
							|  |  |  | 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; | 
					
						
							|  |  |  | 		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		linelength = mode->xres * 2; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case MIPI_YUV420_L: | 
					
						
							|  |  |  | 		pctype = 6; | 
					
						
							|  |  |  | 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; | 
					
						
							|  |  |  | 		pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		linelength = (mode->xres * 12 + 7) / 8; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case MIPI_YUV420: | 
					
						
							|  |  |  | 		pctype = 7; | 
					
						
							|  |  |  | 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; | 
					
						
							|  |  |  | 		pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; | 
					
						
							|  |  |  | 		/* Length of U/V line */ | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		linelength = (mode->xres + 1) / 2; | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-08 20:34:43 -08:00
										 |  |  | 	if (!pdata->lane) | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/* reset DSI link */ | 
					
						
							| 
									
										
										
										
											2010-11-17 06:44:25 +00:00
										 |  |  | 	iowrite32(0x00000001, base + SYSCTRL); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */ | 
					
						
							|  |  |  | 	udelay(50); | 
					
						
							| 
									
										
										
										
											2010-11-17 06:44:25 +00:00
										 |  |  | 	iowrite32(0x00000000, base + SYSCTRL); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* setup DSI link */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * T_wakeup = 0x7000 | 
					
						
							|  |  |  | 	 * T_hs-trail = 3 | 
					
						
							|  |  |  | 	 * T_hs-prepare = 3 | 
					
						
							|  |  |  | 	 * T_clk-trail = 3 | 
					
						
							|  |  |  | 	 * T_clk-prepare = 2 | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2010-11-17 06:44:25 +00:00
										 |  |  | 	iowrite32(0x70003332, base + TIMSET); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/* no responses requested */ | 
					
						
							| 
									
										
										
										
											2010-11-17 06:44:25 +00:00
										 |  |  | 	iowrite32(0x00000000, base + RESREQSET0); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/* request response to packets of type 0x28 */ | 
					
						
							| 
									
										
										
										
											2010-11-17 06:44:25 +00:00
										 |  |  | 	iowrite32(0x00000100, base + RESREQSET1); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/* High-speed transmission timeout, default 0xffffffff */ | 
					
						
							| 
									
										
										
										
											2010-11-17 06:44:25 +00:00
										 |  |  | 	iowrite32(0x0fffffff, base + HSTTOVSET); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/* LP reception timeout, default 0xffffffff */ | 
					
						
							| 
									
										
										
										
											2010-11-17 06:44:25 +00:00
										 |  |  | 	iowrite32(0x0fffffff, base + LPRTOVSET); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/* Turn-around timeout, default 0xffffffff */ | 
					
						
							| 
									
										
										
										
											2010-11-17 06:44:25 +00:00
										 |  |  | 	iowrite32(0x0fffffff, base + TATOVSET); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/* Peripheral reset timeout, default 0xffffffff */ | 
					
						
							| 
									
										
										
										
											2010-11-17 06:44:25 +00:00
										 |  |  | 	iowrite32(0x0fffffff, base + PRTOVSET); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/* Interrupts not used, disable all */ | 
					
						
							|  |  |  | 	iowrite32(0, base + DSIINTE); | 
					
						
							|  |  |  | 	/* DSI-Tx bias on */ | 
					
						
							| 
									
										
										
										
											2010-11-17 06:44:25 +00:00
										 |  |  | 	iowrite32(0x00000001, base + PHYCTRL); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	udelay(200); | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:14 -08:00
										 |  |  | 	/* Deassert resets, power on */ | 
					
						
							| 
									
										
										
										
											2012-03-20 18:34:10 -07:00
										 |  |  | 	iowrite32(0x03070001 | pdata->phyctrl, base + PHYCTRL); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:56 -08:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Default = ULPS enable | | 
					
						
							|  |  |  | 	 *	Contention detection enabled | | 
					
						
							|  |  |  | 	 *	EoT packet transmission enable | | 
					
						
							|  |  |  | 	 *	CRC check enable | | 
					
						
							|  |  |  | 	 *	ECC check enable | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	bitmap_fill((unsigned long *)&tmp, pdata->lane); | 
					
						
							|  |  |  | 	tmp |= 0x00003700; | 
					
						
							|  |  |  | 	iowrite32(tmp, base + SYSCONF); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/* setup l-bridge */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Enable transmission of all packets, | 
					
						
							|  |  |  | 	 * transmit LPS after each HS packet completion | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | 	iowrite32(0x00000006, mipi->linkbase + DTCTR); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/* VSYNC width = 2 (<< 17) */ | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 	iowrite32((mode->vsync_len << pdata->vsynw_offset) | | 
					
						
							| 
									
										
										
										
											2010-12-29 08:12:29 +00:00
										 |  |  | 		  (pdata->clksrc << 16) | (pctype << 12) | datatype, | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | 		  mipi->linkbase + VMCTR1); | 
					
						
							| 
									
										
										
										
											2010-12-29 08:12:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Non-burst mode with sync pulses: VSE and HSE are output, | 
					
						
							|  |  |  | 	 * HSA period allowed, no commands in LP | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2011-11-08 20:34:55 -08:00
										 |  |  | 	vmctr2 = 0; | 
					
						
							|  |  |  | 	if (pdata->flags & SH_MIPI_DSI_VSEE) | 
					
						
							|  |  |  | 		vmctr2 |= 1 << 23; | 
					
						
							|  |  |  | 	if (pdata->flags & SH_MIPI_DSI_HSEE) | 
					
						
							|  |  |  | 		vmctr2 |= 1 << 22; | 
					
						
							|  |  |  | 	if (pdata->flags & SH_MIPI_DSI_HSAE) | 
					
						
							|  |  |  | 		vmctr2 |= 1 << 21; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:34:33 -08:00
										 |  |  | 	if (pdata->flags & SH_MIPI_DSI_BL2E) | 
					
						
							|  |  |  | 		vmctr2 |= 1 << 17; | 
					
						
							| 
									
										
										
										
											2010-12-29 08:12:29 +00:00
										 |  |  | 	if (pdata->flags & SH_MIPI_DSI_HSABM) | 
					
						
							| 
									
										
										
										
											2011-11-08 20:34:12 -08:00
										 |  |  | 		vmctr2 |= 1 << 5; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:34:01 -08:00
										 |  |  | 	if (pdata->flags & SH_MIPI_DSI_HBPBM) | 
					
						
							| 
									
										
										
										
											2011-11-08 20:34:12 -08:00
										 |  |  | 		vmctr2 |= 1 << 4; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:34:24 -08:00
										 |  |  | 	if (pdata->flags & SH_MIPI_DSI_HFPBM) | 
					
						
							|  |  |  | 		vmctr2 |= 1 << 3; | 
					
						
							| 
									
										
										
										
											2010-12-29 08:12:29 +00:00
										 |  |  | 	iowrite32(vmctr2, mipi->linkbase + VMCTR2); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:05 -08:00
										 |  |  | 	 * VMLEN1 = RGBLEN | HSALEN | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * see | 
					
						
							|  |  |  | 	 *  Video mode - Blanking Packet setting | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:05 -08:00
										 |  |  | 	top = linelength << 16; /* RGBLEN */ | 
					
						
							|  |  |  | 	bottom = 0x00000001; | 
					
						
							|  |  |  | 	if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */ | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		bottom = (pdata->lane * mode->hsync_len) - 10; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:05 -08:00
										 |  |  | 	iowrite32(top | bottom , mipi->linkbase + VMLEN1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * VMLEN2 = HBPLEN | HFPLEN | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * see | 
					
						
							|  |  |  | 	 *  Video mode - Blanking Packet setting | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	top	= 0x00010000; | 
					
						
							|  |  |  | 	bottom	= 0x00000001; | 
					
						
							|  |  |  | 	delay	= 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:27 -08:00
										 |  |  | 	div = 1;	/* HSbyteCLK is calculation base
 | 
					
						
							|  |  |  | 			 * HS4divCLK = HSbyteCLK/2 | 
					
						
							|  |  |  | 			 * HS6divCLK is not supported for now */ | 
					
						
							|  |  |  | 	if (pdata->flags & SH_MIPI_DSI_HS4divCLK) | 
					
						
							|  |  |  | 		div = 2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:05 -08:00
										 |  |  | 	if (pdata->flags & SH_MIPI_DSI_HFPBM) {	/* HBPLEN */ | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		top = mode->hsync_len + mode->left_margin; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:27 -08:00
										 |  |  | 		top = ((pdata->lane * top / div) - 10) << 16; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:05 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */ | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		bottom = mode->right_margin; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:27 -08:00
										 |  |  | 		bottom = (pdata->lane * bottom / div) - 12; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:05 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 	bpp = linelength / mode->xres; /* byte / pixel */ | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:27 -08:00
										 |  |  | 	if ((pdata->lane / div) > bpp) { | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 		tmp = mode->xres / bpp; /* output cycle */ | 
					
						
							|  |  |  | 		tmp = mode->xres - tmp; /* (input - output) cycle */ | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:05 -08:00
										 |  |  | 		delay = (pdata->lane * tmp); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	iowrite32(top | (bottom + delay) , mipi->linkbase + VMLEN2); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	msleep(5); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* setup LCD panel */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* cf. drivers/video/omap/lcd_mipid.c */ | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 	sh_mipi_dcs(pdata->channel, MIPI_DCS_EXIT_SLEEP_MODE); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	msleep(120); | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * [7] - Page Address Mode | 
					
						
							|  |  |  | 	 * [6] - Column Address Mode | 
					
						
							|  |  |  | 	 * [5] - Page / Column Address Mode | 
					
						
							|  |  |  | 	 * [4] - Display Device Line Refresh Order | 
					
						
							|  |  |  | 	 * [3] - RGB/BGR Order | 
					
						
							|  |  |  | 	 * [2] - Display Data Latch Data Order | 
					
						
							|  |  |  | 	 * [1] - Flip Horizontal | 
					
						
							|  |  |  | 	 * [0] - Flip Vertical | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 	sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_ADDRESS_MODE, 0x00); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	/* cf. set_data_lines() */ | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 	sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_PIXEL_FORMAT, | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 			  pixfmt << 4); | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 	sh_mipi_dcs(pdata->channel, MIPI_DCS_SET_DISPLAY_ON); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-08 20:36:07 -08:00
										 |  |  | 	/* Enable timeout counters */ | 
					
						
							|  |  |  | 	iowrite32(0x00000f00, base + DSICTRL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-18 12:26:50 +02:00
										 |  |  | static int mipi_display_on(struct sh_mobile_lcdc_entity *entity) | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:45 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | 	struct sh_mipi *mipi = to_sh_mipi(entity); | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:45 -08:00
										 |  |  | 	struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pm_runtime_get_sync(&mipi->pdev->dev); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = pdata->set_dot_clock(mipi->pdev, mipi->base, 1); | 
					
						
							|  |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		goto mipi_display_on_fail1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-14 12:21:17 +02:00
										 |  |  | 	ret = sh_mipi_setup(mipi, &entity->def_mode); | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:45 -08:00
										 |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		goto mipi_display_on_fail2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sh_mipi_dsi_enable(mipi, true); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-28 23:19:59 +01:00
										 |  |  | 	return SH_MOBILE_LCDC_DISPLAY_CONNECTED; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:45 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | mipi_display_on_fail1: | 
					
						
							|  |  |  | 	pm_runtime_put_sync(&mipi->pdev->dev); | 
					
						
							|  |  |  | mipi_display_on_fail2: | 
					
						
							|  |  |  | 	pdata->set_dot_clock(mipi->pdev, mipi->base, 0); | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:45 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | static void mipi_display_off(struct sh_mobile_lcdc_entity *entity) | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct sh_mipi *mipi = to_sh_mipi(entity); | 
					
						
							|  |  |  | 	struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:45 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	sh_mipi_dsi_enable(mipi, false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pdata->set_dot_clock(mipi->pdev, mipi->base, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pm_runtime_put_sync(&mipi->pdev->dev); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | static const struct sh_mobile_lcdc_entity_ops mipi_ops = { | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | 	.display_on = mipi_display_on, | 
					
						
							|  |  |  | 	.display_off = mipi_display_off, | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | static int __init sh_mipi_probe(struct platform_device *pdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct sh_mipi *mipi; | 
					
						
							|  |  |  | 	struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; | 
					
						
							|  |  |  | 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | 	struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	unsigned long rate, f_current; | 
					
						
							|  |  |  | 	int idx = pdev->id, ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | 	if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata) | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 		return -ENODEV; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:14 -08:00
										 |  |  | 	if (!pdata->set_dot_clock) | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	mutex_lock(&array_lock); | 
					
						
							|  |  |  | 	if (idx < 0) | 
					
						
							|  |  |  | 		for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++) | 
					
						
							|  |  |  | 			; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (idx == ARRAY_SIZE(mipi_dsi)) { | 
					
						
							|  |  |  | 		ret = -EBUSY; | 
					
						
							|  |  |  | 		goto efindslot; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mipi = kzalloc(sizeof(*mipi), GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!mipi) { | 
					
						
							|  |  |  | 		ret = -ENOMEM; | 
					
						
							|  |  |  | 		goto ealloc; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | 	mipi->entity.owner = THIS_MODULE; | 
					
						
							|  |  |  | 	mipi->entity.ops = &mipi_ops; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	if (!request_mem_region(res->start, resource_size(res), pdev->name)) { | 
					
						
							|  |  |  | 		dev_err(&pdev->dev, "MIPI register region already claimed\n"); | 
					
						
							|  |  |  | 		ret = -EBUSY; | 
					
						
							|  |  |  | 		goto ereqreg; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mipi->base = ioremap(res->start, resource_size(res)); | 
					
						
							|  |  |  | 	if (!mipi->base) { | 
					
						
							|  |  |  | 		ret = -ENOMEM; | 
					
						
							|  |  |  | 		goto emap; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | 	if (!request_mem_region(res2->start, resource_size(res2), pdev->name)) { | 
					
						
							|  |  |  | 		dev_err(&pdev->dev, "MIPI register region 2 already claimed\n"); | 
					
						
							|  |  |  | 		ret = -EBUSY; | 
					
						
							|  |  |  | 		goto ereqreg2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mipi->linkbase = ioremap(res2->start, resource_size(res2)); | 
					
						
							|  |  |  | 	if (!mipi->linkbase) { | 
					
						
							|  |  |  | 		ret = -ENOMEM; | 
					
						
							|  |  |  | 		goto emap2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:36 -08:00
										 |  |  | 	mipi->pdev = pdev; | 
					
						
							| 
									
										
										
										
											2010-12-27 10:23:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk"); | 
					
						
							|  |  |  | 	if (IS_ERR(mipi->dsit_clk)) { | 
					
						
							|  |  |  | 		ret = PTR_ERR(mipi->dsit_clk); | 
					
						
							|  |  |  | 		goto eclktget; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f_current = clk_get_rate(mipi->dsit_clk); | 
					
						
							|  |  |  | 	/* 80MHz required by the datasheet */ | 
					
						
							|  |  |  | 	rate = clk_round_rate(mipi->dsit_clk, 80000000); | 
					
						
							|  |  |  | 	if (rate > 0 && rate != f_current) | 
					
						
							|  |  |  | 		ret = clk_set_rate(mipi->dsit_clk, rate); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		ret = rate; | 
					
						
							|  |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		goto esettrate; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = clk_enable(mipi->dsit_clk); | 
					
						
							|  |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		goto eclkton; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mipi_dsi[idx] = mipi; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-27 10:23:05 +00:00
										 |  |  | 	pm_runtime_enable(&pdev->dev); | 
					
						
							|  |  |  | 	pm_runtime_resume(&pdev->dev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	mutex_unlock(&array_lock); | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | 	platform_set_drvdata(pdev, &mipi->entity); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | eclkton: | 
					
						
							|  |  |  | esettrate: | 
					
						
							|  |  |  | 	clk_put(mipi->dsit_clk); | 
					
						
							|  |  |  | eclktget: | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | 	iounmap(mipi->linkbase); | 
					
						
							|  |  |  | emap2: | 
					
						
							|  |  |  | 	release_mem_region(res2->start, resource_size(res2)); | 
					
						
							|  |  |  | ereqreg2: | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	iounmap(mipi->base); | 
					
						
							|  |  |  | emap: | 
					
						
							|  |  |  | 	release_mem_region(res->start, resource_size(res)); | 
					
						
							|  |  |  | ereqreg: | 
					
						
							|  |  |  | 	kfree(mipi); | 
					
						
							|  |  |  | ealloc: | 
					
						
							|  |  |  | efindslot: | 
					
						
							|  |  |  | 	mutex_unlock(&array_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-21 13:07:39 -08:00
										 |  |  | static int sh_mipi_remove(struct platform_device *pdev) | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | 	struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 
					
						
							| 
									
										
										
										
											2011-09-11 18:27:50 +02:00
										 |  |  | 	struct sh_mipi *mipi = to_sh_mipi(platform_get_drvdata(pdev)); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	int i, ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&array_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < ARRAY_SIZE(mipi_dsi) && mipi_dsi[i] != mipi; i++) | 
					
						
							|  |  |  | 		; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (i == ARRAY_SIZE(mipi_dsi)) { | 
					
						
							|  |  |  | 		ret = -EINVAL; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ret = 0; | 
					
						
							|  |  |  | 		mipi_dsi[i] = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_unlock(&array_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-27 10:23:05 +00:00
										 |  |  | 	pm_runtime_disable(&pdev->dev); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	clk_disable(mipi->dsit_clk); | 
					
						
							|  |  |  | 	clk_put(mipi->dsit_clk); | 
					
						
							| 
									
										
										
										
											2011-11-08 20:35:14 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-17 09:53:25 +00:00
										 |  |  | 	iounmap(mipi->linkbase); | 
					
						
							|  |  |  | 	if (res2) | 
					
						
							|  |  |  | 		release_mem_region(res2->start, resource_size(res2)); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	iounmap(mipi->base); | 
					
						
							|  |  |  | 	if (res) | 
					
						
							|  |  |  | 		release_mem_region(res->start, resource_size(res)); | 
					
						
							|  |  |  | 	kfree(mipi); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct platform_driver sh_mipi_driver = { | 
					
						
							| 
									
										
										
										
											2012-12-21 13:07:39 -08:00
										 |  |  | 	.remove		= sh_mipi_remove, | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 	.shutdown	= sh_mipi_shutdown, | 
					
						
							|  |  |  | 	.driver = { | 
					
						
							|  |  |  | 		.name	= "sh-mipi-dsi", | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-15 14:02:38 +01:00
										 |  |  | module_platform_driver_probe(sh_mipi_driver, sh_mipi_probe); | 
					
						
							| 
									
										
										
										
											2010-05-23 14:00:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | 
					
						
							|  |  |  | MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver"); | 
					
						
							|  |  |  | MODULE_LICENSE("GPL v2"); |