| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Taal DSI command mode panel | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2009 Nokia Corporation | 
					
						
							|  |  |  |  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or modify it | 
					
						
							|  |  |  |  * under the terms of the GNU General Public License version 2 as published by | 
					
						
							|  |  |  |  * the Free Software Foundation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, but WITHOUT | 
					
						
							|  |  |  |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
					
						
							|  |  |  |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | 
					
						
							|  |  |  |  * more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License along with | 
					
						
							|  |  |  |  * this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*#define DEBUG*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/module.h>
 | 
					
						
							|  |  |  | #include <linux/delay.h>
 | 
					
						
							|  |  |  | #include <linux/err.h>
 | 
					
						
							|  |  |  | #include <linux/jiffies.h>
 | 
					
						
							|  |  |  | #include <linux/sched.h>
 | 
					
						
							|  |  |  | #include <linux/backlight.h>
 | 
					
						
							|  |  |  | #include <linux/fb.h>
 | 
					
						
							|  |  |  | #include <linux/interrupt.h>
 | 
					
						
							|  |  |  | #include <linux/gpio.h>
 | 
					
						
							|  |  |  | #include <linux/workqueue.h>
 | 
					
						
							| 
									
										
											  
											
												include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files.  percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed.  Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability.  As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
  http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
  only the necessary includes are there.  ie. if only gfp is used,
  gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
  blocks and try to put the new include such that its order conforms
  to its surrounding.  It's put in the include block which contains
  core kernel includes, in the same order that the rest are ordered -
  alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
  doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
  because the file doesn't have fitting include block), it prints out
  an error message indicating which .h file needs to be added to the
  file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
   over 4000 files, deleting around 700 includes and adding ~480 gfp.h
   and ~3000 slab.h inclusions.  The script emitted errors for ~400
   files.
2. Each error was manually checked.  Some didn't need the inclusion,
   some needed manual addition while adding it to implementation .h or
   embedding .c file was more appropriate for others.  This step added
   inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
   from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
   e.g. lib/decompress_*.c used malloc/free() wrappers around slab
   APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
   editing them as sprinkling gfp.h and slab.h inclusions around .h
   files could easily lead to inclusion dependency hell.  Most gfp.h
   inclusion directives were ignored as stuff from gfp.h was usually
   wildly available and often used in preprocessor macros.  Each
   slab.h inclusion directive was examined and added manually as
   necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
   were fixed.  CONFIG_GCOV_KERNEL was turned off for all tests (as my
   distributed build env didn't work with gcov compiles) and a few
   more options had to be turned off depending on archs to make things
   build (like ipr on powerpc/64 which failed due to missing writeq).
   * x86 and x86_64 UP and SMP allmodconfig and a custom test config.
   * powerpc and powerpc64 SMP allmodconfig
   * sparc and sparc64 SMP allmodconfig
   * ia64 SMP allmodconfig
   * s390 SMP allmodconfig
   * alpha SMP allmodconfig
   * um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
   a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
											
										 
											2010-03-24 17:04:11 +09:00
										 |  |  | #include <linux/slab.h>
 | 
					
						
							| 
									
										
										
										
											2010-06-09 15:24:46 +03:00
										 |  |  | #include <linux/regulator/consumer.h>
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | #include <linux/mutex.h>
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <plat/display.h>
 | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | #include <plat/nokia-dsi-panel.h>
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* DSI Virtual channel. Hardcoded for now. */ | 
					
						
							|  |  |  | #define TCH 0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define DCS_READ_NUM_ERRORS	0x05
 | 
					
						
							|  |  |  | #define DCS_READ_POWER_MODE	0x0a
 | 
					
						
							|  |  |  | #define DCS_READ_MADCTL		0x0b
 | 
					
						
							|  |  |  | #define DCS_READ_PIXEL_FORMAT	0x0c
 | 
					
						
							|  |  |  | #define DCS_RDDSDR		0x0f
 | 
					
						
							|  |  |  | #define DCS_SLEEP_IN		0x10
 | 
					
						
							|  |  |  | #define DCS_SLEEP_OUT		0x11
 | 
					
						
							|  |  |  | #define DCS_DISPLAY_OFF		0x28
 | 
					
						
							|  |  |  | #define DCS_DISPLAY_ON		0x29
 | 
					
						
							|  |  |  | #define DCS_COLUMN_ADDR		0x2a
 | 
					
						
							|  |  |  | #define DCS_PAGE_ADDR		0x2b
 | 
					
						
							|  |  |  | #define DCS_MEMORY_WRITE	0x2c
 | 
					
						
							|  |  |  | #define DCS_TEAR_OFF		0x34
 | 
					
						
							|  |  |  | #define DCS_TEAR_ON		0x35
 | 
					
						
							|  |  |  | #define DCS_MEM_ACC_CTRL	0x36
 | 
					
						
							|  |  |  | #define DCS_PIXEL_FORMAT	0x3a
 | 
					
						
							|  |  |  | #define DCS_BRIGHTNESS		0x51
 | 
					
						
							|  |  |  | #define DCS_CTRL_DISPLAY	0x53
 | 
					
						
							|  |  |  | #define DCS_WRITE_CABC		0x55
 | 
					
						
							|  |  |  | #define DCS_READ_CABC		0x56
 | 
					
						
							|  |  |  | #define DCS_GET_ID1		0xda
 | 
					
						
							|  |  |  | #define DCS_GET_ID2		0xdb
 | 
					
						
							|  |  |  | #define DCS_GET_ID3		0xdc
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define TAAL_ESD_CHECK_PERIOD	msecs_to_jiffies(5000)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-13 10:57:52 +03:00
										 |  |  | static irqreturn_t taal_te_isr(int irq, void *data); | 
					
						
							|  |  |  | static void taal_te_timeout_work_callback(struct work_struct *work); | 
					
						
							| 
									
										
										
										
											2010-03-02 12:13:55 +02:00
										 |  |  | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-09 15:24:46 +03:00
										 |  |  | struct panel_regulator { | 
					
						
							|  |  |  | 	struct regulator *regulator; | 
					
						
							|  |  |  | 	const char *name; | 
					
						
							|  |  |  | 	int min_uV; | 
					
						
							|  |  |  | 	int max_uV; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void free_regulators(struct panel_regulator *regulators, int n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 		/* disable/put in reverse order */ | 
					
						
							|  |  |  | 		regulator_disable(regulators[n - i - 1].regulator); | 
					
						
							|  |  |  | 		regulator_put(regulators[n - i - 1].regulator); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int init_regulators(struct omap_dss_device *dssdev, | 
					
						
							|  |  |  | 			struct panel_regulator *regulators, int n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int r, i, v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < n; i++) { | 
					
						
							|  |  |  | 		struct regulator *reg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		reg = regulator_get(&dssdev->dev, regulators[i].name); | 
					
						
							|  |  |  | 		if (IS_ERR(reg)) { | 
					
						
							|  |  |  | 			dev_err(&dssdev->dev, "failed to get regulator %s\n", | 
					
						
							|  |  |  | 				regulators[i].name); | 
					
						
							|  |  |  | 			r = PTR_ERR(reg); | 
					
						
							|  |  |  | 			goto err; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* FIXME: better handling of fixed vs. variable regulators */ | 
					
						
							|  |  |  | 		v = regulator_get_voltage(reg); | 
					
						
							|  |  |  | 		if (v < regulators[i].min_uV || v > regulators[i].max_uV) { | 
					
						
							|  |  |  | 			r = regulator_set_voltage(reg, regulators[i].min_uV, | 
					
						
							|  |  |  | 						regulators[i].max_uV); | 
					
						
							|  |  |  | 			if (r) { | 
					
						
							|  |  |  | 				dev_err(&dssdev->dev, | 
					
						
							|  |  |  | 					"failed to set regulator %s voltage\n", | 
					
						
							|  |  |  | 					regulators[i].name); | 
					
						
							|  |  |  | 				regulator_put(reg); | 
					
						
							|  |  |  | 				goto err; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		r = regulator_enable(reg); | 
					
						
							|  |  |  | 		if (r) { | 
					
						
							|  |  |  | 			dev_err(&dssdev->dev, "failed to enable regulator %s\n", | 
					
						
							|  |  |  | 				regulators[i].name); | 
					
						
							|  |  |  | 			regulator_put(reg); | 
					
						
							|  |  |  | 			goto err; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		regulators[i].regulator = reg; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  | 	free_regulators(regulators, i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * struct panel_config - panel configuration | 
					
						
							|  |  |  |  * @name: panel name | 
					
						
							|  |  |  |  * @type: panel type | 
					
						
							|  |  |  |  * @timings: panel resolution | 
					
						
							|  |  |  |  * @sleep: various panel specific delays, passed to msleep() if non-zero | 
					
						
							|  |  |  |  * @reset_sequence: reset sequence timings, passed to udelay() if non-zero | 
					
						
							| 
									
										
										
										
											2010-06-09 15:24:46 +03:00
										 |  |  |  * @regulators: array of panel regulators | 
					
						
							|  |  |  |  * @num_regulators: number of regulators in the array | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  |  */ | 
					
						
							|  |  |  | struct panel_config { | 
					
						
							|  |  |  | 	const char *name; | 
					
						
							|  |  |  | 	int type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct omap_video_timings timings; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct { | 
					
						
							|  |  |  | 		unsigned int sleep_in; | 
					
						
							|  |  |  | 		unsigned int sleep_out; | 
					
						
							|  |  |  | 		unsigned int hw_reset; | 
					
						
							|  |  |  | 		unsigned int enable_te; | 
					
						
							|  |  |  | 	} sleep; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct { | 
					
						
							|  |  |  | 		unsigned int high; | 
					
						
							|  |  |  | 		unsigned int low; | 
					
						
							|  |  |  | 	} reset_sequence; | 
					
						
							| 
									
										
										
										
											2010-06-09 15:24:46 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	struct panel_regulator *regulators; | 
					
						
							|  |  |  | 	int num_regulators; | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  | 	PANEL_TAAL, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct panel_config panel_configs[] = { | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		.name		= "taal", | 
					
						
							|  |  |  | 		.type		= PANEL_TAAL, | 
					
						
							|  |  |  | 		.timings	= { | 
					
						
							|  |  |  | 			.x_res		= 864, | 
					
						
							|  |  |  | 			.y_res		= 480, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		.sleep		= { | 
					
						
							|  |  |  | 			.sleep_in	= 5, | 
					
						
							|  |  |  | 			.sleep_out	= 5, | 
					
						
							|  |  |  | 			.hw_reset	= 5, | 
					
						
							|  |  |  | 			.enable_te	= 100, /* possible panel bug */ | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		.reset_sequence	= { | 
					
						
							|  |  |  | 			.high		= 10, | 
					
						
							|  |  |  | 			.low		= 10, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | struct taal_data { | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	struct mutex lock; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	struct backlight_device *bldev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unsigned long	hw_guard_end;	/* next value of jiffies when we can
 | 
					
						
							|  |  |  | 					 * issue the next sleep in/out command | 
					
						
							|  |  |  | 					 */ | 
					
						
							|  |  |  | 	unsigned long	hw_guard_wait;	/* max guard time in jiffies */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct omap_dss_device *dssdev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bool enabled; | 
					
						
							|  |  |  | 	u8 rotate; | 
					
						
							|  |  |  | 	bool mirror; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bool te_enabled; | 
					
						
							| 
									
										
										
										
											2010-04-13 10:57:52 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	atomic_t do_update; | 
					
						
							|  |  |  | 	struct { | 
					
						
							|  |  |  | 		u16 x; | 
					
						
							|  |  |  | 		u16 y; | 
					
						
							|  |  |  | 		u16 w; | 
					
						
							|  |  |  | 		u16 h; | 
					
						
							|  |  |  | 	} update_region; | 
					
						
							|  |  |  | 	struct delayed_work te_timeout_work; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	bool use_dsi_bl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bool cabc_broken; | 
					
						
							|  |  |  | 	unsigned cabc_mode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bool intro_printed; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct workqueue_struct *esd_wq; | 
					
						
							|  |  |  | 	struct delayed_work esd_work; | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	struct panel_config *panel_config; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | static inline struct nokia_dsi_panel_data | 
					
						
							|  |  |  | *get_panel_data(const struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (struct nokia_dsi_panel_data *) dssdev->data; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | static void taal_esd_work(struct work_struct *work); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hw_guard_start(struct taal_data *td, int guard_msec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	td->hw_guard_wait = msecs_to_jiffies(guard_msec); | 
					
						
							|  |  |  | 	td->hw_guard_end = jiffies + td->hw_guard_wait; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hw_guard_wait(struct taal_data *td) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long wait = td->hw_guard_end - jiffies; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((long)wait > 0 && wait <= td->hw_guard_wait) { | 
					
						
							|  |  |  | 		set_current_state(TASK_UNINTERRUPTIBLE); | 
					
						
							|  |  |  | 		schedule_timeout(wait); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 	u8 buf[1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (r < 0) | 
					
						
							|  |  |  | 		return r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*data = buf[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_dcs_write_0(u8 dcs_cmd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return dsi_vc_dcs_write(TCH, &dcs_cmd, 1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_dcs_write_1(u8 dcs_cmd, u8 param) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u8 buf[2]; | 
					
						
							|  |  |  | 	buf[0] = dcs_cmd; | 
					
						
							|  |  |  | 	buf[1] = param; | 
					
						
							|  |  |  | 	return dsi_vc_dcs_write(TCH, buf, 2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_sleep_in(struct taal_data *td) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u8 cmd; | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hw_guard_wait(td); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmd = DCS_SLEEP_IN; | 
					
						
							|  |  |  | 	r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		return r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hw_guard_start(td, 120); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 	if (td->panel_config->sleep.sleep_in) | 
					
						
							|  |  |  | 		msleep(td->panel_config->sleep.sleep_in); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_sleep_out(struct taal_data *td) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hw_guard_wait(td); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = taal_dcs_write_0(DCS_SLEEP_OUT); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		return r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hw_guard_start(td, 120); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 	if (td->panel_config->sleep.sleep_out) | 
					
						
							|  |  |  | 		msleep(td->panel_config->sleep.sleep_out); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_get_id(u8 *id1, u8 *id2, u8 *id3) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = taal_dcs_read_1(DCS_GET_ID1, id1); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		return r; | 
					
						
							|  |  |  | 	r = taal_dcs_read_1(DCS_GET_ID2, id2); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		return r; | 
					
						
							|  |  |  | 	r = taal_dcs_read_1(DCS_GET_ID3, id3); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		return r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_set_addr_mode(u8 rotate, bool mirror) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 	u8 mode; | 
					
						
							|  |  |  | 	int b5, b6, b7; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = taal_dcs_read_1(DCS_READ_MADCTL, &mode); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		return r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (rotate) { | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 	case 0: | 
					
						
							|  |  |  | 		b7 = 0; | 
					
						
							|  |  |  | 		b6 = 0; | 
					
						
							|  |  |  | 		b5 = 0; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 1: | 
					
						
							|  |  |  | 		b7 = 0; | 
					
						
							|  |  |  | 		b6 = 1; | 
					
						
							|  |  |  | 		b5 = 1; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 2: | 
					
						
							|  |  |  | 		b7 = 1; | 
					
						
							|  |  |  | 		b6 = 1; | 
					
						
							|  |  |  | 		b5 = 0; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 3: | 
					
						
							|  |  |  | 		b7 = 1; | 
					
						
							|  |  |  | 		b6 = 0; | 
					
						
							|  |  |  | 		b5 = 1; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (mirror) | 
					
						
							|  |  |  | 		b6 = !b6; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mode &= ~((1<<7) | (1<<6) | (1<<5)); | 
					
						
							|  |  |  | 	mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 	u16 x1 = x; | 
					
						
							|  |  |  | 	u16 x2 = x + w - 1; | 
					
						
							|  |  |  | 	u16 y1 = y; | 
					
						
							|  |  |  | 	u16 y2 = y + h - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	u8 buf[5]; | 
					
						
							|  |  |  | 	buf[0] = DCS_COLUMN_ADDR; | 
					
						
							|  |  |  | 	buf[1] = (x1 >> 8) & 0xff; | 
					
						
							|  |  |  | 	buf[2] = (x1 >> 0) & 0xff; | 
					
						
							|  |  |  | 	buf[3] = (x2 >> 8) & 0xff; | 
					
						
							|  |  |  | 	buf[4] = (x2 >> 0) & 0xff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		return r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	buf[0] = DCS_PAGE_ADDR; | 
					
						
							|  |  |  | 	buf[1] = (y1 >> 8) & 0xff; | 
					
						
							|  |  |  | 	buf[2] = (y1 >> 0) & 0xff; | 
					
						
							|  |  |  | 	buf[3] = (y2 >> 8) & 0xff; | 
					
						
							|  |  |  | 	buf[4] = (y2 >> 0) & 0xff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		return r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dsi_vc_send_bta_sync(TCH); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_bl_update_status(struct backlight_device *dev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	int r; | 
					
						
							|  |  |  | 	int level; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (dev->props.fb_blank == FB_BLANK_UNBLANK && | 
					
						
							|  |  |  | 			dev->props.power == FB_BLANK_UNBLANK) | 
					
						
							|  |  |  | 		level = dev->props.brightness; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		level = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dev_dbg(&dssdev->dev, "update brightness to %d\n", level); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-15 16:41:07 +03:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	if (td->use_dsi_bl) { | 
					
						
							|  |  |  | 		if (td->enabled) { | 
					
						
							|  |  |  | 			dsi_bus_lock(); | 
					
						
							|  |  |  | 			r = taal_dcs_write_1(DCS_BRIGHTNESS, level); | 
					
						
							|  |  |  | 			dsi_bus_unlock(); | 
					
						
							| 
									
										
										
										
											2010-04-15 16:41:07 +03:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			r = 0; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 		if (!panel_data->set_backlight) | 
					
						
							| 
									
										
										
										
											2010-04-15 16:41:07 +03:00
										 |  |  | 			r = -EINVAL; | 
					
						
							|  |  |  | 		else | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 			r = panel_data->set_backlight(dssdev, level); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-15 16:41:07 +03:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return r; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_bl_get_intensity(struct backlight_device *dev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (dev->props.fb_blank == FB_BLANK_UNBLANK && | 
					
						
							|  |  |  | 			dev->props.power == FB_BLANK_UNBLANK) | 
					
						
							|  |  |  | 		return dev->props.brightness; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct backlight_ops taal_bl_ops = { | 
					
						
							|  |  |  | 	.get_brightness = taal_bl_get_intensity, | 
					
						
							|  |  |  | 	.update_status  = taal_bl_update_status, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void taal_get_timings(struct omap_dss_device *dssdev, | 
					
						
							|  |  |  | 			struct omap_video_timings *timings) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	*timings = dssdev->panel.timings; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void taal_get_resolution(struct omap_dss_device *dssdev, | 
					
						
							|  |  |  | 		u16 *xres, u16 *yres) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (td->rotate == 0 || td->rotate == 2) { | 
					
						
							|  |  |  | 		*xres = dssdev->panel.timings.x_res; | 
					
						
							|  |  |  | 		*yres = dssdev->panel.timings.y_res; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		*yres = dssdev->panel.timings.x_res; | 
					
						
							|  |  |  | 		*xres = dssdev->panel.timings.y_res; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t taal_num_errors_show(struct device *dev, | 
					
						
							|  |  |  | 		struct device_attribute *attr, char *buf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct omap_dss_device *dssdev = to_dss_device(dev); | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							|  |  |  | 	u8 errors; | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-28 11:15:18 +03:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	if (td->enabled) { | 
					
						
							|  |  |  | 		dsi_bus_lock(); | 
					
						
							|  |  |  | 		r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); | 
					
						
							|  |  |  | 		dsi_bus_unlock(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		r = -ENODEV; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-28 11:15:18 +03:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	if (r) | 
					
						
							|  |  |  | 		return r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return snprintf(buf, PAGE_SIZE, "%d\n", errors); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t taal_hw_revision_show(struct device *dev, | 
					
						
							|  |  |  | 		struct device_attribute *attr, char *buf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct omap_dss_device *dssdev = to_dss_device(dev); | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							|  |  |  | 	u8 id1, id2, id3; | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-28 11:15:18 +03:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	if (td->enabled) { | 
					
						
							|  |  |  | 		dsi_bus_lock(); | 
					
						
							|  |  |  | 		r = taal_get_id(&id1, &id2, &id3); | 
					
						
							|  |  |  | 		dsi_bus_unlock(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		r = -ENODEV; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-28 11:15:18 +03:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	if (r) | 
					
						
							|  |  |  | 		return r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char *cabc_modes[] = { | 
					
						
							|  |  |  | 	"off",		/* used also always when CABC is not supported */ | 
					
						
							|  |  |  | 	"ui", | 
					
						
							|  |  |  | 	"still-image", | 
					
						
							|  |  |  | 	"moving-image", | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t show_cabc_mode(struct device *dev, | 
					
						
							|  |  |  | 		struct device_attribute *attr, | 
					
						
							|  |  |  | 		char *buf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct omap_dss_device *dssdev = to_dss_device(dev); | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							|  |  |  | 	const char *mode_str; | 
					
						
							|  |  |  | 	int mode; | 
					
						
							|  |  |  | 	int len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mode = td->cabc_mode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mode_str = "unknown"; | 
					
						
							|  |  |  | 	if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes)) | 
					
						
							|  |  |  | 		mode_str = cabc_modes[mode]; | 
					
						
							|  |  |  | 	len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t store_cabc_mode(struct device *dev, | 
					
						
							|  |  |  | 		struct device_attribute *attr, | 
					
						
							|  |  |  | 		const char *buf, size_t count) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct omap_dss_device *dssdev = to_dss_device(dev); | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) { | 
					
						
							|  |  |  | 		if (sysfs_streq(cabc_modes[i], buf)) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (i == ARRAY_SIZE(cabc_modes)) | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-28 11:15:18 +03:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	if (td->enabled) { | 
					
						
							|  |  |  | 		dsi_bus_lock(); | 
					
						
							|  |  |  | 		if (!td->cabc_broken) | 
					
						
							|  |  |  | 			taal_dcs_write_1(DCS_WRITE_CABC, i); | 
					
						
							|  |  |  | 		dsi_bus_unlock(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	td->cabc_mode = i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-28 11:15:18 +03:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	return count; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ssize_t show_cabc_available_modes(struct device *dev, | 
					
						
							|  |  |  | 		struct device_attribute *attr, | 
					
						
							|  |  |  | 		char *buf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int len; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0, len = 0; | 
					
						
							|  |  |  | 	     len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++) | 
					
						
							|  |  |  | 		len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s", | 
					
						
							|  |  |  | 			i ? " " : "", cabc_modes[i], | 
					
						
							|  |  |  | 			i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : ""); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return len < PAGE_SIZE ? len : PAGE_SIZE - 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL); | 
					
						
							|  |  |  | static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL); | 
					
						
							|  |  |  | static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, | 
					
						
							|  |  |  | 		show_cabc_mode, store_cabc_mode); | 
					
						
							|  |  |  | static DEVICE_ATTR(cabc_available_modes, S_IRUGO, | 
					
						
							|  |  |  | 		show_cabc_available_modes, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct attribute *taal_attrs[] = { | 
					
						
							|  |  |  | 	&dev_attr_num_dsi_errors.attr, | 
					
						
							|  |  |  | 	&dev_attr_hw_revision.attr, | 
					
						
							|  |  |  | 	&dev_attr_cabc_mode.attr, | 
					
						
							|  |  |  | 	&dev_attr_cabc_available_modes.attr, | 
					
						
							|  |  |  | 	NULL, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct attribute_group taal_attr_group = { | 
					
						
							|  |  |  | 	.attrs = taal_attrs, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 12:25:59 +03:00
										 |  |  | static void taal_hw_reset(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (panel_data->reset_gpio == -1) | 
					
						
							| 
									
										
										
										
											2010-04-09 12:25:59 +03:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	gpio_set_value(panel_data->reset_gpio, 1); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 	if (td->panel_config->reset_sequence.high) | 
					
						
							|  |  |  | 		udelay(td->panel_config->reset_sequence.high); | 
					
						
							| 
									
										
										
										
											2010-04-09 12:25:59 +03:00
										 |  |  | 	/* reset the panel */ | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	gpio_set_value(panel_data->reset_gpio, 0); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 	/* assert reset */ | 
					
						
							|  |  |  | 	if (td->panel_config->reset_sequence.low) | 
					
						
							|  |  |  | 		udelay(td->panel_config->reset_sequence.low); | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	gpio_set_value(panel_data->reset_gpio, 1); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 	/* wait after releasing reset */ | 
					
						
							|  |  |  | 	if (td->panel_config->sleep.hw_reset) | 
					
						
							|  |  |  | 		msleep(td->panel_config->sleep.hw_reset); | 
					
						
							| 
									
										
										
										
											2010-04-09 12:25:59 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | static int taal_probe(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-17 16:39:44 -05:00
										 |  |  | 	struct backlight_properties props; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	struct taal_data *td; | 
					
						
							|  |  |  | 	struct backlight_device *bldev; | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 	struct panel_config *panel_config = NULL; | 
					
						
							|  |  |  | 	int r, i; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	dev_dbg(&dssdev->dev, "probe\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	if (!panel_data || !panel_data->name) { | 
					
						
							|  |  |  | 		r = -EINVAL; | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 	for (i = 0; i < ARRAY_SIZE(panel_configs); i++) { | 
					
						
							|  |  |  | 		if (strcmp(panel_data->name, panel_configs[i].name) == 0) { | 
					
						
							|  |  |  | 			panel_config = &panel_configs[i]; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!panel_config) { | 
					
						
							|  |  |  | 		r = -EINVAL; | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	dssdev->panel.config = OMAP_DSS_LCD_TFT; | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 	dssdev->panel.timings = panel_config->timings; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	dssdev->ctrl.pixel_size = 24; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	td = kzalloc(sizeof(*td), GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!td) { | 
					
						
							|  |  |  | 		r = -ENOMEM; | 
					
						
							| 
									
										
										
										
											2010-04-15 12:24:36 +03:00
										 |  |  | 		goto err; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	td->dssdev = dssdev; | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 	td->panel_config = panel_config; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_init(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-13 10:57:52 +03:00
										 |  |  | 	atomic_set(&td->do_update, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-09 15:24:46 +03:00
										 |  |  | 	r = init_regulators(dssdev, panel_config->regulators, | 
					
						
							|  |  |  | 			panel_config->num_regulators); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		goto err_reg; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	td->esd_wq = create_singlethread_workqueue("taal_esd"); | 
					
						
							|  |  |  | 	if (td->esd_wq == NULL) { | 
					
						
							|  |  |  | 		dev_err(&dssdev->dev, "can't create ESD workqueue\n"); | 
					
						
							|  |  |  | 		r = -ENOMEM; | 
					
						
							| 
									
										
										
										
											2010-04-15 12:24:36 +03:00
										 |  |  | 		goto err_wq; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dev_set_drvdata(&dssdev->dev, td); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 12:25:59 +03:00
										 |  |  | 	taal_hw_reset(dssdev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	/* if no platform set_backlight() defined, presume DSI backlight
 | 
					
						
							|  |  |  | 	 * control */ | 
					
						
							| 
									
										
										
										
											2010-02-17 16:39:44 -05:00
										 |  |  | 	memset(&props, 0, sizeof(struct backlight_properties)); | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	if (!panel_data->set_backlight) | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 		td->use_dsi_bl = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-17 16:39:44 -05:00
										 |  |  | 	if (td->use_dsi_bl) | 
					
						
							|  |  |  | 		props.max_brightness = 255; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		props.max_brightness = 127; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	bldev = backlight_device_register("taal", &dssdev->dev, dssdev, | 
					
						
							| 
									
										
										
										
											2010-02-17 16:39:44 -05:00
										 |  |  | 					  &taal_bl_ops, &props); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	if (IS_ERR(bldev)) { | 
					
						
							|  |  |  | 		r = PTR_ERR(bldev); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:24:36 +03:00
										 |  |  | 		goto err_bl; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	td->bldev = bldev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bldev->props.fb_blank = FB_BLANK_UNBLANK; | 
					
						
							|  |  |  | 	bldev->props.power = FB_BLANK_UNBLANK; | 
					
						
							| 
									
										
										
										
											2010-02-17 16:39:44 -05:00
										 |  |  | 	if (td->use_dsi_bl) | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 		bldev->props.brightness = 255; | 
					
						
							| 
									
										
										
										
											2010-02-17 16:39:44 -05:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 		bldev->props.brightness = 127; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	taal_bl_update_status(bldev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	if (panel_data->use_ext_te) { | 
					
						
							|  |  |  | 		int gpio = panel_data->ext_te_gpio; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		r = gpio_request(gpio, "taal irq"); | 
					
						
							|  |  |  | 		if (r) { | 
					
						
							|  |  |  | 			dev_err(&dssdev->dev, "GPIO request failed\n"); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:24:36 +03:00
										 |  |  | 			goto err_gpio; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		gpio_direction_input(gpio); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		r = request_irq(gpio_to_irq(gpio), taal_te_isr, | 
					
						
							|  |  |  | 				IRQF_DISABLED | IRQF_TRIGGER_RISING, | 
					
						
							|  |  |  | 				"taal vsync", dssdev); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (r) { | 
					
						
							|  |  |  | 			dev_err(&dssdev->dev, "IRQ request failed\n"); | 
					
						
							|  |  |  | 			gpio_free(gpio); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:24:36 +03:00
										 |  |  | 			goto err_irq; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-13 10:57:52 +03:00
										 |  |  | 		INIT_DELAYED_WORK_DEFERRABLE(&td->te_timeout_work, | 
					
						
							|  |  |  | 					taal_te_timeout_work_callback); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-13 10:57:52 +03:00
										 |  |  | 		dev_dbg(&dssdev->dev, "Using GPIO TE\n"); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); | 
					
						
							|  |  |  | 	if (r) { | 
					
						
							|  |  |  | 		dev_err(&dssdev->dev, "failed to create sysfs files\n"); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:24:36 +03:00
										 |  |  | 		goto err_sysfs; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2010-04-15 12:24:36 +03:00
										 |  |  | err_sysfs: | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	if (panel_data->use_ext_te) | 
					
						
							|  |  |  | 		free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:24:36 +03:00
										 |  |  | err_irq: | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	if (panel_data->use_ext_te) | 
					
						
							|  |  |  | 		gpio_free(panel_data->ext_te_gpio); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:24:36 +03:00
										 |  |  | err_gpio: | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	backlight_device_unregister(bldev); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:24:36 +03:00
										 |  |  | err_bl: | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	destroy_workqueue(td->esd_wq); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:24:36 +03:00
										 |  |  | err_wq: | 
					
						
							| 
									
										
										
										
											2010-06-09 15:24:46 +03:00
										 |  |  | 	free_regulators(panel_config->regulators, panel_config->num_regulators); | 
					
						
							|  |  |  | err_reg: | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	kfree(td); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:24:36 +03:00
										 |  |  | err: | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void taal_remove(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	struct backlight_device *bldev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dev_dbg(&dssdev->dev, "remove\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	if (panel_data->use_ext_te) { | 
					
						
							|  |  |  | 		int gpio = panel_data->ext_te_gpio; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 		free_irq(gpio_to_irq(gpio), dssdev); | 
					
						
							|  |  |  | 		gpio_free(gpio); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bldev = td->bldev; | 
					
						
							|  |  |  | 	bldev->props.power = FB_BLANK_POWERDOWN; | 
					
						
							|  |  |  | 	taal_bl_update_status(bldev); | 
					
						
							|  |  |  | 	backlight_device_unregister(bldev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 10:23:46 +03:00
										 |  |  | 	cancel_delayed_work(&td->esd_work); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	destroy_workqueue(td->esd_wq); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 12:25:59 +03:00
										 |  |  | 	/* reset, to be sure that the panel is in a valid state */ | 
					
						
							|  |  |  | 	taal_hw_reset(dssdev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-09 15:24:46 +03:00
										 |  |  | 	free_regulators(td->panel_config->regulators, | 
					
						
							|  |  |  | 			td->panel_config->num_regulators); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	kfree(td); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | static int taal_power_on(struct omap_dss_device *dssdev) | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							|  |  |  | 	u8 id1, id2, id3; | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	r = omapdss_dsi_display_enable(dssdev); | 
					
						
							|  |  |  | 	if (r) { | 
					
						
							|  |  |  | 		dev_err(&dssdev->dev, "failed to enable DSI\n"); | 
					
						
							|  |  |  | 		goto err0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 12:25:59 +03:00
										 |  |  | 	taal_hw_reset(dssdev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	omapdss_dsi_vc_enable_hs(TCH, false); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	r = taal_sleep_out(td); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = taal_get_id(&id1, &id2, &id3); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-15 17:07:39 +03:00
										 |  |  | 	/* on early Taal revisions CABC is broken */ | 
					
						
							|  |  |  | 	if (td->panel_config->type == PANEL_TAAL && | 
					
						
							|  |  |  | 		(id2 == 0x00 || id2 == 0xff || id2 == 0x81)) | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 		td->cabc_broken = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 14:15:12 +03:00
										 |  |  | 	r = taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		goto err; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 14:15:12 +03:00
										 |  |  | 	r = taal_dcs_write_1(DCS_CTRL_DISPLAY, | 
					
						
							|  |  |  | 			(1<<2) | (1<<5));	/* BL | BCTRL */ | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		goto err; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 14:15:12 +03:00
										 |  |  | 	r = taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		goto err; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 14:15:12 +03:00
										 |  |  | 	r = taal_set_addr_mode(td->rotate, td->mirror); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!td->cabc_broken) { | 
					
						
							|  |  |  | 		r = taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); | 
					
						
							|  |  |  | 		if (r) | 
					
						
							|  |  |  | 			goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = taal_dcs_write_0(DCS_DISPLAY_ON); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		goto err; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-02 12:13:55 +02:00
										 |  |  | 	r = _taal_enable_te(dssdev, td->te_enabled); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	td->enabled = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!td->intro_printed) { | 
					
						
							| 
									
										
										
										
											2010-04-16 14:21:14 +03:00
										 |  |  | 		dev_info(&dssdev->dev, "%s panel revision %02x.%02x.%02x\n", | 
					
						
							|  |  |  | 			td->panel_config->name, id1, id2, id3); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 		if (td->cabc_broken) | 
					
						
							|  |  |  | 			dev_info(&dssdev->dev, | 
					
						
							|  |  |  | 					"old Taal version, CABC disabled\n"); | 
					
						
							|  |  |  | 		td->intro_printed = true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	omapdss_dsi_vc_enable_hs(TCH, true); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | err: | 
					
						
							| 
									
										
										
										
											2010-04-09 12:25:59 +03:00
										 |  |  | 	dev_err(&dssdev->dev, "error while enabling panel, issuing HW reset\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	taal_hw_reset(dssdev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	omapdss_dsi_display_disable(dssdev); | 
					
						
							|  |  |  | err0: | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | static void taal_power_off(struct omap_dss_device *dssdev) | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							| 
									
										
										
										
											2010-04-09 12:25:59 +03:00
										 |  |  | 	int r; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 12:25:59 +03:00
										 |  |  | 	r = taal_dcs_write_0(DCS_DISPLAY_OFF); | 
					
						
							|  |  |  | 	if (!r) { | 
					
						
							|  |  |  | 		r = taal_sleep_in(td); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 		/* HACK: wait a bit so that the message goes through */ | 
					
						
							| 
									
										
										
										
											2010-04-09 12:25:59 +03:00
										 |  |  | 		msleep(10); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 12:25:59 +03:00
										 |  |  | 	if (r) { | 
					
						
							|  |  |  | 		dev_err(&dssdev->dev, | 
					
						
							|  |  |  | 				"error disabling panel, issuing HW reset\n"); | 
					
						
							|  |  |  | 		taal_hw_reset(dssdev); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	omapdss_dsi_display_disable(dssdev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	td->enabled = 0; | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_enable(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:42:16 +03:00
										 |  |  | 	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	int r; | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	dev_dbg(&dssdev->dev, "enable\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { | 
					
						
							|  |  |  | 		r = -EINVAL; | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 10:06:14 +03:00
										 |  |  | 	dsi_bus_lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	r = taal_power_on(dssdev); | 
					
						
							| 
									
										
										
										
											2010-04-12 10:06:14 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	dsi_bus_unlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	if (r) | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 		goto err; | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-15 12:42:16 +03:00
										 |  |  | 	if (panel_data->use_esd_check) | 
					
						
							|  |  |  | 		queue_delayed_work(td->esd_wq, &td->esd_work, | 
					
						
							|  |  |  | 				TAAL_ESD_CHECK_PERIOD); | 
					
						
							| 
									
										
										
										
											2010-04-12 10:23:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  | 	dev_dbg(&dssdev->dev, "enable failed\n"); | 
					
						
							|  |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void taal_disable(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	dev_dbg(&dssdev->dev, "disable\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 10:23:46 +03:00
										 |  |  | 	cancel_delayed_work(&td->esd_work); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 10:06:14 +03:00
										 |  |  | 	dsi_bus_lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | 
					
						
							|  |  |  | 		taal_power_off(dssdev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 10:06:14 +03:00
										 |  |  | 	dsi_bus_unlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_suspend(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	dev_dbg(&dssdev->dev, "suspend\n"); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | 
					
						
							|  |  |  | 		r = -EINVAL; | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 10:23:46 +03:00
										 |  |  | 	cancel_delayed_work(&td->esd_work); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 10:06:14 +03:00
										 |  |  | 	dsi_bus_lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	taal_power_off(dssdev); | 
					
						
							| 
									
										
										
										
											2010-04-12 10:06:14 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	dsi_bus_unlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | err: | 
					
						
							|  |  |  | 	mutex_unlock(&td->lock); | 
					
						
							|  |  |  | 	return r; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_resume(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							| 
									
										
										
										
											2010-04-15 12:42:16 +03:00
										 |  |  | 	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	int r; | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	dev_dbg(&dssdev->dev, "resume\n"); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { | 
					
						
							|  |  |  | 		r = -EINVAL; | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 10:06:14 +03:00
										 |  |  | 	dsi_bus_lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	r = taal_power_on(dssdev); | 
					
						
							| 
									
										
										
										
											2010-04-12 10:06:14 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	dsi_bus_unlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 10:23:46 +03:00
										 |  |  | 	if (r) { | 
					
						
							| 
									
										
										
										
											2010-04-12 10:25:21 +03:00
										 |  |  | 		dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | 
					
						
							| 
									
										
										
										
											2010-04-12 10:23:46 +03:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2010-04-12 10:25:21 +03:00
										 |  |  | 		dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 
					
						
							| 
									
										
										
										
											2010-04-15 12:42:16 +03:00
										 |  |  | 		if (panel_data->use_esd_check) | 
					
						
							|  |  |  | 			queue_delayed_work(td->esd_wq, &td->esd_work, | 
					
						
							|  |  |  | 					TAAL_ESD_CHECK_PERIOD); | 
					
						
							| 
									
										
										
										
											2010-04-12 10:23:46 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mutex_unlock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return r; | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-01-12 15:12:07 +02:00
										 |  |  | 	return r; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 14:16:41 +02:00
										 |  |  | static void taal_framedone_cb(int err, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct omap_dss_device *dssdev = data; | 
					
						
							|  |  |  | 	dev_dbg(&dssdev->dev, "framedone, err %d\n", err); | 
					
						
							|  |  |  | 	dsi_bus_unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-13 10:57:52 +03:00
										 |  |  | static irqreturn_t taal_te_isr(int irq, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct omap_dss_device *dssdev = data; | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							|  |  |  | 	int old; | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	old = atomic_cmpxchg(&td->do_update, 1, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (old) { | 
					
						
							|  |  |  | 		cancel_delayed_work(&td->te_timeout_work); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		r = omap_dsi_update(dssdev, TCH, | 
					
						
							|  |  |  | 				td->update_region.x, | 
					
						
							|  |  |  | 				td->update_region.y, | 
					
						
							|  |  |  | 				td->update_region.w, | 
					
						
							|  |  |  | 				td->update_region.h, | 
					
						
							|  |  |  | 				taal_framedone_cb, dssdev); | 
					
						
							|  |  |  | 		if (r) | 
					
						
							|  |  |  | 			goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return IRQ_HANDLED; | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  | 	dev_err(&dssdev->dev, "start update failed\n"); | 
					
						
							|  |  |  | 	dsi_bus_unlock(); | 
					
						
							|  |  |  | 	return IRQ_HANDLED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void taal_te_timeout_work_callback(struct work_struct *work) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct taal_data *td = container_of(work, struct taal_data, | 
					
						
							|  |  |  | 					te_timeout_work.work); | 
					
						
							|  |  |  | 	struct omap_dss_device *dssdev = td->dssdev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dev_err(&dssdev->dev, "TE not received for 250ms!\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	atomic_set(&td->do_update, 0); | 
					
						
							|  |  |  | 	dsi_bus_unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 14:16:41 +02:00
										 |  |  | static int taal_update(struct omap_dss_device *dssdev, | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 				    u16 x, u16 y, u16 w, u16 h) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-12 14:16:41 +02:00
										 |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 
					
						
							| 
									
										
										
										
											2010-01-12 14:16:41 +02:00
										 |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-01-12 14:16:41 +02:00
										 |  |  | 	dsi_bus_lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!td->enabled) { | 
					
						
							|  |  |  | 		r = 0; | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-09 15:31:34 +03:00
										 |  |  | 	r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h, true); | 
					
						
							| 
									
										
										
										
											2010-01-12 14:16:41 +02:00
										 |  |  | 	if (r) | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = taal_set_update_window(x, y, w, h); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	if (td->te_enabled && panel_data->use_ext_te) { | 
					
						
							| 
									
										
										
										
											2010-04-13 10:57:52 +03:00
										 |  |  | 		td->update_region.x = x; | 
					
						
							|  |  |  | 		td->update_region.y = y; | 
					
						
							|  |  |  | 		td->update_region.w = w; | 
					
						
							|  |  |  | 		td->update_region.h = h; | 
					
						
							|  |  |  | 		barrier(); | 
					
						
							|  |  |  | 		schedule_delayed_work(&td->te_timeout_work, | 
					
						
							|  |  |  | 				msecs_to_jiffies(250)); | 
					
						
							|  |  |  | 		atomic_set(&td->do_update, 1); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		r = omap_dsi_update(dssdev, TCH, x, y, w, h, | 
					
						
							|  |  |  | 				taal_framedone_cb, dssdev); | 
					
						
							|  |  |  | 		if (r) | 
					
						
							|  |  |  | 			goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-01-12 14:16:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* note: no bus_unlock here. unlock is in framedone_cb */ | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-01-12 14:16:41 +02:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  | 	dsi_bus_unlock(); | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-01-12 14:16:41 +02:00
										 |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_sync(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 14:16:41 +02:00
										 |  |  | 	dev_dbg(&dssdev->dev, "sync\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-01-12 14:16:41 +02:00
										 |  |  | 	dsi_bus_lock(); | 
					
						
							|  |  |  | 	dsi_bus_unlock(); | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-01-12 14:16:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	dev_dbg(&dssdev->dev, "sync done\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-02 12:13:55 +02:00
										 |  |  | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (enable) | 
					
						
							|  |  |  | 		r = taal_dcs_write_1(DCS_TEAR_ON, 0); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		r = taal_dcs_write_0(DCS_TEAR_OFF); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	if (!panel_data->use_ext_te) | 
					
						
							| 
									
										
										
										
											2010-04-13 10:57:52 +03:00
										 |  |  | 		omapdss_dsi_enable_te(dssdev, enable); | 
					
						
							| 
									
										
										
										
											2010-01-11 15:11:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-15 12:55:38 +03:00
										 |  |  | 	if (td->panel_config->sleep.enable_te) | 
					
						
							|  |  |  | 		msleep(td->panel_config->sleep.enable_te); | 
					
						
							| 
									
										
										
										
											2010-01-11 15:11:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-02 12:13:55 +02:00
										 |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							| 
									
										
										
										
											2010-03-02 12:13:55 +02:00
										 |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-05-21 10:09:18 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (td->te_enabled == enable) | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-02 12:13:55 +02:00
										 |  |  | 	dsi_bus_lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 09:36:05 +03:00
										 |  |  | 	if (td->enabled) { | 
					
						
							|  |  |  | 		r = _taal_enable_te(dssdev, enable); | 
					
						
							|  |  |  | 		if (r) | 
					
						
							|  |  |  | 			goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	td->te_enabled = enable; | 
					
						
							| 
									
										
										
										
											2010-03-02 12:13:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-11 15:11:01 +02:00
										 |  |  | 	dsi_bus_unlock(); | 
					
						
							| 
									
										
										
										
											2010-05-21 10:09:18 +03:00
										 |  |  | end: | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-01-11 15:11:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 09:36:05 +03:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  | 	dsi_bus_unlock(); | 
					
						
							|  |  |  | 	mutex_unlock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-11 15:11:01 +02:00
										 |  |  | static int taal_get_te(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&td->lock); | 
					
						
							|  |  |  | 	r = td->te_enabled; | 
					
						
							|  |  |  | 	mutex_unlock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return r; | 
					
						
							| 
									
										
										
										
											2010-01-11 15:11:01 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dev_dbg(&dssdev->dev, "rotate %d\n", rotate); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-05-21 10:09:18 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (td->rotate == rotate) | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-08 16:52:48 +02:00
										 |  |  | 	dsi_bus_lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	if (td->enabled) { | 
					
						
							|  |  |  | 		r = taal_set_addr_mode(rotate, td->mirror); | 
					
						
							|  |  |  | 		if (r) | 
					
						
							| 
									
										
										
										
											2010-01-08 16:52:48 +02:00
										 |  |  | 			goto err; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	td->rotate = rotate; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-08 16:52:48 +02:00
										 |  |  | 	dsi_bus_unlock(); | 
					
						
							| 
									
										
										
										
											2010-05-21 10:09:18 +03:00
										 |  |  | end: | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2010-01-08 16:52:48 +02:00
										 |  |  | err: | 
					
						
							|  |  |  | 	dsi_bus_unlock(); | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-01-08 16:52:48 +02:00
										 |  |  | 	return r; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static u8 taal_get_rotate(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&td->lock); | 
					
						
							|  |  |  | 	r = td->rotate; | 
					
						
							|  |  |  | 	mutex_unlock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return r; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_mirror(struct omap_dss_device *dssdev, bool enable) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dev_dbg(&dssdev->dev, "mirror %d\n", enable); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-05-21 10:09:18 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (td->mirror == enable) | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-08 16:30:33 +02:00
										 |  |  | 	dsi_bus_lock(); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	if (td->enabled) { | 
					
						
							|  |  |  | 		r = taal_set_addr_mode(td->rotate, enable); | 
					
						
							|  |  |  | 		if (r) | 
					
						
							| 
									
										
										
										
											2010-01-08 16:30:33 +02:00
										 |  |  | 			goto err; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	td->mirror = enable; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-08 16:30:33 +02:00
										 |  |  | 	dsi_bus_unlock(); | 
					
						
							| 
									
										
										
										
											2010-05-21 10:09:18 +03:00
										 |  |  | end: | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2010-01-08 16:30:33 +02:00
										 |  |  | err: | 
					
						
							|  |  |  | 	dsi_bus_unlock(); | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-01-08 16:30:33 +02:00
										 |  |  | 	return r; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool taal_get_mirror(struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mutex_lock(&td->lock); | 
					
						
							|  |  |  | 	r = td->mirror; | 
					
						
							|  |  |  | 	mutex_unlock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return r; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_run_test(struct omap_dss_device *dssdev, int test_num) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	u8 id1, id2, id3; | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-04-12 09:36:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!td->enabled) { | 
					
						
							|  |  |  | 		r = -ENODEV; | 
					
						
							|  |  |  | 		goto err1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-08 16:21:28 +02:00
										 |  |  | 	dsi_bus_lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	r = taal_dcs_read_1(DCS_GET_ID1, &id1); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							| 
									
										
										
										
											2010-04-12 09:36:05 +03:00
										 |  |  | 		goto err2; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	r = taal_dcs_read_1(DCS_GET_ID2, &id2); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							| 
									
										
										
										
											2010-04-12 09:36:05 +03:00
										 |  |  | 		goto err2; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	r = taal_dcs_read_1(DCS_GET_ID3, &id3); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							| 
									
										
										
										
											2010-04-12 09:36:05 +03:00
										 |  |  | 		goto err2; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-08 16:21:28 +02:00
										 |  |  | 	dsi_bus_unlock(); | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2010-04-12 09:36:05 +03:00
										 |  |  | err2: | 
					
						
							| 
									
										
										
										
											2010-01-08 16:21:28 +02:00
										 |  |  | 	dsi_bus_unlock(); | 
					
						
							| 
									
										
										
										
											2010-04-12 09:36:05 +03:00
										 |  |  | err1: | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2010-01-08 16:21:28 +02:00
										 |  |  | 	return r; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int taal_memory_read(struct omap_dss_device *dssdev, | 
					
						
							|  |  |  | 		void *buf, size_t size, | 
					
						
							|  |  |  | 		u16 x, u16 y, u16 w, u16 h) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 	int first = 1; | 
					
						
							|  |  |  | 	int plen; | 
					
						
							|  |  |  | 	unsigned buf_used = 0; | 
					
						
							| 
									
										
										
										
											2010-01-08 16:56:44 +02:00
										 |  |  | 	struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	if (size < w * h * 3) | 
					
						
							|  |  |  | 		return -ENOMEM; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!td->enabled) { | 
					
						
							|  |  |  | 		r = -ENODEV; | 
					
						
							|  |  |  | 		goto err1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	size = min(w * h * 3, | 
					
						
							|  |  |  | 			dssdev->panel.timings.x_res * | 
					
						
							|  |  |  | 			dssdev->panel.timings.y_res * 3); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-08 16:56:44 +02:00
										 |  |  | 	dsi_bus_lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	/* plen 1 or 2 goes into short packet. until checksum error is fixed,
 | 
					
						
							|  |  |  | 	 * use short packets. plen 32 works, but bigger packets seem to cause | 
					
						
							|  |  |  | 	 * an error. */ | 
					
						
							|  |  |  | 	if (size % 2) | 
					
						
							|  |  |  | 		plen = 1; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		plen = 2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-08 16:56:44 +02:00
										 |  |  | 	taal_set_update_window(x, y, w, h); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	r = dsi_vc_set_max_rx_packet_size(TCH, plen); | 
					
						
							|  |  |  | 	if (r) | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 		goto err2; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	while (buf_used < size) { | 
					
						
							|  |  |  | 		u8 dcs_cmd = first ? 0x2e : 0x3e; | 
					
						
							|  |  |  | 		first = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		r = dsi_vc_dcs_read(TCH, dcs_cmd, | 
					
						
							|  |  |  | 				buf + buf_used, size - buf_used); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (r < 0) { | 
					
						
							|  |  |  | 			dev_err(&dssdev->dev, "read error\n"); | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 			goto err3; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		buf_used += r; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (r < plen) { | 
					
						
							|  |  |  | 			dev_err(&dssdev->dev, "short read\n"); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (signal_pending(current)) { | 
					
						
							|  |  |  | 			dev_err(&dssdev->dev, "signal pending, " | 
					
						
							|  |  |  | 					"aborting memory read\n"); | 
					
						
							|  |  |  | 			r = -ERESTARTSYS; | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 			goto err3; | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = buf_used; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | err3: | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	dsi_vc_set_max_rx_packet_size(TCH, 1); | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | err2: | 
					
						
							| 
									
										
										
										
											2010-01-08 16:56:44 +02:00
										 |  |  | 	dsi_bus_unlock(); | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | err1: | 
					
						
							|  |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void taal_esd_work(struct work_struct *work) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct taal_data *td = container_of(work, struct taal_data, | 
					
						
							|  |  |  | 			esd_work.work); | 
					
						
							|  |  |  | 	struct omap_dss_device *dssdev = td->dssdev; | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	u8 state1, state2; | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_lock(&td->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!td->enabled) { | 
					
						
							|  |  |  | 		mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	dsi_bus_lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = taal_dcs_read_1(DCS_RDDSDR, &state1); | 
					
						
							|  |  |  | 	if (r) { | 
					
						
							|  |  |  | 		dev_err(&dssdev->dev, "failed to read Taal status\n"); | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Run self diagnostics */ | 
					
						
							|  |  |  | 	r = taal_sleep_out(td); | 
					
						
							|  |  |  | 	if (r) { | 
					
						
							|  |  |  | 		dev_err(&dssdev->dev, "failed to run Taal self-diagnostics\n"); | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r = taal_dcs_read_1(DCS_RDDSDR, &state2); | 
					
						
							|  |  |  | 	if (r) { | 
					
						
							|  |  |  | 		dev_err(&dssdev->dev, "failed to read Taal status\n"); | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Each sleep out command will trigger a self diagnostic and flip
 | 
					
						
							|  |  |  | 	 * Bit6 if the test passes. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (!((state1 ^ state2) & (1 << 6))) { | 
					
						
							|  |  |  | 		dev_err(&dssdev->dev, "LCD self diagnostics failed\n"); | 
					
						
							|  |  |  | 		goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* Self-diagnostics result is also shown on TE GPIO line. We need
 | 
					
						
							|  |  |  | 	 * to re-enable TE after self diagnostics */ | 
					
						
							| 
									
										
										
										
											2010-06-09 15:23:44 +03:00
										 |  |  | 	if (td->te_enabled && panel_data->use_ext_te) { | 
					
						
							| 
									
										
										
										
											2010-03-01 13:52:10 +02:00
										 |  |  | 		r = taal_dcs_write_1(DCS_TEAR_ON, 0); | 
					
						
							|  |  |  | 		if (r) | 
					
						
							|  |  |  | 			goto err; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	dsi_bus_unlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	return; | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  | 	dev_err(&dssdev->dev, "performing LCD reset\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	taal_power_off(dssdev); | 
					
						
							| 
									
										
										
										
											2010-04-09 12:25:59 +03:00
										 |  |  | 	taal_hw_reset(dssdev); | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 	taal_power_on(dssdev); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	dsi_bus_unlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); | 
					
						
							| 
									
										
										
										
											2010-03-03 14:31:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mutex_unlock(&td->lock); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-11 16:12:31 +02:00
										 |  |  | static int taal_set_update_mode(struct omap_dss_device *dssdev, | 
					
						
							|  |  |  | 		enum omap_dss_update_mode mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (mode != OMAP_DSS_UPDATE_MANUAL) | 
					
						
							|  |  |  | 		return -EINVAL; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static enum omap_dss_update_mode taal_get_update_mode( | 
					
						
							|  |  |  | 		struct omap_dss_device *dssdev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return OMAP_DSS_UPDATE_MANUAL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | static struct omap_dss_driver taal_driver = { | 
					
						
							|  |  |  | 	.probe		= taal_probe, | 
					
						
							|  |  |  | 	.remove		= taal_remove, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.enable		= taal_enable, | 
					
						
							|  |  |  | 	.disable	= taal_disable, | 
					
						
							|  |  |  | 	.suspend	= taal_suspend, | 
					
						
							|  |  |  | 	.resume		= taal_resume, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-11 16:12:31 +02:00
										 |  |  | 	.set_update_mode = taal_set_update_mode, | 
					
						
							|  |  |  | 	.get_update_mode = taal_get_update_mode, | 
					
						
							| 
									
										
										
										
											2010-01-12 14:16:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	.update		= taal_update, | 
					
						
							|  |  |  | 	.sync		= taal_sync, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-11 13:54:33 +02:00
										 |  |  | 	.get_resolution	= taal_get_resolution, | 
					
						
							| 
									
										
										
										
											2010-01-11 14:33:40 +02:00
										 |  |  | 	.get_recommended_bpp = omapdss_default_get_recommended_bpp, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	.enable_te	= taal_enable_te, | 
					
						
							| 
									
										
										
										
											2010-01-11 15:11:01 +02:00
										 |  |  | 	.get_te		= taal_get_te, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	.set_rotate	= taal_rotate, | 
					
						
							|  |  |  | 	.get_rotate	= taal_get_rotate, | 
					
						
							|  |  |  | 	.set_mirror	= taal_mirror, | 
					
						
							|  |  |  | 	.get_mirror	= taal_get_mirror, | 
					
						
							|  |  |  | 	.run_test	= taal_run_test, | 
					
						
							|  |  |  | 	.memory_read	= taal_memory_read, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 12:11:25 +02:00
										 |  |  | 	.get_timings	= taal_get_timings, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:31:05 +02:00
										 |  |  | 	.driver         = { | 
					
						
							|  |  |  | 		.name   = "taal", | 
					
						
							|  |  |  | 		.owner  = THIS_MODULE, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int __init taal_init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	omap_dss_register_driver(&taal_driver); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void __exit taal_exit(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	omap_dss_unregister_driver(&taal_driver); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module_init(taal_init); | 
					
						
							|  |  |  | module_exit(taal_exit); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); | 
					
						
							|  |  |  | MODULE_DESCRIPTION("Taal Driver"); | 
					
						
							|  |  |  | MODULE_LICENSE("GPL"); |