Browse Source

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6: (27 commits)
  Staging: sep: return -EFAULT on copy_to_user errors
  Staging: rc2860: return -EFAULT on copy_to_user errors
  Staging: Eliminate a NULL pointer dereference
  staging: Use GFP_ATOMIC when a lock is held
  Staging: comedi - correct parameter gainlkup for DAQCard-6024E in driver ni_mio_cs.c
  Staging: comedi: fixing ni_labpc to mite dependancy
  Staging: wlags49_h2, wlags49_h25: fixed Kconfig dependencies
  Staging: phison: depends on ATA_BMDMA
  Staging: iio-utils: fix memory overflow for dynamically allocateded memory to hold filename
  Staging: adis16255: add proper section markings to hotplug funcs
  Staging: adis16255: fix typo in Kconfig
  Staging: batman-adv: Don't allocate icmp packet with GFP_KERNEL
  Staging: batman-adv: Don't call free_netdev twice
  Staging: batman-adv: Call unregister_netdev on failures to get rtnl lock
  Staging: batman-adv: fix rogue packets on shutdown
  Staging: add MSM framebuffer driver
  Staging: comedi: fixing ni_tio to mite PCI dependancy
  Staging: comedi: fix 8255 and DAS08 Kconfig dependancies.
  Staging: comedi: For COMEDI_BUFINFO, check access to command
  Staging: comedi: COMEDI_BUFINFO with no async - report no bytes read or written
  ...
Linus Torvalds 15 years ago
parent
commit
a094c0afc3
100 changed files with 29916 additions and 88 deletions
  1. 6 0
      drivers/staging/Kconfig
  2. 3 0
      drivers/staging/Makefile
  3. 1 1
      drivers/staging/adis16255/Kconfig
  4. 2 2
      drivers/staging/adis16255/adis16255.c
  5. 1 1
      drivers/staging/batman-adv/device.c
  6. 4 1
      drivers/staging/batman-adv/main.c
  7. 15 9
      drivers/staging/batman-adv/send.c
  8. 59 22
      drivers/staging/comedi/Kconfig
  9. 31 13
      drivers/staging/comedi/comedi_fops.c
  10. 2 2
      drivers/staging/comedi/drivers/Makefile
  11. 7 7
      drivers/staging/comedi/drivers/addi-data/addi_common.c
  12. 2 0
      drivers/staging/comedi/drivers/addi_apci_035.c
  13. 2 0
      drivers/staging/comedi/drivers/addi_apci_1032.c
  14. 2 0
      drivers/staging/comedi/drivers/addi_apci_1500.c
  15. 2 0
      drivers/staging/comedi/drivers/addi_apci_1516.c
  16. 2 0
      drivers/staging/comedi/drivers/addi_apci_1564.c
  17. 2 0
      drivers/staging/comedi/drivers/addi_apci_16xx.c
  18. 2 0
      drivers/staging/comedi/drivers/addi_apci_1710.c
  19. 2 0
      drivers/staging/comedi/drivers/addi_apci_2016.c
  20. 2 0
      drivers/staging/comedi/drivers/addi_apci_2032.c
  21. 2 0
      drivers/staging/comedi/drivers/addi_apci_2200.c
  22. 2 0
      drivers/staging/comedi/drivers/addi_apci_3001.c
  23. 2 0
      drivers/staging/comedi/drivers/addi_apci_3120.c
  24. 2 0
      drivers/staging/comedi/drivers/addi_apci_3200.c
  25. 2 0
      drivers/staging/comedi/drivers/addi_apci_3300.c
  26. 2 0
      drivers/staging/comedi/drivers/addi_apci_3501.c
  27. 2 0
      drivers/staging/comedi/drivers/addi_apci_3xxx.c
  28. 169 11
      drivers/staging/comedi/drivers/adv_pci_dio.c
  29. 25 10
      drivers/staging/comedi/drivers/amplc_dio200.c
  30. 1 1
      drivers/staging/comedi/drivers/ni_mio_cs.c
  31. 1 2
      drivers/staging/comedi/drivers/usbdux.c
  32. 1 3
      drivers/staging/dt3155/allocator.c
  33. 1 2
      drivers/staging/iio/Documentation/iio_utils.h
  34. 1 1
      drivers/staging/iio/ring_sw.c
  35. 7 0
      drivers/staging/mrst-touchscreen/Kconfig
  36. 3 0
      drivers/staging/mrst-touchscreen/Makefile
  37. 2 0
      drivers/staging/mrst-touchscreen/TODO
  38. 864 0
      drivers/staging/mrst-touchscreen/intel-mid-touch.c
  39. 134 0
      drivers/staging/msm/Kconfig
  40. 93 0
      drivers/staging/msm/Makefile
  41. 3 0
      drivers/staging/msm/TODO
  42. 569 0
      drivers/staging/msm/ebi2_l2f.c
  43. 250 0
      drivers/staging/msm/ebi2_lcd.c
  44. 1122 0
      drivers/staging/msm/ebi2_tmd20.c
  45. 248 0
      drivers/staging/msm/hdmi_sii9022.c
  46. 239 0
      drivers/staging/msm/lcdc.c
  47. 54 0
      drivers/staging/msm/lcdc_external.c
  48. 446 0
      drivers/staging/msm/lcdc_gordon.c
  49. 60 0
      drivers/staging/msm/lcdc_grapefruit.c
  50. 88 0
      drivers/staging/msm/lcdc_panel.c
  51. 64 0
      drivers/staging/msm/lcdc_prism.c
  52. 290 0
      drivers/staging/msm/lcdc_sharp_wvga_pt.c
  53. 237 0
      drivers/staging/msm/lcdc_st15.c
  54. 54 0
      drivers/staging/msm/lcdc_st1_wxga.c
  55. 374 0
      drivers/staging/msm/lcdc_toshiba_wvga_pt.c
  56. 56 0
      drivers/staging/msm/lcdc_wxga.c
  57. 98 0
      drivers/staging/msm/logo.c
  58. 375 0
      drivers/staging/msm/mddi.c
  59. 320 0
      drivers/staging/msm/mddi_ext.c
  60. 91 0
      drivers/staging/msm/mddi_ext_lcd.c
  61. 114 0
      drivers/staging/msm/mddi_prism.c
  62. 892 0
      drivers/staging/msm/mddi_sharp.c
  63. 1741 0
      drivers/staging/msm/mddi_toshiba.c
  64. 52 0
      drivers/staging/msm/mddi_toshiba.h
  65. 136 0
      drivers/staging/msm/mddi_toshiba_vga.c
  66. 63 0
      drivers/staging/msm/mddi_toshiba_wvga.c
  67. 64 0
      drivers/staging/msm/mddi_toshiba_wvga_pt.c
  68. 377 0
      drivers/staging/msm/mddihost.c
  69. 225 0
      drivers/staging/msm/mddihost.h
  70. 63 0
      drivers/staging/msm/mddihost_e.c
  71. 2239 0
      drivers/staging/msm/mddihosti.c
  72. 547 0
      drivers/staging/msm/mddihosti.h
  73. 1113 0
      drivers/staging/msm/mdp.c
  74. 695 0
      drivers/staging/msm/mdp.h
  75. 352 0
      drivers/staging/msm/mdp4.h
  76. 181 0
      drivers/staging/msm/mdp4_debugfs.c
  77. 1259 0
      drivers/staging/msm/mdp4_overlay.c
  78. 313 0
      drivers/staging/msm/mdp4_overlay_lcdc.c
  79. 254 0
      drivers/staging/msm/mdp4_overlay_mddi.c
  80. 1686 0
      drivers/staging/msm/mdp4_util.c
  81. 104 0
      drivers/staging/msm/mdp_cursor.c
  82. 561 0
      drivers/staging/msm/mdp_dma.c
  83. 379 0
      drivers/staging/msm/mdp_dma_lcdc.c
  84. 139 0
      drivers/staging/msm/mdp_dma_s.c
  85. 142 0
      drivers/staging/msm/mdp_dma_tv.c
  86. 720 0
      drivers/staging/msm/mdp_hw_init.c
  87. 1502 0
      drivers/staging/msm/mdp_ppp.c
  88. 347 0
      drivers/staging/msm/mdp_ppp_dq.c
  89. 86 0
      drivers/staging/msm/mdp_ppp_dq.h
  90. 2486 0
      drivers/staging/msm/mdp_ppp_v20.c
  91. 828 0
      drivers/staging/msm/mdp_ppp_v31.c
  92. 389 0
      drivers/staging/msm/mdp_vsync.c
  93. 214 0
      drivers/staging/msm/memory.c
  94. 61 0
      drivers/staging/msm/memory_ll.h
  95. 2354 0
      drivers/staging/msm/msm_fb.c
  96. 174 0
      drivers/staging/msm/msm_fb.h
  97. 79 0
      drivers/staging/msm/msm_fb_bl.c
  98. 201 0
      drivers/staging/msm/msm_fb_def.h
  99. 136 0
      drivers/staging/msm/msm_fb_panel.c
  100. 145 0
      drivers/staging/msm/msm_fb_panel.h

+ 6 - 0
drivers/staging/Kconfig

@@ -141,5 +141,11 @@ source "drivers/staging/ti-st/Kconfig"
 
 source "drivers/staging/adis16255/Kconfig"
 
+source "drivers/staging/xgifb/Kconfig"
+
+source "drivers/staging/mrst-touchscreen/Kconfig"
+
+source "drivers/staging/msm/Kconfig"
+
 endif # !STAGING_EXCLUDE_BUILD
 endif # STAGING

+ 3 - 0
drivers/staging/Makefile

@@ -51,3 +51,6 @@ obj-$(CONFIG_CRYSTALHD)		+= crystalhd/
 obj-$(CONFIG_CXT1E1)		+= cxt1e1/
 obj-$(CONFIG_TI_ST)		+= ti-st/
 obj-$(CONFIG_ADIS16255)		+= adis16255/
+obj-$(CONFIG_FB_XGI)		+= xgifb/
+obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH)	+= mrst-touchscreen/
+obj-$(CONFIG_MSM_STAGING)	+= msm/

+ 1 - 1
drivers/staging/adis16255/Kconfig

@@ -1,5 +1,5 @@
 config ADIS16255
-	tristate "Ananlog Devices ADIS16250/16255"
+	tristate "Analog Devices ADIS16250/16255"
 	depends on SPI && SYSFS
 	---help---
 	If you say yes here you get support for the Analog Devices

+ 2 - 2
drivers/staging/adis16255/adis16255.c

@@ -361,7 +361,7 @@ err:
 
 /*-------------------------------------------------------------------------*/
 
-static int spi_adis16255_probe(struct spi_device *spi)
+static int __devinit spi_adis16255_probe(struct spi_device *spi)
 {
 
 	struct adis16255_init_data *init_data = spi->dev.platform_data;
@@ -421,7 +421,7 @@ err:
 	return status;
 }
 
-static int spi_adis16255_remove(struct spi_device *spi)
+static int __devexit spi_adis16255_remove(struct spi_device *spi)
 {
 	struct spi_adis16255_data  *spiadis    = dev_get_drvdata(&spi->dev);
 

+ 1 - 1
drivers/staging/batman-adv/device.c

@@ -309,7 +309,7 @@ void bat_device_add_packet(struct device_client *device_client,
 	struct device_packet *device_packet;
 	unsigned long flags;
 
-	device_packet = kmalloc(sizeof(struct device_packet), GFP_KERNEL);
+	device_packet = kmalloc(sizeof(struct device_packet), GFP_ATOMIC);
 
 	if (!device_packet)
 		return;

+ 4 - 1
drivers/staging/batman-adv/main.c

@@ -127,7 +127,10 @@ int init_module(void)
 	return 0;
 
 unreg_soft_device:
-	unregister_netdevice(soft_device);
+	unregister_netdev(soft_device);
+	soft_device = NULL;
+	return -ENOMEM;
+
 free_soft_device:
 	free_netdev(soft_device);
 	soft_device = NULL;

+ 15 - 9
drivers/staging/batman-adv/send.c

@@ -440,6 +440,9 @@ void send_outstanding_bcast_packet(struct work_struct *work)
 	hlist_del(&forw_packet->list);
 	spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
 
+	if (atomic_read(&module_state) == MODULE_DEACTIVATING)
+		goto out;
+
 	/* rebroadcast packet */
 	rcu_read_lock();
 	list_for_each_entry_rcu(batman_if, &if_list, list) {
@@ -453,15 +456,15 @@ void send_outstanding_bcast_packet(struct work_struct *work)
 
 	forw_packet->num_packets++;
 
-	/* if we still have some more bcasts to send and we are not shutting
-	 * down */
-	if ((forw_packet->num_packets < 3) &&
-	    (atomic_read(&module_state) != MODULE_DEACTIVATING))
+	/* if we still have some more bcasts to send */
+	if (forw_packet->num_packets < 3) {
 		_add_bcast_packet_to_list(forw_packet, ((5 * HZ) / 1000));
-	else {
-		forw_packet_free(forw_packet);
-		atomic_inc(&bcast_queue_left);
+		return;
 	}
+
+out:
+	forw_packet_free(forw_packet);
+	atomic_inc(&bcast_queue_left);
 }
 
 void send_outstanding_bat_packet(struct work_struct *work)
@@ -476,6 +479,9 @@ void send_outstanding_bat_packet(struct work_struct *work)
 	hlist_del(&forw_packet->list);
 	spin_unlock_irqrestore(&forw_bat_list_lock, flags);
 
+	if (atomic_read(&module_state) == MODULE_DEACTIVATING)
+		goto out;
+
 	send_packet(forw_packet);
 
 	/**
@@ -483,10 +489,10 @@ void send_outstanding_bat_packet(struct work_struct *work)
 	 * to determine the queues wake up time unless we are
 	 * shutting down
 	 */
-	if ((forw_packet->own) &&
-	    (atomic_read(&module_state) != MODULE_DEACTIVATING))
+	if (forw_packet->own)
 		schedule_own_packet(forw_packet->if_incoming);
 
+out:
 	/* don't count own packet */
 	if (!forw_packet->own)
 		atomic_inc(&batman_queue_left);

+ 59 - 22
drivers/staging/comedi/Kconfig

@@ -100,15 +100,6 @@ menuconfig COMEDI_ISA_DRIVERS
 
 if COMEDI_ISA_DRIVERS && ISA
 
-config COMEDI_8255
-	tristate "Generic 8255 support"
-	default N
-	---help---
-	  Enable generic 8255 support.
-
-	  To compile this driver as a module, choose M here: the module will be
-	  called 8255.
-
 config COMEDI_ACL7225B
 	tristate "ADlink NuDAQ ACL-7225b and compatibles support"
 	default N
@@ -130,6 +121,7 @@ config COMEDI_PCL711
 
 config COMEDI_PCL724
 	tristate "Advantech PCL-722/724/731 and ADlink ACL-7122/7124/PET-48DIO"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for Advantech PCL-724, PCL-722, PCL-731 and
@@ -198,6 +190,7 @@ config COMEDI_PCL818
 
 config COMEDI_PCM3724
 	tristate "Advantech PCM-3724 PC/104 card support"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for Advantech PCM-3724 PC/104 cards.
@@ -232,18 +225,9 @@ config COMEDI_RTI802
 	  To compile this driver as a module, choose M here: the module will be
 	  called rti802.
 
-config COMEDI_DAS08
-	tristate "DAS-08 compatible ISA, PC/104 and PCMCIA card support"
-	default N
-	---help---
-	  Enable support for Keithley Metrabyte/ComputerBoards DAS08
-	  and compatible ISA and PC/104 cards
-
-	  To compile this driver as a module, choose M here: the module will be
-	  called das08.
-
 config COMEDI_DAS16M1
 	tristate "MeasurementComputing CIO-DAS16/M1DAS-16 ISA card support"
+	select COMEDI_8255
 	select COMEDI_FC
 	default N
 	---help---
@@ -254,6 +238,7 @@ config COMEDI_DAS16M1
 
 config COMEDI_DAS16
 	tristate "DAS-16 compatible ISA and PC/104 card support"
+	select COMEDI_8255
 	select COMEDI_FC
 	default N
 	---help---
@@ -385,6 +370,7 @@ config COMEDI_FL512
 
 config COMEDI_AIO_AIO12_8
 	tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board
@@ -466,6 +452,7 @@ config COMEDI_NI_ATMIO
 config COMEDI_NI_ATMIO16D
 	tristate "NI AT-MIO16/AT-MIO16D series ISA-PNP card support"
 	depends on ISAPNP && COMEDI_NI_COMMON
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for National Instruments AT-MIO16/AT-MIO16D cards.
@@ -667,6 +654,7 @@ config COMEDI_ADDI_APCI_3XXX
 
 config COMEDI_ADL_PCI6208
 	tristate "ADLink PCI-6208A support"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for ADLink PCI-6208A cards
@@ -751,6 +739,7 @@ config COMEDI_ADV_PCI1723
 
 config COMEDI_ADV_PCI_DIO
 	tristate "Advantech PCI DIO card support"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for Advantech PCI DIO cards
@@ -762,6 +751,7 @@ config COMEDI_ADV_PCI_DIO
 
 config COMEDI_AMPLC_DIO200
 	tristate "Amplicon PC272E and PCI272 DIO board support"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for Amplicon PC272E and PCI272 DIO boards
@@ -771,6 +761,7 @@ config COMEDI_AMPLC_DIO200
 
 config COMEDI_AMPLC_PC236
 	tristate "Amplicon PC36AT and PCI236 DIO board support"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for Amplicon PC36AT and PCI236 DIO boards
@@ -799,6 +790,7 @@ config COMEDI_AMPLC_PCI224
 
 config COMEDI_AMPLC_PCI230
 	tristate "Amplicon PCI230 and PCI260 support"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for Amplicon PCI230 and PCI260 Multifunction I/O
@@ -869,6 +861,7 @@ config COMEDI_II_PCI20KC
 
 config COMEDI_DAQBOARD2000
 	tristate "IOtech DAQboard/2000 support"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for the IOtech DAQboard/2000
@@ -896,6 +889,7 @@ config COMEDI_KE_COUNTER
 
 config COMEDI_CB_PCIDAS64
 	tristate "MeasurementComputing PCI-DAS 64xx, 60xx, and 4020 support"
+	select COMEDI_8255
 	select COMEDI_FC
 	default N
 	---help---
@@ -907,6 +901,7 @@ config COMEDI_CB_PCIDAS64
 
 config COMEDI_CB_PCIDAS
 	tristate "MeasurementComputing PCI-DAS support"
+	select COMEDI_8255
 	select COMEDI_FC
 	default N
 	---help---
@@ -920,6 +915,7 @@ config COMEDI_CB_PCIDAS
 
 config COMEDI_CB_PCIDDA
 	tristate "MeasurementComputing PCI-DDA series support"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for ComputerBoards/MeasurementComputing PCI-DDA
@@ -931,6 +927,7 @@ config COMEDI_CB_PCIDDA
 
 config COMEDI_CB_PCIDIO
 	tristate "MeasurementComputing PCI-DIO series support"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for ComputerBoards/MeasurementComputing PCI-DIO series
@@ -941,6 +938,7 @@ config COMEDI_CB_PCIDIO
 
 config COMEDI_CB_PCIMDAS
 	tristate "MeasurementComputing PCIM-DAS1602/16 support"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for ComputerBoards/MeasurementComputing PCI Migration
@@ -951,6 +949,7 @@ config COMEDI_CB_PCIMDAS
 
 config COMEDI_CB_PCIMDDA
 	tristate "MeasurementComputing PCIM-DDA06-16 support"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for ComputerBoards/MeasurementComputing PCIM-DDA06-16
@@ -1026,6 +1025,7 @@ config COMEDI_NI_670X
 config COMEDI_NI_PCIDIO
 	tristate "NI PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503 support"
 	depends on COMEDI_MITE
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for National Instruments PCI-DIO-32HS, PXI-6533,
@@ -1058,6 +1058,7 @@ config COMEDI_NI_PCIMIO
 
 config COMEDI_RTD520
 	tristate "Real Time Devices PCI4520/DM7520 support"
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for Real Time Devices PCI4520/DM7520
@@ -1097,7 +1098,7 @@ endif # COMEDI_PCI_DRIVERS
 
 menuconfig COMEDI_PCMCIA_DRIVERS
 	tristate "Comedi PCMCIA drivers"
-	depends on COMEDI && PCMCIA && PCCARD
+	depends on COMEDI && (PCMCIA || PCCARD)
 	default N
 	---help---
 	  Enable comedi PCMCIA and PCCARD drivers to be built
@@ -1142,6 +1143,7 @@ config COMEDI_NI_DAQ_700_CS
 config COMEDI_NI_DAQ_DIO24_CS
 	tristate "NI DAQ-Card DIO-24 PCMCIA support"
 	depends on COMEDI_NI_COMMON
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for the National Instruments PCMCIA DAQ-Card DIO-24
@@ -1162,8 +1164,8 @@ config COMEDI_NI_LABPC_CS
 config COMEDI_NI_MIO_CS
 	tristate "NI DAQCard E series PCMCIA support"
 	depends on COMEDI_NI_TIO && COMEDI_NI_COMMON
-	default N
 	select COMEDI_FC
+	default N
 	---help---
 	  Enable support for the National Instruments PCMCIA DAQCard E series
 	  DAQCard-ai-16xe-50, DAQCard-ai-16e-4, DAQCard-6062E, DAQCard-6024E
@@ -1265,7 +1267,8 @@ config COMEDI_MITE
 
 config COMEDI_NI_TIO
 	tristate "NI general purpose counter support"
-	select COMEDI_MITE
+	depends on COMEDI_MITE
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable support for National Instruments general purpose counters.
@@ -1278,6 +1281,8 @@ config COMEDI_NI_TIO
 
 config COMEDI_NI_LABPC
 	tristate "NI Lab-PC and compatibles ISA and PCI support"
+	depends on COMEDI_MITE
+	select COMEDI_8255
 	select COMEDI_FC
 	default N
 	---help---
@@ -1291,8 +1296,40 @@ config COMEDI_NI_LABPC
 
 endif # COMEDI_NI_COMMON
 
+config COMEDI_8255
+	tristate "Generic 8255 support"
+	depends on COMEDI
+	default N
+	---help---
+	  Enable generic 8255 support.
+
+	  You should enable compilation this driver if you plan to use a board
+	  that has an 8255 chip. For multifunction boards, the main driver will
+	  configure the 8255 subdevice automatically.
+
+	  Note that most PCI 8255 boards do NOT work with this driver, and
+	  need a separate driver as a wrapper.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called 8255.
+
+config COMEDI_DAS08
+	tristate "DAS-08 compatible support"
+	depends on COMEDI
+	select COMEDI_8255
+	default N
+	---help---
+	  Enable support for DAS08 and compatible ISA, PC/104 and PCI cards.
+
+	  Note that PCMCIA DAS08 cards are not directly supported by this
+	  driver, and need a separate driver as a wrapper.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called das08.
+
 config COMEDI_FC
 	tristate "Comedi shared functions for low-level driver support"
+	depends on COMEDI
 	default N
 	---help---
 	  Enable support for shared functions for low-level drivers.

+ 31 - 13
drivers/staging/comedi/comedi_fops.c

@@ -83,7 +83,7 @@ static int do_subdinfo_ioctl(struct comedi_device *dev,
 static int do_chaninfo_ioctl(struct comedi_device *dev,
 			     struct comedi_chaninfo __user *arg);
 static int do_bufinfo_ioctl(struct comedi_device *dev,
-			    struct comedi_bufinfo __user *arg);
+			    struct comedi_bufinfo __user *arg, void *file);
 static int do_cmd_ioctl(struct comedi_device *dev,
 			struct comedi_cmd __user *arg, void *file);
 static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg,
@@ -169,7 +169,8 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
 		break;
 	case COMEDI_BUFINFO:
 		rc = do_bufinfo_ioctl(dev,
-				      (struct comedi_bufinfo __user *)arg);
+				      (struct comedi_bufinfo __user *)arg,
+				      file);
 		break;
 	case COMEDI_LOCK:
 		rc = do_lock_ioctl(dev, arg, file);
@@ -563,7 +564,7 @@ static int do_chaninfo_ioctl(struct comedi_device *dev,
 
   */
 static int do_bufinfo_ioctl(struct comedi_device *dev,
-			    struct comedi_bufinfo __user *arg)
+			    struct comedi_bufinfo __user *arg, void *file)
 {
 	struct comedi_bufinfo bi;
 	struct comedi_subdevice *s;
@@ -576,6 +577,10 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
 		return -EINVAL;
 
 	s = dev->subdevices + bi.subdevice;
+
+	if (s->lock && s->lock != file)
+		return -EACCES;
+
 	async = s->async;
 
 	if (!async) {
@@ -584,8 +589,17 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
 		bi.buf_read_ptr = 0;
 		bi.buf_write_count = 0;
 		bi.buf_read_count = 0;
+		bi.bytes_read = 0;
+		bi.bytes_written = 0;
 		goto copyback;
 	}
+	if (!s->busy) {
+		bi.bytes_read = 0;
+		bi.bytes_written = 0;
+		goto copyback_position;
+	}
+	if (s->busy != file)
+		return -EACCES;
 
 	if (bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)) {
 		bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read);
@@ -604,6 +618,7 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
 		comedi_buf_write_free(async, bi.bytes_written);
 	}
 
+copyback_position:
 	bi.buf_write_count = async->buf_write_count;
 	bi.buf_write_ptr = async->buf_write_ptr;
 	bi.buf_read_count = async->buf_read_count;
@@ -1576,6 +1591,19 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
 	while (nbytes > 0 && !retval) {
 		set_current_state(TASK_INTERRUPTIBLE);
 
+		if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
+			if (count == 0) {
+				if (comedi_get_subdevice_runflags(s) &
+					SRF_ERROR) {
+					retval = -EPIPE;
+				} else {
+					retval = 0;
+				}
+				do_become_nonbusy(dev, s);
+			}
+			break;
+		}
+
 		n = nbytes;
 
 		m = n;
@@ -1588,16 +1616,6 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
 			n = m;
 
 		if (n == 0) {
-			if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
-				if (comedi_get_subdevice_runflags(s) &
-				    SRF_ERROR) {
-					retval = -EPIPE;
-				} else {
-					retval = 0;
-				}
-				do_become_nonbusy(dev, s);
-				break;
-			}
 			if (file->f_flags & O_NONBLOCK) {
 				retval = -EAGAIN;
 				break;

+ 2 - 2
drivers/staging/comedi/drivers/Makefile

@@ -12,7 +12,6 @@ obj-$(CONFIG_COMEDI_SERIAL2002)		+= serial2002.o
 obj-$(CONFIG_COMEDI_SKEL)		+= skel.o
 
 # Comedi ISA drivers
-obj-$(CONFIG_COMEDI_8255)		+= 8255.o
 obj-$(CONFIG_COMEDI_ACL7225B)		+= acl7225b.o
 obj-$(CONFIG_COMEDI_PCL711)		+= pcl711.o
 obj-$(CONFIG_COMEDI_PCL724)		+= pcl724.o
@@ -26,7 +25,6 @@ obj-$(CONFIG_COMEDI_PCM3724)		+= pcm3724.o
 obj-$(CONFIG_COMEDI_PCM3730)		+= pcm3730.o
 obj-$(CONFIG_COMEDI_RTI800)		+= rti800.o
 obj-$(CONFIG_COMEDI_RTI802)		+= rti802.o
-obj-$(CONFIG_COMEDI_DAS08)		+= das08.o
 obj-$(CONFIG_COMEDI_DAS16M1)		+= das16m1.o
 obj-$(CONFIG_COMEDI_DAS16)		+= das16.o
 obj-$(CONFIG_COMEDI_DAS800)		+= das800.o
@@ -135,4 +133,6 @@ obj-$(CONFIG_COMEDI_NI_TIO)		+= ni_tio.o
 obj-$(CONFIG_COMEDI_NI_TIO)		+= ni_tiocmd.o
 obj-$(CONFIG_COMEDI_NI_LABPC)		+= ni_labpc.o
 
+obj-$(CONFIG_COMEDI_8255)		+= 8255.o
+obj-$(CONFIG_COMEDI_DAS08)		+= das08.o
 obj-$(CONFIG_COMEDI_FC)			+= comedi_fc.o

+ 7 - 7
drivers/staging/comedi/drivers/addi-data/addi_common.c

@@ -68,6 +68,10 @@ You should also find the complete GPL in the COPYING file accompanying this sour
 #include "addi_common.h"
 #include "addi_amcc_s5933.h"
 
+#ifndef ADDIDATA_DRIVER_NAME
+#define ADDIDATA_DRIVER_NAME	"addi_common"
+#endif
+
 /* Update-0.7.57->0.7.68MODULE_AUTHOR("ADDI-DATA GmbH <info@addi-data.com>"); */
 /* Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module"); */
 /* Update-0.7.57->0.7.68MODULE_LICENSE("GPL"); */
@@ -2528,7 +2532,7 @@ static const struct addi_board boardtypes[] = {
 #define n_boardtypes (sizeof(boardtypes)/sizeof(struct addi_board))
 
 static struct comedi_driver driver_addi = {
-	.driver_name = "addi_common",
+	.driver_name = ADDIDATA_DRIVER_NAME,
 	.module = THIS_MODULE,
 	.attach = i_ADDI_Attach,
 	.detach = i_ADDI_Detach,
@@ -2570,10 +2574,6 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	struct pcilst_struct *card = NULL;
 	unsigned char pci_bus, pci_slot, pci_func;
 	int i_Dma = 0;
-	static char c_Identifier[150];
-
-	sprintf(c_Identifier, "Addi-Data GmbH Comedi %s",
-		this_board->pc_DriverName);
 
 	ret = alloc_private(dev, sizeof(struct addi_private));
 	if (ret < 0)
@@ -2583,7 +2583,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		v_pci_card_list_init(this_board->i_VendorId, 1);	/* 1 for displaying the list.. */
 		pci_list_builded = 1;
 	}
-	/* printk("comedi%d: addi_common: board=%s",dev->minor,this_board->pc_DriverName); */
+	/* printk("comedi%d: "ADDIDATA_DRIVER_NAME": board=%s",dev->minor,this_board->pc_DriverName); */
 
 	if ((this_board->i_Dma) && (it->options[2] == 0)) {
 		i_Dma = 1;
@@ -2648,7 +2648,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	if (irq > 0) {
 		if (request_irq(irq, v_ADDI_Interrupt, IRQF_SHARED,
-				c_Identifier, dev) < 0) {
+				this_board->pc_DriverName, dev) < 0) {
 			printk(", unable to allocate IRQ %u, DISABLING IT",
 				irq);
 			irq = 0;	/* Can't use IRQ */

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_035.c

@@ -2,4 +2,6 @@
 
 #define ADDIDATA_WATCHDOG 2	/*  Or shold it be something else */
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_035"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_1032.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_1032 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_1032"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_1500.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_1500 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_1500"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_1516.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_1516 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_1516"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_1564.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_1564 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_1564"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_16xx.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_16XX 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_16xx"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_1710.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_1710 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_1710"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_2016.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_2016 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_2016"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_2032.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_2032 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_2032"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_2200.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_2200 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_2200"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_3001.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_3001 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_3001"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_3120.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_3120 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_3120"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_3200.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_3200 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_3200"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_3300.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_3300 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_3300"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_3501.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_3501 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_3501"
+
 #include "addi-data/addi_common.c"

+ 2 - 0
drivers/staging/comedi/drivers/addi_apci_3xxx.c

@@ -1,3 +1,5 @@
 #define CONFIG_APCI_3XXX 1
 
+#define ADDIDATA_DRIVER_NAME	"addi_apci_3xxx"
+
 #include "addi-data/addi_common.c"

+ 169 - 11
drivers/staging/comedi/drivers/adv_pci_dio.c

@@ -7,17 +7,17 @@
 */
 /*
 Driver: adv_pci_dio
-Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1736UP,
-             PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754,
-             PCI-1756, PCI-1762
+Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U,
+             PCI-1736UP, PCI-1750, PCI-1751, PCI-1752, PCI-1753/E,
+             PCI-1754, PCI-1756, PCI-1762
 Author: Michal Dobes <dobes@tesnet.cz>
 Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733,
-  PCI-1734, PCI-1736UP, PCI-1750,
+  PCI-1734, PCI-1735U, PCI-1736UP, PCI-1750,
   PCI-1751, PCI-1752, PCI-1753,
   PCI-1753+PCI-1753E, PCI-1754, PCI-1756,
   PCI-1760, PCI-1762
 Status: untested
-Updated: Mon, 14 Apr 2008 10:43:08 +0100
+Updated: Tue, 04 May 2010 13:00:00 +0000
 
 This driver supports now only insn interface for DI/DO/DIO.
 
@@ -35,6 +35,7 @@ Configuration options:
 
 #include "comedi_pci.h"
 #include "8255.h"
+#include "8253.h"
 
 #undef PCI_DIO_EXTDEBUG		/* if defined, enable extensive debug logging */
 
@@ -49,7 +50,7 @@ Configuration options:
 
 /* hardware types of the cards */
 enum hw_cards_id {
-	TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1736,
+	TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736,
 	TYPE_PCI1750,
 	TYPE_PCI1751,
 	TYPE_PCI1752,
@@ -67,7 +68,10 @@ enum hw_io_access {
 #define MAX_DI_SUBDEVS	2	/* max number of DI subdevices per card */
 #define MAX_DO_SUBDEVS	2	/* max number of DO subdevices per card */
 #define MAX_DIO_SUBDEVG	2	/* max number of DIO subdevices group per card */
+#define MAX_8254_SUBDEVS   1	/* max number of 8254 counter subdevs per card */
+				/* (could be more than one 8254 per subdevice) */
 
+#define SIZE_8254	   4	/* 8254 IO space length */
 #define SIZE_8255	   4	/* 8255 IO space length */
 
 #define PCIDIO_MAINREG	   2	/* main I/O region for all Advantech cards? */
@@ -85,6 +89,12 @@ enum hw_io_access {
 #define PCI1734_IDO	   0	/* W:   Isolated digital output 0-31 */
 #define PCI173x_BOARDID	   4	/* R:   Board I/D switch for 1730/3/4 */
 
+/* Advantech PCI-1735U */
+#define PCI1735_DI	   0	/* R:   Digital input  0-31 */
+#define PCI1735_DO	   0	/* W:   Digital output 0-31 */
+#define PCI1735_C8254	   4	/* R/W: 8254 counter */
+#define PCI1735_BOARDID	   8    /* R:   Board I/D switch for 1735U */
+
 /*  Advantech PCI-1736UP */
 #define PCI1736_IDI        0	/* R:   Isolated digital input  0-15 */
 #define PCI1736_IDO        0	/* W:   Isolated digital output 0-15 */
@@ -192,7 +202,8 @@ static int pci_dio_detach(struct comedi_device *dev);
 struct diosubd_data {
 	int chans;		/*  num of chans */
 	int addr;		/*  PCI address ofset */
-	int regs;		/*  number of registers to read or 8255 subdevices */
+	int regs;		/*  number of registers to read or 8255
+				    subdevices or 8254 chips */
 	unsigned int specflags;	/*  addon subdevice flags */
 };
 
@@ -206,6 +217,7 @@ struct dio_boardtype {
 	struct diosubd_data sdo[MAX_DO_SUBDEVS];	/*  DO chans */
 	struct diosubd_data sdio[MAX_DIO_SUBDEVG];	/*  DIO 8255 chans */
 	struct diosubd_data boardid;	/*  card supports board ID switch */
+	struct diosubd_data s8254[MAX_8254_SUBDEVS];	/* 8254 subdevices */
 	enum hw_io_access io_access;
 };
 
@@ -214,6 +226,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci_dio_pci_table) = {
 	PCI_VENDOR_ID_ADVANTECH, 0x1730, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 	PCI_VENDOR_ID_ADVANTECH, 0x1733, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 	PCI_VENDOR_ID_ADVANTECH, 0x1734, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
+	PCI_VENDOR_ID_ADVANTECH, 0x1735, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 	PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 	PCI_VENDOR_ID_ADVANTECH, 0x1750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 	PCI_VENDOR_ID_ADVANTECH, 0x1751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
@@ -235,14 +248,15 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
-	 IO_8b,
-	 },
+	 {{0, 0, 0, 0}},
+	 IO_8b},
 	{"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG,
 	 TYPE_PCI1733,
 	 {{0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
+	 {{0, 0, 0, 0}},
 	 IO_8b},
 	{"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG,
 	 TYPE_PCI1734,
@@ -250,6 +264,15 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
+	 {{0, 0, 0, 0}},
+	 IO_8b},
+	{"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG,
+	 TYPE_PCI1735,
+	 {{32, PCI1735_DI, 4, 0}, {0, 0, 0, 0}},
+	 {{32, PCI1735_DO, 4, 0}, {0, 0, 0, 0}},
+	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
+	 { 4, PCI1735_BOARDID, 1, SDF_INTERNAL},
+	 {{3, PCI1735_C8254, 1, 0}},
 	 IO_8b},
 	{"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG,
 	 TYPE_PCI1736,
@@ -257,14 +280,15 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI1736_BOARDID, 1, SDF_INTERNAL},
-	 IO_8b,
-	 },
+	 {{0, 0, 0, 0}},
+	 IO_8b},
 	{"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG,
 	 TYPE_PCI1750,
 	 {{0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0}},
 	 {{0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {0, 0, 0, 0},
+	 {{0, 0, 0, 0}},
 	 IO_8b},
 	{"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG,
 	 TYPE_PCI1751,
@@ -272,6 +296,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {{48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0}},
 	 {0, 0, 0, 0},
+	 {{0, 0, 0, 0}},
 	 IO_8b},
 	{"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG,
 	 TYPE_PCI1752,
@@ -279,6 +304,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
+	 {{0, 0, 0, 0}},
 	 IO_16b},
 	{"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
 	 TYPE_PCI1753,
@@ -286,6 +312,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {{96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0}},
 	 {0, 0, 0, 0},
+	 {{0, 0, 0, 0}},
 	 IO_8b},
 	{"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
 	 TYPE_PCI1753E,
@@ -293,6 +320,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {{96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0}},
 	 {0, 0, 0, 0},
+	 {{0, 0, 0, 0}},
 	 IO_8b},
 	{"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG,
 	 TYPE_PCI1754,
@@ -300,6 +328,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
+	 {{0, 0, 0, 0}},
 	 IO_16b},
 	{"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG,
 	 TYPE_PCI1756,
@@ -307,6 +336,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
+	 {{0, 0, 0, 0}},
 	 IO_16b},
 	{"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0,
 	 TYPE_PCI1760,
@@ -314,6 +344,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {0, 0, 0, 0},
+	 {{0, 0, 0, 0}},
 	 IO_8b},
 	{"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG,
 	 TYPE_PCI1762,
@@ -321,6 +352,7 @@ static const struct dio_boardtype boardtypes[] = {
 	 {{0, 0, 0, 0}, {16, PCI1762_RO, 1, 0}},
 	 {{0, 0, 0, 0}, {0, 0, 0, 0}},
 	 {4, PCI1762_BOARDID, 1, SDF_INTERNAL},
+	 {{0, 0, 0, 0}},
 	 IO_16b}
 };
 
@@ -437,6 +469,83 @@ static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
 	return 2;
 }
 
+/*
+==============================================================================
+*/
+static int pci_8254_insn_read(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn, unsigned int *data)
+{
+	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+	unsigned int chan, chip, chipchan;
+	unsigned long flags;
+
+	chan = CR_CHAN(insn->chanspec);	/* channel on subdevice */
+	chip = chan / 3;		/* chip on subdevice */
+	chipchan = chan - (3 * chip);	/* channel on chip on subdevice */
+	spin_lock_irqsave(&s->spin_lock, flags);
+	data[0] = i8254_read(dev->iobase + d->addr + (SIZE_8254 * chip),
+			0, chipchan);
+	spin_unlock_irqrestore(&s->spin_lock, flags);
+	return 1;
+}
+
+/*
+==============================================================================
+*/
+static int pci_8254_insn_write(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn, unsigned int *data)
+{
+	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+	unsigned int chan, chip, chipchan;
+	unsigned long flags;
+
+	chan = CR_CHAN(insn->chanspec);	/* channel on subdevice */
+	chip = chan / 3;		/* chip on subdevice */
+	chipchan = chan - (3 * chip);	/* channel on chip on subdevice */
+	spin_lock_irqsave(&s->spin_lock, flags);
+	i8254_write(dev->iobase + d->addr + (SIZE_8254 * chip),
+			0, chipchan, data[0]);
+	spin_unlock_irqrestore(&s->spin_lock, flags);
+	return 1;
+}
+
+/*
+==============================================================================
+*/
+static int pci_8254_insn_config(struct comedi_device *dev,
+				struct comedi_subdevice *s,
+				struct comedi_insn *insn, unsigned int *data)
+{
+	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
+	unsigned int chan, chip, chipchan;
+	unsigned long iobase;
+	int ret = 0;
+	unsigned long flags;
+
+	chan = CR_CHAN(insn->chanspec);	/* channel on subdevice */
+	chip = chan / 3;		/* chip on subdevice */
+	chipchan = chan - (3 * chip);	/* channel on chip on subdevice */
+	iobase = dev->iobase + d->addr + (SIZE_8254 * chip);
+	spin_lock_irqsave(&s->spin_lock, flags);
+	switch (data[0]) {
+	case INSN_CONFIG_SET_COUNTER_MODE:
+		ret = i8254_set_mode(iobase, 0, chipchan, data[1]);
+		if (ret < 0)
+			ret = -EINVAL;
+		break;
+	case INSN_CONFIG_8254_READ_STATUS:
+		data[1] = i8254_status(iobase, 0, chipchan);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	spin_unlock_irqrestore(&s->spin_lock, flags);
+	return ret < 0 ? ret : insn->n;
+}
+
 /*
 ==============================================================================
 */
@@ -708,6 +817,15 @@ static int pci_dio_reset(struct comedi_device *dev)
 		outb(0, dev->iobase + PCI1734_IDO + 2);
 		outb(0, dev->iobase + PCI1734_IDO + 3);
 		break;
+	case TYPE_PCI1735:
+		outb(0, dev->iobase + PCI1735_DO);	/*  clear outputs */
+		outb(0, dev->iobase + PCI1735_DO + 1);
+		outb(0, dev->iobase + PCI1735_DO + 2);
+		outb(0, dev->iobase + PCI1735_DO + 3);
+		i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 0, I8254_MODE0);
+		i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 1, I8254_MODE0);
+		i8254_set_mode(dev->iobase + PCI1735_C8254, 0, 2, I8254_MODE0);
+		break;
 
 	case TYPE_PCI1736:
 		outb(0, dev->iobase + PCI1736_IDO);
@@ -874,6 +992,26 @@ static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s,
 	return 0;
 }
 
+/*
+==============================================================================
+*/
+static int pci_dio_add_8254(struct comedi_device *dev,
+			    struct comedi_subdevice * s,
+			    const struct diosubd_data *d, int subdev)
+{
+	s->type = COMEDI_SUBD_COUNTER;
+	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+	s->n_chan = d->chans;
+	s->maxdata = 65535;
+	s->len_chanlist = d->chans;
+	s->insn_read = pci_8254_insn_read;
+	s->insn_write = pci_8254_insn_write;
+	s->insn_config = pci_8254_insn_config;
+	s->private = (void *)d;
+
+	return 0;
+}
+
 /*
 ==============================================================================
 */
@@ -979,6 +1117,9 @@ static int pci_dio_attach(struct comedi_device *dev,
 			n_subdevices += this_board->sdio[i].regs;
 		if (this_board->boardid.chans)
 			n_subdevices++;
+		for (i = 0; i < MAX_8254_SUBDEVS; i++)
+			if (this_board->s8254[i].chans)
+				n_subdevices++;
 	}
 
 	ret = alloc_subdevices(dev, n_subdevices);
@@ -1022,6 +1163,13 @@ static int pci_dio_attach(struct comedi_device *dev,
 		subdev++;
 	}
 
+	for (i = 0; i < MAX_8254_SUBDEVS; i++)
+		if (this_board->s8254[i].chans) {
+			s = dev->subdevices + subdev;
+			pci_dio_add_8254(dev, s, &this_board->s8254[i], subdev);
+			subdev++;
+		}
+
 	if (this_board->cardtype == TYPE_PCI1760)
 		pci1760_attach(dev, it);
 
@@ -1067,6 +1215,16 @@ static int pci_dio_detach(struct comedi_device *dev)
 			}
 		}
 
+		if (this_board->boardid.chans) {
+			subdev++;
+		}
+
+		for (i = 0; i < MAX_8254_SUBDEVS; i++) {
+			if (this_board->s8254[i].chans) {
+				subdev++;
+			}
+		}
+
 		for (i = 0; i < dev->n_subdevices; i++) {
 			s = dev->subdevices + i;
 			s->private = NULL;

+ 25 - 10
drivers/staging/comedi/drivers/amplc_dio200.c

@@ -460,6 +460,7 @@ struct dio200_subdev_8254 {
 	int has_clk_gat_sce;
 	unsigned clock_src[3];	/* Current clock sources */
 	unsigned gate_src[3];	/* Current gate sources */
+	spinlock_t spinlock;
 };
 
 struct dio200_subdev_intr {
@@ -1042,8 +1043,11 @@ dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
 {
 	struct dio200_subdev_8254 *subpriv = s->private;
 	int chan = CR_CHAN(insn->chanspec);
+	unsigned long flags;
 
+	spin_lock_irqsave(&subpriv->spinlock, flags);
 	data[0] = i8254_read(subpriv->iobase, 0, chan);
+	spin_unlock_irqrestore(&subpriv->spinlock, flags);
 
 	return 1;
 }
@@ -1057,8 +1061,11 @@ dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
 {
 	struct dio200_subdev_8254 *subpriv = s->private;
 	int chan = CR_CHAN(insn->chanspec);
+	unsigned long flags;
 
+	spin_lock_irqsave(&subpriv->spinlock, flags);
 	i8254_write(subpriv->iobase, 0, chan, data[0]);
+	spin_unlock_irqrestore(&subpriv->spinlock, flags);
 
 	return 1;
 }
@@ -1151,14 +1158,16 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
 			  struct comedi_insn *insn, unsigned int *data)
 {
 	struct dio200_subdev_8254 *subpriv = s->private;
-	int ret;
+	int ret = 0;
 	int chan = CR_CHAN(insn->chanspec);
+	unsigned long flags;
 
+	spin_lock_irqsave(&subpriv->spinlock, flags);
 	switch (data[0]) {
 	case INSN_CONFIG_SET_COUNTER_MODE:
 		ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
 		if (ret < 0)
-			return -EINVAL;
+			ret = -EINVAL;
 		break;
 	case INSN_CONFIG_8254_READ_STATUS:
 		data[1] = i8254_status(subpriv->iobase, 0, chan);
@@ -1166,30 +1175,35 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
 	case INSN_CONFIG_SET_GATE_SRC:
 		ret = dio200_set_gate_src(subpriv, chan, data[2]);
 		if (ret < 0)
-			return -EINVAL;
+			ret = -EINVAL;
 		break;
 	case INSN_CONFIG_GET_GATE_SRC:
 		ret = dio200_get_gate_src(subpriv, chan);
-		if (ret < 0)
-			return -EINVAL;
+		if (ret < 0) {
+			ret = -EINVAL;
+			break;
+		}
 		data[2] = ret;
 		break;
 	case INSN_CONFIG_SET_CLOCK_SRC:
 		ret = dio200_set_clock_src(subpriv, chan, data[1]);
 		if (ret < 0)
-			return -EINVAL;
+			ret = -EINVAL;
 		break;
 	case INSN_CONFIG_GET_CLOCK_SRC:
 		ret = dio200_get_clock_src(subpriv, chan, &data[2]);
-		if (ret < 0)
-			return -EINVAL;
+		if (ret < 0) {
+			ret = -EINVAL;
+			break;
+		}
 		data[1] = ret;
 		break;
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
 		break;
 	}
-	return insn->n;
+	spin_unlock_irqrestore(&subpriv->spinlock, flags);
+	return ret < 0 ? ret : insn->n;
 }
 
 /*
@@ -1222,6 +1236,7 @@ dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
 	s->insn_write = dio200_subdev_8254_write;
 	s->insn_config = dio200_subdev_8254_config;
 
+	spin_lock_init(&subpriv->spinlock);
 	subpriv->iobase = offset + iobase;
 	subpriv->has_clk_gat_sce = has_clk_gat_sce;
 	if (has_clk_gat_sce) {

+ 1 - 1
drivers/staging/comedi/drivers/ni_mio_cs.c

@@ -123,7 +123,7 @@ static const struct ni_board_struct ni_boards[] = {
 	 .adbits = 12,
 	 .ai_fifo_depth = 1024,
 	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_16,
+	 .gainlkup = ai_gain_4,
 	 .ai_speed = 5000,
 	 .n_aochan = 2,
 	 .aobits = 12,

+ 1 - 2
drivers/staging/comedi/drivers/usbdux.c

@@ -351,8 +351,7 @@ static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
 	int ret = 0;
 
 	if (!this_usbduxsub) {
-		dev_err(&this_usbduxsub->interface->dev,
-			"comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
+		pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
 		return -EFAULT;
 	}
 	dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n");

+ 1 - 3
drivers/staging/dt3155/allocator.c

@@ -176,9 +176,7 @@ int allocator_free_dma(unsigned long address)
 	prev = ptr; ptr = ptr->next;
 
 	if (!ptr) {
-		printk(KERN_ERR ALL_MSG
-			"free_dma(0x%08lx) but add. not allocated\n",
-			ptr->address);
+		pr_err(ALL_MSG "free_dma but add. not allocated\n");
 		return -EINVAL;
 	}
 	PDEBUGG("freeing: %08lx (%li) next %08lx\n", ptr->address, ptr->size,

+ 1 - 2
drivers/staging/iio/Documentation/iio_utils.h

@@ -62,9 +62,8 @@ inline int find_type_by_name(const char *name, const char *type)
 					1) != 0) {
 				filename = malloc(strlen(iio_dir)
 						+ strlen(type)
-						+ 1
 						+ numstrlen
-						+ 1);
+						+ 6);
 				if (filename == NULL)
 					return -ENOMEM;
 				sprintf(filename, "%s%s%d/name",

+ 1 - 1
drivers/staging/iio/ring_sw.c

@@ -20,7 +20,7 @@ static inline int __iio_allocate_sw_ring_buffer(struct iio_sw_ring_buffer *ring,
 	if ((length == 0) || (bytes_per_datum == 0))
 		return -EINVAL;
 	__iio_update_ring_buffer(&ring->buf, bytes_per_datum, length);
-	ring->data = kmalloc(length*ring->buf.bpd, GFP_KERNEL);
+	ring->data = kmalloc(length*ring->buf.bpd, GFP_ATOMIC);
 	ring->read_p = NULL;
 	ring->write_p = NULL;
 	ring->last_written_p = NULL;

+ 7 - 0
drivers/staging/mrst-touchscreen/Kconfig

@@ -0,0 +1,7 @@
+config TOUCHSCREEN_INTEL_MID
+	tristate "Intel MID platform resistive touchscreen"
+	depends on INTEL_SCU_IPC
+	default y
+	help
+	  Say Y here if you have a Intel MID based touchscreen
+	  If unsure, say N.

+ 3 - 0
drivers/staging/mrst-touchscreen/Makefile

@@ -0,0 +1,3 @@
+obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) := intel_mid_touch.o
+
+

+ 2 - 0
drivers/staging/mrst-touchscreen/TODO

@@ -0,0 +1,2 @@
+- Move the driver to not think it is SPI (requires fixing some of the SFI
+  and firmware side)

+ 864 - 0
drivers/staging/mrst-touchscreen/intel-mid-touch.c

@@ -0,0 +1,864 @@
+/*
+ * intel_mid_touch.c - Intel MID Resistive Touch Screen Driver
+ *
+ * Copyright (C) 2008 Intel Corp
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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; ifnot, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Questions/Comments/Bug fixes to Sreedhara (sreedhara.ds@intel.com)
+ * 			    Ramesh Agarwal (ramesh.agarwal@intel.com)
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * TODO:
+ *	kill off mrstouch_debug eventually
+ *	review conversion of r/m/w sequences
+ *	Replace interrupt mutex abuse
+ *	Kill of mrstouchdevp pointer
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/param.h>
+#include <linux/spi/spi.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <asm/intel_scu_ipc.h>
+
+
+#if defined(MRSTOUCH_DEBUG)
+#define mrstouch_debug(fmt, args...)\
+	do { \
+		printk(KERN_DEBUG "\n[MRSTOUCH(%d)] - ", __LINE__); \
+		printk(KERN_DEBUG fmt, ##args); \
+	} while (0);
+#else
+#define mrstouch_debug(fmt, args...)
+#endif
+
+/* PMIC Interrupt registers */
+#define PMIC_REG_ID1   0x00 /*PMIC ID1 register */
+
+/* PMIC Interrupt registers */
+#define PMIC_REG_INT   0x04 /*PMIC interrupt register */
+#define PMIC_REG_MINT  0x05 /*PMIC interrupt mask register */
+
+/* ADC Interrupt registers */
+#define PMIC_REG_ADCINT   0x5F /*ADC interrupt register */
+#define PMIC_REG_MADCINT  0x60 /*ADC interrupt mask register */
+
+/* ADC Control registers */
+#define PMIC_REG_ADCCNTL1    0x61 /*ADC control register */
+
+/* ADC Channel Selection registers */
+#define PMICADDR0     0xA4
+#define END_OF_CHANNEL 0x1F
+
+/* ADC Result register */
+#define PMIC_REG_ADCSNS0H   0x64
+
+/* ADC channels for touch screen */
+#define MRST_TS_CHAN10   0xA /* Touch screen X+ connection */
+#define MRST_TS_CHAN11   0xB /* Touch screen X- connection */
+#define MRST_TS_CHAN12   0xC /* Touch screen Y+ connection */
+#define MRST_TS_CHAN13   0xD /* Touch screen Y- connection */
+
+/* Touch screen coordinate constants */
+#define TOUCH_PRESSURE   	50
+#define TOUCH_PRESSURE_FS	100
+
+#define XMOVE_LIMIT	5
+#define YMOVE_LIMIT	5
+#define XYMOVE_CNT	3
+
+#define MAX_10BIT	((1<<10)-1)
+
+/* Touch screen channel BIAS constants */
+#define XBIAS		0x20
+#define YBIAS		0x40
+#define ZBIAS		0x80
+
+/* Touch screen coordinates */
+#define MIN_X		10
+#define MAX_X		1024
+#define MIN_Y		10
+#define MAX_Y		1024
+#define WAIT_ADC_COMPLETION 10
+
+/* PMIC ADC round robin delays */
+#define ADC_LOOP_DELAY0 0x0 /* Continuous loop */
+#define ADC_LOOP_DELAY1 0x1 /* 4.5  ms approximate */
+
+/* PMIC Vendor Identifiers */
+#define PMIC_VENDOR_FS  0 /* PMIC vendor FreeScale */
+#define PMIC_VENDOR_MAXIM 1 /* PMIC vendor MAXIM */
+#define PMIC_VENDOR_NEC 2 /* PMIC vendor NEC */
+#define MRSTOUCH_MAX_CHANNELS 32 /* Maximum ADC channels */
+
+/* Touch screen device structure */
+struct mrstouch_dev {
+	struct spi_device *spi; /* SPI device associated with touch screen */
+	struct input_dev *input; /* input device for touchscreen*/
+	char 		phys[32]; /* Device name */
+	struct task_struct *pendet_thrd; /* PENDET interrupt handler */
+	struct mutex lock; /* Sync between interrupt and PENDET handler */
+	bool            busy; /* Busy flag */
+	u16             asr; /* Address selection register */
+	int             irq;    /* Touch screen IRQ # */
+	uint		vendor;  /* PMIC vendor */
+	uint		rev;  /* PMIC revision */
+	bool		suspended; /* Device suspended status */
+	bool		disabled;  /* Device disabled status */
+	u16		x;  /* X coordinate */
+	u16		y;  /* Y coordinate */
+	bool		pendown;  /* PEN position */
+} ;
+
+
+/* Global Pointer to Touch screen device */
+static struct mrstouch_dev *mrstouchdevp;
+
+/* Utility to read PMIC ID */
+static int mrstouch_pmic_id(uint *vendor, uint *rev)
+{
+	int err;
+	u8 r;
+
+	err = intel_scu_ipc_ioread8(PMIC_REG_ID1, &r);
+	if (err)
+		return err;
+
+	*vendor = r & 0x7;
+	*rev = (r >> 3) & 0x7;
+
+	return 0;
+}
+
+/*
+ * Parse ADC channels to find end of the channel configured by other ADC user
+ * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels
+ */
+static int mrstouch_chan_parse(struct mrstouch_dev *tsdev)
+{
+	int err, i, j, found;
+	u32 r32;
+
+	found = -1;
+
+	for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
+		if (found >= 0)
+			break;
+
+		err = intel_scu_ipc_ioread32(PMICADDR0, &r32);
+		if (err)
+			return err;
+
+		for (j = 0; j < 32; j+= 8) {
+			if (((r32 >> j) & 0xFF) == END_OF_CHANNEL) {
+				found = i;
+				break;
+			}
+		}
+	}
+	if (found < 0)
+		return 0;
+
+	if (tsdev->vendor == PMIC_VENDOR_FS) {
+		if (found && found > (MRSTOUCH_MAX_CHANNELS - 18))
+			return -ENOSPC;
+	} else {
+		if (found && found > (MRSTOUCH_MAX_CHANNELS - 4))
+			return -ENOSPC;
+	}
+	return found;
+}
+
+/* Utility to enable/disable pendet.
+ * pendet set to true enables PENDET interrupt
+ * pendet set to false disables PENDET interrupt
+ * Also clears RND mask bit
+*/
+static int pendet_enable(struct mrstouch_dev *tsdev, bool pendet)
+{
+	u16 reg;
+	u8 r;
+	u8 pendet_enabled = 0;
+	int retry = 0;
+	int err;
+
+	err = intel_scu_ipc_ioread16(PMIC_REG_MADCINT, &reg);
+	if (err)
+		return err;
+
+	if (pendet) {
+		reg &= ~0x0005;
+		reg |= 0x2000; /* Enable pendet */
+	} else
+		reg &= 0xDFFF; /* Disable pendet */
+
+	/* Set MADCINT and update ADCCNTL1 (next reg byte) */
+	err = intel_scu_ipc_iowrite16(PMIC_REG_MADCINT, reg);
+	if (!pendet || err)
+		return err;
+
+	/*
+	 * Sometimes even after the register write succeeds
+	 * the PMIC register value is not updated. Retry few iterations
+	 * to enable pendet.
+	 */
+
+	err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
+	pendet_enabled = (r >> 5) & 0x01;
+
+	retry = 0;
+	while (!err && !pendet_enabled) {
+		retry++;
+		msleep(10);
+		err = intel_scu_ipc_iowrite8(PMIC_REG_ADCCNTL1, reg >> 8);
+		if (err)
+			break;
+		err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
+		if (err == 0)
+			pendet_enabled = (r >> 5) & 0x01;
+		if (retry >= 10) {
+			dev_err(&tsdev->spi->dev, "Touch screen disabled.\n");
+			return -EIO;
+		}
+	}
+	return 0;
+}
+
+/* To read PMIC ADC touch screen result
+ * Reads ADC storage registers for higher 7 and lower 3 bits
+ * converts the two readings to single value and turns off gain bit
+ */
+static int mrstouch_ts_chan_read(u16 offset, u16 chan, u16 *vp, u16 *vm)
+{
+	int err;
+	u16 result;
+	u32 res;
+
+	result = PMIC_REG_ADCSNS0H + offset;
+
+	if (chan == MRST_TS_CHAN12)
+		result += 4;
+
+	err = intel_scu_ipc_ioread32(result, &res);
+	if (err)
+		return err;
+
+	/* Mash the bits up */
+
+	*vp = (res & 0xFF) << 3;	/* Highest 7 bits */
+	*vp |= (res >> 8) & 0x07;	/* Lower 3 bits */
+	*vp &= 0x3FF;
+
+	res >>= 16;
+
+	*vm = (res & 0xFF) << 3;	/* Highest 7 bits */
+	*vm |= (res >> 8) & 0x07;	/* Lower 3 bits */
+	*vm &= 0x3FF;
+
+	return 0;
+}
+
+/* To configure touch screen channels
+ * Writes touch screen channels to ADC address selection registers
+ */
+static int mrstouch_ts_chan_set(uint offset)
+{
+	int count;
+	u16 chan;
+	u16 reg[5];
+	u8 data[5];
+
+	chan = PMICADDR0 + offset;
+	for (count = 0; count <= 3; count++) {
+		reg[count] = chan++;
+		data[count] = MRST_TS_CHAN10 + count;
+	}
+	reg[count] = chan;
+	data[count] = END_OF_CHANNEL;
+
+	return intel_scu_ipc_writev(reg, data, 5);
+}
+
+/* Initialize ADC */
+static int mrstouch_adc_init(struct mrstouch_dev *tsdev)
+{
+	int err, start;
+	u8 ra, rm;
+
+	err = mrstouch_pmic_id(&tsdev->vendor, &tsdev->rev);
+	if (err) {
+		dev_err(&tsdev->spi->dev, "Unable to read PMIC id\n");
+		return err;
+	}
+
+	start = mrstouch_chan_parse(tsdev);
+	if (start < 0) {
+		dev_err(&tsdev->spi->dev, "Unable to parse channels\n");
+		return start;
+	}
+
+	tsdev->asr = start;
+
+	mrstouch_debug("Channel offset(%d): 0x%X\n", tsdev->asr, tsdev->vendor);
+
+	/* ADC power on, start, enable PENDET and set loop delay
+	 * ADC loop delay is set to 4.5 ms approximately
+	 * Loop delay more than this results in jitter in adc readings
+	 * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET
+	 * interrupt generation sometimes.
+	 */
+
+	if (tsdev->vendor == PMIC_VENDOR_FS) {
+		ra = 0xE0 | ADC_LOOP_DELAY0;
+		rm = 0x5;
+	} else {
+		/* NEC and MAXIm not consistent with loop delay 0 */
+		ra = 0xE0 | ADC_LOOP_DELAY1;
+		rm = 0x0;
+
+		/* configure touch screen channels */
+		err = mrstouch_ts_chan_set(tsdev->asr);
+		if (err)
+			return err;
+	}
+	err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, ra, 0xE7);
+	if (err == 0)
+		err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, rm, 0x03);
+	return err;
+}
+
+/* Reports x,y coordinates to event subsystem */
+static void mrstouch_report_xy(struct mrstouch_dev *tsdev, u16 x, u16 y, u16 z)
+{
+	int xdiff, ydiff;
+
+	if (tsdev->pendown && z <= TOUCH_PRESSURE) {
+		/* Pen removed, report button release */
+		mrstouch_debug("BTN REL(%d)", z);
+		input_report_key(tsdev->input, BTN_TOUCH, 0);
+		tsdev->pendown = false;
+	}
+
+	xdiff = abs(x - tsdev->x);
+	ydiff = abs(y - tsdev->y);
+
+	/*
+	if x and y values changes for XYMOVE_CNT readings it is considered
+	as stylus is moving. This is required to differentiate between stylus
+	movement and jitter
+	*/
+	if (x < MIN_X || x > MAX_X || y < MIN_Y || y > MAX_Y) {
+		/* Spurious values, release button if touched and return */
+		if (tsdev->pendown) {
+			mrstouch_debug("BTN REL(%d)", z);
+			input_report_key(tsdev->input, BTN_TOUCH, 0);
+			tsdev->pendown = false;
+		}
+		return;
+	} else if (xdiff >= XMOVE_LIMIT || ydiff >= YMOVE_LIMIT) {
+		tsdev->x = x;
+		tsdev->y = y;
+
+		input_report_abs(tsdev->input, ABS_X, x);
+		input_report_abs(tsdev->input, ABS_Y, y);
+		input_sync(tsdev->input);
+	}
+
+
+	if (!tsdev->pendown && z > TOUCH_PRESSURE) {
+		/* Pen touched, report button touch */
+		mrstouch_debug("BTN TCH(%d, %d, %d)", x, y, z);
+		input_report_key(tsdev->input, BTN_TOUCH, 1);
+		tsdev->pendown = true;
+	}
+}
+
+
+/* Utility to start ADC, used by freescale handler */
+static int pendet_mask(void)
+{
+	return 	intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x02, 0x02);
+}
+
+/* Utility to stop ADC, used by freescale handler */
+static int pendet_umask(void)
+{
+	return 	intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x00, 0x02);
+}
+
+/* Utility to read ADC, used by freescale handler */
+static int mrstouch_pmic_fs_adc_read(struct mrstouch_dev *tsdev)
+{
+	int err;
+	u16 x, y, z, result;
+	u16 reg[4];
+	u8 data[4];
+
+	result = PMIC_REG_ADCSNS0H + tsdev->asr;
+
+	reg[0] = result + 4;
+	reg[1] = result + 5;
+	reg[2] = result + 16;
+	reg[3] = result + 17;
+
+	err = intel_scu_ipc_readv(reg, data, 4);
+	if (err)
+		goto ipc_error;
+
+	x = data[0] << 3; /* Higher 7 bits */
+	x |= data[1] & 0x7; /* Lower 3 bits */
+	x &= 0x3FF;
+
+	y = data[2] << 3; /* Higher 7 bits */
+	y |= data[3] & 0x7; /* Lower 3 bits */
+	y &= 0x3FF;
+
+	/* Read Z value */
+	reg[0] = result + 28;
+	reg[1] = result + 29;
+
+	err = intel_scu_ipc_readv(reg, data, 4);
+	if (err)
+		goto ipc_error;
+
+	z = data[0] << 3; /* Higher 7 bits */
+	z |= data[1] & 0x7; /* Lower 3 bits */
+	z &= 0x3FF;
+
+#if defined(MRSTOUCH_PRINT_XYZP)
+	mrstouch_debug("X: %d, Y: %d, Z: %d", x, y, z);
+#endif
+
+	if (z >= TOUCH_PRESSURE_FS) {
+		mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE - 1); /* Pen Removed */
+		return TOUCH_PRESSURE - 1;
+	} else {
+		mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE + 1); /* Pen Touched */
+		return TOUCH_PRESSURE + 1;
+	}
+
+	return 0;
+
+ipc_error:
+	dev_err(&tsdev->spi->dev, "ipc error during fs_adc read\n");
+	return err;
+}
+
+/* To handle free scale pmic pendet interrupt */
+static int pmic0_pendet(void *dev_id)
+{
+	int err, count;
+	u16 chan;
+	unsigned int touched;
+	struct mrstouch_dev *tsdev = (struct mrstouch_dev *)dev_id;
+	u16 reg[5];
+	u8 data[5];
+
+	chan = PMICADDR0 + tsdev->asr;
+
+	/* Set X BIAS */
+	for (count = 0; count <= 3; count++) {
+		reg[count] = chan++;
+		data[count] = 0x2A;
+	}
+	reg[count] =  chan++; /* Dummy */
+	data[count] = 0;
+
+	err = intel_scu_ipc_writev(reg, data, 5);
+	if (err)
+		goto ipc_error;
+
+	msleep(WAIT_ADC_COMPLETION);
+
+	/* Set Y BIAS */
+	for (count = 0; count <= 3; count++) {
+		reg[count] = chan++;
+		data[count] = 0x4A;
+	}
+	reg[count] = chan++; /* Dummy */
+	data[count] = 0;
+
+	err = intel_scu_ipc_writev(reg, data, 5);
+	if (err)
+		goto ipc_error;
+
+	msleep(WAIT_ADC_COMPLETION);
+
+	/* Set Z BIAS */
+	err = intel_scu_ipc_iowrite32(chan + 2, 0x8A8A8A8A);
+	if (err)
+		goto ipc_error;
+
+	msleep(WAIT_ADC_COMPLETION);
+
+	/*Read touch screen channels till pen removed
+	 * Freescale reports constant value of z for all points
+	 * z is high when screen is not touched and low when touched
+	 * Map high z value to not touched and low z value to pen touched
+	 */
+	touched = mrstouch_pmic_fs_adc_read(tsdev);
+	while (touched > TOUCH_PRESSURE) {
+		touched = mrstouch_pmic_fs_adc_read(tsdev);
+		msleep(WAIT_ADC_COMPLETION);
+	}
+
+	/* Clear all TS channels */
+	chan = PMICADDR0 + tsdev->asr;
+	for (count = 0; count <= 4; count++) {
+		reg[count] = chan++;
+		data[count] = 0;
+	}
+	err = intel_scu_ipc_writev(reg, data, 5);
+	if (err)
+		goto ipc_error;
+
+	for (count = 0; count <= 4; count++) {
+		reg[count] = chan++;
+		data[count] = 0;
+	}
+	err = intel_scu_ipc_writev(reg, data, 5);
+	if (err)
+		goto ipc_error;
+
+	err = intel_scu_ipc_iowrite32(chan + 2, 0x00000000);
+	if (err)
+		goto ipc_error;
+
+	return 0;
+
+ipc_error:
+	dev_err(&tsdev->spi->dev, "ipc error during pendet\n");
+	return err;
+}
+
+
+/* To enable X, Y and Z bias values
+ * Enables YPYM for X channels and XPXM for Y channels
+ */
+static int mrstouch_ts_bias_set(uint offset, uint bias)
+{
+	int count;
+	u16 chan, start;
+	u16 reg[4];
+	u8 data[4];
+
+	chan = PMICADDR0 + offset;
+	start = MRST_TS_CHAN10;
+
+	for (count = 0; count <= 3; count++) {
+		reg[count] = chan++;
+		data[count] = bias | (start + count);
+	}
+	return intel_scu_ipc_writev(reg, data, 4);
+}
+
+/* To read touch screen channel values */
+static int mrstouch_adc_read(struct mrstouch_dev *tsdev)
+{
+	int err;
+	u16 xp, xm, yp, ym, zp, zm;
+
+	/* configure Y bias for X channels */
+	err = mrstouch_ts_bias_set(tsdev->asr, YBIAS);
+	if (err)
+		goto ipc_error;
+
+	msleep(WAIT_ADC_COMPLETION);
+
+	/* read x+ and x- channels */
+	err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &xp, &xm);
+	if (err)
+		goto ipc_error;
+
+	/* configure x bias for y channels */
+	err = mrstouch_ts_bias_set(tsdev->asr, XBIAS);
+	if (err)
+		goto ipc_error;
+
+	msleep(WAIT_ADC_COMPLETION);
+
+	/* read y+ and y- channels */
+	err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN12, &yp, &ym);
+	if (err)
+		goto ipc_error;
+
+	/* configure z bias for x and y channels */
+	err = mrstouch_ts_bias_set(tsdev->asr, ZBIAS);
+	if (err)
+		goto ipc_error;
+
+	msleep(WAIT_ADC_COMPLETION);
+
+	/* read z+ and z- channels */
+	err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &zp, &zm);
+	if (err)
+		goto ipc_error;
+
+#if defined(MRSTOUCH_PRINT_XYZP)
+	printk(KERN_INFO "X+: %d, Y+: %d, Z+: %d\n", xp, yp, zp);
+#endif
+
+#if defined(MRSTOUCH_PRINT_XYZM)
+	printk(KERN_INFO "X-: %d, Y-: %d, Z-: %d\n", xm, ym, zm);
+#endif
+
+	mrstouch_report_xy(tsdev, xp, yp, zp); /* report x and y to eventX */
+
+	return zp;
+
+ipc_error:
+	dev_err(&tsdev->spi->dev, "ipc error during adc read\n");
+	return err;
+}
+
+/* PENDET interrupt handler function for NEC and MAXIM */
+static void pmic12_pendet(void *data)
+{
+	unsigned int touched;
+	struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
+
+	/* read touch screen channels till pen removed */
+	do {
+		touched = mrstouch_adc_read(tsdev);
+	} while (touched > TOUCH_PRESSURE);
+}
+
+/* Handler to process PENDET interrupt */
+int mrstouch_pendet(void *data)
+{
+	struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
+	while (1) {
+		/* Wait for PENDET interrupt */
+		if (mutex_lock_interruptible(&tsdev->lock)) {
+			msleep(WAIT_ADC_COMPLETION);
+			continue;
+		}
+
+		if (tsdev->busy)
+			return 0;
+
+		tsdev->busy = true;
+
+		if (tsdev->vendor == PMIC_VENDOR_NEC ||
+			tsdev->vendor == PMIC_VENDOR_MAXIM) {
+			/* PENDET must be disabled in NEC before reading ADC */
+			pendet_enable(tsdev,false); /* Disbale PENDET */
+			pmic12_pendet(tsdev);
+			pendet_enable(tsdev, true); /*Enable PENDET */
+		} else if (tsdev->vendor == PMIC_VENDOR_FS) {
+			pendet_umask(); /* Stop ADC */
+			pmic0_pendet(tsdev);
+			pendet_mask(); /* Stop ADC */
+		} else
+		dev_err(&tsdev->spi->dev, "Unsupported touchscreen: %d\n",
+				tsdev->vendor);
+
+		tsdev->busy = false;
+
+	}
+	return 0;
+}
+
+/* PENDET interrupt handler */
+static irqreturn_t pendet_intr_handler(int irq, void *handle)
+{
+	struct mrstouch_dev *tsdev = (struct mrstouch_dev *)handle;
+
+	mutex_unlock(&tsdev->lock);
+	return IRQ_HANDLED;
+}
+
+/* Intializes input device and registers with input subsystem */
+static int ts_input_dev_init(struct mrstouch_dev *tsdev, struct spi_device *spi)
+{
+	int err = 0;
+
+	mrstouch_debug("%s", __func__);
+
+	tsdev->input = input_allocate_device();
+	if (!tsdev->input) {
+		dev_err(&tsdev->spi->dev, "Unable to allocate input device.\n");
+		return -EINVAL;
+	}
+
+	tsdev->input->name = "mrst_touchscreen";
+	snprintf(tsdev->phys, sizeof(tsdev->phys),
+			"%s/input0", dev_name(&spi->dev));
+	tsdev->input->phys = tsdev->phys;
+	tsdev->input->dev.parent = &spi->dev;
+
+	tsdev->input->id.vendor = tsdev->vendor;
+	tsdev->input->id.version = tsdev->rev;
+
+	tsdev->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	tsdev->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	input_set_abs_params(tsdev->input, ABS_X, MIN_X, MIN_Y, 0, 0);
+	input_set_abs_params(tsdev->input, ABS_Y, MIN_X, MIN_Y, 0, 0);
+
+	err = input_register_device(tsdev->input);
+	if (err) {
+		dev_err(&tsdev->spi->dev, "unable to register input device\n");
+		input_free_device(tsdev->input);
+		return err;
+	}
+
+	mrstouch_debug("%s", "mrstouch initialized");
+
+	return 0;
+
+}
+
+/* Probe function for touch screen driver */
+static int __devinit mrstouch_probe(struct spi_device *mrstouch_spi)
+{
+	int err;
+	unsigned int myirq;
+	struct mrstouch_dev *tsdev;
+
+	mrstouch_debug("%s(%p)", __func__, mrstouch_spi);
+
+	mrstouchdevp = NULL;
+	myirq = mrstouch_spi->irq;
+
+	if (!mrstouch_spi->irq) {
+		dev_err(&mrstouch_spi->dev, "no interrupt assigned\n");
+		return -EINVAL;
+	}
+
+	tsdev = kzalloc(sizeof(struct mrstouch_dev), GFP_KERNEL);
+	if (!tsdev) {
+		dev_err(&mrstouch_spi->dev, "unable to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	tsdev->irq = myirq;
+	mrstouchdevp = tsdev;
+
+	err = mrstouch_adc_init(tsdev);
+	if (err) {
+		dev_err(&mrstouch_spi->dev, "ADC init failed\n");
+		goto mrstouch_err_free_mem;
+	}
+
+	dev_set_drvdata(&mrstouch_spi->dev, tsdev);
+	tsdev->spi = mrstouch_spi;
+
+	err = ts_input_dev_init(tsdev, mrstouch_spi);
+	if (err) {
+		dev_err(&tsdev->spi->dev, "ts_input_dev_init failed");
+		goto mrstouch_err_free_mem;
+	}
+
+	mutex_init(&tsdev->lock);
+	mutex_lock(&tsdev->lock)
+
+	mrstouch_debug("Requesting IRQ-%d", myirq);
+	err = request_irq(myirq, pendet_intr_handler,
+				0, "mrstouch", tsdev);
+	if (err) {
+		dev_err(&tsdev->spi->dev, "unable to allocate irq\n");
+		goto mrstouch_err_free_mem;
+	}
+
+	tsdev->pendet_thrd = kthread_run(mrstouch_pendet,
+				(void *)tsdev, "pendet handler");
+	if (IS_ERR(tsdev->pendet_thrd)) {
+		dev_err(&tsdev->spi->dev, "kthread_run failed\n");
+		err = PTR_ERR(tsdev->pendet_thrd);
+		goto mrstouch_err_free_mem;
+	}
+	mrstouch_debug("%s", "Driver initialized");
+	return 0;
+
+mrstouch_err_free_mem:
+	kfree(tsdev);
+	return err;
+}
+
+static int mrstouch_suspend(struct spi_device *spi, pm_message_t msg)
+{
+	mrstouch_debug("%s", __func__);
+	mrstouchdevp->suspended = 1;
+	return 0;
+}
+
+static int mrstouch_resume(struct spi_device *spi)
+{
+	mrstouch_debug("%s", __func__);
+	mrstouchdevp->suspended = 0;
+	return 0;
+}
+
+static int mrstouch_remove(struct spi_device *spi)
+{
+	mrstouch_debug("%s", __func__);
+	free_irq(mrstouchdevp->irq, mrstouchdevp);
+	input_unregister_device(mrstouchdevp->input);
+	input_free_device(mrstouchdevp->input);
+	kfree(mrstouchdevp);
+	if (mrstouchdevp->pendet_thrd)
+		kthread_stop(mrstouchdevp->pendet_thrd);
+	return 0;
+}
+
+static struct spi_driver mrstouch_driver = {
+	.driver = {
+		.name   = "pmic_touch",
+		.bus    = &spi_bus_type,
+		.owner  = THIS_MODULE,
+	},
+	.probe          = mrstouch_probe,
+	.suspend        = mrstouch_suspend,
+	.resume         = mrstouch_resume,
+	.remove         = mrstouch_remove,
+};
+
+static int __init mrstouch_module_init(void)
+{
+	int err;
+
+	mrstouch_debug("%s", __func__);
+	err = spi_register_driver(&mrstouch_driver);
+	if (err) {
+		mrstouch_debug("%s(%d)", "SPI PENDET failed", err);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void __exit mrstouch_module_exit(void)
+{
+	mrstouch_debug("%s", __func__);
+	spi_unregister_driver(&mrstouch_driver);
+	return;
+}
+
+module_init(mrstouch_module_init);
+module_exit(mrstouch_module_exit);
+
+MODULE_AUTHOR("Sreedhara Murthy. D.S, sreedhara.ds@intel.com");
+MODULE_DESCRIPTION("Intel Moorestown Resistive Touch Screen Driver");
+MODULE_LICENSE("GPL");

+ 134 - 0
drivers/staging/msm/Kconfig

@@ -0,0 +1,134 @@
+config MSM_STAGING
+	tristate "MSM Frame Buffer Support"
+	depends on FB && ARCH_MSM && !FB_MSM
+	select FB_BACKLIGHT if FB_MSM_BACKLIGHT
+	select NEW_LEDS
+	select LEDS_CLASS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Support for MSM Framebuffer.
+
+if MSM_STAGING
+
+config FB_MSM_LCDC_HW
+	bool
+	default n
+
+choice
+	prompt "MDP HW version"
+	default FB_MSM_MDP31
+
+config FB_MSM_MDP31
+	select FB_MSM_LCDC_HW
+	bool "MDP HW ver3.1"
+	---help---
+	  Support for MSM MDP HW revision 3.1
+	  Say Y here if this is msm8x50 variant platform.
+endchoice
+
+config FB_MSM_LCDC
+	bool
+	default n
+
+config FB_MSM_TVOUT
+	bool
+	default n
+
+config FB_MSM_LCDC_PANEL
+	bool
+	select FB_MSM_LCDC
+	default n
+
+config FB_MSM_LCDC_PRISM_WVGA
+        bool
+	select FB_MSM_LCDC_PANEL
+	default n
+
+config FB_MSM_LCDC_ST1_WXGA
+	bool
+	select FB_MSM_LCDC_PANEL
+	default n
+
+config FB_MSM_LCDC_ST15_WXGA
+        bool
+        select FB_MSM_LCDC_PANEL
+        default n
+
+config FB_MSM_LCDC_WXGA
+	bool
+	select FB_MSM_LCDC_PANEL
+	default n
+
+choice
+	prompt "LCD Panel"
+	default FB_MSM_LCDC_ST15_PANEL
+
+config FB_MSM_LCDC_PRISM_WVGA_PANEL
+	depends on FB_MSM_LCDC_HW
+	bool "LCDC Prism WVGA Panel"
+	select FB_MSM_LCDC_PRISM_WVGA
+	---help---
+	  Support for LCDC Prism WVGA (800x480) panel
+
+
+config FB_MSM_LCDC_ST15_PANEL
+        depends on FB_MSM_LCDC_HW
+        bool "LCDC ST1.5 Panel"
+        select FB_MSM_LCDC_ST15_WXGA
+        ---help---
+          Support for ST1.5 WXGA (1366x768) panel
+
+config FB_MSM_PANEL_NONE
+	bool "NONE"
+	---help---
+	  This will disable LCD panel
+endchoice
+
+choice
+	prompt "Secondary LCD Panel"
+	depends on  FB_MSM_MDP31
+	default FB_MSM_SECONDARY_PANEL_NONE
+
+config FB_MSM_SECONDARY_PANEL_NONE
+	bool "NONE"
+	---help---
+	  No secondary panel
+endchoice
+
+config FB_MSM_TVOUT_NTSC
+	bool
+	select FB_MSM_TVOUT
+	default n
+
+config FB_MSM_TVOUT_PAL
+	bool
+	select FB_MSM_TVOUT
+	default n
+
+choice
+	depends on  (FB_MSM_MDP22 || FB_MSM_MDP31)
+	prompt "TVOut Region"
+	default FB_MSM_TVOUT_NTSC_M
+
+config FB_MSM_TVOUT_NTSC_M
+	bool "NTSC M"
+	select FB_MSM_TVOUT_NTSC
+	---help---
+	  Support for NTSC M region (North American and Korea)
+
+config FB_MSM_TVOUT_NONE
+	bool "NONE"
+	---help---
+	  This will disable TV Out functionality.
+endchoice
+
+config PMEM_KERNEL_SIZE
+        int "PMEM for kernel components (in MB)"
+        default 2
+        depends on ARCH_QSD8X50
+        help
+          Configures the amount of PMEM for use by kernel components
+          (in MB; minimum 2MB)
+endif

+ 93 - 0
drivers/staging/msm/Makefile

@@ -0,0 +1,93 @@
+obj-y := msm_fb.o staging-devices.o memory.o
+
+obj-$(CONFIG_FB_MSM_LOGO) += logo.o
+obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o
+
+# MDP
+obj-y += mdp.o
+
+ifeq ($(CONFIG_FB_MSM_MDP40),y)
+obj-y += mdp4_util.o
+obj-$(CONFIG_DEBUG_FS) += mdp4_debugfs.o
+else
+obj-y += mdp_hw_init.o
+obj-y += mdp_ppp.o
+ifeq ($(CONFIG_FB_MSM_MDP31),y)
+obj-y += mdp_ppp_v31.o
+obj-$(CONFIG_MDP_PPP_ASYNC_OP) += mdp_ppp_dq.o
+else
+obj-y += mdp_ppp_v20.o
+endif
+endif
+
+ifeq ($(CONFIG_FB_MSM_OVERLAY),y)
+obj-y += mdp4_overlay.o
+obj-y += mdp4_overlay_lcdc.o
+obj-y += mdp4_overlay_mddi.o
+else
+obj-y += mdp_dma_lcdc.o
+endif
+
+obj-y += mdp_dma.o
+obj-y += mdp_dma_s.o
+obj-y += mdp_vsync.o
+obj-y += mdp_cursor.o
+obj-y += mdp_dma_tv.o
+
+# EBI2
+obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o
+
+# LCDC
+obj-$(CONFIG_FB_MSM_LCDC) += lcdc.o
+
+# MDDI
+msm_mddi-objs := mddi.o mddihost.o mddihosti.o
+obj-$(CONFIG_FB_MSM_MDDI) += msm_mddi.o
+
+# External MDDI
+msm_mddi_ext-objs := mddihost_e.o mddi_ext.o
+obj-$(CONFIG_FB_MSM_EXTMDDI) += msm_mddi_ext.o
+
+# TVEnc
+obj-$(CONFIG_FB_MSM_TVOUT) += tvenc.o
+
+# MSM FB Panel
+obj-y += msm_fb_panel.o
+obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_tmd20.o
+obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_l2f.o
+
+ifeq ($(CONFIG_FB_MSM_MDDI_AUTO_DETECT),y)
+obj-y += mddi_prism.o
+obj-y += mddi_toshiba.o
+obj-y += mddi_toshiba_vga.o
+obj-y += mddi_toshiba_wvga_pt.o
+obj-y += mddi_toshiba_wvga.o
+obj-y += mddi_sharp.o
+else
+obj-$(CONFIG_FB_MSM_MDDI_PRISM_WVGA) += mddi_prism.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON) += mddi_toshiba.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON_VGA) += mddi_toshiba_vga.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA_PORTRAIT) += mddi_toshiba_wvga_pt.o
+obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA) += mddi_toshiba_wvga.o
+obj-$(CONFIG_FB_MSM_MDDI_SHARP_QVGA_128x128) += mddi_sharp.o
+endif
+
+obj-$(CONFIG_FB_MSM_LCDC_PANEL) += lcdc_panel.o
+obj-$(CONFIG_FB_MSM_LCDC_PRISM_WVGA) += lcdc_prism.o
+obj-$(CONFIG_FB_MSM_LCDC_EXTERNAL_WXGA) += lcdc_external.o
+obj-$(CONFIG_FB_MSM_LCDC_GORDON_VGA) += lcdc_gordon.o
+obj-$(CONFIG_FB_MSM_LCDC_WXGA) += lcdc_wxga.o
+obj-$(CONFIG_FB_MSM_LCDC_TOSHIBA_WVGA_PT) += lcdc_toshiba_wvga_pt.o
+obj-$(CONFIG_FB_MSM_LCDC_SHARP_WVGA_PT) += lcdc_sharp_wvga_pt.o
+obj-$(CONFIG_FB_MSM_LCDC_GRAPEFRUIT_VGA) += lcdc_grapefruit.o
+obj-$(CONFIG_FB_MSM_LCDC_ST1_WXGA) += lcdc_st1_wxga.o
+obj-$(CONFIG_FB_MSM_LCDC_ST15_WXGA) += lcdc_st15.o
+obj-$(CONFIG_FB_MSM_HDMI_SII_EXTERNAL_720P) += hdmi_sii9022.o
+
+obj-$(CONFIG_FB_MSM_TVOUT_NTSC) += tv_ntsc.o
+obj-$(CONFIG_FB_MSM_TVOUT_PAL) += tv_pal.o
+
+obj-$(CONFIG_FB_MSM_EXTMDDI_SVGA) += mddi_ext_lcd.o
+
+clean:
+	rm *.o .*cmd

+ 3 - 0
drivers/staging/msm/TODO

@@ -0,0 +1,3 @@
+- Merge this code with the existing MSM framebuffer
+- General style clean ups.
+

+ 569 - 0
drivers/staging/msm/ebi2_l2f.c

@@ -0,0 +1,569 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+#include <linux/memory.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+/* The following are for MSM5100 on Gator
+*/
+#ifdef FEATURE_PM1000
+#include "pm1000.h"
+#endif /* FEATURE_PM1000 */
+/* The following are for MSM6050 on Bambi
+*/
+#ifdef FEATURE_PMIC_LCDKBD_LED_DRIVER
+#include "pm.h"
+#endif /* FEATURE_PMIC_LCDKBD_LED_DRIVER */
+
+#ifdef DISP_DEVICE_18BPP
+#undef DISP_DEVICE_18BPP
+#define DISP_DEVICE_16BPP
+#endif
+
+#define QCIF_WIDTH        176
+#define QCIF_HEIGHT       220
+
+static void *DISP_CMD_PORT;
+static void *DISP_DATA_PORT;
+
+#define DISP_CMD_DISON    0xaf
+#define DISP_CMD_DISOFF   0xae
+#define DISP_CMD_DISNOR   0xa6
+#define DISP_CMD_DISINV   0xa7
+#define DISP_CMD_DISCTL   0xca
+#define DISP_CMD_GCP64    0xcb
+#define DISP_CMD_GCP16    0xcc
+#define DISP_CMD_GSSET    0xcd
+#define DISP_GS_2       0x02
+#define DISP_GS_16      0x01
+#define DISP_GS_64      0x00
+#define DISP_CMD_SLPIN    0x95
+#define DISP_CMD_SLPOUT   0x94
+#define DISP_CMD_SD_PSET  0x75
+#define DISP_CMD_MD_PSET  0x76
+#define DISP_CMD_SD_CSET  0x15
+#define DISP_CMD_MD_CSET  0x16
+#define DISP_CMD_DATCTL   0xbc
+#define DISP_DATCTL_666 0x08
+#define DISP_DATCTL_565 0x28
+#define DISP_DATCTL_444 0x38
+#define DISP_CMD_RAMWR    0x5c
+#define DISP_CMD_RAMRD    0x5d
+#define DISP_CMD_PTLIN    0xa8
+#define DISP_CMD_PTLOUT   0xa9
+#define DISP_CMD_ASCSET   0xaa
+#define DISP_CMD_SCSTART  0xab
+#define DISP_CMD_VOLCTL   0xc6
+#define DISP_VOLCTL_TONE 0x80
+#define DISP_CMD_NOp      0x25
+#define DISP_CMD_OSSEL    0xd0
+#define DISP_CMD_3500KSET 0xd1
+#define DISP_CMD_3500KEND 0xd2
+#define DISP_CMD_14MSET   0xd3
+#define DISP_CMD_14MEND   0xd4
+
+#define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, cmd);
+
+#define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, data);
+
+#define DISP_DATA_IN() inpw(DISP_DATA_PORT);
+
+/* Epson device column number starts at 2
+*/
+#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
+	  DISP_CMD_OUT(DISP_CMD_SD_PSET) \
+	  DISP_DATA_OUT((ulhc_row) & 0xFF) \
+	  DISP_DATA_OUT((ulhc_row) >> 8) \
+	  DISP_DATA_OUT((lrhc_row) & 0xFF) \
+	  DISP_DATA_OUT((lrhc_row) >> 8) \
+	  DISP_CMD_OUT(DISP_CMD_SD_CSET) \
+	  DISP_DATA_OUT(((ulhc_col)+2) & 0xFF) \
+	  DISP_DATA_OUT(((ulhc_col)+2) >> 8) \
+	  DISP_DATA_OUT(((lrhc_col)+2) & 0xFF) \
+	  DISP_DATA_OUT(((lrhc_col)+2) >> 8)
+
+#define DISP_MIN_CONTRAST      0
+#define DISP_MAX_CONTRAST      127
+#define DISP_DEFAULT_CONTRAST  80
+
+#define DISP_MIN_BACKLIGHT     0
+#define DISP_MAX_BACKLIGHT     15
+#define DISP_DEFAULT_BACKLIGHT 2
+
+#define WAIT_SEC(sec) mdelay((sec)/1000)
+
+static word disp_area_start_row;
+static word disp_area_end_row;
+static byte disp_contrast = DISP_DEFAULT_CONTRAST;
+static boolean disp_powered_up;
+static boolean disp_initialized = FALSE;
+/* For some reason the contrast set at init time is not good. Need to do
+ * it again
+ */
+static boolean display_on = FALSE;
+static void epsonQcif_disp_init(struct platform_device *pdev);
+static void epsonQcif_disp_set_contrast(word contrast);
+static void epsonQcif_disp_set_display_area(word start_row, word end_row);
+static int epsonQcif_disp_off(struct platform_device *pdev);
+static int epsonQcif_disp_on(struct platform_device *pdev);
+static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres);
+
+volatile word databack;
+static void epsonQcif_disp_init(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+
+	int i;
+
+	if (disp_initialized)
+		return;
+
+	mfd = platform_get_drvdata(pdev);
+
+	DISP_CMD_PORT = mfd->cmd_port;
+	DISP_DATA_PORT = mfd->data_port;
+
+	/* Sleep in */
+	DISP_CMD_OUT(DISP_CMD_SLPIN);
+
+	/* Display off */
+	DISP_CMD_OUT(DISP_CMD_DISOFF);
+
+	/* Display normal */
+	DISP_CMD_OUT(DISP_CMD_DISNOR);
+
+	/* Set data mode */
+	DISP_CMD_OUT(DISP_CMD_DATCTL);
+	DISP_DATA_OUT(DISP_DATCTL_565);
+
+	/* Set display timing */
+	DISP_CMD_OUT(DISP_CMD_DISCTL);
+	DISP_DATA_OUT(0x1c);	/* p1 */
+	DISP_DATA_OUT(0x02);	/* p1 */
+	DISP_DATA_OUT(0x82);	/* p2 */
+	DISP_DATA_OUT(0x00);	/* p3 */
+	DISP_DATA_OUT(0x00);	/* p4 */
+	DISP_DATA_OUT(0xe0);	/* p5 */
+	DISP_DATA_OUT(0x00);	/* p5 */
+	DISP_DATA_OUT(0xdc);	/* p6 */
+	DISP_DATA_OUT(0x00);	/* p6 */
+	DISP_DATA_OUT(0x02);	/* p7 */
+	DISP_DATA_OUT(0x00);	/* p8 */
+
+	/* Set 64 gray scale level */
+	DISP_CMD_OUT(DISP_CMD_GCP64);
+	DISP_DATA_OUT(0x08);	/* p01 */
+	DISP_DATA_OUT(0x00);
+	DISP_DATA_OUT(0x2a);	/* p02 */
+	DISP_DATA_OUT(0x00);
+	DISP_DATA_OUT(0x4e);	/* p03 */
+	DISP_DATA_OUT(0x00);
+	DISP_DATA_OUT(0x6b);	/* p04 */
+	DISP_DATA_OUT(0x00);
+	DISP_DATA_OUT(0x88);	/* p05 */
+	DISP_DATA_OUT(0x00);
+	DISP_DATA_OUT(0xa3);	/* p06 */
+	DISP_DATA_OUT(0x00);
+	DISP_DATA_OUT(0xba);	/* p07 */
+	DISP_DATA_OUT(0x00);
+	DISP_DATA_OUT(0xd1);	/* p08 */
+	DISP_DATA_OUT(0x00);
+	DISP_DATA_OUT(0xe5);	/* p09 */
+	DISP_DATA_OUT(0x00);
+	DISP_DATA_OUT(0xf3);	/* p10 */
+	DISP_DATA_OUT(0x00);
+	DISP_DATA_OUT(0x03);	/* p11 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x13);	/* p12 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x22);	/* p13 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x2f);	/* p14 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x3b);	/* p15 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x46);	/* p16 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x51);	/* p17 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x5b);	/* p18 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x64);	/* p19 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x6c);	/* p20 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x74);	/* p21 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x7c);	/* p22 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x83);	/* p23 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x8a);	/* p24 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x91);	/* p25 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x98);	/* p26 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x9f);	/* p27 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xa6);	/* p28 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xac);	/* p29 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xb2);	/* p30 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xb7);	/* p31 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xbc);	/* p32 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xc1);	/* p33 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xc6);	/* p34 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xcb);	/* p35 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xd0);	/* p36 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xd4);	/* p37 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xd8);	/* p38 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xdc);	/* p39 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xe0);	/* p40 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xe4);	/* p41 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xe8);	/* p42 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xec);	/* p43 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xf0);	/* p44 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xf4);	/* p45 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xf8);	/* p46 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xfb);	/* p47 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xfe);	/* p48 */
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0x01);	/* p49 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x03);	/* p50 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x05);	/* p51 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x07);	/* p52 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x09);	/* p53 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x0b);	/* p54 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x0d);	/* p55 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x0f);	/* p56 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x11);	/* p57 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x13);	/* p58 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x15);	/* p59 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x17);	/* p60 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x19);	/* p61 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x1b);	/* p62 */
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x1c);	/* p63 */
+	DISP_DATA_OUT(0x02);
+
+	/* Set 16 gray scale level */
+	DISP_CMD_OUT(DISP_CMD_GCP16);
+	DISP_DATA_OUT(0x1a);	/* p01 */
+	DISP_DATA_OUT(0x32);	/* p02 */
+	DISP_DATA_OUT(0x42);	/* p03 */
+	DISP_DATA_OUT(0x4c);	/* p04 */
+	DISP_DATA_OUT(0x58);	/* p05 */
+	DISP_DATA_OUT(0x5f);	/* p06 */
+	DISP_DATA_OUT(0x66);	/* p07 */
+	DISP_DATA_OUT(0x6b);	/* p08 */
+	DISP_DATA_OUT(0x70);	/* p09 */
+	DISP_DATA_OUT(0x74);	/* p10 */
+	DISP_DATA_OUT(0x78);	/* p11 */
+	DISP_DATA_OUT(0x7b);	/* p12 */
+	DISP_DATA_OUT(0x7e);	/* p13 */
+	DISP_DATA_OUT(0x80);	/* p14 */
+	DISP_DATA_OUT(0x82);	/* p15 */
+
+	/* Set DSP column */
+	DISP_CMD_OUT(DISP_CMD_MD_CSET);
+	DISP_DATA_OUT(0xff);
+	DISP_DATA_OUT(0x03);
+	DISP_DATA_OUT(0xff);
+	DISP_DATA_OUT(0x03);
+
+	/* Set DSP page */
+	DISP_CMD_OUT(DISP_CMD_MD_PSET);
+	DISP_DATA_OUT(0xff);
+	DISP_DATA_OUT(0x01);
+	DISP_DATA_OUT(0xff);
+	DISP_DATA_OUT(0x01);
+
+	/* Set ARM column */
+	DISP_CMD_OUT(DISP_CMD_SD_CSET);
+	DISP_DATA_OUT(0x02);
+	DISP_DATA_OUT(0x00);
+	DISP_DATA_OUT((QCIF_WIDTH + 1) & 0xFF);
+	DISP_DATA_OUT((QCIF_WIDTH + 1) >> 8);
+
+	/* Set ARM page */
+	DISP_CMD_OUT(DISP_CMD_SD_PSET);
+	DISP_DATA_OUT(0x00);
+	DISP_DATA_OUT(0x00);
+	DISP_DATA_OUT((QCIF_HEIGHT - 1) & 0xFF);
+	DISP_DATA_OUT((QCIF_HEIGHT - 1) >> 8);
+
+	/* Set 64 gray scales */
+	DISP_CMD_OUT(DISP_CMD_GSSET);
+	DISP_DATA_OUT(DISP_GS_64);
+
+	DISP_CMD_OUT(DISP_CMD_OSSEL);
+	DISP_DATA_OUT(0);
+
+	/* Sleep out */
+	DISP_CMD_OUT(DISP_CMD_SLPOUT);
+
+	WAIT_SEC(40000);
+
+	/* Initialize power IC */
+	DISP_CMD_OUT(DISP_CMD_VOLCTL);
+	DISP_DATA_OUT(DISP_VOLCTL_TONE);
+
+	WAIT_SEC(40000);
+
+	/* Set electronic volume, d'xx */
+	DISP_CMD_OUT(DISP_CMD_VOLCTL);
+	DISP_DATA_OUT(DISP_DEFAULT_CONTRAST);	/* value from 0 to 127 */
+
+	/* Initialize display data */
+	DISP_SET_RECT(0, (QCIF_HEIGHT - 1), 0, (QCIF_WIDTH - 1));
+	DISP_CMD_OUT(DISP_CMD_RAMWR);
+	for (i = 0; i < QCIF_HEIGHT * QCIF_WIDTH; i++)
+		DISP_DATA_OUT(0xffff);
+
+	DISP_CMD_OUT(DISP_CMD_RAMRD);
+	databack = DISP_DATA_IN();
+	databack = DISP_DATA_IN();
+	databack = DISP_DATA_IN();
+	databack = DISP_DATA_IN();
+
+	WAIT_SEC(80000);
+
+	DISP_CMD_OUT(DISP_CMD_DISON);
+
+	disp_area_start_row = 0;
+	disp_area_end_row = QCIF_HEIGHT - 1;
+	disp_powered_up = TRUE;
+	disp_initialized = TRUE;
+	epsonQcif_disp_set_display_area(0, QCIF_HEIGHT - 1);
+	display_on = TRUE;
+}
+
+static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres)
+{
+	if (!disp_initialized)
+		return;
+
+	DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
+	DISP_CMD_OUT(DISP_CMD_RAMWR);
+}
+
+static void epsonQcif_disp_set_display_area(word start_row, word end_row)
+{
+	if (!disp_initialized)
+		return;
+
+	if ((start_row == disp_area_start_row)
+	    && (end_row == disp_area_end_row))
+		return;
+	disp_area_start_row = start_row;
+	disp_area_end_row = end_row;
+
+	/* Range checking
+	 */
+	if (end_row >= QCIF_HEIGHT)
+		end_row = QCIF_HEIGHT - 1;
+	if (start_row > end_row)
+		start_row = end_row;
+
+	/* When display is not the full screen, gray scale is set to
+	 ** 2; otherwise it is set to 64.
+	 */
+	if ((start_row == 0) && (end_row == (QCIF_HEIGHT - 1))) {
+		/* The whole screen */
+		DISP_CMD_OUT(DISP_CMD_PTLOUT);
+		WAIT_SEC(10000);
+		DISP_CMD_OUT(DISP_CMD_DISOFF);
+		WAIT_SEC(100000);
+		DISP_CMD_OUT(DISP_CMD_GSSET);
+		DISP_DATA_OUT(DISP_GS_64);
+		WAIT_SEC(100000);
+		DISP_CMD_OUT(DISP_CMD_DISON);
+	} else {
+		/* partial screen */
+		DISP_CMD_OUT(DISP_CMD_PTLIN);
+		DISP_DATA_OUT(start_row);
+		DISP_DATA_OUT(start_row >> 8);
+		DISP_DATA_OUT(end_row);
+		DISP_DATA_OUT(end_row >> 8);
+		DISP_CMD_OUT(DISP_CMD_GSSET);
+		DISP_DATA_OUT(DISP_GS_2);
+	}
+}
+
+static int epsonQcif_disp_off(struct platform_device *pdev)
+{
+	if (!disp_initialized)
+		epsonQcif_disp_init(pdev);
+
+	if (display_on) {
+		DISP_CMD_OUT(DISP_CMD_DISOFF);
+		DISP_CMD_OUT(DISP_CMD_SLPIN);
+		display_on = FALSE;
+	}
+
+	return 0;
+}
+
+static int epsonQcif_disp_on(struct platform_device *pdev)
+{
+	if (!disp_initialized)
+		epsonQcif_disp_init(pdev);
+
+	if (!display_on) {
+		DISP_CMD_OUT(DISP_CMD_SLPOUT);
+		WAIT_SEC(40000);
+		DISP_CMD_OUT(DISP_CMD_DISON);
+		epsonQcif_disp_set_contrast(disp_contrast);
+		display_on = TRUE;
+	}
+
+	return 0;
+}
+
+static void epsonQcif_disp_set_contrast(word contrast)
+{
+	if (!disp_initialized)
+		return;
+
+	/* Initialize power IC, d'24 */
+	DISP_CMD_OUT(DISP_CMD_VOLCTL);
+	DISP_DATA_OUT(DISP_VOLCTL_TONE);
+
+	WAIT_SEC(40000);
+
+	/* Set electronic volume, d'xx */
+	DISP_CMD_OUT(DISP_CMD_VOLCTL);
+	if (contrast > 127)
+		contrast = 127;
+	DISP_DATA_OUT(contrast);	/* value from 0 to 127 */
+	disp_contrast = (byte) contrast;
+}				/* End disp_set_contrast */
+
+static void epsonQcif_disp_clear_screen_area(
+	word start_row, word end_row, word start_column, word end_column) {
+	int32 i;
+
+	/* Clear the display screen */
+	DISP_SET_RECT(start_row, end_row, start_column, end_column);
+	DISP_CMD_OUT(DISP_CMD_RAMWR);
+	i = (end_row - start_row + 1) * (end_column - start_column + 1);
+	for (; i > 0; i--)
+		DISP_DATA_OUT(0xffff);
+}
+
+static int __init epsonQcif_probe(struct platform_device *pdev)
+{
+	msm_fb_add_device(pdev);
+
+	return 0;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = epsonQcif_probe,
+	.driver = {
+		.name   = "ebi2_epson_qcif",
+	},
+};
+
+static struct msm_fb_panel_data epsonQcif_panel_data = {
+	.on = epsonQcif_disp_on,
+	.off = epsonQcif_disp_off,
+	.set_rect = epsonQcif_disp_set_rect,
+};
+
+static struct platform_device this_device = {
+	.name   = "ebi2_epson_qcif",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &epsonQcif_panel_data,
+	}
+};
+
+static int __init epsonQcif_init(void)
+{
+	int ret;
+	struct msm_panel_info *pinfo;
+
+	ret = platform_driver_register(&this_driver);
+	if (!ret) {
+		pinfo = &epsonQcif_panel_data.panel_info;
+		pinfo->xres = QCIF_WIDTH;
+		pinfo->yres = QCIF_HEIGHT;
+		pinfo->type = EBI2_PANEL;
+		pinfo->pdest = DISPLAY_2;
+		pinfo->wait_cycle = 0x808000;
+		pinfo->bpp = 16;
+		pinfo->fb_num = 2;
+		pinfo->lcd.vsync_enable = FALSE;
+
+		ret = platform_device_register(&this_device);
+		if (ret)
+			platform_driver_unregister(&this_driver);
+	}
+
+	return ret;
+}
+
+module_init(epsonQcif_init);

+ 250 - 0
drivers/staging/msm/ebi2_lcd.c

@@ -0,0 +1,250 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+
+#include "msm_fb.h"
+
+static int ebi2_lcd_probe(struct platform_device *pdev);
+static int ebi2_lcd_remove(struct platform_device *pdev);
+
+static struct platform_driver ebi2_lcd_driver = {
+	.probe = ebi2_lcd_probe,
+	.remove = ebi2_lcd_remove,
+	.suspend = NULL,
+	.suspend_late = NULL,
+	.resume_early = NULL,
+	.resume = NULL,
+	.shutdown = NULL,
+	.driver = {
+		   .name = "ebi2_lcd",
+		   },
+};
+
+static void *ebi2_base;
+static void *ebi2_lcd_cfg0;
+static void *ebi2_lcd_cfg1;
+static void __iomem *lcd01_base;
+static void __iomem *lcd02_base;
+static int ebi2_lcd_resource_initialized;
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static int ebi2_lcd_probe(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+	struct platform_device *mdp_dev = NULL;
+	struct msm_fb_panel_data *pdata = NULL;
+	int rc, i;
+
+	if (pdev->id == 0) {
+		for (i = 0; i < pdev->num_resources; i++) {
+			if (!strncmp(pdev->resource[i].name, "base", 4)) {
+				ebi2_base = ioremap(pdev->resource[i].start,
+						pdev->resource[i].end -
+						pdev->resource[i].start + 1);
+				if (!ebi2_base) {
+					printk(KERN_ERR
+						"ebi2_base ioremap failed!\n");
+					return -ENOMEM;
+				}
+				ebi2_lcd_cfg0 = (void *)(ebi2_base + 0x20);
+				ebi2_lcd_cfg1 = (void *)(ebi2_base + 0x24);
+			} else if (!strncmp(pdev->resource[i].name,
+						"lcd01", 5)) {
+				lcd01_base = ioremap(pdev->resource[i].start,
+						pdev->resource[i].end -
+						pdev->resource[i].start + 1);
+				if (!lcd01_base) {
+					printk(KERN_ERR
+						"lcd01_base ioremap failed!\n");
+					return -ENOMEM;
+				}
+			} else if (!strncmp(pdev->resource[i].name,
+						"lcd02", 5)) {
+				lcd02_base = ioremap(pdev->resource[i].start,
+						pdev->resource[i].end -
+						pdev->resource[i].start + 1);
+				if (!lcd02_base) {
+					printk(KERN_ERR
+						"lcd02_base ioremap failed!\n");
+					return -ENOMEM;
+				}
+			}
+		}
+		ebi2_lcd_resource_initialized = 1;
+		return 0;
+	}
+
+	if (!ebi2_lcd_resource_initialized)
+		return -EPERM;
+
+	mfd = platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+		return -ENOMEM;
+
+	if (ebi2_base == NULL)
+		return -ENOMEM;
+
+	mdp_dev = platform_device_alloc("mdp", pdev->id);
+	if (!mdp_dev)
+		return -ENOMEM;
+
+	/* link to the latest pdev */
+	mfd->pdev = mdp_dev;
+	mfd->dest = DISPLAY_LCD;
+
+	/* add panel data */
+	if (platform_device_add_data
+	    (mdp_dev, pdev->dev.platform_data,
+	     sizeof(struct msm_fb_panel_data))) {
+		printk(KERN_ERR "ebi2_lcd_probe: platform_device_add_data failed!\n");
+		platform_device_put(mdp_dev);
+		return -ENOMEM;
+	}
+
+	/* data chain */
+	pdata = mdp_dev->dev.platform_data;
+	pdata->on = panel_next_on;
+	pdata->off = panel_next_off;
+	pdata->next = pdev;
+
+	/* get/set panel specific fb info */
+	mfd->panel_info = pdata->panel_info;
+
+	if (mfd->panel_info.bpp == 24)
+		mfd->fb_imgType = MDP_RGB_888;
+	else
+		mfd->fb_imgType = MDP_RGB_565;
+
+	/* config msm ebi2 lcd register */
+	if (mfd->panel_info.pdest == DISPLAY_1) {
+		outp32(ebi2_base,
+		       (inp32(ebi2_base) & (~(EBI2_PRIM_LCD_CLR))) |
+		       EBI2_PRIM_LCD_SEL);
+		/*
+		 * current design has one set of cfg0/1 register to control
+		 * both EBI2 channels. so, we're using the PRIM channel to
+		 * configure both.
+		 */
+		outp32(ebi2_lcd_cfg0, mfd->panel_info.wait_cycle);
+		if (mfd->panel_info.bpp == 18)
+			outp32(ebi2_lcd_cfg1, 0x01000000);
+		else
+			outp32(ebi2_lcd_cfg1, 0x0);
+	} else {
+#ifdef DEBUG_EBI2_LCD
+		/*
+		 * confliting with QCOM SURF FPGA CS.
+		 * OEM should enable below for their CS mapping
+		 */
+		 outp32(ebi2_base, (inp32(ebi2_base)&(~(EBI2_SECD_LCD_CLR)))
+					|EBI2_SECD_LCD_SEL);
+#endif
+	}
+
+	/*
+	 * map cs (chip select) address
+	 */
+	if (mfd->panel_info.pdest == DISPLAY_1) {
+		mfd->cmd_port = lcd01_base;
+		mfd->data_port =
+		    (void *)((uint32) mfd->cmd_port + EBI2_PRIM_LCD_RS_PIN);
+		mfd->data_port_phys =
+		    (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN);
+	} else {
+		mfd->cmd_port = lcd01_base;
+		mfd->data_port =
+		    (void *)((uint32) mfd->cmd_port + EBI2_SECD_LCD_RS_PIN);
+		mfd->data_port_phys =
+		    (void *)(LCD_SECD_BASE_PHYS + EBI2_SECD_LCD_RS_PIN);
+	}
+
+	/*
+	 * set driver data
+	 */
+	platform_set_drvdata(mdp_dev, mfd);
+
+	/*
+	 * register in mdp driver
+	 */
+	rc = platform_device_add(mdp_dev);
+	if (rc) {
+		goto ebi2_lcd_probe_err;
+	}
+
+	pdev_list[pdev_list_cnt++] = pdev;
+	return 0;
+
+      ebi2_lcd_probe_err:
+	platform_device_put(mdp_dev);
+	return rc;
+}
+
+static int ebi2_lcd_remove(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return 0;
+
+	if (mfd->key != MFD_KEY)
+		return 0;
+
+	iounmap(mfd->cmd_port);
+
+	return 0;
+}
+
+static int ebi2_lcd_register_driver(void)
+{
+	return platform_driver_register(&ebi2_lcd_driver);
+}
+
+static int __init ebi2_lcd_driver_init(void)
+{
+	return ebi2_lcd_register_driver();
+}
+
+module_init(ebi2_lcd_driver_init);

+ 1122 - 0
drivers/staging/msm/ebi2_tmd20.c

@@ -0,0 +1,1122 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+#include <linux/memory.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+/* #define TMD20QVGA_LCD_18BPP */
+#define QVGA_WIDTH        240
+#define QVGA_HEIGHT       320
+
+#ifdef TMD20QVGA_LCD_18BPP
+#define DISP_QVGA_18BPP(x)  ((((x)<<2) & 0x3FC00)|(( (x)<<1)& 0x1FE))
+#define DISP_REG(name)  uint32 register_##name;
+#define OUTPORT(x, y)  outpdw(x, y)
+#define INPORT(x)   inpdw(x)
+#else
+#define DISP_QVGA_18BPP(x)  (x)
+#define DISP_REG(name)  uint16 register_##name;
+#define OUTPORT(x, y)  outpw(x, y)
+#define INPORT(x)   intpw(x)
+#endif
+
+static void *DISP_CMD_PORT;
+static void *DISP_DATA_PORT;
+
+#define DISP_RNTI         0x10
+
+#define DISP_CMD_OUT(cmd) OUTPORT(DISP_CMD_PORT, DISP_QVGA_18BPP(cmd))
+#define DISP_DATA_OUT(data) OUTPORT(DISP_DATA_PORT, data)
+#define DISP_DATA_IN() INPORT(DISP_DATA_PORT)
+
+#if (defined(TMD20QVGA_LCD_18BPP))
+#define DISP_DATA_OUT_16TO18BPP(x) \
+	DISP_DATA_OUT((((x)&0xf800)<<2|((x)&0x80000)>>3) \
+		     | (((x)&0x7e0)<<1) \
+		     | (((x)&0x1F)<<1|((x)&0x10)>>4))
+#else
+#define DISP_DATA_OUT_16TO18BPP(x) \
+	DISP_DATA_OUT(x)
+#endif
+
+#define DISP_WRITE_OUT(addr, data) \
+   register_##addr = DISP_QVGA_18BPP(data); \
+   DISP_CMD_OUT(addr); \
+   DISP_DATA_OUT(register_##addr);
+
+#define DISP_UPDATE_VALUE(addr, bitmask, data) \
+   DISP_WRITE_OUT(##addr, (register_##addr & ~(bitmask)) | (data));
+
+#define DISP_VAL_IF(bitvalue, bitmask) \
+   ((bitvalue) ? (bitmask) : 0)
+
+/* QVGA = 256 x 320 */
+/* actual display is 240 x 320...offset by 0x10 */
+#define DISP_ROW_COL_TO_ADDR(row, col) ((row) * 0x100 + col)
+#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \
+   { \
+   DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \
+   DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, (lrhc_col) + tmd20qvga_panel_offset); \
+   DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, (ulhc_row)); \
+   DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, (lrhc_row)); \
+   DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \
+   DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, (ulhc_row)); \
+   }
+
+#define WAIT_MSEC(msec) mdelay(msec)
+
+/*
+ * TMD QVGA Address
+ */
+/* Display Control */
+#define DISP_START_OSCILLATION_ADDR     0x000
+DISP_REG(DISP_START_OSCILLATION_ADDR)
+#define DISP_DRIVER_OUTPUT_CTL_ADDR     0x001
+    DISP_REG(DISP_DRIVER_OUTPUT_CTL_ADDR)
+#define DISP_LCD_DRIVING_SIG_ADDR     0x002
+    DISP_REG(DISP_LCD_DRIVING_SIG_ADDR)
+#define DISP_ENTRY_MODE_ADDR            0x003
+    DISP_REG(DISP_ENTRY_MODE_ADDR)
+#define DISP_DISPLAY_CTL_1_ADDR         0x007
+    DISP_REG(DISP_DISPLAY_CTL_1_ADDR)
+#define DISP_DISPLAY_CTL_2_ADDR         0x008
+    DISP_REG(DISP_DISPLAY_CTL_2_ADDR)
+
+/* DISPLAY MODE 0x009 partial display not supported */
+#define DISP_POWER_SUPPLY_INTF_ADDR     0x00A
+    DISP_REG(DISP_POWER_SUPPLY_INTF_ADDR)
+
+/* DISPLAY MODE 0x00B xZoom feature is not supported */
+#define DISP_EXT_DISPLAY_CTL_1_ADDR     0x00C
+    DISP_REG(DISP_EXT_DISPLAY_CTL_1_ADDR)
+
+#define DISP_FRAME_CYCLE_CTL_ADDR       0x00D
+    DISP_REG(DISP_FRAME_CYCLE_CTL_ADDR)
+
+#define DISP_EXT_DISPLAY_CTL_2_ADDR     0x00E
+    DISP_REG(DISP_EXT_DISPLAY_CTL_2_ADDR)
+
+#define DISP_EXT_DISPLAY_CTL_3_ADDR     0x00F
+    DISP_REG(DISP_EXT_DISPLAY_CTL_3_ADDR)
+
+#define DISP_LTPS_CTL_1_ADDR            0x012
+    DISP_REG(DISP_LTPS_CTL_1_ADDR)
+#define DISP_LTPS_CTL_2_ADDR            0x013
+    DISP_REG(DISP_LTPS_CTL_2_ADDR)
+#define DISP_LTPS_CTL_3_ADDR            0x014
+    DISP_REG(DISP_LTPS_CTL_3_ADDR)
+#define DISP_LTPS_CTL_4_ADDR            0x018
+    DISP_REG(DISP_LTPS_CTL_4_ADDR)
+#define DISP_LTPS_CTL_5_ADDR            0x019
+    DISP_REG(DISP_LTPS_CTL_5_ADDR)
+#define DISP_LTPS_CTL_6_ADDR            0x01A
+    DISP_REG(DISP_LTPS_CTL_6_ADDR)
+#define DISP_AMP_SETTING_ADDR           0x01C
+    DISP_REG(DISP_AMP_SETTING_ADDR)
+#define DISP_MODE_SETTING_ADDR          0x01D
+    DISP_REG(DISP_MODE_SETTING_ADDR)
+#define DISP_POFF_LN_SETTING_ADDR       0x01E
+    DISP_REG(DISP_POFF_LN_SETTING_ADDR)
+/* Power Contol */
+#define DISP_POWER_CTL_1_ADDR           0x100
+    DISP_REG(DISP_POWER_CTL_1_ADDR)
+#define DISP_POWER_CTL_2_ADDR           0x101
+    DISP_REG(DISP_POWER_CTL_2_ADDR)
+#define DISP_POWER_CTL_3_ADDR           0x102
+    DISP_REG(DISP_POWER_CTL_3_ADDR)
+#define DISP_POWER_CTL_4_ADDR           0x103
+    DISP_REG(DISP_POWER_CTL_4_ADDR)
+#define DISP_POWER_CTL_5_ADDR           0x104
+    DISP_REG(DISP_POWER_CTL_5_ADDR)
+#define DISP_POWER_CTL_6_ADDR           0x105
+    DISP_REG(DISP_POWER_CTL_6_ADDR)
+#define DISP_POWER_CTL_7_ADDR           0x106
+    DISP_REG(DISP_POWER_CTL_7_ADDR)
+/* RAM Access */
+#define DISP_RAM_ADDR_SET_1_ADDR        0x200
+    DISP_REG(DISP_RAM_ADDR_SET_1_ADDR)
+#define DISP_RAM_ADDR_SET_2_ADDR        0x201
+    DISP_REG(DISP_RAM_ADDR_SET_2_ADDR)
+#define DISP_CMD_RAMRD                  DISP_CMD_RAMWR
+#define DISP_CMD_RAMWR                  0x202
+    DISP_REG(DISP_CMD_RAMWR)
+#define DISP_RAM_DATA_MASK_1_ADDR       0x203
+    DISP_REG(DISP_RAM_DATA_MASK_1_ADDR)
+#define DISP_RAM_DATA_MASK_2_ADDR       0x204
+    DISP_REG(DISP_RAM_DATA_MASK_2_ADDR)
+/* Gamma Control, Contrast, Gray Scale Setting */
+#define DISP_GAMMA_CONTROL_1_ADDR       0x300
+    DISP_REG(DISP_GAMMA_CONTROL_1_ADDR)
+#define DISP_GAMMA_CONTROL_2_ADDR       0x301
+    DISP_REG(DISP_GAMMA_CONTROL_2_ADDR)
+#define DISP_GAMMA_CONTROL_3_ADDR       0x302
+    DISP_REG(DISP_GAMMA_CONTROL_3_ADDR)
+#define DISP_GAMMA_CONTROL_4_ADDR       0x303
+    DISP_REG(DISP_GAMMA_CONTROL_4_ADDR)
+#define DISP_GAMMA_CONTROL_5_ADDR       0x304
+    DISP_REG(DISP_GAMMA_CONTROL_5_ADDR)
+/* Coordinate Control */
+#define DISP_VERT_SCROLL_CTL_1_ADDR     0x400
+    DISP_REG(DISP_VERT_SCROLL_CTL_1_ADDR)
+#define DISP_VERT_SCROLL_CTL_2_ADDR     0x401
+    DISP_REG(DISP_VERT_SCROLL_CTL_2_ADDR)
+#define DISP_SCREEN_1_DRV_POS_1_ADDR    0x402
+    DISP_REG(DISP_SCREEN_1_DRV_POS_1_ADDR)
+#define DISP_SCREEN_1_DRV_POS_2_ADDR    0x403
+    DISP_REG(DISP_SCREEN_1_DRV_POS_2_ADDR)
+#define DISP_SCREEN_2_DRV_POS_1_ADDR    0x404
+    DISP_REG(DISP_SCREEN_2_DRV_POS_1_ADDR)
+#define DISP_SCREEN_2_DRV_POS_2_ADDR    0x405
+    DISP_REG(DISP_SCREEN_2_DRV_POS_2_ADDR)
+#define DISP_HORZ_RAM_ADDR_POS_1_ADDR   0x406
+    DISP_REG(DISP_HORZ_RAM_ADDR_POS_1_ADDR)
+#define DISP_HORZ_RAM_ADDR_POS_2_ADDR   0x407
+    DISP_REG(DISP_HORZ_RAM_ADDR_POS_2_ADDR)
+#define DISP_VERT_RAM_ADDR_POS_1_ADDR   0x408
+    DISP_REG(DISP_VERT_RAM_ADDR_POS_1_ADDR)
+#define DISP_VERT_RAM_ADDR_POS_2_ADDR   0x409
+    DISP_REG(DISP_VERT_RAM_ADDR_POS_2_ADDR)
+#define DISP_TMD_700_ADDR               0x700	/*  0x700 */
+    DISP_REG(DISP_TMD_700_ADDR)
+#define DISP_TMD_015_ADDR               0x015	/*  0x700 */
+    DISP_REG(DISP_TMD_015_ADDR)
+#define DISP_TMD_305_ADDR               0x305	/*  0x700 */
+    DISP_REG(DISP_TMD_305_ADDR)
+
+/*
+ * TMD QVGA Bit Definations
+ */
+
+#define DISP_BIT_IB15              0x8000
+#define DISP_BIT_IB14              0x4000
+#define DISP_BIT_IB13              0x2000
+#define DISP_BIT_IB12              0x1000
+#define DISP_BIT_IB11              0x0800
+#define DISP_BIT_IB10              0x0400
+#define DISP_BIT_IB09              0x0200
+#define DISP_BIT_IB08              0x0100
+#define DISP_BIT_IB07              0x0080
+#define DISP_BIT_IB06              0x0040
+#define DISP_BIT_IB05              0x0020
+#define DISP_BIT_IB04              0x0010
+#define DISP_BIT_IB03              0x0008
+#define DISP_BIT_IB02              0x0004
+#define DISP_BIT_IB01              0x0002
+#define DISP_BIT_IB00              0x0001
+/*
+ * Display Control
+ * DISP_START_OSCILLATION_ADDR     Start Oscillation
+ * DISP_DRIVER_OUTPUT_CTL_ADDR     Driver Output Control
+ */
+#define DISP_BITMASK_SS            DISP_BIT_IB08
+#define DISP_BITMASK_NL5           DISP_BIT_IB05
+#define DISP_BITMASK_NL4           DISP_BIT_IB04
+#define DISP_BITMASK_NL3           DISP_BIT_IB03
+#define DISP_BITMASK_NL2           DISP_BIT_IB02
+#define DISP_BITMASK_NL1           DISP_BIT_IB01
+#define DISP_BITMASK_NL0           DISP_BIT_IB00
+/* DISP_LCD_DRIVING_SIG_ADDR       LCD Driving Signal Setting */
+#define DISP_BITMASK_BC            DISP_BIT_IB09
+/* DISP_ENTRY_MODE_ADDR            Entry Mode */
+#define DISP_BITMASK_TRI           DISP_BIT_IB15
+#define DISP_BITMASK_DFM1          DISP_BIT_IB14
+#define DISP_BITMASK_DFM0          DISP_BIT_IB13
+#define DISP_BITMASK_BGR           DISP_BIT_IB12
+#define DISP_BITMASK_HWM0          DISP_BIT_IB08
+#define DISP_BITMASK_ID1           DISP_BIT_IB05
+#define DISP_BITMASK_ID0           DISP_BIT_IB04
+#define DISP_BITMASK_AM            DISP_BIT_IB03
+/* DISP_DISPLAY_CTL_1_ADDR         Display Control (1) */
+#define DISP_BITMASK_COL1          DISP_BIT_IB15
+#define DISP_BITMASK_COL0          DISP_BIT_IB14
+#define DISP_BITMASK_VLE2          DISP_BIT_IB10
+#define DISP_BITMASK_VLE1          DISP_BIT_IB09
+#define DISP_BITMASK_SPT           DISP_BIT_IB08
+#define DISP_BITMASK_PT1           DISP_BIT_IB07
+#define DISP_BITMASK_PT0           DISP_BIT_IB06
+#define DISP_BITMASK_REV           DISP_BIT_IB02
+/* DISP_DISPLAY_CTL_2_ADDR         Display Control (2) */
+#define DISP_BITMASK_FP3           DISP_BIT_IB11
+#define DISP_BITMASK_FP2           DISP_BIT_IB10
+#define DISP_BITMASK_FP1           DISP_BIT_IB09
+#define DISP_BITMASK_FP0           DISP_BIT_IB08
+#define DISP_BITMASK_BP3           DISP_BIT_IB03
+#define DISP_BITMASK_BP2           DISP_BIT_IB02
+#define DISP_BITMASK_BP1           DISP_BIT_IB01
+#define DISP_BITMASK_BP0           DISP_BIT_IB00
+/* DISP_POWER_SUPPLY_INTF_ADDR     Power Supply IC Interface Control */
+#define DISP_BITMASK_CSE           DISP_BIT_IB12
+#define DISP_BITMASK_TE            DISP_BIT_IB08
+#define DISP_BITMASK_IX3           DISP_BIT_IB03
+#define DISP_BITMASK_IX2           DISP_BIT_IB02
+#define DISP_BITMASK_IX1           DISP_BIT_IB01
+#define DISP_BITMASK_IX0           DISP_BIT_IB00
+/* DISP_EXT_DISPLAY_CTL_1_ADDR     External Display Interface Control (1) */
+#define DISP_BITMASK_RM            DISP_BIT_IB08
+#define DISP_BITMASK_DM1           DISP_BIT_IB05
+#define DISP_BITMASK_DM0           DISP_BIT_IB04
+#define DISP_BITMASK_RIM1          DISP_BIT_IB01
+#define DISP_BITMASK_RIM0          DISP_BIT_IB00
+/* DISP_FRAME_CYCLE_CTL_ADDR       Frame Frequency Adjustment Control */
+#define DISP_BITMASK_DIVI1         DISP_BIT_IB09
+#define DISP_BITMASK_DIVI0         DISP_BIT_IB08
+#define DISP_BITMASK_RTNI4         DISP_BIT_IB04
+#define DISP_BITMASK_RTNI3         DISP_BIT_IB03
+#define DISP_BITMASK_RTNI2         DISP_BIT_IB02
+#define DISP_BITMASK_RTNI1         DISP_BIT_IB01
+#define DISP_BITMASK_RTNI0         DISP_BIT_IB00
+/* DISP_EXT_DISPLAY_CTL_2_ADDR     External Display Interface Control (2) */
+#define DISP_BITMASK_DIVE1         DISP_BIT_IB09
+#define DISP_BITMASK_DIVE0         DISP_BIT_IB08
+#define DISP_BITMASK_RTNE7         DISP_BIT_IB07
+#define DISP_BITMASK_RTNE6         DISP_BIT_IB06
+#define DISP_BITMASK_RTNE5         DISP_BIT_IB05
+#define DISP_BITMASK_RTNE4         DISP_BIT_IB04
+#define DISP_BITMASK_RTNE3         DISP_BIT_IB03
+#define DISP_BITMASK_RTNE2         DISP_BIT_IB02
+#define DISP_BITMASK_RTNE1         DISP_BIT_IB01
+#define DISP_BITMASK_RTNE0         DISP_BIT_IB00
+/* DISP_EXT_DISPLAY_CTL_3_ADDR     External Display Interface Control (3) */
+#define DISP_BITMASK_VSPL          DISP_BIT_IB04
+#define DISP_BITMASK_HSPL          DISP_BIT_IB03
+#define DISP_BITMASK_VPL           DISP_BIT_IB02
+#define DISP_BITMASK_EPL           DISP_BIT_IB01
+#define DISP_BITMASK_DPL           DISP_BIT_IB00
+/* DISP_LTPS_CTL_1_ADDR            LTPS Interface Control (1) */
+#define DISP_BITMASK_CLWI3         DISP_BIT_IB11
+#define DISP_BITMASK_CLWI2         DISP_BIT_IB10
+#define DISP_BITMASK_CLWI1         DISP_BIT_IB09
+#define DISP_BITMASK_CLWI0         DISP_BIT_IB08
+#define DISP_BITMASK_CLTI1         DISP_BIT_IB01
+#define DISP_BITMASK_CLTI0         DISP_BIT_IB00
+/* DISP_LTPS_CTL_2_ADDR            LTPS Interface Control (2) */
+#define DISP_BITMASK_OEVBI1        DISP_BIT_IB09
+#define DISP_BITMASK_OEVBI0        DISP_BIT_IB08
+#define DISP_BITMASK_OEVFI1        DISP_BIT_IB01
+#define DISP_BITMASK_OEVFI0        DISP_BIT_IB00
+/* DISP_LTPS_CTL_3_ADDR            LTPS Interface Control (3) */
+#define DISP_BITMASK_SHI1          DISP_BIT_IB01
+#define DISP_BITMASK_SHI0          DISP_BIT_IB00
+/* DISP_LTPS_CTL_4_ADDR            LTPS Interface Control (4) */
+#define DISP_BITMASK_CLWE5         DISP_BIT_IB13
+#define DISP_BITMASK_CLWE4         DISP_BIT_IB12
+#define DISP_BITMASK_CLWE3         DISP_BIT_IB11
+#define DISP_BITMASK_CLWE2         DISP_BIT_IB10
+#define DISP_BITMASK_CLWE1         DISP_BIT_IB09
+#define DISP_BITMASK_CLWE0         DISP_BIT_IB08
+#define DISP_BITMASK_CLTE3         DISP_BIT_IB03
+#define DISP_BITMASK_CLTE2         DISP_BIT_IB02
+#define DISP_BITMASK_CLTE1         DISP_BIT_IB01
+#define DISP_BITMASK_CLTE0         DISP_BIT_IB00
+/* DISP_LTPS_CTL_5_ADDR            LTPS Interface Control (5) */
+#define DISP_BITMASK_OEVBE3        DISP_BIT_IB11
+#define DISP_BITMASK_OEVBE2        DISP_BIT_IB10
+#define DISP_BITMASK_OEVBE1        DISP_BIT_IB09
+#define DISP_BITMASK_OEVBE0        DISP_BIT_IB08
+#define DISP_BITMASK_OEVFE3        DISP_BIT_IB03
+#define DISP_BITMASK_OEVFE2        DISP_BIT_IB02
+#define DISP_BITMASK_OEVFE1        DISP_BIT_IB01
+#define DISP_BITMASK_OEVFE0        DISP_BIT_IB00
+/* DISP_LTPS_CTL_6_ADDR            LTPS Interface Control (6) */
+#define DISP_BITMASK_SHE3          DISP_BIT_IB03
+#define DISP_BITMASK_SHE2          DISP_BIT_IB02
+#define DISP_BITMASK_SHE1          DISP_BIT_IB01
+#define DISP_BITMASK_SHE0          DISP_BIT_IB00
+/* DISP_AMP_SETTING_ADDR           Amplify Setting */
+#define DISP_BITMASK_ABSW1         DISP_BIT_IB01
+#define DISP_BITMASK_ABSW0         DISP_BIT_IB00
+/* DISP_MODE_SETTING_ADDR          Mode Setting */
+#define DISP_BITMASK_DSTB          DISP_BIT_IB02
+#define DISP_BITMASK_STB           DISP_BIT_IB00
+/* DISP_POFF_LN_SETTING_ADDR       Power Off Line Setting */
+#define DISP_BITMASK_POFH3         DISP_BIT_IB03
+#define DISP_BITMASK_POFH2         DISP_BIT_IB02
+#define DISP_BITMASK_POFH1         DISP_BIT_IB01
+#define DISP_BITMASK_POFH0         DISP_BIT_IB00
+
+/* Power Contol */
+/* DISP_POWER_CTL_1_ADDR           Power Control (1) */
+#define DISP_BITMASK_PO            DISP_BIT_IB11
+#define DISP_BITMASK_VCD           DISP_BIT_IB09
+#define DISP_BITMASK_VSC           DISP_BIT_IB08
+#define DISP_BITMASK_CON           DISP_BIT_IB07
+#define DISP_BITMASK_ASW1          DISP_BIT_IB06
+#define DISP_BITMASK_ASW0          DISP_BIT_IB05
+#define DISP_BITMASK_OEV           DISP_BIT_IB04
+#define DISP_BITMASK_OEVE          DISP_BIT_IB03
+#define DISP_BITMASK_FR            DISP_BIT_IB02
+#define DISP_BITMASK_D1            DISP_BIT_IB01
+#define DISP_BITMASK_D0            DISP_BIT_IB00
+/* DISP_POWER_CTL_2_ADDR           Power Control (2) */
+#define DISP_BITMASK_DC4           DISP_BIT_IB15
+#define DISP_BITMASK_DC3           DISP_BIT_IB14
+#define DISP_BITMASK_SAP2          DISP_BIT_IB13
+#define DISP_BITMASK_SAP1          DISP_BIT_IB12
+#define DISP_BITMASK_SAP0          DISP_BIT_IB11
+#define DISP_BITMASK_BT2           DISP_BIT_IB10
+#define DISP_BITMASK_BT1           DISP_BIT_IB09
+#define DISP_BITMASK_BT0           DISP_BIT_IB08
+#define DISP_BITMASK_DC2           DISP_BIT_IB07
+#define DISP_BITMASK_DC1           DISP_BIT_IB06
+#define DISP_BITMASK_DC0           DISP_BIT_IB05
+#define DISP_BITMASK_AP2           DISP_BIT_IB04
+#define DISP_BITMASK_AP1           DISP_BIT_IB03
+#define DISP_BITMASK_AP0           DISP_BIT_IB02
+/* DISP_POWER_CTL_3_ADDR           Power Control (3) */
+#define DISP_BITMASK_VGL4          DISP_BIT_IB10
+#define DISP_BITMASK_VGL3          DISP_BIT_IB09
+#define DISP_BITMASK_VGL2          DISP_BIT_IB08
+#define DISP_BITMASK_VGL1          DISP_BIT_IB07
+#define DISP_BITMASK_VGL0          DISP_BIT_IB06
+#define DISP_BITMASK_VGH4          DISP_BIT_IB04
+#define DISP_BITMASK_VGH3          DISP_BIT_IB03
+#define DISP_BITMASK_VGH2          DISP_BIT_IB02
+#define DISP_BITMASK_VGH1          DISP_BIT_IB01
+#define DISP_BITMASK_VGH0          DISP_BIT_IB00
+/* DISP_POWER_CTL_4_ADDR           Power Control (4) */
+#define DISP_BITMASK_VC2           DISP_BIT_IB02
+#define DISP_BITMASK_VC1           DISP_BIT_IB01
+#define DISP_BITMASK_VC0           DISP_BIT_IB00
+/* DISP_POWER_CTL_5_ADDR           Power Control (5) */
+#define DISP_BITMASK_VRL3          DISP_BIT_IB11
+#define DISP_BITMASK_VRL2          DISP_BIT_IB10
+#define DISP_BITMASK_VRL1          DISP_BIT_IB09
+#define DISP_BITMASK_VRL0          DISP_BIT_IB08
+#define DISP_BITMASK_PON           DISP_BIT_IB04
+#define DISP_BITMASK_VRH3          DISP_BIT_IB03
+#define DISP_BITMASK_VRH2          DISP_BIT_IB02
+#define DISP_BITMASK_VRH1          DISP_BIT_IB01
+#define DISP_BITMASK_VRH0          DISP_BIT_IB00
+/* DISP_POWER_CTL_6_ADDR           Power Control (6) */
+#define DISP_BITMASK_VCOMG         DISP_BIT_IB13
+#define DISP_BITMASK_VDV4          DISP_BIT_IB12
+#define DISP_BITMASK_VDV3          DISP_BIT_IB11
+#define DISP_BITMASK_VDV2          DISP_BIT_IB10
+#define DISP_BITMASK_VDV1          DISP_BIT_IB09
+#define DISP_BITMASK_VDV0          DISP_BIT_IB08
+#define DISP_BITMASK_VCM4          DISP_BIT_IB04
+#define DISP_BITMASK_VCM3          DISP_BIT_IB03
+#define DISP_BITMASK_VCM2          DISP_BIT_IB02
+#define DISP_BITMASK_VCM1          DISP_BIT_IB01
+#define DISP_BITMASK_VCM0          DISP_BIT_IB00
+/* RAM Access */
+/* DISP_RAM_ADDR_SET_1_ADDR        RAM Address Set (1) */
+#define DISP_BITMASK_AD7           DISP_BIT_IB07
+#define DISP_BITMASK_AD6           DISP_BIT_IB06
+#define DISP_BITMASK_AD5           DISP_BIT_IB05
+#define DISP_BITMASK_AD4           DISP_BIT_IB04
+#define DISP_BITMASK_AD3           DISP_BIT_IB03
+#define DISP_BITMASK_AD2           DISP_BIT_IB02
+#define DISP_BITMASK_AD1           DISP_BIT_IB01
+#define DISP_BITMASK_AD0           DISP_BIT_IB00
+/* DISP_RAM_ADDR_SET_2_ADDR        RAM Address Set (2) */
+#define DISP_BITMASK_AD16          DISP_BIT_IB08
+#define DISP_BITMASK_AD15          DISP_BIT_IB07
+#define DISP_BITMASK_AD14          DISP_BIT_IB06
+#define DISP_BITMASK_AD13          DISP_BIT_IB05
+#define DISP_BITMASK_AD12          DISP_BIT_IB04
+#define DISP_BITMASK_AD11          DISP_BIT_IB03
+#define DISP_BITMASK_AD10          DISP_BIT_IB02
+#define DISP_BITMASK_AD9           DISP_BIT_IB01
+#define DISP_BITMASK_AD8           DISP_BIT_IB00
+/*
+ * DISP_CMD_RAMWR       RAM Data Read/Write
+ * Use Data Bit Configuration
+ */
+/* DISP_RAM_DATA_MASK_1_ADDR       RAM Write Data Mask (1) */
+#define DISP_BITMASK_WM11          DISP_BIT_IB13
+#define DISP_BITMASK_WM10          DISP_BIT_IB12
+#define DISP_BITMASK_WM9           DISP_BIT_IB11
+#define DISP_BITMASK_WM8           DISP_BIT_IB10
+#define DISP_BITMASK_WM7           DISP_BIT_IB09
+#define DISP_BITMASK_WM6           DISP_BIT_IB08
+#define DISP_BITMASK_WM5           DISP_BIT_IB05
+#define DISP_BITMASK_WM4           DISP_BIT_IB04
+#define DISP_BITMASK_WM3           DISP_BIT_IB03
+#define DISP_BITMASK_WM2           DISP_BIT_IB02
+#define DISP_BITMASK_WM1           DISP_BIT_IB01
+#define DISP_BITMASK_WM0           DISP_BIT_IB00
+/* DISP_RAM_DATA_MASK_2_ADDR       RAM Write Data Mask (2) */
+#define DISP_BITMASK_WM17          DISP_BIT_IB05
+#define DISP_BITMASK_WM16          DISP_BIT_IB04
+#define DISP_BITMASK_WM15          DISP_BIT_IB03
+#define DISP_BITMASK_WM14          DISP_BIT_IB02
+#define DISP_BITMASK_WM13          DISP_BIT_IB01
+#define DISP_BITMASK_WM12          DISP_BIT_IB00
+/*Gamma Control */
+/* DISP_GAMMA_CONTROL_1_ADDR       Gamma Control (1) */
+#define DISP_BITMASK_PKP12         DISP_BIT_IB10
+#define DISP_BITMASK_PKP11         DISP_BIT_IB08
+#define DISP_BITMASK_PKP10         DISP_BIT_IB09
+#define DISP_BITMASK_PKP02         DISP_BIT_IB02
+#define DISP_BITMASK_PKP01         DISP_BIT_IB01
+#define DISP_BITMASK_PKP00         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_2_ADDR       Gamma Control (2) */
+#define DISP_BITMASK_PKP32         DISP_BIT_IB10
+#define DISP_BITMASK_PKP31         DISP_BIT_IB09
+#define DISP_BITMASK_PKP30         DISP_BIT_IB08
+#define DISP_BITMASK_PKP22         DISP_BIT_IB02
+#define DISP_BITMASK_PKP21         DISP_BIT_IB01
+#define DISP_BITMASK_PKP20         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_3_ADDR       Gamma Control (3) */
+#define DISP_BITMASK_PKP52         DISP_BIT_IB10
+#define DISP_BITMASK_PKP51         DISP_BIT_IB09
+#define DISP_BITMASK_PKP50         DISP_BIT_IB08
+#define DISP_BITMASK_PKP42         DISP_BIT_IB02
+#define DISP_BITMASK_PKP41         DISP_BIT_IB01
+#define DISP_BITMASK_PKP40         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_4_ADDR       Gamma Control (4) */
+#define DISP_BITMASK_PRP12         DISP_BIT_IB10
+#define DISP_BITMASK_PRP11         DISP_BIT_IB08
+#define DISP_BITMASK_PRP10         DISP_BIT_IB09
+#define DISP_BITMASK_PRP02         DISP_BIT_IB02
+#define DISP_BITMASK_PRP01         DISP_BIT_IB01
+#define DISP_BITMASK_PRP00         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_5_ADDR       Gamma Control (5) */
+#define DISP_BITMASK_VRP14         DISP_BIT_IB12
+#define DISP_BITMASK_VRP13         DISP_BIT_IB11
+#define DISP_BITMASK_VRP12         DISP_BIT_IB10
+#define DISP_BITMASK_VRP11         DISP_BIT_IB08
+#define DISP_BITMASK_VRP10         DISP_BIT_IB09
+#define DISP_BITMASK_VRP03         DISP_BIT_IB03
+#define DISP_BITMASK_VRP02         DISP_BIT_IB02
+#define DISP_BITMASK_VRP01         DISP_BIT_IB01
+#define DISP_BITMASK_VRP00         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_6_ADDR       Gamma Control (6) */
+#define DISP_BITMASK_PKN12         DISP_BIT_IB10
+#define DISP_BITMASK_PKN11         DISP_BIT_IB08
+#define DISP_BITMASK_PKN10         DISP_BIT_IB09
+#define DISP_BITMASK_PKN02         DISP_BIT_IB02
+#define DISP_BITMASK_PKN01         DISP_BIT_IB01
+#define DISP_BITMASK_PKN00         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_7_ADDR       Gamma Control (7) */
+#define DISP_BITMASK_PKN32         DISP_BIT_IB10
+#define DISP_BITMASK_PKN31         DISP_BIT_IB08
+#define DISP_BITMASK_PKN30         DISP_BIT_IB09
+#define DISP_BITMASK_PKN22         DISP_BIT_IB02
+#define DISP_BITMASK_PKN21         DISP_BIT_IB01
+#define DISP_BITMASK_PKN20         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_8_ADDR       Gamma Control (8) */
+#define DISP_BITMASK_PKN52         DISP_BIT_IB10
+#define DISP_BITMASK_PKN51         DISP_BIT_IB08
+#define DISP_BITMASK_PKN50         DISP_BIT_IB09
+#define DISP_BITMASK_PKN42         DISP_BIT_IB02
+#define DISP_BITMASK_PKN41         DISP_BIT_IB01
+#define DISP_BITMASK_PKN40         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_9_ADDR       Gamma Control (9) */
+#define DISP_BITMASK_PRN12         DISP_BIT_IB10
+#define DISP_BITMASK_PRN11         DISP_BIT_IB08
+#define DISP_BITMASK_PRN10         DISP_BIT_IB09
+#define DISP_BITMASK_PRN02         DISP_BIT_IB02
+#define DISP_BITMASK_PRN01         DISP_BIT_IB01
+#define DISP_BITMASK_PRN00         DISP_BIT_IB00
+/* DISP_GAMMA_CONTROL_10_ADDR      Gamma Control (10) */
+#define DISP_BITMASK_VRN14         DISP_BIT_IB12
+#define DISP_BITMASK_VRN13         DISP_BIT_IB11
+#define DISP_BITMASK_VRN12         DISP_BIT_IB10
+#define DISP_BITMASK_VRN11         DISP_BIT_IB08
+#define DISP_BITMASK_VRN10         DISP_BIT_IB09
+#define DISP_BITMASK_VRN03         DISP_BIT_IB03
+#define DISP_BITMASK_VRN02         DISP_BIT_IB02
+#define DISP_BITMASK_VRN01         DISP_BIT_IB01
+#define DISP_BITMASK_VRN00         DISP_BIT_IB00
+/* Coordinate Control */
+/* DISP_VERT_SCROLL_CTL_1_ADDR     Vertical Scroll Control (1) */
+#define DISP_BITMASK_VL18          DISP_BIT_IB08
+#define DISP_BITMASK_VL17          DISP_BIT_IB07
+#define DISP_BITMASK_VL16          DISP_BIT_IB06
+#define DISP_BITMASK_VL15          DISP_BIT_IB05
+#define DISP_BITMASK_VL14          DISP_BIT_IB04
+#define DISP_BITMASK_VL13          DISP_BIT_IB03
+#define DISP_BITMASK_VL12          DISP_BIT_IB02
+#define DISP_BITMASK_VL11          DISP_BIT_IB01
+#define DISP_BITMASK_VL10          DISP_BIT_IB00
+/* DISP_VERT_SCROLL_CTL_2_ADDR     Vertical Scroll Control (2) */
+#define DISP_BITMASK_VL28          DISP_BIT_IB08
+#define DISP_BITMASK_VL27          DISP_BIT_IB07
+#define DISP_BITMASK_VL26          DISP_BIT_IB06
+#define DISP_BITMASK_VL25          DISP_BIT_IB05
+#define DISP_BITMASK_VL24          DISP_BIT_IB04
+#define DISP_BITMASK_VL23          DISP_BIT_IB03
+#define DISP_BITMASK_VL22          DISP_BIT_IB02
+#define DISP_BITMASK_VL21          DISP_BIT_IB01
+#define DISP_BITMASK_VL20          DISP_BIT_IB00
+/* DISP_SCREEN_1_DRV_POS_1_ADDR    First Screen Driving Position (1) */
+#define DISP_BITMASK_SS18          DISP_BIT_IB08
+#define DISP_BITMASK_SS17          DISP_BIT_IB07
+#define DISP_BITMASK_SS16          DISP_BIT_IB06
+#define DISP_BITMASK_SS15          DISP_BIT_IB05
+#define DISP_BITMASK_SS14          DISP_BIT_IB04
+#define DISP_BITMASK_SS13          DISP_BIT_IB03
+#define DISP_BITMASK_SS12          DISP_BIT_IB02
+#define DISP_BITMASK_SS11          DISP_BIT_IB01
+#define DISP_BITMASK_SS10          DISP_BIT_IB00
+/* DISP_SCREEN_1_DRV_POS_2_ADDR    First Screen Driving Position (2) */
+#define DISP_BITMASK_SE18          DISP_BIT_IB08
+#define DISP_BITMASK_SE17          DISP_BIT_IB07
+#define DISP_BITMASK_SE16          DISP_BIT_IB06
+#define DISP_BITMASK_SE15          DISP_BIT_IB05
+#define DISP_BITMASK_SE14          DISP_BIT_IB04
+#define DISP_BITMASK_SE13          DISP_BIT_IB03
+#define DISP_BITMASK_SE12          DISP_BIT_IB02
+#define DISP_BITMASK_SE11          DISP_BIT_IB01
+#define DISP_BITMASK_SE10          DISP_BIT_IB00
+/* DISP_SCREEN_2_DRV_POS_1_ADDR    Second Screen Driving Position (1) */
+#define DISP_BITMASK_SS28          DISP_BIT_IB08
+#define DISP_BITMASK_SS27          DISP_BIT_IB07
+#define DISP_BITMASK_SS26          DISP_BIT_IB06
+#define DISP_BITMASK_SS25          DISP_BIT_IB05
+#define DISP_BITMASK_SS24          DISP_BIT_IB04
+#define DISP_BITMASK_SS23          DISP_BIT_IB03
+#define DISP_BITMASK_SS22          DISP_BIT_IB02
+#define DISP_BITMASK_SS21          DISP_BIT_IB01
+#define DISP_BITMASK_SS20          DISP_BIT_IB00
+/* DISP_SCREEN_3_DRV_POS_2_ADDR    Second Screen Driving Position (2) */
+#define DISP_BITMASK_SE28          DISP_BIT_IB08
+#define DISP_BITMASK_SE27          DISP_BIT_IB07
+#define DISP_BITMASK_SE26          DISP_BIT_IB06
+#define DISP_BITMASK_SE25          DISP_BIT_IB05
+#define DISP_BITMASK_SE24          DISP_BIT_IB04
+#define DISP_BITMASK_SE23          DISP_BIT_IB03
+#define DISP_BITMASK_SE22          DISP_BIT_IB02
+#define DISP_BITMASK_SE21          DISP_BIT_IB01
+#define DISP_BITMASK_SE20          DISP_BIT_IB00
+/* DISP_HORZ_RAM_ADDR_POS_1_ADDR   Horizontal RAM Address Position (1) */
+#define DISP_BITMASK_HSA7          DISP_BIT_IB07
+#define DISP_BITMASK_HSA6          DISP_BIT_IB06
+#define DISP_BITMASK_HSA5          DISP_BIT_IB05
+#define DISP_BITMASK_HSA4          DISP_BIT_IB04
+#define DISP_BITMASK_HSA3          DISP_BIT_IB03
+#define DISP_BITMASK_HSA2          DISP_BIT_IB02
+#define DISP_BITMASK_HSA1          DISP_BIT_IB01
+#define DISP_BITMASK_HSA0          DISP_BIT_IB00
+/* DISP_HORZ_RAM_ADDR_POS_2_ADDR   Horizontal RAM Address Position (2) */
+#define DISP_BITMASK_HEA7          DISP_BIT_IB07
+#define DISP_BITMASK_HEA6          DISP_BIT_IB06
+#define DISP_BITMASK_HEA5          DISP_BIT_IB05
+#define DISP_BITMASK_HEA4          DISP_BIT_IB04
+#define DISP_BITMASK_HEA3          DISP_BIT_IB03
+#define DISP_BITMASK_HEA2          DISP_BIT_IB02
+#define DISP_BITMASK_HEA1          DISP_BIT_IB01
+#define DISP_BITMASK_HEA0          DISP_BIT_IB00
+/* DISP_VERT_RAM_ADDR_POS_1_ADDR   Vertical RAM Address Position (1) */
+#define DISP_BITMASK_VSA8          DISP_BIT_IB08
+#define DISP_BITMASK_VSA7          DISP_BIT_IB07
+#define DISP_BITMASK_VSA6          DISP_BIT_IB06
+#define DISP_BITMASK_VSA5          DISP_BIT_IB05
+#define DISP_BITMASK_VSA4          DISP_BIT_IB04
+#define DISP_BITMASK_VSA3          DISP_BIT_IB03
+#define DISP_BITMASK_VSA2          DISP_BIT_IB02
+#define DISP_BITMASK_VSA1          DISP_BIT_IB01
+#define DISP_BITMASK_VSA0          DISP_BIT_IB00
+/* DISP_VERT_RAM_ADDR_POS_2_ADDR   Vertical RAM Address Position (2) */
+#define DISP_BITMASK_VEA8          DISP_BIT_IB08
+#define DISP_BITMASK_VEA7          DISP_BIT_IB07
+#define DISP_BITMASK_VEA6          DISP_BIT_IB06
+#define DISP_BITMASK_VEA5          DISP_BIT_IB05
+#define DISP_BITMASK_VEA4          DISP_BIT_IB04
+#define DISP_BITMASK_VEA3          DISP_BIT_IB03
+#define DISP_BITMASK_VEA2          DISP_BIT_IB02
+#define DISP_BITMASK_VEA1          DISP_BIT_IB01
+#define DISP_BITMASK_VEA0          DISP_BIT_IB00
+static word disp_area_start_row;
+static word disp_area_end_row;
+static boolean disp_initialized = FALSE;
+/* For some reason the contrast set at init time is not good. Need to do
+* it again
+*/
+static boolean display_on = FALSE;
+
+static uint32 tmd20qvga_lcd_rev;
+uint16 tmd20qvga_panel_offset;
+
+#ifdef DISP_DEVICE_8BPP
+static word convert_8_to_16_tbl[256] = {
+	0x0000, 0x2000, 0x4000, 0x6000, 0x8000, 0xA000, 0xC000, 0xE000,
+	0x0100, 0x2100, 0x4100, 0x6100, 0x8100, 0xA100, 0xC100, 0xE100,
+	0x0200, 0x2200, 0x4200, 0x6200, 0x8200, 0xA200, 0xC200, 0xE200,
+	0x0300, 0x2300, 0x4300, 0x6300, 0x8300, 0xA300, 0xC300, 0xE300,
+	0x0400, 0x2400, 0x4400, 0x6400, 0x8400, 0xA400, 0xC400, 0xE400,
+	0x0500, 0x2500, 0x4500, 0x6500, 0x8500, 0xA500, 0xC500, 0xE500,
+	0x0600, 0x2600, 0x4600, 0x6600, 0x8600, 0xA600, 0xC600, 0xE600,
+	0x0700, 0x2700, 0x4700, 0x6700, 0x8700, 0xA700, 0xC700, 0xE700,
+	0x0008, 0x2008, 0x4008, 0x6008, 0x8008, 0xA008, 0xC008, 0xE008,
+	0x0108, 0x2108, 0x4108, 0x6108, 0x8108, 0xA108, 0xC108, 0xE108,
+	0x0208, 0x2208, 0x4208, 0x6208, 0x8208, 0xA208, 0xC208, 0xE208,
+	0x0308, 0x2308, 0x4308, 0x6308, 0x8308, 0xA308, 0xC308, 0xE308,
+	0x0408, 0x2408, 0x4408, 0x6408, 0x8408, 0xA408, 0xC408, 0xE408,
+	0x0508, 0x2508, 0x4508, 0x6508, 0x8508, 0xA508, 0xC508, 0xE508,
+	0x0608, 0x2608, 0x4608, 0x6608, 0x8608, 0xA608, 0xC608, 0xE608,
+	0x0708, 0x2708, 0x4708, 0x6708, 0x8708, 0xA708, 0xC708, 0xE708,
+	0x0010, 0x2010, 0x4010, 0x6010, 0x8010, 0xA010, 0xC010, 0xE010,
+	0x0110, 0x2110, 0x4110, 0x6110, 0x8110, 0xA110, 0xC110, 0xE110,
+	0x0210, 0x2210, 0x4210, 0x6210, 0x8210, 0xA210, 0xC210, 0xE210,
+	0x0310, 0x2310, 0x4310, 0x6310, 0x8310, 0xA310, 0xC310, 0xE310,
+	0x0410, 0x2410, 0x4410, 0x6410, 0x8410, 0xA410, 0xC410, 0xE410,
+	0x0510, 0x2510, 0x4510, 0x6510, 0x8510, 0xA510, 0xC510, 0xE510,
+	0x0610, 0x2610, 0x4610, 0x6610, 0x8610, 0xA610, 0xC610, 0xE610,
+	0x0710, 0x2710, 0x4710, 0x6710, 0x8710, 0xA710, 0xC710, 0xE710,
+	0x0018, 0x2018, 0x4018, 0x6018, 0x8018, 0xA018, 0xC018, 0xE018,
+	0x0118, 0x2118, 0x4118, 0x6118, 0x8118, 0xA118, 0xC118, 0xE118,
+	0x0218, 0x2218, 0x4218, 0x6218, 0x8218, 0xA218, 0xC218, 0xE218,
+	0x0318, 0x2318, 0x4318, 0x6318, 0x8318, 0xA318, 0xC318, 0xE318,
+	0x0418, 0x2418, 0x4418, 0x6418, 0x8418, 0xA418, 0xC418, 0xE418,
+	0x0518, 0x2518, 0x4518, 0x6518, 0x8518, 0xA518, 0xC518, 0xE518,
+	0x0618, 0x2618, 0x4618, 0x6618, 0x8618, 0xA618, 0xC618, 0xE618,
+	0x0718, 0x2718, 0x4718, 0x6718, 0x8718, 0xA718, 0xC718, 0xE718
+};
+#endif /* DISP_DEVICE_8BPP */
+
+static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres);
+static void tmd20qvga_disp_init(struct platform_device *pdev);
+static void tmd20qvga_disp_set_contrast(void);
+static void tmd20qvga_disp_set_display_area(word start_row, word end_row);
+static int tmd20qvga_disp_off(struct platform_device *pdev);
+static int tmd20qvga_disp_on(struct platform_device *pdev);
+static void tmd20qvga_set_revId(int);
+
+/* future use */
+void tmd20qvga_disp_clear_screen_area(word start_row, word end_row,
+				      word start_column, word end_column);
+
+static void tmd20qvga_set_revId(int id)
+{
+
+	tmd20qvga_lcd_rev = id;
+
+	if (tmd20qvga_lcd_rev == 1)
+		tmd20qvga_panel_offset = 0x10;
+	else
+		tmd20qvga_panel_offset = 0;
+}
+
+static void tmd20qvga_disp_init(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+
+	if (disp_initialized)
+		return;
+
+	mfd = platform_get_drvdata(pdev);
+
+	DISP_CMD_PORT = mfd->cmd_port;
+	DISP_DATA_PORT = mfd->data_port;
+
+#ifdef TMD20QVGA_LCD_18BPP
+	tmd20qvga_set_revId(2);
+#else
+	tmd20qvga_set_revId(1);
+#endif
+
+	disp_initialized = TRUE;
+	tmd20qvga_disp_set_contrast();
+	tmd20qvga_disp_set_display_area(0, QVGA_HEIGHT - 1);
+}
+
+static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres)
+{
+	if (!disp_initialized)
+		return;
+
+	DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1);
+
+	DISP_CMD_OUT(DISP_CMD_RAMWR);
+}
+
+static void tmd20qvga_disp_set_display_area(word start_row, word end_row)
+{
+	word start_driving = start_row;
+	word end_driving = end_row;
+
+	if (!disp_initialized)
+		return;
+
+	/* Range checking
+	 */
+	if (end_driving >= QVGA_HEIGHT)
+		end_driving = QVGA_HEIGHT - 1;
+	if (start_driving > end_driving) {
+		/* Probably Backwards Switch */
+		start_driving = end_driving;
+		end_driving = start_row;	/* Has not changed */
+		if (end_driving >= QVGA_HEIGHT)
+			end_driving = QVGA_HEIGHT - 1;
+	}
+
+	if ((start_driving == disp_area_start_row)
+	    && (end_driving == disp_area_end_row))
+		return;
+
+	disp_area_start_row = start_driving;
+	disp_area_end_row = end_driving;
+
+	DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR,
+		       DISP_VAL_IF(start_driving & 0x100,
+				   DISP_BITMASK_SS18) |
+		       DISP_VAL_IF(start_driving & 0x080,
+				   DISP_BITMASK_SS17) |
+		       DISP_VAL_IF(start_driving & 0x040,
+				   DISP_BITMASK_SS16) |
+		       DISP_VAL_IF(start_driving & 0x020,
+				   DISP_BITMASK_SS15) |
+		       DISP_VAL_IF(start_driving & 0x010,
+				   DISP_BITMASK_SS14) |
+		       DISP_VAL_IF(start_driving & 0x008,
+				   DISP_BITMASK_SS13) |
+		       DISP_VAL_IF(start_driving & 0x004,
+				   DISP_BITMASK_SS12) |
+		       DISP_VAL_IF(start_driving & 0x002,
+				   DISP_BITMASK_SS11) |
+		       DISP_VAL_IF(start_driving & 0x001, DISP_BITMASK_SS10));
+
+	DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR,
+			DISP_VAL_IF(end_driving & 0x100, DISP_BITMASK_SE18) |
+			DISP_VAL_IF(end_driving & 0x080, DISP_BITMASK_SE17) |
+			DISP_VAL_IF(end_driving & 0x040, DISP_BITMASK_SE16) |
+			DISP_VAL_IF(end_driving & 0x020, DISP_BITMASK_SE15) |
+			DISP_VAL_IF(end_driving & 0x010, DISP_BITMASK_SE14) |
+			DISP_VAL_IF(end_driving & 0x008, DISP_BITMASK_SE13) |
+			DISP_VAL_IF(end_driving & 0x004, DISP_BITMASK_SE12) |
+			DISP_VAL_IF(end_driving & 0x002, DISP_BITMASK_SE11) |
+			DISP_VAL_IF(end_driving & 0x001, DISP_BITMASK_SE10));
+}
+
+static int tmd20qvga_disp_off(struct platform_device *pdev)
+{
+	if (!disp_initialized)
+		tmd20qvga_disp_init(pdev);
+
+	if (display_on) {
+		if (tmd20qvga_lcd_rev == 2) {
+			DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000A);
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFEE);
+			WAIT_MSEC(40);
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xF812);
+			WAIT_MSEC(40);
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xE811);
+			WAIT_MSEC(40);
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC011);
+			WAIT_MSEC(40);
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x4011);
+			WAIT_MSEC(20);
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0010);
+
+		} else {
+			DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000F);
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFE);
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+			WAIT_MSEC(40);
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BED);
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+			WAIT_MSEC(40);
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x00CD);
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+			WAIT_MSEC(20);
+			DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0);
+		}
+
+		DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0004);
+		DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0000);
+
+		display_on = FALSE;
+	}
+
+	return 0;
+}
+
+static int tmd20qvga_disp_on(struct platform_device *pdev)
+{
+	if (!disp_initialized)
+		tmd20qvga_disp_init(pdev);
+
+	if (!display_on) {
+		/* Deep Stand-by -> Stand-by */
+		DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
+		WAIT_MSEC(1);
+		DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
+		WAIT_MSEC(1);
+		DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR);
+		WAIT_MSEC(1);
+
+		/* OFF -> Deep Stan-By -> Stand-by */
+		/* let's change the state from "Stand-by" to "Sleep" */
+		DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0005);
+		WAIT_MSEC(1);
+
+		/* Sleep -> Displaying */
+		DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0001);
+		DISP_WRITE_OUT(DISP_DRIVER_OUTPUT_CTL_ADDR, 0x0127);
+		DISP_WRITE_OUT(DISP_LCD_DRIVING_SIG_ADDR, 0x200);
+		/* fast write mode */
+		DISP_WRITE_OUT(DISP_ENTRY_MODE_ADDR, 0x0130);
+		if (tmd20qvga_lcd_rev == 2)
+			DISP_WRITE_OUT(DISP_TMD_700_ADDR, 0x0003);
+		/* back porch = 14 + front porch = 2 --> 16 lines */
+		if (tmd20qvga_lcd_rev == 2) {
+#ifdef TMD20QVGA_LCD_18BPP
+			/* 256k color */
+			DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0000);
+#else
+			/* 65k color */
+			DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4000);
+#endif
+			DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x0302);
+		} else {
+#ifdef TMD20QVGA_LCD_18BPP
+			/* 256k color */
+			DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0004);
+#else
+			/* 65k color */
+			DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4004);
+#endif
+			DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x020E);
+		}
+		/* 16 bit one transfer */
+		if (tmd20qvga_lcd_rev == 2) {
+			DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0000);
+			DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010);
+			DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0302);
+			DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0102);
+			DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000);
+			DISP_WRITE_OUT(DISP_TMD_015_ADDR, 0x2000);
+
+			DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000);
+			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
+			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0304);
+			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403);
+			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
+			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0101);
+			DISP_WRITE_OUT(DISP_TMD_305_ADDR, 0);
+
+			DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000);
+			DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F);
+
+			DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x077D);
+
+			DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0005);
+			DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0000);
+			DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0015);
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC010);
+			WAIT_MSEC(1);
+
+			DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x0001);
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFFE);
+			WAIT_MSEC(60);
+		} else {
+			DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0001);
+			DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010);
+			DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0301);
+			DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0001);
+			DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000);
+			DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000);
+			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0507);
+			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0405);
+			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0607);
+			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0502);
+			DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0301);
+			DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000);
+			DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F);
+			DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x0795);
+
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0102);
+			WAIT_MSEC(1);
+
+			DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0450);
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0103);
+			WAIT_MSEC(1);
+
+			DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0008);
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0104);
+			WAIT_MSEC(1);
+
+			DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0C00);
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0105);
+			WAIT_MSEC(1);
+
+			DISP_WRITE_OUT(DISP_POWER_CTL_7_ADDR, 0x0000);
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0106);
+			WAIT_MSEC(1);
+
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0801);
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+			WAIT_MSEC(1);
+
+			DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x001F);
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101);
+			WAIT_MSEC(60);
+
+			DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x009F);
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101);
+			WAIT_MSEC(10);
+
+			DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, 0x0010);
+			DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, 0x00FF);
+			DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, 0x0000);
+			DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, 0x013F);
+			/* RAM starts at address 0x10 */
+			DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, 0x0010);
+			DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, 0x0000);
+
+			/* lcd controller uses internal clock, not ext. vsync */
+			DISP_CMD_OUT(DISP_CMD_RAMWR);
+
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0881);
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+			WAIT_MSEC(40);
+
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BE1);
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+			WAIT_MSEC(40);
+
+			DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFF);
+			DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100);
+		}
+		display_on = TRUE;
+	}
+
+	return 0;
+}
+
+static void tmd20qvga_disp_set_contrast(void)
+{
+#if (defined(TMD20QVGA_LCD_18BPP))
+
+	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
+	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0302);
+	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403);
+	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
+	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07);
+
+#else
+	int newcontrast = 0x46;
+
+	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403);
+
+	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR,
+			DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP20) |
+			DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP21) |
+			DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP22) |
+			DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP30) |
+			DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP31) |
+			DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP32));
+
+	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR,
+			DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP40) |
+			DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP41) |
+			DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP42) |
+			DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP50) |
+			DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP51) |
+			DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP52));
+
+	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303);
+	DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07);
+
+#endif /* defined(TMD20QVGA_LCD_18BPP) */
+
+}	/* End disp_set_contrast */
+
+void tmd20qvga_disp_clear_screen_area
+    (word start_row, word end_row, word start_column, word end_column) {
+	int32 i;
+
+	/* Clear the display screen */
+	DISP_SET_RECT(start_row, end_row, start_column, end_column);
+	DISP_CMD_OUT(DISP_CMD_RAMWR);
+	i = (end_row - start_row + 1) * (end_column - start_column + 1);
+	for (; i > 0; i--)
+		DISP_DATA_OUT_16TO18BPP(0x0);
+}
+
+static int __init tmd20qvga_probe(struct platform_device *pdev)
+{
+	msm_fb_add_device(pdev);
+
+	return 0;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = tmd20qvga_probe,
+	.driver = {
+		.name   = "ebi2_tmd_qvga",
+	},
+};
+
+static struct msm_fb_panel_data tmd20qvga_panel_data = {
+	.on = tmd20qvga_disp_on,
+	.off = tmd20qvga_disp_off,
+	.set_rect = tmd20qvga_disp_set_rect,
+};
+
+static struct platform_device this_device = {
+	.name   = "ebi2_tmd_qvga",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &tmd20qvga_panel_data,
+	}
+};
+
+static int __init tmd20qvga_init(void)
+{
+	int ret;
+	struct msm_panel_info *pinfo;
+
+	ret = platform_driver_register(&this_driver);
+	if (!ret) {
+		pinfo = &tmd20qvga_panel_data.panel_info;
+		pinfo->xres = 240;
+		pinfo->yres = 320;
+		pinfo->type = EBI2_PANEL;
+		pinfo->pdest = DISPLAY_1;
+		pinfo->wait_cycle = 0x808000;
+#ifdef TMD20QVGA_LCD_18BPP
+		pinfo->bpp = 18;
+#else
+		pinfo->bpp = 16;
+#endif
+		pinfo->fb_num = 2;
+		pinfo->lcd.vsync_enable = TRUE;
+		pinfo->lcd.refx100 = 6000;
+		pinfo->lcd.v_back_porch = 16;
+		pinfo->lcd.v_front_porch = 4;
+		pinfo->lcd.v_pulse_width = 0;
+		pinfo->lcd.hw_vsync_mode = FALSE;
+		pinfo->lcd.vsync_notifier_period = 0;
+
+		ret = platform_device_register(&this_device);
+		if (ret)
+			platform_driver_unregister(&this_driver);
+	}
+
+	return ret;
+}
+
+module_init(tmd20qvga_init);

+ 248 - 0
drivers/staging/msm/hdmi_sii9022.c

@@ -0,0 +1,248 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include "msm_fb.h"
+
+#define DEVICE_NAME "sii9022"
+#define SII9022_DEVICE_ID   0xB0
+
+struct sii9022_i2c_addr_data{
+	u8 addr;
+	u8 data;
+};
+
+/* video mode data */
+static u8 video_mode_data[] = {
+	0x00,
+	0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
+};
+
+static u8 avi_io_format[] = {
+	0x09,
+	0x00, 0x00,
+};
+
+/* power state */
+static struct sii9022_i2c_addr_data regset0[] = {
+	{ 0x60, 0x04 },
+	{ 0x63, 0x00 },
+	{ 0x1E, 0x00 },
+};
+
+static u8 video_infoframe[] = {
+	0x0C,
+	0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
+	0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
+};
+
+/* configure audio */
+static struct sii9022_i2c_addr_data regset1[] = {
+	{ 0x26, 0x90 },
+	{ 0x20, 0x90 },
+	{ 0x1F, 0x80 },
+	{ 0x26, 0x80 },
+	{ 0x24, 0x02 },
+	{ 0x25, 0x0B },
+	{ 0xBC, 0x02 },
+	{ 0xBD, 0x24 },
+	{ 0xBE, 0x02 },
+};
+
+/* enable audio */
+static u8 misc_infoframe[] = {
+	0xBF,
+	0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+/* set HDMI, active */
+static struct sii9022_i2c_addr_data regset2[] = {
+	{ 0x1A, 0x01 },
+	{ 0x3D, 0x00 },
+};
+
+static int send_i2c_data(struct i2c_client *client,
+			 struct sii9022_i2c_addr_data *regset,
+			 int size)
+{
+	int i;
+	int rc = 0;
+
+	for (i = 0; i < size; i++) {
+		rc = i2c_smbus_write_byte_data(
+			client,
+			regset[i].addr, regset[i].data);
+		if (rc)
+			break;
+	}
+	return rc;
+}
+
+static int hdmi_sii_enable(struct i2c_client *client)
+{
+	int rc;
+	int retries = 10;
+	int count;
+
+	rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
+	if (rc)
+		goto enable_exit;
+
+	do {
+		msleep(1);
+		rc = i2c_smbus_read_byte_data(client, 0x1B);
+	} while ((rc != SII9022_DEVICE_ID) && retries--);
+
+	if (rc != SII9022_DEVICE_ID)
+		return -ENODEV;
+
+	rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
+	if (rc)
+		goto enable_exit;
+
+	count = ARRAY_SIZE(video_mode_data);
+	rc = i2c_master_send(client, video_mode_data, count);
+	if (rc != count) {
+		rc = -EIO;
+		goto enable_exit;
+	}
+
+	rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
+	if (rc)
+		goto enable_exit;
+	count = ARRAY_SIZE(avi_io_format);
+	rc = i2c_master_send(client, avi_io_format, count);
+	if (rc != count) {
+		rc = -EIO;
+		goto enable_exit;
+	}
+
+	rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
+	if (rc)
+		goto enable_exit;
+
+	count = ARRAY_SIZE(video_infoframe);
+	rc = i2c_master_send(client, video_infoframe, count);
+	if (rc != count) {
+		rc = -EIO;
+		goto enable_exit;
+	}
+
+	rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
+	if (rc)
+		goto enable_exit;
+
+	count = ARRAY_SIZE(misc_infoframe);
+	rc = i2c_master_send(client, misc_infoframe, count);
+	if (rc != count) {
+		rc = -EIO;
+		goto enable_exit;
+	}
+
+	rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
+	if (rc)
+		goto enable_exit;
+
+	return 0;
+enable_exit:
+	printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
+	return rc;
+}
+
+static const struct i2c_device_id hmdi_sii_id[] = {
+	{ DEVICE_NAME, 0 },
+	{ }
+};
+
+static int hdmi_sii_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int rc;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
+		return -ENODEV;
+	rc = hdmi_sii_enable(client);
+	return rc;
+}
+
+
+static struct i2c_driver hdmi_sii_i2c_driver = {
+	.driver = {
+		.name = DEVICE_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = hdmi_sii_probe,
+	.remove =  __exit_p(hdmi_sii_remove),
+	.id_table = hmdi_sii_id,
+};
+
+static int __init hdmi_sii_init(void)
+{
+	int ret;
+	struct msm_panel_info pinfo;
+
+	if (msm_fb_detect_client("hdmi_sii9022"))
+		return 0;
+
+	pinfo.xres = 1280;
+	pinfo.yres = 720;
+	pinfo.type = HDMI_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 24;
+	pinfo.fb_num = 2;
+	pinfo.clk_rate = 74250000;
+
+	pinfo.lcdc.h_back_porch = 124;
+	pinfo.lcdc.h_front_porch = 110;
+	pinfo.lcdc.h_pulse_width = 136;
+	pinfo.lcdc.v_back_porch = 19;
+	pinfo.lcdc.v_front_porch = 5;
+	pinfo.lcdc.v_pulse_width = 6;
+	pinfo.lcdc.border_clr = 0;
+	pinfo.lcdc.underflow_clr = 0xff;
+	pinfo.lcdc.hsync_skew = 0;
+
+	ret = lcdc_device_register(&pinfo);
+	if (ret) {
+		printk(KERN_ERR "%s: failed to register device\n", __func__);
+		goto init_exit;
+	}
+
+	ret = i2c_add_driver(&hdmi_sii_i2c_driver);
+	if (ret)
+		printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
+
+init_exit:
+	return ret;
+}
+
+static void __exit hdmi_sii_exit(void)
+{
+	i2c_del_driver(&hdmi_sii_i2c_driver);
+}
+
+module_init(hdmi_sii_init);
+module_exit(hdmi_sii_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.1");
+MODULE_AUTHOR("Qualcomm Innovation Center, Inc.");
+MODULE_DESCRIPTION("SiI9022 HDMI driver");
+MODULE_ALIAS("platform:hdmi-sii9022");

+ 239 - 0
drivers/staging/msm/lcdc.c

@@ -0,0 +1,239 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_qos_params.h>
+
+#include "msm_fb.h"
+
+static int lcdc_probe(struct platform_device *pdev);
+static int lcdc_remove(struct platform_device *pdev);
+
+static int lcdc_off(struct platform_device *pdev);
+static int lcdc_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static struct clk *mdp_lcdc_pclk_clk;
+static struct clk *mdp_lcdc_pad_pclk_clk;
+
+int mdp_lcdc_pclk_clk_rate;
+int mdp_lcdc_pad_pclk_clk_rate;
+
+static struct platform_driver lcdc_driver = {
+	.probe = lcdc_probe,
+	.remove = lcdc_remove,
+	.suspend = NULL,
+	.resume = NULL,
+	.shutdown = NULL,
+	.driver = {
+		   .name = "lcdc",
+		   },
+};
+
+static struct lcdc_platform_data *lcdc_pdata;
+
+static int lcdc_off(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	ret = panel_next_off(pdev);
+
+	clk_disable(mdp_lcdc_pclk_clk);
+	clk_disable(mdp_lcdc_pad_pclk_clk);
+
+	if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
+		lcdc_pdata->lcdc_power_save(0);
+
+	if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
+		ret = lcdc_pdata->lcdc_gpio_config(0);
+
+//	pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
+//					PM_QOS_DEFAULT_VALUE);
+
+	return ret;
+}
+
+static int lcdc_on(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct msm_fb_data_type *mfd;
+	unsigned long panel_pixclock_freq , pm_qos_freq;
+
+	mfd = platform_get_drvdata(pdev);
+	panel_pixclock_freq = mfd->fbi->var.pixclock;
+
+	if (panel_pixclock_freq > 58000000)
+		/* pm_qos_freq should be in Khz */
+		pm_qos_freq = panel_pixclock_freq / 1000 ;
+	else
+		pm_qos_freq = 58000;
+
+//	pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
+//						pm_qos_freq);
+	mfd = platform_get_drvdata(pdev);
+
+	clk_enable(mdp_lcdc_pclk_clk);
+	clk_enable(mdp_lcdc_pad_pclk_clk);
+
+	if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
+		lcdc_pdata->lcdc_power_save(1);
+	if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config)
+		ret = lcdc_pdata->lcdc_gpio_config(1);
+
+	clk_set_rate(mdp_lcdc_pclk_clk, mfd->fbi->var.pixclock);
+	clk_set_rate(mdp_lcdc_pad_pclk_clk, mfd->fbi->var.pixclock);
+	mdp_lcdc_pclk_clk_rate = clk_get_rate(mdp_lcdc_pclk_clk);
+	mdp_lcdc_pad_pclk_clk_rate = clk_get_rate(mdp_lcdc_pad_pclk_clk);
+
+	ret = panel_next_on(pdev);
+	return ret;
+}
+
+static int lcdc_probe(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+	struct fb_info *fbi;
+	struct platform_device *mdp_dev = NULL;
+	struct msm_fb_panel_data *pdata = NULL;
+	int rc;
+
+	if (pdev->id == 0) {
+		lcdc_pdata = pdev->dev.platform_data;
+		return 0;
+	}
+
+	mfd = platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+		return -ENOMEM;
+
+	mdp_dev = platform_device_alloc("mdp", pdev->id);
+	if (!mdp_dev)
+		return -ENOMEM;
+
+	/*
+	 * link to the latest pdev
+	 */
+	mfd->pdev = mdp_dev;
+	mfd->dest = DISPLAY_LCDC;
+
+	/*
+	 * alloc panel device data
+	 */
+	if (platform_device_add_data
+	    (mdp_dev, pdev->dev.platform_data,
+	     sizeof(struct msm_fb_panel_data))) {
+		printk(KERN_ERR "lcdc_probe: platform_device_add_data failed!\n");
+		platform_device_put(mdp_dev);
+		return -ENOMEM;
+	}
+	/*
+	 * data chain
+	 */
+	pdata = (struct msm_fb_panel_data *)mdp_dev->dev.platform_data;
+	pdata->on = lcdc_on;
+	pdata->off = lcdc_off;
+	pdata->next = pdev;
+
+	/*
+	 * get/set panel specific fb info
+	 */
+	mfd->panel_info = pdata->panel_info;
+	mfd->fb_imgType = MDP_RGB_565;
+
+	fbi = mfd->fbi;
+	fbi->var.pixclock = mfd->panel_info.clk_rate;
+	fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
+	fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
+	fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
+	fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
+	fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
+	fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;
+
+	/*
+	 * set driver data
+	 */
+	platform_set_drvdata(mdp_dev, mfd);
+
+	/*
+	 * register in mdp driver
+	 */
+	rc = platform_device_add(mdp_dev);
+	if (rc)
+		goto lcdc_probe_err;
+
+	pdev_list[pdev_list_cnt++] = pdev;
+		return 0;
+
+lcdc_probe_err:
+	platform_device_put(mdp_dev);
+	return rc;
+}
+
+static int lcdc_remove(struct platform_device *pdev)
+{
+//	pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc");
+	return 0;
+}
+
+static int lcdc_register_driver(void)
+{
+	return platform_driver_register(&lcdc_driver);
+}
+
+static int __init lcdc_driver_init(void)
+{
+	mdp_lcdc_pclk_clk = clk_get(NULL, "mdp_lcdc_pclk_clk");
+	if (IS_ERR(mdp_lcdc_pclk_clk)) {
+		printk(KERN_ERR "error: can't get mdp_lcdc_pclk_clk!\n");
+		return IS_ERR(mdp_lcdc_pclk_clk);
+	}
+	mdp_lcdc_pad_pclk_clk = clk_get(NULL, "mdp_lcdc_pad_pclk_clk");
+	if (IS_ERR(mdp_lcdc_pad_pclk_clk)) {
+		printk(KERN_ERR "error: can't get mdp_lcdc_pad_pclk_clk!\n");
+		return IS_ERR(mdp_lcdc_pad_pclk_clk);
+	}
+//	pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
+//				PM_QOS_DEFAULT_VALUE);
+	return lcdc_register_driver();
+}
+
+module_init(lcdc_driver_init);

+ 54 - 0
drivers/staging/msm/lcdc_external.c

@@ -0,0 +1,54 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+static int __init lcdc_external_init(void)
+{
+	int ret;
+	struct msm_panel_info pinfo;
+
+	if (msm_fb_detect_client("lcdc_external"))
+		return 0;
+
+	pinfo.xres = 1280;
+	pinfo.yres = 720;
+	pinfo.type = LCDC_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 24;
+	pinfo.fb_num = 2;
+	pinfo.clk_rate = 74250000;
+
+	pinfo.lcdc.h_back_porch = 124;
+	pinfo.lcdc.h_front_porch = 110;
+	pinfo.lcdc.h_pulse_width = 136;
+	pinfo.lcdc.v_back_porch = 19;
+	pinfo.lcdc.v_front_porch = 5;
+	pinfo.lcdc.v_pulse_width = 6;
+	pinfo.lcdc.border_clr = 0;	/* blk */
+	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
+	pinfo.lcdc.hsync_skew = 0;
+
+	ret = lcdc_device_register(&pinfo);
+	if (ret)
+		printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(lcdc_external_init);

+ 446 - 0
drivers/staging/msm/lcdc_gordon.c

@@ -0,0 +1,446 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/delay.h>
+#include <mach/gpio.h>
+#include "msm_fb.h"
+
+/* registers */
+#define GORDON_REG_NOP          0x00
+#define GORDON_REG_IMGCTL1      0x10
+#define GORDON_REG_IMGCTL2      0x11
+#define GORDON_REG_IMGSET1      0x12
+#define GORDON_REG_IMGSET2      0x13
+#define GORDON_REG_IVBP1        0x14
+#define GORDON_REG_IHBP1        0x15
+#define GORDON_REG_IVNUM1       0x16
+#define GORDON_REG_IHNUM1       0x17
+#define GORDON_REG_IVBP2        0x18
+#define GORDON_REG_IHBP2        0x19
+#define GORDON_REG_IVNUM2       0x1A
+#define GORDON_REG_IHNUM2       0x1B
+#define GORDON_REG_LCDIFCTL1    0x30
+#define GORDON_REG_VALTRAN      0x31
+#define GORDON_REG_AVCTL        0x33
+#define GORDON_REG_LCDIFCTL2    0x34
+#define GORDON_REG_LCDIFCTL3    0x35
+#define GORDON_REG_LCDIFSET1    0x36
+#define GORDON_REG_PCCTL        0x3C
+#define GORDON_REG_TPARAM1      0x40
+#define GORDON_REG_TLCDIF1      0x41
+#define GORDON_REG_TSSPB_ST1    0x42
+#define GORDON_REG_TSSPB_ED1    0x43
+#define GORDON_REG_TSCK_ST1     0x44
+#define GORDON_REG_TSCK_WD1     0x45
+#define GORDON_REG_TGSPB_VST1   0x46
+#define GORDON_REG_TGSPB_VED1   0x47
+#define GORDON_REG_TGSPB_CH1    0x48
+#define GORDON_REG_TGCK_ST1     0x49
+#define GORDON_REG_TGCK_ED1     0x4A
+#define GORDON_REG_TPCTL_ST1    0x4B
+#define GORDON_REG_TPCTL_ED1    0x4C
+#define GORDON_REG_TPCHG_ED1    0x4D
+#define GORDON_REG_TCOM_CH1     0x4E
+#define GORDON_REG_THBP1        0x4F
+#define GORDON_REG_TPHCTL1      0x50
+#define GORDON_REG_EVPH1        0x51
+#define GORDON_REG_EVPL1        0x52
+#define GORDON_REG_EVNH1        0x53
+#define GORDON_REG_EVNL1        0x54
+#define GORDON_REG_TBIAS1       0x55
+#define GORDON_REG_TPARAM2      0x56
+#define GORDON_REG_TLCDIF2      0x57
+#define GORDON_REG_TSSPB_ST2    0x58
+#define GORDON_REG_TSSPB_ED2    0x59
+#define GORDON_REG_TSCK_ST2     0x5A
+#define GORDON_REG_TSCK_WD2     0x5B
+#define GORDON_REG_TGSPB_VST2   0x5C
+#define GORDON_REG_TGSPB_VED2   0x5D
+#define GORDON_REG_TGSPB_CH2    0x5E
+#define GORDON_REG_TGCK_ST2     0x5F
+#define GORDON_REG_TGCK_ED2     0x60
+#define GORDON_REG_TPCTL_ST2    0x61
+#define GORDON_REG_TPCTL_ED2    0x62
+#define GORDON_REG_TPCHG_ED2    0x63
+#define GORDON_REG_TCOM_CH2     0x64
+#define GORDON_REG_THBP2        0x65
+#define GORDON_REG_TPHCTL2      0x66
+#define GORDON_REG_POWCTL       0x80
+
+static int lcdc_gordon_panel_off(struct platform_device *pdev);
+
+static int spi_cs;
+static int spi_sclk;
+static int spi_sdo;
+static int spi_sdi;
+static int spi_dac;
+static unsigned char bit_shift[8] = { (1 << 7),	/* MSB */
+	(1 << 6),
+	(1 << 5),
+	(1 << 4),
+	(1 << 3),
+	(1 << 2),
+	(1 << 1),
+	(1 << 0)		               /* LSB */
+};
+
+struct gordon_state_type{
+	boolean disp_initialized;
+	boolean display_on;
+	boolean disp_powered_up;
+};
+
+static struct gordon_state_type gordon_state = { 0 };
+static struct msm_panel_common_pdata *lcdc_gordon_pdata;
+
+static void serigo(uint16 reg, uint8 data)
+{
+	unsigned int tx_val = ((0x00FF & reg) << 8) | data;
+	unsigned char i, val = 0;
+
+	/* Enable the Chip Select */
+	gpio_set_value(spi_cs, 1);
+	udelay(33);
+
+	/* Transmit it in two parts, Higher Byte first, then Lower Byte */
+	val = (unsigned char)((tx_val & 0xFF00) >> 8);
+
+	/* Clock should be Low before entering ! */
+	for (i = 0; i < 8; i++) {
+		/* #1: Drive the Data (High or Low) */
+		if (val & bit_shift[i])
+			gpio_set_value(spi_sdi, 1);
+		else
+			gpio_set_value(spi_sdi, 0);
+
+		/* #2: Drive the Clk High and then Low */
+		udelay(33);
+		gpio_set_value(spi_sclk, 1);
+		udelay(33);
+		gpio_set_value(spi_sclk, 0);
+	}
+
+	/* Idle state of SDO (MOSI) is Low */
+	gpio_set_value(spi_sdi, 0);
+	/* ..then Lower Byte */
+	val = (uint8) (tx_val & 0x00FF);
+	/* Before we enter here the Clock should be Low ! */
+
+	for (i = 0; i < 8; i++) {
+		/* #1: Drive the Data (High or Low) */
+		if (val & bit_shift[i])
+			gpio_set_value(spi_sdi, 1);
+		else
+			gpio_set_value(spi_sdi, 0);
+
+		/* #2: Drive the Clk High and then Low */
+		udelay(33);
+
+		gpio_set_value(spi_sclk, 1);
+		udelay(33);
+		gpio_set_value(spi_sclk, 0);
+	}
+
+	/* Idle state of SDO (MOSI) is Low */
+	gpio_set_value(spi_sdi, 0);
+
+	/* Now Disable the Chip Select */
+	udelay(33);
+	gpio_set_value(spi_cs, 0);
+}
+
+static void spi_init(void)
+{
+	/* Setting the Default GPIO's */
+	spi_sclk = *(lcdc_gordon_pdata->gpio_num);
+	spi_cs   = *(lcdc_gordon_pdata->gpio_num + 1);
+	spi_sdi  = *(lcdc_gordon_pdata->gpio_num + 2);
+	spi_sdo  = *(lcdc_gordon_pdata->gpio_num + 3);
+
+	/* Set the output so that we dont disturb the slave device */
+	gpio_set_value(spi_sclk, 0);
+	gpio_set_value(spi_sdi, 0);
+
+	/* Set the Chip Select De-asserted */
+	gpio_set_value(spi_cs, 0);
+
+}
+
+static void gordon_disp_powerup(void)
+{
+	if (!gordon_state.disp_powered_up && !gordon_state.display_on) {
+		/* Reset the hardware first */
+		/* Include DAC power up implementation here */
+	      gordon_state.disp_powered_up = TRUE;
+	}
+}
+
+static void gordon_init(void)
+{
+	/* Image interface settings */
+	serigo(GORDON_REG_IMGCTL2, 0x00);
+	serigo(GORDON_REG_IMGSET1, 0x00);
+
+	/* Exchange the RGB signal for J510(Softbank mobile) */
+	serigo(GORDON_REG_IMGSET2, 0x12);
+	serigo(GORDON_REG_LCDIFSET1, 0x00);
+
+	/* Pre-charge settings */
+	serigo(GORDON_REG_PCCTL, 0x09);
+	serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+
+	mdelay(1);
+}
+
+static void gordon_disp_on(void)
+{
+	if (gordon_state.disp_powered_up && !gordon_state.display_on) {
+		gordon_init();
+		mdelay(20);
+		/* gordon_dispmode setting */
+		serigo(GORDON_REG_TPARAM1, 0x30);
+		serigo(GORDON_REG_TLCDIF1, 0x00);
+		serigo(GORDON_REG_TSSPB_ST1, 0x8B);
+		serigo(GORDON_REG_TSSPB_ED1, 0x93);
+		serigo(GORDON_REG_TSCK_ST1, 0x88);
+		serigo(GORDON_REG_TSCK_WD1, 0x00);
+		serigo(GORDON_REG_TGSPB_VST1, 0x01);
+		serigo(GORDON_REG_TGSPB_VED1, 0x02);
+		serigo(GORDON_REG_TGSPB_CH1, 0x5E);
+		serigo(GORDON_REG_TGCK_ST1, 0x80);
+		serigo(GORDON_REG_TGCK_ED1, 0x3C);
+		serigo(GORDON_REG_TPCTL_ST1, 0x50);
+		serigo(GORDON_REG_TPCTL_ED1, 0x74);
+		serigo(GORDON_REG_TPCHG_ED1, 0x78);
+		serigo(GORDON_REG_TCOM_CH1, 0x50);
+		serigo(GORDON_REG_THBP1, 0x84);
+		serigo(GORDON_REG_TPHCTL1, 0x00);
+		serigo(GORDON_REG_EVPH1, 0x70);
+		serigo(GORDON_REG_EVPL1, 0x64);
+		serigo(GORDON_REG_EVNH1, 0x56);
+		serigo(GORDON_REG_EVNL1, 0x48);
+		serigo(GORDON_REG_TBIAS1, 0x88);
+
+		/* QVGA settings */
+		serigo(GORDON_REG_TPARAM2, 0x28);
+		serigo(GORDON_REG_TLCDIF2, 0x14);
+		serigo(GORDON_REG_TSSPB_ST2, 0x49);
+		serigo(GORDON_REG_TSSPB_ED2, 0x4B);
+		serigo(GORDON_REG_TSCK_ST2, 0x4A);
+		serigo(GORDON_REG_TSCK_WD2, 0x02);
+		serigo(GORDON_REG_TGSPB_VST2, 0x02);
+		serigo(GORDON_REG_TGSPB_VED2, 0x03);
+		serigo(GORDON_REG_TGSPB_CH2, 0x2F);
+		serigo(GORDON_REG_TGCK_ST2, 0x40);
+		serigo(GORDON_REG_TGCK_ED2, 0x1E);
+		serigo(GORDON_REG_TPCTL_ST2, 0x2C);
+		serigo(GORDON_REG_TPCTL_ED2, 0x3A);
+		serigo(GORDON_REG_TPCHG_ED2, 0x3C);
+		serigo(GORDON_REG_TCOM_CH2, 0x28);
+		serigo(GORDON_REG_THBP2, 0x4D);
+		serigo(GORDON_REG_TPHCTL2, 0x1A);
+
+		/* VGA settings */
+		serigo(GORDON_REG_IVBP1, 0x02);
+		serigo(GORDON_REG_IHBP1, 0x90);
+		serigo(GORDON_REG_IVNUM1, 0xA0);
+		serigo(GORDON_REG_IHNUM1, 0x78);
+
+		/* QVGA settings */
+		serigo(GORDON_REG_IVBP2, 0x02);
+		serigo(GORDON_REG_IHBP2, 0x48);
+		serigo(GORDON_REG_IVNUM2, 0x50);
+		serigo(GORDON_REG_IHNUM2, 0x3C);
+
+		/* Gordon Charge pump settings and ON */
+		serigo(GORDON_REG_POWCTL, 0x03);
+		mdelay(15);
+		serigo(GORDON_REG_POWCTL, 0x07);
+		mdelay(15);
+
+		serigo(GORDON_REG_POWCTL, 0x0F);
+		mdelay(15);
+
+		serigo(GORDON_REG_AVCTL, 0x03);
+		mdelay(15);
+
+		serigo(GORDON_REG_POWCTL, 0x1F);
+		mdelay(15);
+
+		serigo(GORDON_REG_POWCTL, 0x5F);
+		mdelay(15);
+
+		serigo(GORDON_REG_POWCTL, 0x7F);
+		mdelay(15);
+
+		serigo(GORDON_REG_LCDIFCTL1, 0x02);
+		mdelay(15);
+
+		serigo(GORDON_REG_IMGCTL1, 0x00);
+		mdelay(15);
+
+		serigo(GORDON_REG_LCDIFCTL3, 0x00);
+		mdelay(15);
+
+		serigo(GORDON_REG_VALTRAN, 0x01);
+		mdelay(15);
+
+		serigo(GORDON_REG_LCDIFCTL1, 0x03);
+		mdelay(1);
+		gordon_state.display_on = TRUE;
+	}
+}
+
+static int lcdc_gordon_panel_on(struct platform_device *pdev)
+{
+	if (!gordon_state.disp_initialized) {
+		/* Configure reset GPIO that drives DAC */
+		lcdc_gordon_pdata->panel_config_gpio(1);
+		spi_dac = *(lcdc_gordon_pdata->gpio_num + 4);
+		gpio_set_value(spi_dac, 0);
+		udelay(15);
+		gpio_set_value(spi_dac, 1);
+		spi_init();	/* LCD needs SPI */
+		gordon_disp_powerup();
+		gordon_disp_on();
+		gordon_state.disp_initialized = TRUE;
+	}
+	return 0;
+}
+
+static int lcdc_gordon_panel_off(struct platform_device *pdev)
+{
+	if (gordon_state.disp_powered_up && gordon_state.display_on) {
+		serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+		serigo(GORDON_REG_VALTRAN, 0x01);
+		serigo(GORDON_REG_LCDIFCTL1, 0x02);
+		serigo(GORDON_REG_LCDIFCTL3, 0x01);
+		mdelay(20);
+		serigo(GORDON_REG_VALTRAN, 0x01);
+		serigo(GORDON_REG_IMGCTL1, 0x01);
+		serigo(GORDON_REG_LCDIFCTL1, 0x00);
+		mdelay(20);
+
+		serigo(GORDON_REG_POWCTL, 0x1F);
+		mdelay(40);
+
+		serigo(GORDON_REG_POWCTL, 0x07);
+		mdelay(40);
+
+		serigo(GORDON_REG_POWCTL, 0x03);
+		mdelay(40);
+
+		serigo(GORDON_REG_POWCTL, 0x00);
+		mdelay(40);
+		lcdc_gordon_pdata->panel_config_gpio(0);
+		gordon_state.display_on = FALSE;
+		gordon_state.disp_initialized = FALSE;
+	}
+	return 0;
+}
+
+static void lcdc_gordon_set_backlight(struct msm_fb_data_type *mfd)
+{
+		int bl_level = mfd->bl_level;
+
+		if (bl_level <= 1) {
+			/* keep back light OFF */
+			serigo(GORDON_REG_LCDIFCTL2, 0x0B);
+			udelay(15);
+			serigo(GORDON_REG_VALTRAN, 0x01);
+		} else {
+			/* keep back light ON */
+			serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+			udelay(15);
+			serigo(GORDON_REG_VALTRAN, 0x01);
+		}
+}
+
+static int __init gordon_probe(struct platform_device *pdev)
+{
+	if (pdev->id == 0) {
+		lcdc_gordon_pdata = pdev->dev.platform_data;
+		return 0;
+	}
+	msm_fb_add_device(pdev);
+	return 0;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = gordon_probe,
+	.driver = {
+		.name   = "lcdc_gordon_vga",
+	},
+};
+
+static struct msm_fb_panel_data gordon_panel_data = {
+	.on = lcdc_gordon_panel_on,
+	.off = lcdc_gordon_panel_off,
+	.set_backlight = lcdc_gordon_set_backlight,
+};
+
+static struct platform_device this_device = {
+	.name   = "lcdc_gordon_vga",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &gordon_panel_data,
+	}
+};
+
+static int __init lcdc_gordon_panel_init(void)
+{
+	int ret;
+	struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+	if (msm_fb_detect_client("lcdc_gordon_vga"))
+		return 0;
+#endif
+	ret = platform_driver_register(&this_driver);
+	if (ret)
+		return ret;
+
+	pinfo = &gordon_panel_data.panel_info;
+	pinfo->xres = 480;
+	pinfo->yres = 640;
+	pinfo->type = LCDC_PANEL;
+	pinfo->pdest = DISPLAY_1;
+	pinfo->wait_cycle = 0;
+	pinfo->bpp = 24;
+	pinfo->fb_num = 2;
+	pinfo->clk_rate = 24500000;
+	pinfo->bl_max = 4;
+	pinfo->bl_min = 1;
+
+	pinfo->lcdc.h_back_porch = 84;
+	pinfo->lcdc.h_front_porch = 33;
+	pinfo->lcdc.h_pulse_width = 60;
+	pinfo->lcdc.v_back_porch = 0;
+	pinfo->lcdc.v_front_porch = 2;
+	pinfo->lcdc.v_pulse_width = 2;
+	pinfo->lcdc.border_clr = 0;     /* blk */
+	pinfo->lcdc.underflow_clr = 0xff;       /* blue */
+	pinfo->lcdc.hsync_skew = 0;
+
+	ret = platform_device_register(&this_device);
+	if (ret)
+		platform_driver_unregister(&this_driver);
+
+	return ret;
+}
+
+module_init(lcdc_gordon_panel_init);

+ 60 - 0
drivers/staging/msm/lcdc_grapefruit.c

@@ -0,0 +1,60 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+#include "mddihosti.h"
+#endif
+
+static int __init lcdc_grapefruit_init(void)
+{
+	int ret;
+	struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+	if (msm_fb_detect_client("lcdc_grapefruit_vga"))
+		return 0;
+#endif
+
+	pinfo.xres = 1024;
+	pinfo.yres = 600;
+	pinfo.type = LCDC_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 18;
+	pinfo.fb_num = 2;
+	pinfo.clk_rate = 40000000;
+
+	pinfo.lcdc.h_back_porch = 88;
+	pinfo.lcdc.h_front_porch = 40;
+	pinfo.lcdc.h_pulse_width = 128;
+	pinfo.lcdc.v_back_porch = 23;
+	pinfo.lcdc.v_front_porch = 1;
+	pinfo.lcdc.v_pulse_width = 4;
+	pinfo.lcdc.border_clr = 0;	/* blk */
+	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
+	pinfo.lcdc.hsync_skew = 0;
+
+	ret = lcdc_device_register(&pinfo);
+	if (ret)
+		printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(lcdc_grapefruit_init);

+ 88 - 0
drivers/staging/msm/lcdc_panel.c

@@ -0,0 +1,88 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+static int lcdc_panel_on(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int lcdc_panel_off(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int __init lcdc_panel_probe(struct platform_device *pdev)
+{
+	msm_fb_add_device(pdev);
+
+	return 0;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = lcdc_panel_probe,
+	.driver = {
+		.name   = "lcdc_panel",
+	},
+};
+
+static struct msm_fb_panel_data lcdc_panel_data = {
+	.on = lcdc_panel_on,
+	.off = lcdc_panel_off,
+};
+
+static int lcdc_dev_id;
+
+int lcdc_device_register(struct msm_panel_info *pinfo)
+{
+	struct platform_device *pdev = NULL;
+	int ret;
+
+	pdev = platform_device_alloc("lcdc_panel", ++lcdc_dev_id);
+	if (!pdev)
+		return -ENOMEM;
+
+	lcdc_panel_data.panel_info = *pinfo;
+	ret = platform_device_add_data(pdev, &lcdc_panel_data,
+		sizeof(lcdc_panel_data));
+	if (ret) {
+		printk(KERN_ERR
+		  "%s: platform_device_add_data failed!\n", __func__);
+		goto err_device_put;
+	}
+
+	ret = platform_device_add(pdev);
+	if (ret) {
+		printk(KERN_ERR
+		  "%s: platform_device_register failed!\n", __func__);
+		goto err_device_put;
+	}
+
+	return 0;
+
+err_device_put:
+	platform_device_put(pdev);
+	return ret;
+}
+
+static int __init lcdc_panel_init(void)
+{
+	return platform_driver_register(&this_driver);
+}
+
+module_init(lcdc_panel_init);

+ 64 - 0
drivers/staging/msm/lcdc_prism.c

@@ -0,0 +1,64 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+#include "mddihosti.h"
+#endif
+
+static int __init lcdc_prism_init(void)
+{
+	int ret;
+	struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+	ret = msm_fb_detect_client("lcdc_prism_wvga");
+	if (ret == -ENODEV)
+		return 0;
+
+	if (ret && (mddi_get_client_id() != 0))
+		return 0;
+#endif
+
+	pinfo.xres = 800;
+	pinfo.yres = 480;
+	pinfo.type = LCDC_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 24;
+	pinfo.fb_num = 2;
+	pinfo.clk_rate = 38460000;
+
+	pinfo.lcdc.h_back_porch = 21;
+	pinfo.lcdc.h_front_porch = 81;
+	pinfo.lcdc.h_pulse_width = 60;
+	pinfo.lcdc.v_back_porch = 18;
+	pinfo.lcdc.v_front_porch = 27;
+	pinfo.lcdc.v_pulse_width = 2;
+	pinfo.lcdc.border_clr = 0;	/* blk */
+	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
+	pinfo.lcdc.hsync_skew = 0;
+
+	ret = lcdc_device_register(&pinfo);
+	if (ret)
+		printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(lcdc_prism_init);

+ 290 - 0
drivers/staging/msm/lcdc_sharp_wvga_pt.c

@@ -0,0 +1,290 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/delay.h>
+#ifdef CONFIG_ARCH_MSM7X30
+#include <linux/mfd/pmic8058.h>
+#endif
+#include <mach/gpio.h>
+#include "msm_fb.h"
+
+static int lcdc_sharp_panel_off(struct platform_device *pdev);
+
+static int spi_cs;
+static int spi_sclk;
+static int spi_mosi;
+static int spi_miso;
+static unsigned char bit_shift[8] = { (1 << 7),	/* MSB */
+	(1 << 6),
+	(1 << 5),
+	(1 << 4),
+	(1 << 3),
+	(1 << 2),
+	(1 << 1),
+	(1 << 0)		               /* LSB */
+};
+
+struct sharp_state_type {
+	boolean disp_initialized;
+	boolean display_on;
+	boolean disp_powered_up;
+};
+
+struct sharp_spi_data {
+	u8 addr;
+	u8 data;
+};
+
+static struct sharp_spi_data init_sequence[] = {
+	{  15, 0x01 },
+	{   5, 0x01 },
+	{   7, 0x10 },
+	{   9, 0x1E },
+	{  10, 0x04 },
+	{  17, 0xFF },
+	{  21, 0x8A },
+	{  22, 0x00 },
+	{  23, 0x82 },
+	{  24, 0x24 },
+	{  25, 0x22 },
+	{  26, 0x6D },
+	{  27, 0xEB },
+	{  28, 0xB9 },
+	{  29, 0x3A },
+	{  49, 0x1A },
+	{  50, 0x16 },
+	{  51, 0x05 },
+	{  55, 0x7F },
+	{  56, 0x15 },
+	{  57, 0x7B },
+	{  60, 0x05 },
+	{  61, 0x0C },
+	{  62, 0x80 },
+	{  63, 0x00 },
+	{  92, 0x90 },
+	{  97, 0x01 },
+	{  98, 0xFF },
+	{ 113, 0x11 },
+	{ 114, 0x02 },
+	{ 115, 0x08 },
+	{ 123, 0xAB },
+	{ 124, 0x04 },
+	{   6, 0x02 },
+	{ 133, 0x00 },
+	{ 134, 0xFE },
+	{ 135, 0x22 },
+	{ 136, 0x0B },
+	{ 137, 0xFF },
+	{ 138, 0x0F },
+	{ 139, 0x00 },
+	{ 140, 0xFE },
+	{ 141, 0x22 },
+	{ 142, 0x0B },
+	{ 143, 0xFF },
+	{ 144, 0x0F },
+	{ 145, 0x00 },
+	{ 146, 0xFE },
+	{ 147, 0x22 },
+	{ 148, 0x0B },
+	{ 149, 0xFF },
+	{ 150, 0x0F },
+	{ 202, 0x30 },
+	{  30, 0x01 },
+	{   4, 0x01 },
+	{  31, 0x41 },
+};
+
+static struct sharp_state_type sharp_state = { 0 };
+static struct msm_panel_common_pdata *lcdc_sharp_pdata;
+
+static void sharp_spi_write_byte(u8 val)
+{
+	int i;
+
+	/* Clock should be Low before entering */
+	for (i = 0; i < 8; i++) {
+		/* #1: Drive the Data (High or Low) */
+		if (val & bit_shift[i])
+			gpio_set_value(spi_mosi, 1);
+		else
+			gpio_set_value(spi_mosi, 0);
+
+		/* #2: Drive the Clk High and then Low */
+		gpio_set_value(spi_sclk, 1);
+		gpio_set_value(spi_sclk, 0);
+	}
+}
+
+static void serigo(u8 reg, u8 data)
+{
+	/* Enable the Chip Select - low */
+	gpio_set_value(spi_cs, 0);
+	udelay(1);
+
+	/* Transmit register address first, then data */
+	sharp_spi_write_byte(reg);
+
+	/* Idle state of MOSI is Low */
+	gpio_set_value(spi_mosi, 0);
+	udelay(1);
+	sharp_spi_write_byte(data);
+
+	gpio_set_value(spi_mosi, 0);
+	gpio_set_value(spi_cs, 1);
+}
+
+static void sharp_spi_init(void)
+{
+	spi_sclk = *(lcdc_sharp_pdata->gpio_num);
+	spi_cs   = *(lcdc_sharp_pdata->gpio_num + 1);
+	spi_mosi = *(lcdc_sharp_pdata->gpio_num + 2);
+	spi_miso = *(lcdc_sharp_pdata->gpio_num + 3);
+
+	/* Set the output so that we don't disturb the slave device */
+	gpio_set_value(spi_sclk, 0);
+	gpio_set_value(spi_mosi, 0);
+
+	/* Set the Chip Select deasserted (active low) */
+	gpio_set_value(spi_cs, 1);
+}
+
+static void sharp_disp_powerup(void)
+{
+	if (!sharp_state.disp_powered_up && !sharp_state.display_on)
+		sharp_state.disp_powered_up = TRUE;
+}
+
+static void sharp_disp_on(void)
+{
+	int i;
+
+	if (sharp_state.disp_powered_up && !sharp_state.display_on) {
+		for (i = 0; i < ARRAY_SIZE(init_sequence); i++) {
+			serigo(init_sequence[i].addr,
+			       init_sequence[i].data);
+		}
+		mdelay(10);
+		serigo(31, 0xC1);
+		mdelay(10);
+		serigo(31, 0xD9);
+		serigo(31, 0xDF);
+
+		sharp_state.display_on = TRUE;
+	}
+}
+
+static int lcdc_sharp_panel_on(struct platform_device *pdev)
+{
+	if (!sharp_state.disp_initialized) {
+		lcdc_sharp_pdata->panel_config_gpio(1);
+		sharp_spi_init();
+		sharp_disp_powerup();
+		sharp_disp_on();
+		sharp_state.disp_initialized = TRUE;
+	}
+	return 0;
+}
+
+static int lcdc_sharp_panel_off(struct platform_device *pdev)
+{
+	if (sharp_state.disp_powered_up && sharp_state.display_on) {
+		serigo(4, 0x00);
+		mdelay(40);
+		serigo(31, 0xC1);
+		mdelay(40);
+		serigo(31, 0x00);
+		mdelay(100);
+		sharp_state.display_on = FALSE;
+		sharp_state.disp_initialized = FALSE;
+	}
+	return 0;
+}
+
+static int __init sharp_probe(struct platform_device *pdev)
+{
+	if (pdev->id == 0) {
+		lcdc_sharp_pdata = pdev->dev.platform_data;
+		return 0;
+	}
+	msm_fb_add_device(pdev);
+	return 0;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = sharp_probe,
+	.driver = {
+		.name   = "lcdc_sharp_wvga",
+	},
+};
+
+static struct msm_fb_panel_data sharp_panel_data = {
+	.on = lcdc_sharp_panel_on,
+	.off = lcdc_sharp_panel_off,
+};
+
+static struct platform_device this_device = {
+	.name   = "lcdc_sharp_wvga",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &sharp_panel_data,
+	}
+};
+
+static int __init lcdc_sharp_panel_init(void)
+{
+	int ret;
+	struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+	if (msm_fb_detect_client("lcdc_sharp_wvga_pt"))
+		return 0;
+#endif
+
+	ret = platform_driver_register(&this_driver);
+	if (ret)
+		return ret;
+
+	pinfo = &sharp_panel_data.panel_info;
+	pinfo->xres = 480;
+	pinfo->yres = 800;
+	pinfo->type = LCDC_PANEL;
+	pinfo->pdest = DISPLAY_1;
+	pinfo->wait_cycle = 0;
+	pinfo->bpp = 18;
+	pinfo->fb_num = 2;
+	pinfo->clk_rate = 24500000;
+	pinfo->bl_max = 4;
+	pinfo->bl_min = 1;
+
+	pinfo->lcdc.h_back_porch = 20;
+	pinfo->lcdc.h_front_porch = 10;
+	pinfo->lcdc.h_pulse_width = 10;
+	pinfo->lcdc.v_back_porch = 2;
+	pinfo->lcdc.v_front_porch = 2;
+	pinfo->lcdc.v_pulse_width = 2;
+	pinfo->lcdc.border_clr = 0;
+	pinfo->lcdc.underflow_clr = 0xff;
+	pinfo->lcdc.hsync_skew = 0;
+
+	ret = platform_device_register(&this_device);
+	if (ret)
+		platform_driver_unregister(&this_driver);
+
+	return ret;
+}
+
+module_init(lcdc_sharp_panel_init);

+ 237 - 0
drivers/staging/msm/lcdc_st15.c

@@ -0,0 +1,237 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include "msm_fb.h"
+
+#define DEVICE_NAME "sii9022"
+#define SII9022_DEVICE_ID   0xB0
+
+struct sii9022_i2c_addr_data{
+	u8 addr;
+	u8 data;
+};
+
+/* video mode data */
+static u8 video_mode_data[] = {
+	0x00,
+	0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
+};
+
+static u8 avi_io_format[] = {
+	0x09,
+	0x00, 0x00,
+};
+
+/* power state */
+static struct sii9022_i2c_addr_data regset0[] = {
+	{ 0x60, 0x04 },
+	{ 0x63, 0x00 },
+	{ 0x1E, 0x00 },
+};
+
+static u8 video_infoframe[] = {
+	0x0C,
+	0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00,
+	0xE9, 0x02, 0x04, 0x01, 0x04, 0x06,
+};
+
+/* configure audio */
+static struct sii9022_i2c_addr_data regset1[] = {
+	{ 0x26, 0x90 },
+	{ 0x20, 0x90 },
+	{ 0x1F, 0x80 },
+	{ 0x26, 0x80 },
+	{ 0x24, 0x02 },
+	{ 0x25, 0x0B },
+	{ 0xBC, 0x02 },
+	{ 0xBD, 0x24 },
+	{ 0xBE, 0x02 },
+};
+
+/* enable audio */
+static u8 misc_infoframe[] = {
+	0xBF,
+	0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+/* set HDMI, active */
+static struct sii9022_i2c_addr_data regset2[] = {
+	{ 0x1A, 0x01 },
+	{ 0x3D, 0x00 },
+};
+
+static int send_i2c_data(struct i2c_client *client,
+			 struct sii9022_i2c_addr_data *regset,
+			 int size)
+{
+	int i;
+	int rc = 0;
+
+	for (i = 0; i < size; i++) {
+		rc = i2c_smbus_write_byte_data(
+			client,
+			regset[i].addr, regset[i].data);
+		if (rc)
+			break;
+	}
+	return rc;
+}
+
+static int hdmi_sii_enable(struct i2c_client *client)
+{
+	int rc;
+	int retries = 10;
+	int count;
+
+	rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00);
+	if (rc)
+		goto enable_exit;
+
+	do {
+		msleep(1);
+		rc = i2c_smbus_read_byte_data(client, 0x1B);
+	} while ((rc != SII9022_DEVICE_ID) && retries--);
+
+	if (rc != SII9022_DEVICE_ID)
+		return -ENODEV;
+
+	rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11);
+	if (rc)
+		goto enable_exit;
+
+	count = ARRAY_SIZE(video_mode_data);
+	rc = i2c_master_send(client, video_mode_data, count);
+	if (rc != count) {
+		rc = -EIO;
+		goto enable_exit;
+	}
+
+	rc = i2c_smbus_write_byte_data(client, 0x08, 0x20);
+	if (rc)
+		goto enable_exit;
+	count = ARRAY_SIZE(avi_io_format);
+	rc = i2c_master_send(client, avi_io_format, count);
+	if (rc != count) {
+		rc = -EIO;
+		goto enable_exit;
+	}
+
+	rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0));
+	if (rc)
+		goto enable_exit;
+
+	count = ARRAY_SIZE(video_infoframe);
+	rc = i2c_master_send(client, video_infoframe, count);
+	if (rc != count) {
+		rc = -EIO;
+		goto enable_exit;
+	}
+
+	rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1));
+	if (rc)
+		goto enable_exit;
+
+	count = ARRAY_SIZE(misc_infoframe);
+	rc = i2c_master_send(client, misc_infoframe, count);
+	if (rc != count) {
+		rc = -EIO;
+		goto enable_exit;
+	}
+
+	rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2));
+	if (rc)
+		goto enable_exit;
+
+	return 0;
+enable_exit:
+	printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
+	return rc;
+}
+
+static const struct i2c_device_id hmdi_sii_id[] = {
+	{ DEVICE_NAME, 0 },
+	{ }
+};
+
+static int hdmi_sii_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int rc;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
+		return -ENODEV;
+	rc = hdmi_sii_enable(client);
+	return rc;
+}
+
+
+static struct i2c_driver hdmi_sii_i2c_driver = {
+	.driver = {
+		.name = DEVICE_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = hdmi_sii_probe,
+	.remove =  __exit_p(hdmi_sii_remove),
+	.id_table = hmdi_sii_id,
+};
+
+static int __init lcdc_st15_init(void)
+{
+	int ret;
+	struct msm_panel_info pinfo;
+
+	if (msm_fb_detect_client("lcdc_st15"))
+		return 0;
+
+	pinfo.xres = 1366;
+	pinfo.yres = 768;
+	pinfo.type = LCDC_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 24;
+	pinfo.fb_num = 2;
+	pinfo.clk_rate = 74250000;
+
+	pinfo.lcdc.h_back_porch = 120;
+	pinfo.lcdc.h_front_porch = 20;
+	pinfo.lcdc.h_pulse_width = 40;
+	pinfo.lcdc.v_back_porch = 25;
+	pinfo.lcdc.v_front_porch = 1;
+	pinfo.lcdc.v_pulse_width = 7;
+	pinfo.lcdc.border_clr = 0;      /* blk */
+	pinfo.lcdc.underflow_clr = 0xff;        /* blue */
+	pinfo.lcdc.hsync_skew = 0;
+
+	ret = lcdc_device_register(&pinfo);
+	if (ret) {
+		printk(KERN_ERR "%s: failed to register device!\n", __func__);
+		goto init_exit;
+	}
+
+	ret = i2c_add_driver(&hdmi_sii_i2c_driver);
+	if (ret)
+		printk(KERN_ERR "%s: failed to add i2c driver\n", __func__);
+
+init_exit:
+	return ret;
+}
+
+module_init(lcdc_st15_init);

+ 54 - 0
drivers/staging/msm/lcdc_st1_wxga.c

@@ -0,0 +1,54 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+static int __init lcdc_st1_wxga_init(void)
+{
+	int ret;
+	struct msm_panel_info pinfo;
+
+	if (msm_fb_detect_client("lcdc_st1_wxga"))
+		return 0;
+
+	pinfo.xres = 1280;
+	pinfo.yres = 720;
+	pinfo.type = LCDC_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 18;
+	pinfo.fb_num = 2;
+	pinfo.clk_rate = 74250000;
+
+	pinfo.lcdc.h_back_porch = 124;
+	pinfo.lcdc.h_front_porch = 110;
+	pinfo.lcdc.h_pulse_width = 136;
+	pinfo.lcdc.v_back_porch = 19;
+	pinfo.lcdc.v_front_porch = 5;
+	pinfo.lcdc.v_pulse_width = 6;
+	pinfo.lcdc.border_clr = 0;	/* blk */
+	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
+	pinfo.lcdc.hsync_skew = 0;
+
+	ret = lcdc_device_register(&pinfo);
+	if (ret)
+		printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(lcdc_st1_wxga_init);

+ 374 - 0
drivers/staging/msm/lcdc_toshiba_wvga_pt.c

@@ -0,0 +1,374 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <mach/gpio.h>
+#include <mach/pmic.h>
+#include "msm_fb.h"
+
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+#include "mddihosti.h"
+#endif
+
+static int spi_cs;
+static int spi_sclk;
+static int spi_mosi;
+static int spi_miso;
+
+struct toshiba_state_type{
+	boolean disp_initialized;
+	boolean display_on;
+	boolean disp_powered_up;
+};
+
+static struct toshiba_state_type toshiba_state = { 0 };
+static struct msm_panel_common_pdata *lcdc_toshiba_pdata;
+
+static void toshiba_spi_write_byte(char dc, uint8 data)
+{
+	uint32 bit;
+	int bnum;
+
+	gpio_set_value(spi_sclk, 0); /* clk low */
+	/* dc: 0 for command, 1 for parameter */
+	gpio_set_value(spi_mosi, dc);
+	udelay(1);	/* at least 20 ns */
+	gpio_set_value(spi_sclk, 1); /* clk high */
+	udelay(1);	/* at least 20 ns */
+	bnum = 8;	/* 8 data bits */
+	bit = 0x80;
+	while (bnum) {
+		gpio_set_value(spi_sclk, 0); /* clk low */
+		if (data & bit)
+			gpio_set_value(spi_mosi, 1);
+		else
+			gpio_set_value(spi_mosi, 0);
+		udelay(1);
+		gpio_set_value(spi_sclk, 1); /* clk high */
+		udelay(1);
+		bit >>= 1;
+		bnum--;
+	}
+}
+
+static void toshiba_spi_write(char cmd, uint32 data, int num)
+{
+	char *bp;
+
+	gpio_set_value(spi_cs, 1);	/* cs high */
+
+	/* command byte first */
+	toshiba_spi_write_byte(0, cmd);
+
+	/* followed by parameter bytes */
+	if (num) {
+		bp = (char *)&data;;
+		bp += (num - 1);
+		while (num) {
+			toshiba_spi_write_byte(1, *bp);
+			num--;
+			bp--;
+		}
+	}
+
+	gpio_set_value(spi_cs, 0);	/* cs low */
+	udelay(1);
+}
+
+void toshiba_spi_read_bytes(char cmd, uint32 *data, int num)
+{
+	uint32 dbit, bits;
+	int bnum;
+
+	gpio_set_value(spi_cs, 1);	/* cs high */
+
+	/* command byte first */
+	toshiba_spi_write_byte(0, cmd);
+
+	if (num > 1) {
+		/* extra dc bit */
+		gpio_set_value(spi_sclk, 0); /* clk low */
+		udelay(1);
+		dbit = gpio_get_value(spi_miso);/* dc bit */
+		udelay(1);
+		gpio_set_value(spi_sclk, 1); /* clk high */
+	}
+
+	/* followed by data bytes */
+	bnum = num * 8;	/* number of bits */
+	bits = 0;
+	while (bnum) {
+		bits <<= 1;
+		gpio_set_value(spi_sclk, 0); /* clk low */
+		udelay(1);
+		dbit = gpio_get_value(spi_miso);
+		udelay(1);
+		gpio_set_value(spi_sclk, 1); /* clk high */
+		bits |= dbit;
+		bnum--;
+	}
+
+	*data = bits;
+
+	udelay(1);
+	gpio_set_value(spi_cs, 0);	/* cs low */
+	udelay(1);
+}
+
+static void spi_pin_assign(void)
+{
+	/* Setting the Default GPIO's */
+	spi_sclk = *(lcdc_toshiba_pdata->gpio_num);
+	spi_cs   = *(lcdc_toshiba_pdata->gpio_num + 1);
+	spi_mosi  = *(lcdc_toshiba_pdata->gpio_num + 2);
+	spi_miso  = *(lcdc_toshiba_pdata->gpio_num + 3);
+}
+
+static void toshiba_disp_powerup(void)
+{
+	if (!toshiba_state.disp_powered_up && !toshiba_state.display_on) {
+		/* Reset the hardware first */
+		/* Include DAC power up implementation here */
+	      toshiba_state.disp_powered_up = TRUE;
+	}
+}
+
+static void toshiba_disp_on(void)
+{
+	uint32	data;
+
+	gpio_set_value(spi_cs, 0);	/* low */
+	gpio_set_value(spi_sclk, 1);	/* high */
+	gpio_set_value(spi_mosi, 0);
+	gpio_set_value(spi_miso, 0);
+
+	if (toshiba_state.disp_powered_up && !toshiba_state.display_on) {
+		toshiba_spi_write(0, 0, 0);
+		mdelay(7);
+		toshiba_spi_write(0, 0, 0);
+		mdelay(7);
+		toshiba_spi_write(0, 0, 0);
+		mdelay(7);
+		toshiba_spi_write(0xba, 0x11, 1);
+		toshiba_spi_write(0x36, 0x00, 1);
+		mdelay(1);
+		toshiba_spi_write(0x3a, 0x60, 1);
+		toshiba_spi_write(0xb1, 0x5d, 1);
+		mdelay(1);
+		toshiba_spi_write(0xb2, 0x33, 1);
+		toshiba_spi_write(0xb3, 0x22, 1);
+		mdelay(1);
+		toshiba_spi_write(0xb4, 0x02, 1);
+		toshiba_spi_write(0xb5, 0x1e, 1); /* vcs -- adjust brightness */
+		mdelay(1);
+		toshiba_spi_write(0xb6, 0x27, 1);
+		toshiba_spi_write(0xb7, 0x03, 1);
+		mdelay(1);
+		toshiba_spi_write(0xb9, 0x24, 1);
+		toshiba_spi_write(0xbd, 0xa1, 1);
+		mdelay(1);
+		toshiba_spi_write(0xbb, 0x00, 1);
+		toshiba_spi_write(0xbf, 0x01, 1);
+		mdelay(1);
+		toshiba_spi_write(0xbe, 0x00, 1);
+		toshiba_spi_write(0xc0, 0x11, 1);
+		mdelay(1);
+		toshiba_spi_write(0xc1, 0x11, 1);
+		toshiba_spi_write(0xc2, 0x11, 1);
+		mdelay(1);
+		toshiba_spi_write(0xc3, 0x3232, 2);
+		mdelay(1);
+		toshiba_spi_write(0xc4, 0x3232, 2);
+		mdelay(1);
+		toshiba_spi_write(0xc5, 0x3232, 2);
+		mdelay(1);
+		toshiba_spi_write(0xc6, 0x3232, 2);
+		mdelay(1);
+		toshiba_spi_write(0xc7, 0x6445, 2);
+		mdelay(1);
+		toshiba_spi_write(0xc8, 0x44, 1);
+		toshiba_spi_write(0xc9, 0x52, 1);
+		mdelay(1);
+		toshiba_spi_write(0xca, 0x00, 1);
+		mdelay(1);
+		toshiba_spi_write(0xec, 0x02a4, 2);	/* 0x02a4 */
+		mdelay(1);
+		toshiba_spi_write(0xcf, 0x01, 1);
+		mdelay(1);
+		toshiba_spi_write(0xd0, 0xc003, 2);	/* c003 */
+		mdelay(1);
+		toshiba_spi_write(0xd1, 0x01, 1);
+		mdelay(1);
+		toshiba_spi_write(0xd2, 0x0028, 2);
+		mdelay(1);
+		toshiba_spi_write(0xd3, 0x0028, 2);
+		mdelay(1);
+		toshiba_spi_write(0xd4, 0x26a4, 2);
+		mdelay(1);
+		toshiba_spi_write(0xd5, 0x20, 1);
+		mdelay(1);
+		toshiba_spi_write(0xef, 0x3200, 2);
+		mdelay(32);
+		toshiba_spi_write(0xbc, 0x80, 1);	/* wvga pass through */
+		toshiba_spi_write(0x3b, 0x00, 1);
+		mdelay(1);
+		toshiba_spi_write(0xb0, 0x16, 1);
+		mdelay(1);
+		toshiba_spi_write(0xb8, 0xfff5, 2);
+		mdelay(1);
+		toshiba_spi_write(0x11, 0, 0);
+		mdelay(5);
+		toshiba_spi_write(0x29, 0, 0);
+		mdelay(5);
+		toshiba_state.display_on = TRUE;
+	}
+
+	data = 0;
+	toshiba_spi_read_bytes(0x04, &data, 3);
+	printk(KERN_INFO "toshiba_disp_on: id=%x\n", data);
+
+}
+
+static int lcdc_toshiba_panel_on(struct platform_device *pdev)
+{
+	if (!toshiba_state.disp_initialized) {
+		/* Configure reset GPIO that drives DAC */
+		if (lcdc_toshiba_pdata->panel_config_gpio)
+			lcdc_toshiba_pdata->panel_config_gpio(1);
+		toshiba_disp_powerup();
+		toshiba_disp_on();
+		toshiba_state.disp_initialized = TRUE;
+	}
+	return 0;
+}
+
+static int lcdc_toshiba_panel_off(struct platform_device *pdev)
+{
+	if (toshiba_state.disp_powered_up && toshiba_state.display_on) {
+		/* Main panel power off (Deep standby in) */
+
+		toshiba_spi_write(0x28, 0, 0);	/* display off */
+		mdelay(1);
+		toshiba_spi_write(0xb8, 0x8002, 2);	/* output control */
+		mdelay(1);
+		toshiba_spi_write(0x10, 0x00, 1);	/* sleep mode in */
+		mdelay(85);		/* wait 85 msec */
+		toshiba_spi_write(0xb0, 0x00, 1);	/* deep standby in */
+		mdelay(1);
+		if (lcdc_toshiba_pdata->panel_config_gpio)
+			lcdc_toshiba_pdata->panel_config_gpio(0);
+		toshiba_state.display_on = FALSE;
+		toshiba_state.disp_initialized = FALSE;
+	}
+	return 0;
+}
+
+static void lcdc_toshiba_set_backlight(struct msm_fb_data_type *mfd)
+{
+	int bl_level;
+	int ret = -EPERM;
+
+	bl_level = mfd->bl_level;
+	ret = pmic_set_led_intensity(LED_LCD, bl_level);
+
+	if (ret)
+		printk(KERN_WARNING "%s: can't set lcd backlight!\n",
+				__func__);
+}
+
+static int __init toshiba_probe(struct platform_device *pdev)
+{
+	if (pdev->id == 0) {
+		lcdc_toshiba_pdata = pdev->dev.platform_data;
+		spi_pin_assign();
+		return 0;
+	}
+	msm_fb_add_device(pdev);
+	return 0;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = toshiba_probe,
+	.driver = {
+		.name   = "lcdc_toshiba_wvga",
+	},
+};
+
+static struct msm_fb_panel_data toshiba_panel_data = {
+	.on = lcdc_toshiba_panel_on,
+	.off = lcdc_toshiba_panel_off,
+	.set_backlight = lcdc_toshiba_set_backlight,
+};
+
+static struct platform_device this_device = {
+	.name   = "lcdc_toshiba_wvga",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &toshiba_panel_data,
+	}
+};
+
+static int __init lcdc_toshiba_panel_init(void)
+{
+	int ret;
+	struct msm_panel_info *pinfo;
+#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
+	if (mddi_get_client_id() != 0)
+		return 0;
+
+	ret = msm_fb_detect_client("lcdc_toshiba_wvga_pt");
+	if (ret)
+		return 0;
+
+#endif
+
+	ret = platform_driver_register(&this_driver);
+	if (ret)
+		return ret;
+
+	pinfo = &toshiba_panel_data.panel_info;
+	pinfo->xres = 480;
+	pinfo->yres = 800;
+	pinfo->type = LCDC_PANEL;
+	pinfo->pdest = DISPLAY_1;
+	pinfo->wait_cycle = 0;
+	pinfo->bpp = 18;
+	pinfo->fb_num = 2;
+	/* 30Mhz mdp_lcdc_pclk and mdp_lcdc_pad_pcl */
+	pinfo->clk_rate = 27648000;
+	pinfo->bl_max = 15;
+	pinfo->bl_min = 1;
+
+	pinfo->lcdc.h_back_porch = 184;	/* hsw = 8 + hbp=184 */
+	pinfo->lcdc.h_front_porch = 4;
+	pinfo->lcdc.h_pulse_width = 8;
+	pinfo->lcdc.v_back_porch = 2;	/* vsw=1 + vbp = 2 */
+	pinfo->lcdc.v_front_porch = 3;
+	pinfo->lcdc.v_pulse_width = 1;
+	pinfo->lcdc.border_clr = 0;     /* blk */
+	pinfo->lcdc.underflow_clr = 0xff;       /* blue */
+	pinfo->lcdc.hsync_skew = 0;
+
+	ret = platform_device_register(&this_device);
+	if (ret)
+		platform_driver_unregister(&this_driver);
+
+	return ret;
+}
+
+device_initcall(lcdc_toshiba_panel_init);

+ 56 - 0
drivers/staging/msm/lcdc_wxga.c

@@ -0,0 +1,56 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+
+static int __init lcdc_wxga_init(void)
+{
+	int ret;
+	struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+	if (msm_fb_detect_client("lcdc_wxga"))
+		return 0;
+#endif
+
+	pinfo.xres = 1280;
+	pinfo.yres = 720;
+	pinfo.type = LCDC_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 24;
+	pinfo.fb_num = 2;
+	pinfo.clk_rate = 74250000;
+
+	pinfo.lcdc.h_back_porch = 124;
+	pinfo.lcdc.h_front_porch = 110;
+	pinfo.lcdc.h_pulse_width = 136;
+	pinfo.lcdc.v_back_porch = 19;
+	pinfo.lcdc.v_front_porch = 5;
+	pinfo.lcdc.v_pulse_width = 6;
+	pinfo.lcdc.border_clr = 0;	/* blk */
+	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
+	pinfo.lcdc.hsync_skew = 0;
+
+	ret = lcdc_device_register(&pinfo);
+	if (ret)
+		printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(lcdc_wxga_init);

+ 98 - 0
drivers/staging/msm/logo.c

@@ -0,0 +1,98 @@
+/* drivers/video/msm/logo.c
+ *
+ * Show Logo in RLE 565 format
+ *
+ * Copyright (C) 2008 Google Incorporated
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fb.h>
+#include <linux/vt_kern.h>
+#include <linux/unistd.h>
+#include <linux/syscalls.h>
+
+#include <linux/irq.h>
+#include <asm/system.h>
+
+#define fb_width(fb)	((fb)->var.xres)
+#define fb_height(fb)	((fb)->var.yres)
+#define fb_size(fb)	((fb)->var.xres * (fb)->var.yres * 2)
+
+static void memset16(void *_ptr, unsigned short val, unsigned count)
+{
+	unsigned short *ptr = _ptr;
+	count >>= 1;
+	while (count--)
+		*ptr++ = val;
+}
+
+/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */
+int load_565rle_image(char *filename)
+{
+	struct fb_info *info;
+	int fd, err = 0;
+	unsigned count, max;
+	unsigned short *data, *bits, *ptr;
+
+	info = registered_fb[0];
+	if (!info) {
+		printk(KERN_WARNING "%s: Can not access framebuffer\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	fd = sys_open(filename, O_RDONLY, 0);
+	if (fd < 0) {
+		printk(KERN_WARNING "%s: Can not open %s\n",
+			__func__, filename);
+		return -ENOENT;
+	}
+	count = (unsigned)sys_lseek(fd, (off_t)0, 2);
+	if (count == 0) {
+		sys_close(fd);
+		err = -EIO;
+		goto err_logo_close_file;
+	}
+	sys_lseek(fd, (off_t)0, 0);
+	data = kmalloc(count, GFP_KERNEL);
+	if (!data) {
+		printk(KERN_WARNING "%s: Can not alloc data\n", __func__);
+		err = -ENOMEM;
+		goto err_logo_close_file;
+	}
+	if ((unsigned)sys_read(fd, (char *)data, count) != count) {
+		err = -EIO;
+		goto err_logo_free_data;
+	}
+
+	max = fb_width(info) * fb_height(info);
+	ptr = data;
+	bits = (unsigned short *)(info->screen_base);
+	while (count > 3) {
+		unsigned n = ptr[0];
+		if (n > max)
+			break;
+		memset16(bits, ptr[1], n << 1);
+		bits += n;
+		max -= n;
+		ptr += 2;
+		count -= 4;
+	}
+
+err_logo_free_data:
+	kfree(data);
+err_logo_close_file:
+	sys_close(fd);
+	return err;
+}
+EXPORT_SYMBOL(load_565rle_image);

+ 375 - 0
drivers/staging/msm/mddi.c

@@ -0,0 +1,375 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include "msm_fb.h"
+#include "mddihosti.h"
+#include "mddihost.h"
+#include <mach/gpio.h>
+#include <mach/clk.h>
+
+static int mddi_probe(struct platform_device *pdev);
+static int mddi_remove(struct platform_device *pdev);
+
+static int mddi_off(struct platform_device *pdev);
+static int mddi_on(struct platform_device *pdev);
+
+static int mddi_suspend(struct platform_device *pdev, pm_message_t state);
+static int mddi_resume(struct platform_device *pdev);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_early_suspend(struct early_suspend *h);
+static void mddi_early_resume(struct early_suspend *h);
+#endif
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+static struct clk *mddi_clk;
+static struct clk *mddi_pclk;
+static struct mddi_platform_data *mddi_pdata;
+
+static struct platform_driver mddi_driver = {
+	.probe = mddi_probe,
+	.remove = mddi_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+#ifdef CONFIG_PM
+	.suspend = mddi_suspend,
+	.resume = mddi_resume,
+#endif
+#endif
+	.suspend_late = NULL,
+	.resume_early = NULL,
+	.shutdown = NULL,
+	.driver = {
+		   .name = "mddi",
+		   },
+};
+
+extern int int_mddi_pri_flag;
+
+static int mddi_off(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	ret = panel_next_off(pdev);
+
+	if (mddi_pdata && mddi_pdata->mddi_power_save)
+		mddi_pdata->mddi_power_save(0);
+
+	return ret;
+}
+
+static int mddi_on(struct platform_device *pdev)
+{
+	int ret = 0;
+	u32 clk_rate;
+	struct msm_fb_data_type *mfd;
+
+	mfd = platform_get_drvdata(pdev);
+
+	if (mddi_pdata && mddi_pdata->mddi_power_save)
+		mddi_pdata->mddi_power_save(1);
+
+	clk_rate = mfd->fbi->var.pixclock;
+	clk_rate = min(clk_rate, mfd->panel_info.clk_max);
+
+	if (mddi_pdata &&
+	    mddi_pdata->mddi_sel_clk &&
+	    mddi_pdata->mddi_sel_clk(&clk_rate))
+			printk(KERN_ERR
+			  "%s: can't select mddi io clk targate rate = %d\n",
+			  __func__, clk_rate);
+
+	if (clk_set_min_rate(mddi_clk, clk_rate) < 0)
+		printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+			__func__);
+
+	ret = panel_next_on(pdev);
+
+	return ret;
+}
+
+static int mddi_resource_initialized;
+
+static int mddi_probe(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+	struct platform_device *mdp_dev = NULL;
+	struct msm_fb_panel_data *pdata = NULL;
+	int rc;
+	resource_size_t size ;
+	u32 clk_rate;
+
+	if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
+		mddi_pdata = pdev->dev.platform_data;
+
+		size =  resource_size(&pdev->resource[0]);
+		msm_pmdh_base =  ioremap(pdev->resource[0].start, size);
+
+		MSM_FB_INFO("primary mddi base phy_addr = 0x%x virt = 0x%x\n",
+				pdev->resource[0].start, (int) msm_pmdh_base);
+
+		if (unlikely(!msm_pmdh_base))
+			return -ENOMEM;
+
+		if (mddi_pdata && mddi_pdata->mddi_power_save)
+			mddi_pdata->mddi_power_save(1);
+
+		mddi_resource_initialized = 1;
+		return 0;
+	}
+
+	if (!mddi_resource_initialized)
+		return -EPERM;
+
+	mfd = platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+		return -ENOMEM;
+
+	mdp_dev = platform_device_alloc("mdp", pdev->id);
+	if (!mdp_dev)
+		return -ENOMEM;
+
+	/*
+	 * link to the latest pdev
+	 */
+	mfd->pdev = mdp_dev;
+	mfd->dest = DISPLAY_LCD;
+
+	/*
+	 * alloc panel device data
+	 */
+	if (platform_device_add_data
+	    (mdp_dev, pdev->dev.platform_data,
+	     sizeof(struct msm_fb_panel_data))) {
+		printk(KERN_ERR "mddi_probe: platform_device_add_data failed!\n");
+		platform_device_put(mdp_dev);
+		return -ENOMEM;
+	}
+	/*
+	 * data chain
+	 */
+	pdata = mdp_dev->dev.platform_data;
+	pdata->on = mddi_on;
+	pdata->off = mddi_off;
+	pdata->next = pdev;
+
+	/*
+	 * get/set panel specific fb info
+	 */
+	mfd->panel_info = pdata->panel_info;
+	mfd->fb_imgType = MDP_RGB_565;
+
+	clk_rate = mfd->panel_info.clk_max;
+	if (mddi_pdata &&
+	    mddi_pdata->mddi_sel_clk &&
+	    mddi_pdata->mddi_sel_clk(&clk_rate))
+			printk(KERN_ERR
+			  "%s: can't select mddi io clk targate rate = %d\n",
+			  __func__, clk_rate);
+
+	if (clk_set_max_rate(mddi_clk, clk_rate) < 0)
+		printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
+	mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
+
+	/*
+	 * set driver data
+	 */
+	platform_set_drvdata(mdp_dev, mfd);
+
+	/*
+	 * register in mdp driver
+	 */
+	rc = platform_device_add(mdp_dev);
+	if (rc)
+		goto mddi_probe_err;
+
+	pdev_list[pdev_list_cnt++] = pdev;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	mfd->mddi_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
+	mfd->mddi_early_suspend.suspend = mddi_early_suspend;
+	mfd->mddi_early_suspend.resume = mddi_early_resume;
+	register_early_suspend(&mfd->mddi_early_suspend);
+#endif
+
+	return 0;
+
+mddi_probe_err:
+	platform_device_put(mdp_dev);
+	return rc;
+}
+
+static int mddi_pad_ctrl;
+static int mddi_power_locked;
+static int mddi_is_in_suspend;
+
+void mddi_disable(int lock)
+{
+	mddi_host_type host_idx = MDDI_HOST_PRIM;
+
+	if (mddi_power_locked)
+		return;
+
+	if (lock)
+		mddi_power_locked = 1;
+
+	if (mddi_host_timer.function)
+		del_timer_sync(&mddi_host_timer);
+
+	mddi_pad_ctrl = mddi_host_reg_in(PAD_CTL);
+	mddi_host_reg_out(PAD_CTL, 0x0);
+
+	if (clk_set_min_rate(mddi_clk, 0) < 0)
+		printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
+
+	clk_disable(mddi_clk);
+	if (mddi_pclk)
+		clk_disable(mddi_pclk);
+	disable_irq(INT_MDDI_PRI);
+
+	if (mddi_pdata && mddi_pdata->mddi_power_save)
+		mddi_pdata->mddi_power_save(0);
+}
+
+static int mddi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	if (mddi_is_in_suspend)
+		return 0;
+
+	mddi_is_in_suspend = 1;
+	mddi_disable(0);
+	return 0;
+}
+
+static int mddi_resume(struct platform_device *pdev)
+{
+	mddi_host_type host_idx = MDDI_HOST_PRIM;
+
+	if (!mddi_is_in_suspend)
+		return 0;
+
+	mddi_is_in_suspend = 0;
+
+	if (mddi_power_locked)
+		return 0;
+
+	enable_irq(INT_MDDI_PRI);
+	clk_enable(mddi_clk);
+	if (mddi_pclk)
+		clk_enable(mddi_pclk);
+	mddi_host_reg_out(PAD_CTL, mddi_pad_ctrl);
+
+	if (mddi_host_timer.function)
+		mddi_host_timer_service(0);
+
+	return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_early_suspend(struct early_suspend *h)
+{
+	pm_message_t state;
+	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+							mddi_early_suspend);
+
+	state.event = PM_EVENT_SUSPEND;
+	mddi_suspend(mfd->pdev, state);
+}
+
+static void mddi_early_resume(struct early_suspend *h)
+{
+	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+							mddi_early_suspend);
+	mddi_resume(mfd->pdev);
+}
+#endif
+
+static int mddi_remove(struct platform_device *pdev)
+{
+	if (mddi_host_timer.function)
+		del_timer_sync(&mddi_host_timer);
+
+	iounmap(msm_pmdh_base);
+
+	return 0;
+}
+
+static int mddi_register_driver(void)
+{
+	return platform_driver_register(&mddi_driver);
+}
+
+static int __init mddi_driver_init(void)
+{
+	int ret;
+
+	mddi_clk = clk_get(NULL, "mddi_clk");
+	if (IS_ERR(mddi_clk)) {
+		printk(KERN_ERR "can't find mddi_clk \n");
+		return PTR_ERR(mddi_clk);
+	}
+	clk_enable(mddi_clk);
+
+	mddi_pclk = clk_get(NULL, "mddi_pclk");
+	if (IS_ERR(mddi_pclk))
+		mddi_pclk = NULL;
+	else
+		clk_enable(mddi_pclk);
+
+	ret = mddi_register_driver();
+	if (ret) {
+		clk_disable(mddi_clk);
+		clk_put(mddi_clk);
+		if (mddi_pclk) {
+			clk_disable(mddi_pclk);
+			clk_put(mddi_pclk);
+		}
+		printk(KERN_ERR "mddi_register_driver() failed!\n");
+		return ret;
+	}
+
+	mddi_init();
+
+	return ret;
+}
+
+module_init(mddi_driver_init);

+ 320 - 0
drivers/staging/msm/mddi_ext.c

@@ -0,0 +1,320 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <mach/clk.h>
+#include <linux/platform_device.h>
+
+#include "msm_fb.h"
+#include "mddihosti.h"
+
+static int mddi_ext_probe(struct platform_device *pdev);
+static int mddi_ext_remove(struct platform_device *pdev);
+
+static int mddi_ext_off(struct platform_device *pdev);
+static int mddi_ext_on(struct platform_device *pdev);
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state);
+static int mddi_ext_resume(struct platform_device *pdev);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_ext_early_suspend(struct early_suspend *h);
+static void mddi_ext_early_resume(struct early_suspend *h);
+#endif
+
+static struct platform_driver mddi_ext_driver = {
+	.probe = mddi_ext_probe,
+	.remove = mddi_ext_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+#ifdef CONFIG_PM
+	.suspend = mddi_ext_suspend,
+	.resume = mddi_ext_resume,
+#endif
+#endif
+	.resume_early = NULL,
+	.resume = NULL,
+	.shutdown = NULL,
+	.driver = {
+		   .name = "mddi_ext",
+		   },
+};
+
+static struct clk *mddi_ext_clk;
+static struct mddi_platform_data *mddi_ext_pdata;
+
+extern int int_mddi_ext_flag;
+
+static int mddi_ext_off(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	ret = panel_next_off(pdev);
+	mddi_host_stop_ext_display();
+
+	return ret;
+}
+
+static int mddi_ext_on(struct platform_device *pdev)
+{
+	int ret = 0;
+	u32 clk_rate;
+	struct msm_fb_data_type *mfd;
+
+	mfd = platform_get_drvdata(pdev);
+
+	clk_rate = mfd->fbi->var.pixclock;
+	clk_rate = min(clk_rate, mfd->panel_info.clk_max);
+
+	if (mddi_ext_pdata &&
+	    mddi_ext_pdata->mddi_sel_clk &&
+	    mddi_ext_pdata->mddi_sel_clk(&clk_rate))
+		printk(KERN_ERR
+			  "%s: can't select mddi io clk targate rate = %d\n",
+			  __func__, clk_rate);
+
+	if (clk_set_min_rate(mddi_ext_clk, clk_rate) < 0)
+		printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+			__func__);
+
+	mddi_host_start_ext_display();
+	ret = panel_next_on(pdev);
+
+	return ret;
+}
+
+static int mddi_ext_resource_initialized;
+
+static int mddi_ext_probe(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+	struct platform_device *mdp_dev = NULL;
+	struct msm_fb_panel_data *pdata = NULL;
+	int rc;
+	resource_size_t size ;
+	u32 clk_rate;
+
+	if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
+		mddi_ext_pdata = pdev->dev.platform_data;
+
+		size =  resource_size(&pdev->resource[0]);
+		msm_emdh_base = ioremap(pdev->resource[0].start, size);
+
+		MSM_FB_INFO("external mddi base address = 0x%x\n",
+				pdev->resource[0].start);
+
+		if (unlikely(!msm_emdh_base))
+			return -ENOMEM;
+
+		mddi_ext_resource_initialized = 1;
+		return 0;
+	}
+
+	if (!mddi_ext_resource_initialized)
+		return -EPERM;
+
+	mfd = platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+		return -ENOMEM;
+
+	mdp_dev = platform_device_alloc("mdp", pdev->id);
+	if (!mdp_dev)
+		return -ENOMEM;
+
+	/*
+	 * link to the latest pdev
+	 */
+	mfd->pdev = mdp_dev;
+	mfd->dest = DISPLAY_EXT_MDDI;
+
+	/*
+	 * alloc panel device data
+	 */
+	if (platform_device_add_data
+	    (mdp_dev, pdev->dev.platform_data,
+	     sizeof(struct msm_fb_panel_data))) {
+		printk(KERN_ERR "mddi_ext_probe: platform_device_add_data failed!\n");
+		platform_device_put(mdp_dev);
+		return -ENOMEM;
+	}
+	/*
+	 * data chain
+	 */
+	pdata = mdp_dev->dev.platform_data;
+	pdata->on = mddi_ext_on;
+	pdata->off = mddi_ext_off;
+	pdata->next = pdev;
+
+	/*
+	 * get/set panel specific fb info
+	 */
+	mfd->panel_info = pdata->panel_info;
+	mfd->fb_imgType = MDP_RGB_565;
+
+	clk_rate = mfd->panel_info.clk_max;
+	if (mddi_ext_pdata &&
+	    mddi_ext_pdata->mddi_sel_clk &&
+	    mddi_ext_pdata->mddi_sel_clk(&clk_rate))
+			printk(KERN_ERR
+			  "%s: can't select mddi io clk targate rate = %d\n",
+			  __func__, clk_rate);
+
+	if (clk_set_max_rate(mddi_ext_clk, clk_rate) < 0)
+		printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
+	mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
+
+	/*
+	 * set driver data
+	 */
+	platform_set_drvdata(mdp_dev, mfd);
+
+	/*
+	 * register in mdp driver
+	 */
+	rc = platform_device_add(mdp_dev);
+	if (rc)
+		goto mddi_ext_probe_err;
+
+	pdev_list[pdev_list_cnt++] = pdev;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	mfd->mddi_ext_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
+	mfd->mddi_ext_early_suspend.suspend = mddi_ext_early_suspend;
+	mfd->mddi_ext_early_suspend.resume = mddi_ext_early_resume;
+	register_early_suspend(&mfd->mddi_ext_early_suspend);
+#endif
+
+	return 0;
+
+mddi_ext_probe_err:
+	platform_device_put(mdp_dev);
+	return rc;
+}
+
+static int mddi_ext_is_in_suspend;
+
+static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	if (mddi_ext_is_in_suspend)
+		return 0;
+
+	mddi_ext_is_in_suspend = 1;
+
+	if (clk_set_min_rate(mddi_ext_clk, 0) < 0)
+		printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
+
+	clk_disable(mddi_ext_clk);
+	disable_irq(INT_MDDI_EXT);
+
+	return 0;
+}
+
+static int mddi_ext_resume(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+
+	mfd = platform_get_drvdata(pdev);
+
+	if (!mddi_ext_is_in_suspend)
+		return 0;
+
+	mddi_ext_is_in_suspend = 0;
+	enable_irq(INT_MDDI_EXT);
+
+	clk_enable(mddi_ext_clk);
+
+	return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mddi_ext_early_suspend(struct early_suspend *h)
+{
+	pm_message_t state;
+	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+							mddi_ext_early_suspend);
+
+	state.event = PM_EVENT_SUSPEND;
+	mddi_ext_suspend(mfd->pdev, state);
+}
+
+static void mddi_ext_early_resume(struct early_suspend *h)
+{
+	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+							mddi_ext_early_suspend);
+	mddi_ext_resume(mfd->pdev);
+}
+#endif
+
+static int mddi_ext_remove(struct platform_device *pdev)
+{
+	iounmap(msm_emdh_base);
+	return 0;
+}
+
+static int mddi_ext_register_driver(void)
+{
+	return platform_driver_register(&mddi_ext_driver);
+}
+
+static int __init mddi_ext_driver_init(void)
+{
+	int ret;
+
+	mddi_ext_clk = clk_get(NULL, "emdh_clk");
+	if (IS_ERR(mddi_ext_clk)) {
+		printk(KERN_ERR "can't find emdh_clk\n");
+		return PTR_ERR(mddi_ext_clk);
+	}
+	clk_enable(mddi_ext_clk);
+
+	ret = mddi_ext_register_driver();
+	if (ret) {
+		clk_disable(mddi_ext_clk);
+		clk_put(mddi_ext_clk);
+		printk(KERN_ERR "mddi_ext_register_driver() failed!\n");
+		return ret;
+	}
+	mddi_init();
+
+	return ret;
+}
+
+module_init(mddi_ext_driver_init);

+ 91 - 0
drivers/staging/msm/mddi_ext_lcd.c

@@ -0,0 +1,91 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+static int mddi_ext_lcd_on(struct platform_device *pdev);
+static int mddi_ext_lcd_off(struct platform_device *pdev);
+
+static int mddi_ext_lcd_on(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int mddi_ext_lcd_off(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int __init mddi_ext_lcd_probe(struct platform_device *pdev)
+{
+	msm_fb_add_device(pdev);
+
+	return 0;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = mddi_ext_lcd_probe,
+	.driver = {
+		.name   = "extmddi_svga",
+	},
+};
+
+static struct msm_fb_panel_data mddi_ext_lcd_panel_data = {
+	.panel_info.xres = 800,
+	.panel_info.yres = 600,
+	.panel_info.type = EXT_MDDI_PANEL,
+	.panel_info.pdest = DISPLAY_1,
+	.panel_info.wait_cycle = 0,
+	.panel_info.bpp = 18,
+	.panel_info.fb_num = 2,
+	.panel_info.clk_rate = 122880000,
+	.panel_info.clk_min  = 120000000,
+	.panel_info.clk_max  = 125000000,
+	.on = mddi_ext_lcd_on,
+	.off = mddi_ext_lcd_off,
+};
+
+static struct platform_device this_device = {
+	.name   = "extmddi_svga",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &mddi_ext_lcd_panel_data,
+	}
+};
+
+static int __init mddi_ext_lcd_init(void)
+{
+	int ret;
+	struct msm_panel_info *pinfo;
+
+	ret = platform_driver_register(&this_driver);
+	if (!ret) {
+		pinfo = &mddi_ext_lcd_panel_data.panel_info;
+		pinfo->lcd.vsync_enable = FALSE;
+		pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+
+		ret = platform_device_register(&this_device);
+		if (ret)
+			platform_driver_unregister(&this_driver);
+	}
+
+	return ret;
+}
+
+module_init(mddi_ext_lcd_init);

+ 114 - 0
drivers/staging/msm/mddi_prism.c

@@ -0,0 +1,114 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+static int prism_lcd_on(struct platform_device *pdev);
+static int prism_lcd_off(struct platform_device *pdev);
+
+static int prism_lcd_on(struct platform_device *pdev)
+{
+	/* Set the MDP pixel data attributes for Primary Display */
+	mddi_host_write_pix_attr_reg(0x00C3);
+
+	return 0;
+}
+
+static int prism_lcd_off(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int __init prism_probe(struct platform_device *pdev)
+{
+	msm_fb_add_device(pdev);
+
+	return 0;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = prism_probe,
+	.driver = {
+		.name   = "mddi_prism_wvga",
+	},
+};
+
+static struct msm_fb_panel_data prism_panel_data = {
+	.on = prism_lcd_on,
+	.off = prism_lcd_off,
+};
+
+static struct platform_device this_device = {
+	.name   = "mddi_prism_wvga",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &prism_panel_data,
+	}
+};
+
+static int __init prism_init(void)
+{
+	int ret;
+	struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+	u32 id;
+
+	ret = msm_fb_detect_client("mddi_prism_wvga");
+	if (ret == -ENODEV)
+		return 0;
+
+	if (ret) {
+		id = mddi_get_client_id();
+
+		if (((id >> 16) != 0x4474) || ((id & 0xffff) == 0x8960))
+			return 0;
+	}
+#endif
+	ret = platform_driver_register(&this_driver);
+	if (!ret) {
+		pinfo = &prism_panel_data.panel_info;
+		pinfo->xres = 800;
+		pinfo->yres = 480;
+		pinfo->type = MDDI_PANEL;
+		pinfo->pdest = DISPLAY_1;
+		pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+		pinfo->wait_cycle = 0;
+		pinfo->bpp = 18;
+		pinfo->fb_num = 2;
+		pinfo->clk_rate = 153600000;
+		pinfo->clk_min = 150000000;
+		pinfo->clk_max = 160000000;
+		pinfo->lcd.vsync_enable = TRUE;
+		pinfo->lcd.refx100 = 6050;
+		pinfo->lcd.v_back_porch = 23;
+		pinfo->lcd.v_front_porch = 20;
+		pinfo->lcd.v_pulse_width = 105;
+		pinfo->lcd.hw_vsync_mode = TRUE;
+		pinfo->lcd.vsync_notifier_period = 0;
+
+		ret = platform_device_register(&this_device);
+		if (ret)
+			platform_driver_unregister(&this_driver);
+	}
+
+	return ret;
+}
+
+module_init(prism_init);

+ 892 - 0
drivers/staging/msm/mddi_sharp.c

@@ -0,0 +1,892 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#define SHARP_QVGA_PRIM 1
+#define SHARP_128X128_SECD 2
+
+extern uint32 mddi_host_core_version;
+static boolean mddi_debug_prim_wait = FALSE;
+static boolean mddi_sharp_vsync_wake = TRUE;
+static boolean mddi_sharp_monitor_refresh_value = TRUE;
+static boolean mddi_sharp_report_refresh_measurements = FALSE;
+static uint32 mddi_sharp_rows_per_second = 13830;	/* 5200000/376 */
+static uint32 mddi_sharp_rows_per_refresh = 338;
+static uint32 mddi_sharp_usecs_per_refresh = 24440;	/* (376+338)/5200000 */
+static boolean mddi_sharp_debug_60hz_refresh = FALSE;
+
+extern mddi_gpio_info_type mddi_gpio;
+extern boolean mddi_vsync_detect_enabled;
+static msm_fb_vsync_handler_type mddi_sharp_vsync_handler;
+static void *mddi_sharp_vsync_handler_arg;
+static uint16 mddi_sharp_vsync_attempts;
+
+static void mddi_sharp_prim_lcd_init(void);
+static void mddi_sharp_sub_lcd_init(void);
+static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd);
+static void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler,
+					 void *);
+static void mddi_sharp_lcd_vsync_detected(boolean detected);
+static struct msm_panel_common_pdata *mddi_sharp_pdata;
+
+#define REG_SYSCTL    0x0000
+#define REG_INTR    0x0006
+#define REG_CLKCNF    0x000C
+#define REG_CLKDIV1    0x000E
+#define REG_CLKDIV2    0x0010
+
+#define REG_GIOD    0x0040
+#define REG_GIOA    0x0042
+
+#define REG_AGM      0x010A
+#define REG_FLFT    0x0110
+#define REG_FRGT    0x0112
+#define REG_FTOP    0x0114
+#define REG_FBTM    0x0116
+#define REG_FSTRX    0x0118
+#define REG_FSTRY    0x011A
+#define REG_VRAM    0x0202
+#define REG_SSDCTL    0x0330
+#define REG_SSD0    0x0332
+#define REG_PSTCTL1    0x0400
+#define REG_PSTCTL2    0x0402
+#define REG_PTGCTL    0x042A
+#define REG_PTHP    0x042C
+#define REG_PTHB    0x042E
+#define REG_PTHW    0x0430
+#define REG_PTHF    0x0432
+#define REG_PTVP    0x0434
+#define REG_PTVB    0x0436
+#define REG_PTVW    0x0438
+#define REG_PTVF    0x043A
+#define REG_VBLKS    0x0458
+#define REG_VBLKE    0x045A
+#define REG_SUBCTL    0x0700
+#define REG_SUBTCMD    0x0702
+#define REG_SUBTCMDD  0x0704
+#define REG_REVBYTE    0x0A02
+#define REG_REVCNT    0x0A04
+#define REG_REVATTR    0x0A06
+#define REG_REVFMT    0x0A08
+
+#define SHARP_SUB_UNKNOWN 0xffffffff
+#define SHARP_SUB_HYNIX 1
+#define SHARP_SUB_ROHM  2
+
+static uint32 sharp_subpanel_type = SHARP_SUB_UNKNOWN;
+
+static void sub_through_write(int sub_rs, uint32 sub_data)
+{
+	mddi_queue_register_write(REG_SUBTCMDD, sub_data, FALSE, 0);
+
+	/* CS=1,RD=1,WE=1,RS=sub_rs */
+	mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
+
+	/* CS=0,RD=1,WE=1,RS=sub_rs */
+	mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+	/* CS=0,RD=1,WE=0,RS=sub_rs */
+	mddi_queue_register_write(REG_SUBTCMD, 0x0004 | sub_rs, FALSE, 0);
+
+	/* CS=0,RD=1,WE=1,RS=sub_rs */
+	mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+	/* CS=1,RD=1,WE=1,RS=sub_rs */
+	mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
+}
+
+static uint32 sub_through_read(int sub_rs)
+{
+	uint32 sub_data;
+
+	/* CS=1,RD=1,WE=1,RS=sub_rs */
+	mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0);
+
+	/* CS=0,RD=1,WE=1,RS=sub_rs */
+	mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+	/* CS=0,RD=1,WE=0,RS=sub_rs */
+	mddi_queue_register_write(REG_SUBTCMD, 0x0002 | sub_rs, TRUE, 0);
+
+	mddi_queue_register_read(REG_SUBTCMDD, &sub_data, TRUE, 0);
+
+	/* CS=0,RD=1,WE=1,RS=sub_rs */
+	mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0);
+
+	/* CS=1,RD=1,WE=1,RS=sub_rs */
+	mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0);
+
+	return sub_data;
+}
+
+static void serigo(uint32 ssd)
+{
+	uint32 ssdctl;
+
+	mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
+	ssdctl = ((ssdctl & 0xE7) | 0x02);
+
+	mddi_queue_register_write(REG_SSD0, ssd, FALSE, 0);
+	mddi_queue_register_write(REG_SSDCTL, ssdctl, TRUE, 0);
+
+	do {
+		mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0);
+	} while ((ssdctl & 0x0002) != 0);
+
+	if (mddi_debug_prim_wait)
+		mddi_wait(2);
+}
+
+static void mddi_sharp_lcd_powerdown(void)
+{
+	serigo(0x0131);
+	serigo(0x0300);
+	mddi_wait(40);
+	serigo(0x0135);
+	mddi_wait(20);
+	serigo(0x2122);
+	mddi_wait(20);
+	serigo(0x0201);
+	mddi_wait(20);
+	serigo(0x2100);
+	mddi_wait(20);
+	serigo(0x2000);
+	mddi_wait(20);
+
+	mddi_queue_register_write(REG_PSTCTL1, 0x1, TRUE, 0);
+	mddi_wait(100);
+	mddi_queue_register_write(REG_PSTCTL1, 0x0, TRUE, 0);
+	mddi_wait(2);
+	mddi_queue_register_write(REG_SYSCTL, 0x1, TRUE, 0);
+	mddi_wait(2);
+	mddi_queue_register_write(REG_CLKDIV1, 0x3, TRUE, 0);
+	mddi_wait(2);
+	mddi_queue_register_write(REG_SSDCTL, 0x0000, TRUE, 0);	/* SSDRESET */
+	mddi_queue_register_write(REG_SYSCTL, 0x0, TRUE, 0);
+	mddi_wait(2);
+}
+
+static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd)
+{
+	uint32 regdata;
+	int32 level;
+	int max = mfd->panel_info.bl_max;
+	int min = mfd->panel_info.bl_min;
+
+	if (mddi_sharp_pdata && mddi_sharp_pdata->backlight_level) {
+		level = mddi_sharp_pdata->backlight_level(mfd->bl_level,
+							  max,
+							  min);
+
+		if (level < 0)
+			return;
+
+		/* use Rodem GPIO(2:0) to give 8 levels of backlight (7-0) */
+		/* Set lower 3 GPIOs as Outputs (set to 0) */
+		mddi_queue_register_read(REG_GIOA, &regdata, TRUE, 0);
+		mddi_queue_register_write(REG_GIOA, regdata & 0xfff8, TRUE, 0);
+
+		/* Set lower 3 GPIOs as level */
+		mddi_queue_register_read(REG_GIOD, &regdata, TRUE, 0);
+		mddi_queue_register_write(REG_GIOD,
+			  (regdata & 0xfff8) | (0x07 & level), TRUE, 0);
+	}
+}
+
+static void mddi_sharp_prim_lcd_init(void)
+{
+	mddi_queue_register_write(REG_SYSCTL, 0x4000, TRUE, 0);
+	mddi_wait(1);
+	mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
+	mddi_wait(5);
+	mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
+	mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
+
+	/* new reg write below */
+	if (mddi_sharp_debug_60hz_refresh)
+		mddi_queue_register_write(REG_CLKCNF, 0x070d, FALSE, 0);
+	else
+		mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
+
+	mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
+	mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
+	mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
+	mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
+	mddi_queue_register_write(REG_PTHW, 240, FALSE, 0);
+	if (mddi_sharp_debug_60hz_refresh)
+		mddi_queue_register_write(REG_PTHF, 12, FALSE, 0);
+	else
+		mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
+
+	mddi_wait(1);
+
+	mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
+	mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
+	mddi_queue_register_write(REG_PTVW, 320, FALSE, 0);
+	mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
+
+	mddi_wait(1);
+
+	/* vram_color set REG_AGM???? */
+	mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
+
+	mddi_queue_register_write(REG_SSDCTL, 0x0000, FALSE, 0);
+	mddi_queue_register_write(REG_SSDCTL, 0x0001, TRUE, 0);
+	mddi_wait(1);
+	mddi_queue_register_write(REG_PSTCTL1, 0x0001, TRUE, 0);
+	mddi_wait(10);
+
+	serigo(0x0701);
+	/* software reset */
+	mddi_wait(1);
+	/* Wait over 50us */
+
+	serigo(0x0400);
+	/* DCLK~ACHSYNC~ACVSYNC polarity setting */
+	serigo(0x2900);
+	/* EEPROM start read address setting */
+	serigo(0x2606);
+	/* EEPROM start read register setting */
+	mddi_wait(20);
+	/* Wait over 20ms */
+
+	serigo(0x0503);
+	/* Horizontal timing setting */
+	serigo(0x062C);
+	/* Veritical timing setting */
+	serigo(0x2001);
+	/* power initialize setting(VDC2) */
+	mddi_wait(20);
+	/* Wait over 20ms */
+
+	serigo(0x2120);
+	/* Initialize power setting(CPS) */
+	mddi_wait(20);
+	/* Wait over 20ms */
+
+	serigo(0x2130);
+	/* Initialize power setting(CPS) */
+	mddi_wait(20);
+	/* Wait over 20ms */
+
+	serigo(0x2132);
+	/* Initialize power setting(CPS) */
+	mddi_wait(10);
+	/* Wait over 10ms */
+
+	serigo(0x2133);
+	/* Initialize power setting(CPS) */
+	mddi_wait(20);
+	/* Wait over 20ms */
+
+	serigo(0x0200);
+	/* Panel initialize release(INIT) */
+	mddi_wait(1);
+	/* Wait over 1ms */
+
+	serigo(0x0131);
+	/* Panel setting(CPS) */
+	mddi_wait(1);
+	/* Wait over 1ms */
+
+	mddi_queue_register_write(REG_PSTCTL1, 0x0003, TRUE, 0);
+
+	/* if (FFA LCD is upside down) -> serigo(0x0100); */
+	serigo(0x0130);
+
+	/* Black mask release(display ON) */
+	mddi_wait(1);
+	/* Wait over 1ms */
+
+	if (mddi_sharp_vsync_wake) {
+		mddi_queue_register_write(REG_VBLKS, 0x1001, TRUE, 0);
+		mddi_queue_register_write(REG_VBLKE, 0x1002, TRUE, 0);
+	}
+
+	/* Set the MDP pixel data attributes for Primary Display */
+	mddi_host_write_pix_attr_reg(0x00C3);
+	return;
+
+}
+
+void mddi_sharp_sub_lcd_init(void)
+{
+
+	mddi_queue_register_write(REG_SYSCTL, 0x4000, FALSE, 0);
+	mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0);
+	mddi_wait(100);
+
+	mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0);
+	mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0);
+	mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0);
+	mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0);
+	mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0);
+	mddi_queue_register_write(REG_PTHP, 4, FALSE, 0);
+	mddi_queue_register_write(REG_PTHB, 40, FALSE, 0);
+	mddi_queue_register_write(REG_PTHW, 128, FALSE, 0);
+	mddi_queue_register_write(REG_PTHF, 92, FALSE, 0);
+	mddi_queue_register_write(REG_PTVP, 1, FALSE, 0);
+	mddi_queue_register_write(REG_PTVB, 2, FALSE, 0);
+	mddi_queue_register_write(REG_PTVW, 128, FALSE, 0);
+	mddi_queue_register_write(REG_PTVF, 15, FALSE, 0);
+
+	/* Now the sub display..... */
+	/* Reset High */
+	mddi_queue_register_write(REG_SUBCTL, 0x0200, FALSE, 0);
+	/* CS=1,RD=1,WE=1,RS=1 */
+	mddi_queue_register_write(REG_SUBTCMD, 0x000f, TRUE, 0);
+	mddi_wait(1);
+	/* Wait 5us */
+
+	if (sharp_subpanel_type == SHARP_SUB_UNKNOWN) {
+		uint32 data;
+
+		sub_through_write(1, 0x05);
+		sub_through_write(1, 0x6A);
+		sub_through_write(1, 0x1D);
+		sub_through_write(1, 0x05);
+		data = sub_through_read(1);
+		if (data == 0x6A) {
+			sharp_subpanel_type = SHARP_SUB_HYNIX;
+		} else {
+			sub_through_write(0, 0x36);
+			sub_through_write(1, 0xA8);
+			sub_through_write(0, 0x09);
+			data = sub_through_read(1);
+			data = sub_through_read(1);
+			if (data == 0x54) {
+				sub_through_write(0, 0x36);
+				sub_through_write(1, 0x00);
+				sharp_subpanel_type = SHARP_SUB_ROHM;
+			}
+		}
+	}
+
+	if (sharp_subpanel_type == SHARP_SUB_HYNIX) {
+		sub_through_write(1, 0x00);	/* Display setting 1 */
+		sub_through_write(1, 0x04);
+		sub_through_write(1, 0x01);
+		sub_through_write(1, 0x05);
+		sub_through_write(1, 0x0280);
+		sub_through_write(1, 0x0301);
+		sub_through_write(1, 0x0402);
+		sub_through_write(1, 0x0500);
+		sub_through_write(1, 0x0681);
+		sub_through_write(1, 0x077F);
+		sub_through_write(1, 0x08C0);
+		sub_through_write(1, 0x0905);
+		sub_through_write(1, 0x0A02);
+		sub_through_write(1, 0x0B00);
+		sub_through_write(1, 0x0C00);
+		sub_through_write(1, 0x0D00);
+		sub_through_write(1, 0x0E00);
+		sub_through_write(1, 0x0F00);
+
+		sub_through_write(1, 0x100B);	/* Display setting 2 */
+		sub_through_write(1, 0x1103);
+		sub_through_write(1, 0x1237);
+		sub_through_write(1, 0x1300);
+		sub_through_write(1, 0x1400);
+		sub_through_write(1, 0x1500);
+		sub_through_write(1, 0x1605);
+		sub_through_write(1, 0x1700);
+		sub_through_write(1, 0x1800);
+		sub_through_write(1, 0x192E);
+		sub_through_write(1, 0x1A00);
+		sub_through_write(1, 0x1B00);
+		sub_through_write(1, 0x1C00);
+
+		sub_through_write(1, 0x151A);	/* Power setting */
+
+		sub_through_write(1, 0x2002);	/* Gradation Palette setting */
+		sub_through_write(1, 0x2107);
+		sub_through_write(1, 0x220C);
+		sub_through_write(1, 0x2310);
+		sub_through_write(1, 0x2414);
+		sub_through_write(1, 0x2518);
+		sub_through_write(1, 0x261C);
+		sub_through_write(1, 0x2720);
+		sub_through_write(1, 0x2824);
+		sub_through_write(1, 0x2928);
+		sub_through_write(1, 0x2A2B);
+		sub_through_write(1, 0x2B2E);
+		sub_through_write(1, 0x2C31);
+		sub_through_write(1, 0x2D34);
+		sub_through_write(1, 0x2E37);
+		sub_through_write(1, 0x2F3A);
+		sub_through_write(1, 0x303C);
+		sub_through_write(1, 0x313E);
+		sub_through_write(1, 0x323F);
+		sub_through_write(1, 0x3340);
+		sub_through_write(1, 0x3441);
+		sub_through_write(1, 0x3543);
+		sub_through_write(1, 0x3646);
+		sub_through_write(1, 0x3749);
+		sub_through_write(1, 0x384C);
+		sub_through_write(1, 0x394F);
+		sub_through_write(1, 0x3A52);
+		sub_through_write(1, 0x3B59);
+		sub_through_write(1, 0x3C60);
+		sub_through_write(1, 0x3D67);
+		sub_through_write(1, 0x3E6E);
+		sub_through_write(1, 0x3F7F);
+		sub_through_write(1, 0x4001);
+		sub_through_write(1, 0x4107);
+		sub_through_write(1, 0x420C);
+		sub_through_write(1, 0x4310);
+		sub_through_write(1, 0x4414);
+		sub_through_write(1, 0x4518);
+		sub_through_write(1, 0x461C);
+		sub_through_write(1, 0x4720);
+		sub_through_write(1, 0x4824);
+		sub_through_write(1, 0x4928);
+		sub_through_write(1, 0x4A2B);
+		sub_through_write(1, 0x4B2E);
+		sub_through_write(1, 0x4C31);
+		sub_through_write(1, 0x4D34);
+		sub_through_write(1, 0x4E37);
+		sub_through_write(1, 0x4F3A);
+		sub_through_write(1, 0x503C);
+		sub_through_write(1, 0x513E);
+		sub_through_write(1, 0x523F);
+		sub_through_write(1, 0x5340);
+		sub_through_write(1, 0x5441);
+		sub_through_write(1, 0x5543);
+		sub_through_write(1, 0x5646);
+		sub_through_write(1, 0x5749);
+		sub_through_write(1, 0x584C);
+		sub_through_write(1, 0x594F);
+		sub_through_write(1, 0x5A52);
+		sub_through_write(1, 0x5B59);
+		sub_through_write(1, 0x5C60);
+		sub_through_write(1, 0x5D67);
+		sub_through_write(1, 0x5E6E);
+		sub_through_write(1, 0x5F7E);
+		sub_through_write(1, 0x6000);
+		sub_through_write(1, 0x6107);
+		sub_through_write(1, 0x620C);
+		sub_through_write(1, 0x6310);
+		sub_through_write(1, 0x6414);
+		sub_through_write(1, 0x6518);
+		sub_through_write(1, 0x661C);
+		sub_through_write(1, 0x6720);
+		sub_through_write(1, 0x6824);
+		sub_through_write(1, 0x6928);
+		sub_through_write(1, 0x6A2B);
+		sub_through_write(1, 0x6B2E);
+		sub_through_write(1, 0x6C31);
+		sub_through_write(1, 0x6D34);
+		sub_through_write(1, 0x6E37);
+		sub_through_write(1, 0x6F3A);
+		sub_through_write(1, 0x703C);
+		sub_through_write(1, 0x713E);
+		sub_through_write(1, 0x723F);
+		sub_through_write(1, 0x7340);
+		sub_through_write(1, 0x7441);
+		sub_through_write(1, 0x7543);
+		sub_through_write(1, 0x7646);
+		sub_through_write(1, 0x7749);
+		sub_through_write(1, 0x784C);
+		sub_through_write(1, 0x794F);
+		sub_through_write(1, 0x7A52);
+		sub_through_write(1, 0x7B59);
+		sub_through_write(1, 0x7C60);
+		sub_through_write(1, 0x7D67);
+		sub_through_write(1, 0x7E6E);
+		sub_through_write(1, 0x7F7D);
+
+		sub_through_write(1, 0x1851);	/* Display on */
+
+		mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0);
+
+		/* 1 pixel / 1 post clock */
+		mddi_queue_register_write(REG_CLKDIV2, 0x3b00, FALSE, 0);
+
+		/* SUB LCD select */
+		mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
+
+		/* RS=0,command initiate number=0,select master mode */
+		mddi_queue_register_write(REG_SUBCTL, 0x0202, FALSE, 0);
+
+		/* Sub LCD Data transform start */
+		mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
+
+	} else if (sharp_subpanel_type == SHARP_SUB_ROHM) {
+
+		sub_through_write(0, 0x01);	/* Display setting */
+		sub_through_write(1, 0x00);
+
+		mddi_wait(1);
+		/* Wait 100us  <----- ******* Update 2005/01/24 */
+
+		sub_through_write(0, 0xB6);
+		sub_through_write(1, 0x0C);
+		sub_through_write(1, 0x4A);
+		sub_through_write(1, 0x20);
+		sub_through_write(0, 0x3A);
+		sub_through_write(1, 0x05);
+		sub_through_write(0, 0xB7);
+		sub_through_write(1, 0x01);
+		sub_through_write(0, 0xBA);
+		sub_through_write(1, 0x20);
+		sub_through_write(1, 0x02);
+		sub_through_write(0, 0x25);
+		sub_through_write(1, 0x4F);
+		sub_through_write(0, 0xBB);
+		sub_through_write(1, 0x00);
+		sub_through_write(0, 0x36);
+		sub_through_write(1, 0x00);
+		sub_through_write(0, 0xB1);
+		sub_through_write(1, 0x05);
+		sub_through_write(0, 0xBE);
+		sub_through_write(1, 0x80);
+		sub_through_write(0, 0x26);
+		sub_through_write(1, 0x01);
+		sub_through_write(0, 0x2A);
+		sub_through_write(1, 0x02);
+		sub_through_write(1, 0x81);
+		sub_through_write(0, 0x2B);
+		sub_through_write(1, 0x00);
+		sub_through_write(1, 0x7F);
+
+		sub_through_write(0, 0x2C);
+		sub_through_write(0, 0x11);	/* Sleep mode off */
+
+		mddi_wait(1);
+		/* Wait 100 ms <----- ******* Update 2005/01/24 */
+
+		sub_through_write(0, 0x29);	/* Display on */
+		sub_through_write(0, 0xB3);
+		sub_through_write(1, 0x20);
+		sub_through_write(1, 0xAA);
+		sub_through_write(1, 0xA0);
+		sub_through_write(1, 0x20);
+		sub_through_write(1, 0x30);
+		sub_through_write(1, 0xA6);
+		sub_through_write(1, 0xFF);
+		sub_through_write(1, 0x9A);
+		sub_through_write(1, 0x9F);
+		sub_through_write(1, 0xAF);
+		sub_through_write(1, 0xBC);
+		sub_through_write(1, 0xCF);
+		sub_through_write(1, 0xDF);
+		sub_through_write(1, 0x20);
+		sub_through_write(1, 0x9C);
+		sub_through_write(1, 0x8A);
+
+		sub_through_write(0, 0x002C);	/* Display on */
+
+		/* 1 pixel / 2 post clock */
+		mddi_queue_register_write(REG_CLKDIV2, 0x7b00, FALSE, 0);
+
+		/* SUB LCD select */
+		mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0);
+
+		/* RS=1,command initiate number=0,select master mode */
+		mddi_queue_register_write(REG_SUBCTL, 0x0242, FALSE, 0);
+
+		/* Sub LCD Data transform start */
+		mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0);
+
+	}
+
+	/* Set the MDP pixel data attributes for Sub Display */
+	mddi_host_write_pix_attr_reg(0x00C0);
+}
+
+void mddi_sharp_lcd_vsync_detected(boolean detected)
+{
+	/* static timetick_type start_time = 0; */
+	static struct timeval start_time;
+	static boolean first_time = TRUE;
+	/* uint32 mdp_cnt_val = 0; */
+	/* timetick_type elapsed_us; */
+	struct timeval now;
+	uint32 elapsed_us;
+	uint32 num_vsyncs;
+
+	if ((detected) || (mddi_sharp_vsync_attempts > 5)) {
+		if ((detected) && (mddi_sharp_monitor_refresh_value)) {
+			/* if (start_time != 0) */
+			if (!first_time) {
+				jiffies_to_timeval(jiffies, &now);
+				elapsed_us =
+				    (now.tv_sec - start_time.tv_sec) * 1000000 +
+				    now.tv_usec - start_time.tv_usec;
+				/*
+				* LCD is configured for a refresh every usecs,
+				* so to determine the number of vsyncs that
+				* have occurred since the last measurement add
+				* half that to the time difference and divide
+				* by the refresh rate.
+				*/
+				num_vsyncs = (elapsed_us +
+					      (mddi_sharp_usecs_per_refresh >>
+					       1)) /
+				    mddi_sharp_usecs_per_refresh;
+				/*
+				 * LCD is configured for * hsyncs (rows) per
+				 * refresh cycle. Calculate new rows_per_second
+				 * value based upon these new measurements.
+				 * MDP can update with this new value.
+				 */
+				mddi_sharp_rows_per_second =
+				    (mddi_sharp_rows_per_refresh * 1000 *
+				     num_vsyncs) / (elapsed_us / 1000);
+			}
+			/* start_time = timetick_get(); */
+			first_time = FALSE;
+			jiffies_to_timeval(jiffies, &start_time);
+			if (mddi_sharp_report_refresh_measurements) {
+				/* mdp_cnt_val = MDP_LINE_COUNT; */
+			}
+		}
+		/* if detected = TRUE, client initiated wakeup was detected */
+		if (mddi_sharp_vsync_handler != NULL) {
+			(*mddi_sharp_vsync_handler)
+			    (mddi_sharp_vsync_handler_arg);
+			mddi_sharp_vsync_handler = NULL;
+		}
+		mddi_vsync_detect_enabled = FALSE;
+		mddi_sharp_vsync_attempts = 0;
+		/* need to clear this vsync wakeup */
+		if (!mddi_queue_register_write_int(REG_INTR, 0x0000)) {
+			MDDI_MSG_ERR("Vsync interrupt clear failed!\n");
+		}
+		if (!detected) {
+			/* give up after 5 failed attempts but show error */
+			MDDI_MSG_NOTICE("Vsync detection failed!\n");
+		} else if ((mddi_sharp_monitor_refresh_value) &&
+			(mddi_sharp_report_refresh_measurements)) {
+			MDDI_MSG_NOTICE("  Lines Per Second=%d!\n",
+				mddi_sharp_rows_per_second);
+		}
+	} else
+		/* if detected = FALSE, we woke up from hibernation, but did not
+		 * detect client initiated wakeup.
+		 */
+		mddi_sharp_vsync_attempts++;
+}
+
+/* ISR to be executed */
+void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg)
+{
+	boolean error = FALSE;
+	unsigned long flags;
+
+	/* Disable interrupts */
+	spin_lock_irqsave(&mddi_host_spin_lock, flags);
+	/* INTLOCK(); */
+
+	if (mddi_sharp_vsync_handler != NULL)
+		error = TRUE;
+
+	/* Register the handler for this particular GROUP interrupt source */
+	mddi_sharp_vsync_handler = handler;
+	mddi_sharp_vsync_handler_arg = arg;
+
+	/* Restore interrupts */
+	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+	/* INTFREE(); */
+
+	if (error)
+		MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n");
+
+	/* Enable the vsync wakeup */
+	mddi_queue_register_write(REG_INTR, 0x8100, FALSE, 0);
+
+	mddi_sharp_vsync_attempts = 1;
+	mddi_vsync_detect_enabled = TRUE;
+}				/* mddi_sharp_vsync_set_handler */
+
+static int mddi_sharp_lcd_on(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+
+	mfd = platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (mfd->panel.id == SHARP_QVGA_PRIM)
+		mddi_sharp_prim_lcd_init();
+	else
+		mddi_sharp_sub_lcd_init();
+
+	return 0;
+}
+
+static int mddi_sharp_lcd_off(struct platform_device *pdev)
+{
+	mddi_sharp_lcd_powerdown();
+	return 0;
+}
+
+static int __init mddi_sharp_probe(struct platform_device *pdev)
+{
+	if (pdev->id == 0) {
+		mddi_sharp_pdata = pdev->dev.platform_data;
+		return 0;
+	}
+
+	msm_fb_add_device(pdev);
+
+	return 0;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = mddi_sharp_probe,
+	.driver = {
+		.name   = "mddi_sharp_qvga",
+	},
+};
+
+static struct msm_fb_panel_data mddi_sharp_panel_data0 = {
+	.on = mddi_sharp_lcd_on,
+	.off = mddi_sharp_lcd_off,
+	.set_backlight = mddi_sharp_lcd_set_backlight,
+	.set_vsync_notifier = mddi_sharp_vsync_set_handler,
+};
+
+static struct platform_device this_device_0 = {
+	.name   = "mddi_sharp_qvga",
+	.id	= SHARP_QVGA_PRIM,
+	.dev	= {
+		.platform_data = &mddi_sharp_panel_data0,
+	}
+};
+
+static struct msm_fb_panel_data mddi_sharp_panel_data1 = {
+	.on = mddi_sharp_lcd_on,
+	.off = mddi_sharp_lcd_off,
+};
+
+static struct platform_device this_device_1 = {
+	.name   = "mddi_sharp_qvga",
+	.id	= SHARP_128X128_SECD,
+	.dev	= {
+		.platform_data = &mddi_sharp_panel_data1,
+	}
+};
+
+static int __init mddi_sharp_init(void)
+{
+	int ret;
+	struct msm_panel_info *pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+	u32 id;
+
+	ret = msm_fb_detect_client("mddi_sharp_qvga");
+	if (ret == -ENODEV)
+		return 0;
+
+	if (ret) {
+		id = mddi_get_client_id();
+
+		if (((id >> 16) != 0x0) || ((id & 0xffff) != 0x8835))
+			return 0;
+	}
+#endif
+	if (mddi_host_core_version > 8) {
+		/* can use faster refresh with newer hw revisions */
+		mddi_sharp_debug_60hz_refresh = TRUE;
+
+		/* Timing variables for tracking vsync */
+		/* dot_clock = 6.00MHz
+		 * horizontal count = 296
+		 * vertical count = 338
+		 * refresh rate = 6000000/(296+338) = 60Hz
+		 */
+		mddi_sharp_rows_per_second = 20270;	/* 6000000/296 */
+		mddi_sharp_rows_per_refresh = 338;
+		mddi_sharp_usecs_per_refresh = 16674;	/* (296+338)/6000000 */
+	} else {
+		/* Timing variables for tracking vsync */
+		/* dot_clock = 5.20MHz
+		 * horizontal count = 376
+		 * vertical count = 338
+		 * refresh rate = 5200000/(376+338) = 41Hz
+		 */
+		mddi_sharp_rows_per_second = 13830;	/* 5200000/376 */
+		mddi_sharp_rows_per_refresh = 338;
+		mddi_sharp_usecs_per_refresh = 24440;	/* (376+338)/5200000 */
+	}
+
+	ret = platform_driver_register(&this_driver);
+	if (!ret) {
+		pinfo = &mddi_sharp_panel_data0.panel_info;
+		pinfo->xres = 240;
+		pinfo->yres = 320;
+		pinfo->type = MDDI_PANEL;
+		pinfo->pdest = DISPLAY_1;
+		pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+		pinfo->wait_cycle = 0;
+		pinfo->bpp = 18;
+		pinfo->fb_num = 2;
+		pinfo->clk_rate = 122880000;
+		pinfo->clk_min = 120000000;
+		pinfo->clk_max = 125000000;
+		pinfo->lcd.vsync_enable = TRUE;
+		pinfo->lcd.refx100 =
+			(mddi_sharp_rows_per_second * 100) /
+			mddi_sharp_rows_per_refresh;
+		pinfo->lcd.v_back_porch = 12;
+		pinfo->lcd.v_front_porch = 6;
+		pinfo->lcd.v_pulse_width = 0;
+		pinfo->lcd.hw_vsync_mode = FALSE;
+		pinfo->lcd.vsync_notifier_period = (1 * HZ);
+		pinfo->bl_max = 7;
+		pinfo->bl_min = 1;
+
+		ret = platform_device_register(&this_device_0);
+		if (ret)
+			platform_driver_unregister(&this_driver);
+
+		pinfo = &mddi_sharp_panel_data1.panel_info;
+		pinfo->xres = 128;
+		pinfo->yres = 128;
+		pinfo->type = MDDI_PANEL;
+		pinfo->pdest = DISPLAY_2;
+		pinfo->mddi.vdopkt = 0x400;
+		pinfo->wait_cycle = 0;
+		pinfo->bpp = 18;
+		pinfo->clk_rate = 122880000;
+		pinfo->clk_min = 120000000;
+		pinfo->clk_max = 125000000;
+		pinfo->fb_num = 2;
+
+		ret = platform_device_register(&this_device_1);
+		if (ret) {
+			platform_device_unregister(&this_device_0);
+			platform_driver_unregister(&this_driver);
+		}
+	}
+
+	if (!ret)
+		mddi_lcd.vsync_detected = mddi_sharp_lcd_vsync_detected;
+
+	return ret;
+}
+
+module_init(mddi_sharp_init);

+ 1741 - 0
drivers/staging/msm/mddi_toshiba.c

@@ -0,0 +1,1741 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+#include "mddi_toshiba.h"
+
+#define TM_GET_DID(id) ((id) & 0xff)
+#define TM_GET_PID(id) (((id) & 0xff00)>>8)
+
+#define MDDI_CLIENT_CORE_BASE  0x108000
+#define LCD_CONTROL_BLOCK_BASE 0x110000
+#define SPI_BLOCK_BASE         0x120000
+#define PWM_BLOCK_BASE         0x140000
+#define SYSTEM_BLOCK1_BASE     0x160000
+
+#define TTBUSSEL    (MDDI_CLIENT_CORE_BASE|0x18)
+#define DPSET0      (MDDI_CLIENT_CORE_BASE|0x1C)
+#define DPSET1      (MDDI_CLIENT_CORE_BASE|0x20)
+#define DPSUS       (MDDI_CLIENT_CORE_BASE|0x24)
+#define DPRUN       (MDDI_CLIENT_CORE_BASE|0x28)
+#define SYSCKENA    (MDDI_CLIENT_CORE_BASE|0x2C)
+
+#define BITMAP0     (MDDI_CLIENT_CORE_BASE|0x44)
+#define BITMAP1     (MDDI_CLIENT_CORE_BASE|0x48)
+#define BITMAP2     (MDDI_CLIENT_CORE_BASE|0x4C)
+#define BITMAP3     (MDDI_CLIENT_CORE_BASE|0x50)
+#define BITMAP4     (MDDI_CLIENT_CORE_BASE|0x54)
+
+#define SRST        (LCD_CONTROL_BLOCK_BASE|0x00)
+#define PORT_ENB    (LCD_CONTROL_BLOCK_BASE|0x04)
+#define START       (LCD_CONTROL_BLOCK_BASE|0x08)
+#define PORT        (LCD_CONTROL_BLOCK_BASE|0x0C)
+
+#define INTFLG      (LCD_CONTROL_BLOCK_BASE|0x18)
+#define INTMSK      (LCD_CONTROL_BLOCK_BASE|0x1C)
+#define MPLFBUF     (LCD_CONTROL_BLOCK_BASE|0x20)
+
+#define PXL         (LCD_CONTROL_BLOCK_BASE|0x30)
+#define HCYCLE      (LCD_CONTROL_BLOCK_BASE|0x34)
+#define HSW         (LCD_CONTROL_BLOCK_BASE|0x38)
+#define HDE_START   (LCD_CONTROL_BLOCK_BASE|0x3C)
+#define HDE_SIZE    (LCD_CONTROL_BLOCK_BASE|0x40)
+#define VCYCLE      (LCD_CONTROL_BLOCK_BASE|0x44)
+#define VSW         (LCD_CONTROL_BLOCK_BASE|0x48)
+#define VDE_START   (LCD_CONTROL_BLOCK_BASE|0x4C)
+#define VDE_SIZE    (LCD_CONTROL_BLOCK_BASE|0x50)
+#define WAKEUP      (LCD_CONTROL_BLOCK_BASE|0x54)
+#define REGENB      (LCD_CONTROL_BLOCK_BASE|0x5C)
+#define VSYNIF      (LCD_CONTROL_BLOCK_BASE|0x60)
+#define WRSTB       (LCD_CONTROL_BLOCK_BASE|0x64)
+#define RDSTB       (LCD_CONTROL_BLOCK_BASE|0x68)
+#define ASY_DATA    (LCD_CONTROL_BLOCK_BASE|0x6C)
+#define ASY_DATB    (LCD_CONTROL_BLOCK_BASE|0x70)
+#define ASY_DATC    (LCD_CONTROL_BLOCK_BASE|0x74)
+#define ASY_DATD    (LCD_CONTROL_BLOCK_BASE|0x78)
+#define ASY_DATE    (LCD_CONTROL_BLOCK_BASE|0x7C)
+#define ASY_DATF    (LCD_CONTROL_BLOCK_BASE|0x80)
+#define ASY_DATG    (LCD_CONTROL_BLOCK_BASE|0x84)
+#define ASY_DATH    (LCD_CONTROL_BLOCK_BASE|0x88)
+#define ASY_CMDSET  (LCD_CONTROL_BLOCK_BASE|0x8C)
+#define MONI        (LCD_CONTROL_BLOCK_BASE|0xB0)
+#define VPOS        (LCD_CONTROL_BLOCK_BASE|0xC0)
+
+#define SSICTL      (SPI_BLOCK_BASE|0x00)
+#define SSITIME     (SPI_BLOCK_BASE|0x04)
+#define SSITX       (SPI_BLOCK_BASE|0x08)
+#define SSIINTS     (SPI_BLOCK_BASE|0x14)
+
+#define TIMER0LOAD    (PWM_BLOCK_BASE|0x00)
+#define TIMER0CTRL    (PWM_BLOCK_BASE|0x08)
+#define PWM0OFF       (PWM_BLOCK_BASE|0x1C)
+#define TIMER1LOAD    (PWM_BLOCK_BASE|0x20)
+#define TIMER1CTRL    (PWM_BLOCK_BASE|0x28)
+#define PWM1OFF       (PWM_BLOCK_BASE|0x3C)
+#define TIMER2LOAD    (PWM_BLOCK_BASE|0x40)
+#define TIMER2CTRL    (PWM_BLOCK_BASE|0x48)
+#define PWM2OFF       (PWM_BLOCK_BASE|0x5C)
+#define PWMCR         (PWM_BLOCK_BASE|0x68)
+
+#define GPIOIS      (GPIO_BLOCK_BASE|0x08)
+#define GPIOIEV     (GPIO_BLOCK_BASE|0x10)
+#define GPIOIC      (GPIO_BLOCK_BASE|0x20)
+
+#define WKREQ       (SYSTEM_BLOCK1_BASE|0x00)
+#define CLKENB      (SYSTEM_BLOCK1_BASE|0x04)
+#define DRAMPWR     (SYSTEM_BLOCK1_BASE|0x08)
+#define INTMASK     (SYSTEM_BLOCK1_BASE|0x0C)
+#define CNT_DIS     (SYSTEM_BLOCK1_BASE|0x10)
+
+typedef enum {
+	TOSHIBA_STATE_OFF,
+	TOSHIBA_STATE_PRIM_SEC_STANDBY,
+	TOSHIBA_STATE_PRIM_SEC_READY,
+	TOSHIBA_STATE_PRIM_NORMAL_MODE,
+	TOSHIBA_STATE_SEC_NORMAL_MODE
+} mddi_toshiba_state_t;
+
+static uint32 mddi_toshiba_curr_vpos;
+static boolean mddi_toshiba_monitor_refresh_value = FALSE;
+static boolean mddi_toshiba_report_refresh_measurements = FALSE;
+
+boolean mddi_toshiba_61Hz_refresh = TRUE;
+
+/* Modifications to timing to increase refresh rate to > 60Hz.
+ *   20MHz dot clock.
+ *   646 total rows.
+ *   506 total columns.
+ *   refresh rate = 61.19Hz
+ */
+static uint32 mddi_toshiba_rows_per_second = 39526;
+static uint32 mddi_toshiba_usecs_per_refresh = 16344;
+static uint32 mddi_toshiba_rows_per_refresh = 646;
+extern boolean mddi_vsync_detect_enabled;
+
+static msm_fb_vsync_handler_type mddi_toshiba_vsync_handler;
+static void *mddi_toshiba_vsync_handler_arg;
+static uint16 mddi_toshiba_vsync_attempts;
+
+static mddi_toshiba_state_t toshiba_state = TOSHIBA_STATE_OFF;
+
+static struct msm_panel_common_pdata *mddi_toshiba_pdata;
+
+static int mddi_toshiba_lcd_on(struct platform_device *pdev);
+static int mddi_toshiba_lcd_off(struct platform_device *pdev);
+
+static void mddi_toshiba_state_transition(mddi_toshiba_state_t a,
+					  mddi_toshiba_state_t b)
+{
+	if (toshiba_state != a) {
+		MDDI_MSG_ERR("toshiba state trans. (%d->%d) found %d\n", a, b,
+			     toshiba_state);
+	}
+	toshiba_state = b;
+}
+
+#define GORDON_REG_IMGCTL1      0x10	/* Image interface control 1   */
+#define GORDON_REG_IMGCTL2      0x11	/* Image interface control 2   */
+#define GORDON_REG_IMGSET1      0x12	/* Image interface settings 1  */
+#define GORDON_REG_IMGSET2      0x13	/* Image interface settings 2  */
+#define GORDON_REG_IVBP1        0x14	/* DM0: Vert back porch        */
+#define GORDON_REG_IHBP1        0x15	/* DM0: Horiz back porch       */
+#define GORDON_REG_IVNUM1       0x16	/* DM0: Num of vert lines      */
+#define GORDON_REG_IHNUM1       0x17	/* DM0: Num of pixels per line */
+#define GORDON_REG_IVBP2        0x18	/* DM1: Vert back porch        */
+#define GORDON_REG_IHBP2        0x19	/* DM1: Horiz back porch       */
+#define GORDON_REG_IVNUM2       0x1A	/* DM1: Num of vert lines      */
+#define GORDON_REG_IHNUM2       0x1B	/* DM1: Num of pixels per line */
+#define GORDON_REG_LCDIFCTL1    0x30	/* LCD interface control 1     */
+#define GORDON_REG_VALTRAN      0x31	/* LCD IF ctl: VALTRAN sync flag */
+#define GORDON_REG_AVCTL        0x33
+#define GORDON_REG_LCDIFCTL2    0x34	/* LCD interface control 2     */
+#define GORDON_REG_LCDIFCTL3    0x35	/* LCD interface control 3     */
+#define GORDON_REG_LCDIFSET1    0x36	/* LCD interface settings 1    */
+#define GORDON_REG_PCCTL        0x3C
+#define GORDON_REG_TPARAM1      0x40
+#define GORDON_REG_TLCDIF1      0x41
+#define GORDON_REG_TSSPB_ST1    0x42
+#define GORDON_REG_TSSPB_ED1    0x43
+#define GORDON_REG_TSCK_ST1     0x44
+#define GORDON_REG_TSCK_WD1     0x45
+#define GORDON_REG_TGSPB_VST1   0x46
+#define GORDON_REG_TGSPB_VED1   0x47
+#define GORDON_REG_TGSPB_CH1    0x48
+#define GORDON_REG_TGCK_ST1     0x49
+#define GORDON_REG_TGCK_ED1     0x4A
+#define GORDON_REG_TPCTL_ST1    0x4B
+#define GORDON_REG_TPCTL_ED1    0x4C
+#define GORDON_REG_TPCHG_ED1    0x4D
+#define GORDON_REG_TCOM_CH1     0x4E
+#define GORDON_REG_THBP1        0x4F
+#define GORDON_REG_TPHCTL1      0x50
+#define GORDON_REG_EVPH1        0x51
+#define GORDON_REG_EVPL1        0x52
+#define GORDON_REG_EVNH1        0x53
+#define GORDON_REG_EVNL1        0x54
+#define GORDON_REG_TBIAS1       0x55
+#define GORDON_REG_TPARAM2      0x56
+#define GORDON_REG_TLCDIF2      0x57
+#define GORDON_REG_TSSPB_ST2    0x58
+#define GORDON_REG_TSSPB_ED2    0x59
+#define GORDON_REG_TSCK_ST2     0x5A
+#define GORDON_REG_TSCK_WD2     0x5B
+#define GORDON_REG_TGSPB_VST2   0x5C
+#define GORDON_REG_TGSPB_VED2   0x5D
+#define GORDON_REG_TGSPB_CH2    0x5E
+#define GORDON_REG_TGCK_ST2     0x5F
+#define GORDON_REG_TGCK_ED2     0x60
+#define GORDON_REG_TPCTL_ST2    0x61
+#define GORDON_REG_TPCTL_ED2    0x62
+#define GORDON_REG_TPCHG_ED2    0x63
+#define GORDON_REG_TCOM_CH2     0x64
+#define GORDON_REG_THBP2        0x65
+#define GORDON_REG_TPHCTL2      0x66
+#define GORDON_REG_EVPH2        0x67
+#define GORDON_REG_EVPL2        0x68
+#define GORDON_REG_EVNH2        0x69
+#define GORDON_REG_EVNL2        0x6A
+#define GORDON_REG_TBIAS2       0x6B
+#define GORDON_REG_POWCTL       0x80
+#define GORDON_REG_POWOSC1      0x81
+#define GORDON_REG_POWOSC2      0x82
+#define GORDON_REG_POWSET       0x83
+#define GORDON_REG_POWTRM1      0x85
+#define GORDON_REG_POWTRM2      0x86
+#define GORDON_REG_POWTRM3      0x87
+#define GORDON_REG_POWTRMSEL    0x88
+#define GORDON_REG_POWHIZ       0x89
+
+void serigo(uint16 reg, uint8 data)
+{
+	uint32 mddi_val = 0;
+	mddi_queue_register_read(SSIINTS, &mddi_val, TRUE, 0);
+	if (mddi_val & (1 << 8))
+		mddi_wait(1);
+	/* No De-assert of CS and send 2 bytes */
+	mddi_val = 0x90000 | ((0x00FF & reg) << 8) | data;
+	mddi_queue_register_write(SSITX, mddi_val, TRUE, 0);
+}
+
+void gordon_init(void)
+{
+       /* Image interface settings ***/
+	serigo(GORDON_REG_IMGCTL2, 0x00);
+	serigo(GORDON_REG_IMGSET1, 0x01);
+
+	/* Exchange the RGB signal for J510(Softbank mobile) */
+	serigo(GORDON_REG_IMGSET2, 0x12);
+	serigo(GORDON_REG_LCDIFSET1, 0x00);
+	mddi_wait(2);
+
+	/* Pre-charge settings */
+	serigo(GORDON_REG_PCCTL, 0x09);
+	serigo(GORDON_REG_LCDIFCTL2, 0x1B);
+	mddi_wait(1);
+}
+
+void gordon_disp_on(void)
+{
+	/*gordon_dispmode setting */
+	/*VGA settings */
+	serigo(GORDON_REG_TPARAM1, 0x30);
+	serigo(GORDON_REG_TLCDIF1, 0x00);
+	serigo(GORDON_REG_TSSPB_ST1, 0x8B);
+	serigo(GORDON_REG_TSSPB_ED1, 0x93);
+	mddi_wait(2);
+	serigo(GORDON_REG_TSCK_ST1, 0x88);
+	serigo(GORDON_REG_TSCK_WD1, 0x00);
+	serigo(GORDON_REG_TGSPB_VST1, 0x01);
+	serigo(GORDON_REG_TGSPB_VED1, 0x02);
+	mddi_wait(2);
+	serigo(GORDON_REG_TGSPB_CH1, 0x5E);
+	serigo(GORDON_REG_TGCK_ST1, 0x80);
+	serigo(GORDON_REG_TGCK_ED1, 0x3C);
+	serigo(GORDON_REG_TPCTL_ST1, 0x50);
+	mddi_wait(2);
+	serigo(GORDON_REG_TPCTL_ED1, 0x74);
+	serigo(GORDON_REG_TPCHG_ED1, 0x78);
+	serigo(GORDON_REG_TCOM_CH1, 0x50);
+	serigo(GORDON_REG_THBP1, 0x84);
+	mddi_wait(2);
+	serigo(GORDON_REG_TPHCTL1, 0x00);
+	serigo(GORDON_REG_EVPH1, 0x70);
+	serigo(GORDON_REG_EVPL1, 0x64);
+	serigo(GORDON_REG_EVNH1, 0x56);
+	mddi_wait(2);
+	serigo(GORDON_REG_EVNL1, 0x48);
+	serigo(GORDON_REG_TBIAS1, 0x88);
+	mddi_wait(2);
+	serigo(GORDON_REG_TPARAM2, 0x28);
+	serigo(GORDON_REG_TLCDIF2, 0x14);
+	serigo(GORDON_REG_TSSPB_ST2, 0x49);
+	serigo(GORDON_REG_TSSPB_ED2, 0x4B);
+	mddi_wait(2);
+	serigo(GORDON_REG_TSCK_ST2, 0x4A);
+	serigo(GORDON_REG_TSCK_WD2, 0x02);
+	serigo(GORDON_REG_TGSPB_VST2, 0x02);
+	serigo(GORDON_REG_TGSPB_VED2, 0x03);
+	mddi_wait(2);
+	serigo(GORDON_REG_TGSPB_CH2, 0x2F);
+	serigo(GORDON_REG_TGCK_ST2, 0x40);
+	serigo(GORDON_REG_TGCK_ED2, 0x1E);
+	serigo(GORDON_REG_TPCTL_ST2, 0x2C);
+	mddi_wait(2);
+	serigo(GORDON_REG_TPCTL_ED2, 0x3A);
+	serigo(GORDON_REG_TPCHG_ED2, 0x3C);
+	serigo(GORDON_REG_TCOM_CH2, 0x28);
+	serigo(GORDON_REG_THBP2, 0x4D);
+	mddi_wait(2);
+	serigo(GORDON_REG_TPHCTL2, 0x1A);
+	mddi_wait(2);
+	serigo(GORDON_REG_IVBP1, 0x02);
+	serigo(GORDON_REG_IHBP1, 0x90);
+	serigo(GORDON_REG_IVNUM1, 0xA0);
+	serigo(GORDON_REG_IHNUM1, 0x78);
+	mddi_wait(2);
+	serigo(GORDON_REG_IVBP2, 0x02);
+	serigo(GORDON_REG_IHBP2, 0x48);
+	serigo(GORDON_REG_IVNUM2, 0x50);
+	serigo(GORDON_REG_IHNUM2, 0x3C);
+	mddi_wait(2);
+	serigo(GORDON_REG_POWCTL, 0x03);
+	mddi_wait(15);
+	serigo(GORDON_REG_POWCTL, 0x07);
+	mddi_wait(15);
+	serigo(GORDON_REG_POWCTL, 0x0F);
+	mddi_wait(15);
+	serigo(GORDON_REG_AVCTL, 0x03);
+	mddi_wait(15);
+	serigo(GORDON_REG_POWCTL, 0x1F);
+	mddi_wait(15);
+	serigo(GORDON_REG_POWCTL, 0x5F);
+	mddi_wait(15);
+	serigo(GORDON_REG_POWCTL, 0x7F);
+	mddi_wait(15);
+	serigo(GORDON_REG_LCDIFCTL1, 0x02);
+	mddi_wait(15);
+	serigo(GORDON_REG_IMGCTL1, 0x00);
+	mddi_wait(15);
+	serigo(GORDON_REG_LCDIFCTL3, 0x00);
+	mddi_wait(15);
+	serigo(GORDON_REG_VALTRAN, 0x01);
+	mddi_wait(15);
+	serigo(GORDON_REG_LCDIFCTL1, 0x03);
+	serigo(GORDON_REG_LCDIFCTL1, 0x03);
+	mddi_wait(1);
+}
+
+void gordon_disp_off(void)
+{
+	serigo(GORDON_REG_LCDIFCTL2, 0x7B);
+	serigo(GORDON_REG_VALTRAN, 0x01);
+	serigo(GORDON_REG_LCDIFCTL1, 0x02);
+	serigo(GORDON_REG_LCDIFCTL3, 0x01);
+	mddi_wait(20);
+	serigo(GORDON_REG_VALTRAN, 0x01);
+	serigo(GORDON_REG_IMGCTL1, 0x01);
+	serigo(GORDON_REG_LCDIFCTL1, 0x00);
+	mddi_wait(20);
+	serigo(GORDON_REG_POWCTL, 0x1F);
+	mddi_wait(40);
+	serigo(GORDON_REG_POWCTL, 0x07);
+	mddi_wait(40);
+	serigo(GORDON_REG_POWCTL, 0x03);
+	mddi_wait(40);
+	serigo(GORDON_REG_POWCTL, 0x00);
+	mddi_wait(40);
+}
+
+void gordon_disp_init(void)
+{
+	gordon_init();
+	mddi_wait(20);
+	gordon_disp_on();
+}
+
+static void toshiba_common_initial_setup(struct msm_fb_data_type *mfd)
+{
+	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) {
+		write_client_reg(DPSET0    , 0x4bec0066, TRUE);
+		write_client_reg(DPSET1    , 0x00000113, TRUE);
+		write_client_reg(DPSUS     , 0x00000000, TRUE);
+		write_client_reg(DPRUN     , 0x00000001, TRUE);
+		mddi_wait(5);
+		write_client_reg(SYSCKENA  , 0x00000001, TRUE);
+		write_client_reg(CLKENB    , 0x0000a0e9, TRUE);
+
+		write_client_reg(GPIODATA  , 0x03FF0000, TRUE);
+		write_client_reg(GPIODIR   , 0x0000024D, TRUE);
+		write_client_reg(GPIOSEL   , 0x00000173, TRUE);
+		write_client_reg(GPIOPC    , 0x03C300C0, TRUE);
+		write_client_reg(WKREQ     , 0x00000000, TRUE);
+		write_client_reg(GPIOIS    , 0x00000000, TRUE);
+		write_client_reg(GPIOIEV   , 0x00000001, TRUE);
+		write_client_reg(GPIOIC    , 0x000003FF, TRUE);
+		write_client_reg(GPIODATA  , 0x00040004, TRUE);
+
+		write_client_reg(GPIODATA  , 0x00080008, TRUE);
+		write_client_reg(DRAMPWR   , 0x00000001, TRUE);
+		write_client_reg(CLKENB    , 0x0000a0eb, TRUE);
+		write_client_reg(PWMCR     , 0x00000000, TRUE);
+		mddi_wait(1);
+
+		write_client_reg(SSICTL    , 0x00060399, TRUE);
+		write_client_reg(SSITIME   , 0x00000100, TRUE);
+		write_client_reg(CNT_DIS   , 0x00000002, TRUE);
+		write_client_reg(SSICTL    , 0x0006039b, TRUE);
+
+		write_client_reg(SSITX     , 0x00000000, TRUE);
+		mddi_wait(7);
+		write_client_reg(SSITX     , 0x00000000, TRUE);
+		mddi_wait(7);
+		write_client_reg(SSITX     , 0x00000000, TRUE);
+		mddi_wait(7);
+
+		write_client_reg(SSITX     , 0x000800BA, TRUE);
+		write_client_reg(SSITX     , 0x00000111, TRUE);
+		write_client_reg(SSITX     , 0x00080036, TRUE);
+		write_client_reg(SSITX     , 0x00000100, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x0008003A, TRUE);
+		write_client_reg(SSITX     , 0x00000160, TRUE);
+		write_client_reg(SSITX     , 0x000800B1, TRUE);
+		write_client_reg(SSITX     , 0x0000015D, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800B2, TRUE);
+		write_client_reg(SSITX     , 0x00000133, TRUE);
+		write_client_reg(SSITX     , 0x000800B3, TRUE);
+		write_client_reg(SSITX     , 0x00000122, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800B4, TRUE);
+		write_client_reg(SSITX     , 0x00000102, TRUE);
+		write_client_reg(SSITX     , 0x000800B5, TRUE);
+		write_client_reg(SSITX     , 0x0000011E, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800B6, TRUE);
+		write_client_reg(SSITX     , 0x00000127, TRUE);
+		write_client_reg(SSITX     , 0x000800B7, TRUE);
+		write_client_reg(SSITX     , 0x00000103, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800B9, TRUE);
+		write_client_reg(SSITX     , 0x00000124, TRUE);
+		write_client_reg(SSITX     , 0x000800BD, TRUE);
+		write_client_reg(SSITX     , 0x000001A1, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800BB, TRUE);
+		write_client_reg(SSITX     , 0x00000100, TRUE);
+		write_client_reg(SSITX     , 0x000800BF, TRUE);
+		write_client_reg(SSITX     , 0x00000101, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800BE, TRUE);
+		write_client_reg(SSITX     , 0x00000100, TRUE);
+		write_client_reg(SSITX     , 0x000800C0, TRUE);
+		write_client_reg(SSITX     , 0x00000111, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800C1, TRUE);
+		write_client_reg(SSITX     , 0x00000111, TRUE);
+		write_client_reg(SSITX     , 0x000800C2, TRUE);
+		write_client_reg(SSITX     , 0x00000111, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800C3, TRUE);
+		write_client_reg(SSITX     , 0x00080132, TRUE);
+		write_client_reg(SSITX     , 0x00000132, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800C4, TRUE);
+		write_client_reg(SSITX     , 0x00080132, TRUE);
+		write_client_reg(SSITX     , 0x00000132, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800C5, TRUE);
+		write_client_reg(SSITX     , 0x00080132, TRUE);
+		write_client_reg(SSITX     , 0x00000132, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800C6, TRUE);
+		write_client_reg(SSITX     , 0x00080132, TRUE);
+		write_client_reg(SSITX     , 0x00000132, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800C7, TRUE);
+		write_client_reg(SSITX     , 0x00080164, TRUE);
+		write_client_reg(SSITX     , 0x00000145, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800C8, TRUE);
+		write_client_reg(SSITX     , 0x00000144, TRUE);
+		write_client_reg(SSITX     , 0x000800C9, TRUE);
+		write_client_reg(SSITX     , 0x00000152, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800CA, TRUE);
+		write_client_reg(SSITX     , 0x00000100, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800EC, TRUE);
+		write_client_reg(SSITX     , 0x00080101, TRUE);
+		write_client_reg(SSITX     , 0x000001FC, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800CF, TRUE);
+		write_client_reg(SSITX     , 0x00000101, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800D0, TRUE);
+		write_client_reg(SSITX     , 0x00080110, TRUE);
+		write_client_reg(SSITX     , 0x00000104, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800D1, TRUE);
+		write_client_reg(SSITX     , 0x00000101, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800D2, TRUE);
+		write_client_reg(SSITX     , 0x00080100, TRUE);
+		write_client_reg(SSITX     , 0x00000128, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800D3, TRUE);
+		write_client_reg(SSITX     , 0x00080100, TRUE);
+		write_client_reg(SSITX     , 0x00000128, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800D4, TRUE);
+		write_client_reg(SSITX     , 0x00080126, TRUE);
+		write_client_reg(SSITX     , 0x000001A4, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800D5, TRUE);
+		write_client_reg(SSITX     , 0x00000120, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800EF, TRUE);
+		write_client_reg(SSITX     , 0x00080132, TRUE);
+		write_client_reg(SSITX     , 0x00000100, TRUE);
+		mddi_wait(1);
+
+		write_client_reg(BITMAP0   , 0x032001E0, TRUE);
+		write_client_reg(BITMAP1   , 0x032001E0, TRUE);
+		write_client_reg(BITMAP2   , 0x014000F0, TRUE);
+		write_client_reg(BITMAP3   , 0x014000F0, TRUE);
+		write_client_reg(BITMAP4   , 0x014000F0, TRUE);
+		write_client_reg(CLKENB    , 0x0000A1EB, TRUE);
+		write_client_reg(PORT_ENB  , 0x00000001, TRUE);
+		write_client_reg(PORT      , 0x00000004, TRUE);
+		write_client_reg(PXL       , 0x00000002, TRUE);
+		write_client_reg(MPLFBUF   , 0x00000000, TRUE);
+		write_client_reg(HCYCLE    , 0x000000FD, TRUE);
+		write_client_reg(HSW       , 0x00000003, TRUE);
+		write_client_reg(HDE_START , 0x00000007, TRUE);
+		write_client_reg(HDE_SIZE  , 0x000000EF, TRUE);
+		write_client_reg(VCYCLE    , 0x00000325, TRUE);
+		write_client_reg(VSW       , 0x00000001, TRUE);
+		write_client_reg(VDE_START , 0x00000003, TRUE);
+		write_client_reg(VDE_SIZE  , 0x0000031F, TRUE);
+		write_client_reg(START     , 0x00000001, TRUE);
+		mddi_wait(32);
+		write_client_reg(SSITX     , 0x000800BC, TRUE);
+		write_client_reg(SSITX     , 0x00000180, TRUE);
+		write_client_reg(SSITX     , 0x0008003B, TRUE);
+		write_client_reg(SSITX     , 0x00000100, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800B0, TRUE);
+		write_client_reg(SSITX     , 0x00000116, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x000800B8, TRUE);
+		write_client_reg(SSITX     , 0x000801FF, TRUE);
+		write_client_reg(SSITX     , 0x000001F5, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX     , 0x00000011, TRUE);
+		mddi_wait(5);
+		write_client_reg(SSITX     , 0x00000029, TRUE);
+		return;
+	}
+
+	if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+		write_client_reg(DPSET0, 0x4BEC0066, TRUE);
+		write_client_reg(DPSET1, 0x00000113, TRUE);
+		write_client_reg(DPSUS, 0x00000000, TRUE);
+		write_client_reg(DPRUN, 0x00000001, TRUE);
+		mddi_wait(14);
+		write_client_reg(SYSCKENA, 0x00000001, TRUE);
+		write_client_reg(CLKENB, 0x000000EF, TRUE);
+		write_client_reg(GPIO_BLOCK_BASE, 0x03FF0000, TRUE);
+		write_client_reg(GPIODIR, 0x0000024D, TRUE);
+		write_client_reg(SYSTEM_BLOCK2_BASE, 0x00000173, TRUE);
+		write_client_reg(GPIOPC, 0x03C300C0, TRUE);
+		write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000000, TRUE);
+		write_client_reg(GPIOIS, 0x00000000, TRUE);
+		write_client_reg(GPIOIEV, 0x00000001, TRUE);
+		write_client_reg(GPIOIC, 0x000003FF, TRUE);
+		write_client_reg(GPIO_BLOCK_BASE, 0x00060006, TRUE);
+		write_client_reg(GPIO_BLOCK_BASE, 0x00080008, TRUE);
+		write_client_reg(GPIO_BLOCK_BASE, 0x02000200, TRUE);
+		write_client_reg(DRAMPWR, 0x00000001, TRUE);
+		write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+		write_client_reg(PWM_BLOCK_BASE, 0x00001388, TRUE);
+		write_client_reg(PWM0OFF, 0x00001387, TRUE);
+		write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+		write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+		write_client_reg(PWM1OFF, 0x00001387, TRUE);
+		write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
+		write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
+		write_client_reg(PWMCR, 0x00000003, TRUE);
+		mddi_wait(1);
+		write_client_reg(SPI_BLOCK_BASE, 0x00063111, TRUE);
+		write_client_reg(SSITIME, 0x00000100, TRUE);
+		write_client_reg(SPI_BLOCK_BASE, 0x00063113, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX, 0x00000000, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX, 0x00000000, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX, 0x00000000, TRUE);
+		mddi_wait(1);
+		write_client_reg(CLKENB, 0x0000A1EF, TRUE);
+		write_client_reg(START, 0x00000000, TRUE);
+		write_client_reg(WRSTB, 0x0000003F, TRUE);
+		write_client_reg(RDSTB, 0x00000432, TRUE);
+		write_client_reg(PORT_ENB, 0x00000002, TRUE);
+		write_client_reg(VSYNIF, 0x00000000, TRUE);
+		write_client_reg(ASY_DATA, 0x80000000, TRUE);
+		write_client_reg(ASY_DATB, 0x00000001, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+		mddi_wait(10);
+		write_client_reg(ASY_DATA, 0x80000000, TRUE);
+		write_client_reg(ASY_DATB, 0x80000000, TRUE);
+		write_client_reg(ASY_DATC, 0x80000000, TRUE);
+		write_client_reg(ASY_DATD, 0x80000000, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+		write_client_reg(ASY_DATA, 0x80000007, TRUE);
+		write_client_reg(ASY_DATB, 0x00004005, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+		mddi_wait(20);
+		write_client_reg(ASY_DATA, 0x80000059, TRUE);
+		write_client_reg(ASY_DATB, 0x00000000, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+
+		write_client_reg(VSYNIF, 0x00000001, TRUE);
+		write_client_reg(PORT_ENB, 0x00000001, TRUE);
+	} else {
+		write_client_reg(DPSET0, 0x4BEC0066, TRUE);
+		write_client_reg(DPSET1, 0x00000113, TRUE);
+		write_client_reg(DPSUS, 0x00000000, TRUE);
+		write_client_reg(DPRUN, 0x00000001, TRUE);
+		mddi_wait(14);
+		write_client_reg(SYSCKENA, 0x00000001, TRUE);
+		write_client_reg(CLKENB, 0x000000EF, TRUE);
+		write_client_reg(GPIODATA, 0x03FF0000, TRUE);
+		write_client_reg(GPIODIR, 0x0000024D, TRUE);
+		write_client_reg(GPIOSEL, 0x00000173, TRUE);
+		write_client_reg(GPIOPC, 0x03C300C0, TRUE);
+		write_client_reg(WKREQ, 0x00000000, TRUE);
+		write_client_reg(GPIOIS, 0x00000000, TRUE);
+		write_client_reg(GPIOIEV, 0x00000001, TRUE);
+		write_client_reg(GPIOIC, 0x000003FF, TRUE);
+		write_client_reg(GPIODATA, 0x00060006, TRUE);
+		write_client_reg(GPIODATA, 0x00080008, TRUE);
+		write_client_reg(GPIODATA, 0x02000200, TRUE);
+
+		if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA) {
+			mddi_wait(400);
+			write_client_reg(DRAMPWR, 0x00000001, TRUE);
+
+			write_client_reg(CNT_DIS, 0x00000002, TRUE);
+			write_client_reg(BITMAP0, 0x01E00320, TRUE);
+			write_client_reg(PORT_ENB, 0x00000001, TRUE);
+			write_client_reg(PORT, 0x00000004, TRUE);
+			write_client_reg(PXL, 0x0000003A, TRUE);
+			write_client_reg(MPLFBUF, 0x00000000, TRUE);
+			write_client_reg(HCYCLE, 0x00000253, TRUE);
+			write_client_reg(HSW, 0x00000003, TRUE);
+			write_client_reg(HDE_START, 0x00000017, TRUE);
+			write_client_reg(HDE_SIZE, 0x0000018F, TRUE);
+			write_client_reg(VCYCLE, 0x000001FF, TRUE);
+			write_client_reg(VSW, 0x00000001, TRUE);
+			write_client_reg(VDE_START, 0x00000003, TRUE);
+			write_client_reg(VDE_SIZE, 0x000001DF, TRUE);
+			write_client_reg(START, 0x00000001, TRUE);
+			mddi_wait(1);
+			write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+			write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+			write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+			write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+			write_client_reg(PWM1OFF, 0x00000087, TRUE);
+		} else {
+			write_client_reg(DRAMPWR, 0x00000001, TRUE);
+			write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+			write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+			write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+			write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+			write_client_reg(PWM1OFF, 0x00001387, TRUE);
+		}
+
+		write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
+		write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
+		write_client_reg(PWMCR, 0x00000003, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSICTL, 0x00000799, TRUE);
+		write_client_reg(SSITIME, 0x00000100, TRUE);
+		write_client_reg(SSICTL, 0x0000079b, TRUE);
+		write_client_reg(SSITX, 0x00000000, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX, 0x00000000, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX, 0x00000000, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX, 0x000800BA, TRUE);
+		write_client_reg(SSITX, 0x00000111, TRUE);
+		write_client_reg(SSITX, 0x00080036, TRUE);
+		write_client_reg(SSITX, 0x00000100, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800BB, TRUE);
+		write_client_reg(SSITX, 0x00000100, TRUE);
+		write_client_reg(SSITX, 0x0008003A, TRUE);
+		write_client_reg(SSITX, 0x00000160, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800BF, TRUE);
+		write_client_reg(SSITX, 0x00000100, TRUE);
+		write_client_reg(SSITX, 0x000800B1, TRUE);
+		write_client_reg(SSITX, 0x0000015D, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800B2, TRUE);
+		write_client_reg(SSITX, 0x00000133, TRUE);
+		write_client_reg(SSITX, 0x000800B3, TRUE);
+		write_client_reg(SSITX, 0x00000122, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800B4, TRUE);
+		write_client_reg(SSITX, 0x00000102, TRUE);
+		write_client_reg(SSITX, 0x000800B5, TRUE);
+		write_client_reg(SSITX, 0x0000011F, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800B6, TRUE);
+		write_client_reg(SSITX, 0x00000128, TRUE);
+		write_client_reg(SSITX, 0x000800B7, TRUE);
+		write_client_reg(SSITX, 0x00000103, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800B9, TRUE);
+		write_client_reg(SSITX, 0x00000120, TRUE);
+		write_client_reg(SSITX, 0x000800BD, TRUE);
+		write_client_reg(SSITX, 0x00000102, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800BE, TRUE);
+		write_client_reg(SSITX, 0x00000100, TRUE);
+		write_client_reg(SSITX, 0x000800C0, TRUE);
+		write_client_reg(SSITX, 0x00000111, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800C1, TRUE);
+		write_client_reg(SSITX, 0x00000111, TRUE);
+		write_client_reg(SSITX, 0x000800C2, TRUE);
+		write_client_reg(SSITX, 0x00000111, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800C3, TRUE);
+		write_client_reg(SSITX, 0x0008010A, TRUE);
+		write_client_reg(SSITX, 0x0000010A, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800C4, TRUE);
+		write_client_reg(SSITX, 0x00080160, TRUE);
+		write_client_reg(SSITX, 0x00000160, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800C5, TRUE);
+		write_client_reg(SSITX, 0x00080160, TRUE);
+		write_client_reg(SSITX, 0x00000160, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800C6, TRUE);
+		write_client_reg(SSITX, 0x00080160, TRUE);
+		write_client_reg(SSITX, 0x00000160, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800C7, TRUE);
+		write_client_reg(SSITX, 0x00080133, TRUE);
+		write_client_reg(SSITX, 0x00000143, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800C8, TRUE);
+		write_client_reg(SSITX, 0x00000144, TRUE);
+		write_client_reg(SSITX, 0x000800C9, TRUE);
+		write_client_reg(SSITX, 0x00000133, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800CA, TRUE);
+		write_client_reg(SSITX, 0x00000100, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800EC, TRUE);
+		write_client_reg(SSITX, 0x00080102, TRUE);
+		write_client_reg(SSITX, 0x00000118, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800CF, TRUE);
+		write_client_reg(SSITX, 0x00000101, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800D0, TRUE);
+		write_client_reg(SSITX, 0x00080110, TRUE);
+		write_client_reg(SSITX, 0x00000104, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800D1, TRUE);
+		write_client_reg(SSITX, 0x00000101, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800D2, TRUE);
+		write_client_reg(SSITX, 0x00080100, TRUE);
+		write_client_reg(SSITX, 0x0000013A, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800D3, TRUE);
+		write_client_reg(SSITX, 0x00080100, TRUE);
+		write_client_reg(SSITX, 0x0000013A, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800D4, TRUE);
+		write_client_reg(SSITX, 0x00080124, TRUE);
+		write_client_reg(SSITX, 0x0000016E, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX, 0x000800D5, TRUE);
+		write_client_reg(SSITX, 0x00000124, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800ED, TRUE);
+		write_client_reg(SSITX, 0x00080101, TRUE);
+		write_client_reg(SSITX, 0x0000010A, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800D6, TRUE);
+		write_client_reg(SSITX, 0x00000101, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800D7, TRUE);
+		write_client_reg(SSITX, 0x00080110, TRUE);
+		write_client_reg(SSITX, 0x0000010A, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800D8, TRUE);
+		write_client_reg(SSITX, 0x00000101, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800D9, TRUE);
+		write_client_reg(SSITX, 0x00080100, TRUE);
+		write_client_reg(SSITX, 0x00000114, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800DE, TRUE);
+		write_client_reg(SSITX, 0x00080100, TRUE);
+		write_client_reg(SSITX, 0x00000114, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800DF, TRUE);
+		write_client_reg(SSITX, 0x00080112, TRUE);
+		write_client_reg(SSITX, 0x0000013F, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800E0, TRUE);
+		write_client_reg(SSITX, 0x0000010B, TRUE);
+		write_client_reg(SSITX, 0x000800E2, TRUE);
+		write_client_reg(SSITX, 0x00000101, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800E3, TRUE);
+		write_client_reg(SSITX, 0x00000136, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800E4, TRUE);
+		write_client_reg(SSITX, 0x00080100, TRUE);
+		write_client_reg(SSITX, 0x00000103, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800E5, TRUE);
+		write_client_reg(SSITX, 0x00080102, TRUE);
+		write_client_reg(SSITX, 0x00000104, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800E6, TRUE);
+		write_client_reg(SSITX, 0x00000103, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800E7, TRUE);
+		write_client_reg(SSITX, 0x00080104, TRUE);
+		write_client_reg(SSITX, 0x0000010A, TRUE);
+		mddi_wait(2);
+		write_client_reg(SSITX, 0x000800E8, TRUE);
+		write_client_reg(SSITX, 0x00000104, TRUE);
+		write_client_reg(CLKENB, 0x000001EF, TRUE);
+		write_client_reg(START, 0x00000000, TRUE);
+		write_client_reg(WRSTB, 0x0000003F, TRUE);
+		write_client_reg(RDSTB, 0x00000432, TRUE);
+		write_client_reg(PORT_ENB, 0x00000002, TRUE);
+		write_client_reg(VSYNIF, 0x00000000, TRUE);
+		write_client_reg(ASY_DATA, 0x80000000, TRUE);
+		write_client_reg(ASY_DATB, 0x00000001, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+		mddi_wait(10);
+		write_client_reg(ASY_DATA, 0x80000000, TRUE);
+		write_client_reg(ASY_DATB, 0x80000000, TRUE);
+		write_client_reg(ASY_DATC, 0x80000000, TRUE);
+		write_client_reg(ASY_DATD, 0x80000000, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+		write_client_reg(ASY_DATA, 0x80000007, TRUE);
+		write_client_reg(ASY_DATB, 0x00004005, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+		mddi_wait(20);
+		write_client_reg(ASY_DATA, 0x80000059, TRUE);
+		write_client_reg(ASY_DATB, 0x00000000, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+		write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+		write_client_reg(VSYNIF, 0x00000001, TRUE);
+		write_client_reg(PORT_ENB, 0x00000001, TRUE);
+	}
+
+	mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_STANDBY,
+				      TOSHIBA_STATE_PRIM_SEC_READY);
+}
+
+static void toshiba_prim_start(struct msm_fb_data_type *mfd)
+{
+	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+		return;
+
+	if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+		write_client_reg(BITMAP1, 0x01E000F0, TRUE);
+		write_client_reg(BITMAP2, 0x01E000F0, TRUE);
+		write_client_reg(BITMAP3, 0x01E000F0, TRUE);
+		write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+		write_client_reg(CLKENB, 0x000001EF, TRUE);
+		write_client_reg(PORT_ENB, 0x00000001, TRUE);
+		write_client_reg(PORT, 0x00000016, TRUE);
+		write_client_reg(PXL, 0x00000002, TRUE);
+		write_client_reg(MPLFBUF, 0x00000000, TRUE);
+		write_client_reg(HCYCLE, 0x00000185, TRUE);
+		write_client_reg(HSW, 0x00000018, TRUE);
+		write_client_reg(HDE_START, 0x0000004A, TRUE);
+		write_client_reg(HDE_SIZE, 0x000000EF, TRUE);
+		write_client_reg(VCYCLE, 0x0000028E, TRUE);
+		write_client_reg(VSW, 0x00000004, TRUE);
+		write_client_reg(VDE_START, 0x00000009, TRUE);
+		write_client_reg(VDE_SIZE, 0x0000027F, TRUE);
+		write_client_reg(START, 0x00000001, TRUE);
+		write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000002, TRUE);
+	} else{
+
+		write_client_reg(VSYNIF, 0x00000001, TRUE);
+		write_client_reg(PORT_ENB, 0x00000001, TRUE);
+		write_client_reg(BITMAP1, 0x01E000F0, TRUE);
+		write_client_reg(BITMAP2, 0x01E000F0, TRUE);
+		write_client_reg(BITMAP3, 0x01E000F0, TRUE);
+		write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+		write_client_reg(CLKENB, 0x000001EF, TRUE);
+		write_client_reg(PORT_ENB, 0x00000001, TRUE);
+		write_client_reg(PORT, 0x00000004, TRUE);
+		write_client_reg(PXL, 0x00000002, TRUE);
+		write_client_reg(MPLFBUF, 0x00000000, TRUE);
+
+		if (mddi_toshiba_61Hz_refresh) {
+			write_client_reg(HCYCLE, 0x000000FC, TRUE);
+			mddi_toshiba_rows_per_second = 39526;
+			mddi_toshiba_rows_per_refresh = 646;
+			mddi_toshiba_usecs_per_refresh = 16344;
+		} else {
+			write_client_reg(HCYCLE, 0x0000010b, TRUE);
+			mddi_toshiba_rows_per_second = 37313;
+			mddi_toshiba_rows_per_refresh = 646;
+			mddi_toshiba_usecs_per_refresh = 17313;
+		}
+
+		write_client_reg(HSW, 0x00000003, TRUE);
+		write_client_reg(HDE_START, 0x00000007, TRUE);
+		write_client_reg(HDE_SIZE, 0x000000EF, TRUE);
+		write_client_reg(VCYCLE, 0x00000285, TRUE);
+		write_client_reg(VSW, 0x00000001, TRUE);
+		write_client_reg(VDE_START, 0x00000003, TRUE);
+		write_client_reg(VDE_SIZE, 0x0000027F, TRUE);
+		write_client_reg(START, 0x00000001, TRUE);
+		mddi_wait(10);
+		write_client_reg(SSITX, 0x000800BC, TRUE);
+		write_client_reg(SSITX, 0x00000180, TRUE);
+		write_client_reg(SSITX, 0x0008003B, TRUE);
+		write_client_reg(SSITX, 0x00000100, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX, 0x000800B0, TRUE);
+		write_client_reg(SSITX, 0x00000116, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX, 0x000800B8, TRUE);
+		write_client_reg(SSITX, 0x000801FF, TRUE);
+		write_client_reg(SSITX, 0x000001F5, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX, 0x00000011, TRUE);
+		write_client_reg(SSITX, 0x00000029, TRUE);
+		write_client_reg(WKREQ, 0x00000000, TRUE);
+		write_client_reg(WAKEUP, 0x00000000, TRUE);
+		write_client_reg(INTMSK, 0x00000001, TRUE);
+	}
+
+	mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY,
+				      TOSHIBA_STATE_PRIM_NORMAL_MODE);
+}
+
+static void toshiba_sec_start(struct msm_fb_data_type *mfd)
+{
+	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+		return;
+
+	write_client_reg(VSYNIF, 0x00000000, TRUE);
+	write_client_reg(PORT_ENB, 0x00000002, TRUE);
+	write_client_reg(CLKENB, 0x000011EF, TRUE);
+	write_client_reg(BITMAP0, 0x028001E0, TRUE);
+	write_client_reg(BITMAP1, 0x00000000, TRUE);
+	write_client_reg(BITMAP2, 0x00000000, TRUE);
+	write_client_reg(BITMAP3, 0x00000000, TRUE);
+	write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+	write_client_reg(PORT, 0x00000000, TRUE);
+	write_client_reg(PXL, 0x00000000, TRUE);
+	write_client_reg(MPLFBUF, 0x00000004, TRUE);
+	write_client_reg(HCYCLE, 0x0000006B, TRUE);
+	write_client_reg(HSW, 0x00000003, TRUE);
+	write_client_reg(HDE_START, 0x00000007, TRUE);
+	write_client_reg(HDE_SIZE, 0x00000057, TRUE);
+	write_client_reg(VCYCLE, 0x000000E6, TRUE);
+	write_client_reg(VSW, 0x00000001, TRUE);
+	write_client_reg(VDE_START, 0x00000003, TRUE);
+	write_client_reg(VDE_SIZE, 0x000000DB, TRUE);
+	write_client_reg(ASY_DATA, 0x80000001, TRUE);
+	write_client_reg(ASY_DATB, 0x0000011B, TRUE);
+	write_client_reg(ASY_DATC, 0x80000002, TRUE);
+	write_client_reg(ASY_DATD, 0x00000700, TRUE);
+	write_client_reg(ASY_DATE, 0x80000003, TRUE);
+	write_client_reg(ASY_DATF, 0x00000230, TRUE);
+	write_client_reg(ASY_DATG, 0x80000008, TRUE);
+	write_client_reg(ASY_DATH, 0x00000402, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+	write_client_reg(ASY_DATA, 0x80000009, TRUE);
+	write_client_reg(ASY_DATB, 0x00000000, TRUE);
+	write_client_reg(ASY_DATC, 0x8000000B, TRUE);
+	write_client_reg(ASY_DATD, 0x00000000, TRUE);
+	write_client_reg(ASY_DATE, 0x8000000C, TRUE);
+	write_client_reg(ASY_DATF, 0x00000000, TRUE);
+	write_client_reg(ASY_DATG, 0x8000000D, TRUE);
+	write_client_reg(ASY_DATH, 0x00000409, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+	write_client_reg(ASY_DATA, 0x8000000E, TRUE);
+	write_client_reg(ASY_DATB, 0x00000409, TRUE);
+	write_client_reg(ASY_DATC, 0x80000030, TRUE);
+	write_client_reg(ASY_DATD, 0x00000000, TRUE);
+	write_client_reg(ASY_DATE, 0x80000031, TRUE);
+	write_client_reg(ASY_DATF, 0x00000100, TRUE);
+	write_client_reg(ASY_DATG, 0x80000032, TRUE);
+	write_client_reg(ASY_DATH, 0x00000104, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+	write_client_reg(ASY_DATA, 0x80000033, TRUE);
+	write_client_reg(ASY_DATB, 0x00000400, TRUE);
+	write_client_reg(ASY_DATC, 0x80000034, TRUE);
+	write_client_reg(ASY_DATD, 0x00000306, TRUE);
+	write_client_reg(ASY_DATE, 0x80000035, TRUE);
+	write_client_reg(ASY_DATF, 0x00000706, TRUE);
+	write_client_reg(ASY_DATG, 0x80000036, TRUE);
+	write_client_reg(ASY_DATH, 0x00000707, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+	write_client_reg(ASY_DATA, 0x80000037, TRUE);
+	write_client_reg(ASY_DATB, 0x00000004, TRUE);
+	write_client_reg(ASY_DATC, 0x80000038, TRUE);
+	write_client_reg(ASY_DATD, 0x00000000, TRUE);
+	write_client_reg(ASY_DATE, 0x80000039, TRUE);
+	write_client_reg(ASY_DATF, 0x00000000, TRUE);
+	write_client_reg(ASY_DATG, 0x8000003A, TRUE);
+	write_client_reg(ASY_DATH, 0x00000001, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+	write_client_reg(ASY_DATA, 0x80000044, TRUE);
+	write_client_reg(ASY_DATB, 0x0000AF00, TRUE);
+	write_client_reg(ASY_DATC, 0x80000045, TRUE);
+	write_client_reg(ASY_DATD, 0x0000DB00, TRUE);
+	write_client_reg(ASY_DATE, 0x08000042, TRUE);
+	write_client_reg(ASY_DATF, 0x0000DB00, TRUE);
+	write_client_reg(ASY_DATG, 0x80000021, TRUE);
+	write_client_reg(ASY_DATH, 0x00000000, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+	write_client_reg(PXL, 0x0000000C, TRUE);
+	write_client_reg(VSYNIF, 0x00000001, TRUE);
+	write_client_reg(ASY_DATA, 0x80000022, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000003, TRUE);
+	write_client_reg(START, 0x00000001, TRUE);
+	mddi_wait(60);
+	write_client_reg(PXL, 0x00000000, TRUE);
+	write_client_reg(VSYNIF, 0x00000000, TRUE);
+	write_client_reg(START, 0x00000000, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+	write_client_reg(ASY_DATA, 0x80000050, TRUE);
+	write_client_reg(ASY_DATB, 0x00000000, TRUE);
+	write_client_reg(ASY_DATC, 0x80000051, TRUE);
+	write_client_reg(ASY_DATD, 0x00000E00, TRUE);
+	write_client_reg(ASY_DATE, 0x80000052, TRUE);
+	write_client_reg(ASY_DATF, 0x00000D01, TRUE);
+	write_client_reg(ASY_DATG, 0x80000053, TRUE);
+	write_client_reg(ASY_DATH, 0x00000000, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+	write_client_reg(ASY_DATA, 0x80000058, TRUE);
+	write_client_reg(ASY_DATB, 0x00000000, TRUE);
+	write_client_reg(ASY_DATC, 0x8000005A, TRUE);
+	write_client_reg(ASY_DATD, 0x00000E01, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+	write_client_reg(ASY_DATA, 0x80000011, TRUE);
+	write_client_reg(ASY_DATB, 0x00000812, TRUE);
+	write_client_reg(ASY_DATC, 0x80000012, TRUE);
+	write_client_reg(ASY_DATD, 0x00000003, TRUE);
+	write_client_reg(ASY_DATE, 0x80000013, TRUE);
+	write_client_reg(ASY_DATF, 0x00000909, TRUE);
+	write_client_reg(ASY_DATG, 0x80000010, TRUE);
+	write_client_reg(ASY_DATH, 0x00000040, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+	mddi_wait(40);
+	write_client_reg(ASY_DATA, 0x80000010, TRUE);
+	write_client_reg(ASY_DATB, 0x00000340, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(60);
+	write_client_reg(ASY_DATA, 0x80000010, TRUE);
+	write_client_reg(ASY_DATB, 0x00003340, TRUE);
+	write_client_reg(ASY_DATC, 0x80000007, TRUE);
+	write_client_reg(ASY_DATD, 0x00004007, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+	mddi_wait(1);
+	write_client_reg(ASY_DATA, 0x80000007, TRUE);
+	write_client_reg(ASY_DATB, 0x00004017, TRUE);
+	write_client_reg(ASY_DATC, 0x8000005B, TRUE);
+	write_client_reg(ASY_DATD, 0x00000000, TRUE);
+	write_client_reg(ASY_DATE, 0x80000059, TRUE);
+	write_client_reg(ASY_DATF, 0x00000011, TRUE);
+	write_client_reg(ASY_CMDSET, 0x0000000D, TRUE);
+	write_client_reg(ASY_CMDSET, 0x0000000C, TRUE);
+	mddi_wait(20);
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	/* LTPS I/F control */
+	write_client_reg(ASY_DATB, 0x00000019, TRUE);
+	/* Direct cmd transfer enable */
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	/* Direct cmd transfer disable */
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(20);
+	/* Index setting of SUB LCDD */
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	/* LTPS I/F control */
+	write_client_reg(ASY_DATB, 0x00000079, TRUE);
+	/* Direct cmd transfer enable */
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	/* Direct cmd transfer disable */
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(20);
+	/* Index setting of SUB LCDD */
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	/* LTPS I/F control */
+	write_client_reg(ASY_DATB, 0x000003FD, TRUE);
+	/* Direct cmd transfer enable */
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	/* Direct cmd transfer disable */
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(20);
+	mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY,
+				      TOSHIBA_STATE_SEC_NORMAL_MODE);
+}
+
+static void toshiba_prim_lcd_off(struct msm_fb_data_type *mfd)
+{
+	if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+		gordon_disp_off();
+	} else{
+
+		/* Main panel power off (Deep standby in) */
+		write_client_reg(SSITX, 0x000800BC, TRUE);
+		write_client_reg(SSITX, 0x00000100, TRUE);
+		write_client_reg(SSITX, 0x00000028, TRUE);
+		mddi_wait(1);
+		write_client_reg(SSITX, 0x000800B8, TRUE);
+		write_client_reg(SSITX, 0x00000180, TRUE);
+		write_client_reg(SSITX, 0x00000102, TRUE);
+		write_client_reg(SSITX, 0x00000010, TRUE);
+	}
+	write_client_reg(PORT, 0x00000003, TRUE);
+	write_client_reg(REGENB, 0x00000001, TRUE);
+	mddi_wait(1);
+	write_client_reg(PXL, 0x00000000, TRUE);
+	write_client_reg(START, 0x00000000, TRUE);
+	write_client_reg(REGENB, 0x00000001, TRUE);
+	mddi_wait(3);
+	if (TM_GET_PID(mfd->panel.id) != LCD_SHARP_2P4_VGA) {
+		write_client_reg(SSITX, 0x000800B0, TRUE);
+		write_client_reg(SSITX, 0x00000100, TRUE);
+	}
+	mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_NORMAL_MODE,
+				      TOSHIBA_STATE_PRIM_SEC_STANDBY);
+}
+
+static void toshiba_sec_lcd_off(struct msm_fb_data_type *mfd)
+{
+	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+		return;
+
+	write_client_reg(VSYNIF, 0x00000000, TRUE);
+	write_client_reg(PORT_ENB, 0x00000002, TRUE);
+	write_client_reg(ASY_DATA, 0x80000007, TRUE);
+	write_client_reg(ASY_DATB, 0x00004016, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(2);
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	write_client_reg(ASY_DATB, 0x00000019, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(2);
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	write_client_reg(ASY_DATB, 0x0000000B, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(2);
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	write_client_reg(ASY_DATB, 0x00000002, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(4);
+	write_client_reg(ASY_DATA, 0x80000010, TRUE);
+	write_client_reg(ASY_DATB, 0x00000300, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(4);
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	write_client_reg(ASY_DATB, 0x00000000, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(2);
+	write_client_reg(ASY_DATA, 0x80000007, TRUE);
+	write_client_reg(ASY_DATB, 0x00004004, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(2);
+	write_client_reg(PORT, 0x00000000, TRUE);
+	write_client_reg(PXL, 0x00000000, TRUE);
+	write_client_reg(START, 0x00000000, TRUE);
+	write_client_reg(VSYNIF, 0x00000001, TRUE);
+	write_client_reg(PORT_ENB, 0x00000001, TRUE);
+	write_client_reg(REGENB, 0x00000001, TRUE);
+	mddi_toshiba_state_transition(TOSHIBA_STATE_SEC_NORMAL_MODE,
+				      TOSHIBA_STATE_PRIM_SEC_STANDBY);
+}
+
+static void toshiba_sec_cont_update_start(struct msm_fb_data_type *mfd)
+{
+
+	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+		return;
+
+	write_client_reg(VSYNIF, 0x00000000, TRUE);
+	write_client_reg(PORT_ENB, 0x00000002, TRUE);
+	write_client_reg(INTMASK, 0x00000001, TRUE);
+	write_client_reg(TTBUSSEL, 0x0000000B, TRUE);
+	write_client_reg(MONI, 0x00000008, TRUE);
+	write_client_reg(CLKENB, 0x000000EF, TRUE);
+	write_client_reg(CLKENB, 0x000010EF, TRUE);
+	write_client_reg(CLKENB, 0x000011EF, TRUE);
+	write_client_reg(BITMAP4, 0x00DC00B0, TRUE);
+	write_client_reg(HCYCLE, 0x0000006B, TRUE);
+	write_client_reg(HSW, 0x00000003, TRUE);
+	write_client_reg(HDE_START, 0x00000002, TRUE);
+	write_client_reg(HDE_SIZE, 0x00000057, TRUE);
+	write_client_reg(VCYCLE, 0x000000E6, TRUE);
+	write_client_reg(VSW, 0x00000001, TRUE);
+	write_client_reg(VDE_START, 0x00000003, TRUE);
+	write_client_reg(VDE_SIZE, 0x000000DB, TRUE);
+	write_client_reg(WRSTB, 0x00000015, TRUE);
+	write_client_reg(MPLFBUF, 0x00000004, TRUE);
+	write_client_reg(ASY_DATA, 0x80000021, TRUE);
+	write_client_reg(ASY_DATB, 0x00000000, TRUE);
+	write_client_reg(ASY_DATC, 0x80000022, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000007, TRUE);
+	write_client_reg(PXL, 0x00000089, TRUE);
+	write_client_reg(VSYNIF, 0x00000001, TRUE);
+	mddi_wait(2);
+}
+
+static void toshiba_sec_cont_update_stop(struct msm_fb_data_type *mfd)
+{
+	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+		return;
+
+	write_client_reg(PXL, 0x00000000, TRUE);
+	write_client_reg(VSYNIF, 0x00000000, TRUE);
+	write_client_reg(START, 0x00000000, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+	mddi_wait(3);
+	write_client_reg(SRST, 0x00000002, TRUE);
+	mddi_wait(3);
+	write_client_reg(SRST, 0x00000003, TRUE);
+}
+
+static void toshiba_sec_backlight_on(struct msm_fb_data_type *mfd)
+{
+	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+		return;
+
+	write_client_reg(TIMER0CTRL, 0x00000060, TRUE);
+	write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+	write_client_reg(PWM0OFF, 0x00000001, TRUE);
+	write_client_reg(TIMER1CTRL, 0x00000060, TRUE);
+	write_client_reg(TIMER1LOAD, 0x00001388, TRUE);
+	write_client_reg(PWM1OFF, 0x00001387, TRUE);
+	write_client_reg(TIMER0CTRL, 0x000000E0, TRUE);
+	write_client_reg(TIMER1CTRL, 0x000000E0, TRUE);
+	write_client_reg(PWMCR, 0x00000003, TRUE);
+}
+
+static void toshiba_sec_sleep_in(struct msm_fb_data_type *mfd)
+{
+	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+		return;
+
+	write_client_reg(VSYNIF, 0x00000000, TRUE);
+	write_client_reg(PORT_ENB, 0x00000002, TRUE);
+	write_client_reg(ASY_DATA, 0x80000007, TRUE);
+	write_client_reg(ASY_DATB, 0x00004016, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(2);
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	write_client_reg(ASY_DATB, 0x00000019, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(2);
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	write_client_reg(ASY_DATB, 0x0000000B, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(2);
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	write_client_reg(ASY_DATB, 0x00000002, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(4);
+	write_client_reg(ASY_DATA, 0x80000010, TRUE);
+	write_client_reg(ASY_DATB, 0x00000300, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(4);
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	write_client_reg(ASY_DATB, 0x00000000, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(2);
+	write_client_reg(ASY_DATA, 0x80000007, TRUE);
+	write_client_reg(ASY_DATB, 0x00004004, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(2);
+	write_client_reg(PORT, 0x00000000, TRUE);
+	write_client_reg(PXL, 0x00000000, TRUE);
+	write_client_reg(START, 0x00000000, TRUE);
+	write_client_reg(REGENB, 0x00000001, TRUE);
+	/* Sleep in sequence */
+	write_client_reg(ASY_DATA, 0x80000010, TRUE);
+	write_client_reg(ASY_DATB, 0x00000302, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+}
+
+static void toshiba_sec_sleep_out(struct msm_fb_data_type *mfd)
+{
+	if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT)
+		return;
+
+	write_client_reg(VSYNIF, 0x00000000, TRUE);
+	write_client_reg(PORT_ENB, 0x00000002, TRUE);
+	write_client_reg(ASY_DATA, 0x80000010, TRUE);
+	write_client_reg(ASY_DATB, 0x00000300, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	/*  Display ON sequence */
+	write_client_reg(ASY_DATA, 0x80000011, TRUE);
+	write_client_reg(ASY_DATB, 0x00000812, TRUE);
+	write_client_reg(ASY_DATC, 0x80000012, TRUE);
+	write_client_reg(ASY_DATD, 0x00000003, TRUE);
+	write_client_reg(ASY_DATE, 0x80000013, TRUE);
+	write_client_reg(ASY_DATF, 0x00000909, TRUE);
+	write_client_reg(ASY_DATG, 0x80000010, TRUE);
+	write_client_reg(ASY_DATH, 0x00000040, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000001, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000000, TRUE);
+	mddi_wait(4);
+	write_client_reg(ASY_DATA, 0x80000010, TRUE);
+	write_client_reg(ASY_DATB, 0x00000340, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(6);
+	write_client_reg(ASY_DATA, 0x80000010, TRUE);
+	write_client_reg(ASY_DATB, 0x00003340, TRUE);
+	write_client_reg(ASY_DATC, 0x80000007, TRUE);
+	write_client_reg(ASY_DATD, 0x00004007, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000009, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000008, TRUE);
+	mddi_wait(1);
+	write_client_reg(ASY_DATA, 0x80000007, TRUE);
+	write_client_reg(ASY_DATB, 0x00004017, TRUE);
+	write_client_reg(ASY_DATC, 0x8000005B, TRUE);
+	write_client_reg(ASY_DATD, 0x00000000, TRUE);
+	write_client_reg(ASY_DATE, 0x80000059, TRUE);
+	write_client_reg(ASY_DATF, 0x00000011, TRUE);
+	write_client_reg(ASY_CMDSET, 0x0000000D, TRUE);
+	write_client_reg(ASY_CMDSET, 0x0000000C, TRUE);
+	mddi_wait(2);
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	write_client_reg(ASY_DATB, 0x00000019, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(2);
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	write_client_reg(ASY_DATB, 0x00000079, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(2);
+	write_client_reg(ASY_DATA, 0x80000059, TRUE);
+	write_client_reg(ASY_DATB, 0x000003FD, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000005, TRUE);
+	write_client_reg(ASY_CMDSET, 0x00000004, TRUE);
+	mddi_wait(2);
+}
+
+static void mddi_toshiba_lcd_set_backlight(struct msm_fb_data_type *mfd)
+{
+	int32 level;
+	int ret = -EPERM;
+	int max = mfd->panel_info.bl_max;
+	int min = mfd->panel_info.bl_min;
+
+	if (mddi_toshiba_pdata && mddi_toshiba_pdata->pmic_backlight) {
+		ret = mddi_toshiba_pdata->pmic_backlight(mfd->bl_level);
+		if (!ret)
+			return;
+	}
+
+	if (ret && mddi_toshiba_pdata && mddi_toshiba_pdata->backlight_level) {
+		level = mddi_toshiba_pdata->backlight_level(mfd->bl_level,
+								max, min);
+
+		if (level < 0)
+			return;
+
+		if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA)
+			write_client_reg(TIMER0LOAD, 0x00001388, TRUE);
+	} else {
+		if (!max)
+			level = 0;
+		else
+			level = (mfd->bl_level * 4999) / max;
+	}
+
+	write_client_reg(PWM0OFF, level, TRUE);
+}
+
+static void mddi_toshiba_vsync_set_handler(msm_fb_vsync_handler_type handler,	/* ISR to be executed */
+					   void *arg)
+{
+	boolean error = FALSE;
+	unsigned long flags;
+
+	/* Disable interrupts */
+	spin_lock_irqsave(&mddi_host_spin_lock, flags);
+	/* INTLOCK(); */
+
+	if (mddi_toshiba_vsync_handler != NULL) {
+		error = TRUE;
+	} else {
+		/* Register the handler for this particular GROUP interrupt source */
+		mddi_toshiba_vsync_handler = handler;
+		mddi_toshiba_vsync_handler_arg = arg;
+	}
+
+	/* Restore interrupts */
+	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+	/* MDDI_INTFREE(); */
+	if (error) {
+		MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n");
+	} else {
+		/* Enable the vsync wakeup */
+		mddi_queue_register_write(INTMSK, 0x0000, FALSE, 0);
+
+		mddi_toshiba_vsync_attempts = 1;
+		mddi_vsync_detect_enabled = TRUE;
+	}
+}				/* mddi_toshiba_vsync_set_handler */
+
+static void mddi_toshiba_lcd_vsync_detected(boolean detected)
+{
+	/* static timetick_type start_time = 0; */
+	static struct timeval start_time;
+	static boolean first_time = TRUE;
+	/* uint32 mdp_cnt_val = 0; */
+	/* timetick_type elapsed_us; */
+	struct timeval now;
+	uint32 elapsed_us;
+	uint32 num_vsyncs;
+
+	if ((detected) || (mddi_toshiba_vsync_attempts > 5)) {
+		if ((detected) && (mddi_toshiba_monitor_refresh_value)) {
+			/* if (start_time != 0) */
+			if (!first_time) {
+				jiffies_to_timeval(jiffies, &now);
+				elapsed_us =
+				    (now.tv_sec - start_time.tv_sec) * 1000000 +
+				    now.tv_usec - start_time.tv_usec;
+				/*
+				 * LCD is configured for a refresh every usecs,
+				 *  so to determine the number of vsyncs that
+				 *  have occurred since the last measurement
+				 *  add half that to the time difference and
+				 *  divide by the refresh rate.
+				 */
+				num_vsyncs = (elapsed_us +
+					      (mddi_toshiba_usecs_per_refresh >>
+					       1)) /
+				    mddi_toshiba_usecs_per_refresh;
+				/*
+				 * LCD is configured for * hsyncs (rows) per
+				 * refresh cycle. Calculate new rows_per_second
+				 * value based upon these new measurements.
+				 * MDP can update with this new value.
+				 */
+				mddi_toshiba_rows_per_second =
+				    (mddi_toshiba_rows_per_refresh * 1000 *
+				     num_vsyncs) / (elapsed_us / 1000);
+			}
+			/* start_time = timetick_get(); */
+			first_time = FALSE;
+			jiffies_to_timeval(jiffies, &start_time);
+			if (mddi_toshiba_report_refresh_measurements) {
+				(void)mddi_queue_register_read_int(VPOS,
+								   &mddi_toshiba_curr_vpos);
+				/* mdp_cnt_val = MDP_LINE_COUNT; */
+			}
+		}
+		/* if detected = TRUE, client initiated wakeup was detected */
+		if (mddi_toshiba_vsync_handler != NULL) {
+			(*mddi_toshiba_vsync_handler)
+			    (mddi_toshiba_vsync_handler_arg);
+			mddi_toshiba_vsync_handler = NULL;
+		}
+		mddi_vsync_detect_enabled = FALSE;
+		mddi_toshiba_vsync_attempts = 0;
+		/* need to disable the interrupt wakeup */
+		if (!mddi_queue_register_write_int(INTMSK, 0x0001))
+			MDDI_MSG_ERR("Vsync interrupt disable failed!\n");
+		if (!detected) {
+			/* give up after 5 failed attempts but show error */
+			MDDI_MSG_NOTICE("Vsync detection failed!\n");
+		} else if ((mddi_toshiba_monitor_refresh_value) &&
+			   (mddi_toshiba_report_refresh_measurements)) {
+			MDDI_MSG_NOTICE("  Last Line Counter=%d!\n",
+					mddi_toshiba_curr_vpos);
+		/* MDDI_MSG_NOTICE("  MDP Line Counter=%d!\n",mdp_cnt_val); */
+			MDDI_MSG_NOTICE("  Lines Per Second=%d!\n",
+					mddi_toshiba_rows_per_second);
+		}
+		/* clear the interrupt */
+		if (!mddi_queue_register_write_int(INTFLG, 0x0001))
+			MDDI_MSG_ERR("Vsync interrupt clear failed!\n");
+	} else {
+		/* if detected = FALSE, we woke up from hibernation, but did not
+		 * detect client initiated wakeup.
+		 */
+		mddi_toshiba_vsync_attempts++;
+	}
+}
+
+static void mddi_toshiba_prim_init(struct msm_fb_data_type *mfd)
+{
+
+	switch (toshiba_state) {
+	case TOSHIBA_STATE_PRIM_SEC_READY:
+		break;
+	case TOSHIBA_STATE_OFF:
+		toshiba_state = TOSHIBA_STATE_PRIM_SEC_STANDBY;
+		toshiba_common_initial_setup(mfd);
+		break;
+	case TOSHIBA_STATE_PRIM_SEC_STANDBY:
+		toshiba_common_initial_setup(mfd);
+		break;
+	case TOSHIBA_STATE_SEC_NORMAL_MODE:
+		toshiba_sec_cont_update_stop(mfd);
+		toshiba_sec_sleep_in(mfd);
+		toshiba_sec_sleep_out(mfd);
+		toshiba_sec_lcd_off(mfd);
+		toshiba_common_initial_setup(mfd);
+		break;
+	default:
+		MDDI_MSG_ERR("mddi_toshiba_prim_init from state %d\n",
+			     toshiba_state);
+	}
+
+	toshiba_prim_start(mfd);
+	if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA)
+		gordon_disp_init();
+	mddi_host_write_pix_attr_reg(0x00C3);
+}
+
+static void mddi_toshiba_sec_init(struct msm_fb_data_type *mfd)
+{
+
+	switch (toshiba_state) {
+	case TOSHIBA_STATE_PRIM_SEC_READY:
+		break;
+	case TOSHIBA_STATE_PRIM_SEC_STANDBY:
+		toshiba_common_initial_setup(mfd);
+		break;
+	case TOSHIBA_STATE_PRIM_NORMAL_MODE:
+		toshiba_prim_lcd_off(mfd);
+		toshiba_common_initial_setup(mfd);
+		break;
+	default:
+		MDDI_MSG_ERR("mddi_toshiba_sec_init from state %d\n",
+			     toshiba_state);
+	}
+
+	toshiba_sec_start(mfd);
+	toshiba_sec_backlight_on(mfd);
+	toshiba_sec_cont_update_start(mfd);
+	mddi_host_write_pix_attr_reg(0x0400);
+}
+
+static void mddi_toshiba_lcd_powerdown(struct msm_fb_data_type *mfd)
+{
+	switch (toshiba_state) {
+	case TOSHIBA_STATE_PRIM_SEC_READY:
+		mddi_toshiba_prim_init(mfd);
+		mddi_toshiba_lcd_powerdown(mfd);
+		return;
+	case TOSHIBA_STATE_PRIM_SEC_STANDBY:
+		break;
+	case TOSHIBA_STATE_PRIM_NORMAL_MODE:
+		toshiba_prim_lcd_off(mfd);
+		break;
+	case TOSHIBA_STATE_SEC_NORMAL_MODE:
+		toshiba_sec_cont_update_stop(mfd);
+		toshiba_sec_sleep_in(mfd);
+		toshiba_sec_sleep_out(mfd);
+		toshiba_sec_lcd_off(mfd);
+		break;
+	default:
+		MDDI_MSG_ERR("mddi_toshiba_lcd_powerdown from state %d\n",
+			     toshiba_state);
+	}
+}
+
+static int mddi_sharpgordon_firsttime = 1;
+
+static int mddi_toshiba_lcd_on(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+	mfd = platform_get_drvdata(pdev);
+	if (!mfd)
+		return -ENODEV;
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (TM_GET_DID(mfd->panel.id) == TOSHIBA_VGA_PRIM)
+		mddi_toshiba_prim_init(mfd);
+	else
+		mddi_toshiba_sec_init(mfd);
+	if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) {
+		if (mddi_sharpgordon_firsttime) {
+			mddi_sharpgordon_firsttime = 0;
+			write_client_reg(REGENB, 0x00000001, TRUE);
+		}
+	}
+	return 0;
+}
+
+static int mddi_toshiba_lcd_off(struct platform_device *pdev)
+{
+	mddi_toshiba_lcd_powerdown(platform_get_drvdata(pdev));
+	return 0;
+}
+
+static int __init mddi_toshiba_lcd_probe(struct platform_device *pdev)
+{
+	if (pdev->id == 0) {
+		mddi_toshiba_pdata = pdev->dev.platform_data;
+		return 0;
+	}
+
+	msm_fb_add_device(pdev);
+
+	return 0;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = mddi_toshiba_lcd_probe,
+	.driver = {
+		.name   = "mddi_toshiba",
+	},
+};
+
+static struct msm_fb_panel_data toshiba_panel_data = {
+	.on 		= mddi_toshiba_lcd_on,
+	.off 		= mddi_toshiba_lcd_off,
+};
+
+static int ch_used[3];
+
+int mddi_toshiba_device_register(struct msm_panel_info *pinfo,
+					u32 channel, u32 panel)
+{
+	struct platform_device *pdev = NULL;
+	int ret;
+
+	if ((channel >= 3) || ch_used[channel])
+		return -ENODEV;
+
+	if ((channel != TOSHIBA_VGA_PRIM) &&
+	    mddi_toshiba_pdata && mddi_toshiba_pdata->panel_num)
+		if (mddi_toshiba_pdata->panel_num() < 2)
+			return -ENODEV;
+
+	ch_used[channel] = TRUE;
+
+	pdev = platform_device_alloc("mddi_toshiba", (panel << 8)|channel);
+	if (!pdev)
+		return -ENOMEM;
+
+	if (channel == TOSHIBA_VGA_PRIM) {
+		toshiba_panel_data.set_backlight =
+				mddi_toshiba_lcd_set_backlight;
+
+		if (pinfo->lcd.vsync_enable) {
+			toshiba_panel_data.set_vsync_notifier =
+				mddi_toshiba_vsync_set_handler;
+			mddi_lcd.vsync_detected =
+				mddi_toshiba_lcd_vsync_detected;
+		}
+	} else {
+		toshiba_panel_data.set_backlight = NULL;
+		toshiba_panel_data.set_vsync_notifier = NULL;
+	}
+
+	toshiba_panel_data.panel_info = *pinfo;
+
+	ret = platform_device_add_data(pdev, &toshiba_panel_data,
+		sizeof(toshiba_panel_data));
+	if (ret) {
+		printk(KERN_ERR
+		  "%s: platform_device_add_data failed!\n", __func__);
+		goto err_device_put;
+	}
+
+	ret = platform_device_add(pdev);
+	if (ret) {
+		printk(KERN_ERR
+		  "%s: platform_device_register failed!\n", __func__);
+		goto err_device_put;
+	}
+
+	return 0;
+
+err_device_put:
+	platform_device_put(pdev);
+	return ret;
+}
+
+static int __init mddi_toshiba_lcd_init(void)
+{
+	return platform_driver_register(&this_driver);
+}
+
+module_init(mddi_toshiba_lcd_init);

+ 52 - 0
drivers/staging/msm/mddi_toshiba.h

@@ -0,0 +1,52 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MDDI_TOSHIBA_H
+#define MDDI_TOSHIBA_H
+
+#define TOSHIBA_VGA_PRIM 1
+#define TOSHIBA_VGA_SECD 2
+
+#define LCD_TOSHIBA_2P4_VGA 	0
+#define LCD_TOSHIBA_2P4_WVGA 	1
+#define LCD_TOSHIBA_2P4_WVGA_PT	2
+#define LCD_SHARP_2P4_VGA 	3
+
+#define GPIO_BLOCK_BASE        0x150000
+#define SYSTEM_BLOCK2_BASE     0x170000
+
+#define GPIODIR     (GPIO_BLOCK_BASE|0x04)
+#define GPIOSEL     (SYSTEM_BLOCK2_BASE|0x00)
+#define GPIOPC      (GPIO_BLOCK_BASE|0x28)
+#define GPIODATA    (GPIO_BLOCK_BASE|0x00)
+
+#define write_client_reg(__X, __Y, __Z) {\
+  mddi_queue_register_write(__X, __Y, TRUE, 0);\
+}
+
+#endif /* MDDI_TOSHIBA_H */

+ 136 - 0
drivers/staging/msm/mddi_toshiba_vga.c

@@ -0,0 +1,136 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+#include "mddi_toshiba.h"
+
+static uint32 read_client_reg(uint32 addr)
+{
+	uint32 val;
+	mddi_queue_register_read(addr, &val, TRUE, 0);
+	return val;
+}
+
+static uint32 toshiba_lcd_gpio_read(void)
+{
+	uint32 val;
+
+	write_client_reg(GPIODIR, 0x0000000C, TRUE);
+	write_client_reg(GPIOSEL, 0x00000000, TRUE);
+	write_client_reg(GPIOSEL, 0x00000000, TRUE);
+	write_client_reg(GPIOPC, 0x03CF00C0, TRUE);
+	val = read_client_reg(GPIODATA) & 0x2C0;
+
+	return val;
+}
+
+static u32 mddi_toshiba_panel_detect(void)
+{
+	mddi_host_type host_idx = MDDI_HOST_PRIM;
+	uint32 lcd_gpio;
+	u32 mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA;
+
+	/* Toshiba display requires larger drive_lo value */
+	mddi_host_reg_out(DRIVE_LO, 0x0050);
+
+	lcd_gpio = toshiba_lcd_gpio_read();
+	switch (lcd_gpio) {
+	case 0x0080:
+		mddi_toshiba_lcd = LCD_SHARP_2P4_VGA;
+		break;
+
+	case 0x00C0:
+	default:
+		mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA;
+		break;
+	}
+
+	return mddi_toshiba_lcd;
+}
+
+static int __init mddi_toshiba_vga_init(void)
+{
+	int ret;
+	struct msm_panel_info pinfo;
+	u32 panel;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+	u32 id;
+
+	ret = msm_fb_detect_client("mddi_toshiba_vga");
+	if (ret == -ENODEV)
+		return 0;
+
+	if (ret) {
+		id = mddi_get_client_id();
+		if ((id >> 16) != 0xD263)
+			return 0;
+	}
+#endif
+
+	panel = mddi_toshiba_panel_detect();
+
+	pinfo.xres = 480;
+	pinfo.yres = 640;
+	pinfo.type = MDDI_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 18;
+	pinfo.lcd.vsync_enable = TRUE;
+	pinfo.lcd.refx100 = 6118;
+	pinfo.lcd.v_back_porch = 6;
+	pinfo.lcd.v_front_porch = 0;
+	pinfo.lcd.v_pulse_width = 0;
+	pinfo.lcd.hw_vsync_mode = FALSE;
+	pinfo.lcd.vsync_notifier_period = (1 * HZ);
+	pinfo.bl_max = 99;
+	pinfo.bl_min = 1;
+	pinfo.clk_rate = 122880000;
+	pinfo.clk_min =  120000000;
+	pinfo.clk_max =  200000000;
+	pinfo.fb_num = 2;
+
+	ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM, panel);
+	if (ret) {
+		printk(KERN_ERR "%s: failed to register device!\n", __func__);
+		return ret;
+	}
+
+	pinfo.xres = 176;
+	pinfo.yres = 220;
+	pinfo.type = MDDI_PANEL;
+	pinfo.pdest = DISPLAY_2;
+	pinfo.mddi.vdopkt = 0x400;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 18;
+	pinfo.clk_rate = 122880000;
+	pinfo.clk_min =  120000000;
+	pinfo.clk_max =  200000000;
+	pinfo.fb_num = 2;
+
+	ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_SECD, panel);
+	if (ret)
+		printk(KERN_WARNING
+			"%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(mddi_toshiba_vga_init);

+ 63 - 0
drivers/staging/msm/mddi_toshiba_wvga.c

@@ -0,0 +1,63 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddi_toshiba.h"
+
+static int __init mddi_toshiba_wvga_init(void)
+{
+	int ret;
+	struct msm_panel_info pinfo;
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+	if (msm_fb_detect_client("mddi_toshiba_wvga"))
+		return 0;
+#endif
+
+	pinfo.xres = 800;
+	pinfo.yres = 480;
+	pinfo.pdest = DISPLAY_2;
+	pinfo.type = MDDI_PANEL;
+	pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 18;
+	pinfo.lcd.vsync_enable = TRUE;
+	pinfo.lcd.refx100 = 6118;
+	pinfo.lcd.v_back_porch = 6;
+	pinfo.lcd.v_front_porch = 0;
+	pinfo.lcd.v_pulse_width = 0;
+	pinfo.lcd.hw_vsync_mode = FALSE;
+	pinfo.lcd.vsync_notifier_period = (1 * HZ);
+	pinfo.bl_max = 4;
+	pinfo.bl_min = 1;
+	pinfo.clk_rate = 192000000;
+	pinfo.clk_min =  190000000;
+	pinfo.clk_max =  200000000;
+	pinfo.fb_num = 2;
+
+	ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM,
+					   LCD_TOSHIBA_2P4_WVGA);
+	if (ret) {
+		printk(KERN_ERR "%s: failed to register device!\n", __func__);
+		return ret;
+	}
+
+	return ret;
+}
+
+module_init(mddi_toshiba_wvga_init);

+ 64 - 0
drivers/staging/msm/mddi_toshiba_wvga_pt.c

@@ -0,0 +1,64 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+#include "mddi_toshiba.h"
+
+static int __init mddi_toshiba_wvga_pt_init(void)
+{
+	int ret;
+	struct msm_panel_info pinfo;
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+	uint id;
+
+	ret = msm_fb_detect_client("mddi_toshiba_wvga_pt");
+	if (ret == -ENODEV)
+		return 0;
+
+	if (ret) {
+		id = mddi_get_client_id();
+		if (id != 0xd2638722)
+			return 0;
+	}
+#endif
+
+	pinfo.xres = 480;
+	pinfo.yres = 800;
+	pinfo.type = MDDI_PANEL;
+	pinfo.pdest = DISPLAY_1;
+	pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR;
+	pinfo.wait_cycle = 0;
+	pinfo.bpp = 18;
+	pinfo.lcd.vsync_enable = FALSE;
+	pinfo.bl_max = 15;
+	pinfo.bl_min = 1;
+	pinfo.clk_rate = 192000000;
+	pinfo.clk_min =  190000000;
+	pinfo.clk_max =  200000000;
+	pinfo.fb_num = 2;
+
+	ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM,
+						LCD_TOSHIBA_2P4_WVGA_PT);
+	if (ret)
+		printk(KERN_ERR "%s: failed to register device!\n", __func__);
+
+	return ret;
+}
+
+module_init(mddi_toshiba_wvga_pt_init);

+ 377 - 0
drivers/staging/msm/mddihost.c

@@ -0,0 +1,377 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#include <linux/clk.h>
+#include <mach/clk.h>
+
+struct semaphore mddi_host_mutex;
+
+struct clk *mddi_io_clk;
+static boolean mddi_host_powered = FALSE;
+static boolean mddi_host_initialized = FALSE;
+extern uint32 *mddi_reg_read_value_ptr;
+
+mddi_lcd_func_type mddi_lcd;
+
+extern mddi_client_capability_type mddi_client_capability_pkt;
+
+#ifdef FEATURE_MDDI_HITACHI
+extern void mddi_hitachi_window_adjust(uint16 x1,
+				       uint16 x2, uint16 y1, uint16 y2);
+#endif
+
+extern void mddi_toshiba_lcd_init(void);
+
+#ifdef FEATURE_MDDI_S6D0142
+extern void mddi_s6d0142_lcd_init(void);
+extern void mddi_s6d0142_window_adjust(uint16 x1,
+				       uint16 x2,
+				       uint16 y1,
+				       uint16 y2,
+				       mddi_llist_done_cb_type done_cb);
+#endif
+
+void mddi_init(void)
+{
+	if (mddi_host_initialized)
+		return;
+
+	mddi_host_initialized = TRUE;
+
+	init_MUTEX(&mddi_host_mutex);
+
+	if (!mddi_host_powered) {
+		down(&mddi_host_mutex);
+		mddi_host_init(MDDI_HOST_PRIM);
+		mddi_host_powered = TRUE;
+		up(&mddi_host_mutex);
+		mdelay(10);
+	}
+}
+
+int mddi_host_register_read(uint32 reg_addr,
+     uint32 *reg_value_ptr, boolean wait, mddi_host_type host) {
+	mddi_linked_list_type *curr_llist_ptr;
+	mddi_register_access_packet_type *regacc_pkt_ptr;
+	uint16 curr_llist_idx;
+	int ret = 0;
+
+	if (in_interrupt())
+		MDDI_MSG_CRIT("Called from ISR context\n");
+
+	if (!mddi_host_powered) {
+		MDDI_MSG_ERR("MDDI powered down!\n");
+		mddi_init();
+	}
+
+	down(&mddi_host_mutex);
+
+	mddi_reg_read_value_ptr = reg_value_ptr;
+	curr_llist_idx = mddi_get_reg_read_llist_item(host, TRUE);
+	if (curr_llist_idx == UNASSIGNED_INDEX) {
+		up(&mddi_host_mutex);
+
+		/* need to change this to some sort of wait */
+		MDDI_MSG_ERR("Attempting to queue up more than 1 reg read\n");
+		return -EINVAL;
+	}
+
+	curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+	curr_llist_ptr->link_controller_flags = 0x11;
+	curr_llist_ptr->packet_header_count = 14;
+	curr_llist_ptr->packet_data_count = 0;
+
+	curr_llist_ptr->next_packet_pointer = NULL;
+	curr_llist_ptr->packet_data_pointer = NULL;
+	curr_llist_ptr->reserved = 0;
+
+	regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+	regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count;
+	regacc_pkt_ptr->packet_type = 146;	/* register access packet */
+	regacc_pkt_ptr->bClient_ID = 0;
+	regacc_pkt_ptr->read_write_info = 0x8001;
+	regacc_pkt_ptr->register_address = reg_addr;
+
+	/* now adjust pointers */
+	mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
+				   NULL, host);
+	/* need to check if we can write the pointer or not */
+
+	up(&mddi_host_mutex);
+
+	if (wait) {
+		int wait_ret;
+
+		mddi_linked_list_notify_type *llist_notify_ptr;
+		llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
+		wait_ret = wait_for_completion_timeout(
+					&(llist_notify_ptr->done_comp), 5 * HZ);
+
+		if (wait_ret <= 0)
+			ret = -EBUSY;
+
+		if (wait_ret < 0)
+			printk(KERN_ERR "%s: failed to wait for completion!\n",
+				__func__);
+		else if (!wait_ret)
+			printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
+	}
+
+	MDDI_MSG_DEBUG("Reg Read value=0x%x\n", *reg_value_ptr);
+
+	return ret;
+}				/* mddi_host_register_read */
+
+int mddi_host_register_write(uint32 reg_addr,
+     uint32 reg_val, enum mddi_data_packet_size_type packet_size,
+     boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host) {
+	mddi_linked_list_type *curr_llist_ptr;
+	mddi_linked_list_type *curr_llist_dma_ptr;
+	mddi_register_access_packet_type *regacc_pkt_ptr;
+	uint16 curr_llist_idx;
+	int ret = 0;
+
+	if (in_interrupt())
+		MDDI_MSG_CRIT("Called from ISR context\n");
+
+	if (!mddi_host_powered) {
+		MDDI_MSG_ERR("MDDI powered down!\n");
+		mddi_init();
+	}
+
+	down(&mddi_host_mutex);
+
+	curr_llist_idx = mddi_get_next_free_llist_item(host, TRUE);
+	curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+	curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx];
+
+	curr_llist_ptr->link_controller_flags = 1;
+	curr_llist_ptr->packet_header_count = 14;
+	curr_llist_ptr->packet_data_count = 4;
+
+	curr_llist_ptr->next_packet_pointer = NULL;
+	curr_llist_ptr->reserved = 0;
+
+	regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+	regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count +
+					(uint16)packet_size;
+	regacc_pkt_ptr->packet_type = 146;	/* register access packet */
+	regacc_pkt_ptr->bClient_ID = 0;
+	regacc_pkt_ptr->read_write_info = 0x0001;
+	regacc_pkt_ptr->register_address = reg_addr;
+	regacc_pkt_ptr->register_data_list = reg_val;
+
+	MDDI_MSG_DEBUG("Reg Access write reg=0x%x, value=0x%x\n",
+		       regacc_pkt_ptr->register_address,
+		       regacc_pkt_ptr->register_data_list);
+
+	regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt;
+	curr_llist_ptr->packet_data_pointer =
+	    (void *)(&regacc_pkt_ptr->register_data_list);
+
+	/* now adjust pointers */
+	mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait,
+				   done_cb, host);
+
+	up(&mddi_host_mutex);
+
+	if (wait) {
+		int wait_ret;
+
+		mddi_linked_list_notify_type *llist_notify_ptr;
+		llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx];
+		wait_ret = wait_for_completion_timeout(
+					&(llist_notify_ptr->done_comp), 5 * HZ);
+
+		if (wait_ret <= 0)
+			ret = -EBUSY;
+
+		if (wait_ret < 0)
+			printk(KERN_ERR "%s: failed to wait for completion!\n",
+				__func__);
+		else if (!wait_ret)
+			printk(KERN_ERR "%s: Timed out waiting!\n", __func__);
+	}
+
+	return ret;
+}				/* mddi_host_register_write */
+
+boolean mddi_host_register_read_int
+    (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host) {
+	mddi_linked_list_type *curr_llist_ptr;
+	mddi_register_access_packet_type *regacc_pkt_ptr;
+	uint16 curr_llist_idx;
+
+	if (!in_interrupt())
+		MDDI_MSG_CRIT("Called from TASK context\n");
+
+	if (!mddi_host_powered) {
+		MDDI_MSG_ERR("MDDI powered down!\n");
+		return FALSE;
+	}
+
+	if (down_trylock(&mddi_host_mutex) != 0)
+		return FALSE;
+
+	mddi_reg_read_value_ptr = reg_value_ptr;
+	curr_llist_idx = mddi_get_reg_read_llist_item(host, FALSE);
+	if (curr_llist_idx == UNASSIGNED_INDEX) {
+		up(&mddi_host_mutex);
+		return FALSE;
+	}
+
+	curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+	curr_llist_ptr->link_controller_flags = 0x11;
+	curr_llist_ptr->packet_header_count = 14;
+	curr_llist_ptr->packet_data_count = 0;
+
+	curr_llist_ptr->next_packet_pointer = NULL;
+	curr_llist_ptr->packet_data_pointer = NULL;
+	curr_llist_ptr->reserved = 0;
+
+	regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+	regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count;
+	regacc_pkt_ptr->packet_type = 146;	/* register access packet */
+	regacc_pkt_ptr->bClient_ID = 0;
+	regacc_pkt_ptr->read_write_info = 0x8001;
+	regacc_pkt_ptr->register_address = reg_addr;
+
+	/* now adjust pointers */
+	mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE,
+				   NULL, host);
+	/* need to check if we can write the pointer or not */
+
+	up(&mddi_host_mutex);
+
+	return TRUE;
+
+}				/* mddi_host_register_read */
+
+boolean mddi_host_register_write_int
+    (uint32 reg_addr,
+     uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host) {
+	mddi_linked_list_type *curr_llist_ptr;
+	mddi_linked_list_type *curr_llist_dma_ptr;
+	mddi_register_access_packet_type *regacc_pkt_ptr;
+	uint16 curr_llist_idx;
+
+	if (!in_interrupt())
+		MDDI_MSG_CRIT("Called from TASK context\n");
+
+	if (!mddi_host_powered) {
+		MDDI_MSG_ERR("MDDI powered down!\n");
+		return FALSE;
+	}
+
+	if (down_trylock(&mddi_host_mutex) != 0)
+		return FALSE;
+
+	curr_llist_idx = mddi_get_next_free_llist_item(host, FALSE);
+	if (curr_llist_idx == UNASSIGNED_INDEX) {
+		up(&mddi_host_mutex);
+		return FALSE;
+	}
+
+	curr_llist_ptr = &llist_extern[host][curr_llist_idx];
+	curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx];
+
+	curr_llist_ptr->link_controller_flags = 1;
+	curr_llist_ptr->packet_header_count = 14;
+	curr_llist_ptr->packet_data_count = 4;
+
+	curr_llist_ptr->next_packet_pointer = NULL;
+	curr_llist_ptr->reserved = 0;
+
+	regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt;
+
+	regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count + 4;
+	regacc_pkt_ptr->packet_type = 146;	/* register access packet */
+	regacc_pkt_ptr->bClient_ID = 0;
+	regacc_pkt_ptr->read_write_info = 0x0001;
+	regacc_pkt_ptr->register_address = reg_addr;
+	regacc_pkt_ptr->register_data_list = reg_val;
+
+	regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt;
+	curr_llist_ptr->packet_data_pointer =
+	    (void *)(&(regacc_pkt_ptr->register_data_list));
+
+	/* now adjust pointers */
+	mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE,
+				   done_cb, host);
+	up(&mddi_host_mutex);
+
+	return TRUE;
+
+}				/* mddi_host_register_write */
+
+void mddi_wait(uint16 time_ms)
+{
+	mdelay(time_ms);
+}
+
+void mddi_client_lcd_vsync_detected(boolean detected)
+{
+	if (mddi_lcd.vsync_detected)
+		(*mddi_lcd.vsync_detected) (detected);
+}
+
+/* extended version of function includes done callback */
+void mddi_window_adjust_ext(struct msm_fb_data_type *mfd,
+			    uint16 x1,
+			    uint16 x2,
+			    uint16 y1,
+			    uint16 y2, mddi_llist_done_cb_type done_cb)
+{
+#ifdef FEATURE_MDDI_HITACHI
+	if (mfd->panel.id == HITACHI)
+		mddi_hitachi_window_adjust(x1, x2, y1, y2);
+#elif defined(FEATURE_MDDI_S6D0142)
+	if (mfd->panel.id == MDDI_LCD_S6D0142)
+		mddi_s6d0142_window_adjust(x1, x2, y1, y2, done_cb);
+#else
+	/* Do nothing then... except avoid lint/compiler warnings */
+	(void)x1;
+	(void)x2;
+	(void)y1;
+	(void)y2;
+	(void)done_cb;
+#endif
+}
+
+void mddi_window_adjust(struct msm_fb_data_type *mfd,
+			uint16 x1, uint16 x2, uint16 y1, uint16 y2)
+{
+	mddi_window_adjust_ext(mfd, x1, x2, y1, y2, NULL);
+}

+ 225 - 0
drivers/staging/msm/mddihost.h

@@ -0,0 +1,225 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MDDIHOST_H
+#define MDDIHOST_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb_panel.h"
+
+#undef FEATURE_MDDI_MC4
+#undef FEATURE_MDDI_S6D0142
+#undef FEATURE_MDDI_HITACHI
+#define FEATURE_MDDI_SHARP
+#define FEATURE_MDDI_TOSHIBA
+#undef FEATURE_MDDI_E751
+#define FEATURE_MDDI_CORONA
+#define FEATURE_MDDI_PRISM
+
+#define T_MSM7500
+
+typedef enum {
+	format_16bpp,
+	format_18bpp,
+	format_24bpp
+} mddi_video_format;
+
+typedef enum {
+	MDDI_LCD_NONE = 0,
+	MDDI_LCD_MC4,
+	MDDI_LCD_S6D0142,
+	MDDI_LCD_SHARP,
+	MDDI_LCD_E751,
+	MDDI_LCD_CORONA,
+	MDDI_LCD_HITACHI,
+	MDDI_LCD_TOSHIBA,
+	MDDI_LCD_PRISM,
+	MDDI_LCD_TP2,
+	MDDI_NUM_LCD_TYPES,
+	MDDI_LCD_DEFAULT = MDDI_LCD_TOSHIBA
+} mddi_lcd_type;
+
+typedef enum {
+	MDDI_HOST_PRIM = 0,
+	MDDI_HOST_EXT,
+	MDDI_NUM_HOST_CORES
+} mddi_host_type;
+
+typedef enum {
+	MDDI_DRIVER_RESET,	/* host core registers have not been written. */
+	MDDI_DRIVER_DISABLED,	/* registers written, interrupts disabled. */
+	MDDI_DRIVER_ENABLED	/* registers written, interrupts enabled. */
+} mddi_host_driver_state_type;
+
+typedef enum {
+	MDDI_GPIO_INT_0 = 0,
+	MDDI_GPIO_INT_1,
+	MDDI_GPIO_INT_2,
+	MDDI_GPIO_INT_3,
+	MDDI_GPIO_INT_4,
+	MDDI_GPIO_INT_5,
+	MDDI_GPIO_INT_6,
+	MDDI_GPIO_INT_7,
+	MDDI_GPIO_INT_8,
+	MDDI_GPIO_INT_9,
+	MDDI_GPIO_INT_10,
+	MDDI_GPIO_INT_11,
+	MDDI_GPIO_INT_12,
+	MDDI_GPIO_INT_13,
+	MDDI_GPIO_INT_14,
+	MDDI_GPIO_INT_15,
+	MDDI_GPIO_NUM_INTS
+} mddi_gpio_int_type;
+
+enum mddi_data_packet_size_type {
+	MDDI_DATA_PACKET_4_BYTES  = 4,
+	MDDI_DATA_PACKET_8_BYTES  = 8,
+	MDDI_DATA_PACKET_12_BYTES = 12,
+	MDDI_DATA_PACKET_16_BYTES = 16,
+	MDDI_DATA_PACKET_24_BYTES = 24
+};
+
+typedef struct {
+	uint32 addr;
+	uint32 value;
+} mddi_reg_write_type;
+
+boolean mddi_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg);
+
+typedef void (*mddi_llist_done_cb_type) (void);
+
+typedef void (*mddi_rev_handler_type) (void *);
+
+boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type);
+
+#define MDDI_DEFAULT_PRIM_PIX_ATTR 0xC3
+#define MDDI_DEFAULT_SECD_PIX_ATTR 0xC0
+
+typedef int gpio_int_polarity_type;
+typedef int gpio_int_handler_type;
+
+typedef struct {
+	void (*vsync_detected) (boolean);
+} mddi_lcd_func_type;
+
+extern mddi_lcd_func_type mddi_lcd;
+void mddi_init(void);
+
+void mddi_powerdown(void);
+
+void mddi_host_start_ext_display(void);
+void mddi_host_stop_ext_display(void);
+
+extern spinlock_t mddi_host_spin_lock;
+#ifdef T_MSM7500
+void mddi_reset(void);
+#ifdef FEATURE_DUAL_PROC_MODEM_DISPLAY
+void mddi_host_switch_proc_control(boolean on);
+#endif
+#endif
+void mddi_host_exit_power_collapse(void);
+
+void mddi_queue_splash_screen
+    (void *buf_ptr,
+     boolean clear_area,
+     int16 src_width,
+     int16 src_starting_row,
+     int16 src_starting_column,
+     int16 num_of_rows,
+     int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column);
+
+void mddi_queue_image
+    (void *buf_ptr,
+     uint8 stereo_video,
+     boolean clear_area,
+     int16 src_width,
+     int16 src_starting_row,
+     int16 src_starting_column,
+     int16 num_of_rows,
+     int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column);
+
+int mddi_host_register_read
+    (uint32 reg_addr,
+     uint32 *reg_value_ptr, boolean wait, mddi_host_type host_idx);
+int mddi_host_register_write
+    (uint32 reg_addr, uint32 reg_val,
+     enum mddi_data_packet_size_type packet_size,
+     boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host);
+boolean mddi_host_register_write_int
+    (uint32 reg_addr,
+     uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host);
+boolean mddi_host_register_read_int
+    (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host_idx);
+void mddi_queue_register_write_static
+    (uint32 reg_addr,
+     uint32 reg_val, boolean wait, mddi_llist_done_cb_type done_cb);
+void mddi_queue_static_window_adjust
+    (const mddi_reg_write_type *reg_write,
+     uint16 num_writes, mddi_llist_done_cb_type done_cb);
+
+#define mddi_queue_register_read(reg, val_ptr, wait, sig) \
+	mddi_host_register_read(reg, val_ptr, wait, MDDI_HOST_PRIM)
+#define mddi_queue_register_write(reg, val, wait, sig) \
+	mddi_host_register_write(reg, val, MDDI_DATA_PACKET_4_BYTES,\
+	wait, NULL, MDDI_HOST_PRIM)
+#define mddi_queue_register_write_extn(reg, val, pkt_size, wait, sig) \
+	mddi_host_register_write(reg, val, pkt_size, \
+	wait, NULL, MDDI_HOST_PRIM)
+#define mddi_queue_register_write_int(reg, val) \
+	mddi_host_register_write_int(reg, val, NULL, MDDI_HOST_PRIM)
+#define mddi_queue_register_read_int(reg, val_ptr) \
+	mddi_host_register_read_int(reg, val_ptr, MDDI_HOST_PRIM)
+#define mddi_queue_register_writes(reg_ptr, val, wait, sig) \
+	mddi_host_register_writes(reg_ptr, val, wait, sig, MDDI_HOST_PRIM)
+
+void mddi_wait(uint16 time_ms);
+void mddi_assign_max_pkt_dimensions(uint16 image_cols,
+				    uint16 image_rows,
+				    uint16 bpp,
+				    uint16 *max_cols, uint16 * max_rows);
+uint16 mddi_assign_pkt_height(uint16 pkt_width, uint16 pkt_height, uint16 bpp);
+void mddi_queue_reverse_encapsulation(boolean wait);
+void mddi_disable(int lock);
+#endif /* MDDIHOST_H */

+ 63 - 0
drivers/staging/msm/mddihost_e.c

@@ -0,0 +1,63 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#include <linux/clk.h>
+#include <mach/clk.h>
+
+extern struct semaphore mddi_host_mutex;
+static boolean mddi_host_ext_powered = FALSE;
+
+void mddi_host_start_ext_display(void)
+{
+	down(&mddi_host_mutex);
+
+	if (!mddi_host_ext_powered) {
+		mddi_host_init(MDDI_HOST_EXT);
+
+		mddi_host_ext_powered = TRUE;
+	}
+
+	up(&mddi_host_mutex);
+}
+
+void mddi_host_stop_ext_display(void)
+{
+	down(&mddi_host_mutex);
+
+	if (mddi_host_ext_powered) {
+		mddi_host_powerdown(MDDI_HOST_EXT);
+
+		mddi_host_ext_powered = FALSE;
+	}
+
+	up(&mddi_host_mutex);
+}

+ 2239 - 0
drivers/staging/msm/mddihosti.c

@@ -0,0 +1,2239 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include "msm_fb_panel.h"
+#include "mddihost.h"
+#include "mddihosti.h"
+
+#define FEATURE_MDDI_UNDERRUN_RECOVERY
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+static void mddi_read_rev_packet(byte *data_ptr);
+#endif
+
+struct timer_list mddi_host_timer;
+
+#define MDDI_DEFAULT_TIMER_LENGTH 5000	/* 5 seconds */
+uint32 mddi_rtd_frequency = 60000;	/* send RTD every 60 seconds */
+uint32 mddi_client_status_frequency = 60000;	/* get status pkt every 60 secs */
+
+boolean mddi_vsync_detect_enabled = FALSE;
+mddi_gpio_info_type mddi_gpio;
+
+uint32 mddi_host_core_version;
+boolean mddi_debug_log_statistics = FALSE;
+/* #define FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION */
+/* default to TRUE in case MDP does not vote */
+static boolean mddi_host_mdp_active_flag = TRUE;
+static uint32 mddi_log_stats_counter;
+uint32 mddi_log_stats_frequency = 4000;
+
+#define MDDI_DEFAULT_REV_PKT_SIZE            0x20
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+static boolean mddi_rev_ptr_workaround = TRUE;
+static uint32 mddi_reg_read_retry;
+static uint32 mddi_reg_read_retry_max = 20;
+static boolean mddi_enable_reg_read_retry = TRUE;
+static boolean mddi_enable_reg_read_retry_once = FALSE;
+
+#define MDDI_MAX_REV_PKT_SIZE                0x60
+
+#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE  0x60
+
+#define MDDI_VIDEO_REV_PKT_SIZE              0x40
+#define MDDI_REV_BUFFER_SIZE  MDDI_MAX_REV_PKT_SIZE
+static byte rev_packet_data[MDDI_MAX_REV_PKT_SIZE];
+#endif /* FEATURE_MDDI_DISABLE_REVERSE */
+/* leave these variables so graphics will compile */
+
+#define MDDI_MAX_REV_DATA_SIZE  128
+/*lint -d__align(x) */
+boolean mddi_debug_clear_rev_data = TRUE;
+
+uint32 *mddi_reg_read_value_ptr;
+
+mddi_client_capability_type mddi_client_capability_pkt;
+static boolean mddi_client_capability_request = FALSE;
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+
+#define MAX_MDDI_REV_HANDLERS 2
+#define INVALID_PKT_TYPE 0xFFFF
+
+typedef struct {
+	mddi_rev_handler_type handler;	/* ISR to be executed */
+	uint16 pkt_type;
+} mddi_rev_pkt_handler_type;
+static mddi_rev_pkt_handler_type mddi_rev_pkt_handler[MAX_MDDI_REV_HANDLERS] =
+    { {NULL, INVALID_PKT_TYPE}, {NULL, INVALID_PKT_TYPE} };
+
+static boolean mddi_rev_encap_user_request = FALSE;
+static mddi_linked_list_notify_type mddi_rev_user;
+
+spinlock_t mddi_host_spin_lock;
+extern uint32 mdp_in_processing;
+#endif
+
+typedef enum {
+	MDDI_REV_IDLE
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+	    , MDDI_REV_REG_READ_ISSUED,
+	MDDI_REV_REG_READ_SENT,
+	MDDI_REV_ENCAP_ISSUED,
+	MDDI_REV_STATUS_REQ_ISSUED,
+	MDDI_REV_CLIENT_CAP_ISSUED
+#endif
+} mddi_rev_link_state_type;
+
+typedef enum {
+	MDDI_LINK_DISABLED,
+	MDDI_LINK_HIBERNATING,
+	MDDI_LINK_ACTIVATING,
+	MDDI_LINK_ACTIVE
+} mddi_host_link_state_type;
+
+typedef struct {
+	uint32 count;
+	uint32 in_count;
+	uint32 disp_req_count;
+	uint32 state_change_count;
+	uint32 ll_done_count;
+	uint32 rev_avail_count;
+	uint32 error_count;
+	uint32 rev_encap_count;
+	uint32 llist_ptr_write_1;
+	uint32 llist_ptr_write_2;
+} mddi_host_int_type;
+
+typedef struct {
+	uint32 fwd_crc_count;
+	uint32 rev_crc_count;
+	uint32 pri_underflow;
+	uint32 sec_underflow;
+	uint32 rev_overflow;
+	uint32 pri_overwrite;
+	uint32 sec_overwrite;
+	uint32 rev_overwrite;
+	uint32 dma_failure;
+	uint32 rtd_failure;
+	uint32 reg_read_failure;
+#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
+	uint32 pri_underrun_detected;
+#endif
+} mddi_host_stat_type;
+
+typedef struct {
+	uint32 rtd_cnt;
+	uint32 rev_enc_cnt;
+	uint32 vid_cnt;
+	uint32 reg_acc_cnt;
+	uint32 cli_stat_cnt;
+	uint32 cli_cap_cnt;
+	uint32 reg_read_cnt;
+	uint32 link_active_cnt;
+	uint32 link_hibernate_cnt;
+	uint32 vsync_response_cnt;
+	uint32 fwd_crc_cnt;
+	uint32 rev_crc_cnt;
+} mddi_log_params_struct_type;
+
+typedef struct {
+	uint32 rtd_value;
+	uint32 rtd_counter;
+	uint32 client_status_cnt;
+	boolean rev_ptr_written;
+	uint8 *rev_ptr_start;
+	uint8 *rev_ptr_curr;
+	uint32 mddi_rev_ptr_write_val;
+	dma_addr_t rev_data_dma_addr;
+	uint16 rev_pkt_size;
+	mddi_rev_link_state_type rev_state;
+	mddi_host_link_state_type link_state;
+	mddi_host_driver_state_type driver_state;
+	boolean disable_hibernation;
+	uint32 saved_int_reg;
+	uint32 saved_int_en;
+	mddi_linked_list_type *llist_ptr;
+	dma_addr_t llist_dma_addr;
+	mddi_linked_list_type *llist_dma_ptr;
+	uint32 *rev_data_buf;
+	struct completion mddi_llist_avail_comp;
+	boolean mddi_waiting_for_llist_avail;
+	mddi_host_int_type int_type;
+	mddi_host_stat_type stats;
+	mddi_log_params_struct_type log_parms;
+	mddi_llist_info_type llist_info;
+	mddi_linked_list_notify_type llist_notify[MDDI_MAX_NUM_LLIST_ITEMS];
+} mddi_host_cntl_type;
+
+static mddi_host_type mddi_curr_host = MDDI_HOST_PRIM;
+static mddi_host_cntl_type mhctl[MDDI_NUM_HOST_CORES];
+mddi_linked_list_type *llist_extern[MDDI_NUM_HOST_CORES];
+mddi_linked_list_type *llist_dma_extern[MDDI_NUM_HOST_CORES];
+mddi_linked_list_notify_type *llist_extern_notify[MDDI_NUM_HOST_CORES];
+static mddi_log_params_struct_type prev_parms[MDDI_NUM_HOST_CORES];
+
+extern uint32 mdp_total_vdopkts;
+
+static boolean mddi_host_io_clock_on = FALSE;
+static boolean mddi_host_hclk_on = FALSE;
+
+int int_mddi_pri_flag = FALSE;
+int int_mddi_ext_flag = FALSE;
+
+static void mddi_report_errors(uint32 int_reg)
+{
+	mddi_host_type host_idx = mddi_curr_host;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	if (int_reg & MDDI_INT_PRI_UNDERFLOW) {
+		pmhctl->stats.pri_underflow++;
+		MDDI_MSG_ERR("!!! MDDI Primary Underflow !!!\n");
+	}
+	if (int_reg & MDDI_INT_SEC_UNDERFLOW) {
+		pmhctl->stats.sec_underflow++;
+		MDDI_MSG_ERR("!!! MDDI Secondary Underflow !!!\n");
+	}
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+	if (int_reg & MDDI_INT_REV_OVERFLOW) {
+		pmhctl->stats.rev_overflow++;
+		MDDI_MSG_ERR("!!! MDDI Reverse Overflow !!!\n");
+		pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+		mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
+
+	}
+	if (int_reg & MDDI_INT_CRC_ERROR)
+		MDDI_MSG_ERR("!!! MDDI Reverse CRC Error !!!\n");
+#endif
+	if (int_reg & MDDI_INT_PRI_OVERWRITE) {
+		pmhctl->stats.pri_overwrite++;
+		MDDI_MSG_ERR("!!! MDDI Primary Overwrite !!!\n");
+	}
+	if (int_reg & MDDI_INT_SEC_OVERWRITE) {
+		pmhctl->stats.sec_overwrite++;
+		MDDI_MSG_ERR("!!! MDDI Secondary Overwrite !!!\n");
+	}
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+	if (int_reg & MDDI_INT_REV_OVERWRITE) {
+		pmhctl->stats.rev_overwrite++;
+		/* This will show up normally and is not a problem */
+		MDDI_MSG_DEBUG("MDDI Reverse Overwrite!\n");
+	}
+	if (int_reg & MDDI_INT_RTD_FAILURE) {
+		mddi_host_reg_outm(INTEN, MDDI_INT_RTD_FAILURE, 0);
+		pmhctl->stats.rtd_failure++;
+		MDDI_MSG_ERR("!!! MDDI RTD Failure !!!\n");
+	}
+#endif
+	if (int_reg & MDDI_INT_DMA_FAILURE) {
+		pmhctl->stats.dma_failure++;
+		MDDI_MSG_ERR("!!! MDDI DMA Abort !!!\n");
+	}
+}
+
+static void mddi_host_enable_io_clock(void)
+{
+	if (!MDDI_HOST_IS_IO_CLOCK_ON)
+		MDDI_HOST_ENABLE_IO_CLOCK;
+}
+
+static void mddi_host_enable_hclk(void)
+{
+
+	if (!MDDI_HOST_IS_HCLK_ON)
+		MDDI_HOST_ENABLE_HCLK;
+}
+
+static void mddi_host_disable_io_clock(void)
+{
+#ifndef FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE
+	if (MDDI_HOST_IS_IO_CLOCK_ON)
+		MDDI_HOST_DISABLE_IO_CLOCK;
+#endif
+}
+
+static void mddi_host_disable_hclk(void)
+{
+#ifndef FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE
+	if (MDDI_HOST_IS_HCLK_ON)
+		MDDI_HOST_DISABLE_HCLK;
+#endif
+}
+
+static void mddi_vote_to_sleep(mddi_host_type host_idx, boolean sleep)
+{
+	uint16 vote_mask;
+
+	if (host_idx == MDDI_HOST_PRIM)
+		vote_mask = 0x01;
+	else
+		vote_mask = 0x02;
+}
+
+static void mddi_report_state_change(uint32 int_reg)
+{
+	mddi_host_type host_idx = mddi_curr_host;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	if ((pmhctl->saved_int_reg & MDDI_INT_IN_HIBERNATION) &&
+	    (pmhctl->saved_int_reg & MDDI_INT_LINK_ACTIVE)) {
+		/* recover from condition where the io_clock was turned off by the
+		   clock driver during a transition to hibernation. The io_clock
+		   disable is to prevent MDP/MDDI underruns when changing ARM
+		   clock speeds. In the process of halting the ARM, the hclk
+		   divider needs to be set to 1. When it is set to 1, there is
+		   a small time (usecs) when hclk is off or slow, and this can
+		   cause an underrun. To prevent the underrun, clock driver turns
+		   off the MDDI io_clock before making the change. */
+		mddi_host_reg_out(CMD, MDDI_CMD_POWERUP);
+	}
+
+	if (int_reg & MDDI_INT_LINK_ACTIVE) {
+		pmhctl->link_state = MDDI_LINK_ACTIVE;
+		pmhctl->log_parms.link_active_cnt++;
+		pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
+		MDDI_MSG_DEBUG("!!! MDDI Active RTD:0x%x!!!\n",
+			       pmhctl->rtd_value);
+		/* now interrupt on hibernation */
+		mddi_host_reg_outm(INTEN,
+				   (MDDI_INT_IN_HIBERNATION |
+				    MDDI_INT_LINK_ACTIVE),
+				   MDDI_INT_IN_HIBERNATION);
+
+#ifdef DEBUG_MDDIHOSTI
+		/* if gpio interrupt is enabled, start polling at fastest
+		 * registered rate
+		 */
+		if (mddi_gpio.polling_enabled) {
+			timer_reg(&mddi_gpio_poll_timer,
+		mddi_gpio_poll_timer_cb, 0, mddi_gpio.polling_interval, 0);
+		}
+#endif
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+		if (mddi_rev_ptr_workaround) {
+			/* HW CR: need to reset reverse register stuff */
+			pmhctl->rev_ptr_written = FALSE;
+			pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+		}
+#endif
+		/* vote on sleep */
+		mddi_vote_to_sleep(host_idx, FALSE);
+
+		if (host_idx == MDDI_HOST_PRIM) {
+			if (mddi_vsync_detect_enabled) {
+				/*
+				 * Indicate to client specific code that vsync
+				 * was enabled, but we did not detect a client
+				 * intiated wakeup. The client specific
+				 * handler can either reassert vsync detection,
+				 * or treat this as a valid vsync.
+				 */
+				mddi_client_lcd_vsync_detected(FALSE);
+				pmhctl->log_parms.vsync_response_cnt++;
+			}
+		}
+	}
+	if (int_reg & MDDI_INT_IN_HIBERNATION) {
+		pmhctl->link_state = MDDI_LINK_HIBERNATING;
+		pmhctl->log_parms.link_hibernate_cnt++;
+		MDDI_MSG_DEBUG("!!! MDDI Hibernating !!!\n");
+		/* now interrupt on link_active */
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+		mddi_host_reg_outm(INTEN,
+				   (MDDI_INT_MDDI_IN |
+				    MDDI_INT_IN_HIBERNATION |
+				    MDDI_INT_LINK_ACTIVE),
+				   MDDI_INT_LINK_ACTIVE);
+#else
+		mddi_host_reg_outm(INTEN,
+				   (MDDI_INT_MDDI_IN |
+				    MDDI_INT_IN_HIBERNATION |
+				    MDDI_INT_LINK_ACTIVE),
+				   (MDDI_INT_MDDI_IN | MDDI_INT_LINK_ACTIVE));
+
+		pmhctl->rtd_counter = mddi_rtd_frequency;
+
+		if (pmhctl->rev_state != MDDI_REV_IDLE) {
+			/* a rev_encap will not wake up the link, so we do that here */
+			pmhctl->link_state = MDDI_LINK_ACTIVATING;
+			mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+		}
+#endif
+
+		if (pmhctl->disable_hibernation) {
+			mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
+			mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+			pmhctl->link_state = MDDI_LINK_ACTIVATING;
+		}
+#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
+		if ((pmhctl->llist_info.transmitting_start_idx !=
+		     UNASSIGNED_INDEX)
+		    &&
+		    ((pmhctl->
+		      saved_int_reg & (MDDI_INT_PRI_LINK_LIST_DONE |
+				       MDDI_INT_PRI_PTR_READ)) ==
+		     MDDI_INT_PRI_PTR_READ)) {
+			mddi_linked_list_type *llist_dma;
+			llist_dma = pmhctl->llist_dma_ptr;
+			/*
+			 * All indications are that we have not received a
+			 * linked list done interrupt, due to an underrun
+			 * condition. Recovery attempt is to send again.
+			 */
+			dma_coherent_pre_ops();
+			/* Write to primary pointer register again */
+			mddi_host_reg_out(PRI_PTR,
+					  &llist_dma[pmhctl->llist_info.
+						     transmitting_start_idx]);
+			pmhctl->stats.pri_underrun_detected++;
+		}
+#endif
+
+		/* vote on sleep */
+		if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+			mddi_vote_to_sleep(host_idx, TRUE);
+		}
+
+#ifdef DEBUG_MDDIHOSTI
+		/* need to stop polling timer */
+		if (mddi_gpio.polling_enabled) {
+			(void) timer_clr(&mddi_gpio_poll_timer, T_NONE);
+		}
+#endif
+	}
+}
+
+void mddi_host_timer_service(unsigned long data)
+{
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+	unsigned long flags;
+#endif
+	mddi_host_type host_idx;
+	mddi_host_cntl_type *pmhctl;
+
+	unsigned long time_ms = MDDI_DEFAULT_TIMER_LENGTH;
+	init_timer(&mddi_host_timer);
+	mddi_host_timer.function = mddi_host_timer_service;
+	mddi_host_timer.data = 0;
+
+	mddi_host_timer.expires = jiffies + ((time_ms * HZ) / 1000);
+	add_timer(&mddi_host_timer);
+
+	for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
+	     host_idx++) {
+		pmhctl = &(mhctl[host_idx]);
+		mddi_log_stats_counter += (uint32) time_ms;
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+		pmhctl->rtd_counter += (uint32) time_ms;
+		pmhctl->client_status_cnt += (uint32) time_ms;
+
+		if (host_idx == MDDI_HOST_PRIM) {
+			if (pmhctl->client_status_cnt >=
+			    mddi_client_status_frequency) {
+				if ((pmhctl->link_state ==
+				     MDDI_LINK_HIBERNATING)
+				    && (pmhctl->client_status_cnt >
+					mddi_client_status_frequency)) {
+					/*
+					 * special case where we are hibernating
+					 * and mddi_host_isr is not firing, so
+					 * kick the link so that the status can
+					 * be retrieved
+					 */
+
+					/* need to wake up link before issuing
+					 * rev encap command
+					 */
+					MDDI_MSG_INFO("wake up link!\n");
+					spin_lock_irqsave(&mddi_host_spin_lock,
+							  flags);
+					mddi_host_enable_hclk();
+					mddi_host_enable_io_clock();
+					pmhctl->link_state =
+					    MDDI_LINK_ACTIVATING;
+					mddi_host_reg_out(CMD,
+							  MDDI_CMD_LINK_ACTIVE);
+					spin_unlock_irqrestore
+					    (&mddi_host_spin_lock, flags);
+				} else
+				    if ((pmhctl->link_state == MDDI_LINK_ACTIVE)
+					&& pmhctl->disable_hibernation) {
+					/*
+					 * special case where we have disabled
+					 * hibernation and mddi_host_isr
+					 * is not firing, so enable interrupt
+					 * for no pkts pending, which will
+					 * generate an interrupt
+					 */
+					MDDI_MSG_INFO("kick isr!\n");
+					spin_lock_irqsave(&mddi_host_spin_lock,
+							  flags);
+					mddi_host_enable_hclk();
+					mddi_host_reg_outm(INTEN,
+							   MDDI_INT_NO_CMD_PKTS_PEND,
+							   MDDI_INT_NO_CMD_PKTS_PEND);
+					spin_unlock_irqrestore
+					    (&mddi_host_spin_lock, flags);
+				}
+			}
+		}
+#endif /* #ifndef FEATURE_MDDI_DISABLE_REVERSE */
+	}
+
+	/* Check if logging is turned on */
+	for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
+	     host_idx++) {
+		mddi_log_params_struct_type *prev_ptr = &(prev_parms[host_idx]);
+		pmhctl = &(mhctl[host_idx]);
+
+		if (mddi_debug_log_statistics) {
+
+			/* get video pkt count from MDP, since MDDI sw cannot know this */
+			pmhctl->log_parms.vid_cnt = mdp_total_vdopkts;
+
+			if (mddi_log_stats_counter >= mddi_log_stats_frequency) {
+				/* mddi_log_stats_counter = 0; */
+				if (mddi_debug_log_statistics) {
+					MDDI_MSG_NOTICE
+					    ("MDDI Statistics since last report:\n");
+					MDDI_MSG_NOTICE("  Packets sent:\n");
+					MDDI_MSG_NOTICE
+					    ("    %d RTD packet(s)\n",
+					     pmhctl->log_parms.rtd_cnt -
+					     prev_ptr->rtd_cnt);
+					if (prev_ptr->rtd_cnt !=
+					    pmhctl->log_parms.rtd_cnt) {
+						unsigned long flags;
+						spin_lock_irqsave
+						    (&mddi_host_spin_lock,
+						     flags);
+						mddi_host_enable_hclk();
+						pmhctl->rtd_value =
+						    mddi_host_reg_in(RTD_VAL);
+						spin_unlock_irqrestore
+						    (&mddi_host_spin_lock,
+						     flags);
+						MDDI_MSG_NOTICE
+						    ("      RTD value=%d\n",
+						     pmhctl->rtd_value);
+					}
+					MDDI_MSG_NOTICE
+					    ("    %d VIDEO packets\n",
+					     pmhctl->log_parms.vid_cnt -
+					     prev_ptr->vid_cnt);
+					MDDI_MSG_NOTICE
+					    ("    %d Register Access packets\n",
+					     pmhctl->log_parms.reg_acc_cnt -
+					     prev_ptr->reg_acc_cnt);
+					MDDI_MSG_NOTICE
+					    ("    %d Reverse Encapsulation packet(s)\n",
+					     pmhctl->log_parms.rev_enc_cnt -
+					     prev_ptr->rev_enc_cnt);
+					if (prev_ptr->rev_enc_cnt !=
+					    pmhctl->log_parms.rev_enc_cnt) {
+						/* report # of reverse CRC errors */
+						MDDI_MSG_NOTICE
+						    ("      %d reverse CRC errors detected\n",
+						     pmhctl->log_parms.
+						     rev_crc_cnt -
+						     prev_ptr->rev_crc_cnt);
+					}
+					MDDI_MSG_NOTICE
+					    ("  Packets received:\n");
+					MDDI_MSG_NOTICE
+					    ("    %d Client Status packets",
+					     pmhctl->log_parms.cli_stat_cnt -
+					     prev_ptr->cli_stat_cnt);
+					if (prev_ptr->cli_stat_cnt !=
+					    pmhctl->log_parms.cli_stat_cnt) {
+						MDDI_MSG_NOTICE
+						    ("      %d forward CRC errors reported\n",
+						     pmhctl->log_parms.
+						     fwd_crc_cnt -
+						     prev_ptr->fwd_crc_cnt);
+					}
+					MDDI_MSG_NOTICE
+					    ("    %d Register Access Read packets\n",
+					     pmhctl->log_parms.reg_read_cnt -
+					     prev_ptr->reg_read_cnt);
+
+					if (pmhctl->link_state ==
+					    MDDI_LINK_ACTIVE) {
+						MDDI_MSG_NOTICE
+						    ("  Current Link Status: Active\n");
+					} else
+					    if ((pmhctl->link_state ==
+						 MDDI_LINK_HIBERNATING)
+						|| (pmhctl->link_state ==
+						    MDDI_LINK_ACTIVATING)) {
+						MDDI_MSG_NOTICE
+						    ("  Current Link Status: Hibernation\n");
+					} else {
+						MDDI_MSG_NOTICE
+						    ("  Current Link Status: Inactive\n");
+					}
+					MDDI_MSG_NOTICE
+					    ("    Active state entered %d times\n",
+					     pmhctl->log_parms.link_active_cnt -
+					     prev_ptr->link_active_cnt);
+					MDDI_MSG_NOTICE
+					    ("    Hibernation state entered %d times\n",
+					     pmhctl->log_parms.
+					     link_hibernate_cnt -
+					     prev_ptr->link_hibernate_cnt);
+				}
+			}
+			prev_parms[host_idx] = pmhctl->log_parms;
+		}
+	}
+	if (mddi_log_stats_counter >= mddi_log_stats_frequency)
+		mddi_log_stats_counter = 0;
+
+	return;
+}				/* mddi_host_timer_cb */
+
+static void mddi_process_link_list_done(void)
+{
+	mddi_host_type host_idx = mddi_curr_host;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	/* normal forward linked list packet(s) were sent */
+	if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
+		MDDI_MSG_ERR("**** getting LL done, but no list ****\n");
+	} else {
+		uint16 idx;
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+		if (pmhctl->rev_state == MDDI_REV_REG_READ_ISSUED) {
+			/* special case where a register read packet was sent */
+			pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
+			if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
+				MDDI_MSG_ERR
+				    ("**** getting LL done, but no list ****\n");
+			}
+		}
+#endif
+		for (idx = pmhctl->llist_info.transmitting_start_idx;;) {
+			uint16 next_idx = pmhctl->llist_notify[idx].next_idx;
+			/* with reg read we don't release the waiting tcb until after
+			 * the reverse encapsulation has completed.
+			 */
+			if (idx != pmhctl->llist_info.reg_read_idx) {
+				/* notify task that may be waiting on this completion */
+				if (pmhctl->llist_notify[idx].waiting) {
+					complete(&
+						 (pmhctl->llist_notify[idx].
+						  done_comp));
+				}
+				if (pmhctl->llist_notify[idx].done_cb != NULL) {
+					(*(pmhctl->llist_notify[idx].done_cb))
+					    ();
+				}
+
+				pmhctl->llist_notify[idx].in_use = FALSE;
+				pmhctl->llist_notify[idx].waiting = FALSE;
+				pmhctl->llist_notify[idx].done_cb = NULL;
+				if (idx < MDDI_NUM_DYNAMIC_LLIST_ITEMS) {
+					/* static LLIST items are configured only once */
+					pmhctl->llist_notify[idx].next_idx =
+					    UNASSIGNED_INDEX;
+				}
+				/*
+				 * currently, all linked list packets are
+				 * register access, so we can increment the
+				 * counter for that packet type here.
+				 */
+				pmhctl->log_parms.reg_acc_cnt++;
+			}
+			if (idx == pmhctl->llist_info.transmitting_end_idx)
+				break;
+			idx = next_idx;
+			if (idx == UNASSIGNED_INDEX)
+				MDDI_MSG_CRIT("MDDI linked list corruption!\n");
+		}
+
+		pmhctl->llist_info.transmitting_start_idx = UNASSIGNED_INDEX;
+		pmhctl->llist_info.transmitting_end_idx = UNASSIGNED_INDEX;
+
+		if (pmhctl->mddi_waiting_for_llist_avail) {
+			if (!
+			    (pmhctl->
+			     llist_notify[pmhctl->llist_info.next_free_idx].
+			     in_use)) {
+				pmhctl->mddi_waiting_for_llist_avail = FALSE;
+				complete(&(pmhctl->mddi_llist_avail_comp));
+			}
+		}
+	}
+
+	/* Turn off MDDI_INT_PRI_LINK_LIST_DONE interrupt */
+	mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, 0);
+
+}
+
+static void mddi_queue_forward_linked_list(void)
+{
+	uint16 first_pkt_index;
+	mddi_linked_list_type *llist_dma;
+	mddi_host_type host_idx = mddi_curr_host;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+	llist_dma = pmhctl->llist_dma_ptr;
+
+	first_pkt_index = UNASSIGNED_INDEX;
+
+	if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+		if (pmhctl->llist_info.reg_read_waiting) {
+			if (pmhctl->rev_state == MDDI_REV_IDLE) {
+				/*
+				 * we have a register read to send and
+				 * can send it now
+				 */
+				pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
+				mddi_reg_read_retry = 0;
+				first_pkt_index =
+				    pmhctl->llist_info.waiting_start_idx;
+				pmhctl->llist_info.reg_read_waiting = FALSE;
+			}
+		} else
+#endif
+		{
+			/*
+			 * not register read to worry about, go ahead and write
+			 * anything that may be on the waiting list.
+			 */
+			first_pkt_index = pmhctl->llist_info.waiting_start_idx;
+		}
+	}
+
+	if (first_pkt_index != UNASSIGNED_INDEX) {
+		pmhctl->llist_info.transmitting_start_idx =
+		    pmhctl->llist_info.waiting_start_idx;
+		pmhctl->llist_info.transmitting_end_idx =
+		    pmhctl->llist_info.waiting_end_idx;
+		pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
+		pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
+
+		/* write to the primary pointer register */
+		MDDI_MSG_DEBUG("MDDI writing primary ptr with idx=%d\n",
+			       first_pkt_index);
+
+		pmhctl->int_type.llist_ptr_write_2++;
+
+		dma_coherent_pre_ops();
+		mddi_host_reg_out(PRI_PTR, &llist_dma[first_pkt_index]);
+
+		/* enable interrupt when complete */
+		mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
+				   MDDI_INT_PRI_LINK_LIST_DONE);
+
+	}
+
+}
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+static void mddi_read_rev_packet(byte *data_ptr)
+{
+	uint16 i, length;
+	mddi_host_type host_idx = mddi_curr_host;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	uint8 *rev_ptr_overflow =
+	    (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE);
+
+	/* first determine the length and handle invalid lengths */
+	length = *pmhctl->rev_ptr_curr++;
+	if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+		pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+	length |= ((*pmhctl->rev_ptr_curr++) << 8);
+	if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+		pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+	if (length > (pmhctl->rev_pkt_size - 2)) {
+		MDDI_MSG_ERR("Invalid rev pkt length %d\n", length);
+		/* rev_pkt_size should always be <= rev_ptr_size so limit to packet size */
+		length = pmhctl->rev_pkt_size - 2;
+	}
+
+	/* If the data pointer is NULL, just increment the pmhctl->rev_ptr_curr.
+	 * Loop around if necessary. Don't bother reading the data.
+	 */
+	if (data_ptr == NULL) {
+		pmhctl->rev_ptr_curr += length;
+		if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+			pmhctl->rev_ptr_curr -= MDDI_REV_BUFFER_SIZE;
+		return;
+	}
+
+	data_ptr[0] = length & 0x0ff;
+	data_ptr[1] = length >> 8;
+	data_ptr += 2;
+	/* copy the data to data_ptr byte-at-a-time */
+	for (i = 0; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow);
+	     i++)
+		*data_ptr++ = *pmhctl->rev_ptr_curr++;
+	if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
+		pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+	for (; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow); i++)
+		*data_ptr++ = *pmhctl->rev_ptr_curr++;
+}
+
+static void mddi_process_rev_packets(void)
+{
+	uint32 rev_packet_count;
+	word i;
+	uint32 crc_errors;
+	boolean mddi_reg_read_successful = FALSE;
+	mddi_host_type host_idx = mddi_curr_host;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	pmhctl->log_parms.rev_enc_cnt++;
+	if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
+	    (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED) &&
+	    (pmhctl->rev_state != MDDI_REV_CLIENT_CAP_ISSUED)) {
+		MDDI_MSG_ERR("Wrong state %d for reverse int\n",
+			     pmhctl->rev_state);
+	}
+	/* Turn off MDDI_INT_REV_AVAIL interrupt */
+	mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL, 0);
+
+	/* Clear rev data avail int */
+	mddi_host_reg_out(INT, MDDI_INT_REV_DATA_AVAIL);
+
+	/* Get Number of packets */
+	rev_packet_count = mddi_host_reg_in(REV_PKT_CNT);
+
+#ifndef T_MSM7500
+	/* Clear out rev packet counter */
+	mddi_host_reg_out(REV_PKT_CNT, 0x0000);
+#endif
+
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+	if ((pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) &&
+	    (rev_packet_count > 0) &&
+	    (mddi_host_core_version == 0x28 ||
+	     mddi_host_core_version == 0x30)) {
+
+		uint32 int_reg;
+		uint32 max_count = 0;
+
+		mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
+		int_reg = mddi_host_reg_in(INT);
+		while ((int_reg & 0x100000) == 0) {
+			udelay(3);
+			int_reg = mddi_host_reg_in(INT);
+			if (++max_count > 100)
+				break;
+		}
+	}
+#endif
+
+	/* Get CRC error count */
+	crc_errors = mddi_host_reg_in(REV_CRC_ERR);
+	if (crc_errors != 0) {
+		pmhctl->log_parms.rev_crc_cnt += crc_errors;
+		pmhctl->stats.rev_crc_count += crc_errors;
+		MDDI_MSG_ERR("!!! MDDI %d Reverse CRC Error(s) !!!\n",
+			     crc_errors);
+#ifndef T_MSM7500
+		/* Clear CRC error count */
+		mddi_host_reg_out(REV_CRC_ERR, 0x0000);
+#endif
+		/* also issue an RTD to attempt recovery */
+		pmhctl->rtd_counter = mddi_rtd_frequency;
+	}
+
+	pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
+
+	MDDI_MSG_DEBUG("MDDI rev pkt cnt=%d, ptr=0x%x, RTD:0x%x\n",
+		       rev_packet_count,
+		       pmhctl->rev_ptr_curr - pmhctl->rev_ptr_start,
+		       pmhctl->rtd_value);
+
+	if (rev_packet_count >= 1) {
+		mddi_invalidate_cache_lines((uint32 *) pmhctl->rev_ptr_start,
+					    MDDI_REV_BUFFER_SIZE);
+	}
+	/* order the reads */
+	dma_coherent_post_ops();
+	for (i = 0; i < rev_packet_count; i++) {
+		mddi_rev_packet_type *rev_pkt_ptr;
+
+		mddi_read_rev_packet(rev_packet_data);
+
+		rev_pkt_ptr = (mddi_rev_packet_type *) rev_packet_data;
+
+		if (rev_pkt_ptr->packet_length > pmhctl->rev_pkt_size) {
+			MDDI_MSG_ERR("!!!invalid packet size: %d\n",
+				     rev_pkt_ptr->packet_length);
+		}
+
+		MDDI_MSG_DEBUG("MDDI rev pkt 0x%x size 0x%x\n",
+			       rev_pkt_ptr->packet_type,
+			       rev_pkt_ptr->packet_length);
+
+		/* Do whatever you want to do with the data based on the packet type */
+		switch (rev_pkt_ptr->packet_type) {
+		case 66:	/* Client Capability */
+			{
+				mddi_client_capability_type
+				    *client_capability_pkt_ptr;
+
+				client_capability_pkt_ptr =
+				    (mddi_client_capability_type *)
+				    rev_packet_data;
+				MDDI_MSG_NOTICE
+				    ("Client Capability: Week=%d, Year=%d\n",
+				     client_capability_pkt_ptr->
+				     Week_of_Manufacture,
+				     client_capability_pkt_ptr->
+				     Year_of_Manufacture);
+				memcpy((void *)&mddi_client_capability_pkt,
+				       (void *)rev_packet_data,
+				       sizeof(mddi_client_capability_type));
+				pmhctl->log_parms.cli_cap_cnt++;
+			}
+			break;
+
+		case 70:	/* Display Status */
+			{
+				mddi_client_status_type *client_status_pkt_ptr;
+
+				client_status_pkt_ptr =
+				    (mddi_client_status_type *) rev_packet_data;
+				if ((client_status_pkt_ptr->crc_error_count !=
+				     0)
+				    || (client_status_pkt_ptr->
+					reverse_link_request != 0)) {
+					MDDI_MSG_ERR
+					    ("Client Status: RevReq=%d, CrcErr=%d\n",
+					     client_status_pkt_ptr->
+					     reverse_link_request,
+					     client_status_pkt_ptr->
+					     crc_error_count);
+				} else {
+					MDDI_MSG_DEBUG
+					    ("Client Status: RevReq=%d, CrcErr=%d\n",
+					     client_status_pkt_ptr->
+					     reverse_link_request,
+					     client_status_pkt_ptr->
+					     crc_error_count);
+				}
+				pmhctl->log_parms.fwd_crc_cnt +=
+				    client_status_pkt_ptr->crc_error_count;
+				pmhctl->stats.fwd_crc_count +=
+				    client_status_pkt_ptr->crc_error_count;
+				pmhctl->log_parms.cli_stat_cnt++;
+			}
+			break;
+
+		case 146:	/* register access packet */
+			{
+				mddi_register_access_packet_type
+				    * regacc_pkt_ptr;
+
+				regacc_pkt_ptr =
+				    (mddi_register_access_packet_type *)
+				    rev_packet_data;
+
+				MDDI_MSG_DEBUG
+				    ("Reg Acc parse reg=0x%x, value=0x%x\n",
+				     regacc_pkt_ptr->register_address,
+				     regacc_pkt_ptr->register_data_list);
+
+				/* Copy register value to location passed in */
+				if (mddi_reg_read_value_ptr) {
+#if defined(T_MSM6280) && !defined(T_MSM7200)
+					/* only least significant 16 bits are valid with 6280 */
+					*mddi_reg_read_value_ptr =
+					    regacc_pkt_ptr->
+					    register_data_list & 0x0000ffff;
+#else
+					*mddi_reg_read_value_ptr =
+					    regacc_pkt_ptr->register_data_list;
+#endif
+					mddi_reg_read_successful = TRUE;
+					mddi_reg_read_value_ptr = NULL;
+				}
+
+#ifdef DEBUG_MDDIHOSTI
+				if ((mddi_gpio.polling_enabled) &&
+				    (regacc_pkt_ptr->register_address ==
+				     mddi_gpio.polling_reg)) {
+					/*
+					 * ToDo: need to call Linux GPIO call
+					 * here...
+					 */
+					 mddi_client_lcd_gpio_poll(
+					 regacc_pkt_ptr->register_data_list);
+				}
+#endif
+				pmhctl->log_parms.reg_read_cnt++;
+			}
+			break;
+
+		default:	/* any other packet */
+			{
+				uint16 hdlr;
+
+				for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS;
+				     hdlr++) {
+					if (mddi_rev_pkt_handler[hdlr].
+					    pkt_type ==
+					    rev_pkt_ptr->packet_type) {
+						(*
+						 (mddi_rev_pkt_handler[hdlr].
+						  handler)) (rev_pkt_ptr);
+					/* pmhctl->rev_state = MDDI_REV_IDLE; */
+						break;
+					}
+				}
+				if (hdlr >= MAX_MDDI_REV_HANDLERS)
+					MDDI_MSG_ERR("MDDI unknown rev pkt\n");
+			}
+			break;
+		}
+	}
+	if ((pmhctl->rev_ptr_curr + pmhctl->rev_pkt_size) >=
+	    (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE)) {
+		pmhctl->rev_ptr_written = FALSE;
+	}
+
+	if (pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) {
+		pmhctl->rev_state = MDDI_REV_IDLE;
+		if (mddi_rev_user.waiting) {
+			mddi_rev_user.waiting = FALSE;
+			complete(&(mddi_rev_user.done_comp));
+		} else if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
+			MDDI_MSG_ERR
+			    ("Reverse Encap state, but no reg read in progress\n");
+		} else {
+			if ((!mddi_reg_read_successful) &&
+			    (mddi_reg_read_retry < mddi_reg_read_retry_max) &&
+			    (mddi_enable_reg_read_retry)) {
+				/*
+				 * There is a race condition that can happen
+				 * where the reverse encapsulation message is
+				 * sent out by the MDDI host before the register
+				 * read packet is sent. As a work-around for
+				 * that problem we issue the reverse
+				 * encapsulation one more time before giving up.
+				 */
+				if (mddi_enable_reg_read_retry_once)
+					mddi_reg_read_retry =
+					    mddi_reg_read_retry_max;
+				pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
+				pmhctl->stats.reg_read_failure++;
+			} else {
+				uint16 reg_read_idx =
+				    pmhctl->llist_info.reg_read_idx;
+
+				mddi_reg_read_retry = 0;
+				if (pmhctl->llist_notify[reg_read_idx].waiting) {
+					complete(&
+						 (pmhctl->
+						  llist_notify[reg_read_idx].
+						  done_comp));
+				}
+				pmhctl->llist_info.reg_read_idx =
+				    UNASSIGNED_INDEX;
+				if (pmhctl->llist_notify[reg_read_idx].
+				    done_cb != NULL) {
+					(*
+					 (pmhctl->llist_notify[reg_read_idx].
+					  done_cb)) ();
+				}
+				pmhctl->llist_notify[reg_read_idx].next_idx =
+				    UNASSIGNED_INDEX;
+				pmhctl->llist_notify[reg_read_idx].in_use =
+				    FALSE;
+				pmhctl->llist_notify[reg_read_idx].waiting =
+				    FALSE;
+				pmhctl->llist_notify[reg_read_idx].done_cb =
+				    NULL;
+				if (!mddi_reg_read_successful)
+					pmhctl->stats.reg_read_failure++;
+			}
+		}
+	} else if (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) {
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+		if (mddi_host_core_version == 0x28 ||
+		    mddi_host_core_version == 0x30) {
+			mddi_host_reg_out(FIFO_ALLOC, 0x00);
+			pmhctl->rev_ptr_written = TRUE;
+			mddi_host_reg_out(REV_PTR,
+				pmhctl->mddi_rev_ptr_write_val);
+			pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+			mddi_host_reg_out(CMD, 0xC00);
+		}
+#endif
+
+		if (mddi_rev_user.waiting) {
+			mddi_rev_user.waiting = FALSE;
+			complete(&(mddi_rev_user.done_comp));
+		}
+		pmhctl->rev_state = MDDI_REV_IDLE;
+	} else {
+		pmhctl->rev_state = MDDI_REV_IDLE;
+	}
+
+	/* pmhctl->rev_state = MDDI_REV_IDLE; */
+
+	/* Re-enable interrupt */
+	mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL,
+			   MDDI_INT_REV_DATA_AVAIL);
+
+}
+
+static void mddi_issue_reverse_encapsulation(void)
+{
+	mddi_host_type host_idx = mddi_curr_host;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+	/* Only issue a reverse encapsulation packet if:
+	 * 1) another reverse is not in progress (MDDI_REV_IDLE).
+	 * 2) a register read has been sent (MDDI_REV_REG_READ_SENT).
+	 * 3) forward is not in progress, because of a hw bug in client that
+	 *    causes forward crc errors on packet immediately after rev encap.
+	 */
+	if (((pmhctl->rev_state == MDDI_REV_IDLE) ||
+	     (pmhctl->rev_state == MDDI_REV_REG_READ_SENT)) &&
+	    (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
+	    (!mdp_in_processing)) {
+		uint32 mddi_command = MDDI_CMD_SEND_REV_ENCAP;
+
+		if ((pmhctl->rev_state == MDDI_REV_REG_READ_SENT) ||
+		    (mddi_rev_encap_user_request == TRUE)) {
+			mddi_host_enable_io_clock();
+			if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+				/* need to wake up link before issuing rev encap command */
+				MDDI_MSG_DEBUG("wake up link!\n");
+				pmhctl->link_state = MDDI_LINK_ACTIVATING;
+				mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+			} else {
+				if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
+					MDDI_MSG_DEBUG
+					    ("mddi sending RTD command!\n");
+					mddi_host_reg_out(CMD,
+							  MDDI_CMD_SEND_RTD);
+					pmhctl->rtd_counter = 0;
+					pmhctl->log_parms.rtd_cnt++;
+				}
+				if (pmhctl->rev_state != MDDI_REV_REG_READ_SENT) {
+					/* this is generic reverse request by user, so
+					 * reset the waiting flag. */
+					mddi_rev_encap_user_request = FALSE;
+				}
+				/* link is active so send reverse encap to get register read results */
+				pmhctl->rev_state = MDDI_REV_ENCAP_ISSUED;
+				mddi_command = MDDI_CMD_SEND_REV_ENCAP;
+				MDDI_MSG_DEBUG("sending rev encap!\n");
+			}
+		} else
+		    if ((pmhctl->client_status_cnt >=
+			 mddi_client_status_frequency)
+			|| mddi_client_capability_request) {
+			mddi_host_enable_io_clock();
+			if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+				/* only wake up the link if it client status is overdue */
+				if ((pmhctl->client_status_cnt >=
+				     (mddi_client_status_frequency * 2))
+				    || mddi_client_capability_request) {
+					/* need to wake up link before issuing rev encap command */
+					MDDI_MSG_DEBUG("wake up link!\n");
+					pmhctl->link_state =
+					    MDDI_LINK_ACTIVATING;
+					mddi_host_reg_out(CMD,
+							  MDDI_CMD_LINK_ACTIVE);
+				}
+			} else {
+				if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
+					MDDI_MSG_DEBUG
+					    ("mddi sending RTD command!\n");
+					mddi_host_reg_out(CMD,
+							  MDDI_CMD_SEND_RTD);
+					pmhctl->rtd_counter = 0;
+					pmhctl->log_parms.rtd_cnt++;
+				}
+				/* periodically get client status */
+				MDDI_MSG_DEBUG
+				    ("mddi sending rev enc! (get status)\n");
+				if (mddi_client_capability_request) {
+					pmhctl->rev_state =
+					    MDDI_REV_CLIENT_CAP_ISSUED;
+					mddi_command = MDDI_CMD_GET_CLIENT_CAP;
+					mddi_client_capability_request = FALSE;
+				} else {
+					pmhctl->rev_state =
+					    MDDI_REV_STATUS_REQ_ISSUED;
+					pmhctl->client_status_cnt = 0;
+					mddi_command =
+					    MDDI_CMD_GET_CLIENT_STATUS;
+				}
+			}
+		}
+		if ((pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) ||
+		    (pmhctl->rev_state == MDDI_REV_STATUS_REQ_ISSUED) ||
+		    (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED)) {
+			pmhctl->int_type.rev_encap_count++;
+#if defined(T_MSM6280) && !defined(T_MSM7200)
+			mddi_rev_pointer_written = TRUE;
+			mddi_host_reg_out(REV_PTR, mddi_rev_ptr_write_val);
+			mddi_rev_ptr_curr = mddi_rev_ptr_start;
+			/* force new rev ptr command */
+			mddi_host_reg_out(CMD, 0xC00);
+#else
+			if (!pmhctl->rev_ptr_written) {
+				MDDI_MSG_DEBUG("writing reverse pointer!\n");
+				pmhctl->rev_ptr_written = TRUE;
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+				if ((pmhctl->rev_state ==
+				     MDDI_REV_CLIENT_CAP_ISSUED) &&
+				    (mddi_host_core_version == 0x28 ||
+				     mddi_host_core_version == 0x30)) {
+					pmhctl->rev_ptr_written = FALSE;
+					mddi_host_reg_out(FIFO_ALLOC, 0x02);
+				} else
+					mddi_host_reg_out(REV_PTR,
+						  pmhctl->
+						  mddi_rev_ptr_write_val);
+#else
+				mddi_host_reg_out(REV_PTR,
+						  pmhctl->
+						  mddi_rev_ptr_write_val);
+#endif
+			}
+#endif
+			if (mddi_debug_clear_rev_data) {
+				uint16 i;
+				for (i = 0; i < MDDI_MAX_REV_DATA_SIZE / 4; i++)
+					pmhctl->rev_data_buf[i] = 0xdddddddd;
+				/* clean cache */
+				mddi_flush_cache_lines(pmhctl->rev_data_buf,
+						       MDDI_MAX_REV_DATA_SIZE);
+			}
+
+			/* send reverse encapsulation to get needed data */
+			mddi_host_reg_out(CMD, mddi_command);
+		}
+	}
+
+}
+
+static void mddi_process_client_initiated_wakeup(void)
+{
+	mddi_host_type host_idx = mddi_curr_host;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	/* Disable MDDI_INT Interrupt, we detect client initiated wakeup one
+	 * time for each entry into hibernation */
+	mddi_host_reg_outm(INTEN, MDDI_INT_MDDI_IN, 0);
+
+	if (host_idx == MDDI_HOST_PRIM) {
+		if (mddi_vsync_detect_enabled) {
+			mddi_host_enable_io_clock();
+#ifndef MDDI_HOST_DISP_LISTEN
+			/* issue command to bring up link */
+			/* need to do this to clear the vsync condition */
+			if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+				pmhctl->link_state = MDDI_LINK_ACTIVATING;
+				mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+			}
+#endif
+			/*
+			 * Indicate to client specific code that vsync was
+			 * enabled, and we did not detect a client initiated
+			 * wakeup. The client specific handler can clear the
+			 * condition if necessary to prevent subsequent
+			 * client initiated wakeups.
+			 */
+			mddi_client_lcd_vsync_detected(TRUE);
+			pmhctl->log_parms.vsync_response_cnt++;
+			MDDI_MSG_NOTICE("MDDI_INT_IN condition\n");
+
+		}
+	}
+
+	if (mddi_gpio.polling_enabled) {
+		mddi_host_enable_io_clock();
+		/* check interrupt status now */
+		(void)mddi_queue_register_read_int(mddi_gpio.polling_reg,
+						   &mddi_gpio.polling_val);
+	}
+}
+#endif /* FEATURE_MDDI_DISABLE_REVERSE */
+
+static void mddi_host_isr(void)
+{
+	uint32 int_reg, int_en;
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+	uint32 status_reg;
+#endif
+	mddi_host_type host_idx = mddi_curr_host;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	if (!MDDI_HOST_IS_HCLK_ON) {
+		MDDI_HOST_ENABLE_HCLK;
+		MDDI_MSG_DEBUG("HCLK disabled, but isr is firing\n");
+	}
+	int_reg = mddi_host_reg_in(INT);
+	int_en = mddi_host_reg_in(INTEN);
+	pmhctl->saved_int_reg = int_reg;
+	pmhctl->saved_int_en = int_en;
+	int_reg = int_reg & int_en;
+	pmhctl->int_type.count++;
+
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+	status_reg = mddi_host_reg_in(STAT);
+
+	if ((int_reg & MDDI_INT_MDDI_IN) ||
+	    ((int_en & MDDI_INT_MDDI_IN) &&
+	     ((int_reg == 0) || (status_reg & MDDI_STAT_CLIENT_WAKEUP_REQ)))) {
+		/*
+		 * The MDDI_IN condition will clear itself, and so it is
+		 * possible that MDDI_IN was the reason for the isr firing,
+		 * even though the interrupt register does not have the
+		 * MDDI_IN bit set. To check if this was the case we need to
+		 * look at the status register bit that signifies a client
+		 * initiated wakeup. If the status register bit is set, as well
+		 * as the MDDI_IN interrupt enabled, then we treat this as a
+		 * client initiated wakeup.
+		 */
+		if (int_reg & MDDI_INT_MDDI_IN)
+			pmhctl->int_type.in_count++;
+		mddi_process_client_initiated_wakeup();
+	}
+#endif
+
+	if (int_reg & MDDI_INT_LINK_STATE_CHANGES) {
+		pmhctl->int_type.state_change_count++;
+		mddi_report_state_change(int_reg);
+	}
+
+	if (int_reg & MDDI_INT_PRI_LINK_LIST_DONE) {
+		pmhctl->int_type.ll_done_count++;
+		mddi_process_link_list_done();
+	}
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+	if (int_reg & MDDI_INT_REV_DATA_AVAIL) {
+		pmhctl->int_type.rev_avail_count++;
+		mddi_process_rev_packets();
+	}
+#endif
+
+	if (int_reg & MDDI_INT_ERROR_CONDITIONS) {
+		pmhctl->int_type.error_count++;
+		mddi_report_errors(int_reg);
+
+		mddi_host_reg_out(INT, int_reg & MDDI_INT_ERROR_CONDITIONS);
+	}
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+	mddi_issue_reverse_encapsulation();
+
+	if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
+	    (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED))
+#endif
+		/* don't want simultaneous reverse and forward with Eagle */
+		mddi_queue_forward_linked_list();
+
+	if (int_reg & MDDI_INT_NO_CMD_PKTS_PEND) {
+		/* this interrupt is used to kick the isr when hibernation is disabled */
+		mddi_host_reg_outm(INTEN, MDDI_INT_NO_CMD_PKTS_PEND, 0);
+	}
+
+	if ((!mddi_host_mdp_active_flag) &&
+	    (!mddi_vsync_detect_enabled) &&
+	    (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
+	    (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
+	    (pmhctl->rev_state == MDDI_REV_IDLE)) {
+		if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
+			mddi_host_disable_io_clock();
+			mddi_host_disable_hclk();
+		}
+#ifdef FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION
+		else if ((pmhctl->link_state == MDDI_LINK_ACTIVE) &&
+			 (!pmhctl->disable_hibernation)) {
+			mddi_host_reg_out(CMD, MDDI_CMD_POWERDOWN);
+		}
+#endif
+	}
+}
+
+static void mddi_host_isr_primary(void)
+{
+	mddi_curr_host = MDDI_HOST_PRIM;
+	mddi_host_isr();
+}
+
+irqreturn_t mddi_pmdh_isr_proxy(int irq, void *ptr)
+{
+	mddi_host_isr_primary();
+	return IRQ_HANDLED;
+}
+
+static void mddi_host_isr_external(void)
+{
+	mddi_curr_host = MDDI_HOST_EXT;
+	mddi_host_isr();
+	mddi_curr_host = MDDI_HOST_PRIM;
+}
+
+irqreturn_t mddi_emdh_isr_proxy(int irq, void *ptr)
+{
+	mddi_host_isr_external();
+	return IRQ_HANDLED;
+}
+
+static void mddi_host_initialize_registers(mddi_host_type host_idx)
+{
+	uint32 pad_reg_val;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
+		return;
+
+	/* turn on HCLK to MDDI host core */
+	mddi_host_enable_hclk();
+
+	/* MDDI Reset command */
+	mddi_host_reg_out(CMD, MDDI_CMD_RESET);
+
+	/* Version register (= 0x01) */
+	mddi_host_reg_out(VERSION, 0x0001);
+
+	/* Bytes per subframe register */
+	mddi_host_reg_out(BPS, MDDI_HOST_BYTES_PER_SUBFRAME);
+
+	/* Subframes per media frames register (= 0x03) */
+	mddi_host_reg_out(SPM, 0x0003);
+
+	/* Turn Around 1 register (= 0x05) */
+	mddi_host_reg_out(TA1_LEN, 0x0005);
+
+	/* Turn Around 2 register (= 0x0C) */
+	mddi_host_reg_out(TA2_LEN, MDDI_HOST_TA2_LEN);
+
+	/* Drive hi register (= 0x96) */
+	mddi_host_reg_out(DRIVE_HI, 0x0096);
+
+	/* Drive lo register (= 0x32) */
+	mddi_host_reg_out(DRIVE_LO, 0x0032);
+
+	/* Display wakeup count register (= 0x3c) */
+	mddi_host_reg_out(DISP_WAKE, 0x003c);
+
+	/* Reverse Rate Divisor register (= 0x2) */
+	mddi_host_reg_out(REV_RATE_DIV, MDDI_HOST_REV_RATE_DIV);
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+	/* Reverse Pointer Size */
+	mddi_host_reg_out(REV_SIZE, MDDI_REV_BUFFER_SIZE);
+
+	/* Rev Encap Size */
+	mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
+#endif
+
+	/* Periodic Rev Encap */
+	/* don't send periodically */
+	mddi_host_reg_out(CMD, MDDI_CMD_PERIODIC_REV_ENCAP);
+
+	pad_reg_val = mddi_host_reg_in(PAD_CTL);
+	if (pad_reg_val == 0) {
+		/* If we are turning on band gap, need to wait 5us before turning
+		 * on the rest of the PAD */
+		mddi_host_reg_out(PAD_CTL, 0x08000);
+		udelay(5);
+	}
+#ifdef T_MSM7200
+	/* Recommendation from PAD hw team */
+	mddi_host_reg_out(PAD_CTL, 0xa850a);
+#else
+	/* Recommendation from PAD hw team */
+	mddi_host_reg_out(PAD_CTL, 0xa850f);
+#endif
+
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+	mddi_host_reg_out(PAD_IO_CTL, 0x00320000);
+	mddi_host_reg_out(PAD_CAL, 0x00220020);
+#endif
+
+	mddi_host_core_version = mddi_host_reg_inm(CORE_VER, 0xffff);
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+	if (mddi_host_core_version >= 8)
+		mddi_rev_ptr_workaround = FALSE;
+	pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
+#endif
+
+	if ((mddi_host_core_version > 8) && (mddi_host_core_version < 0x19))
+		mddi_host_reg_out(TEST, 0x2);
+
+	/* Need an even number for counts */
+	mddi_host_reg_out(DRIVER_START_CNT, 0x60006);
+
+#ifndef T_MSM7500
+	/* Setup defaults for MDP related register */
+	mddi_host_reg_out(MDP_VID_FMT_DES, 0x5666);
+	mddi_host_reg_out(MDP_VID_PIX_ATTR, 0x00C3);
+	mddi_host_reg_out(MDP_VID_CLIENTID, 0);
+#endif
+
+	/* automatically hibernate after 1 empty subframe */
+	if (pmhctl->disable_hibernation)
+		mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
+	else
+		mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
+
+	/* Bring up link if display (client) requests it */
+#ifdef MDDI_HOST_DISP_LISTEN
+	mddi_host_reg_out(CMD, MDDI_CMD_DISP_LISTEN);
+#else
+	mddi_host_reg_out(CMD, MDDI_CMD_DISP_IGNORE);
+#endif
+
+}
+
+void mddi_host_configure_interrupts(mddi_host_type host_idx, boolean enable)
+{
+	unsigned long flags;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+	/* turn on HCLK to MDDI host core if it has been disabled */
+	mddi_host_enable_hclk();
+	/* Clear MDDI Interrupt enable reg */
+	mddi_host_reg_out(INTEN, 0);
+
+	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+	if (enable) {
+		pmhctl->driver_state = MDDI_DRIVER_ENABLED;
+
+		if (host_idx == MDDI_HOST_PRIM) {
+			if (request_irq
+			    (INT_MDDI_PRI, mddi_pmdh_isr_proxy, IRQF_DISABLED,
+			     "PMDH", 0) != 0)
+				printk(KERN_ERR
+				       "a mddi: unable to request_irq\n");
+			else
+				int_mddi_pri_flag = TRUE;
+		} else {
+			if (request_irq
+			    (INT_MDDI_EXT, mddi_emdh_isr_proxy, IRQF_DISABLED,
+			     "EMDH", 0) != 0)
+				printk(KERN_ERR
+				       "b mddi: unable to request_irq\n");
+			else
+				int_mddi_ext_flag = TRUE;
+		}
+
+		/* Set MDDI Interrupt enable reg -- Enable Reverse data avail */
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+		mddi_host_reg_out(INTEN,
+				  MDDI_INT_ERROR_CONDITIONS |
+				  MDDI_INT_LINK_STATE_CHANGES);
+#else
+		/* Reverse Pointer register */
+		pmhctl->rev_ptr_written = FALSE;
+
+		mddi_host_reg_out(INTEN,
+				  MDDI_INT_REV_DATA_AVAIL |
+				  MDDI_INT_ERROR_CONDITIONS |
+				  MDDI_INT_LINK_STATE_CHANGES);
+		pmhctl->rtd_counter = mddi_rtd_frequency;
+		pmhctl->client_status_cnt = 0;
+#endif
+	} else {
+		if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
+			pmhctl->driver_state = MDDI_DRIVER_DISABLED;
+	}
+
+}
+
+static void mddi_host_powerup(mddi_host_type host_idx)
+{
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	if (pmhctl->link_state != MDDI_LINK_DISABLED)
+		return;
+
+	/* enable IO_CLK and hclk to MDDI host core */
+	mddi_host_enable_io_clock();
+
+	mddi_host_initialize_registers(host_idx);
+	mddi_host_configure_interrupts(host_idx, TRUE);
+
+	pmhctl->link_state = MDDI_LINK_ACTIVATING;
+
+	/* Link activate command */
+	mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
+
+#ifdef CLKRGM_MDDI_IO_CLOCK_IN_MHZ
+	MDDI_MSG_NOTICE("MDDI Host: Activating Link %d Mbps\n",
+			CLKRGM_MDDI_IO_CLOCK_IN_MHZ * 2);
+#else
+	MDDI_MSG_NOTICE("MDDI Host: Activating Link\n");
+#endif
+
+	/* Initialize the timer */
+	if (host_idx == MDDI_HOST_PRIM)
+		mddi_host_timer_service(0);
+}
+
+void mddi_host_init(mddi_host_type host_idx)
+/* Write out the MDDI configuration registers */
+{
+	static boolean initialized = FALSE;
+	mddi_host_cntl_type *pmhctl;
+
+	if (host_idx >= MDDI_NUM_HOST_CORES) {
+		MDDI_MSG_ERR("Invalid host core index\n");
+		return;
+	}
+
+	if (!initialized) {
+		uint16 idx;
+		mddi_host_type host;
+		for (host = MDDI_HOST_PRIM; host < MDDI_NUM_HOST_CORES; host++) {
+			pmhctl = &(mhctl[host]);
+			initialized = TRUE;
+
+			pmhctl->llist_ptr =
+			    dma_alloc_coherent(NULL, MDDI_LLIST_POOL_SIZE,
+					       &(pmhctl->llist_dma_addr),
+					       GFP_KERNEL);
+			pmhctl->llist_dma_ptr =
+			    (mddi_linked_list_type *) (void *)pmhctl->
+			    llist_dma_addr;
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+			pmhctl->rev_data_buf = NULL;
+			if (pmhctl->llist_ptr == NULL)
+#else
+			mddi_rev_user.waiting = FALSE;
+			init_completion(&(mddi_rev_user.done_comp));
+			pmhctl->rev_data_buf =
+			    dma_alloc_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
+					       &(pmhctl->rev_data_dma_addr),
+					       GFP_KERNEL);
+			if ((pmhctl->llist_ptr == NULL)
+			    || (pmhctl->rev_data_buf == NULL))
+#endif
+			{
+				MDDI_MSG_CRIT
+				    ("unable to alloc non-cached memory\n");
+			}
+			llist_extern[host] = pmhctl->llist_ptr;
+			llist_dma_extern[host] = pmhctl->llist_dma_ptr;
+			llist_extern_notify[host] = pmhctl->llist_notify;
+
+			for (idx = 0; idx < UNASSIGNED_INDEX; idx++) {
+				init_completion(&
+						(pmhctl->llist_notify[idx].
+						 done_comp));
+			}
+			init_completion(&(pmhctl->mddi_llist_avail_comp));
+			spin_lock_init(&mddi_host_spin_lock);
+			pmhctl->mddi_waiting_for_llist_avail = FALSE;
+			pmhctl->mddi_rev_ptr_write_val =
+			    (uint32) (void *)(pmhctl->rev_data_dma_addr);
+			pmhctl->rev_ptr_start = (void *)pmhctl->rev_data_buf;
+
+			pmhctl->rev_pkt_size = MDDI_DEFAULT_REV_PKT_SIZE;
+			pmhctl->rev_state = MDDI_REV_IDLE;
+#ifdef IMAGE_MODEM_PROC
+			/* assume hibernation state is last state from APPS proc, so that
+			 * we don't reinitialize the host core */
+			pmhctl->link_state = MDDI_LINK_HIBERNATING;
+#else
+			pmhctl->link_state = MDDI_LINK_DISABLED;
+#endif
+			pmhctl->driver_state = MDDI_DRIVER_DISABLED;
+			pmhctl->disable_hibernation = FALSE;
+
+			/* initialize llist variables */
+			pmhctl->llist_info.transmitting_start_idx =
+			    UNASSIGNED_INDEX;
+			pmhctl->llist_info.transmitting_end_idx =
+			    UNASSIGNED_INDEX;
+			pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
+			pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
+			pmhctl->llist_info.reg_read_idx = UNASSIGNED_INDEX;
+			pmhctl->llist_info.next_free_idx =
+			    MDDI_FIRST_DYNAMIC_LLIST_IDX;
+			pmhctl->llist_info.reg_read_waiting = FALSE;
+
+			mddi_vsync_detect_enabled = FALSE;
+			mddi_gpio.polling_enabled = FALSE;
+
+			pmhctl->int_type.count = 0;
+			pmhctl->int_type.in_count = 0;
+			pmhctl->int_type.disp_req_count = 0;
+			pmhctl->int_type.state_change_count = 0;
+			pmhctl->int_type.ll_done_count = 0;
+			pmhctl->int_type.rev_avail_count = 0;
+			pmhctl->int_type.error_count = 0;
+			pmhctl->int_type.rev_encap_count = 0;
+			pmhctl->int_type.llist_ptr_write_1 = 0;
+			pmhctl->int_type.llist_ptr_write_2 = 0;
+
+			pmhctl->stats.fwd_crc_count = 0;
+			pmhctl->stats.rev_crc_count = 0;
+			pmhctl->stats.pri_underflow = 0;
+			pmhctl->stats.sec_underflow = 0;
+			pmhctl->stats.rev_overflow = 0;
+			pmhctl->stats.pri_overwrite = 0;
+			pmhctl->stats.sec_overwrite = 0;
+			pmhctl->stats.rev_overwrite = 0;
+			pmhctl->stats.dma_failure = 0;
+			pmhctl->stats.rtd_failure = 0;
+			pmhctl->stats.reg_read_failure = 0;
+#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
+			pmhctl->stats.pri_underrun_detected = 0;
+#endif
+
+			pmhctl->log_parms.rtd_cnt = 0;
+			pmhctl->log_parms.rev_enc_cnt = 0;
+			pmhctl->log_parms.vid_cnt = 0;
+			pmhctl->log_parms.reg_acc_cnt = 0;
+			pmhctl->log_parms.cli_stat_cnt = 0;
+			pmhctl->log_parms.cli_cap_cnt = 0;
+			pmhctl->log_parms.reg_read_cnt = 0;
+			pmhctl->log_parms.link_active_cnt = 0;
+			pmhctl->log_parms.link_hibernate_cnt = 0;
+			pmhctl->log_parms.fwd_crc_cnt = 0;
+			pmhctl->log_parms.rev_crc_cnt = 0;
+			pmhctl->log_parms.vsync_response_cnt = 0;
+
+			prev_parms[host_idx] = pmhctl->log_parms;
+			mddi_client_capability_pkt.packet_length = 0;
+		}
+
+#ifndef T_MSM7500
+		/* tell clock driver we are user of this PLL */
+		MDDI_HOST_ENABLE_IO_CLOCK;
+#endif
+	}
+
+	mddi_host_powerup(host_idx);
+	pmhctl = &(mhctl[host_idx]);
+}
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+static uint32 mddi_client_id;
+
+uint32 mddi_get_client_id(void)
+{
+
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+	mddi_host_type host_idx = MDDI_HOST_PRIM;
+	static boolean client_detection_try = FALSE;
+	mddi_host_cntl_type *pmhctl;
+	unsigned long flags;
+	uint16 saved_rev_pkt_size;
+
+	if (!client_detection_try) {
+		/* Toshiba display requires larger drive_lo value */
+		mddi_host_reg_out(DRIVE_LO, 0x0050);
+
+		pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+		saved_rev_pkt_size = pmhctl->rev_pkt_size;
+
+		/* Increase Rev Encap Size */
+		pmhctl->rev_pkt_size = MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE;
+		mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
+
+		/* disable hibernation temporarily */
+		if (!pmhctl->disable_hibernation)
+			mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
+
+		mddi_rev_user.waiting = TRUE;
+		INIT_COMPLETION(mddi_rev_user.done_comp);
+
+		spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+		/* turn on clock(s), if they have been disabled */
+		mddi_host_enable_hclk();
+		mddi_host_enable_io_clock();
+
+		mddi_client_capability_request = TRUE;
+
+		if (pmhctl->rev_state == MDDI_REV_IDLE) {
+			/* attempt to send the reverse encapsulation now */
+			mddi_issue_reverse_encapsulation();
+		}
+		spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+		wait_for_completion_killable(&(mddi_rev_user.done_comp));
+
+		/* Set Rev Encap Size back to its original value */
+		pmhctl->rev_pkt_size = saved_rev_pkt_size;
+		mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
+
+		/* reenable auto-hibernate */
+		if (!pmhctl->disable_hibernation)
+			mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
+
+		mddi_host_reg_out(DRIVE_LO, 0x0032);
+		client_detection_try = TRUE;
+
+		mddi_client_id = (mddi_client_capability_pkt.Mfr_Name<<16) |
+				mddi_client_capability_pkt.Product_Code;
+
+		if (!mddi_client_id)
+			mddi_disable(1);
+	}
+
+#if 0
+	switch (mddi_client_capability_pkt.Mfr_Name) {
+	case 0x4474:
+		if ((mddi_client_capability_pkt.Product_Code != 0x8960) &&
+		    (target == DISPLAY_1)) {
+			ret = PRISM_WVGA;
+		}
+		break;
+
+	case 0xD263:
+		if (target == DISPLAY_1)
+			ret = TOSHIBA_VGA_PRIM;
+		else if (target == DISPLAY_2)
+			ret = TOSHIBA_QCIF_SECD;
+		break;
+
+	case 0:
+		if (mddi_client_capability_pkt.Product_Code == 0x8835) {
+			if (target == DISPLAY_1)
+				ret = SHARP_QVGA_PRIM;
+			else if (target == DISPLAY_2)
+				ret = SHARP_128x128_SECD;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	if ((!client_detection_try) && (ret != TOSHIBA_VGA_PRIM)
+	    && (ret != TOSHIBA_QCIF_SECD)) {
+		/* Not a Toshiba display, so change drive_lo back to default value */
+		mddi_host_reg_out(DRIVE_LO, 0x0032);
+	}
+#endif
+
+#endif
+
+	return mddi_client_id;
+}
+#endif
+
+void mddi_host_powerdown(mddi_host_type host_idx)
+{
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	if (host_idx >= MDDI_NUM_HOST_CORES) {
+		MDDI_MSG_ERR("Invalid host core index\n");
+		return;
+	}
+
+	if (pmhctl->driver_state == MDDI_DRIVER_RESET) {
+		return;
+	}
+
+	if (host_idx == MDDI_HOST_PRIM) {
+		/* disable timer */
+		del_timer(&mddi_host_timer);
+	}
+
+	mddi_host_configure_interrupts(host_idx, FALSE);
+
+	/* turn on HCLK to MDDI host core if it has been disabled */
+	mddi_host_enable_hclk();
+
+	/* MDDI Reset command */
+	mddi_host_reg_out(CMD, MDDI_CMD_RESET);
+
+	/* Pad Control Register */
+	mddi_host_reg_out(PAD_CTL, 0x0);
+
+	/* disable IO_CLK and hclk to MDDI host core */
+	mddi_host_disable_io_clock();
+	mddi_host_disable_hclk();
+
+	pmhctl->link_state = MDDI_LINK_DISABLED;
+	pmhctl->driver_state = MDDI_DRIVER_RESET;
+
+	MDDI_MSG_NOTICE("MDDI Host: Disabling Link\n");
+
+}
+
+uint16 mddi_get_next_free_llist_item(mddi_host_type host_idx, boolean wait)
+{
+	unsigned long flags;
+	uint16 ret_idx;
+	boolean forced_wait = FALSE;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	ret_idx = pmhctl->llist_info.next_free_idx;
+
+	pmhctl->llist_info.next_free_idx++;
+	if (pmhctl->llist_info.next_free_idx >= MDDI_NUM_DYNAMIC_LLIST_ITEMS)
+		pmhctl->llist_info.next_free_idx = MDDI_FIRST_DYNAMIC_LLIST_IDX;
+	spin_lock_irqsave(&mddi_host_spin_lock, flags);
+	if (pmhctl->llist_notify[ret_idx].in_use) {
+		if (!wait) {
+			pmhctl->llist_info.next_free_idx = ret_idx;
+			ret_idx = UNASSIGNED_INDEX;
+		} else {
+			forced_wait = TRUE;
+			INIT_COMPLETION(pmhctl->mddi_llist_avail_comp);
+		}
+	}
+	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+	if (forced_wait) {
+		wait_for_completion_killable(&
+						  (pmhctl->
+						   mddi_llist_avail_comp));
+		MDDI_MSG_ERR("task waiting on mddi llist item\n");
+	}
+
+	if (ret_idx != UNASSIGNED_INDEX) {
+		pmhctl->llist_notify[ret_idx].waiting = FALSE;
+		pmhctl->llist_notify[ret_idx].done_cb = NULL;
+		pmhctl->llist_notify[ret_idx].in_use = TRUE;
+		pmhctl->llist_notify[ret_idx].next_idx = UNASSIGNED_INDEX;
+	}
+
+	return ret_idx;
+}
+
+uint16 mddi_get_reg_read_llist_item(mddi_host_type host_idx, boolean wait)
+{
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+	MDDI_MSG_CRIT("No reverse link available\n");
+	(void)wait;
+	return FALSE;
+#else
+	unsigned long flags;
+	uint16 ret_idx;
+	boolean error = FALSE;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	spin_lock_irqsave(&mddi_host_spin_lock, flags);
+	if (pmhctl->llist_info.reg_read_idx != UNASSIGNED_INDEX) {
+		/* need to block here or is this an error condition? */
+		error = TRUE;
+		ret_idx = UNASSIGNED_INDEX;
+	}
+	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+	if (!error) {
+		ret_idx = pmhctl->llist_info.reg_read_idx =
+		    mddi_get_next_free_llist_item(host_idx, wait);
+		/* clear the reg_read_waiting flag */
+		pmhctl->llist_info.reg_read_waiting = FALSE;
+	}
+
+	if (error)
+		MDDI_MSG_ERR("***** Reg read still in progress! ****\n");
+	return ret_idx;
+#endif
+
+}
+
+void mddi_queue_forward_packets(uint16 first_llist_idx,
+				uint16 last_llist_idx,
+				boolean wait,
+				mddi_llist_done_cb_type llist_done_cb,
+				mddi_host_type host_idx)
+{
+	unsigned long flags;
+	mddi_linked_list_type *llist;
+	mddi_linked_list_type *llist_dma;
+	mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
+
+	if ((first_llist_idx >= UNASSIGNED_INDEX) ||
+	    (last_llist_idx >= UNASSIGNED_INDEX)) {
+		MDDI_MSG_ERR("MDDI queueing invalid linked list\n");
+		return;
+	}
+
+	if (pmhctl->link_state == MDDI_LINK_DISABLED)
+		MDDI_MSG_CRIT("MDDI host powered down!\n");
+
+	llist = pmhctl->llist_ptr;
+	llist_dma = pmhctl->llist_dma_ptr;
+
+	/* clean cache so MDDI host can read data */
+	memory_barrier();
+
+	pmhctl->llist_notify[last_llist_idx].waiting = wait;
+	if (wait)
+		INIT_COMPLETION(pmhctl->llist_notify[last_llist_idx].done_comp);
+	pmhctl->llist_notify[last_llist_idx].done_cb = llist_done_cb;
+
+	spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+	if ((pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
+	    (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
+	    (pmhctl->rev_state == MDDI_REV_IDLE)) {
+		/* no packets are currently transmitting */
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+		if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
+			/* This is the special case where the packet is a register read. */
+			pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
+			mddi_reg_read_retry = 0;
+			/* mddi_rev_reg_read_attempt = 1; */
+		}
+#endif
+		/* assign transmitting index values */
+		pmhctl->llist_info.transmitting_start_idx = first_llist_idx;
+		pmhctl->llist_info.transmitting_end_idx = last_llist_idx;
+
+		/* turn on clock(s), if they have been disabled */
+		mddi_host_enable_hclk();
+		mddi_host_enable_io_clock();
+		pmhctl->int_type.llist_ptr_write_1++;
+		/* Write to primary pointer register */
+		dma_coherent_pre_ops();
+		mddi_host_reg_out(PRI_PTR, &llist_dma[first_llist_idx]);
+
+		/* enable interrupt when complete */
+		mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
+				   MDDI_INT_PRI_LINK_LIST_DONE);
+
+	} else if (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) {
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+		if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
+			/*
+			 * we have a register read to send but need to wait
+			 * for current reverse activity to end or there are
+			 * packets currently transmitting
+			 */
+			/* mddi_rev_reg_read_attempt = 0; */
+			pmhctl->llist_info.reg_read_waiting = TRUE;
+		}
+#endif
+
+		/* assign waiting index values */
+		pmhctl->llist_info.waiting_start_idx = first_llist_idx;
+		pmhctl->llist_info.waiting_end_idx = last_llist_idx;
+	} else {
+		uint16 prev_end_idx = pmhctl->llist_info.waiting_end_idx;
+#ifndef FEATURE_MDDI_DISABLE_REVERSE
+		if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
+			/*
+			 * we have a register read to send but need to wait
+			 * for current reverse activity to end or there are
+			 * packets currently transmitting
+			 */
+			/* mddi_rev_reg_read_attempt = 0; */
+			pmhctl->llist_info.reg_read_waiting = TRUE;
+		}
+#endif
+
+		llist = pmhctl->llist_ptr;
+
+		/* clear end flag in previous last packet */
+		llist[prev_end_idx].link_controller_flags = 0;
+		pmhctl->llist_notify[prev_end_idx].next_idx = first_llist_idx;
+
+		/* set the next_packet_pointer of the previous last packet */
+		llist[prev_end_idx].next_packet_pointer =
+		    (void *)(&llist_dma[first_llist_idx]);
+
+		/* clean cache so MDDI host can read data */
+		memory_barrier();
+
+		/* assign new waiting last index value */
+		pmhctl->llist_info.waiting_end_idx = last_llist_idx;
+	}
+
+	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+}
+
+void mddi_host_write_pix_attr_reg(uint32 value)
+{
+	(void)value;
+}
+
+void mddi_queue_reverse_encapsulation(boolean wait)
+{
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+	MDDI_MSG_CRIT("No reverse link available\n");
+	(void)wait;
+#else
+	unsigned long flags;
+	boolean error = FALSE;
+	mddi_host_type host_idx = MDDI_HOST_PRIM;
+	mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+	spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+	/* turn on clock(s), if they have been disabled */
+	mddi_host_enable_hclk();
+	mddi_host_enable_io_clock();
+
+	if (wait) {
+		if (!mddi_rev_user.waiting) {
+			mddi_rev_user.waiting = TRUE;
+			INIT_COMPLETION(mddi_rev_user.done_comp);
+		} else
+			error = TRUE;
+	}
+	mddi_rev_encap_user_request = TRUE;
+
+	if (pmhctl->rev_state == MDDI_REV_IDLE) {
+		/* attempt to send the reverse encapsulation now */
+		mddi_host_type orig_host_idx = mddi_curr_host;
+		mddi_curr_host = host_idx;
+		mddi_issue_reverse_encapsulation();
+		mddi_curr_host = orig_host_idx;
+	}
+	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+	if (error) {
+		MDDI_MSG_ERR("Reverse Encap request already in progress\n");
+	} else if (wait)
+		wait_for_completion_killable(&(mddi_rev_user.done_comp));
+#endif
+}
+
+/* ISR to be executed */
+boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type)
+{
+#ifdef FEATURE_MDDI_DISABLE_REVERSE
+	MDDI_MSG_CRIT("No reverse link available\n");
+	(void)handler;
+	(void)pkt_type;
+	return (FALSE);
+#else
+	unsigned long flags;
+	uint16 hdlr;
+	boolean handler_set = FALSE;
+	boolean overwrite = FALSE;
+	mddi_host_type host_idx = MDDI_HOST_PRIM;
+	mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+	/* Disable interrupts */
+	spin_lock_irqsave(&mddi_host_spin_lock, flags);
+
+	for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
+		if (mddi_rev_pkt_handler[hdlr].pkt_type == pkt_type) {
+			mddi_rev_pkt_handler[hdlr].handler = handler;
+			if (handler == NULL) {
+				/* clearing handler from table */
+				mddi_rev_pkt_handler[hdlr].pkt_type =
+				    INVALID_PKT_TYPE;
+				handler_set = TRUE;
+				if (pkt_type == 0x10) {	/* video stream packet */
+					/* ensure HCLK on to MDDI host core before register write */
+					mddi_host_enable_hclk();
+					/* No longer getting video, so reset rev encap size to default */
+					pmhctl->rev_pkt_size =
+					    MDDI_DEFAULT_REV_PKT_SIZE;
+					mddi_host_reg_out(REV_ENCAP_SZ,
+							  pmhctl->rev_pkt_size);
+				}
+			} else {
+				/* already a handler for this packet */
+				overwrite = TRUE;
+			}
+			break;
+		}
+	}
+	if ((hdlr >= MAX_MDDI_REV_HANDLERS) && (handler != NULL)) {
+		/* assigning new handler */
+		for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
+			if (mddi_rev_pkt_handler[hdlr].pkt_type ==
+			    INVALID_PKT_TYPE) {
+				if ((pkt_type == 0x10) &&	/* video stream packet */
+				    (pmhctl->rev_pkt_size <
+				     MDDI_VIDEO_REV_PKT_SIZE)) {
+					/* ensure HCLK on to MDDI host core before register write */
+					mddi_host_enable_hclk();
+					/* Increase Rev Encap Size */
+					pmhctl->rev_pkt_size =
+					    MDDI_VIDEO_REV_PKT_SIZE;
+					mddi_host_reg_out(REV_ENCAP_SZ,
+							  pmhctl->rev_pkt_size);
+				}
+				mddi_rev_pkt_handler[hdlr].handler = handler;
+				mddi_rev_pkt_handler[hdlr].pkt_type = pkt_type;
+				handler_set = TRUE;
+				break;
+			}
+		}
+	}
+
+	/* Restore interrupts */
+	spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+
+	if (overwrite)
+		MDDI_MSG_ERR("Overwriting previous rev packet handler\n");
+
+	return handler_set;
+
+#endif
+}				/* mddi_set_rev_handler */
+
+void mddi_host_disable_hibernation(boolean disable)
+{
+	mddi_host_type host_idx = MDDI_HOST_PRIM;
+	mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
+
+	if (disable) {
+		pmhctl->disable_hibernation = TRUE;
+		/* hibernation will be turned off by isr next time it is entered */
+	} else {
+		if (pmhctl->disable_hibernation) {
+			unsigned long flags;
+			spin_lock_irqsave(&mddi_host_spin_lock, flags);
+			if (!MDDI_HOST_IS_HCLK_ON)
+				MDDI_HOST_ENABLE_HCLK;
+			mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
+			spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
+			pmhctl->disable_hibernation = FALSE;
+		}
+	}
+}
+
+void mddi_mhctl_remove(mddi_host_type host_idx)
+{
+	mddi_host_cntl_type *pmhctl;
+
+	pmhctl = &(mhctl[host_idx]);
+
+	dma_free_coherent(NULL, MDDI_LLIST_POOL_SIZE, (void *)pmhctl->llist_ptr,
+			  pmhctl->llist_dma_addr);
+
+	dma_free_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
+			  (void *)pmhctl->rev_data_buf,
+			  pmhctl->rev_data_dma_addr);
+}

+ 547 - 0
drivers/staging/msm/mddihosti.h

@@ -0,0 +1,547 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MDDIHOSTI_H
+#define MDDIHOSTI_H
+
+#include "msm_fb.h"
+#include "mddihost.h"
+#include <linux/clk.h>
+
+/* Register offsets in MDDI, applies to both msm_pmdh_base and
+ * (u32)msm_emdh_base. */
+#define MDDI_CMD   		0x0000
+#define MDDI_VERSION   		0x0004
+#define MDDI_PRI_PTR		0x0008
+#define MDDI_BPS		0x0010
+#define MDDI_SPM		0x0014
+#define MDDI_INT		0x0018
+#define MDDI_INTEN		0x001c
+#define MDDI_REV_PTR		0x0020
+#define MDDI_REV_SIZE		0x0024
+#define MDDI_STAT		0x0028
+#define MDDI_REV_RATE_DIV	0x002c
+#define MDDI_REV_CRC_ERR	0x0030
+#define MDDI_TA1_LEN		0x0034
+#define MDDI_TA2_LEN		0x0038
+#define MDDI_TEST		0x0040
+#define MDDI_REV_PKT_CNT	0x0044
+#define MDDI_DRIVE_HI		0x0048
+#define MDDI_DRIVE_LO		0x004c
+#define MDDI_DISP_WAKE		0x0050
+#define MDDI_REV_ENCAP_SZ	0x0054
+#define MDDI_RTD_VAL		0x0058
+#define MDDI_PAD_CTL		0x0068
+#define MDDI_DRIVER_START_CNT	0x006c
+#define MDDI_CORE_VER		0x008c
+#define MDDI_FIFO_ALLOC         0x0090
+#define MDDI_PAD_IO_CTL         0x00a0
+#define MDDI_PAD_CAL            0x00a4
+
+extern u32 mddi_msg_level;
+
+/* No longer need to write to clear these registers */
+#define xxxx_mddi_host_reg_outm(reg, mask, val)  \
+do { \
+	if (host_idx == MDDI_HOST_PRIM) \
+		mddi_host_reg_outm_pmdh(reg, mask, val); \
+	else \
+		mddi_host_reg_outm_emdh(reg, mask, val); \
+} while (0)
+
+#define mddi_host_reg_outm(reg, mask, val) \
+do { \
+	unsigned long __addr; \
+	if (host_idx == MDDI_HOST_PRIM) \
+		__addr = (u32)msm_pmdh_base + MDDI_##reg; \
+	else \
+		__addr = (u32)msm_emdh_base + MDDI_##reg; \
+	writel((readl(__addr) & ~(mask)) | ((val) & (mask)), __addr); \
+} while (0)
+
+#define xxxx_mddi_host_reg_out(reg, val) \
+do { \
+	if (host_idx == MDDI_HOST_PRIM)  \
+		mddi_host_reg_out_pmdh(reg, val); \
+	else \
+		mddi_host_reg_out_emdh(reg, val); \
+	} while (0)
+
+#define mddi_host_reg_out(reg, val) \
+do { \
+	if (host_idx == MDDI_HOST_PRIM) \
+		writel(val, (u32)msm_pmdh_base + MDDI_##reg); \
+	else \
+		writel(val, (u32)msm_emdh_base + MDDI_##reg); \
+} while (0)
+
+#define xxxx_mddi_host_reg_in(reg)  \
+  ((host_idx) ? \
+     mddi_host_reg_in_emdh(reg) : mddi_host_reg_in_pmdh(reg));
+
+#define mddi_host_reg_in(reg) \
+((host_idx) ? \
+	readl((u32)msm_emdh_base + MDDI_##reg) : \
+	readl((u32)msm_pmdh_base + MDDI_##reg)) \
+
+#define xxxx_mddi_host_reg_inm(reg, mask)  \
+  ((host_idx) ? \
+    mddi_host_reg_inm_emdh(reg, mask) : \
+    mddi_host_reg_inm_pmdh(reg, mask);)
+
+#define mddi_host_reg_inm(reg, mask) \
+((host_idx) ? \
+	readl((u32)msm_emdh_base + MDDI_##reg) & (mask) : \
+	readl((u32)msm_pmdh_base + MDDI_##reg) & (mask)) \
+
+/* Using non-cacheable pmem, so do nothing */
+#define mddi_invalidate_cache_lines(addr_start, num_bytes)
+/*
+ * Using non-cacheable pmem, so do nothing with cache
+ * but, ensure write goes out to memory
+ */
+#define mddi_flush_cache_lines(addr_start, num_bytes)  \
+    (void) addr_start; \
+    (void) num_bytes;  \
+    memory_barrier()
+
+/* Since this translates to Remote Procedure Calls to check on clock status
+* just use a local variable to keep track of io_clock */
+#define MDDI_HOST_IS_IO_CLOCK_ON mddi_host_io_clock_on
+#define MDDI_HOST_ENABLE_IO_CLOCK
+#define MDDI_HOST_DISABLE_IO_CLOCK
+#define MDDI_HOST_IS_HCLK_ON mddi_host_hclk_on
+#define MDDI_HOST_ENABLE_HCLK
+#define MDDI_HOST_DISABLE_HCLK
+#define FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE
+#define FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE
+
+#define TRAMP_MDDI_HOST_ISR TRAMP_MDDI_PRI_ISR
+#define TRAMP_MDDI_HOST_EXT_ISR TRAMP_MDDI_EXT_ISR
+#define MDP_LINE_COUNT_BMSK  0x3ff
+#define MDP_SYNC_STATUS  0x000c
+#define MDP_LINE_COUNT      \
+(readl(msm_mdp_base + MDP_SYNC_STATUS) & MDP_LINE_COUNT_BMSK)
+
+/* MDP sends 256 pixel packets, so lower value hibernates more without
+* significantly increasing latency of waiting for next subframe */
+#define MDDI_HOST_BYTES_PER_SUBFRAME  0x3C00
+
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
+#define MDDI_HOST_TA2_LEN       0x001a
+#define MDDI_HOST_REV_RATE_DIV  0x0004
+#else
+#define MDDI_HOST_TA2_LEN       0x000c
+#define MDDI_HOST_REV_RATE_DIV  0x0002
+#endif
+
+#define MDDI_MSG_EMERG(msg, ...)    \
+	if (mddi_msg_level > 0)  \
+		printk(KERN_EMERG msg, ## __VA_ARGS__);
+#define MDDI_MSG_ALERT(msg, ...)    \
+	if (mddi_msg_level > 1)  \
+		printk(KERN_ALERT msg, ## __VA_ARGS__);
+#define MDDI_MSG_CRIT(msg, ...)    \
+	if (mddi_msg_level > 2)  \
+		printk(KERN_CRIT msg, ## __VA_ARGS__);
+#define MDDI_MSG_ERR(msg, ...)    \
+	if (mddi_msg_level > 3)  \
+		printk(KERN_ERR msg, ## __VA_ARGS__);
+#define MDDI_MSG_WARNING(msg, ...)    \
+	if (mddi_msg_level > 4)  \
+		printk(KERN_WARNING msg, ## __VA_ARGS__);
+#define MDDI_MSG_NOTICE(msg, ...)    \
+	if (mddi_msg_level > 5)  \
+		printk(KERN_NOTICE msg, ## __VA_ARGS__);
+#define MDDI_MSG_INFO(msg, ...)    \
+	if (mddi_msg_level > 6)  \
+		printk(KERN_INFO msg, ## __VA_ARGS__);
+#define MDDI_MSG_DEBUG(msg, ...)    \
+	if (mddi_msg_level > 7)  \
+		printk(KERN_DEBUG msg, ## __VA_ARGS__);
+
+#define GCC_PACKED __attribute__((packed))
+typedef struct GCC_PACKED {
+	uint16 packet_length;
+	/* total # of bytes in the packet not including
+		the packet_length field. */
+
+	uint16 packet_type;
+	/* A Packet Type of 70 identifies the packet as
+		a Client status Packet. */
+
+	uint16 bClient_ID;
+	/* This field is reserved for future use and shall
+		be set to zero. */
+
+} mddi_rev_packet_type;
+
+typedef struct GCC_PACKED {
+	uint16 packet_length;
+	/* total # of bytes in the packet not including
+		the packet_length field. */
+
+	uint16 packet_type;
+	/* A Packet Type of 70 identifies the packet as
+		a Client status Packet. */
+
+	uint16 bClient_ID;
+	/* This field is reserved for future use and shall
+		be set to zero. */
+
+	uint16 reverse_link_request;
+	/* 16 bit unsigned integer with number of bytes client
+		needs in the * reverse encapsulation message
+		to transmit data. */
+
+	uint8 crc_error_count;
+	uint8 capability_change;
+	uint16 graphics_busy_flags;
+
+	uint16 parameter_CRC;
+	/* 16-bit CRC of all the bytes in the packet
+		including Packet Length. */
+
+} mddi_client_status_type;
+
+typedef struct GCC_PACKED {
+	uint16 packet_length;
+	/* total # of bytes in the packet not including
+		the packet_length field. */
+
+	uint16 packet_type;
+	/* A Packet Type of 66 identifies the packet as
+		a Client Capability Packet. */
+
+	uint16 bClient_ID;
+	/* This field is reserved for future use and
+		shall be set to zero. */
+
+	uint16 Protocol_Version;
+	uint16 Minimum_Protocol_Version;
+	uint16 Data_Rate_Capability;
+	uint8 Interface_Type_Capability;
+	uint8 Number_of_Alt_Displays;
+	uint16 PostCal_Data_Rate;
+	uint16 Bitmap_Width;
+	uint16 Bitmap_Height;
+	uint16 Display_Window_Width;
+	uint16 Display_Window_Height;
+	uint32 Color_Map_Size;
+	uint16 Color_Map_RGB_Width;
+	uint16 RGB_Capability;
+	uint8 Monochrome_Capability;
+	uint8 Reserved_1;
+	uint16 Y_Cb_Cr_Capability;
+	uint16 Bayer_Capability;
+	uint16 Alpha_Cursor_Image_Planes;
+	uint32 Client_Feature_Capability_Indicators;
+	uint8 Maximum_Video_Frame_Rate_Capability;
+	uint8 Minimum_Video_Frame_Rate_Capability;
+	uint16 Minimum_Sub_frame_Rate;
+	uint16 Audio_Buffer_Depth;
+	uint16 Audio_Channel_Capability;
+	uint16 Audio_Sample_Rate_Capability;
+	uint8 Audio_Sample_Resolution;
+	uint8 Mic_Audio_Sample_Resolution;
+	uint16 Mic_Sample_Rate_Capability;
+	uint8 Keyboard_Data_Format;
+	uint8 pointing_device_data_format;
+	uint16 content_protection_type;
+	uint16 Mfr_Name;
+	uint16 Product_Code;
+	uint16 Reserved_3;
+	uint32 Serial_Number;
+	uint8 Week_of_Manufacture;
+	uint8 Year_of_Manufacture;
+
+	uint16 parameter_CRC;
+	/* 16-bit CRC of all the bytes in the packet including Packet Length. */
+
+} mddi_client_capability_type;
+
+typedef struct GCC_PACKED {
+	uint16 packet_length;
+	/* total # of bytes in the packet not including the packet_length field. */
+
+	uint16 packet_type;
+	/* A Packet Type of 16 identifies the packet as a Video Stream Packet. */
+
+	uint16 bClient_ID;
+	/* This field is reserved for future use and shall be set to zero. */
+
+	uint16 video_data_format_descriptor;
+	/* format of each pixel in the Pixel Data in the present stream in the
+	 * present packet.
+	 * If bits [15:13] = 000 monochrome
+	 * If bits [15:13] = 001 color pixels (palette).
+	 * If bits [15:13] = 010 color pixels in raw RGB
+	 * If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format
+	 * If bits [15:13] = 100 Bayer pixels
+	 */
+
+	uint16 pixel_data_attributes;
+	/* interpreted as follows:
+	 * Bits [1:0] = 11  pixel data is displayed to both eyes
+	 * Bits [1:0] = 10  pixel data is routed to the left eye only.
+	 * Bits [1:0] = 01  pixel data is routed to the right eye only.
+	 * Bits [1:0] = 00  pixel data is routed to the alternate display.
+	 * Bit 2 is 0  Pixel Data is in the standard progressive format.
+	 * Bit 2 is 1  Pixel Data is in interlace format.
+	 * Bit 3 is 0  Pixel Data is in the standard progressive format.
+	 * Bit 3 is 1  Pixel Data is in alternate pixel format.
+	 * Bit 4 is 0  Pixel Data is to or from the display frame buffer.
+	 * Bit 4 is 1  Pixel Data is to or from the camera.
+	 * Bit 5 is 0  pixel data contains the next consecutive row of pixels.
+	 * Bit 5 is 1  X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge,
+	 *             X Start, and Y Start parameters are not defined and
+	 *             shall be ignored by the client.
+	 * Bits [7:6] = 01  Pixel data is written to the offline image buffer.
+	 * Bits [7:6] = 00  Pixel data is written to the buffer to refresh display.
+	 * Bits [7:6] = 11  Pixel data is written to all image buffers.
+	 * Bits [7:6] = 10  Invalid. Reserved for future use.
+	 * Bits 8 through 11 alternate display number.
+	 * Bits 12 through 14 are reserved for future use and shall be set to zero.
+	 * Bit 15 is 1 the row of pixels is the last row of pixels in a frame.
+	 */
+
+	uint16 x_left_edge;
+	uint16 y_top_edge;
+	/* X,Y coordinate of the top left edge of the screen window */
+
+	uint16 x_right_edge;
+	uint16 y_bottom_edge;
+	/*  X,Y coordinate of the bottom right edge of the window being updated. */
+
+	uint16 x_start;
+	uint16 y_start;
+	/*  (X Start, Y Start) is the first pixel in the Pixel Data field below. */
+
+	uint16 pixel_count;
+	/*  number of pixels in the Pixel Data field below. */
+
+	uint16 parameter_CRC;
+	/*  16-bit CRC of all bytes from the Packet Length to the Pixel Count. */
+
+	uint16 reserved;
+	/* 16-bit variable to make structure align on 4 byte boundary */
+
+} mddi_video_stream_packet_type;
+
+typedef struct GCC_PACKED {
+	uint16 packet_length;
+	/* total # of bytes in the packet not including the packet_length field. */
+
+	uint16 packet_type;
+	/* A Packet Type of 146 identifies the packet as a Register Access Packet. */
+
+	uint16 bClient_ID;
+	/* This field is reserved for future use and shall be set to zero. */
+
+	uint16 read_write_info;
+	/* Bits 13:0  a 14-bit unsigned integer that specifies the number of
+	 *            32-bit Register Data List items to be transferred in the
+	 *            Register Data List field.
+	 * Bits[15:14] = 00  Write to register(s);
+	 * Bits[15:14] = 10  Read from register(s);
+	 * Bits[15:14] = 11  Response to a Read.
+	 * Bits[15:14] = 01  this value is reserved for future use. */
+
+	uint32 register_address;
+	/* the register address that is to be written to or read from. */
+
+	uint16 parameter_CRC;
+	/* 16-bit CRC of all bytes from the Packet Length to the Register Address. */
+
+	uint32 register_data_list;
+	/* list of 4-byte register data values for/from client registers */
+
+} mddi_register_access_packet_type;
+
+typedef union GCC_PACKED {
+	mddi_video_stream_packet_type video_pkt;
+	mddi_register_access_packet_type register_pkt;
+	/* add 48 byte pad to ensure 64 byte llist struct, that can be
+	 * manipulated easily with cache */
+	uint32 alignment_pad[12];	/* 48 bytes */
+} mddi_packet_header_type;
+
+typedef struct GCC_PACKED mddi_host_llist_struct {
+	uint16 link_controller_flags;
+	uint16 packet_header_count;
+	uint16 packet_data_count;
+	void *packet_data_pointer;
+	struct mddi_host_llist_struct *next_packet_pointer;
+	uint16 reserved;
+	mddi_packet_header_type packet_header;
+} mddi_linked_list_type;
+
+typedef struct {
+	struct completion done_comp;
+	mddi_llist_done_cb_type done_cb;
+	uint16 next_idx;
+	boolean waiting;
+	boolean in_use;
+} mddi_linked_list_notify_type;
+
+#define MDDI_LLIST_POOL_SIZE 0x1000
+#define MDDI_MAX_NUM_LLIST_ITEMS (MDDI_LLIST_POOL_SIZE / \
+		 sizeof(mddi_linked_list_type))
+#define UNASSIGNED_INDEX MDDI_MAX_NUM_LLIST_ITEMS
+#define MDDI_FIRST_DYNAMIC_LLIST_IDX 0
+
+/* Static llist items can be used for applications that frequently send
+ * the same set of packets using the linked list interface. */
+/* Here we configure for 6 static linked list items:
+ *  The 1st is used for a the adaptive backlight setting.
+ *  and the remaining 5 are used for sending window adjustments for
+ *  MDDI clients that need windowing info sent separate from video
+ *  packets. */
+#define MDDI_NUM_STATIC_ABL_ITEMS 1
+#define MDDI_NUM_STATIC_WINDOW_ITEMS 5
+#define MDDI_NUM_STATIC_LLIST_ITEMS (MDDI_NUM_STATIC_ABL_ITEMS + \
+				MDDI_NUM_STATIC_WINDOW_ITEMS)
+#define MDDI_NUM_DYNAMIC_LLIST_ITEMS (MDDI_MAX_NUM_LLIST_ITEMS - \
+				MDDI_NUM_STATIC_LLIST_ITEMS)
+
+#define MDDI_FIRST_STATIC_LLIST_IDX  MDDI_NUM_DYNAMIC_LLIST_ITEMS
+#define MDDI_FIRST_STATIC_ABL_IDX  MDDI_FIRST_STATIC_LLIST_IDX
+#define MDDI_FIRST_STATIC_WINDOW_IDX  (MDDI_FIRST_STATIC_LLIST_IDX + \
+				MDDI_NUM_STATIC_ABL_ITEMS)
+
+/* GPIO registers */
+#define VSYNC_WAKEUP_REG          0x80
+#define GPIO_REG                  0x81
+#define GPIO_OUTPUT_REG           0x82
+#define GPIO_INTERRUPT_REG        0x83
+#define GPIO_INTERRUPT_ENABLE_REG 0x84
+#define GPIO_POLARITY_REG         0x85
+
+/* Interrupt Bits */
+#define MDDI_INT_PRI_PTR_READ       0x0001
+#define MDDI_INT_SEC_PTR_READ       0x0002
+#define MDDI_INT_REV_DATA_AVAIL     0x0004
+#define MDDI_INT_DISP_REQ           0x0008
+#define MDDI_INT_PRI_UNDERFLOW      0x0010
+#define MDDI_INT_SEC_UNDERFLOW      0x0020
+#define MDDI_INT_REV_OVERFLOW       0x0040
+#define MDDI_INT_CRC_ERROR          0x0080
+#define MDDI_INT_MDDI_IN            0x0100
+#define MDDI_INT_PRI_OVERWRITE      0x0200
+#define MDDI_INT_SEC_OVERWRITE      0x0400
+#define MDDI_INT_REV_OVERWRITE      0x0800
+#define MDDI_INT_DMA_FAILURE        0x1000
+#define MDDI_INT_LINK_ACTIVE        0x2000
+#define MDDI_INT_IN_HIBERNATION     0x4000
+#define MDDI_INT_PRI_LINK_LIST_DONE 0x8000
+#define MDDI_INT_SEC_LINK_LIST_DONE 0x10000
+#define MDDI_INT_NO_CMD_PKTS_PEND   0x20000
+#define MDDI_INT_RTD_FAILURE        0x40000
+
+#define MDDI_INT_ERROR_CONDITIONS ( \
+	MDDI_INT_PRI_UNDERFLOW | MDDI_INT_SEC_UNDERFLOW | \
+	MDDI_INT_REV_OVERFLOW | MDDI_INT_CRC_ERROR | \
+	MDDI_INT_PRI_OVERWRITE | MDDI_INT_SEC_OVERWRITE | \
+	MDDI_INT_RTD_FAILURE | \
+	MDDI_INT_REV_OVERWRITE | MDDI_INT_DMA_FAILURE)
+
+#define MDDI_INT_LINK_STATE_CHANGES ( \
+	MDDI_INT_LINK_ACTIVE | MDDI_INT_IN_HIBERNATION)
+
+/* Status Bits */
+#define MDDI_STAT_LINK_ACTIVE        0x0001
+#define MDDI_STAT_NEW_REV_PTR        0x0002
+#define MDDI_STAT_NEW_PRI_PTR        0x0004
+#define MDDI_STAT_NEW_SEC_PTR        0x0008
+#define MDDI_STAT_IN_HIBERNATION     0x0010
+#define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020
+#define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040
+#define MDDI_STAT_PENDING_TIMING_PKT 0x0080
+#define MDDI_STAT_PENDING_REV_ENCAP  0x0100
+#define MDDI_STAT_PENDING_POWERDOWN  0x0200
+#define MDDI_STAT_RTD_MEAS_FAIL      0x0800
+#define MDDI_STAT_CLIENT_WAKEUP_REQ  0x1000
+
+/* Command Bits */
+#define MDDI_CMD_POWERDOWN           0x0100
+#define MDDI_CMD_POWERUP             0x0200
+#define MDDI_CMD_HIBERNATE           0x0300
+#define MDDI_CMD_RESET               0x0400
+#define MDDI_CMD_DISP_IGNORE         0x0501
+#define MDDI_CMD_DISP_LISTEN         0x0500
+#define MDDI_CMD_SEND_REV_ENCAP      0x0600
+#define MDDI_CMD_GET_CLIENT_CAP      0x0601
+#define MDDI_CMD_GET_CLIENT_STATUS   0x0602
+#define MDDI_CMD_SEND_RTD            0x0700
+#define MDDI_CMD_LINK_ACTIVE         0x0900
+#define MDDI_CMD_PERIODIC_REV_ENCAP  0x0A00
+
+extern void mddi_host_init(mddi_host_type host);
+extern void mddi_host_powerdown(mddi_host_type host);
+extern uint16 mddi_get_next_free_llist_item(mddi_host_type host, boolean wait);
+extern uint16 mddi_get_reg_read_llist_item(mddi_host_type host, boolean wait);
+extern void mddi_queue_forward_packets(uint16 first_llist_idx,
+				       uint16 last_llist_idx,
+				       boolean wait,
+				       mddi_llist_done_cb_type llist_done_cb,
+				       mddi_host_type host);
+
+extern void mddi_host_write_pix_attr_reg(uint32 value);
+extern void mddi_client_lcd_gpio_poll(uint32 poll_reg_val);
+extern void mddi_client_lcd_vsync_detected(boolean detected);
+extern void mddi_host_disable_hibernation(boolean disable);
+
+extern mddi_linked_list_type *llist_extern[];
+extern mddi_linked_list_type *llist_dma_extern[];
+extern mddi_linked_list_notify_type *llist_extern_notify[];
+extern struct timer_list mddi_host_timer;
+
+typedef struct {
+	uint16 transmitting_start_idx;
+	uint16 transmitting_end_idx;
+	uint16 waiting_start_idx;
+	uint16 waiting_end_idx;
+	uint16 reg_read_idx;
+	uint16 next_free_idx;
+	boolean reg_read_waiting;
+} mddi_llist_info_type;
+
+extern mddi_llist_info_type mddi_llist;
+
+#define MDDI_GPIO_DEFAULT_POLLING_INTERVAL 200
+typedef struct {
+	uint32 polling_reg;
+	uint32 polling_val;
+	uint32 polling_interval;
+	boolean polling_enabled;
+} mddi_gpio_info_type;
+
+uint32 mddi_get_client_id(void);
+void mddi_mhctl_remove(mddi_host_type host_idx);
+void mddi_host_timer_service(unsigned long data);
+#endif /* MDDIHOSTI_H */

+ 1113 - 0
drivers/staging/msm/mdp.c

@@ -0,0 +1,1113 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#ifdef CONFIG_FB_MSM_MDP40
+#include "mdp4.h"
+#endif
+
+static struct clk *mdp_clk;
+static struct clk *mdp_pclk;
+
+struct completion mdp_ppp_comp;
+struct semaphore mdp_ppp_mutex;
+struct semaphore mdp_pipe_ctrl_mutex;
+
+unsigned long mdp_timer_duration = (HZ);   /* 1 sec */
+/* unsigned long mdp_mdp_timer_duration=0; */
+
+boolean mdp_ppp_waiting = FALSE;
+uint32 mdp_tv_underflow_cnt;
+uint32 mdp_lcdc_underflow_cnt;
+
+boolean mdp_current_clk_on = FALSE;
+boolean mdp_is_in_isr = FALSE;
+
+/*
+ * legacy mdp_in_processing is only for DMA2-MDDI
+ * this applies to DMA2 block only
+ */
+uint32 mdp_in_processing = FALSE;
+
+#ifdef CONFIG_FB_MSM_MDP40
+uint32 mdp_intr_mask = MDP4_ANY_INTR_MASK;
+#else
+uint32 mdp_intr_mask = MDP_ANY_INTR_MASK;
+#endif
+
+MDP_BLOCK_TYPE mdp_debug[MDP_MAX_BLOCK];
+
+int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
+
+spinlock_t mdp_spin_lock;
+struct workqueue_struct *mdp_dma_wq;	/*mdp dma wq */
+struct workqueue_struct *mdp_vsync_wq;	/*mdp vsync wq */
+
+static struct workqueue_struct *mdp_pipe_ctrl_wq; /* mdp mdp pipe ctrl wq */
+static struct delayed_work mdp_pipe_ctrl_worker;
+
+#ifdef CONFIG_FB_MSM_MDP40
+struct mdp_dma_data dma2_data;
+struct mdp_dma_data dma_s_data;
+struct mdp_dma_data dma_e_data;
+#else
+static struct mdp_dma_data dma2_data;
+static struct mdp_dma_data dma_s_data;
+static struct mdp_dma_data dma_e_data;
+#endif
+static struct mdp_dma_data dma3_data;
+
+extern ktime_t mdp_dma2_last_update_time;
+
+extern uint32 mdp_dma2_update_time_in_usec;
+extern int mdp_lcd_rd_cnt_offset_slow;
+extern int mdp_lcd_rd_cnt_offset_fast;
+extern int mdp_usec_diff_threshold;
+
+#ifdef CONFIG_FB_MSM_LCDC
+extern int mdp_lcdc_pclk_clk_rate;
+extern int mdp_lcdc_pad_pclk_clk_rate;
+extern int first_pixel_start_x;
+extern int first_pixel_start_y;
+#endif
+
+#ifdef MSM_FB_ENABLE_DBGFS
+struct dentry *mdp_dir;
+#endif
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int mdp_suspend(struct platform_device *pdev, pm_message_t state);
+#else
+#define mdp_suspend NULL
+#endif
+
+struct timeval mdp_dma2_timeval;
+struct timeval mdp_ppp_timeval;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static struct early_suspend early_suspend;
+#endif
+
+#ifndef CONFIG_FB_MSM_MDP22
+DEFINE_MUTEX(mdp_lut_push_sem);
+static int mdp_lut_i;
+static int mdp_lut_hw_update(struct fb_cmap *cmap)
+{
+	int i;
+	u16 *c[3];
+	u16 r, g, b;
+
+	c[0] = cmap->green;
+	c[1] = cmap->blue;
+	c[2] = cmap->red;
+
+	for (i = 0; i < cmap->len; i++) {
+		if (copy_from_user(&r, cmap->red++, sizeof(r)) ||
+		    copy_from_user(&g, cmap->green++, sizeof(g)) ||
+		    copy_from_user(&b, cmap->blue++, sizeof(b)))
+			return -EFAULT;
+
+#ifdef CONFIG_FB_MSM_MDP40
+		MDP_OUTP(MDP_BASE + 0x94800 +
+#else
+		MDP_OUTP(MDP_BASE + 0x93800 +
+#endif
+			(0x400*mdp_lut_i) + cmap->start*4 + i*4,
+				((g & 0xff) |
+				 ((b & 0xff) << 8) |
+				 ((r & 0xff) << 16)));
+	}
+
+	return 0;
+}
+
+static int mdp_lut_push;
+static int mdp_lut_push_i;
+static int mdp_lut_update_nonlcdc(struct fb_info *info, struct fb_cmap *cmap)
+{
+	int ret;
+
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	ret = mdp_lut_hw_update(cmap);
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+	if (ret)
+		return ret;
+
+	mutex_lock(&mdp_lut_push_sem);
+	mdp_lut_push = 1;
+	mdp_lut_push_i = mdp_lut_i;
+	mutex_unlock(&mdp_lut_push_sem);
+
+	mdp_lut_i = (mdp_lut_i + 1)%2;
+
+	return 0;
+}
+
+static int mdp_lut_update_lcdc(struct fb_info *info, struct fb_cmap *cmap)
+{
+	int ret;
+
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	ret = mdp_lut_hw_update(cmap);
+
+	if (ret) {
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+		return ret;
+	}
+
+	MDP_OUTP(MDP_BASE + 0x90070, (mdp_lut_i << 10) | 0x17);
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	mdp_lut_i = (mdp_lut_i + 1)%2;
+
+	return 0;
+}
+
+#define MDP_HIST_MAX_BIN 32
+static __u32 mdp_hist_r[MDP_HIST_MAX_BIN];
+static __u32 mdp_hist_g[MDP_HIST_MAX_BIN];
+static __u32 mdp_hist_b[MDP_HIST_MAX_BIN];
+
+#ifdef CONFIG_FB_MSM_MDP40
+struct mdp_histogram mdp_hist;
+struct completion mdp_hist_comp;
+#else
+static struct mdp_histogram mdp_hist;
+static struct completion mdp_hist_comp;
+#endif
+
+static int mdp_do_histogram(struct fb_info *info, struct mdp_histogram *hist)
+{
+	int ret = 0;
+
+	if (!hist->frame_cnt || (hist->bin_cnt == 0) ||
+				 (hist->bin_cnt > MDP_HIST_MAX_BIN))
+		return -EINVAL;
+
+	INIT_COMPLETION(mdp_hist_comp);
+
+	mdp_hist.bin_cnt = hist->bin_cnt;
+	mdp_hist.r = (hist->r) ? mdp_hist_r : 0;
+	mdp_hist.g = (hist->g) ? mdp_hist_g : 0;
+	mdp_hist.b = (hist->b) ? mdp_hist_b : 0;
+
+#ifdef CONFIG_FB_MSM_MDP40
+	MDP_OUTP(MDP_BASE + 0x95004, hist->frame_cnt);
+	MDP_OUTP(MDP_BASE + 0x95000, 1);
+#else
+	MDP_OUTP(MDP_BASE + 0x94004, hist->frame_cnt);
+	MDP_OUTP(MDP_BASE + 0x94000, 1);
+#endif
+	wait_for_completion_killable(&mdp_hist_comp);
+
+	if (hist->r) {
+		ret = copy_to_user(hist->r, mdp_hist.r, hist->bin_cnt*4);
+		if (ret)
+			goto hist_err;
+	}
+	if (hist->g) {
+		ret = copy_to_user(hist->g, mdp_hist.g, hist->bin_cnt*4);
+		if (ret)
+			goto hist_err;
+	}
+	if (hist->b) {
+		ret = copy_to_user(hist->b, mdp_hist.b, hist->bin_cnt*4);
+		if (ret)
+			goto hist_err;
+	}
+	return 0;
+
+hist_err:
+	printk(KERN_ERR "%s: invalid hist buffer\n", __func__);
+	return ret;
+}
+#endif
+
+/* Returns < 0 on error, 0 on timeout, or > 0 on successful wait */
+
+int mdp_ppp_pipe_wait(void)
+{
+	int ret = 1;
+
+	/* wait 5 seconds for the operation to complete before declaring
+	the MDP hung */
+
+	if (mdp_ppp_waiting == TRUE) {
+		ret = wait_for_completion_interruptible_timeout(&mdp_ppp_comp,
+								5 * HZ);
+
+		if (!ret)
+			printk(KERN_ERR "%s: Timed out waiting for the MDP.\n",
+					__func__);
+	}
+
+	return ret;
+}
+
+static DEFINE_SPINLOCK(mdp_lock);
+static int mdp_irq_mask;
+static int mdp_irq_enabled;
+
+void mdp_enable_irq(uint32 term)
+{
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&mdp_lock, irq_flags);
+	if (mdp_irq_mask & term) {
+		printk(KERN_ERR "MDP IRQ term-0x%x is already set\n", term);
+	} else {
+		mdp_irq_mask |= term;
+		if (mdp_irq_mask && !mdp_irq_enabled) {
+			mdp_irq_enabled = 1;
+			enable_irq(INT_MDP);
+		}
+	}
+	spin_unlock_irqrestore(&mdp_lock, irq_flags);
+}
+
+void mdp_disable_irq(uint32 term)
+{
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&mdp_lock, irq_flags);
+	if (!(mdp_irq_mask & term)) {
+		printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term);
+	} else {
+		mdp_irq_mask &= ~term;
+		if (!mdp_irq_mask && mdp_irq_enabled) {
+			mdp_irq_enabled = 0;
+			disable_irq(INT_MDP);
+		}
+	}
+	spin_unlock_irqrestore(&mdp_lock, irq_flags);
+}
+
+void mdp_disable_irq_nolock(uint32 term)
+{
+
+	if (!(mdp_irq_mask & term)) {
+		printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term);
+	} else {
+		mdp_irq_mask &= ~term;
+		if (!mdp_irq_mask && mdp_irq_enabled) {
+			mdp_irq_enabled = 0;
+			disable_irq(INT_MDP);
+		}
+	}
+}
+
+void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd)
+{
+
+	dmb();	/* memory barrier */
+
+	/* kick off PPP engine */
+	if (term == MDP_PPP_TERM) {
+		if (mdp_debug[MDP_PPP_BLOCK])
+			jiffies_to_timeval(jiffies, &mdp_ppp_timeval);
+
+		/* let's turn on PPP block */
+		mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+		mdp_enable_irq(term);
+		INIT_COMPLETION(mdp_ppp_comp);
+		mdp_ppp_waiting = TRUE;
+		outpdw(MDP_BASE + 0x30, 0x1000);
+		wait_for_completion_killable(&mdp_ppp_comp);
+		mdp_disable_irq(term);
+
+		if (mdp_debug[MDP_PPP_BLOCK]) {
+			struct timeval now;
+
+			jiffies_to_timeval(jiffies, &now);
+			mdp_ppp_timeval.tv_usec =
+			    now.tv_usec - mdp_ppp_timeval.tv_usec;
+			MSM_FB_INFO("MDP-PPP: %d\n",
+				    (int)mdp_ppp_timeval.tv_usec);
+		}
+	} else if (term == MDP_DMA2_TERM) {
+		if (mdp_debug[MDP_DMA2_BLOCK]) {
+			MSM_FB_INFO("MDP-DMA2: %d\n",
+				    (int)mdp_dma2_timeval.tv_usec);
+			jiffies_to_timeval(jiffies, &mdp_dma2_timeval);
+		}
+		/* DMA update timestamp */
+		mdp_dma2_last_update_time = ktime_get_real();
+		/* let's turn on DMA2 block */
+#if 0
+		mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+#endif
+#ifdef CONFIG_FB_MSM_MDP22
+		outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x0044, 0x0);/* start DMA */
+#else
+		if (mdp_lut_push) {
+			mutex_lock(&mdp_lut_push_sem);
+			mdp_lut_push = 0;
+			MDP_OUTP(MDP_BASE + 0x90070,
+					(mdp_lut_push_i << 10) | 0x17);
+			mutex_unlock(&mdp_lut_push_sem);
+		}
+#ifdef CONFIG_FB_MSM_MDP40
+		outpdw(MDP_BASE + 0x000c, 0x0);	/* start DMA */
+#else
+		outpdw(MDP_BASE + 0x0044, 0x0);	/* start DMA */
+#endif
+#endif
+#ifdef CONFIG_FB_MSM_MDP40
+	} else if (term == MDP_DMA_S_TERM) {
+		mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+		outpdw(MDP_BASE + 0x0010, 0x0);	/* start DMA */
+	} else if (term == MDP_DMA_E_TERM) {
+		mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+		outpdw(MDP_BASE + 0x0014, 0x0);	/* start DMA */
+	} else if (term == MDP_OVERLAY0_TERM) {
+		mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+		outpdw(MDP_BASE + 0x0004, 0);
+	} else if (term == MDP_OVERLAY1_TERM) {
+		mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+		outpdw(MDP_BASE + 0x0008, 0);
+	}
+#else
+	} else if (term == MDP_DMA_S_TERM) {
+		mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+		outpdw(MDP_BASE + 0x0048, 0x0);	/* start DMA */
+	}
+#endif
+}
+
+static void mdp_pipe_ctrl_workqueue_handler(struct work_struct *work)
+{
+	mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+		   boolean isr)
+{
+	boolean mdp_all_blocks_off = TRUE;
+	int i;
+	unsigned long flag;
+
+	spin_lock_irqsave(&mdp_spin_lock, flag);
+	if (MDP_BLOCK_POWER_ON == state) {
+		mdp_block_power_cnt[block]++;
+
+		if (MDP_DMA2_BLOCK == block)
+			mdp_in_processing = TRUE;
+	} else {
+		mdp_block_power_cnt[block]--;
+
+		if (mdp_block_power_cnt[block] < 0) {
+			/*
+			* Master has to serve a request to power off MDP always
+			* It also has a timer to power off.  So, in case of
+			* timer expires first and DMA2 finishes later,
+			* master has to power off two times
+			* There shouldn't be multiple power-off request for
+			* other blocks
+			*/
+			if (block != MDP_MASTER_BLOCK) {
+				MSM_FB_INFO("mdp_block_power_cnt[block=%d] \
+				multiple power-off request\n", block);
+			}
+			mdp_block_power_cnt[block] = 0;
+		}
+
+		if (MDP_DMA2_BLOCK == block)
+			mdp_in_processing = FALSE;
+	}
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+	/*
+	 * If it's in isr, we send our request to workqueue.
+	 * Otherwise, processing happens in the current context
+	 */
+	if (isr) {
+		/* checking all blocks power state */
+		for (i = 0; i < MDP_MAX_BLOCK; i++) {
+			if (mdp_block_power_cnt[i] > 0)
+				mdp_all_blocks_off = FALSE;
+		}
+
+		if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
+			/* send workqueue to turn off mdp power */
+			queue_delayed_work(mdp_pipe_ctrl_wq,
+					   &mdp_pipe_ctrl_worker,
+					   mdp_timer_duration);
+		}
+	} else {
+		down(&mdp_pipe_ctrl_mutex);
+		/* checking all blocks power state */
+		for (i = 0; i < MDP_MAX_BLOCK; i++) {
+			if (mdp_block_power_cnt[i] > 0)
+				mdp_all_blocks_off = FALSE;
+		}
+
+		/*
+		 * find out whether a delayable work item is currently
+		 * pending
+		 */
+
+		if (delayed_work_pending(&mdp_pipe_ctrl_worker)) {
+			/*
+			 * try to cancel the current work if it fails to
+			 * stop (which means del_timer can't delete it
+			 * from the list, it's about to expire and run),
+			 * we have to let it run. queue_delayed_work won't
+			 * accept the next job which is same as
+			 * queue_delayed_work(mdp_timer_duration = 0)
+			 */
+			cancel_delayed_work(&mdp_pipe_ctrl_worker);
+		}
+
+		if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
+			if (block == MDP_MASTER_BLOCK) {
+				mdp_current_clk_on = FALSE;
+				/* turn off MDP clks */
+				if (mdp_clk != NULL) {
+					clk_disable(mdp_clk);
+					MSM_FB_DEBUG("MDP CLK OFF\n");
+				}
+				if (mdp_pclk != NULL) {
+					clk_disable(mdp_pclk);
+					MSM_FB_DEBUG("MDP PCLK OFF\n");
+				}
+			} else {
+				/* send workqueue to turn off mdp power */
+				queue_delayed_work(mdp_pipe_ctrl_wq,
+						   &mdp_pipe_ctrl_worker,
+						   mdp_timer_duration);
+			}
+		} else if ((!mdp_all_blocks_off) && (!mdp_current_clk_on)) {
+			mdp_current_clk_on = TRUE;
+			/* turn on MDP clks */
+			if (mdp_clk != NULL) {
+				clk_enable(mdp_clk);
+				MSM_FB_DEBUG("MDP CLK ON\n");
+			}
+			if (mdp_pclk != NULL) {
+				clk_enable(mdp_pclk);
+				MSM_FB_DEBUG("MDP PCLK ON\n");
+			}
+		}
+		up(&mdp_pipe_ctrl_mutex);
+	}
+}
+
+#ifndef CONFIG_FB_MSM_MDP40
+irqreturn_t mdp_isr(int irq, void *ptr)
+{
+	uint32 mdp_interrupt = 0;
+	struct mdp_dma_data *dma;
+
+	mdp_is_in_isr = TRUE;
+	do {
+		mdp_interrupt = inp32(MDP_INTR_STATUS);
+		outp32(MDP_INTR_CLEAR, mdp_interrupt);
+
+		mdp_interrupt &= mdp_intr_mask;
+
+		if (mdp_interrupt & TV_ENC_UNDERRUN) {
+			mdp_interrupt &= ~(TV_ENC_UNDERRUN);
+			mdp_tv_underflow_cnt++;
+		}
+
+		if (!mdp_interrupt)
+			break;
+
+		/* DMA3 TV-Out Start */
+		if (mdp_interrupt & TV_OUT_DMA3_START) {
+			/* let's disable TV out interrupt */
+			mdp_intr_mask &= ~TV_OUT_DMA3_START;
+			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+
+			dma = &dma3_data;
+			if (dma->waiting) {
+				dma->waiting = FALSE;
+				complete(&dma->comp);
+			}
+		}
+#ifndef CONFIG_FB_MSM_MDP22
+		if (mdp_interrupt & MDP_HIST_DONE) {
+			outp32(MDP_BASE + 0x94018, 0x3);
+			outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
+			if (mdp_hist.r)
+				memcpy(mdp_hist.r, MDP_BASE + 0x94100,
+						mdp_hist.bin_cnt*4);
+			if (mdp_hist.g)
+				memcpy(mdp_hist.g, MDP_BASE + 0x94200,
+						mdp_hist.bin_cnt*4);
+			if (mdp_hist.b)
+				memcpy(mdp_hist.b, MDP_BASE + 0x94300,
+						mdp_hist.bin_cnt*4);
+			complete(&mdp_hist_comp);
+		}
+
+		/* LCDC UnderFlow */
+		if (mdp_interrupt & LCDC_UNDERFLOW) {
+			mdp_lcdc_underflow_cnt++;
+		}
+		/* LCDC Frame Start */
+		if (mdp_interrupt & LCDC_FRAME_START) {
+			/* let's disable LCDC interrupt */
+			mdp_intr_mask &= ~LCDC_FRAME_START;
+			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+
+			dma = &dma2_data;
+			if (dma->waiting) {
+				dma->waiting = FALSE;
+				complete(&dma->comp);
+			}
+		}
+
+		/* DMA2 LCD-Out Complete */
+		if (mdp_interrupt & MDP_DMA_S_DONE) {
+			dma = &dma_s_data;
+			dma->busy = FALSE;
+			mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF,
+				      TRUE);
+			complete(&dma->comp);
+		}
+#endif
+
+		/* DMA2 LCD-Out Complete */
+		if (mdp_interrupt & MDP_DMA_P_DONE) {
+			struct timeval now;
+			ktime_t now_k;
+
+			now_k = ktime_get_real();
+			mdp_dma2_last_update_time.tv.sec =
+			    now_k.tv.sec - mdp_dma2_last_update_time.tv.sec;
+			mdp_dma2_last_update_time.tv.nsec =
+			    now_k.tv.nsec - mdp_dma2_last_update_time.tv.nsec;
+
+			if (mdp_debug[MDP_DMA2_BLOCK]) {
+				jiffies_to_timeval(jiffies, &now);
+				mdp_dma2_timeval.tv_usec =
+				    now.tv_usec - mdp_dma2_timeval.tv_usec;
+			}
+
+			dma = &dma2_data;
+			dma->busy = FALSE;
+			mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF,
+				      TRUE);
+			complete(&dma->comp);
+		}
+		/* PPP Complete */
+		if (mdp_interrupt & MDP_PPP_DONE) {
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+			mdp_ppp_djob_done();
+#else
+			mdp_pipe_ctrl(MDP_PPP_BLOCK,
+				MDP_BLOCK_POWER_OFF, TRUE);
+			if (mdp_ppp_waiting) {
+				mdp_ppp_waiting = FALSE;
+				complete(&mdp_ppp_comp);
+			}
+#endif
+		}
+	} while (1);
+
+	mdp_is_in_isr = FALSE;
+
+	return IRQ_HANDLED;
+}
+#endif
+
+static void mdp_drv_init(void)
+{
+	int i;
+
+	for (i = 0; i < MDP_MAX_BLOCK; i++) {
+		mdp_debug[i] = 0;
+	}
+
+	/* initialize spin lock and workqueue */
+	spin_lock_init(&mdp_spin_lock);
+	mdp_dma_wq = create_singlethread_workqueue("mdp_dma_wq");
+	mdp_vsync_wq = create_singlethread_workqueue("mdp_vsync_wq");
+	mdp_pipe_ctrl_wq = create_singlethread_workqueue("mdp_pipe_ctrl_wq");
+	INIT_DELAYED_WORK(&mdp_pipe_ctrl_worker,
+			  mdp_pipe_ctrl_workqueue_handler);
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+	mdp_ppp_dq_init();
+#endif
+
+	/* initialize semaphore */
+	init_completion(&mdp_ppp_comp);
+	init_MUTEX(&mdp_ppp_mutex);
+	init_MUTEX(&mdp_pipe_ctrl_mutex);
+
+	dma2_data.busy = FALSE;
+	dma2_data.waiting = FALSE;
+	init_completion(&dma2_data.comp);
+	init_MUTEX(&dma2_data.mutex);
+	mutex_init(&dma2_data.ov_mutex);
+
+	dma3_data.busy = FALSE;
+	dma3_data.waiting = FALSE;
+	init_completion(&dma3_data.comp);
+	init_MUTEX(&dma3_data.mutex);
+
+	dma_s_data.busy = FALSE;
+	dma_s_data.waiting = FALSE;
+	init_completion(&dma_s_data.comp);
+	init_MUTEX(&dma_s_data.mutex);
+
+	dma_e_data.busy = FALSE;
+	dma_e_data.waiting = FALSE;
+	init_completion(&dma_e_data.comp);
+
+#ifndef CONFIG_FB_MSM_MDP22
+	init_completion(&mdp_hist_comp);
+#endif
+
+	/* initializing mdp power block counter to 0 */
+	for (i = 0; i < MDP_MAX_BLOCK; i++) {
+		mdp_block_power_cnt[i] = 0;
+	}
+
+#ifdef MSM_FB_ENABLE_DBGFS
+	{
+		struct dentry *root;
+		char sub_name[] = "mdp";
+
+		root = msm_fb_get_debugfs_root();
+		if (root != NULL) {
+			mdp_dir = debugfs_create_dir(sub_name, root);
+
+			if (mdp_dir) {
+				msm_fb_debugfs_file_create(mdp_dir,
+					"dma2_update_time_in_usec",
+					(u32 *) &mdp_dma2_update_time_in_usec);
+				msm_fb_debugfs_file_create(mdp_dir,
+					"vs_rdcnt_slow",
+					(u32 *) &mdp_lcd_rd_cnt_offset_slow);
+				msm_fb_debugfs_file_create(mdp_dir,
+					"vs_rdcnt_fast",
+					(u32 *) &mdp_lcd_rd_cnt_offset_fast);
+				msm_fb_debugfs_file_create(mdp_dir,
+					"mdp_usec_diff_threshold",
+					(u32 *) &mdp_usec_diff_threshold);
+				msm_fb_debugfs_file_create(mdp_dir,
+					"mdp_current_clk_on",
+					(u32 *) &mdp_current_clk_on);
+#ifdef CONFIG_FB_MSM_LCDC
+				msm_fb_debugfs_file_create(mdp_dir,
+					"lcdc_start_x",
+					(u32 *) &first_pixel_start_x);
+				msm_fb_debugfs_file_create(mdp_dir,
+					"lcdc_start_y",
+					(u32 *) &first_pixel_start_y);
+				msm_fb_debugfs_file_create(mdp_dir,
+					"mdp_lcdc_pclk_clk_rate",
+					(u32 *) &mdp_lcdc_pclk_clk_rate);
+				msm_fb_debugfs_file_create(mdp_dir,
+					"mdp_lcdc_pad_pclk_clk_rate",
+					(u32 *) &mdp_lcdc_pad_pclk_clk_rate);
+#endif
+			}
+		}
+	}
+#endif
+}
+
+static int mdp_probe(struct platform_device *pdev);
+static int mdp_remove(struct platform_device *pdev);
+
+static struct platform_driver mdp_driver = {
+	.probe = mdp_probe,
+	.remove = mdp_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+	.suspend = mdp_suspend,
+	.resume = NULL,
+#endif
+	.shutdown = NULL,
+	.driver = {
+		/*
+		 * Driver name must match the device name added in
+		 * platform.c.
+		 */
+		.name = "mdp",
+	},
+};
+
+static int mdp_off(struct platform_device *pdev)
+{
+	int ret = 0;
+
+#ifdef MDP_HW_VSYNC
+	struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+#endif
+
+	ret = panel_next_off(pdev);
+
+#ifdef MDP_HW_VSYNC
+	mdp_hw_vsync_clk_disable(mfd);
+#endif
+
+	return ret;
+}
+
+static int mdp_on(struct platform_device *pdev)
+{
+#ifdef MDP_HW_VSYNC
+	struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+#endif
+
+	int ret = 0;
+
+#ifdef MDP_HW_VSYNC
+	mdp_hw_vsync_clk_enable(mfd);
+#endif
+
+	ret = panel_next_on(pdev);
+
+	return ret;
+}
+
+static int mdp_irq_clk_setup(void)
+{
+	int ret;
+
+#ifdef CONFIG_FB_MSM_MDP40
+	ret = request_irq(INT_MDP, mdp4_isr, IRQF_DISABLED, "MDP", 0);
+#else
+	ret = request_irq(INT_MDP, mdp_isr, IRQF_DISABLED, "MDP", 0);
+#endif
+	if (ret) {
+		printk(KERN_ERR "mdp request_irq() failed!\n");
+		return ret;
+	}
+	disable_irq(INT_MDP);
+
+	mdp_clk = clk_get(NULL, "mdp_clk");
+
+	if (IS_ERR(mdp_clk)) {
+		ret = PTR_ERR(mdp_clk);
+		printk(KERN_ERR "can't get mdp_clk error:%d!\n", ret);
+		free_irq(INT_MDP, 0);
+		return ret;
+	}
+
+	mdp_pclk = clk_get(NULL, "mdp_pclk");
+	if (IS_ERR(mdp_pclk))
+		mdp_pclk = NULL;
+
+
+#ifdef CONFIG_FB_MSM_MDP40
+	/*
+	 * mdp_clk should greater than mdp_pclk always
+	 */
+	clk_set_rate(mdp_clk, 122880000); /* 122.88 Mhz */
+	printk(KERN_INFO "mdp_clk: mdp_clk=%d mdp_pclk=%d\n",
+		(int)clk_get_rate(mdp_clk), (int)clk_get_rate(mdp_pclk));
+#endif
+
+	return 0;
+}
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+static int mdp_resource_initialized;
+static struct msm_panel_common_pdata *mdp_pdata;
+
+static int mdp_probe(struct platform_device *pdev)
+{
+	struct platform_device *msm_fb_dev = NULL;
+	struct msm_fb_data_type *mfd;
+	struct msm_fb_panel_data *pdata = NULL;
+	int rc;
+	resource_size_t  size ;
+#ifdef CONFIG_FB_MSM_MDP40
+	int intf, if_no;
+#else
+	unsigned long flag;
+#endif
+
+	if ((pdev->id == 0) && (pdev->num_resources > 0)) {
+		mdp_pdata = pdev->dev.platform_data;
+
+		size =  resource_size(&pdev->resource[0]);
+		msm_mdp_base = ioremap(pdev->resource[0].start, size);
+
+		MSM_FB_INFO("MDP HW Base phy_Address = 0x%x virt = 0x%x\n",
+			(int)pdev->resource[0].start, (int)msm_mdp_base);
+
+		if (unlikely(!msm_mdp_base))
+			return -ENOMEM;
+
+		printk("irq clk setup\n");
+		rc = mdp_irq_clk_setup();
+		printk("irq clk setup done\n");
+		if (rc)
+			return rc;
+
+		/* initializing mdp hw */
+#ifdef CONFIG_FB_MSM_MDP40
+		mdp4_hw_init();
+#else
+		mdp_hw_init();
+#endif
+
+		mdp_resource_initialized = 1;
+		return 0;
+	}
+
+	if (!mdp_resource_initialized)
+		return -EPERM;
+
+	mfd = platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+		return -ENOMEM;
+
+	msm_fb_dev = platform_device_alloc("msm_fb", pdev->id);
+	if (!msm_fb_dev)
+		return -ENOMEM;
+
+	/* link to the latest pdev */
+	mfd->pdev = msm_fb_dev;
+
+	/* add panel data */
+	if (platform_device_add_data
+	    (msm_fb_dev, pdev->dev.platform_data,
+	     sizeof(struct msm_fb_panel_data))) {
+		printk(KERN_ERR "mdp_probe: platform_device_add_data failed!\n");
+		rc = -ENOMEM;
+		goto mdp_probe_err;
+	}
+	/* data chain */
+	pdata = msm_fb_dev->dev.platform_data;
+	pdata->on = mdp_on;
+	pdata->off = mdp_off;
+	pdata->next = pdev;
+
+	switch (mfd->panel.type) {
+	case EXT_MDDI_PANEL:
+	case MDDI_PANEL:
+	case EBI2_PANEL:
+		INIT_WORK(&mfd->dma_update_worker,
+			  mdp_lcd_update_workqueue_handler);
+		INIT_WORK(&mfd->vsync_resync_worker,
+			  mdp_vsync_resync_workqueue_handler);
+		mfd->hw_refresh = FALSE;
+
+		if (mfd->panel.type == EXT_MDDI_PANEL) {
+			/* 15 fps -> 66 msec */
+			mfd->refresh_timer_duration = (66 * HZ / 1000);
+		} else {
+			/* 24 fps -> 42 msec */
+			mfd->refresh_timer_duration = (42 * HZ / 1000);
+		}
+
+#ifdef CONFIG_FB_MSM_MDP22
+		mfd->dma_fnc = mdp_dma2_update;
+		mfd->dma = &dma2_data;
+#else
+		if (mfd->panel_info.pdest == DISPLAY_1) {
+#ifdef CONFIG_FB_MSM_OVERLAY
+			mfd->dma_fnc = mdp4_mddi_overlay;
+#else
+			mfd->dma_fnc = mdp_dma2_update;
+#endif
+			mfd->dma = &dma2_data;
+			mfd->lut_update = mdp_lut_update_nonlcdc;
+			mfd->do_histogram = mdp_do_histogram;
+		} else {
+			mfd->dma_fnc = mdp_dma_s_update;
+			mfd->dma = &dma_s_data;
+		}
+#endif
+		if (mdp_pdata)
+			mfd->vsync_gpio = mdp_pdata->gpio;
+		else
+			mfd->vsync_gpio = -1;
+
+#ifdef CONFIG_FB_MSM_MDP40
+		if (mfd->panel.type == EBI2_PANEL)
+			intf = EBI2_INTF;
+		else
+			intf = MDDI_INTF;
+
+		if (mfd->panel_info.pdest == DISPLAY_1)
+			if_no = PRIMARY_INTF_SEL;
+		else
+			if_no = SECONDARY_INTF_SEL;
+
+		mdp4_display_intf_sel(if_no, intf);
+#endif
+		mdp_config_vsync(mfd);
+		break;
+
+	case HDMI_PANEL:
+	case LCDC_PANEL:
+		pdata->on = mdp_lcdc_on;
+		pdata->off = mdp_lcdc_off;
+		mfd->hw_refresh = TRUE;
+		mfd->cursor_update = mdp_hw_cursor_update;
+#ifndef CONFIG_FB_MSM_MDP22
+		mfd->lut_update = mdp_lut_update_lcdc;
+		mfd->do_histogram = mdp_do_histogram;
+#endif
+#ifdef CONFIG_FB_MSM_OVERLAY
+		mfd->dma_fnc = mdp4_lcdc_overlay;
+#else
+		mfd->dma_fnc = mdp_lcdc_update;
+#endif
+
+#ifdef CONFIG_FB_MSM_MDP40
+		if (mfd->panel.type == HDMI_PANEL) {
+			mfd->dma = &dma_e_data;
+			mdp4_display_intf_sel(EXTERNAL_INTF_SEL, LCDC_RGB_INTF);
+		} else {
+			mfd->dma = &dma2_data;
+			mdp4_display_intf_sel(PRIMARY_INTF_SEL, LCDC_RGB_INTF);
+		}
+#else
+		mfd->dma = &dma2_data;
+		spin_lock_irqsave(&mdp_spin_lock, flag);
+		mdp_intr_mask &= ~MDP_DMA_P_DONE;
+		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+		spin_unlock_irqrestore(&mdp_spin_lock, flag);
+#endif
+		break;
+
+	case TV_PANEL:
+		pdata->on = mdp_dma3_on;
+		pdata->off = mdp_dma3_off;
+		mfd->hw_refresh = TRUE;
+		mfd->dma_fnc = mdp_dma3_update;
+		mfd->dma = &dma3_data;
+		break;
+
+	default:
+		printk(KERN_ERR "mdp_probe: unknown device type!\n");
+		rc = -ENODEV;
+		goto mdp_probe_err;
+	}
+
+	/* set driver data */
+	platform_set_drvdata(msm_fb_dev, mfd);
+
+	rc = platform_device_add(msm_fb_dev);
+	if (rc) {
+		goto mdp_probe_err;
+	}
+
+	pdev_list[pdev_list_cnt++] = pdev;
+	return 0;
+
+      mdp_probe_err:
+	platform_device_put(msm_fb_dev);
+	return rc;
+}
+
+static void mdp_suspend_sub(void)
+{
+	/* cancel pipe ctrl worker */
+	cancel_delayed_work(&mdp_pipe_ctrl_worker);
+
+	/* for workder can't be cancelled... */
+	flush_workqueue(mdp_pipe_ctrl_wq);
+
+	/* let's wait for PPP completion */
+	while (mdp_block_power_cnt[MDP_PPP_BLOCK] > 0) ;
+
+	/* try to power down */
+	mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int mdp_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	mdp_suspend_sub();
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mdp_early_suspend(struct early_suspend *h)
+{
+	mdp_suspend_sub();
+}
+#endif
+
+static int mdp_remove(struct platform_device *pdev)
+{
+	iounmap(msm_mdp_base);
+	return 0;
+}
+
+static int mdp_register_driver(void)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;
+	early_suspend.suspend = mdp_early_suspend;
+	register_early_suspend(&early_suspend);
+#endif
+
+	return platform_driver_register(&mdp_driver);
+}
+
+static int __init mdp_driver_init(void)
+{
+	int ret;
+
+	mdp_drv_init();
+
+	ret = mdp_register_driver();
+	if (ret) {
+		printk(KERN_ERR "mdp_register_driver() failed!\n");
+		return ret;
+	}
+
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_FB_MSM_MDP40)
+	mdp4_debugfs_init();
+#endif
+
+	return 0;
+
+}
+
+module_init(mdp_driver_init);

+ 695 - 0
drivers/staging/msm/mdp.h

@@ -0,0 +1,695 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MDP_H
+#define MDP_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/hrtimer.h>
+#include "msm_mdp.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include "msm_fb_panel.h"
+
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+#include "mdp_ppp_dq.h"
+#endif
+
+#ifdef BIT
+#undef BIT
+#endif
+
+#define BIT(x)  (1<<(x))
+
+#define MDPOP_NOP               0
+#define MDPOP_LR                BIT(0)	/* left to right flip */
+#define MDPOP_UD                BIT(1)	/* up and down flip */
+#define MDPOP_ROT90             BIT(2)	/* rotate image to 90 degree */
+#define MDPOP_ROT180            (MDPOP_UD|MDPOP_LR)
+#define MDPOP_ROT270            (MDPOP_ROT90|MDPOP_UD|MDPOP_LR)
+#define MDPOP_ASCALE            BIT(7)
+#define MDPOP_ALPHAB            BIT(8)	/* enable alpha blending */
+#define MDPOP_TRANSP            BIT(9)	/* enable transparency */
+#define MDPOP_DITHER            BIT(10)	/* enable dither */
+#define MDPOP_SHARPENING	BIT(11) /* enable sharpening */
+#define MDPOP_BLUR		BIT(12) /* enable blur */
+#define MDPOP_FG_PM_ALPHA       BIT(13)
+
+struct mdp_table_entry {
+	uint32_t reg;
+	uint32_t val;
+};
+
+extern struct mdp_ccs mdp_ccs_yuv2rgb ;
+extern struct mdp_ccs mdp_ccs_rgb2yuv ;
+
+/*
+ * MDP Image Structure
+ */
+typedef struct mdpImg_ {
+	uint32 imgType;		/* Image type */
+	uint32 *bmy_addr;	/* bitmap or y addr */
+	uint32 *cbcr_addr;	/* cbcr addr */
+	uint32 width;		/* image width */
+	uint32 mdpOp;		/* image opertion (rotation,flip up/down, alpha/tp) */
+	uint32 tpVal;		/* transparency color */
+	uint32 alpha;		/* alpha percentage 0%(0x0) ~ 100%(0x100) */
+	int    sp_value;        /* sharpening strength */
+} MDPIMG;
+
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+#define MDP_OUTP(addr, data)	mdp_ppp_outdw((uint32_t)(addr),	\
+					 (uint32_t)(data))
+#else
+#define MDP_OUTP(addr, data) outpdw((addr), (data))
+#endif
+
+#define MDP_KTIME2USEC(kt) (kt.tv.sec*1000000 + kt.tv.nsec/1000)
+
+#define MDP_BASE msm_mdp_base
+
+typedef enum {
+	MDP_BC_SCALE_POINT2_POINT4,
+	MDP_BC_SCALE_POINT4_POINT6,
+	MDP_BC_SCALE_POINT6_POINT8,
+	MDP_BC_SCALE_POINT8_1,
+	MDP_BC_SCALE_UP,
+	MDP_PR_SCALE_POINT2_POINT4,
+	MDP_PR_SCALE_POINT4_POINT6,
+	MDP_PR_SCALE_POINT6_POINT8,
+	MDP_PR_SCALE_POINT8_1,
+	MDP_PR_SCALE_UP,
+	MDP_SCALE_BLUR,
+	MDP_INIT_SCALE
+} MDP_SCALE_MODE;
+
+typedef enum {
+	MDP_BLOCK_POWER_OFF,
+	MDP_BLOCK_POWER_ON
+} MDP_BLOCK_POWER_STATE;
+
+typedef enum {
+	MDP_MASTER_BLOCK,
+	MDP_CMD_BLOCK,
+	MDP_PPP_BLOCK,
+	MDP_DMA2_BLOCK,
+	MDP_DMA3_BLOCK,
+	MDP_DMA_S_BLOCK,
+	MDP_DMA_E_BLOCK,
+	MDP_OVERLAY0_BLOCK,
+	MDP_OVERLAY1_BLOCK,
+	MDP_MAX_BLOCK
+} MDP_BLOCK_TYPE;
+
+/* Let's keep Q Factor power of 2 for optimization */
+#define MDP_SCALE_Q_FACTOR 512
+
+#ifdef CONFIG_FB_MSM_MDP31
+#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8)
+#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8)
+#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8)
+#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8)
+#else
+#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
+#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
+#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
+#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
+#endif
+
+/* SHIM Q Factor */
+#define PHI_Q_FACTOR          29
+#define PQF_PLUS_5            (PHI_Q_FACTOR + 5)	/* due to 32 phases */
+#define PQF_PLUS_4            (PHI_Q_FACTOR + 4)
+#define PQF_PLUS_2            (PHI_Q_FACTOR + 2)	/* to get 4.0 */
+#define PQF_MINUS_2           (PHI_Q_FACTOR - 2)	/* to get 0.25 */
+#define PQF_PLUS_5_PLUS_2     (PQF_PLUS_5 + 2)
+#define PQF_PLUS_5_MINUS_2    (PQF_PLUS_5 - 2)
+
+#define MDP_CONVTP(tpVal) (((tpVal&0xF800)<<8)|((tpVal&0x7E0)<<5)|((tpVal&0x1F)<<3))
+
+#define MDPOP_ROTATION (MDPOP_ROT90|MDPOP_LR|MDPOP_UD)
+#define MDP_CHKBIT(val, bit) ((bit) == ((val) & (bit)))
+
+/* overlay interface API defines */
+typedef enum {
+	MORE_IBUF,
+	FINAL_IBUF,
+	COMPLETE_IBUF
+} MDP_IBUF_STATE;
+
+struct mdp_dirty_region {
+	__u32 xoffset;		/* source origin in the x-axis */
+	__u32 yoffset;		/* source origin in the y-axis */
+	__u32 width;		/* number of pixels in the x-axis */
+	__u32 height;		/* number of pixels in the y-axis */
+};
+
+/*
+ * MDP extended data types
+ */
+typedef struct mdp_roi_s {
+	uint32 x;
+	uint32 y;
+	uint32 width;
+	uint32 height;
+	int32 lcd_x;
+	int32 lcd_y;
+	uint32 dst_width;
+	uint32 dst_height;
+} MDP_ROI;
+
+typedef struct mdp_ibuf_s {
+	uint8 *buf;
+	uint32 bpp;
+	uint32 ibuf_type;
+	uint32 ibuf_width;
+	uint32 ibuf_height;
+
+	MDP_ROI roi;
+	MDPIMG mdpImg;
+
+	int32 dma_x;
+	int32 dma_y;
+	uint32 dma_w;
+	uint32 dma_h;
+
+	uint32 vsync_enable;
+	uint32 visible_swapped;
+} MDPIBUF;
+
+struct mdp_dma_data {
+	boolean busy;
+	boolean waiting;
+	struct mutex ov_mutex;
+	struct semaphore mutex;
+	struct completion comp;
+};
+
+#define MDP_CMD_DEBUG_ACCESS_BASE   (MDP_BASE+0x10000)
+
+#define MDP_DMA2_TERM 0x1
+#define MDP_DMA3_TERM 0x2
+#define MDP_PPP_TERM 0x4
+#define MDP_DMA_S_TERM 0x8
+#ifdef CONFIG_FB_MSM_MDP40
+#define MDP_DMA_E_TERM 0x10
+#define MDP_OVERLAY0_TERM 0x20
+#define MDP_OVERLAY1_TERM 0x40
+#endif
+
+#define ACTIVE_START_X_EN BIT(31)
+#define ACTIVE_START_Y_EN BIT(31)
+#define ACTIVE_HIGH 0
+#define ACTIVE_LOW 1
+#define MDP_DMA_S_DONE  BIT(2)
+#define LCDC_FRAME_START    BIT(15)
+#define LCDC_UNDERFLOW      BIT(16)
+
+#ifdef CONFIG_FB_MSM_MDP22
+#define MDP_DMA_P_DONE 	BIT(2)
+#else
+#define MDP_DMA_P_DONE 	BIT(14)
+#endif
+
+#define MDP_PPP_DONE 				BIT(0)
+#define TV_OUT_DMA3_DONE    BIT(6)
+#define TV_ENC_UNDERRUN     BIT(7)
+#define TV_OUT_DMA3_START   BIT(13)
+#define MDP_HIST_DONE       BIT(20)
+
+#ifdef CONFIG_FB_MSM_MDP22
+#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \
+			MDP_DMA_P_DONE| \
+			TV_ENC_UNDERRUN)
+#else
+#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \
+			MDP_DMA_P_DONE| \
+			MDP_DMA_S_DONE| \
+			LCDC_UNDERFLOW| \
+			MDP_HIST_DONE| \
+			TV_ENC_UNDERRUN)
+#endif
+
+#define MDP_TOP_LUMA       16
+#define MDP_TOP_CHROMA     0
+#define MDP_BOTTOM_LUMA    19
+#define MDP_BOTTOM_CHROMA  3
+#define MDP_LEFT_LUMA      22
+#define MDP_LEFT_CHROMA    6
+#define MDP_RIGHT_LUMA     25
+#define MDP_RIGHT_CHROMA   9
+
+#define CLR_G 0x0
+#define CLR_B 0x1
+#define CLR_R 0x2
+#define CLR_ALPHA 0x3
+
+#define CLR_Y  CLR_G
+#define CLR_CB CLR_B
+#define CLR_CR CLR_R
+
+/* from lsb to msb */
+#define MDP_GET_PACK_PATTERN(a,x,y,z,bit) (((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z))
+
+/*
+ * 0x0000 0x0004 0x0008 MDP sync config
+ */
+#ifdef CONFIG_FB_MSM_MDP22
+#define MDP_SYNCFG_HGT_LOC 22
+#define MDP_SYNCFG_VSYNC_EXT_EN BIT(21)
+#define MDP_SYNCFG_VSYNC_INT_EN BIT(20)
+#else
+#define MDP_SYNCFG_HGT_LOC 21
+#define MDP_SYNCFG_VSYNC_EXT_EN BIT(20)
+#define MDP_SYNCFG_VSYNC_INT_EN BIT(19)
+#define MDP_HW_VSYNC
+#endif
+
+/*
+ * 0x0018 MDP VSYNC THREASH
+ */
+#define MDP_PRIM_BELOW_LOC 0
+#define MDP_PRIM_ABOVE_LOC 8
+
+/*
+ * MDP_PRIMARY_VSYNC_OUT_CTRL
+ * 0x0080,84,88 internal vsync pulse config
+ */
+#define VSYNC_PULSE_EN BIT(31)
+#define VSYNC_PULSE_INV BIT(30)
+
+/*
+ * 0x008c MDP VSYNC CONTROL
+ */
+#define DISP0_VSYNC_MAP_VSYNC0 0
+#define DISP0_VSYNC_MAP_VSYNC1 BIT(0)
+#define DISP0_VSYNC_MAP_VSYNC2 BIT(0)|BIT(1)
+
+#define DISP1_VSYNC_MAP_VSYNC0 0
+#define DISP1_VSYNC_MAP_VSYNC1 BIT(2)
+#define DISP1_VSYNC_MAP_VSYNC2 BIT(2)|BIT(3)
+
+#define PRIMARY_LCD_SYNC_EN BIT(4)
+#define PRIMARY_LCD_SYNC_DISABLE 0
+
+#define SECONDARY_LCD_SYNC_EN BIT(5)
+#define SECONDARY_LCD_SYNC_DISABLE 0
+
+#define EXTERNAL_LCD_SYNC_EN BIT(6)
+#define EXTERNAL_LCD_SYNC_DISABLE 0
+
+/*
+ * 0x101f0 MDP VSYNC Threshold
+ */
+#define VSYNC_THRESHOLD_ABOVE_LOC 0
+#define VSYNC_THRESHOLD_BELOW_LOC 16
+#define VSYNC_ANTI_TEAR_EN BIT(31)
+
+/*
+ * 0x10004 command config
+ */
+#define MDP_CMD_DBGBUS_EN BIT(0)
+
+/*
+ * 0x10124 or 0x101d4PPP source config
+ */
+#define PPP_SRC_C0G_8BITS (BIT(1)|BIT(0))
+#define PPP_SRC_C1B_8BITS (BIT(3)|BIT(2))
+#define PPP_SRC_C2R_8BITS (BIT(5)|BIT(4))
+#define PPP_SRC_C3A_8BITS (BIT(7)|BIT(6))
+
+#define PPP_SRC_C0G_6BITS BIT(1)
+#define PPP_SRC_C1B_6BITS BIT(3)
+#define PPP_SRC_C2R_6BITS BIT(5)
+
+#define PPP_SRC_C0G_5BITS BIT(0)
+#define PPP_SRC_C1B_5BITS BIT(2)
+#define PPP_SRC_C2R_5BITS BIT(4)
+
+#define PPP_SRC_C3_ALPHA_EN BIT(8)
+
+#define PPP_SRC_BPP_INTERLVD_1BYTES 0
+#define PPP_SRC_BPP_INTERLVD_2BYTES BIT(9)
+#define PPP_SRC_BPP_INTERLVD_3BYTES BIT(10)
+#define PPP_SRC_BPP_INTERLVD_4BYTES (BIT(10)|BIT(9))
+
+#define PPP_SRC_BPP_ROI_ODD_X BIT(11)
+#define PPP_SRC_BPP_ROI_ODD_Y BIT(12)
+#define PPP_SRC_INTERLVD_2COMPONENTS BIT(13)
+#define PPP_SRC_INTERLVD_3COMPONENTS BIT(14)
+#define PPP_SRC_INTERLVD_4COMPONENTS (BIT(14)|BIT(13))
+
+/*
+ * RGB666 unpack format
+ * TIGHT means R6+G6+B6 together
+ * LOOSE means R6+2 +G6+2+ B6+2 (with MSB)
+ * or 2+R6 +2+G6 +2+B6 (with LSB)
+ */
+#define PPP_SRC_UNPACK_TIGHT BIT(17)
+#define PPP_SRC_UNPACK_LOOSE 0
+#define PPP_SRC_UNPACK_ALIGN_LSB 0
+#define PPP_SRC_UNPACK_ALIGN_MSB BIT(18)
+
+#define PPP_SRC_FETCH_PLANES_INTERLVD 0
+#define PPP_SRC_FETCH_PLANES_PSEUDOPLNR BIT(20)
+
+#define PPP_SRC_WMV9_MODE BIT(21)	/* window media version 9 */
+
+/*
+ * 0x10138 PPP operation config
+ */
+#define PPP_OP_SCALE_X_ON BIT(0)
+#define PPP_OP_SCALE_Y_ON BIT(1)
+
+#define PPP_OP_CONVERT_RGB2YCBCR 0
+#define PPP_OP_CONVERT_YCBCR2RGB BIT(2)
+#define PPP_OP_CONVERT_ON BIT(3)
+
+#define PPP_OP_CONVERT_MATRIX_PRIMARY 0
+#define PPP_OP_CONVERT_MATRIX_SECONDARY BIT(4)
+
+#define PPP_OP_LUT_C0_ON BIT(5)
+#define PPP_OP_LUT_C1_ON BIT(6)
+#define PPP_OP_LUT_C2_ON BIT(7)
+
+/* rotate or blend enable */
+#define PPP_OP_ROT_ON BIT(8)
+
+#define PPP_OP_ROT_90 BIT(9)
+#define PPP_OP_FLIP_LR BIT(10)
+#define PPP_OP_FLIP_UD BIT(11)
+
+#define PPP_OP_BLEND_ON BIT(12)
+
+#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0
+#define PPP_OP_BLEND_DSTPIXEL_ALPHA BIT(13)
+#define PPP_OP_BLEND_CONSTANT_ALPHA BIT(14)
+#define PPP_OP_BLEND_SRCPIXEL_TRANSP (BIT(13)|BIT(14))
+
+#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0
+#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE BIT(15)
+
+#define PPP_OP_DITHER_EN BIT(16)
+
+#define PPP_OP_COLOR_SPACE_RGB 0
+#define PPP_OP_COLOR_SPACE_YCBCR BIT(17)
+
+#define PPP_OP_SRC_CHROMA_RGB 0
+#define PPP_OP_SRC_CHROMA_H2V1 BIT(18)
+#define PPP_OP_SRC_CHROMA_H1V2 BIT(19)
+#define PPP_OP_SRC_CHROMA_420 (BIT(18)|BIT(19))
+#define PPP_OP_SRC_CHROMA_COSITE 0
+#define PPP_OP_SRC_CHROMA_OFFSITE BIT(20)
+
+#define PPP_OP_DST_CHROMA_RGB 0
+#define PPP_OP_DST_CHROMA_H2V1 BIT(21)
+#define PPP_OP_DST_CHROMA_H1V2 BIT(22)
+#define PPP_OP_DST_CHROMA_420 (BIT(21)|BIT(22))
+#define PPP_OP_DST_CHROMA_COSITE 0
+#define PPP_OP_DST_CHROMA_OFFSITE BIT(23)
+
+#define PPP_BLEND_CALPHA_TRNASP BIT(24)
+
+#define PPP_OP_BG_CHROMA_RGB 0
+#define PPP_OP_BG_CHROMA_H2V1 BIT(25)
+#define PPP_OP_BG_CHROMA_H1V2 BIT(26)
+#define PPP_OP_BG_CHROMA_420 BIT(25)|BIT(26)
+#define PPP_OP_BG_CHROMA_SITE_COSITE 0
+#define PPP_OP_BG_CHROMA_SITE_OFFSITE BIT(27)
+#define PPP_OP_DEINT_EN BIT(29)
+
+#define PPP_BLEND_BG_USE_ALPHA_SEL      (1 << 0)
+#define PPP_BLEND_BG_ALPHA_REVERSE      (1 << 3)
+#define PPP_BLEND_BG_SRCPIXEL_ALPHA     (0 << 1)
+#define PPP_BLEND_BG_DSTPIXEL_ALPHA     (1 << 1)
+#define PPP_BLEND_BG_CONSTANT_ALPHA     (2 << 1)
+#define PPP_BLEND_BG_CONST_ALPHA_VAL(x) ((x) << 24)
+
+#define PPP_OP_DST_RGB 0
+#define PPP_OP_DST_YCBCR BIT(30)
+/*
+ * 0x10150 PPP destination config
+ */
+#define PPP_DST_C0G_8BIT (BIT(0)|BIT(1))
+#define PPP_DST_C1B_8BIT (BIT(3)|BIT(2))
+#define PPP_DST_C2R_8BIT (BIT(5)|BIT(4))
+#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6))
+
+#define PPP_DST_C0G_6BIT BIT(1)
+#define PPP_DST_C1B_6BIT BIT(3)
+#define PPP_DST_C2R_6BIT BIT(5)
+
+#define PPP_DST_C0G_5BIT BIT(0)
+#define PPP_DST_C1B_5BIT BIT(2)
+#define PPP_DST_C2R_5BIT BIT(4)
+
+#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6))
+#define PPP_DST_C3ALPHA_EN BIT(8)
+
+#define PPP_DST_PACKET_CNT_INTERLVD_2ELEM BIT(9)
+#define PPP_DST_PACKET_CNT_INTERLVD_3ELEM BIT(10)
+#define PPP_DST_PACKET_CNT_INTERLVD_4ELEM (BIT(10)|BIT(9))
+#define PPP_DST_PACKET_CNT_INTERLVD_6ELEM (BIT(11)|BIT(9))
+
+#define PPP_DST_PACK_LOOSE 0
+#define PPP_DST_PACK_TIGHT BIT(13)
+#define PPP_DST_PACK_ALIGN_LSB 0
+#define PPP_DST_PACK_ALIGN_MSB BIT(14)
+
+#define PPP_DST_OUT_SEL_AXI 0
+#define PPP_DST_OUT_SEL_MDDI BIT(15)
+
+#define PPP_DST_BPP_2BYTES BIT(16)
+#define PPP_DST_BPP_3BYTES BIT(17)
+#define PPP_DST_BPP_4BYTES (BIT(17)|BIT(16))
+
+#define PPP_DST_PLANE_INTERLVD 0
+#define PPP_DST_PLANE_PLANAR BIT(18)
+#define PPP_DST_PLANE_PSEUDOPLN BIT(19)
+
+#define PPP_DST_TO_TV BIT(20)
+
+#define PPP_DST_MDDI_PRIMARY 0
+#define PPP_DST_MDDI_SECONDARY BIT(21)
+#define PPP_DST_MDDI_EXTERNAL BIT(22)
+
+/*
+ * 0x10180 DMA config
+ */
+#define DMA_DSTC0G_8BITS (BIT(1)|BIT(0))
+#define DMA_DSTC1B_8BITS (BIT(3)|BIT(2))
+#define DMA_DSTC2R_8BITS (BIT(5)|BIT(4))
+
+#define DMA_DSTC0G_6BITS BIT(1)
+#define DMA_DSTC1B_6BITS BIT(3)
+#define DMA_DSTC2R_6BITS BIT(5)
+
+#define DMA_DSTC0G_5BITS BIT(0)
+#define DMA_DSTC1B_5BITS BIT(2)
+#define DMA_DSTC2R_5BITS BIT(4)
+
+#define DMA_PACK_TIGHT                      BIT(6)
+#define DMA_PACK_LOOSE                      0
+#define DMA_PACK_ALIGN_LSB                  0
+/*
+ * use DMA_PACK_ALIGN_MSB if the upper 6 bits from 8 bits output
+ * from LCDC block maps into 6 pins out to the panel
+ */
+#define DMA_PACK_ALIGN_MSB                  BIT(7)
+#define DMA_PACK_PATTERN_RGB \
+       (MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
+#define DMA_PACK_PATTERN_BGR \
+       (MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 2)<<8)
+#define DMA_OUT_SEL_AHB                     0
+#define DMA_OUT_SEL_LCDC                    BIT(20)
+#define DMA_IBUF_FORMAT_RGB888              0
+#define DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888  BIT(26)
+
+#ifdef CONFIG_FB_MSM_MDP22
+#define DMA_OUT_SEL_MDDI BIT(14)
+#define DMA_AHBM_LCD_SEL_PRIMARY 0
+#define DMA_AHBM_LCD_SEL_SECONDARY BIT(15)
+#define DMA_IBUF_C3ALPHA_EN BIT(16)
+#define DMA_DITHER_EN BIT(17)
+#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
+#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY BIT(18)
+#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL BIT(19)
+#define DMA_IBUF_FORMAT_RGB565 BIT(20)
+#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0
+#define DMA_IBUF_NONCONTIGUOUS BIT(21)
+#else
+#define DMA_OUT_SEL_MDDI                    BIT(19)
+#define DMA_AHBM_LCD_SEL_PRIMARY            0
+#define DMA_AHBM_LCD_SEL_SECONDARY          0
+#define DMA_IBUF_C3ALPHA_EN                 0
+#define DMA_DITHER_EN                       BIT(24)
+#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY     0
+#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY   0
+#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL    0
+#define DMA_IBUF_FORMAT_RGB565              BIT(25)
+#define DMA_IBUF_NONCONTIGUOUS 0
+#endif
+
+/*
+ * MDDI Register
+ */
+#define MDDI_VDO_PACKET_DESC  0x5666
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define MDP_INTR_ENABLE		(msm_mdp_base + 0x0050)
+#define MDP_INTR_STATUS		(msm_mdp_base + 0x0054)
+#define MDP_INTR_CLEAR		(msm_mdp_base + 0x0058)
+#define MDP_EBI2_LCD0		(msm_mdp_base + 0x0060)
+#define MDP_EBI2_LCD1		(msm_mdp_base + 0x0064)
+#define MDP_EBI2_PORTMAP_MODE	(msm_mdp_base + 0x0070)
+
+#define MDP_DMA_P_HIST_INTR_STATUS 	(msm_mdp_base + 0x95014)
+#define MDP_DMA_P_HIST_INTR_CLEAR 	(msm_mdp_base + 0x95018)
+#define MDP_DMA_P_HIST_INTR_ENABLE 	(msm_mdp_base + 0x9501C)
+#else
+#define MDP_INTR_ENABLE		(msm_mdp_base + 0x0020)
+#define MDP_INTR_STATUS		(msm_mdp_base + 0x0024)
+#define MDP_INTR_CLEAR		(msm_mdp_base + 0x0028)
+#define MDP_EBI2_LCD0		(msm_mdp_base + 0x003c)
+#define MDP_EBI2_LCD1		(msm_mdp_base + 0x0040)
+#define MDP_EBI2_PORTMAP_MODE	(msm_mdp_base + 0x005c)
+#endif
+
+#define MDP_FULL_BYPASS_WORD43  (msm_mdp_base + 0x101ac)
+
+#define MDP_CSC_PFMVn(n)	(msm_mdp_base + 0x40400 + 4 * (n))
+#define MDP_CSC_PRMVn(n)	(msm_mdp_base + 0x40440 + 4 * (n))
+#define MDP_CSC_PRE_BV1n(n)	(msm_mdp_base + 0x40500 + 4 * (n))
+#define MDP_CSC_PRE_BV2n(n)	(msm_mdp_base + 0x40540 + 4 * (n))
+#define MDP_CSC_POST_BV1n(n)	(msm_mdp_base + 0x40580 + 4 * (n))
+#define MDP_CSC_POST_BV2n(n)	(msm_mdp_base + 0x405c0 + 4 * (n))
+
+#ifdef CONFIG_FB_MSM_MDP31
+#define MDP_CSC_PRE_LV1n(n)	(msm_mdp_base + 0x40600 + 4 * (n))
+#define MDP_CSC_PRE_LV2n(n)	(msm_mdp_base + 0x40640 + 4 * (n))
+#define MDP_CSC_POST_LV1n(n)	(msm_mdp_base + 0x40680 + 4 * (n))
+#define MDP_CSC_POST_LV2n(n)	(msm_mdp_base + 0x406c0 + 4 * (n))
+#define MDP_PPP_SCALE_COEFF_LSBn(n)	(msm_mdp_base + 0x50400 + 8 * (n))
+#define MDP_PPP_SCALE_COEFF_MSBn(n)	(msm_mdp_base + 0x50404 + 8 * (n))
+
+#define SCALE_D0_SET  0
+#define SCALE_D1_SET  BIT(0)
+#define SCALE_D2_SET  BIT(1)
+#define SCALE_U1_SET  (BIT(0)|BIT(1))
+
+#else
+#define MDP_CSC_PRE_LV1n(n)	(msm_mdp_base + 0x40580 + 4 * (n))
+#endif
+
+#define MDP_CURSOR_WIDTH 64
+#define MDP_CURSOR_HEIGHT 64
+#define MDP_CURSOR_SIZE (MDP_CURSOR_WIDTH*MDP_CURSOR_WIDTH*4)
+
+#define MDP_DMA_P_LUT_C0_EN   BIT(0)
+#define MDP_DMA_P_LUT_C1_EN   BIT(1)
+#define MDP_DMA_P_LUT_C2_EN   BIT(2)
+#define MDP_DMA_P_LUT_POST    BIT(4)
+
+void mdp_hw_init(void);
+int mdp_ppp_pipe_wait(void);
+void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd);
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+		   boolean isr);
+void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
+			  boolean sync);
+void mdp_dma_pan_update(struct fb_info *info);
+void mdp_refresh_screen(unsigned long data);
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
+		struct file **pp_src, struct file **pp_dest);
+void mdp_lcd_update_workqueue_handler(struct work_struct *work);
+void mdp_vsync_resync_workqueue_handler(struct work_struct *work);
+void mdp_dma2_update(struct msm_fb_data_type *mfd);
+void mdp_config_vsync(struct msm_fb_data_type *);
+uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd);
+enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht);
+void mdp_set_scale(MDPIBUF *iBuf,
+		   uint32 dst_roi_width,
+		   uint32 dst_roi_height,
+		   boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr);
+void mdp_init_scale_table(void);
+void mdp_adjust_start_addr(uint8 **src0,
+			   uint8 **src1,
+			   int v_slice,
+			   int h_slice,
+			   int x,
+			   int y,
+			   uint32 width,
+			   uint32 height, int bpp, MDPIBUF *iBuf, int layer);
+void mdp_set_blend_attr(MDPIBUF *iBuf,
+			uint32 *alpha,
+			uint32 *tpVal,
+			uint32 perPixelAlpha, uint32 *pppop_reg_ptr);
+
+int mdp_dma3_on(struct platform_device *pdev);
+int mdp_dma3_off(struct platform_device *pdev);
+void mdp_dma3_update(struct msm_fb_data_type *mfd);
+
+int mdp_lcdc_on(struct platform_device *pdev);
+int mdp_lcdc_off(struct platform_device *pdev);
+void mdp_lcdc_update(struct msm_fb_data_type *mfd);
+int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor);
+void mdp_enable_irq(uint32 term);
+void mdp_disable_irq(uint32 term);
+void mdp_disable_irq_nolock(uint32 term);
+uint32_t mdp_get_bytes_per_pixel(uint32_t format);
+
+#ifdef MDP_HW_VSYNC
+void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd);
+void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd);
+#endif
+
+void mdp_dma_s_update(struct msm_fb_data_type *mfd);
+
+/* Added to support flipping */
+void mdp_set_offset_info(struct fb_info *info, uint32 address, uint32 interval);
+
+int get_gem_img(struct mdp_img *img, unsigned long *start,
+		unsigned long *len);
+int get_img(struct mdp_img *img, struct fb_info *info,
+		unsigned long *start, unsigned long *len,
+		struct file **pp_file);
+
+
+/*int get_img(struct msmfb_data *img, struct fb_info *info,
+	unsigned long *start, unsigned long *len, struct file **pp_file);*/
+#endif /* MDP_H */

+ 352 - 0
drivers/staging/msm/mdp4.h

@@ -0,0 +1,352 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MDP4_H
+#define MDP4_H
+
+extern struct mdp_dma_data dma2_data;
+extern struct mdp_dma_data dma_s_data;
+extern struct mdp_dma_data dma_e_data;
+extern struct mdp_histogram mdp_hist;
+extern struct completion mdp_hist_comp;
+extern boolean mdp_is_in_isr;
+extern uint32 mdp_intr_mask;
+extern spinlock_t mdp_spin_lock;
+
+
+#define MDP4_NONBLOCKING	/* enable non blocking ioctl */
+
+#define MDP4_OVERLAYPROC0_BASE	0x10000
+#define MDP4_OVERLAYPROC1_BASE	0x18000
+
+#define MDP4_VIDEO_BASE 0x20000
+#define MDP4_VIDEO_OFF 0x10000
+
+#define MDP4_RGB_BASE 0x40000
+#define MDP4_RGB_OFF 0x10000
+
+enum {		/* display */
+	PRIMARY_INTF_SEL,
+	SECONDARY_INTF_SEL,
+	EXTERNAL_INTF_SEL
+};
+
+enum {
+	LCDC_RGB_INTF,
+	DTV_INTF = LCDC_RGB_INTF,
+	MDDI_LCDC_INTF,
+	MDDI_INTF,
+	EBI2_INTF
+};
+
+enum {
+	MDDI_PRIMARY_SET,
+	MDDI_SECONDARY_SET,
+	MDDI_EXTERNAL_SET
+};
+
+enum {
+	EBI2_LCD0,
+	EBI2_LCD1
+};
+
+enum {
+	OVERLAY_MODE_NONE,
+	OVERLAY_MODE_BLT
+};
+
+enum {
+	OVERLAY_REFRESH_ON_DEMAND,
+	OVERLAY_REFRESH_VSYNC,
+	OVERLAY_REFRESH_VSYNC_HALF,
+	OVERLAY_REFRESH_VSYNC_QUARTER
+};
+
+enum {
+	OVERLAY_FRAMEBUF,
+	OVERLAY_DIRECTOUT
+};
+
+/* system interrupts */
+#define INTR_OVERLAY0_DONE		BIT(0)
+#define INTR_OVERLAY1_DONE		BIT(1)
+#define INTR_DMA_S_DONE			BIT(2)
+#define INTR_DMA_E_DONE			BIT(3)
+#define INTR_DMA_P_DONE			BIT(4)
+#define INTR_VG1_HISTOGRAM		BIT(5)
+#define INTR_VG2_HISTOGRAM		BIT(6)
+#define INTR_PRIMARY_VSYNC		BIT(7)
+#define INTR_PRIMARY_INTF_UDERRUN	BIT(8)
+#define INTR_EXTERNAL_VSYNC		BIT(9)
+#define INTR_EXTERNAL_INTF_UDERRUN	BIT(10)
+#define INTR_DMA_P_HISTOGRAM		BIT(17)
+
+/* histogram interrupts */
+#define INTR_HIST_DONE			BIT(0)
+#define INTR_HIST_RESET_SEQ_DONE	BIT(1)
+
+
+#ifdef CONFIG_FB_MSM_OVERLAY
+#define MDP4_ANY_INTR_MASK	(INTR_OVERLAY0_DONE)
+#else
+#define MDP4_ANY_INTR_MASK	(INTR_DMA_P_DONE)
+#endif
+
+enum {
+	OVERLAY_PIPE_RGB1,
+	OVERLAY_PIPE_RGB2,
+};
+
+enum {
+	OVERLAY_PIPE_VG1,	/* video/graphic */
+	OVERLAY_PIPE_VG2
+};
+
+enum {
+	OVERLAY_TYPE_RGB,
+	OVERLAY_TYPE_VG		/* video/graphic */
+};
+
+enum {
+	MDP4_MIXER0,
+	MDP4_MIXER1
+};
+
+#define MDP4_MAX_MIXER	2
+
+enum {
+	OVERLAY_PLANE_INTERLEAVED,
+	OVERLAY_PLANE_PLANAR,
+	OVERLAY_PLANE_PSEUDO_PLANAR
+};
+
+enum {
+	MDP4_MIXER_STAGE_UNUNSED,	/* pipe not used */
+	MDP4_MIXER_STAGE_BASE,
+	MDP4_MIXER_STAGE0,	/* zorder 0 */
+	MDP4_MIXER_STAGE1,	/* zorder 1 */
+	MDP4_MIXER_STAGE2	/* zorder 2 */
+};
+
+#define MDP4_MAX_STAGE	4
+
+enum {
+	MDP4_FRAME_FORMAT_LINEAR,
+	MDP4_FRAME_FORMAT_ARGB_TILE,
+	MDP4_FRAME_FORMAT_VIDEO_SUPERTILE
+};
+
+enum {
+	MDP4_CHROMA_RGB,
+	MDP4_CHROMA_H2V1,
+	MDP4_CHROMA_H1V2,
+	MDP4_CHROMA_420
+};
+
+#define MDP4_BLEND_BG_TRANSP_EN		BIT(9)
+#define MDP4_BLEND_FG_TRANSP_EN		BIT(8)
+#define MDP4_BLEND_BG_MOD_ALPHA		BIT(7)
+#define MDP4_BLEND_BG_INV_ALPHA		BIT(6)
+#define MDP4_BLEND_BG_ALPHA_FG_CONST	(0 << 4)
+#define MDP4_BLEND_BG_ALPHA_BG_CONST	(1 << 4)
+#define MDP4_BLEND_BG_ALPHA_FG_PIXEL	(2 << 4)
+#define MDP4_BLEND_BG_ALPHA_BG_PIXEL	(3 << 4)
+#define MDP4_BLEND_FG_MOD_ALPHA		BIT(3)
+#define MDP4_BLEND_FG_INV_ALPHA		BIT(2)
+#define MDP4_BLEND_FG_ALPHA_FG_CONST	(0 << 0)
+#define MDP4_BLEND_FG_ALPHA_BG_CONST	(1 << 0)
+#define MDP4_BLEND_FG_ALPHA_FG_PIXEL	(2 << 0)
+#define MDP4_BLEND_FG_ALPHA_BG_PIXEL	(3 << 0)
+
+#define MDP4_FORMAT_SOLID_FILL		BIT(22)
+#define MDP4_FORMAT_UNPACK_ALIGN_MSB	BIT(18)
+#define MDP4_FORMAT_UNPACK_TIGHT	BIT(17)
+#define MDP4_FORMAT_90_ROTATED		BIT(12)
+#define MDP4_FORMAT_ALPHA_ENABLE	BIT(8)
+
+#define MDP4_OP_DEINT_ODD_REF  	BIT(19)
+#define MDP4_OP_IGC_LUT_EN	BIT(16)
+#define MDP4_OP_DITHER_EN     	BIT(15)
+#define MDP4_OP_FLIP_UD		BIT(14)
+#define MDP4_OP_FLIP_LR		BIT(13)
+#define MDP4_OP_CSC_EN		BIT(11)
+#define MDP4_OP_SRC_DATA_YCBCR	BIT(9)
+#define MDP4_OP_SCALEY_FIR 		(0 << 4)
+#define MDP4_OP_SCALEY_MN_PHASE 	(1 << 4)
+#define MDP4_OP_SCALEY_PIXEL_RPT	(2 << 4)
+#define MDP4_OP_SCALEX_FIR 		(0 << 2)
+#define MDP4_OP_SCALEX_MN_PHASE 	(1 << 2)
+#define MDP4_OP_SCALEX_PIXEL_RPT 	(2 << 2)
+#define MDP4_OP_SCALEY_EN	BIT(1)
+#define MDP4_OP_SCALEX_EN	BIT(0)
+
+#define MDP4_PIPE_PER_MIXER	2
+
+#define MDP4_MAX_PLANE		4
+
+#define MDP4_MAX_VIDEO_PIPE 2
+#define MDP4_MAX_RGB_PIPE 2
+#define MDP4_MAX_OVERLAY_PIPE 	16
+
+
+struct mdp4_overlay_pipe {
+	uint32 pipe_type;		/* rgb, video/graphic */
+	uint32 pipe_num;
+	uint32 pipe_ndx;
+	uint32 mixer_num;		/* which mixer used */
+	uint32 mixer_stage;		/* which stage of mixer used */
+	uint32 src_format;
+	uint32 src_width;	/* source img width */
+	uint32 src_height;	/* source img height */
+	uint32 src_w;		/* roi */
+	uint32 src_h;		/* roi */
+	uint32 src_x;		/* roi */
+	uint32 src_y;		/* roi */
+	uint32 dst_w;		/* roi */
+	uint32 dst_h;		/* roi */
+	uint32 dst_x;		/* roi */
+	uint32 dst_y;		/* roi */
+	uint32 op_mode;
+	uint32 transp;
+	uint32 blend_op;
+	uint32 phasex_step;
+	uint32 phasey_step;
+	uint32 alpha;
+	uint32 is_fg;		/* control alpha & color key */
+	uint32 srcp0_addr;	/* interleave, luma */
+	uint32 srcp0_ystride;
+	uint32 srcp1_addr;	/* pseudoplanar, chroma plane */
+	uint32 srcp1_ystride;
+	uint32 srcp2_addr;	/* planar color 2*/
+	uint32 srcp2_ystride;
+	uint32 srcp3_addr;	/* alpha/color 3 */
+	uint32 srcp3_ystride;
+	uint32 fetch_plane;
+	uint32 frame_format;		/* video */
+	uint32 chroma_site;		/* video */
+	uint32 chroma_sample;		/* video */
+	uint32 solid_fill;
+	uint32 vc1_reduce;		/* video */
+	uint32 fatch_planes;		/* video */
+	uint32 unpack_align_msb;/* 0 to LSB, 1 to MSB */
+	uint32 unpack_tight;/* 0 for loose, 1 for tight */
+	uint32 unpack_count;/* 0 = 1 component, 1 = 2 component ... */
+	uint32 rotated_90; /* has been rotated 90 degree */
+	uint32 bpp;	/* byte per pixel */
+	uint32 alpha_enable;/*  source has alpha */
+	/*
+	 * number of bits for source component,
+	 * 0 = 1 bit, 1 = 2 bits, 2 = 6 bits, 3 = 8 bits
+	 */
+	uint32 a_bit;	/* component 3, alpha */
+	uint32 r_bit;	/* component 2, R_Cr */
+	uint32 b_bit;	/* component 1, B_Cb */
+	uint32 g_bit;	/* component 0, G_lumz */
+	/*
+	 * unpack pattern
+	 * A = C3, R = C2, B = C1, G = C0
+	 */
+	uint32 element3; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+	uint32 element2; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+	uint32 element1; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+	uint32 element0; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */
+	struct completion comp;
+	struct mdp_overlay req_data;
+};
+
+void mdp4_sw_reset(unsigned long bits);
+void mdp4_display_intf_sel(int output, unsigned long intf);
+void mdp4_overlay_cfg(int layer, int blt_mode, int refresh, int direct_out);
+void mdp4_ebi2_lcd_setup(int lcd, unsigned long base, int ystride);
+void mdp4_mddi_setup(int which, unsigned long id);
+unsigned long mdp4_display_status(void);
+void mdp4_enable_clk_irq(void);
+void mdp4_disable_clk_irq(void);
+void mdp4_dma_p_update(struct msm_fb_data_type *mfd);
+void mdp4_dma_s_update(struct msm_fb_data_type *mfd);
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+		   boolean isr);
+void mdp4_pipe_kickoff(uint32 pipe, struct msm_fb_data_type *mfd);
+int mdp4_lcdc_on(struct platform_device *pdev);
+int mdp4_lcdc_off(struct platform_device *pdev);
+void mdp4_lcdc_update(struct msm_fb_data_type *mfd);
+void mdp4_intr_clear_set(ulong clear, ulong set);
+void mdp4_dma_p_cfg(void);
+void mdp4_hw_init(void);
+void mdp4_isr_read(int);
+void mdp4_clear_lcdc(void);
+void mdp4_mixer_blend_init(int mixer_num);
+void mdp4_vg_qseed_init(int vg_num);
+void mdp4_vg_csc_mv_setup(int vp_num);
+void mdp4_vg_csc_pre_bv_setup(int vp_num);
+void mdp4_vg_csc_post_bv_setup(int vp_num);
+void mdp4_vg_csc_pre_lv_setup(int vp_num);
+void mdp4_vg_csc_post_lv_setup(int vp_num);
+irqreturn_t mdp4_isr(int irq, void *ptr);
+void mdp4_overlay_format_to_pipe(uint32 format, struct mdp4_overlay_pipe *pipe);
+uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe);
+uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe);
+uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe);
+void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd);
+void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe);
+void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all);
+void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe);
+void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe);
+void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe);
+int mdp4_mixer_stage_can_run(struct mdp4_overlay_pipe *pipe);
+void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe);
+void mdp4_mddi_overlay(struct msm_fb_data_type *mfd);
+int mdp4_overlay_format2type(uint32 format);
+int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe);
+int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req);
+int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req);
+int mdp4_overlay_unset(struct fb_info *info, int ndx);
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
+				struct file **pp_src_file);
+struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void);
+void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe);
+void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc);
+void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe);
+int mdp4_overlay_active(int mixer);
+void mdp4_overlay0_done_lcdc(void);
+void mdp4_overlay0_done_mddi(void);
+void mdp4_mddi_overlay_restore(void);
+void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
+				struct mdp4_overlay_pipe *pipe);
+void mdp4_rgb_igc_lut_setup(int num);
+void mdp4_vg_igc_lut_setup(int num);
+void mdp4_mixer_gc_lut_setup(int mixer_num);
+
+#ifdef CONFIG_DEBUG_FS
+int mdp4_debugfs_init(void);
+#endif
+
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
+	struct file **pp_src_file, struct file **pp_dst_file);
+
+#endif /* MDP_H */

+ 181 - 0
drivers/staging/msm/mdp4_debugfs.c

@@ -0,0 +1,181 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+
+#define MDP4_DEBUG_BUF	128
+
+
+static char mdp4_debug_buf[MDP4_DEBUG_BUF];
+static ulong mdp4_debug_offset;
+static ulong mdp4_base_addr;
+
+static int mdp4_offset_set(void *data, u64 val)
+{
+	mdp4_debug_offset = (int)val;
+	return 0;
+}
+
+static int mdp4_offset_get(void *data, u64 *val)
+{
+	*val = (u64)mdp4_debug_offset;
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(
+			mdp4_offset_fops,
+			mdp4_offset_get,
+			mdp4_offset_set,
+			"%llx\n");
+
+
+static int mdp4_debugfs_open(struct inode *inode, struct file *file)
+{
+	/* non-seekable */
+	file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+	return 0;
+}
+
+static int mdp4_debugfs_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static ssize_t mdp4_debugfs_write(
+	struct file *file,
+	const char __user *buff,
+	size_t count,
+	loff_t *ppos)
+{
+	int cnt;
+	unsigned int data;
+
+	printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n",
+		__func__, (int)mdp4_debug_offset, (int)count, (int)*ppos);
+
+	if (count > sizeof(mdp4_debug_buf))
+		return -EFAULT;
+
+	if (copy_from_user(mdp4_debug_buf, buff, count))
+		return -EFAULT;
+
+
+	mdp4_debug_buf[count] = 0;	/* end of string */
+
+	cnt = sscanf(mdp4_debug_buf, "%x", &data);
+	if (cnt < 1) {
+		printk(KERN_ERR "%s: sscanf failed cnt=%d" , __func__, cnt);
+		return -EINVAL;
+	}
+
+	writel(&data, mdp4_base_addr + mdp4_debug_offset);
+
+	return 0;
+}
+
+static ssize_t mdp4_debugfs_read(
+	struct file *file,
+	char __user *buff,
+	size_t count,
+	loff_t *ppos)
+{
+	int len = 0;
+	unsigned int data;
+
+	printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n",
+		__func__, (int)mdp4_debug_offset, (int)count, (int)*ppos);
+
+	if (*ppos)
+		return 0;	/* the end */
+
+	data = readl(mdp4_base_addr + mdp4_debug_offset);
+
+	len = snprintf(mdp4_debug_buf, 4, "%x\n", data);
+
+	if (len > 0) {
+		if (len > count)
+			len = count;
+		if (copy_to_user(buff, mdp4_debug_buf, len))
+			return -EFAULT;
+	}
+
+	printk(KERN_INFO "%s: len=%d\n", __func__, len);
+
+	if (len < 0)
+		return 0;
+
+	*ppos += len;	/* increase offset */
+
+	return len;
+}
+
+static const struct file_operations mdp4_debugfs_fops = {
+	.open = mdp4_debugfs_open,
+	.release = mdp4_debugfs_release,
+	.read = mdp4_debugfs_read,
+	.write = mdp4_debugfs_write,
+};
+
+int mdp4_debugfs_init(void)
+{
+	struct dentry *dent = debugfs_create_dir("mdp4", NULL);
+
+	if (IS_ERR(dent)) {
+		printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n",
+			__FILE__, __LINE__, PTR_ERR(dent));
+		return -1;
+	}
+
+	if (debugfs_create_file("offset", 0644, dent, 0, &mdp4_offset_fops)
+			== NULL) {
+		printk(KERN_ERR "%s(%d): debugfs_create_file: offset fail\n",
+			__FILE__, __LINE__);
+		return -1;
+	}
+
+	if (debugfs_create_file("regs", 0644, dent, 0, &mdp4_debugfs_fops)
+			== NULL) {
+		printk(KERN_ERR "%s(%d): debugfs_create_file: regs fail\n",
+			__FILE__, __LINE__);
+		return -1;
+	}
+
+	mdp4_debug_offset = 0;
+	mdp4_base_addr = (ulong) msm_mdp_base;	/* defined at msm_fb_def.h */
+
+	return 0;
+}

+ 1259 - 0
drivers/staging/msm/mdp4_overlay.c

@@ -0,0 +1,1259 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/fb.h>
+#include <msm_mdp.h>
+#include <linux/file.h>
+#include "android_pmem.h"
+#include <linux/major.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <linux/mutex.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+
+struct mdp4_overlay_ctrl {
+	struct mdp4_overlay_pipe plist[MDP4_MAX_OVERLAY_PIPE];
+	struct mdp4_overlay_pipe *stage[MDP4_MAX_MIXER][MDP4_MAX_STAGE];
+} mdp4_overlay_db;
+
+static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
+
+
+void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc)
+{
+	uint32	dma2_cfg_reg;
+
+	dma2_cfg_reg = DMA_DITHER_EN;
+
+	if (mfd->fb_imgType == MDP_BGR_565)
+		dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+	else
+		dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+
+	if (mfd->panel_info.bpp == 18) {
+		dma2_cfg_reg |= DMA_DSTC0G_6BITS |	/* 666 18BPP */
+		    DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+	} else if (mfd->panel_info.bpp == 16) {
+		dma2_cfg_reg |= DMA_DSTC0G_6BITS |	/* 565 16BPP */
+		    DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+	} else {
+		dma2_cfg_reg |= DMA_DSTC0G_8BITS |	/* 888 16BPP */
+		    DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+	}
+
+	if (lcdc)
+		dma2_cfg_reg |= DMA_PACK_ALIGN_MSB;
+
+	/* dma2 config register */
+	MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
+
+}
+
+void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe)
+{
+
+	/* dma_p source */
+	MDP_OUTP(MDP_BASE + 0x90004,
+			(pipe->src_height << 16 | pipe->src_width));
+	MDP_OUTP(MDP_BASE + 0x90008, pipe->srcp0_addr);
+	MDP_OUTP(MDP_BASE + 0x9000c, pipe->srcp0_ystride);
+
+	/* dma_p dest */
+	MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x));
+}
+
+#define MDP4_VG_PHASE_STEP_DEFAULT	0x20000000
+#define MDP4_VG_PHASE_STEP_SHIFT	29
+
+static int mdp4_leading_0(uint32 num)
+{
+	uint32 bit = 0x80000000;
+	int i;
+
+	for (i = 0; i < 32; i++) {
+		if (bit & num)
+			return i;
+		bit >>= 1;
+	}
+
+	return i;
+}
+
+static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst)
+{
+	uint32 val;
+	int	n;
+
+	n = mdp4_leading_0(src);
+	if (n > f_num)
+		n = f_num;
+	val = src << n;	/* maximum to reduce lose of resolution */
+	val /= dst;
+	if (n < f_num) {
+		n = f_num - n;
+		val <<= n;
+	}
+
+	return val;
+}
+
+static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe)
+{
+
+	pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
+	pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
+
+	if (pipe->dst_h && pipe->src_h != pipe->dst_h) {
+		if (pipe->dst_h >= pipe->src_h * 8)	/* too much */
+			return;
+		pipe->op_mode |= MDP4_OP_SCALEY_EN;
+
+		if (pipe->pipe_type == OVERLAY_TYPE_VG) {
+			if (pipe->dst_h <= (pipe->src_h / 4))
+				pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
+			else
+				pipe->op_mode |= MDP4_OP_SCALEY_FIR;
+		}
+
+		pipe->phasey_step = mdp4_scale_phase_step(29,
+					pipe->src_h, pipe->dst_h);
+	}
+
+	if (pipe->dst_w && pipe->src_w != pipe->dst_w) {
+		if (pipe->dst_w >= pipe->src_w * 8)	/* too much */
+			return;
+		pipe->op_mode |= MDP4_OP_SCALEX_EN;
+
+		if (pipe->pipe_type == OVERLAY_TYPE_VG) {
+			if (pipe->dst_w <= (pipe->src_w / 4))
+				pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
+			else
+				pipe->op_mode |= MDP4_OP_SCALEY_FIR;
+		}
+
+		pipe->phasex_step = mdp4_scale_phase_step(29,
+					pipe->src_w, pipe->dst_w);
+	}
+}
+
+void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe)
+{
+	char *rgb_base;
+	uint32 src_size, src_xy, dst_size, dst_xy;
+	uint32 format, pattern;
+
+	rgb_base = MDP_BASE + MDP4_RGB_BASE;
+	rgb_base += (MDP4_RGB_OFF * pipe->pipe_num);
+
+	src_size = ((pipe->src_h << 16) | pipe->src_w);
+	src_xy = ((pipe->src_y << 16) | pipe->src_x);
+	dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
+	dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
+
+	format = mdp4_overlay_format(pipe);
+	pattern = mdp4_overlay_unpack_pattern(pipe);
+
+	pipe->op_mode |= MDP4_OP_IGC_LUT_EN;
+
+	mdp4_scale_setup(pipe);
+
+	outpdw(rgb_base + 0x0000, src_size);	/* MDP_RGB_SRC_SIZE */
+	outpdw(rgb_base + 0x0004, src_xy);	/* MDP_RGB_SRC_XY */
+	outpdw(rgb_base + 0x0008, dst_size);	/* MDP_RGB_DST_SIZE */
+	outpdw(rgb_base + 0x000c, dst_xy);	/* MDP_RGB_DST_XY */
+
+	outpdw(rgb_base + 0x0010, pipe->srcp0_addr);
+	outpdw(rgb_base + 0x0040, pipe->srcp0_ystride);
+
+	outpdw(rgb_base + 0x0050, format);/* MDP_RGB_SRC_FORMAT */
+	outpdw(rgb_base + 0x0054, pattern);/* MDP_RGB_SRC_UNPACK_PATTERN */
+	outpdw(rgb_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
+	outpdw(rgb_base + 0x005c, pipe->phasex_step);
+	outpdw(rgb_base + 0x0060, pipe->phasey_step);
+
+	/* 16 bytes-burst x 3 req <= 48 bytes */
+	outpdw(rgb_base + 0x1004, 0xc2);	/* MDP_RGB_FETCH_CFG */
+}
+
+void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe)
+{
+	char *vg_base;
+	uint32 frame_size, src_size, src_xy, dst_size, dst_xy;
+	uint32 format, pattern;
+
+	vg_base = MDP_BASE + MDP4_VIDEO_BASE;
+	vg_base += (MDP4_VIDEO_OFF * pipe->pipe_num);
+
+	frame_size = ((pipe->src_height << 16) | pipe->src_width);
+	src_size = ((pipe->src_h << 16) | pipe->src_w);
+	src_xy = ((pipe->src_y << 16) | pipe->src_x);
+	dst_size = ((pipe->dst_h << 16) | pipe->dst_w);
+	dst_xy = ((pipe->dst_y << 16) | pipe->dst_x);
+
+	format = mdp4_overlay_format(pipe);
+	pattern = mdp4_overlay_unpack_pattern(pipe);
+
+	pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR |
+				MDP4_OP_IGC_LUT_EN);
+
+	mdp4_scale_setup(pipe);
+
+	outpdw(vg_base + 0x0000, src_size);	/* MDP_RGB_SRC_SIZE */
+	outpdw(vg_base + 0x0004, src_xy);	/* MDP_RGB_SRC_XY */
+	outpdw(vg_base + 0x0008, dst_size);	/* MDP_RGB_DST_SIZE */
+	outpdw(vg_base + 0x000c, dst_xy);	/* MDP_RGB_DST_XY */
+	outpdw(vg_base + 0x0048, frame_size);	/* TILE frame size */
+
+	/* luma component plane */
+	outpdw(vg_base + 0x0010, pipe->srcp0_addr);
+
+	/* chroma component plane */
+	outpdw(vg_base + 0x0014, pipe->srcp1_addr);
+
+	outpdw(vg_base + 0x0040,
+			pipe->srcp1_ystride << 16 | pipe->srcp0_ystride);
+
+	outpdw(vg_base + 0x0050, format);	/* MDP_RGB_SRC_FORMAT */
+	outpdw(vg_base + 0x0054, pattern);	/* MDP_RGB_SRC_UNPACK_PATTERN */
+	outpdw(vg_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */
+	outpdw(vg_base + 0x005c, pipe->phasex_step);
+	outpdw(vg_base + 0x0060, pipe->phasey_step);
+
+	if (pipe->op_mode & MDP4_OP_DITHER_EN) {
+		outpdw(vg_base + 0x0068,
+			pipe->r_bit << 4 | pipe->b_bit << 2 | pipe->g_bit);
+	}
+
+	/* 16 bytes-burst x 3 req <= 48 bytes */
+	outpdw(vg_base + 0x1004, 0xc2);	/* MDP_VG_FETCH_CFG */
+}
+
+int mdp4_overlay_format2type(uint32 format)
+{
+	switch (format) {
+	case MDP_RGB_565:
+	case MDP_RGB_888:
+	case MDP_BGR_565:
+	case MDP_ARGB_8888:
+	case MDP_RGBA_8888:
+	case MDP_BGRA_8888:
+		return OVERLAY_TYPE_RGB;
+	case MDP_YCRYCB_H2V1:
+	case MDP_Y_CRCB_H2V1:
+	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H2V2:
+	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CBCR_H2V2_TILE:
+	case MDP_Y_CRCB_H2V2_TILE:
+		return OVERLAY_TYPE_VG;
+	default:
+		return -ERANGE;
+	}
+
+}
+
+#define C3_ALPHA	3	/* alpha */
+#define C2_R_Cr		2	/* R/Cr */
+#define C1_B_Cb		1	/* B/Cb */
+#define C0_G_Y		0	/* G/luma */
+
+int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe)
+{
+	switch (pipe->src_format) {
+	case MDP_RGB_565:
+		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+		pipe->a_bit = 0;
+		pipe->r_bit = 1;	/* R, 5 bits */
+		pipe->b_bit = 1;	/* B, 5 bits */
+		pipe->g_bit = 2;	/* G, 6 bits */
+		pipe->alpha_enable = 0;
+		pipe->unpack_tight = 1;
+		pipe->unpack_align_msb = 0;
+		pipe->unpack_count = 2;
+		pipe->element2 = C2_R_Cr;	/* R */
+		pipe->element1 = C0_G_Y;	/* G */
+		pipe->element0 = C1_B_Cb;	/* B */
+		pipe->bpp = 2;	/* 2 bpp */
+		break;
+	case MDP_RGB_888:
+		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+		pipe->a_bit = 0;
+		pipe->r_bit = 3;	/* R, 8 bits */
+		pipe->b_bit = 3;	/* B, 8 bits */
+		pipe->g_bit = 3;	/* G, 8 bits */
+		pipe->alpha_enable = 0;
+		pipe->unpack_tight = 1;
+		pipe->unpack_align_msb = 0;
+		pipe->unpack_count = 2;
+		pipe->element2 = C2_R_Cr;	/* R */
+		pipe->element1 = C0_G_Y;	/* G */
+		pipe->element0 = C1_B_Cb;	/* B */
+		pipe->bpp = 3;	/* 3 bpp */
+		break;
+	case MDP_BGR_565:
+		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+		pipe->a_bit = 0;
+		pipe->r_bit = 1;	/* R, 5 bits */
+		pipe->b_bit = 1;	/* B, 5 bits */
+		pipe->g_bit = 2;	/* G, 6 bits */
+		pipe->alpha_enable = 0;
+		pipe->unpack_tight = 1;
+		pipe->unpack_align_msb = 0;
+		pipe->unpack_count = 2;
+		pipe->element2 = C1_B_Cb;	/* B */
+		pipe->element1 = C0_G_Y;	/* G */
+		pipe->element0 = C2_R_Cr;	/* R */
+		pipe->bpp = 2;	/* 2 bpp */
+		break;
+	case MDP_ARGB_8888:
+		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+		pipe->a_bit = 3;	/* alpha, 4 bits */
+		pipe->r_bit = 3;	/* R, 8 bits */
+		pipe->b_bit = 3;	/* B, 8 bits */
+		pipe->g_bit = 3;	/* G, 8 bits */
+		pipe->alpha_enable = 1;
+		pipe->unpack_tight = 1;
+		pipe->unpack_align_msb = 0;
+		pipe->unpack_count = 3;
+		pipe->element3 = C3_ALPHA;	/* alpha */
+		pipe->element2 = C2_R_Cr;	/* R */
+		pipe->element1 = C0_G_Y;	/* G */
+		pipe->element0 = C1_B_Cb;	/* B */
+		pipe->bpp = 4;		/* 4 bpp */
+		break;
+	case MDP_RGBA_8888:
+		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+		pipe->a_bit = 3;	/* alpha, 4 bits */
+		pipe->r_bit = 3;	/* R, 8 bits */
+		pipe->b_bit = 3;	/* B, 8 bits */
+		pipe->g_bit = 3;	/* G, 8 bits */
+		pipe->alpha_enable = 1;
+		pipe->unpack_tight = 1;
+		pipe->unpack_align_msb = 0;
+		pipe->unpack_count = 3;
+		pipe->element3 = C2_R_Cr;	/* R */
+		pipe->element2 = C0_G_Y;	/* G */
+		pipe->element1 = C1_B_Cb;	/* B */
+		pipe->element0 = C3_ALPHA;	/* alpha */
+		pipe->bpp = 4;		/* 4 bpp */
+		break;
+	case MDP_BGRA_8888:
+		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+		pipe->a_bit = 3;	/* alpha, 4 bits */
+		pipe->r_bit = 3;	/* R, 8 bits */
+		pipe->b_bit = 3;	/* B, 8 bits */
+		pipe->g_bit = 3;	/* G, 8 bits */
+		pipe->alpha_enable = 1;
+		pipe->unpack_tight = 1;
+		pipe->unpack_align_msb = 0;
+		pipe->unpack_count = 3;
+		pipe->element3 = C1_B_Cb;	/* B */
+		pipe->element2 = C0_G_Y;	/* G */
+		pipe->element1 = C2_R_Cr;	/* R */
+		pipe->element0 = C3_ALPHA;	/* alpha */
+		pipe->bpp = 4;		/* 4 bpp */
+		break;
+	case MDP_YCRYCB_H2V1:
+		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+		pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+		pipe->a_bit = 0;	/* alpha, 4 bits */
+		pipe->r_bit = 3;	/* R, 8 bits */
+		pipe->b_bit = 3;	/* B, 8 bits */
+		pipe->g_bit = 3;	/* G, 8 bits */
+		pipe->alpha_enable = 0;
+		pipe->unpack_tight = 1;
+		pipe->unpack_align_msb = 0;
+		pipe->unpack_count = 3;
+		pipe->element3 = C0_G_Y;	/* G */
+		pipe->element2 = C2_R_Cr;	/* R */
+		pipe->element1 = C0_G_Y;	/* G */
+		pipe->element0 = C1_B_Cb;	/* B */
+		pipe->bpp = 2;		/* 2 bpp */
+		pipe->chroma_sample = MDP4_CHROMA_H2V1;
+		break;
+	case MDP_Y_CRCB_H2V1:
+	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H2V2:
+	case MDP_Y_CBCR_H2V2:
+		pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+		pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
+		pipe->a_bit = 0;
+		pipe->r_bit = 3;	/* R, 8 bits */
+		pipe->b_bit = 3;	/* B, 8 bits */
+		pipe->g_bit = 3;	/* G, 8 bits */
+		pipe->alpha_enable = 0;
+		pipe->unpack_tight = 1;
+		pipe->unpack_align_msb = 0;
+		pipe->unpack_count = 1;		/* 2 */
+		pipe->element3 = C0_G_Y;	/* not used */
+		pipe->element2 = C0_G_Y;	/* not used */
+		if (pipe->src_format == MDP_Y_CRCB_H2V1) {
+			pipe->element1 = C2_R_Cr;	/* R */
+			pipe->element0 = C1_B_Cb;	/* B */
+			pipe->chroma_sample = MDP4_CHROMA_H2V1;
+		} else if (pipe->src_format == MDP_Y_CBCR_H2V1) {
+			pipe->element1 = C1_B_Cb;	/* B */
+			pipe->element0 = C2_R_Cr;	/* R */
+			pipe->chroma_sample = MDP4_CHROMA_H2V1;
+		} else if (pipe->src_format == MDP_Y_CRCB_H2V2) {
+			pipe->element1 = C2_R_Cr;	/* R */
+			pipe->element0 = C1_B_Cb;	/* B */
+			pipe->chroma_sample = MDP4_CHROMA_420;
+		} else if (pipe->src_format == MDP_Y_CBCR_H2V2) {
+			pipe->element1 = C1_B_Cb;	/* B */
+			pipe->element0 = C2_R_Cr;	/* R */
+			pipe->chroma_sample = MDP4_CHROMA_420;
+		}
+		pipe->bpp = 2;	/* 2 bpp */
+		break;
+	case MDP_Y_CBCR_H2V2_TILE:
+	case MDP_Y_CRCB_H2V2_TILE:
+		pipe->frame_format = MDP4_FRAME_FORMAT_VIDEO_SUPERTILE;
+		pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR;
+		pipe->a_bit = 0;
+		pipe->r_bit = 3;	/* R, 8 bits */
+		pipe->b_bit = 3;	/* B, 8 bits */
+		pipe->g_bit = 3;	/* G, 8 bits */
+		pipe->alpha_enable = 0;
+		pipe->unpack_tight = 1;
+		pipe->unpack_align_msb = 0;
+		pipe->unpack_count = 1;		/* 2 */
+		pipe->element3 = C0_G_Y;	/* not used */
+		pipe->element2 = C0_G_Y;	/* not used */
+		if (pipe->src_format == MDP_Y_CRCB_H2V2_TILE) {
+			pipe->element1 = C2_R_Cr;	/* R */
+			pipe->element0 = C1_B_Cb;	/* B */
+			pipe->chroma_sample = MDP4_CHROMA_420;
+		} else if (pipe->src_format == MDP_Y_CBCR_H2V2_TILE) {
+			pipe->element1 = C1_B_Cb;	/* B */
+			pipe->element0 = C2_R_Cr;	/* R */
+			pipe->chroma_sample = MDP4_CHROMA_420;
+		}
+		pipe->bpp = 2;	/* 2 bpp */
+		break;
+	default:
+		/* not likely */
+		return -ERANGE;
+	}
+
+	return 0;
+}
+
+/*
+ * color_key_convert: output with 12 bits color key
+ */
+static uint32 color_key_convert(int start, int num, uint32 color)
+{
+
+	uint32 data;
+
+	data = (color >> start) & ((1 << num) - 1);
+
+	if (num == 5)
+		data = (data << 7) + (data << 2) + (data >> 3);
+	else if (num == 6)
+		data = (data << 6) + data;
+	else	/* 8 bits */
+		data = (data << 4) + (data >> 4);
+
+	return data;
+
+}
+
+void transp_color_key(int format, uint32 transp,
+			uint32 *c0, uint32 *c1, uint32 *c2)
+{
+	int b_start, g_start, r_start;
+	int b_num, g_num, r_num;
+
+	switch (format) {
+	case MDP_RGB_565:
+		b_start = 0;
+		g_start = 5;
+		r_start = 11;
+		r_num = 5;
+		g_num = 6;
+		b_num = 5;
+		break;
+	case MDP_RGB_888:
+	case MDP_XRGB_8888:
+	case MDP_ARGB_8888:
+		b_start = 0;
+		g_start = 8;
+		r_start = 16;
+		r_num = 8;
+		g_num = 8;
+		b_num = 8;
+		break;
+	case MDP_BGR_565:
+		b_start = 11;
+		g_start = 5;
+		r_start = 0;
+		r_num = 5;
+		g_num = 6;
+		b_num = 5;
+		break;
+	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CBCR_H2V1:
+		b_start = 8;
+		g_start = 16;
+		r_start = 0;
+		r_num = 8;
+		g_num = 8;
+		b_num = 8;
+		break;
+	case MDP_Y_CRCB_H2V2:
+	case MDP_Y_CRCB_H2V1:
+		b_start = 0;
+		g_start = 16;
+		r_start = 8;
+		r_num = 8;
+		g_num = 8;
+		b_num = 8;
+		break;
+	default:
+		b_start = 0;
+		g_start = 8;
+		r_start = 16;
+		r_num = 8;
+		g_num = 8;
+		b_num = 8;
+		break;
+	}
+
+	*c0 = color_key_convert(g_start, g_num, transp);
+	*c1 = color_key_convert(b_start, b_num, transp);
+	*c2 = color_key_convert(r_start, r_num, transp);
+}
+
+uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe)
+{
+	uint32	format;
+
+	format = 0;
+
+	if (pipe->solid_fill)
+		format |= MDP4_FORMAT_SOLID_FILL;
+
+	if (pipe->unpack_align_msb)
+		format |= MDP4_FORMAT_UNPACK_ALIGN_MSB;
+
+	if (pipe->unpack_tight)
+		format |= MDP4_FORMAT_UNPACK_TIGHT;
+
+	if (pipe->alpha_enable)
+		format |= MDP4_FORMAT_ALPHA_ENABLE;
+
+	format |= (pipe->unpack_count << 13);
+	format |= ((pipe->bpp - 1) << 9);
+	format |= (pipe->a_bit << 6);
+	format |= (pipe->r_bit << 4);
+	format |= (pipe->b_bit << 2);
+	format |= pipe->g_bit;
+
+	format |= (pipe->frame_format << 29);
+
+	if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
+		/* video/graphic */
+		format |= (pipe->fetch_plane << 19);
+		format |= (pipe->chroma_site << 28);
+		format |= (pipe->chroma_sample << 26);
+	}
+
+	return format;
+}
+
+uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe)
+{
+	return (pipe->element3 << 24) | (pipe->element2 << 16) |
+			(pipe->element1 << 8) | pipe->element0;
+}
+
+void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe)
+{
+	uint32 data;
+	char *overlay_base;
+
+	if (pipe->mixer_num == MDP4_MIXER1)
+		overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+	else
+		overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+	/* MDP_OVERLAYPROC_CFG */
+	outpdw(overlay_base + 0x0004, 0x01); /* directout */
+	data = pipe->src_height;
+	data <<= 16;
+	data |= pipe->src_width;
+	outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
+	outpdw(overlay_base + 0x000c, pipe->srcp0_addr);
+	outpdw(overlay_base + 0x0010, pipe->srcp0_ystride);
+	outpdw(overlay_base + 0x0014, 0x4);	/* GC_LUT_EN, 888 */
+}
+
+int mdp4_overlay_active(int mixer)
+{
+	uint32 data, mask, i;
+	int p1, p2;
+
+	data = inpdw(MDP_BASE + 0x10100);
+	p1 = 0;
+	p2 = 0;
+	for (i = 0; i < 8; i++) {
+		mask = data & 0x0f;
+		if (mask) {
+			if (mask <= 4)
+				p1++;
+			else
+				p2++;
+		}
+		data >>= 4;
+	}
+
+	if (mixer)
+		return p2;
+	else
+		return p1;
+}
+
+void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
+{
+	uint32 data, mask, snum, stage, mixer;
+
+	stage = pipe->mixer_stage;
+	mixer = pipe->mixer_num;
+
+	/* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1  */
+	data = inpdw(MDP_BASE + 0x10100);
+
+	if (mixer == MDP4_MIXER1)
+		stage += 8;
+
+	if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
+		snum = 0;
+		snum += (4 * pipe->pipe_num);
+	} else {
+		snum = 8;
+		snum += (4 * pipe->pipe_num);	/* RGB1 and RGB2 */
+	}
+
+	mask = 0x0f;
+	mask <<= snum;
+	stage <<= snum;
+	data &= ~mask;	/* clear old bits */
+
+	data |= stage;
+
+	outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
+
+	data = inpdw(MDP_BASE + 0x10100);
+
+	ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe;	/* keep it */
+}
+
+void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
+{
+	uint32 data, mask, snum, stage, mixer;
+
+	stage = pipe->mixer_stage;
+	mixer = pipe->mixer_num;
+
+	if (pipe != ctrl->stage[mixer][stage])	/* not runing */
+		return;
+
+	/* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1  */
+	data = inpdw(MDP_BASE + 0x10100);
+
+	if (mixer == MDP4_MIXER1)
+		stage += 8;
+
+	if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */
+		snum = 0;
+		snum += (4 * pipe->pipe_num);
+	} else {
+		snum = 8;
+		snum += (4 * pipe->pipe_num);	/* RGB1 and RGB2 */
+	}
+
+	mask = 0x0f;
+	mask <<= snum;
+	data &= ~mask;	/* clear old bits */
+
+	outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */
+
+	data = inpdw(MDP_BASE + 0x10100);
+
+	ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;	/* clear it */
+}
+
+void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
+{
+	unsigned char *overlay_base;
+	uint32 c0, c1, c2, blend_op;
+	int off;
+
+	if (pipe->mixer_num) 	/* mixer number, /dev/fb0, /dev/fb1 */
+		overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+	else
+		overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+	/* stage 0 to stage 2 */
+	off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
+
+	blend_op = 0;
+	if (pipe->alpha_enable) 	/* ARGB */
+		blend_op = MDP4_BLEND_FG_ALPHA_FG_PIXEL |
+				MDP4_BLEND_BG_ALPHA_FG_PIXEL;
+	else
+		blend_op = (MDP4_BLEND_BG_ALPHA_BG_CONST |
+				MDP4_BLEND_FG_ALPHA_FG_CONST);
+
+
+	if (pipe->alpha_enable == 0) { 	/* not ARGB */
+		if (pipe->is_fg) {
+			outpdw(overlay_base + off + 0x108, pipe->alpha);
+			outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
+		} else {
+			outpdw(overlay_base + off + 0x108, 0xff - pipe->alpha);
+			outpdw(overlay_base + off + 0x10c, pipe->alpha);
+		}
+	}
+
+	if (pipe->transp != MDP_TRANSP_NOP) {
+		transp_color_key(pipe->src_format, pipe->transp, &c0, &c1, &c2);
+		if (pipe->is_fg) {
+			blend_op |= MDP4_BLEND_FG_TRANSP_EN; /* Fg blocked */
+			/* lower limit */
+			if (c0 > 0x10)
+				c0 -= 0x10;
+			if (c1 > 0x10)
+				c1 -= 0x10;
+			if (c2 > 0x10)
+				c2 -= 0x10;
+			outpdw(overlay_base + off + 0x110,
+						(c1 << 16 | c0));/* low */
+			outpdw(overlay_base + off + 0x114, c2);/* low */
+			/* upper limit */
+			if ((c0 + 0x20) < 0x0fff)
+				c0 += 0x20;
+			else
+				c0 = 0x0fff;
+			if ((c1 + 0x20) < 0x0fff)
+				c1 += 0x20;
+			else
+				c1 = 0x0fff;
+			if ((c2 + 0x20) < 0x0fff)
+				c2 += 0x20;
+			else
+				c2 = 0x0fff;
+			outpdw(overlay_base + off + 0x118,
+					(c1 << 16 | c0));/* high */
+			outpdw(overlay_base + off + 0x11c, c2);/* high */
+		} else {
+			blend_op |= MDP4_BLEND_BG_TRANSP_EN; /* bg blocked */
+			/* lower limit */
+			if (c0 > 0x10)
+				c0 -= 0x10;
+			if (c1 > 0x10)
+				c1 -= 0x10;
+			if (c2 > 0x10)
+				c2 -= 0x10;
+			outpdw(overlay_base + 0x180,
+						(c1 << 16 | c0));/* low */
+			outpdw(overlay_base + 0x184, c2);/* low */
+			/* upper limit */
+			if ((c0 + 0x20) < 0x0fff)
+				c0 += 0x20;
+			else
+				c0 = 0x0fff;
+			if ((c1 + 0x20) < 0x0fff)
+				c1 += 0x20;
+			else
+				c1 = 0x0fff;
+			if ((c2 + 0x20) < 0x0fff)
+				c2 += 0x20;
+			else
+				c2 = 0x0fff;
+			outpdw(overlay_base + 0x188,
+						(c1 << 16 | c0));/* high */
+			outpdw(overlay_base + 0x18c, c2);/* high */
+		}
+	}
+	outpdw(overlay_base + off + 0x104, blend_op);
+}
+
+void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
+{
+	uint32 bits = 0;
+
+	if (pipe->mixer_num == MDP4_MIXER1)
+		bits |= 0x02;
+	else
+		bits |= 0x01;
+
+	if (all) {
+		if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
+			if (pipe->pipe_num == OVERLAY_PIPE_RGB2)
+				bits |= 0x20;
+			else
+				bits |= 0x10;
+		} else {
+			if (pipe->pipe_num == OVERLAY_PIPE_VG2)
+				bits |= 0x08;
+			else
+				bits |= 0x04;
+		}
+	}
+
+	outpdw(MDP_BASE + 0x18000, bits);	/* MDP_OVERLAY_REG_FLUSH */
+
+	while (inpdw(MDP_BASE + 0x18000) & bits) /* self clear when complete */
+		;
+}
+
+struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx)
+{
+	struct mdp4_overlay_pipe *pipe;
+
+	if (ndx == 0 || ndx >= MDP4_MAX_OVERLAY_PIPE)
+		return NULL;
+
+	pipe = &ctrl->plist[ndx - 1];	/* ndx start from 1 */
+
+	if (pipe->pipe_ndx == 0)
+		return NULL;
+
+	return pipe;
+}
+
+struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void)
+{
+	int i;
+	struct mdp4_overlay_pipe *pipe;
+
+	pipe = &ctrl->plist[0];
+	for (i = 0; i < MDP4_MAX_OVERLAY_PIPE; i++) {
+		if (pipe->pipe_ndx == 0) {
+			pipe->pipe_ndx = i + 1;	/* start from 1 */
+			init_completion(&pipe->comp);
+	printk(KERN_INFO "mdp4_overlay_pipe_alloc: pipe=%x ndx=%d\n",
+					(int)pipe, pipe->pipe_ndx);
+			return pipe;
+		}
+		pipe++;
+	}
+
+	return NULL;
+}
+
+
+void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
+{
+	printk(KERN_INFO "mdp4_overlay_pipe_free: pipe=%x ndx=%d\n",
+					(int)pipe, pipe->pipe_ndx);
+	memset(pipe, 0, sizeof(*pipe));
+}
+
+static int get_pipe_num(int ptype, int stage)
+{
+	if (ptype == OVERLAY_TYPE_RGB) {
+		if (stage == MDP4_MIXER_STAGE_BASE)
+			return OVERLAY_PIPE_RGB1;
+		else
+			return OVERLAY_PIPE_RGB2;
+	} else {
+		if (stage == MDP4_MIXER_STAGE0)
+			return OVERLAY_PIPE_VG1;
+		else
+			return OVERLAY_PIPE_VG2;
+	}
+}
+
+int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer)
+{
+	struct mdp4_overlay_pipe *pipe;
+
+	pipe = ctrl->stage[mixer][z_order];
+
+	if (pipe == NULL)
+		return 0;
+
+	if (pipe->pipe_ndx == id)	/* same req, recycle */
+		return 0;
+
+	return -EPERM;
+}
+
+static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer,
+			struct mdp4_overlay_pipe **ppipe)
+{
+	struct mdp4_overlay_pipe *pipe;
+	int ret, ptype;
+
+	if (mixer >= MDP4_MAX_MIXER) {
+		printk(KERN_ERR "mpd_overlay_req2pipe: mixer out of range!\n");
+		return -ERANGE;
+	}
+
+	if (req->z_order < 0 || req->z_order > 2) {
+		printk(KERN_ERR "mpd_overlay_req2pipe: z_order=%d out of range!\n",
+				req->z_order);
+		return -ERANGE;
+	}
+
+	if (req->src_rect.h == 0 || req->src_rect.w == 0) {
+		printk(KERN_ERR "mpd_overlay_req2pipe: src img of zero size!\n");
+		return -EINVAL;
+	}
+
+	ret = mdp4_overlay_req_check(req->id, req->z_order, mixer);
+	if (ret < 0)
+		return ret;
+
+	ptype = mdp4_overlay_format2type(req->src.format);
+	if (ptype < 0)
+		return ptype;
+
+	if (req->id == MSMFB_NEW_REQUEST)  /* new request */
+		pipe = mdp4_overlay_pipe_alloc();
+	else
+		pipe = mdp4_overlay_ndx2pipe(req->id);
+
+	if (pipe == NULL)
+		return -ENOMEM;
+
+	pipe->src_format = req->src.format;
+	ret = mdp4_overlay_format2pipe(pipe);
+
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * base layer == 1, reserved for frame buffer
+	 * zorder 0 == stage 0 == 2
+	 * zorder 1 == stage 1 == 3
+	 * zorder 2 == stage 2 == 4
+	 */
+	if (req->id == MSMFB_NEW_REQUEST) {  /* new request */
+		pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
+		pipe->pipe_type = ptype;
+		pipe->pipe_num = get_pipe_num(ptype, pipe->mixer_stage);
+		printk(KERN_INFO "mpd4_overlay_req2pipe: zorder=%d pipe_num=%d\n",
+				req->z_order, pipe->pipe_num);
+	}
+
+	pipe->src_width = req->src.width & 0x07ff;	/* source img width */
+	pipe->src_height = req->src.height & 0x07ff;	/* source img height */
+	pipe->src_h = req->src_rect.h & 0x07ff;
+	pipe->src_w = req->src_rect.w & 0x07ff;
+	pipe->src_y = req->src_rect.y & 0x07ff;
+	pipe->src_x = req->src_rect.x & 0x07ff;
+	pipe->dst_h = req->dst_rect.h & 0x07ff;
+	pipe->dst_w = req->dst_rect.w & 0x07ff;
+	pipe->dst_y = req->dst_rect.y & 0x07ff;
+	pipe->dst_x = req->dst_rect.x & 0x07ff;
+
+	if (req->flags & MDP_FLIP_LR)
+		pipe->op_mode |= MDP4_OP_FLIP_LR;
+
+	if (req->flags & MDP_FLIP_UD)
+		pipe->op_mode |= MDP4_OP_FLIP_UD;
+
+	if (req->flags & MDP_DITHER)
+		pipe->op_mode |= MDP4_OP_DITHER_EN;
+
+	if (req->flags & MDP_DEINTERLACE)
+		pipe->op_mode |= MDP4_OP_DEINT_ODD_REF;
+
+	pipe->is_fg = req->is_fg;/* control alpha and color key */
+
+	pipe->alpha = req->alpha & 0x0ff;
+
+	pipe->transp = req->transp_mask;
+
+	*ppipe = pipe;
+
+	return 0;
+}
+
+int get_img(struct msmfb_data *img, struct fb_info *info,
+	unsigned long *start, unsigned long *len, struct file **pp_file)
+{
+	int put_needed, ret = 0;
+	struct file *file;
+#ifdef CONFIG_ANDROID_PMEM
+	unsigned long vstart;
+#endif
+
+#ifdef CONFIG_ANDROID_PMEM
+	if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
+		return 0;
+#endif
+	file = fget_light(img->memory_id, &put_needed);
+	if (file == NULL)
+		return -1;
+
+	if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+		*start = info->fix.smem_start;
+		*len = info->fix.smem_len;
+		*pp_file = file;
+	} else {
+		ret = -1;
+		fput_light(file, put_needed);
+	}
+	return ret;
+}
+int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req)
+{
+	struct mdp4_overlay_pipe *pipe;
+
+	pipe = mdp4_overlay_ndx2pipe(req->id);
+	if (pipe == NULL)
+		return -ENODEV;
+
+	*req = pipe->req_data;
+
+	return 0;
+}
+
+int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	int ret, mixer;
+	struct mdp4_overlay_pipe *pipe;
+	int lcdc;
+
+	if (mfd == NULL)
+		return -ENODEV;
+
+	if (req->src.format == MDP_FB_FORMAT)
+		req->src.format = mfd->fb_imgType;
+
+	if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+		return -EINTR;
+
+	mixer = info->node; /* minor number of char device */
+
+	ret = mdp4_overlay_req2pipe(req, mixer, &pipe);
+	if (ret < 0) {
+		mutex_unlock(&mfd->dma->ov_mutex);
+		return ret;
+	}
+
+	lcdc = inpdw(MDP_BASE + 0xc0000);
+
+	if (lcdc == 0) { /* mddi */
+		/* MDP cmd block enable */
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	}
+
+	/* return id back to user */
+	req->id = pipe->pipe_ndx;	/* pipe_ndx start from 1 */
+	pipe->req_data = *req;		/* keep original req */
+
+	mutex_unlock(&mfd->dma->ov_mutex);
+
+	return 0;
+}
+
+int mdp4_overlay_unset(struct fb_info *info, int ndx)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct mdp4_overlay_pipe *pipe;
+	int lcdc;
+
+	if (mfd == NULL)
+		return -ENODEV;
+
+	if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+		return -EINTR;
+
+	pipe = mdp4_overlay_ndx2pipe(ndx);
+
+	if (pipe == NULL) {
+		mutex_unlock(&mfd->dma->ov_mutex);
+		return -ENODEV;
+	}
+
+	lcdc = inpdw(MDP_BASE + 0xc0000);
+
+	mdp4_mixer_stage_down(pipe);
+
+	if (lcdc == 0) { /* mddi */
+		/* MDP cmd block disable */
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	}
+
+	if (lcdc) /* LCDC mode */
+		mdp4_overlay_reg_flush(pipe, 0);
+
+	mdp4_overlay_pipe_free(pipe);
+
+	if (lcdc == 0) { /* mddi */
+		mdp4_mddi_overlay_restore();
+	}
+
+	mutex_unlock(&mfd->dma->ov_mutex);
+
+	return 0;
+}
+
+struct tile_desc {
+	uint32 width;  /* tile's width */
+	uint32 height; /* tile's height */
+	uint32 row_tile_w; /* tiles per row's width */
+	uint32 row_tile_h; /* tiles per row's height */
+};
+
+void tile_samsung(struct tile_desc *tp)
+{
+	/*
+	 * each row of samsung tile consists of two tiles in height
+	 * and two tiles in width which means width should align to
+	 * 64 x 2 bytes and height should align to 32 x 2 bytes.
+	 * video decoder generate two tiles in width and one tile
+	 * in height which ends up height align to 32 X 1 bytes.
+	 */
+	tp->width = 64;		/* 64 bytes */
+	tp->row_tile_w = 2;	/* 2 tiles per row's width */
+	tp->height = 32;	/* 32 bytes */
+	tp->row_tile_h = 1;	/* 1 tiles per row's height */
+}
+
+uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp)
+{
+	uint32 tile_w, tile_h;
+	uint32 row_num_w, row_num_h;
+
+
+	tile_w = tp->width * tp->row_tile_w;
+	tile_h = tp->height * tp->row_tile_h;
+
+	row_num_w = (pipe->src_width + tile_w - 1) / tile_w;
+	row_num_h = (pipe->src_height + tile_h - 1) / tile_h;
+
+	return row_num_w * row_num_h * tile_w * tile_h;
+}
+
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
+		struct file **pp_src_file)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct msmfb_data *img;
+	struct mdp4_overlay_pipe *pipe;
+	ulong start, addr;
+	ulong len = 0;
+	struct file *p_src_file = 0;
+	int lcdc;
+
+	if (mfd == NULL)
+		return -ENODEV;
+
+	pipe = mdp4_overlay_ndx2pipe(req->id);
+	if (pipe == NULL)
+		return -ENODEV;
+
+	if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+		return -EINTR;
+
+	img = &req->data;
+	get_img(img, info, &start, &len, &p_src_file);
+	if (len == 0) {
+		mutex_unlock(&mfd->dma->ov_mutex);
+		printk(KERN_ERR "mdp_overlay_play: could not retrieve"
+				       " image from memory\n");
+		return -1;
+	}
+	*pp_src_file = p_src_file;
+
+	addr = start + img->offset;
+	pipe->srcp0_addr = addr;
+	pipe->srcp0_ystride = pipe->src_width * pipe->bpp;
+
+	if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
+		if (pipe->frame_format == MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) {
+			struct tile_desc tile;
+
+			tile_samsung(&tile);
+			pipe->srcp1_addr = addr + tile_mem_size(pipe, &tile);
+		} else
+			pipe->srcp1_addr = addr +
+					pipe->src_width * pipe->src_height;
+
+		pipe->srcp0_ystride = pipe->src_width;
+		pipe->srcp1_ystride = pipe->src_width;
+	}
+
+	lcdc = inpdw(MDP_BASE + 0xc0000);
+	lcdc &= 0x01; /* LCDC mode */
+
+	if (pipe->pipe_type == OVERLAY_TYPE_VG)
+		mdp4_overlay_vg_setup(pipe);	/* video/graphic pipe */
+	else
+		mdp4_overlay_rgb_setup(pipe);	/* rgb pipe */
+
+	mdp4_mixer_blend_setup(pipe);
+	mdp4_mixer_stage_up(pipe);
+
+	if (lcdc) { /* LCDC mode */
+		mdp4_overlay_reg_flush(pipe, 1);
+	}
+
+	if (lcdc) { /* LCDC mode */
+		if (pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) { /* done */
+			mutex_unlock(&mfd->dma->ov_mutex);
+			return 0;
+		}
+	}
+
+	if (lcdc == 0) { /* MDDI mode */
+#ifdef MDP4_NONBLOCKING
+		if (mfd->panel_power_on)
+#else
+		if (!mfd->dma->busy && mfd->panel_power_on)
+#endif
+			mdp4_mddi_overlay_kickoff(mfd, pipe);
+	}
+
+	mutex_unlock(&mfd->dma->ov_mutex);
+
+	return 0;
+}

+ 313 - 0
drivers/staging/msm/mdp4_overlay_lcdc.c

@@ -0,0 +1,313 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define LCDC_BASE	0xC0000
+#else
+#define LCDC_BASE	0xE0000
+#endif
+
+int first_pixel_start_x;
+int first_pixel_start_y;
+
+static struct mdp4_overlay_pipe *lcdc_pipe;
+
+int mdp_lcdc_on(struct platform_device *pdev)
+{
+	int lcdc_width;
+	int lcdc_height;
+	int lcdc_bpp;
+	int lcdc_border_clr;
+	int lcdc_underflow_clr;
+	int lcdc_hsync_skew;
+
+	int hsync_period;
+	int hsync_ctrl;
+	int vsync_period;
+	int display_hctl;
+	int display_v_start;
+	int display_v_end;
+	int active_hctl;
+	int active_h_start;
+	int active_h_end;
+	int active_v_start;
+	int active_v_end;
+	int ctrl_polarity;
+	int h_back_porch;
+	int h_front_porch;
+	int v_back_porch;
+	int v_front_porch;
+	int hsync_pulse_width;
+	int vsync_pulse_width;
+	int hsync_polarity;
+	int vsync_polarity;
+	int data_en_polarity;
+	int hsync_start_x;
+	int hsync_end_x;
+	uint8 *buf;
+	int bpp, ptype;
+	uint32 format;
+	struct fb_info *fbi;
+	struct fb_var_screeninfo *var;
+	struct msm_fb_data_type *mfd;
+	struct mdp4_overlay_pipe *pipe;
+	int ret;
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	fbi = mfd->fbi;
+	var = &fbi->var;
+
+	/* MDP cmd block enable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+	bpp = fbi->var.bits_per_pixel / 8;
+	buf = (uint8 *) fbi->fix.smem_start;
+	buf += fbi->var.xoffset * bpp +
+		fbi->var.yoffset * fbi->fix.line_length;
+
+	if (bpp == 2)
+		format = MDP_RGB_565;
+	else if (bpp == 3)
+		format = MDP_RGB_888;
+	else
+		format = MDP_ARGB_8888;
+
+
+	if (lcdc_pipe == NULL) {
+		ptype = mdp4_overlay_format2type(format);
+		pipe = mdp4_overlay_pipe_alloc();
+		pipe->pipe_type = ptype;
+		/* use RGB1 pipe */
+		pipe->pipe_num  = OVERLAY_PIPE_RGB1;
+		pipe->mixer_stage  = MDP4_MIXER_STAGE_BASE;
+		pipe->mixer_num  = MDP4_MIXER0;
+		pipe->src_format = format;
+		mdp4_overlay_format2pipe(pipe);
+
+		lcdc_pipe = pipe; /* keep it */
+	} else {
+		pipe = lcdc_pipe;
+	}
+
+	pipe->src_height = fbi->var.yres;
+	pipe->src_width = fbi->var.xres;
+	pipe->src_h = fbi->var.yres;
+	pipe->src_w = fbi->var.xres;
+	pipe->src_y = 0;
+	pipe->src_x = 0;
+	pipe->srcp0_addr = (uint32) buf;
+	pipe->srcp0_ystride = fbi->fix.line_length;
+
+	mdp4_overlay_dmap_xy(pipe);
+	mdp4_overlay_dmap_cfg(mfd, 1);
+
+	mdp4_overlay_rgb_setup(pipe);
+
+	mdp4_mixer_stage_up(pipe);
+
+	mdp4_overlayproc_cfg(pipe);
+
+	/*
+	 * LCDC timing setting
+	 */
+	h_back_porch = var->left_margin;
+	h_front_porch = var->right_margin;
+	v_back_porch = var->upper_margin;
+	v_front_porch = var->lower_margin;
+	hsync_pulse_width = var->hsync_len;
+	vsync_pulse_width = var->vsync_len;
+	lcdc_border_clr = mfd->panel_info.lcdc.border_clr;
+	lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
+	lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
+
+	lcdc_width = mfd->panel_info.xres;
+	lcdc_height = mfd->panel_info.yres;
+	lcdc_bpp = mfd->panel_info.bpp;
+
+	hsync_period =
+	    hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
+	hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
+	hsync_start_x = hsync_pulse_width + h_back_porch;
+	hsync_end_x = hsync_period - h_front_porch - 1;
+	display_hctl = (hsync_end_x << 16) | hsync_start_x;
+
+	vsync_period =
+	    (vsync_pulse_width + v_back_porch + lcdc_height +
+	     v_front_porch) * hsync_period;
+	display_v_start =
+	    (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew;
+	display_v_end =
+	    vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1;
+
+	if (lcdc_width != var->xres) {
+		active_h_start = hsync_start_x + first_pixel_start_x;
+		active_h_end = active_h_start + var->xres - 1;
+		active_hctl =
+		    ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
+	} else {
+		active_hctl = 0;
+	}
+
+	if (lcdc_height != var->yres) {
+		active_v_start =
+		    display_v_start + first_pixel_start_y * hsync_period;
+		active_v_end = active_v_start + (var->yres) * hsync_period - 1;
+		active_v_start |= ACTIVE_START_Y_EN;
+	} else {
+		active_v_start = 0;
+		active_v_end = 0;
+	}
+
+
+#ifdef CONFIG_FB_MSM_MDP40
+	hsync_polarity = 1;
+	vsync_polarity = 1;
+	lcdc_underflow_clr |= 0x80000000;	/* enable recovery */
+#else
+	hsync_polarity = 0;
+	vsync_polarity = 0;
+#endif
+	data_en_polarity = 0;
+
+	ctrl_polarity =
+	    (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
+
+	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x4, hsync_ctrl);
+	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x8, vsync_period);
+	MDP_OUTP(MDP_BASE + LCDC_BASE + 0xc, vsync_pulse_width * hsync_period);
+	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x10, display_hctl);
+	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x14, display_v_start);
+	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x18, display_v_end);
+	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x28, lcdc_border_clr);
+	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x2c, lcdc_underflow_clr);
+	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x30, lcdc_hsync_skew);
+	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x38, ctrl_polarity);
+	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x1c, active_hctl);
+	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x20, active_v_start);
+	MDP_OUTP(MDP_BASE + LCDC_BASE + 0x24, active_v_end);
+
+	ret = panel_next_on(pdev);
+	if (ret == 0) {
+		/* enable LCDC block */
+		MDP_OUTP(MDP_BASE + LCDC_BASE, 1);
+		mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	}
+	/* MDP cmd block disable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+	return ret;
+}
+
+int mdp_lcdc_off(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct mdp4_overlay_pipe *pipe;
+
+	/* MDP cmd block enable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	MDP_OUTP(MDP_BASE + LCDC_BASE, 0);
+	/* MDP cmd block disable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+	ret = panel_next_off(pdev);
+
+	/* delay to make sure the last frame finishes */
+	mdelay(100);
+
+	/* dis-engage rgb0 from mixer */
+	pipe = lcdc_pipe;
+	mdp4_mixer_stage_down(pipe);
+
+	return ret;
+}
+
+/*
+ * mdp4_overlay0_done_lcdc: called from isr
+ */
+void mdp4_overlay0_done_lcdc()
+{
+	complete(&lcdc_pipe->comp);
+}
+
+void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd)
+{
+	struct fb_info *fbi = mfd->fbi;
+	uint8 *buf;
+	int bpp;
+	unsigned long flag;
+	struct mdp4_overlay_pipe *pipe;
+
+	if (!mfd->panel_power_on)
+		return;
+
+	/* no need to power on cmd block since it's lcdc mode */
+	bpp = fbi->var.bits_per_pixel / 8;
+	buf = (uint8 *) fbi->fix.smem_start;
+	buf += fbi->var.xoffset * bpp +
+		fbi->var.yoffset * fbi->fix.line_length;
+
+	mutex_lock(&mfd->dma->ov_mutex);
+
+	pipe = lcdc_pipe;
+	pipe->srcp0_addr = (uint32) buf;
+	mdp4_overlay_rgb_setup(pipe);
+	mdp4_overlay_reg_flush(pipe, 1); /* rgb1 and mixer0 */
+
+	/* enable irq */
+	spin_lock_irqsave(&mdp_spin_lock, flag);
+	mdp_enable_irq(MDP_OVERLAY0_TERM);
+	INIT_COMPLETION(lcdc_pipe->comp);
+	mfd->dma->waiting = TRUE;
+	outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE);
+	mdp_intr_mask |= INTR_OVERLAY0_DONE;
+	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+	wait_for_completion_killable(&lcdc_pipe->comp);
+	mdp_disable_irq(MDP_OVERLAY0_TERM);
+
+	mutex_unlock(&mfd->dma->ov_mutex);
+}

+ 254 - 0
drivers/staging/msm/mdp4_overlay_mddi.c

@@ -0,0 +1,254 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+static struct mdp4_overlay_pipe *mddi_pipe;
+static struct mdp4_overlay_pipe *pending_pipe;
+static struct msm_fb_data_type *mddi_mfd;
+
+#define WHOLESCREEN
+
+void mdp4_overlay_update_lcd(struct msm_fb_data_type *mfd)
+{
+	MDPIBUF *iBuf = &mfd->ibuf;
+	uint8 *src;
+	int bpp, ptype;
+	uint32 format;
+	uint32 mddi_ld_param;
+	uint16 mddi_vdo_packet_reg;
+	struct mdp4_overlay_pipe *pipe;
+
+	if (mfd->key != MFD_KEY)
+		return;
+
+	mddi_mfd = mfd;		/* keep it */
+
+	bpp = iBuf->bpp;
+
+	if (bpp == 2)
+		format = MDP_RGB_565;
+	else if (bpp == 3)
+		format = MDP_RGB_888;
+	else
+		format = MDP_ARGB_8888;
+
+	/* MDP cmd block enable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+	if (mddi_pipe == NULL) {
+		ptype = mdp4_overlay_format2type(format);
+		pipe = mdp4_overlay_pipe_alloc();
+		pipe->pipe_type = ptype;
+		/* use RGB1 pipe */
+		pipe->pipe_num  = OVERLAY_PIPE_RGB1;
+		pipe->mixer_num  = MDP4_MIXER0;
+		pipe->src_format = format;
+		mdp4_overlay_format2pipe(pipe);
+
+		mddi_pipe = pipe; /* keep it */
+
+		mddi_ld_param = 0;
+		mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
+
+		if (mfd->panel_info.type == MDDI_PANEL) {
+			if (mfd->panel_info.pdest == DISPLAY_1)
+				mddi_ld_param = 0;
+			else
+				mddi_ld_param = 1;
+		} else {
+			mddi_ld_param = 2;
+		}
+
+		MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
+		MDP_OUTP(MDP_BASE + 0x00094,
+			 (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
+	} else {
+		pipe = mddi_pipe;
+	}
+
+
+	src = (uint8 *) iBuf->buf;
+
+#ifdef WHOLESCREEN
+	{
+		struct fb_info *fbi;
+
+		fbi = mfd->fbi;
+		pipe->src_height = fbi->var.yres;
+		pipe->src_width = fbi->var.xres;
+		pipe->src_h = fbi->var.yres;
+		pipe->src_w = fbi->var.xres;
+		pipe->src_y = 0;
+		pipe->src_x = 0;
+		pipe->dst_h = fbi->var.yres;
+		pipe->dst_w = fbi->var.xres;
+		pipe->dst_y = 0;
+		pipe->dst_x = 0;
+		pipe->srcp0_addr = (uint32)src;
+		pipe->srcp0_ystride = fbi->var.xres_virtual * bpp;
+	}
+
+#else
+	if (mdp4_overlay_active(MDP4_MIXER0)) {
+		struct fb_info *fbi;
+
+		fbi = mfd->fbi;
+		pipe->src_height = fbi->var.yres;
+		pipe->src_width = fbi->var.xres;
+		pipe->src_h = fbi->var.yres;
+		pipe->src_w = fbi->var.xres;
+		pipe->src_y = 0;
+		pipe->src_x = 0;
+		pipe->dst_h = fbi->var.yres;
+		pipe->dst_w = fbi->var.xres;
+		pipe->dst_y = 0;
+		pipe->dst_x = 0;
+		pipe->srcp0_addr = (uint32) src;
+		pipe->srcp0_ystride = fbi->var.xres_virtual * bpp;
+	} else {
+		/* starting input address */
+		src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * bpp;
+
+		pipe->src_height = iBuf->dma_h;
+		pipe->src_width = iBuf->dma_w;
+		pipe->src_h = iBuf->dma_h;
+		pipe->src_w = iBuf->dma_w;
+		pipe->src_y = 0;
+		pipe->src_x = 0;
+		pipe->dst_h = iBuf->dma_h;
+		pipe->dst_w = iBuf->dma_w;
+		pipe->dst_y = iBuf->dma_y;
+		pipe->dst_x = iBuf->dma_x;
+		pipe->srcp0_addr = (uint32) src;
+		pipe->srcp0_ystride = iBuf->ibuf_width * bpp;
+	}
+#endif
+
+	pipe->mixer_stage  = MDP4_MIXER_STAGE_BASE;
+
+	mdp4_overlay_rgb_setup(pipe);
+
+	mdp4_mixer_stage_up(pipe);
+
+	mdp4_overlayproc_cfg(pipe);
+
+	mdp4_overlay_dmap_xy(pipe);
+
+	mdp4_overlay_dmap_cfg(mfd, 0);
+
+	/* MDP cmd block disable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+}
+
+/*
+ * mdp4_overlay0_done_mddi: called from isr
+ */
+void mdp4_overlay0_done_mddi()
+{
+	if (pending_pipe)
+		complete(&pending_pipe->comp);
+}
+
+void mdp4_mddi_overlay_restore(void)
+{
+	/* mutex holded by caller */
+	mdp4_overlay_update_lcd(mddi_mfd);
+	mdp4_mddi_overlay_kickoff(mddi_mfd, mddi_pipe);
+}
+
+void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
+				struct mdp4_overlay_pipe *pipe)
+{
+#ifdef MDP4_NONBLOCKING
+	unsigned long flag;
+
+	spin_lock_irqsave(&mdp_spin_lock, flag);
+	if (mfd->dma->busy == TRUE) {
+		INIT_COMPLETION(pipe->comp);
+		pending_pipe = pipe;
+	}
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+	if (pending_pipe != NULL) {
+		/* wait until DMA finishes the current job */
+		wait_for_completion_killable(&pipe->comp);
+		pending_pipe = NULL;
+	}
+	down(&mfd->sem);
+	mdp_enable_irq(MDP_OVERLAY0_TERM);
+	mfd->dma->busy = TRUE;
+	/* start OVERLAY pipe */
+	mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
+	up(&mfd->sem);
+#else
+	down(&mfd->sem);
+	mdp_enable_irq(MDP_OVERLAY0_TERM);
+	mfd->dma->busy = TRUE;
+	INIT_COMPLETION(pipe->comp);
+	pending_pipe = pipe;
+
+	/* start OVERLAY pipe */
+	mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
+	up(&mfd->sem);
+
+	/* wait until DMA finishes the current job */
+	wait_for_completion_killable(&pipe->comp);
+	mdp_disable_irq(MDP_OVERLAY0_TERM);
+#endif
+
+}
+
+void mdp4_mddi_overlay(struct msm_fb_data_type *mfd)
+{
+	mutex_lock(&mfd->dma->ov_mutex);
+
+	if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
+		mdp4_overlay_update_lcd(mfd);
+
+		mdp4_mddi_overlay_kickoff(mfd, mddi_pipe);
+
+	/* signal if pan function is waiting for the update completion */
+		if (mfd->pan_waiting) {
+			mfd->pan_waiting = FALSE;
+			complete(&mfd->pan_comp);
+		}
+	}
+
+	mutex_unlock(&mfd->dma->ov_mutex);
+}

+ 1686 - 0
drivers/staging/msm/mdp4_util.c

@@ -0,0 +1,1686 @@
+
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+void mdp4_sw_reset(ulong bits)
+{
+	bits &= 0x1f;	/* 5 bits */
+	outpdw(MDP_BASE + 0x001c, bits);	/* MDP_SW_RESET */
+
+	while (inpdw(MDP_BASE + 0x001c) & bits) /* self clear when complete */
+		;
+	MSM_FB_INFO("mdp4_sw_reset: 0x%x\n", (int)bits);
+}
+
+void mdp4_overlay_cfg(int overlayer, int blt_mode, int refresh, int direct_out)
+{
+	ulong bits = 0;
+
+	if (blt_mode)
+		bits |= (1 << 3);
+	refresh &= 0x03;	/* 2 bites */
+	bits |= (refresh << 1);
+	direct_out &= 0x01;
+	bits |= direct_out;
+
+	if (overlayer == MDP4_MIXER0)
+		outpdw(MDP_BASE + 0x10004, bits); /* MDP_OVERLAY0_CFG */
+	else
+		outpdw(MDP_BASE + 0x18004, bits); /* MDP_OVERLAY1_CFG */
+
+	MSM_FB_INFO("mdp4_overlay_cfg: 0x%x\n", (int)inpdw(MDP_BASE + 0x10004));
+}
+
+void mdp4_display_intf_sel(int output, ulong intf)
+{
+	ulong bits, mask;
+
+	bits = inpdw(MDP_BASE + 0x0038);	/* MDP_DISP_INTF_SEL */
+
+	mask = 0x03;	/* 2 bits */
+	intf &= 0x03;	/* 2 bits */
+
+	switch (output) {
+	case EXTERNAL_INTF_SEL:
+		intf <<= 4;
+		mask <<= 4;
+		break;
+	case SECONDARY_INTF_SEL:
+		intf &= 0x02;	/* only MDDI and EBI2 support */
+		intf <<= 2;
+		mask <<= 2;
+		break;
+	default:
+		break;
+	}
+
+
+	bits &= ~mask;
+	bits |= intf;
+
+	outpdw(MDP_BASE + 0x0038, bits);	/* MDP_DISP_INTF_SEL */
+
+  MSM_FB_INFO("mdp4_display_intf_sel: 0x%x\n", (int)inpdw(MDP_BASE + 0x0038));
+}
+
+unsigned long mdp4_display_status(void)
+{
+	return inpdw(MDP_BASE + 0x0018) & 0x3ff;	/* MDP_DISPLAY_STATUS */
+}
+
+void mdp4_ebi2_lcd_setup(int lcd, ulong base, int ystride)
+{
+	/* always use memory map */
+	ystride &= 0x01fff;	/* 13 bits */
+	if (lcd == EBI2_LCD0) {
+		outpdw(MDP_BASE + 0x0060, base);/* MDP_EBI2_LCD0 */
+		outpdw(MDP_BASE + 0x0068, ystride);/* MDP_EBI2_LCD0_YSTRIDE */
+	} else {
+		outpdw(MDP_BASE + 0x0064, base);/* MDP_EBI2_LCD1 */
+		outpdw(MDP_BASE + 0x006c, ystride);/* MDP_EBI2_LCD1_YSTRIDE */
+	}
+}
+
+void mdp4_mddi_setup(int mddi, unsigned long id)
+{
+	ulong 	bits;
+
+	if (mddi == MDDI_EXTERNAL_SET)
+		bits = 0x02;
+	else if (mddi == MDDI_SECONDARY_SET)
+		bits = 0x01;
+	else
+		bits = 0;	/* PRIMARY_SET */
+
+	id <<= 16;
+
+	bits |= id;
+
+	outpdw(MDP_BASE + 0x0090, bits); /* MDP_MDDI_PARAM_WR_SEL */
+}
+
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
+	struct file **pp_src_file, struct file **pp_dst_file)
+{
+
+	/* not implemented yet */
+	return -1;
+}
+
+void mdp4_hw_init(void)
+{
+	ulong bits;
+
+	/* MDP cmd block enable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifdef MDP4_ERROR
+	/*
+	 * Issue software reset on DMA_P will casue DMA_P dma engine stall
+	 * on LCDC mode. However DMA_P does not stall at MDDI mode.
+	 * This need further investigation.
+	 */
+	mdp4_sw_reset(0x17);
+#endif
+
+	mdp4_clear_lcdc();
+
+	mdp4_mixer_blend_init(0);
+	mdp4_mixer_blend_init(1);
+	mdp4_vg_qseed_init(0);
+	mdp4_vg_qseed_init(1);
+	mdp4_vg_csc_mv_setup(0);
+	mdp4_vg_csc_mv_setup(1);
+	mdp4_vg_csc_pre_bv_setup(0);
+	mdp4_vg_csc_pre_bv_setup(1);
+	mdp4_vg_csc_post_bv_setup(0);
+	mdp4_vg_csc_post_bv_setup(1);
+	mdp4_vg_csc_pre_lv_setup(0);
+	mdp4_vg_csc_pre_lv_setup(1);
+	mdp4_vg_csc_post_lv_setup(0);
+	mdp4_vg_csc_post_lv_setup(1);
+
+	mdp4_mixer_gc_lut_setup(0);
+	mdp4_mixer_gc_lut_setup(1);
+
+	mdp4_vg_igc_lut_setup(0);
+	mdp4_vg_igc_lut_setup(1);
+
+	 mdp4_rgb_igc_lut_setup(0);
+	 mdp4_rgb_igc_lut_setup(1);
+
+	outp32(MDP_EBI2_PORTMAP_MODE, 0x3);
+
+	/* system interrupts */
+
+	bits =  mdp_intr_mask;
+	outpdw(MDP_BASE + 0x0050, bits);/* enable specififed interrupts */
+
+	/* histogram */
+	MDP_OUTP(MDP_BASE + 0x95010, 1);	/* auto clear HIST */
+
+	/* enable histogram interrupts */
+	outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE);
+
+	/* For the max read pending cmd config below, if the MDP clock     */
+	/* is less than the AXI clock, then we must use 3 pending          */
+	/* pending requests.  Otherwise, we should use 8 pending requests. */
+	/* In the future we should do this detection automatically.	   */
+
+	/* max read pending cmd config */
+	outpdw(MDP_BASE + 0x004c, 0x02222);	/* 3 pending requests */
+
+	/* dma_p fetch config */
+	outpdw(MDP_BASE + 0x91004, 0x27);	/* burst size of 8 */
+
+#ifndef CONFIG_FB_MSM_OVERLAY
+	/* both REFRESH_MODE and DIRECT_OUT are ignored at BLT mode */
+	mdp4_overlay_cfg(MDP4_MIXER0, OVERLAY_MODE_BLT, 0, 0);
+	mdp4_overlay_cfg(MDP4_MIXER1, OVERLAY_MODE_BLT, 0, 0);
+#endif
+
+	/* MDP cmd block disable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+
+void mdp4_clear_lcdc(void)
+{
+	uint32 bits;
+
+	bits = inpdw(MDP_BASE + 0xc0000);
+	if (bits & 0x01) /* enabled already */
+		return;
+
+	outpdw(MDP_BASE + 0xc0004, 0);	/* vsync ctrl out */
+	outpdw(MDP_BASE + 0xc0008, 0);	/* vsync period */
+	outpdw(MDP_BASE + 0xc000c, 0);	/* vsync pusle width */
+	outpdw(MDP_BASE + 0xc0010, 0);	/* lcdc display HCTL */
+	outpdw(MDP_BASE + 0xc0014, 0);	/* lcdc display v start */
+	outpdw(MDP_BASE + 0xc0018, 0);	/* lcdc display v end */
+	outpdw(MDP_BASE + 0xc001c, 0);	/* lcdc active hctl */
+	outpdw(MDP_BASE + 0xc0020, 0);	/* lcdc active v start */
+	outpdw(MDP_BASE + 0xc0024, 0);	/* lcdc active v end */
+	outpdw(MDP_BASE + 0xc0028, 0);	/* lcdc board color */
+	outpdw(MDP_BASE + 0xc002c, 0);	/* lcdc underflow ctrl */
+	outpdw(MDP_BASE + 0xc0030, 0);	/* lcdc hsync skew */
+	outpdw(MDP_BASE + 0xc0034, 0);	/* lcdc test ctl */
+	outpdw(MDP_BASE + 0xc0038, 0);	/* lcdc ctl polarity */
+}
+
+static struct mdp_dma_data overlay1_data;
+static int intr_dma_p;
+static int intr_dma_s;
+static int intr_dma_e;
+static int intr_overlay0;
+static int intr_overlay1;
+
+irqreturn_t mdp4_isr(int irq, void *ptr)
+{
+	uint32 isr, mask, lcdc;
+	struct mdp_dma_data *dma;
+
+	mdp_is_in_isr = TRUE;
+
+	while (1) {
+		isr = inpdw(MDP_INTR_STATUS);
+		if (isr == 0)
+			break;
+
+		mask = inpdw(MDP_INTR_ENABLE);
+		outpdw(MDP_INTR_CLEAR, isr);
+
+		isr &= mask;
+
+		if (unlikely(isr == 0))
+			break;
+
+		if (isr & INTR_DMA_P_DONE) {
+			intr_dma_p++;
+			lcdc = inpdw(MDP_BASE + 0xc0000);
+			dma = &dma2_data;
+			if (lcdc & 0x01) {	/* LCDC enable */
+				/* disable LCDC interrupt */
+				mdp_intr_mask &= ~INTR_DMA_P_DONE;
+				outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+				dma->waiting = FALSE;
+			} else {
+				dma->busy = FALSE;
+				mdp_pipe_ctrl(MDP_DMA2_BLOCK,
+					MDP_BLOCK_POWER_OFF, TRUE);
+			}
+			complete(&dma->comp);
+		}
+		if (isr & INTR_DMA_S_DONE) {
+			intr_dma_s++;
+			dma = &dma_s_data;
+			dma->busy = FALSE;
+			mdp_pipe_ctrl(MDP_DMA_S_BLOCK,
+					MDP_BLOCK_POWER_OFF, TRUE);
+			complete(&dma->comp);
+		}
+		if (isr & INTR_DMA_E_DONE) {
+			intr_dma_e++;
+			dma = &dma_e_data;
+			mdp_intr_mask &= ~INTR_DMA_E_DONE;
+			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+			dma->busy = FALSE;
+
+			if (dma->waiting) {
+				dma->waiting = FALSE;
+				complete(&dma->comp);
+			}
+		}
+		if (isr & INTR_OVERLAY0_DONE) {
+			intr_overlay0++;
+			lcdc = inpdw(MDP_BASE + 0xc0000);
+			dma = &dma2_data;
+			if (lcdc & 0x01) {	/* LCDC enable */
+				/* disable LCDC interrupt */
+				mdp_intr_mask &= ~INTR_OVERLAY0_DONE;
+				outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+				dma->waiting = FALSE;
+				mdp4_overlay0_done_lcdc();
+			} else {	/* MDDI */
+				dma->busy = FALSE;
+#ifdef MDP4_NONBLOCKING
+				mdp_disable_irq_nolock(MDP_OVERLAY0_TERM);
+#endif
+				mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK,
+					MDP_BLOCK_POWER_OFF, TRUE);
+				mdp4_overlay0_done_mddi();
+			}
+		}
+		if (isr & INTR_OVERLAY1_DONE) {
+			intr_overlay1++;
+			dma = &overlay1_data;
+			dma->busy = FALSE;
+			mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK,
+					MDP_BLOCK_POWER_OFF, TRUE);
+			complete(&dma->comp);
+		}
+		if (isr & INTR_DMA_P_HISTOGRAM) {
+			isr = inpdw(MDP_DMA_P_HIST_INTR_STATUS);
+			mask = inpdw(MDP_DMA_P_HIST_INTR_ENABLE);
+			outpdw(MDP_DMA_P_HIST_INTR_CLEAR, isr);
+			isr &= mask;
+			if (isr & INTR_HIST_DONE) {
+				if (mdp_hist.r)
+					memcpy(mdp_hist.r, MDP_BASE + 0x95100,
+							mdp_hist.bin_cnt*4);
+				if (mdp_hist.g)
+					memcpy(mdp_hist.g, MDP_BASE + 0x95200,
+							mdp_hist.bin_cnt*4);
+				if (mdp_hist.b)
+					memcpy(mdp_hist.b, MDP_BASE + 0x95300,
+						mdp_hist.bin_cnt*4);
+				complete(&mdp_hist_comp);
+			}
+		}
+	}
+
+	mdp_is_in_isr = FALSE;
+
+	return IRQ_HANDLED;
+}
+
+
+/*
+ * QSEED tables
+ */
+
+static uint32 vg_qseed_table0[] = {
+	0x5556aaff, 0x00000000, 0x00000000, 0x00000000
+};
+
+static uint32 vg_qseed_table1[] = {
+	0x76543210, 0xfedcba98
+};
+
+static uint32 vg_qseed_table2[] = {
+	0x02000000, 0x00000000, 0x02060ff2, 0x00000008,
+	0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021,
+	0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042,
+	0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068,
+	0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095,
+	0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6,
+	0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa,
+	0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d,
+	0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f,
+	0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f,
+	0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7,
+	0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc,
+	0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5,
+	0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203,
+	0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a,
+	0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206,
+	0x02000000, 0x00000000, 0x02040ff2, 0x0000000a,
+	0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029,
+	0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050,
+	0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c,
+	0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae,
+	0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2,
+	0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117,
+	0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148,
+	0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177,
+	0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2,
+	0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4,
+	0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2,
+	0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6,
+	0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203,
+	0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208,
+	0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205,
+	0x02000000, 0x00000000, 0x02020ff2, 0x0000000c,
+	0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030,
+	0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d,
+	0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e,
+	0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4,
+	0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9,
+	0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e,
+	0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d,
+	0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188,
+	0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae,
+	0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc,
+	0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7,
+	0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8,
+	0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202,
+	0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206,
+	0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204,
+	0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f,
+	0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e,
+	0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075,
+	0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad,
+	0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7,
+	0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e,
+	0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150,
+	0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b,
+	0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1,
+	0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0,
+	0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8,
+	0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed,
+	0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa,
+	0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202,
+	0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205,
+	0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203,
+	0x02000000, 0x00000000, 0x02050ff5, 0x00000006,
+	0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a,
+	0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034,
+	0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054,
+	0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079,
+	0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3,
+	0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1,
+	0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101,
+	0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132,
+	0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163,
+	0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f,
+	0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba,
+	0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc,
+	0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3,
+	0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201,
+	0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204,
+	0x02000000, 0x00000000, 0x02030ff5, 0x00000008,
+	0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020,
+	0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040,
+	0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065,
+	0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f,
+	0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd,
+	0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee,
+	0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d,
+	0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d,
+	0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b,
+	0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2,
+	0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6,
+	0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3,
+	0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6,
+	0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202,
+	0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203,
+	0x02000000, 0x00000000, 0x02020ff5, 0x00000009,
+	0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026,
+	0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b,
+	0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074,
+	0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3,
+	0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3,
+	0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105,
+	0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135,
+	0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162,
+	0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c,
+	0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af,
+	0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0,
+	0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7,
+	0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7,
+	0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200,
+	0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203,
+	0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c,
+	0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032,
+	0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f,
+	0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090,
+	0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4,
+	0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8,
+	0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129,
+	0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156,
+	0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e,
+	0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3,
+	0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0,
+	0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db,
+	0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed,
+	0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa,
+	0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201,
+	0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202,
+	0x02000000, 0x00000000, 0x02040ff7, 0x00000005,
+	0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016,
+	0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c,
+	0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046,
+	0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066,
+	0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b,
+	0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4,
+	0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0,
+	0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f,
+	0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140,
+	0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f,
+	0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e,
+	0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6,
+	0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5,
+	0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa,
+	0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202,
+	0x02000000, 0x00000000, 0x02030ff7, 0x00000006,
+	0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b,
+	0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035,
+	0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055,
+	0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079,
+	0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2,
+	0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf,
+	0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc,
+	0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b,
+	0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a,
+	0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185,
+	0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae,
+	0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1,
+	0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea,
+	0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb,
+	0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202,
+	0x02000000, 0x00000000, 0x02010ff7, 0x00000008,
+	0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020,
+	0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f,
+	0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062,
+	0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b,
+	0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7,
+	0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6,
+	0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114,
+	0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141,
+	0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d,
+	0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196,
+	0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb,
+	0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8,
+	0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed,
+	0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb,
+	0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201,
+	0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a,
+	0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a,
+	0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051,
+	0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b,
+	0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa,
+	0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da,
+	0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a,
+	0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138,
+	0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162,
+	0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b,
+	0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab,
+	0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9,
+	0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1,
+	0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2,
+	0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd,
+	0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201,
+	0x02000000, 0x00000000, 0x02030ff9, 0x00000004,
+	0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010,
+	0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020,
+	0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034,
+	0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d,
+	0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a,
+	0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c,
+	0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2,
+	0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd,
+	0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c,
+	0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b,
+	0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170,
+	0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0,
+	0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8,
+	0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea,
+	0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe,
+	0x02000000, 0x00000000, 0x02020ff9, 0x00000005,
+	0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014,
+	0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028,
+	0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040,
+	0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d,
+	0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f,
+	0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4,
+	0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd,
+	0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9,
+	0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128,
+	0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155,
+	0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185,
+	0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0,
+	0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3,
+	0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef,
+	0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff,
+	0x02000000, 0x00000000, 0x02010ff9, 0x00000006,
+	0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018,
+	0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f,
+	0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b,
+	0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c,
+	0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091,
+	0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9,
+	0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4,
+	0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110,
+	0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f,
+	0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a,
+	0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195,
+	0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb,
+	0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9,
+	0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1,
+	0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff,
+	0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008,
+	0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020,
+	0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e,
+	0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060,
+	0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087,
+	0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1,
+	0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd,
+	0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109,
+	0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135,
+	0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160,
+	0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187,
+	0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac,
+	0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb,
+	0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
+	0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
+	0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff,
+	0x02000000, 0x00000000, 0x02060ff2, 0x00000008,
+	0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021,
+	0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042,
+	0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068,
+	0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095,
+	0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6,
+	0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa,
+	0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d,
+	0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f,
+	0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f,
+	0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7,
+	0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc,
+	0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5,
+	0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203,
+	0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a,
+	0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206,
+	0x02000000, 0x00000000, 0x02040ff2, 0x0000000a,
+	0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029,
+	0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050,
+	0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c,
+	0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae,
+	0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2,
+	0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117,
+	0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148,
+	0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177,
+	0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2,
+	0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4,
+	0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2,
+	0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6,
+	0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203,
+	0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208,
+	0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205,
+	0x02000000, 0x00000000, 0x02020ff2, 0x0000000c,
+	0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030,
+	0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d,
+	0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e,
+	0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4,
+	0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9,
+	0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e,
+	0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d,
+	0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188,
+	0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae,
+	0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc,
+	0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7,
+	0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8,
+	0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202,
+	0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206,
+	0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204,
+	0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f,
+	0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e,
+	0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075,
+	0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad,
+	0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7,
+	0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e,
+	0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150,
+	0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b,
+	0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1,
+	0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0,
+	0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8,
+	0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed,
+	0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa,
+	0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202,
+	0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205,
+	0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203,
+	0x02000000, 0x00000000, 0x02050ff5, 0x00000006,
+	0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a,
+	0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034,
+	0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054,
+	0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079,
+	0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3,
+	0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1,
+	0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101,
+	0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132,
+	0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163,
+	0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f,
+	0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba,
+	0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc,
+	0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3,
+	0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201,
+	0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204,
+	0x02000000, 0x00000000, 0x02030ff5, 0x00000008,
+	0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020,
+	0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040,
+	0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065,
+	0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f,
+	0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd,
+	0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee,
+	0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d,
+	0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d,
+	0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b,
+	0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2,
+	0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6,
+	0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3,
+	0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6,
+	0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202,
+	0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203,
+	0x02000000, 0x00000000, 0x02020ff5, 0x00000009,
+	0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026,
+	0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b,
+	0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074,
+	0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3,
+	0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3,
+	0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105,
+	0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135,
+	0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162,
+	0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c,
+	0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af,
+	0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0,
+	0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7,
+	0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7,
+	0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200,
+	0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203,
+	0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c,
+	0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032,
+	0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f,
+	0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090,
+	0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4,
+	0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8,
+	0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129,
+	0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156,
+	0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e,
+	0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3,
+	0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0,
+	0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db,
+	0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed,
+	0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa,
+	0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201,
+	0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202,
+	0x02000000, 0x00000000, 0x02040ff7, 0x00000005,
+	0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016,
+	0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c,
+	0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046,
+	0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066,
+	0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b,
+	0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4,
+	0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0,
+	0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f,
+	0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140,
+	0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f,
+	0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e,
+	0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6,
+	0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5,
+	0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa,
+	0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202,
+	0x02000000, 0x00000000, 0x02030ff7, 0x00000006,
+	0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b,
+	0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035,
+	0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055,
+	0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079,
+	0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2,
+	0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf,
+	0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc,
+	0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b,
+	0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a,
+	0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185,
+	0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae,
+	0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1,
+	0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea,
+	0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb,
+	0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202,
+	0x02000000, 0x00000000, 0x02010ff7, 0x00000008,
+	0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020,
+	0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f,
+	0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062,
+	0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b,
+	0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7,
+	0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6,
+	0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114,
+	0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141,
+	0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d,
+	0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196,
+	0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb,
+	0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8,
+	0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed,
+	0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb,
+	0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201,
+	0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a,
+	0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a,
+	0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051,
+	0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b,
+	0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa,
+	0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da,
+	0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a,
+	0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138,
+	0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162,
+	0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b,
+	0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab,
+	0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9,
+	0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1,
+	0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2,
+	0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd,
+	0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201,
+	0x02000000, 0x00000000, 0x02030ff9, 0x00000004,
+	0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010,
+	0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020,
+	0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034,
+	0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d,
+	0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a,
+	0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c,
+	0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2,
+	0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd,
+	0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c,
+	0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b,
+	0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170,
+	0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0,
+	0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8,
+	0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea,
+	0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe,
+	0x02000000, 0x00000000, 0x02020ff9, 0x00000005,
+	0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014,
+	0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028,
+	0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040,
+	0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d,
+	0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f,
+	0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4,
+	0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd,
+	0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9,
+	0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128,
+	0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155,
+	0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185,
+	0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0,
+	0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3,
+	0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef,
+	0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff,
+	0x02000000, 0x00000000, 0x02010ff9, 0x00000006,
+	0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018,
+	0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f,
+	0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b,
+	0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c,
+	0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091,
+	0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9,
+	0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4,
+	0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110,
+	0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f,
+	0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a,
+	0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195,
+	0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb,
+	0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9,
+	0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1,
+	0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff,
+	0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008,
+	0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020,
+	0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e,
+	0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060,
+	0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087,
+	0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1,
+	0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd,
+	0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109,
+	0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135,
+	0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160,
+	0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187,
+	0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac,
+	0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb,
+	0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3,
+	0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5,
+	0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff
+};
+
+
+#define MDP4_QSEED_TABLE0_OFF 0x8100
+#define MDP4_QSEED_TABLE1_OFF 0x8200
+#define MDP4_QSEED_TABLE2_OFF 0x9000
+
+void mdp4_vg_qseed_init(int vp_num)
+{
+	uint32 *off;
+	int i, voff;
+
+	voff = MDP4_VIDEO_OFF * vp_num;
+	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+						MDP4_QSEED_TABLE0_OFF);
+	for (i = 0; i < (sizeof(vg_qseed_table0) / sizeof(uint32)); i++) {
+		outpdw(off, vg_qseed_table0[i]);
+		off++;
+	}
+
+	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+						MDP4_QSEED_TABLE1_OFF);
+	for (i = 0; i < (sizeof(vg_qseed_table1) / sizeof(uint32)); i++) {
+		outpdw(off, vg_qseed_table1[i]);
+		off++;
+	}
+
+	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+						MDP4_QSEED_TABLE2_OFF);
+	for (i = 0; i < (sizeof(vg_qseed_table2) / sizeof(uint32)); i++) {
+		outpdw(off, vg_qseed_table2[i]);
+		off++;
+	}
+
+}
+
+void mdp4_mixer_blend_init(mixer_num)
+{
+	unsigned char *overlay_base;
+	int off;
+
+	if (mixer_num) 	/* mixer number, /dev/fb0, /dev/fb1 */
+		overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+	else
+		overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+	/* stage 0 to stage 2 */
+	off = 0;
+	outpdw(overlay_base + off + 0x104, 0x010);
+	outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+	outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
+
+	off += 0x20;
+	outpdw(overlay_base + off + 0x104, 0x010);
+	outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+	outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
+
+	off += 0x20;
+	outpdw(overlay_base + off + 0x104, 0x010);
+	outpdw(overlay_base + off + 0x108, 0xff);/* FG */
+	outpdw(overlay_base + off + 0x10c, 0x00);/* BG */
+}
+
+
+static uint32 csc_matrix_tab[9] = {
+	0x0254, 0x0000, 0x0331,
+	0x0254, 0xff37, 0xfe60,
+	0x0254, 0x0409, 0x0000
+};
+
+static uint32 csc_pre_bv_tab[3] = {0xfff0, 0xff80, 0xff80 };
+static uint32 csc_post_bv_tab[3] = {0, 0, 0 };
+
+static  uint32 csc_pre_lv_tab[6] =  {0, 0xff, 0, 0xff, 0, 0xff };
+static  uint32 csc_post_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff };
+
+#define MDP4_CSC_MV_OFF 	0x4400
+#define MDP4_CSC_PRE_BV_OFF 	0x4500
+#define MDP4_CSC_POST_BV_OFF 	0x4580
+#define MDP4_CSC_PRE_LV_OFF 	0x4600
+#define MDP4_CSC_POST_LV_OFF 	0x4680
+
+void mdp4_vg_csc_mv_setup(int vp_num)
+{
+	uint32 *off;
+	int i, voff;
+
+	voff = MDP4_VIDEO_OFF * vp_num;
+	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+					MDP4_CSC_MV_OFF);
+	for (i = 0; i < 9; i++) {
+		outpdw(off, csc_matrix_tab[i]);
+		off++;
+	}
+}
+
+void mdp4_vg_csc_pre_bv_setup(int vp_num)
+{
+	uint32 *off;
+	int i, voff;
+
+	voff = MDP4_VIDEO_OFF * vp_num;
+	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+					MDP4_CSC_PRE_BV_OFF);
+	for (i = 0; i < 3; i++) {
+		outpdw(off, csc_pre_bv_tab[i]);
+		off++;
+	}
+}
+
+void mdp4_vg_csc_post_bv_setup(int vp_num)
+{
+	uint32 *off;
+	int i, voff;
+
+	voff = MDP4_VIDEO_OFF * vp_num;
+	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+					MDP4_CSC_POST_BV_OFF);
+	for (i = 0; i < 3; i++) {
+		outpdw(off, csc_post_bv_tab[i]);
+		off++;
+	}
+}
+
+void mdp4_vg_csc_pre_lv_setup(int vp_num)
+{
+	uint32 *off;
+	int i, voff;
+
+	voff = MDP4_VIDEO_OFF * vp_num;
+	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+					MDP4_CSC_PRE_LV_OFF);
+
+	for (i = 0; i < 6; i++) {
+		outpdw(off, csc_pre_lv_tab[i]);
+		off++;
+	}
+}
+
+void mdp4_vg_csc_post_lv_setup(int vp_num)
+{
+	uint32 *off;
+	int i, voff;
+
+	voff = MDP4_VIDEO_OFF * vp_num;
+	off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff +
+					MDP4_CSC_POST_LV_OFF);
+
+	for (i = 0; i < 6; i++) {
+		outpdw(off, csc_post_lv_tab[i]);
+		off++;
+	}
+}
+
+char gc_lut[] = {
+	0x0, 0x1, 0x2, 0x2, 0x3, 0x4, 0x5, 0x6,
+	0x6, 0x7, 0x8, 0x9, 0xA, 0xA, 0xB, 0xC,
+	0xD, 0xD, 0xE, 0xF, 0xF, 0x10, 0x10, 0x11,
+	0x12, 0x12, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15,
+	0x16, 0x16, 0x17, 0x17, 0x17, 0x18, 0x18, 0x19,
+	0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C,
+	0x1C, 0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F,
+	0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21,
+	0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24,
+	0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26,
+	0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28,
+	0x28, 0x29, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A,
+	0x2A, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2C, 0x2C,
+	0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E,
+	0x2E, 0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x2F, 0x30,
+	0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
+	0x31, 0x32, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33,
+	0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x34, 0x34,
+	0x35, 0x35, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36,
+	0x36, 0x36, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
+	0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39,
+	0x39, 0x39, 0x39, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A,
+	0x3A, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3C,
+	0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D,
+	0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E,
+	0x3E, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x40,
+	0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41,
+	0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43, 0x43,
+	0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+	0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
+	0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47,
+	0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48,
+	0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49,
+	0x49, 0x49, 0x49, 0x49, 0x49, 0x4A, 0x4A, 0x4A,
+	0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B, 0x4B,
+	0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4C, 0x4C, 0x4C,
+	0x4C, 0x4C, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4D,
+	0x4D, 0x4D, 0x4D, 0x4D, 0x4E, 0x4E, 0x4E, 0x4E,
+	0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4F, 0x4F, 0x4F,
+	0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x50, 0x50, 0x50,
+	0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51,
+	0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52,
+	0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x53, 0x53,
+	0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54,
+	0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
+	0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+	0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56,
+	0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+	0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58,
+	0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59,
+	0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5A, 0x5A,
+	0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+	0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B,
+	0x5B, 0x5B, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
+	0x5C, 0x5C, 0x5C, 0x5C, 0x5D, 0x5D, 0x5D, 0x5D,
+	0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5E, 0x5E,
+	0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E,
+	0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F,
+	0x5F, 0x5F, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
+	0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+	0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x62,
+	0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62,
+	0x62, 0x62, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x64, 0x64, 0x64,
+	0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+	0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
+	0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66,
+	0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x67,
+	0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67,
+	0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68,
+	0x68, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69,
+	0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
+	0x69, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
+	0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6B, 0x6B, 0x6B,
+	0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B,
+	0x6B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C,
+	0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D,
+	0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
+	0x6D, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E,
+	0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6F, 0x6F, 0x6F,
+	0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F,
+	0x6F, 0x6F, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
+	0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71,
+	0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
+	0x71, 0x71, 0x71, 0x72, 0x72, 0x72, 0x72, 0x72,
+	0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+	0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+	0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74,
+	0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74,
+	0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
+	0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
+	0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+	0x76, 0x76, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77,
+	0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+	0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x78, 0x78,
+	0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
+	0x78, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
+	0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x7A, 0x7A,
+	0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A,
+	0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7B,
+	0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B,
+	0x7B, 0x7B, 0x7B, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C,
+	0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C,
+	0x7C, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
+	0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
+	0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E,
+	0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F,
+	0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
+	0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x80, 0x80, 0x80,
+	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+	0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81,
+	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+	0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x82,
+	0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
+	0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+	0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+	0x83, 0x83, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
+	0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
+	0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+	0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+	0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
+	0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
+	0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
+	0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
+	0x87, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+	0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
+	0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
+	0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
+	0x89, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A,
+	0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A,
+	0x8A, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B,
+	0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B,
+	0x8B, 0x8B, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C,
+	0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C,
+	0x8C, 0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D,
+	0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D,
+	0x8D, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8E, 0x8E,
+	0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E,
+	0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, 0x8F, 0x8F,
+	0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F,
+	0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x90, 0x90,
+	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x91,
+	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+	0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
+	0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
+	0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
+	0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+	0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+	0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+	0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95,
+	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+	0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
+	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
+	0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x97,
+	0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97,
+	0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+	0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
+	0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
+	0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+	0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+	0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0x9B, 0x9B,
+	0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B,
+	0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B,
+	0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C,
+	0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C,
+	0x9C, 0x9C, 0x9C, 0x9C, 0x9D, 0x9D, 0x9D, 0x9D,
+	0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D,
+	0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9E,
+	0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+	0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E,
+	0x9E, 0x9E, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F,
+	0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F,
+	0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0xA0, 0xA0,
+	0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+	0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+	0xA0, 0xA0, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
+	0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
+	0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA2, 0xA2,
+	0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2,
+	0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2,
+	0xA2, 0xA2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
+	0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
+	0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA4, 0xA4,
+	0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+	0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4,
+	0xA4, 0xA4, 0xA4, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+	0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+	0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5,
+	0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
+	0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
+	0xA6, 0xA6, 0xA6, 0xA6, 0xA7, 0xA7, 0xA7, 0xA7,
+	0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7,
+	0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7,
+	0xA7, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
+	0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8,
+	0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA9,
+	0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9,
+	0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9,
+	0xA9, 0xA9, 0xA9, 0xA9, 0xAA, 0xAA, 0xAA, 0xAA,
+	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+	0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+	0xAA, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
+	0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB,
+	0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAC,
+	0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+	0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC,
+	0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAD, 0xAD, 0xAD,
+	0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD,
+	0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD,
+	0xAD, 0xAD, 0xAD, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
+	0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
+	0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
+	0xAE, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF,
+	0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF,
+	0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xB0,
+	0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0,
+	0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0,
+	0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB1, 0xB1,
+	0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1,
+	0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1,
+	0xB1, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2, 0xB2, 0xB2,
+	0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2,
+	0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2,
+	0xB2, 0xB2, 0xB2, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
+	0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
+	0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3,
+	0xB3, 0xB3, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
+	0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
+	0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
+	0xB4, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
+	0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
+	0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5,
+	0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+	0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+	0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+	0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7,
+	0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7,
+	0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB8,
+	0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8,
+	0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8,
+	0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB9,
+	0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
+	0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
+	0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xBA,
+	0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA,
+	0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA,
+	0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBB,
+	0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
+	0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
+	0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
+	0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
+	0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
+	0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC,
+	0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
+	0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
+	0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD,
+	0xBD, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
+	0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
+	0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE,
+	0xBE, 0xBE, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
+	0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
+	0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF,
+	0xBF, 0xBF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+	0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+	0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
+	0xC0, 0xC0, 0xC0, 0xC0, 0xC1, 0xC1, 0xC1, 0xC1,
+	0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
+	0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1,
+	0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC2, 0xC2, 0xC2,
+	0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
+	0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
+	0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC3, 0xC3,
+	0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+	0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+	0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3,
+	0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
+	0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
+	0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4,
+	0xC4, 0xC4, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
+	0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
+	0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5,
+	0xC5, 0xC5, 0xC5, 0xC5, 0xC6, 0xC6, 0xC6, 0xC6,
+	0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
+	0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
+	0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, 0xC7,
+	0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
+	0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
+	0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7,
+	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+	0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+	0xC8, 0xC8, 0xC8, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
+	0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
+	0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9,
+	0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xCA, 0xCA,
+	0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
+	0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
+	0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA,
+	0xCA, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
+	0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
+	0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB,
+	0xCB, 0xCB, 0xCB, 0xCB, 0xCC, 0xCC, 0xCC, 0xCC,
+	0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
+	0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
+	0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD,
+	0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
+	0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
+	0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD,
+	0xCD, 0xCD, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
+	0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
+	0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE,
+	0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCF, 0xCF,
+	0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
+	0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
+	0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF,
+	0xCF, 0xCF, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
+	0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
+	0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
+	0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD1, 0xD1, 0xD1,
+	0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
+	0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
+	0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1,
+	0xD1, 0xD1, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+	0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+	0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2,
+	0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD3, 0xD3,
+	0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
+	0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
+	0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3,
+	0xD3, 0xD3, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
+	0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
+	0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4,
+	0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD5,
+	0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
+	0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
+	0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5,
+	0xD5, 0xD5, 0xD5, 0xD5, 0xD6, 0xD6, 0xD6, 0xD6,
+	0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
+	0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
+	0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6,
+	0xD6, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
+	0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
+	0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
+	0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD8, 0xD8,
+	0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
+	0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
+	0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
+	0xD8, 0xD8, 0xD8, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+	0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+	0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+	0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9,
+	0xD9, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
+	0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
+	0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
+	0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDB, 0xDB,
+	0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
+	0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
+	0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB,
+	0xDB, 0xDB, 0xDB, 0xDB, 0xDC, 0xDC, 0xDC, 0xDC,
+	0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
+	0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
+	0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC,
+	0xDC, 0xDC, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+	0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+	0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+	0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
+	0xDD, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
+	0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
+	0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE,
+	0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDF,
+	0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
+	0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
+	0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF,
+	0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xE0, 0xE0,
+	0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+	0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+	0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+	0xE0, 0xE0, 0xE0, 0xE0, 0xE1, 0xE1, 0xE1, 0xE1,
+	0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
+	0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
+	0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1,
+	0xE1, 0xE1, 0xE1, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+	0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+	0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+	0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2,
+	0xE2, 0xE2, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+	0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+	0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+	0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3,
+	0xE3, 0xE3, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+	0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+	0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+	0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4,
+	0xE4, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+	0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+	0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+	0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+	0xE5, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+	0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+	0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+	0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6,
+	0xE6, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+	0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+	0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+	0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
+	0xE7, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+	0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+	0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+	0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8,
+	0xE8, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+	0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+	0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+	0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9,
+	0xE9, 0xE9, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+	0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+	0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+	0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA,
+	0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+	0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+	0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+	0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB,
+	0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+	0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+	0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+	0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC,
+	0xEC, 0xEC, 0xEC, 0xEC, 0xED, 0xED, 0xED, 0xED,
+	0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+	0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+	0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+	0xED, 0xED, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEE,
+	0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+	0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+	0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+	0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF,
+	0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+	0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+	0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+	0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+	0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+	0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+	0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+	0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+	0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+	0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+	0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+	0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1,
+	0xF1, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF2, 0xF2,
+	0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+	0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+	0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+	0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF3, 0xF3,
+	0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+	0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+	0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+	0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3,
+	0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+	0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+	0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+	0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4,
+	0xF4, 0xF4, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+	0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+	0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+	0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5,
+	0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6,
+	0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+	0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+	0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+	0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6,
+	0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+	0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+	0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+	0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
+	0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+	0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+	0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+	0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
+	0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9,
+	0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+	0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+	0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+	0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9,
+	0xF9, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+	0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+	0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+	0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+	0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB,
+	0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+	0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+	0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+	0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB,
+	0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+	0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+	0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+	0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+	0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD,
+	0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+	0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+	0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+	0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD,
+	0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+	0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+	0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+	0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+	0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+void mdp4_mixer_gc_lut_setup(int mixer_num)
+{
+	unsigned char *base;
+	uint32 data;
+	char val;
+	int i, off;
+
+	if (mixer_num) 	/* mixer number, /dev/fb0, /dev/fb1 */
+		base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+	else
+		base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
+
+	base += 0x4000;	/* GC_LUT offset */
+
+	off = 0;
+	for (i = 0; i < 4096; i++) {
+		val = gc_lut[i];
+		data = (val << 16 | val << 8 | val); /* R, B, and G are same */
+		outpdw(base + off, data);
+		off += 4;
+	}
+}
+
+uint32 igc_video_lut[] = {	 /* non linear */
+	0x0, 0x1, 0x2, 0x4, 0x5, 0x6, 0x7, 0x9,
+	0xA, 0xB, 0xC, 0xE, 0xF, 0x10, 0x12, 0x14,
+	0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23,
+	0x25, 0x28, 0x2A, 0x2D, 0x30, 0x32, 0x35, 0x38,
+	0x3B, 0x3E, 0x42, 0x45, 0x48, 0x4C, 0x4F, 0x53,
+	0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x70, 0x74,
+	0x79, 0x7E, 0x83, 0x88, 0x8D, 0x92, 0x97, 0x9C,
+	0xA2, 0xA8, 0xAD, 0xB3, 0xB9, 0xBF, 0xC5, 0xCC,
+	0xD2, 0xD8, 0xDF, 0xE6, 0xED, 0xF4, 0xFB, 0x102,
+	0x109, 0x111, 0x118, 0x120, 0x128, 0x130, 0x138, 0x140,
+	0x149, 0x151, 0x15A, 0x162, 0x16B, 0x174, 0x17D, 0x186,
+	0x190, 0x199, 0x1A3, 0x1AC, 0x1B6, 0x1C0, 0x1CA, 0x1D5,
+	0x1DF, 0x1EA, 0x1F4, 0x1FF, 0x20A, 0x215, 0x220, 0x22B,
+	0x237, 0x242, 0x24E, 0x25A, 0x266, 0x272, 0x27F, 0x28B,
+	0x298, 0x2A4, 0x2B1, 0x2BE, 0x2CB, 0x2D8, 0x2E6, 0x2F3,
+	0x301, 0x30F, 0x31D, 0x32B, 0x339, 0x348, 0x356, 0x365,
+	0x374, 0x383, 0x392, 0x3A1, 0x3B1, 0x3C0, 0x3D0, 0x3E0,
+	0x3F0, 0x400, 0x411, 0x421, 0x432, 0x443, 0x454, 0x465,
+	0x476, 0x487, 0x499, 0x4AB, 0x4BD, 0x4CF, 0x4E1, 0x4F3,
+	0x506, 0x518, 0x52B, 0x53E, 0x551, 0x565, 0x578, 0x58C,
+	0x5A0, 0x5B3, 0x5C8, 0x5DC, 0x5F0, 0x605, 0x61A, 0x62E,
+	0x643, 0x659, 0x66E, 0x684, 0x699, 0x6AF, 0x6C5, 0x6DB,
+	0x6F2, 0x708, 0x71F, 0x736, 0x74D, 0x764, 0x77C, 0x793,
+	0x7AB, 0x7C3, 0x7DB, 0x7F3, 0x80B, 0x824, 0x83D, 0x855,
+	0x86F, 0x888, 0x8A1, 0x8BB, 0x8D4, 0x8EE, 0x908, 0x923,
+	0x93D, 0x958, 0x973, 0x98E, 0x9A9, 0x9C4, 0x9DF, 0x9FB,
+	0xA17, 0xA33, 0xA4F, 0xA6C, 0xA88, 0xAA5, 0xAC2, 0xADF,
+	0xAFC, 0xB19, 0xB37, 0xB55, 0xB73, 0xB91, 0xBAF, 0xBCE,
+	0xBEC, 0xC0B, 0xC2A, 0xC4A, 0xC69, 0xC89, 0xCA8, 0xCC8,
+	0xCE8, 0xD09, 0xD29, 0xD4A, 0xD6B, 0xD8C, 0xDAD, 0xDCF,
+	0xDF0, 0xE12, 0xE34, 0xE56, 0xE79, 0xE9B, 0xEBE, 0xEE1,
+	0xF04, 0xF27, 0xF4B, 0xF6E, 0xF92, 0xFB6, 0xFDB, 0xFFF,
+};
+
+void mdp4_vg_igc_lut_setup(int vp_num)
+{
+	unsigned char *base;
+	int i, voff, off;
+	uint32 data, val;
+
+	voff = MDP4_VIDEO_OFF * vp_num;
+	base = MDP_BASE + MDP4_VIDEO_BASE + voff + 0x5000;
+
+	off = 0;
+	for (i = 0; i < 256; i++) {
+		val = igc_video_lut[i];
+		data = (val << 16 | val);	/* color 0 and 1 */
+		outpdw(base + off, data);
+		outpdw(base + off + 0x800, val);	/* color 2 */
+		off += 4;
+	}
+}
+
+uint32 igc_rgb_lut[] = {   /* linear */
+	0x0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
+	0x80, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
+	0x101, 0x111, 0x121, 0x131, 0x141, 0x151, 0x161, 0x171,
+	0x181, 0x191, 0x1A2, 0x1B2, 0x1C2, 0x1D2, 0x1E2, 0x1F2,
+	0x202, 0x212, 0x222, 0x232, 0x242, 0x252, 0x262, 0x272,
+	0x282, 0x292, 0x2A2, 0x2B3, 0x2C3, 0x2D3, 0x2E3, 0x2F3,
+	0x303, 0x313, 0x323, 0x333, 0x343, 0x353, 0x363, 0x373,
+	0x383, 0x393, 0x3A3, 0x3B3, 0x3C4, 0x3D4, 0x3E4, 0x3F4,
+	0x404, 0x414, 0x424, 0x434, 0x444, 0x454, 0x464, 0x474,
+	0x484, 0x494, 0x4A4, 0x4B4, 0x4C4, 0x4D5, 0x4E5, 0x4F5,
+	0x505, 0x515, 0x525, 0x535, 0x545, 0x555, 0x565, 0x575,
+	0x585, 0x595, 0x5A5, 0x5B5, 0x5C5, 0x5D5, 0x5E6, 0x5F6,
+	0x606, 0x616, 0x626, 0x636, 0x646, 0x656, 0x666, 0x676,
+	0x686, 0x696, 0x6A6, 0x6B6, 0x6C6, 0x6D6, 0x6E6, 0x6F7,
+	0x707, 0x717, 0x727, 0x737, 0x747, 0x757, 0x767, 0x777,
+	0x787, 0x797, 0x7A7, 0x7B7, 0x7C7, 0x7D7, 0x7E7, 0x7F7,
+	0x808, 0x818, 0x828, 0x838, 0x848, 0x858, 0x868, 0x878,
+	0x888, 0x898, 0x8A8, 0x8B8, 0x8C8, 0x8D8, 0x8E8, 0x8F8,
+	0x908, 0x919, 0x929, 0x939, 0x949, 0x959, 0x969, 0x979,
+	0x989, 0x999, 0x9A9, 0x9B9, 0x9C9, 0x9D9, 0x9E9, 0x9F9,
+	0xA09, 0xA19, 0xA2A, 0xA3A, 0xA4A, 0xA5A, 0xA6A, 0xA7A,
+	0xA8A, 0xA9A, 0xAAA, 0xABA, 0xACA, 0xADA, 0xAEA, 0xAFA,
+	0xB0A, 0xB1A, 0xB2A, 0xB3B, 0xB4B, 0xB5B, 0xB6B, 0xB7B,
+	0xB8B, 0xB9B, 0xBAB, 0xBBB, 0xBCB, 0xBDB, 0xBEB, 0xBFB,
+	0xC0B, 0xC1B, 0xC2B, 0xC3B, 0xC4C, 0xC5C, 0xC6C, 0xC7C,
+	0xC8C, 0xC9C, 0xCAC, 0xCBC, 0xCCC, 0xCDC, 0xCEC, 0xCFC,
+	0xD0C, 0xD1C, 0xD2C, 0xD3C, 0xD4C, 0xD5D, 0xD6D, 0xD7D,
+	0xD8D, 0xD9D, 0xDAD, 0xDBD, 0xDCD, 0xDDD, 0xDED, 0xDFD,
+	0xE0D, 0xE1D, 0xE2D, 0xE3D, 0xE4D, 0xE5D, 0xE6E, 0xE7E,
+	0xE8E, 0xE9E, 0xEAE, 0xEBE, 0xECE, 0xEDE, 0xEEE, 0xEFE,
+	0xF0E, 0xF1E, 0xF2E, 0xF3E, 0xF4E, 0xF5E, 0xF6E, 0xF7F,
+	0xF8F, 0xF9F, 0xFAF, 0xFBF, 0xFCF, 0xFDF, 0xFEF, 0xFFF,
+};
+
+void mdp4_rgb_igc_lut_setup(int num)
+{
+	unsigned char *base;
+	int i, voff, off;
+	uint32 data, val;
+
+	voff = MDP4_RGB_OFF * num;
+	base = MDP_BASE + MDP4_RGB_BASE + voff + 0x5000;
+
+	off = 0;
+	for (i = 0; i < 256; i++) {
+		val = igc_rgb_lut[i];
+		data = (val << 16 | val);	/* color 0 and 1 */
+		outpdw(base + off, data);
+		outpdw(base + off + 0x800, val);	/* color 2 */
+		off += 4;
+	}
+}

+ 104 - 0
drivers/staging/msm/mdp_cursor.c

@@ -0,0 +1,104 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+
+#include <mach/hardware.h>
+#include <asm/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+static int cursor_enabled;
+
+int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct fb_image *img = &cursor->image;
+	int calpha_en, transp_en;
+	int alpha;
+	int ret = 0;
+
+	if ((img->width > MDP_CURSOR_WIDTH) ||
+	    (img->height > MDP_CURSOR_HEIGHT) ||
+	    (img->depth != 32))
+		return -EINVAL;
+
+	if (cursor->set & FB_CUR_SETPOS)
+		MDP_OUTP(MDP_BASE + 0x9004c, (img->dy << 16) | img->dx);
+
+	if (cursor->set & FB_CUR_SETIMAGE) {
+		ret = copy_from_user(mfd->cursor_buf, img->data,
+					img->width*img->height*4);
+		if (ret)
+			return ret;
+
+		if (img->bg_color == 0xffffffff)
+			transp_en = 0;
+		else
+			transp_en = 1;
+
+		alpha = (img->fg_color & 0xff000000) >> 24;
+
+		if (alpha)
+			calpha_en = 0x2; /* xrgb */
+		else
+			calpha_en = 0x1; /* argb */
+
+		MDP_OUTP(MDP_BASE + 0x90044, (img->height << 16) | img->width);
+		MDP_OUTP(MDP_BASE + 0x90048, mfd->cursor_buf_phys);
+		/* order the writes the cursor_buf before updating the
+		 * hardware */
+//		dma_coherent_pre_ops();
+		MDP_OUTP(MDP_BASE + 0x90060,
+			 (transp_en << 3) | (calpha_en << 1) |
+			 (inp32(MDP_BASE + 0x90060) & 0x1));
+#ifdef CONFIG_FB_MSM_MDP40
+		MDP_OUTP(MDP_BASE + 0x90064, (alpha << 24));
+		MDP_OUTP(MDP_BASE + 0x90068, (0xffffff & img->bg_color));
+		MDP_OUTP(MDP_BASE + 0x9006C, (0xffffff & img->bg_color));
+#else
+		MDP_OUTP(MDP_BASE + 0x90064,
+			 (alpha << 24) | (0xffffff & img->bg_color));
+		MDP_OUTP(MDP_BASE + 0x90068, 0);
+#endif
+	}
+
+	if ((cursor->enable) && (!cursor_enabled)) {
+		cursor_enabled = 1;
+		MDP_OUTP(MDP_BASE + 0x90060, inp32(MDP_BASE + 0x90060) | 0x1);
+	} else if ((!cursor->enable) && (cursor_enabled)) {
+		cursor_enabled = 0;
+		MDP_OUTP(MDP_BASE + 0x90060,
+			 inp32(MDP_BASE + 0x90060) & (~0x1));
+	}
+
+	return 0;
+}

+ 561 - 0
drivers/staging/msm/mdp_dma.c

@@ -0,0 +1,561 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mddihost.h"
+
+static uint32 mdp_last_dma2_update_width;
+static uint32 mdp_last_dma2_update_height;
+static uint32 mdp_curr_dma2_update_width;
+static uint32 mdp_curr_dma2_update_height;
+
+ktime_t mdp_dma2_last_update_time = { 0 };
+
+int mdp_lcd_rd_cnt_offset_slow = 20;
+int mdp_lcd_rd_cnt_offset_fast = 20;
+int mdp_vsync_usec_wait_line_too_short = 5;
+uint32 mdp_dma2_update_time_in_usec;
+uint32 mdp_total_vdopkts;
+
+extern u32 msm_fb_debug_enabled;
+extern struct workqueue_struct *mdp_dma_wq;
+
+int vsync_start_y_adjust = 4;
+
+static void mdp_dma2_update_lcd(struct msm_fb_data_type *mfd)
+{
+	MDPIBUF *iBuf = &mfd->ibuf;
+	int mddi_dest = FALSE;
+	uint32 outBpp = iBuf->bpp;
+	uint32 dma2_cfg_reg;
+	uint8 *src;
+	uint32 mddi_ld_param;
+	uint16 mddi_vdo_packet_reg;
+	struct msm_fb_panel_data *pdata =
+	    (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+	uint32 ystride = mfd->fbi->fix.line_length;
+
+	dma2_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB |
+	    DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;
+
+#ifdef CONFIG_FB_MSM_MDP30
+	/*
+	 * Software workaround:  On 7x25/7x27, the MDP will not
+	 * respond if dma_w is 1 pixel.  Set the update width to
+	 * 2 pixels and adjust the x offset if needed.
+	 */
+	if (iBuf->dma_w == 1) {
+		iBuf->dma_w = 2;
+		if (iBuf->dma_x == (iBuf->ibuf_width - 2))
+			iBuf->dma_x--;
+	}
+#endif
+
+	if (mfd->fb_imgType == MDP_BGR_565)
+		dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+	else
+		dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+	if (outBpp == 4)
+		dma2_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
+
+	if (outBpp == 2)
+		dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+
+	mddi_ld_param = 0;
+	mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
+
+	if ((mfd->panel_info.type == MDDI_PANEL) ||
+	    (mfd->panel_info.type == EXT_MDDI_PANEL)) {
+		dma2_cfg_reg |= DMA_OUT_SEL_MDDI;
+		mddi_dest = TRUE;
+
+		if (mfd->panel_info.type == MDDI_PANEL) {
+			mdp_total_vdopkts++;
+			if (mfd->panel_info.pdest == DISPLAY_1) {
+				dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
+				mddi_ld_param = 0;
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+				mddi_window_adjust(mfd, iBuf->dma_x,
+						   iBuf->dma_w - 1, iBuf->dma_y,
+						   iBuf->dma_h - 1);
+#endif
+			} else {
+				dma2_cfg_reg |=
+				    DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY;
+				mddi_ld_param = 1;
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+				mddi_window_adjust(mfd, iBuf->dma_x,
+						   iBuf->dma_w - 1, iBuf->dma_y,
+						   iBuf->dma_h - 1);
+#endif
+			}
+		} else {
+			dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL;
+			mddi_ld_param = 2;
+		}
+	} else {
+		if (mfd->panel_info.pdest == DISPLAY_1) {
+			dma2_cfg_reg |= DMA_AHBM_LCD_SEL_PRIMARY;
+			outp32(MDP_EBI2_LCD0, mfd->data_port_phys);
+		} else {
+			dma2_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
+			outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
+		}
+	}
+
+	dma2_cfg_reg |= DMA_DITHER_EN;
+
+	src = (uint8 *) iBuf->buf;
+	/* starting input address */
+	src += iBuf->dma_x * outBpp + iBuf->dma_y * ystride;
+
+	mdp_curr_dma2_update_width = iBuf->dma_w;
+	mdp_curr_dma2_update_height = iBuf->dma_h;
+
+	/* MDP cmd block enable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifdef CONFIG_FB_MSM_MDP22
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0184,
+			(iBuf->dma_h << 16 | iBuf->dma_w));
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0188, src);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x018C, ystride);
+#else
+	MDP_OUTP(MDP_BASE + 0x90004, (iBuf->dma_h << 16 | iBuf->dma_w));
+	MDP_OUTP(MDP_BASE + 0x90008, src);
+	MDP_OUTP(MDP_BASE + 0x9000c, ystride);
+#endif
+
+	if (mfd->panel_info.bpp == 18) {
+		dma2_cfg_reg |= DMA_DSTC0G_6BITS |	/* 666 18BPP */
+		    DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+	} else {
+		dma2_cfg_reg |= DMA_DSTC0G_6BITS |	/* 565 16BPP */
+		    DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+	}
+
+	if (mddi_dest) {
+#ifdef CONFIG_FB_MSM_MDP22
+		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0194,
+			 (iBuf->dma_y << 16) | iBuf->dma_x);
+		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0, mddi_ld_param);
+		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4,
+			 (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
+#else
+		MDP_OUTP(MDP_BASE + 0x90010, (iBuf->dma_y << 16) | iBuf->dma_x);
+		MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
+		MDP_OUTP(MDP_BASE + 0x00094,
+			 (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
+#endif
+	} else {
+		/* setting EBI2 LCDC write window */
+		pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
+				iBuf->dma_h);
+	}
+
+	/* dma2 config register */
+#ifdef MDP_HW_VSYNC
+	MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
+
+	if ((mfd->use_mdp_vsync) &&
+	    (mfd->ibuf.vsync_enable) && (mfd->panel_info.lcd.vsync_enable)) {
+		uint32 start_y;
+
+		if (vsync_start_y_adjust <= iBuf->dma_y)
+			start_y = iBuf->dma_y - vsync_start_y_adjust;
+		else
+			start_y =
+			    (mfd->total_lcd_lines - 1) - (vsync_start_y_adjust -
+							  iBuf->dma_y);
+
+		/*
+		 * MDP VSYNC clock must be On by now so, we don't have to
+		 * re-enable it
+		 */
+		MDP_OUTP(MDP_BASE + 0x210, start_y);
+		MDP_OUTP(MDP_BASE + 0x20c, 1);	/* enable prim vsync */
+	} else {
+		MDP_OUTP(MDP_BASE + 0x20c, 0);	/* disable prim vsync */
+	}
+#else
+#ifdef CONFIG_FB_MSM_MDP22
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0180, dma2_cfg_reg);
+#else
+	MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
+#endif
+#endif /* MDP_HW_VSYNC */
+
+	/* MDP cmd block disable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}
+
+static ktime_t vt = { 0 };
+int mdp_usec_diff_threshold = 100;
+int mdp_expected_usec_wait;
+
+enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht)
+{
+	struct msm_fb_data_type *mfd = NULL;
+
+	mfd = container_of(ht, struct msm_fb_data_type, dma_hrtimer);
+
+	mdp_pipe_kickoff(MDP_DMA2_TERM, mfd);
+
+	if (msm_fb_debug_enabled) {
+		ktime_t t;
+		int usec_diff;
+		int actual_wait;
+
+		t = ktime_get_real();
+
+		actual_wait =
+		    (t.tv.sec - vt.tv.sec) * 1000000 + (t.tv.nsec -
+							vt.tv.nsec) / 1000;
+		usec_diff = actual_wait - mdp_expected_usec_wait;
+
+		if ((mdp_usec_diff_threshold < usec_diff) || (usec_diff < 0))
+			MSM_FB_DEBUG
+			    ("HRT Diff = %d usec Exp=%d usec  Act=%d usec\n",
+			     usec_diff, mdp_expected_usec_wait, actual_wait);
+	}
+
+	return HRTIMER_NORESTART;
+}
+
+static void mdp_dma_schedule(struct msm_fb_data_type *mfd, uint32 term)
+{
+	/*
+	 * dma2 configure VSYNC block
+	 * vsync supported on Primary LCD only for now
+	 */
+	int32 mdp_lcd_rd_cnt;
+	uint32 usec_wait_time;
+	uint32 start_y;
+
+	/*
+	 * ToDo: if we can move HRT timer callback to workqueue, we can
+	 * move DMA2 power on under mdp_pipe_kickoff().
+	 * This will save a power for hrt time wait.
+	 * However if the latency for context switch (hrt irq -> workqueue)
+	 * is too big, we will miss the vsync timing.
+	 */
+	if (term == MDP_DMA2_TERM)
+		mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+	mdp_dma2_update_time_in_usec =
+	    MDP_KTIME2USEC(mdp_dma2_last_update_time);
+
+	if ((!mfd->ibuf.vsync_enable) || (!mfd->panel_info.lcd.vsync_enable)
+	    || (mfd->use_mdp_vsync)) {
+		mdp_pipe_kickoff(term, mfd);
+		return;
+	}
+	/* SW vsync logic starts here */
+
+	/* get current rd counter */
+	mdp_lcd_rd_cnt = mdp_get_lcd_line_counter(mfd);
+	if (mdp_dma2_update_time_in_usec != 0) {
+		uint32 num, den;
+
+		/*
+		 * roi width boundary calculation to know the size of pixel
+		 * width that MDP can send faster or slower than LCD read
+		 * pointer
+		 */
+
+		num = mdp_last_dma2_update_width * mdp_last_dma2_update_height;
+		den =
+		    (((mfd->panel_info.lcd.refx100 * mfd->total_lcd_lines) /
+		      1000) * (mdp_dma2_update_time_in_usec / 100)) / 1000;
+
+		if (den == 0)
+			mfd->vsync_width_boundary[mdp_last_dma2_update_width] =
+			    mfd->panel_info.xres + 1;
+		else
+			mfd->vsync_width_boundary[mdp_last_dma2_update_width] =
+			    (int)(num / den);
+	}
+
+	if (mfd->vsync_width_boundary[mdp_last_dma2_update_width] >
+	    mdp_curr_dma2_update_width) {
+		/* MDP wrp is faster than LCD rdp */
+		mdp_lcd_rd_cnt += mdp_lcd_rd_cnt_offset_fast;
+	} else {
+		/* MDP wrp is slower than LCD rdp */
+		mdp_lcd_rd_cnt -= mdp_lcd_rd_cnt_offset_slow;
+	}
+
+	if (mdp_lcd_rd_cnt < 0)
+		mdp_lcd_rd_cnt = mfd->total_lcd_lines + mdp_lcd_rd_cnt;
+	else if (mdp_lcd_rd_cnt > mfd->total_lcd_lines)
+		mdp_lcd_rd_cnt = mdp_lcd_rd_cnt - mfd->total_lcd_lines - 1;
+
+	/* get wrt pointer position */
+	start_y = mfd->ibuf.dma_y;
+
+	/* measure line difference between start_y and rd counter */
+	if (start_y > mdp_lcd_rd_cnt) {
+		/*
+		 * *100 for lcd_ref_hzx100 was already multiplied by 100
+		 * *1000000 is for usec conversion
+		 */
+
+		if ((start_y - mdp_lcd_rd_cnt) <=
+		    mdp_vsync_usec_wait_line_too_short)
+			usec_wait_time = 0;
+		else
+			usec_wait_time =
+			    ((start_y -
+			      mdp_lcd_rd_cnt) * 1000000) /
+			    ((mfd->total_lcd_lines *
+			      mfd->panel_info.lcd.refx100) / 100);
+	} else {
+		if ((start_y + (mfd->total_lcd_lines - mdp_lcd_rd_cnt)) <=
+		    mdp_vsync_usec_wait_line_too_short)
+			usec_wait_time = 0;
+		else
+			usec_wait_time =
+			    ((start_y +
+			      (mfd->total_lcd_lines -
+			       mdp_lcd_rd_cnt)) * 1000000) /
+			    ((mfd->total_lcd_lines *
+			      mfd->panel_info.lcd.refx100) / 100);
+	}
+
+	mdp_last_dma2_update_width = mdp_curr_dma2_update_width;
+	mdp_last_dma2_update_height = mdp_curr_dma2_update_height;
+
+	if (usec_wait_time == 0) {
+		mdp_pipe_kickoff(term, mfd);
+	} else {
+		ktime_t wait_time;
+
+		wait_time.tv.sec = 0;
+		wait_time.tv.nsec = usec_wait_time * 1000;
+
+		if (msm_fb_debug_enabled) {
+			vt = ktime_get_real();
+			mdp_expected_usec_wait = usec_wait_time;
+		}
+		hrtimer_start(&mfd->dma_hrtimer, wait_time, HRTIMER_MODE_REL);
+	}
+}
+
+#ifdef MDDI_HOST_WINDOW_WORKAROUND
+void mdp_dma2_update(struct msm_fb_data_type *mfd)
+{
+	MDPIBUF *iBuf;
+	uint32 upper_height;
+
+	if (mfd->panel.type == EXT_MDDI_PANEL) {
+		mdp_dma2_update_sub(mfd);
+		return;
+	}
+
+	iBuf = &mfd->ibuf;
+
+	upper_height =
+	    (uint32) mddi_assign_pkt_height((uint16) iBuf->dma_w,
+					    (uint16) iBuf->dma_h, 18);
+
+	if (upper_height >= iBuf->dma_h) {
+		mdp_dma2_update_sub(mfd);
+	} else {
+		MDPIBUF lower_height;
+
+		/* sending the upper region first */
+		lower_height = iBuf->dma_h - upper_height;
+		iBuf->dma_h = upper_height;
+		mdp_dma2_update_sub(mfd);
+
+		/* sending the lower region second */
+		iBuf->dma_h = lower_height;
+		iBuf->dma_y += lower_height;
+		iBuf->vsync_enable = FALSE;
+		mdp_dma2_update_sub(mfd);
+	}
+}
+
+void mdp_dma2_update_sub(struct msm_fb_data_type *mfd)
+#else
+void mdp_dma2_update(struct msm_fb_data_type *mfd)
+#endif
+{
+	down(&mfd->dma->mutex);
+	if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
+		down(&mfd->sem);
+		mfd->ibuf_flushed = TRUE;
+		mdp_dma2_update_lcd(mfd);
+
+		mdp_enable_irq(MDP_DMA2_TERM);
+		mfd->dma->busy = TRUE;
+		INIT_COMPLETION(mfd->dma->comp);
+
+		/* schedule DMA to start */
+		mdp_dma_schedule(mfd, MDP_DMA2_TERM);
+		up(&mfd->sem);
+
+		/* wait until DMA finishes the current job */
+		wait_for_completion_killable(&mfd->dma->comp);
+		mdp_disable_irq(MDP_DMA2_TERM);
+
+	/* signal if pan function is waiting for the update completion */
+		if (mfd->pan_waiting) {
+			mfd->pan_waiting = FALSE;
+			complete(&mfd->pan_comp);
+		}
+	}
+	up(&mfd->dma->mutex);
+}
+
+void mdp_lcd_update_workqueue_handler(struct work_struct *work)
+{
+	struct msm_fb_data_type *mfd = NULL;
+
+	mfd = container_of(work, struct msm_fb_data_type, dma_update_worker);
+	if (mfd)
+		mfd->dma_fnc(mfd);
+}
+
+void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
+			  boolean sync)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	MDPIBUF *iBuf;
+	int bpp = info->var.bits_per_pixel / 8;
+
+	down(&mfd->sem);
+	iBuf = &mfd->ibuf;
+	iBuf->buf = (uint8 *) info->fix.smem_start;
+	iBuf->buf += info->var.xoffset * bpp +
+			info->var.yoffset * info->fix.line_length;
+
+	iBuf->ibuf_width = info->var.xres_virtual;
+	iBuf->bpp = bpp;
+
+	iBuf->vsync_enable = sync;
+
+	if (dirty) {
+		/*
+		 * ToDo: dirty region check inside var.xoffset+xres
+		 * <-> var.yoffset+yres
+		 */
+		iBuf->dma_x = dirty->xoffset % info->var.xres;
+		iBuf->dma_y = dirty->yoffset % info->var.yres;
+		iBuf->dma_w = dirty->width;
+		iBuf->dma_h = dirty->height;
+	} else {
+		iBuf->dma_x = 0;
+		iBuf->dma_y = 0;
+		iBuf->dma_w = info->var.xres;
+		iBuf->dma_h = info->var.yres;
+	}
+	mfd->ibuf_flushed = FALSE;
+	up(&mfd->sem);
+}
+
+void mdp_set_offset_info(struct fb_info *info, uint32 addr, uint32 sync)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	MDPIBUF *iBuf;
+
+	int bpp = info->var.bits_per_pixel / 8;
+
+	down(&mfd->sem);
+	iBuf = &mfd->ibuf;
+	iBuf->ibuf_width = info->var.xres_virtual;
+	iBuf->bpp = bpp;
+	iBuf->vsync_enable = sync;
+	iBuf->dma_x = 0;
+	iBuf->dma_y = 0;
+	iBuf->dma_w = info->var.xres;
+	iBuf->dma_h = info->var.yres;
+	iBuf->buf = (uint8 *) addr;
+
+	mfd->ibuf_flushed = FALSE;
+	up(&mfd->sem);
+}
+
+void mdp_dma_pan_update(struct fb_info *info)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	MDPIBUF *iBuf;
+
+	iBuf = &mfd->ibuf;
+
+	if (mfd->sw_currently_refreshing) {
+		/* we need to wait for the pending update */
+		mfd->pan_waiting = TRUE;
+		if (!mfd->ibuf_flushed) {
+			wait_for_completion_killable(&mfd->pan_comp);
+		}
+		/* waiting for this update to complete */
+		mfd->pan_waiting = TRUE;
+		wait_for_completion_killable(&mfd->pan_comp);
+	} else
+		mfd->dma_fnc(mfd);
+}
+
+void mdp_refresh_screen(unsigned long data)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
+
+	if ((mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) {
+		init_timer(&mfd->refresh_timer);
+		mfd->refresh_timer.function = mdp_refresh_screen;
+		mfd->refresh_timer.data = data;
+
+		if (mfd->dma->busy)
+			/* come back in 1 msec */
+			mfd->refresh_timer.expires = jiffies + (HZ / 1000);
+		else
+			mfd->refresh_timer.expires =
+			    jiffies + mfd->refresh_timer_duration;
+
+		add_timer(&mfd->refresh_timer);
+
+		if (!mfd->dma->busy) {
+			if (!queue_work(mdp_dma_wq, &mfd->dma_update_worker)) {
+				MSM_FB_DEBUG("mdp_dma: can't queue_work! -> \
+			MDP/MDDI/LCD clock speed needs to be increased\n");
+			}
+		}
+	} else {
+		if (!mfd->hw_refresh)
+			complete(&mfd->refresher_comp);
+	}
+}

+ 379 - 0
drivers/staging/msm/mdp_dma_lcdc.c

@@ -0,0 +1,379 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mdp4.h"
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define LCDC_BASE	0xC0000
+#define DTV_BASE	0xD0000
+#define DMA_E_BASE      0xB0000
+#else
+#define LCDC_BASE	0xE0000
+#endif
+
+#define DMA_P_BASE      0x90000
+
+extern spinlock_t mdp_spin_lock;
+#ifndef CONFIG_FB_MSM_MDP40
+extern uint32 mdp_intr_mask;
+#endif
+
+int first_pixel_start_x;
+int first_pixel_start_y;
+
+int mdp_lcdc_on(struct platform_device *pdev)
+{
+	int lcdc_width;
+	int lcdc_height;
+	int lcdc_bpp;
+	int lcdc_border_clr;
+	int lcdc_underflow_clr;
+	int lcdc_hsync_skew;
+
+	int hsync_period;
+	int hsync_ctrl;
+	int vsync_period;
+	int display_hctl;
+	int display_v_start;
+	int display_v_end;
+	int active_hctl;
+	int active_h_start;
+	int active_h_end;
+	int active_v_start;
+	int active_v_end;
+	int ctrl_polarity;
+	int h_back_porch;
+	int h_front_porch;
+	int v_back_porch;
+	int v_front_porch;
+	int hsync_pulse_width;
+	int vsync_pulse_width;
+	int hsync_polarity;
+	int vsync_polarity;
+	int data_en_polarity;
+	int hsync_start_x;
+	int hsync_end_x;
+	uint8 *buf;
+	int bpp;
+	uint32 dma2_cfg_reg;
+	struct fb_info *fbi;
+	struct fb_var_screeninfo *var;
+	struct msm_fb_data_type *mfd;
+	uint32 dma_base;
+	uint32 timer_base = LCDC_BASE;
+	uint32 block = MDP_DMA2_BLOCK;
+	int ret;
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	fbi = mfd->fbi;
+	var = &fbi->var;
+
+	/* MDP cmd block enable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+	bpp = fbi->var.bits_per_pixel / 8;
+	buf = (uint8 *) fbi->fix.smem_start;
+	buf += fbi->var.xoffset * bpp + fbi->var.yoffset * fbi->fix.line_length;
+
+	dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_DITHER_EN | DMA_OUT_SEL_LCDC;
+
+	if (mfd->fb_imgType == MDP_BGR_565)
+		dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
+	else
+		dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+	if (bpp == 2)
+		dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+	else if (bpp == 3)
+		dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB888;
+	else
+		dma2_cfg_reg |= DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888;
+
+	switch (mfd->panel_info.bpp) {
+	case 24:
+		dma2_cfg_reg |= DMA_DSTC0G_8BITS |
+		    DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+		break;
+
+	case 18:
+		dma2_cfg_reg |= DMA_DSTC0G_6BITS |
+		    DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+		break;
+
+	case 16:
+		dma2_cfg_reg |= DMA_DSTC0G_6BITS |
+		    DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+		break;
+
+	default:
+		printk(KERN_ERR "mdp lcdc can't support format %d bpp!\n",
+		       mfd->panel_info.bpp);
+		return -ENODEV;
+	}
+
+	/* DMA register config */
+
+	dma_base = DMA_P_BASE;
+
+#ifdef CONFIG_FB_MSM_MDP40
+	if (mfd->panel.type == HDMI_PANEL)
+		dma_base = DMA_E_BASE;
+#endif
+
+	/* starting address */
+	MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);
+	/* active window width and height */
+	MDP_OUTP(MDP_BASE + dma_base + 0x4, ((fbi->var.yres) << 16) |
+						(fbi->var.xres));
+	/* buffer ystride */
+	MDP_OUTP(MDP_BASE + dma_base + 0xc, fbi->fix.line_length);
+	/* x/y coordinate = always 0 for lcdc */
+	MDP_OUTP(MDP_BASE + dma_base + 0x10, 0);
+	/* dma config */
+	MDP_OUTP(MDP_BASE + dma_base, dma2_cfg_reg);
+
+	/*
+	 * LCDC timing setting
+	 */
+	h_back_porch = var->left_margin;
+	h_front_porch = var->right_margin;
+	v_back_porch = var->upper_margin;
+	v_front_porch = var->lower_margin;
+	hsync_pulse_width = var->hsync_len;
+	vsync_pulse_width = var->vsync_len;
+	lcdc_border_clr = mfd->panel_info.lcdc.border_clr;
+	lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr;
+	lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew;
+
+	lcdc_width = mfd->panel_info.xres;
+	lcdc_height = mfd->panel_info.yres;
+	lcdc_bpp = mfd->panel_info.bpp;
+
+	hsync_period =
+	    hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
+	hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
+	hsync_start_x = hsync_pulse_width + h_back_porch;
+	hsync_end_x = hsync_period - h_front_porch - 1;
+	display_hctl = (hsync_end_x << 16) | hsync_start_x;
+
+	vsync_period =
+	    (vsync_pulse_width + v_back_porch + lcdc_height +
+	     v_front_porch) * hsync_period;
+	display_v_start =
+	    (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew;
+	display_v_end =
+	    vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1;
+
+	if (lcdc_width != var->xres) {
+		active_h_start = hsync_start_x + first_pixel_start_x;
+		active_h_end = active_h_start + var->xres - 1;
+		active_hctl =
+		    ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start;
+	} else {
+		active_hctl = 0;
+	}
+
+	if (lcdc_height != var->yres) {
+		active_v_start =
+		    display_v_start + first_pixel_start_y * hsync_period;
+		active_v_end = active_v_start + (var->yres) * hsync_period - 1;
+		active_v_start |= ACTIVE_START_Y_EN;
+	} else {
+		active_v_start = 0;
+		active_v_end = 0;
+	}
+
+
+#ifdef CONFIG_FB_MSM_MDP40
+	if (mfd->panel.type == HDMI_PANEL) {
+		block = MDP_DMA_E_BLOCK;
+		timer_base = DTV_BASE;
+		hsync_polarity = 0;
+		vsync_polarity = 0;
+	} else {
+		hsync_polarity = 1;
+		vsync_polarity = 1;
+	}
+
+	lcdc_underflow_clr |= 0x80000000;	/* enable recovery */
+#else
+	hsync_polarity = 0;
+	vsync_polarity = 0;
+#endif
+	data_en_polarity = 0;
+
+	ctrl_polarity =
+	    (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity);
+
+	MDP_OUTP(MDP_BASE + timer_base + 0x4, hsync_ctrl);
+	MDP_OUTP(MDP_BASE + timer_base + 0x8, vsync_period);
+	MDP_OUTP(MDP_BASE + timer_base + 0xc, vsync_pulse_width * hsync_period);
+	if (timer_base == LCDC_BASE) {
+		MDP_OUTP(MDP_BASE + timer_base + 0x10, display_hctl);
+		MDP_OUTP(MDP_BASE + timer_base + 0x14, display_v_start);
+		MDP_OUTP(MDP_BASE + timer_base + 0x18, display_v_end);
+		MDP_OUTP(MDP_BASE + timer_base + 0x28, lcdc_border_clr);
+		MDP_OUTP(MDP_BASE + timer_base + 0x2c, lcdc_underflow_clr);
+		MDP_OUTP(MDP_BASE + timer_base + 0x30, lcdc_hsync_skew);
+		MDP_OUTP(MDP_BASE + timer_base + 0x38, ctrl_polarity);
+		MDP_OUTP(MDP_BASE + timer_base + 0x1c, active_hctl);
+		MDP_OUTP(MDP_BASE + timer_base + 0x20, active_v_start);
+		MDP_OUTP(MDP_BASE + timer_base + 0x24, active_v_end);
+	} else {
+		MDP_OUTP(MDP_BASE + timer_base + 0x18, display_hctl);
+		MDP_OUTP(MDP_BASE + timer_base + 0x1c, display_v_start);
+		MDP_OUTP(MDP_BASE + timer_base + 0x20, display_v_end);
+		MDP_OUTP(MDP_BASE + timer_base + 0x40, lcdc_border_clr);
+		MDP_OUTP(MDP_BASE + timer_base + 0x44, lcdc_underflow_clr);
+		MDP_OUTP(MDP_BASE + timer_base + 0x48, lcdc_hsync_skew);
+		MDP_OUTP(MDP_BASE + timer_base + 0x50, ctrl_polarity);
+		MDP_OUTP(MDP_BASE + timer_base + 0x2c, active_hctl);
+		MDP_OUTP(MDP_BASE + timer_base + 0x30, active_v_start);
+		MDP_OUTP(MDP_BASE + timer_base + 0x38, active_v_end);
+	}
+
+	ret = panel_next_on(pdev);
+	if (ret == 0) {
+		/* enable LCDC block */
+		MDP_OUTP(MDP_BASE + timer_base, 1);
+		mdp_pipe_ctrl(block, MDP_BLOCK_POWER_ON, FALSE);
+	}
+	/* MDP cmd block disable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+	return ret;
+}
+
+int mdp_lcdc_off(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct msm_fb_data_type *mfd;
+	uint32 timer_base = LCDC_BASE;
+	uint32 block = MDP_DMA2_BLOCK;
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+#ifdef CONFIG_FB_MSM_MDP40
+	if (mfd->panel.type == HDMI_PANEL) {
+		block = MDP_DMA_E_BLOCK;
+		timer_base = DTV_BASE;
+	}
+#endif
+
+	/* MDP cmd block enable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	MDP_OUTP(MDP_BASE + timer_base, 0);
+	/* MDP cmd block disable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	mdp_pipe_ctrl(block, MDP_BLOCK_POWER_OFF, FALSE);
+
+	ret = panel_next_off(pdev);
+
+	/* delay to make sure the last frame finishes */
+	mdelay(100);
+
+	return ret;
+}
+
+void mdp_lcdc_update(struct msm_fb_data_type *mfd)
+{
+	struct fb_info *fbi = mfd->fbi;
+	uint8 *buf;
+	int bpp;
+	unsigned long flag;
+	uint32 dma_base;
+	int irq_block = MDP_DMA2_TERM;
+#ifdef CONFIG_FB_MSM_MDP40
+	int intr = INTR_DMA_P_DONE;
+#endif
+
+	if (!mfd->panel_power_on)
+		return;
+
+	/* no need to power on cmd block since it's lcdc mode */
+
+	if (!mfd->ibuf.visible_swapped) {
+		bpp = fbi->var.bits_per_pixel / 8;
+		buf = (uint8 *) fbi->fix.smem_start;
+		buf += fbi->var.xoffset * bpp +
+		fbi->var.yoffset * fbi->fix.line_length;
+	} else {
+		/* we've done something to update the pointer. */
+		bpp =  mfd->ibuf.bpp;
+		buf = mfd->ibuf.buf;
+	}
+
+	dma_base = DMA_P_BASE;
+
+#ifdef CONFIG_FB_MSM_MDP40
+	if (mfd->panel.type == HDMI_PANEL) {
+		intr = INTR_DMA_E_DONE;
+		irq_block = MDP_DMA_E_TERM;
+		dma_base = DMA_E_BASE;
+	}
+#endif
+
+	/* starting address */
+	MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf);
+
+	/* enable LCDC irq */
+	spin_lock_irqsave(&mdp_spin_lock, flag);
+	mdp_enable_irq(irq_block);
+	INIT_COMPLETION(mfd->dma->comp);
+	mfd->dma->waiting = TRUE;
+#ifdef CONFIG_FB_MSM_MDP40
+	outp32(MDP_INTR_CLEAR, intr);
+	mdp_intr_mask |= intr;
+	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+#else
+	outp32(MDP_INTR_CLEAR, LCDC_FRAME_START);
+	mdp_intr_mask |= LCDC_FRAME_START;
+	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+#endif
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+	if (mfd->ibuf.vsync_enable)
+		wait_for_completion_killable(&mfd->dma->comp);
+	mdp_disable_irq(irq_block);
+}

+ 139 - 0
drivers/staging/msm/mdp_dma_s.c

@@ -0,0 +1,139 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+static void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd)
+{
+	MDPIBUF *iBuf = &mfd->ibuf;
+	int mddi_dest = FALSE;
+	uint32 outBpp = iBuf->bpp;
+	uint32 dma_s_cfg_reg;
+	uint8 *src;
+	struct msm_fb_panel_data *pdata =
+	    (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+	dma_s_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB |
+	    DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;
+
+	if (mfd->fb_imgType == MDP_BGR_565)
+		dma_s_cfg_reg |= DMA_PACK_PATTERN_BGR;
+	else
+		dma_s_cfg_reg |= DMA_PACK_PATTERN_RGB;
+
+	if (outBpp == 4)
+		dma_s_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
+
+	if (outBpp == 2)
+		dma_s_cfg_reg |= DMA_IBUF_FORMAT_RGB565;
+
+	if (mfd->panel_info.pdest != DISPLAY_2) {
+		printk(KERN_ERR "error: non-secondary type through dma_s!\n");
+		return;
+	}
+
+	if (mfd->panel_info.type == MDDI_PANEL) {
+		dma_s_cfg_reg |= DMA_OUT_SEL_MDDI;
+		mddi_dest = TRUE;
+	} else {
+		dma_s_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
+		outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
+	}
+
+	dma_s_cfg_reg |= DMA_DITHER_EN;
+
+	src = (uint8 *) iBuf->buf;
+	/* starting input address */
+	src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * outBpp;
+
+	/* MDP cmd block enable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	/* PIXELSIZE */
+	MDP_OUTP(MDP_BASE + 0xa0004, (iBuf->dma_h << 16 | iBuf->dma_w));
+	MDP_OUTP(MDP_BASE + 0xa0008, src);	/* ibuf address */
+	MDP_OUTP(MDP_BASE + 0xa000c, iBuf->ibuf_width * outBpp);/* ystride */
+
+	if (mfd->panel_info.bpp == 18) {
+		dma_s_cfg_reg |= DMA_DSTC0G_6BITS |	/* 666 18BPP */
+		    DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
+	} else {
+		dma_s_cfg_reg |= DMA_DSTC0G_6BITS |	/* 565 16BPP */
+		    DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
+	}
+
+	if (mddi_dest) {
+		MDP_OUTP(MDP_BASE + 0xa0010, (iBuf->dma_y << 16) | iBuf->dma_x);
+		MDP_OUTP(MDP_BASE + 0x00090, 1);
+		MDP_OUTP(MDP_BASE + 0x00094,
+				(MDDI_VDO_PACKET_DESC << 16) |
+				mfd->panel_info.mddi.vdopkt);
+	} else {
+		/* setting LCDC write window */
+		pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
+				iBuf->dma_h);
+	}
+
+	MDP_OUTP(MDP_BASE + 0xa0000, dma_s_cfg_reg);
+
+	/* MDP cmd block disable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd);
+}
+
+void mdp_dma_s_update(struct msm_fb_data_type *mfd)
+{
+	down(&mfd->dma->mutex);
+	if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
+		down(&mfd->sem);
+		mdp_enable_irq(MDP_DMA_S_TERM);
+		mfd->dma->busy = TRUE;
+		INIT_COMPLETION(mfd->dma->comp);
+		mfd->ibuf_flushed = TRUE;
+		mdp_dma_s_update_lcd(mfd);
+		up(&mfd->sem);
+
+		/* wait until DMA finishes the current job */
+		wait_for_completion_killable(&mfd->dma->comp);
+		mdp_disable_irq(MDP_DMA_S_TERM);
+
+	/* signal if pan function is waiting for the update completion */
+		if (mfd->pan_waiting) {
+			mfd->pan_waiting = FALSE;
+			complete(&mfd->pan_comp);
+		}
+	}
+	up(&mfd->dma->mutex);
+}

+ 142 - 0
drivers/staging/msm/mdp_dma_tv.c

@@ -0,0 +1,142 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+
+#include <linux/fb.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+extern spinlock_t mdp_spin_lock;
+extern uint32 mdp_intr_mask;
+
+int mdp_dma3_on(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+	struct fb_info *fbi;
+	uint8 *buf;
+	int bpp;
+	int ret = 0;
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	fbi = mfd->fbi;
+	/* MDP cmd block enable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+	bpp = fbi->var.bits_per_pixel / 8;
+	buf = (uint8 *) fbi->fix.smem_start;
+	buf += fbi->var.xoffset * bpp +
+		fbi->var.yoffset * fbi->fix.line_length;
+
+	/* starting address[31..8] of Video frame buffer is CS0 */
+	MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
+
+	mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+	MDP_OUTP(MDP_BASE + 0xC0004, 0x4c60674); /* flicker filter enabled */
+	MDP_OUTP(MDP_BASE + 0xC0010, 0x20);	/* sobel treshold */
+
+	MDP_OUTP(MDP_BASE + 0xC0018, 0xeb0010);	/* Y  Max, Y  min */
+	MDP_OUTP(MDP_BASE + 0xC001C, 0xf00010);	/* Cb Max, Cb min */
+	MDP_OUTP(MDP_BASE + 0xC0020, 0xf00010);	/* Cb Max, Cb min */
+
+	MDP_OUTP(MDP_BASE + 0xC000C, 0x67686970); /* add a few chars for CC */
+	MDP_OUTP(MDP_BASE + 0xC0000, 0x1);	/* MDP tv out enable */
+
+	/* MDP cmd block disable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+	ret = panel_next_on(pdev);
+
+	return ret;
+}
+
+int mdp_dma3_off(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	ret = panel_next_off(pdev);
+	if (ret)
+		return ret;
+
+	/* MDP cmd block enable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	MDP_OUTP(MDP_BASE + 0xC0000, 0x0);
+	/* MDP cmd block disable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+	mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+	/* delay to make sure the last frame finishes */
+	mdelay(100);
+
+	return ret;
+}
+
+void mdp_dma3_update(struct msm_fb_data_type *mfd)
+{
+	struct fb_info *fbi = mfd->fbi;
+	uint8 *buf;
+	int bpp;
+	unsigned long flag;
+
+	if (!mfd->panel_power_on)
+		return;
+
+	/* no need to power on cmd block since dma3 is running */
+	bpp = fbi->var.bits_per_pixel / 8;
+	buf = (uint8 *) fbi->fix.smem_start;
+	buf += fbi->var.xoffset * bpp +
+		fbi->var.yoffset * fbi->fix.line_length;
+	MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
+
+	spin_lock_irqsave(&mdp_spin_lock, flag);
+	mdp_enable_irq(MDP_DMA3_TERM);
+	INIT_COMPLETION(mfd->dma->comp);
+	mfd->dma->waiting = TRUE;
+
+	outp32(MDP_INTR_CLEAR, TV_OUT_DMA3_START);
+	mdp_intr_mask |= TV_OUT_DMA3_START;
+	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+	wait_for_completion_killable(&mfd->dma->comp);
+	mdp_disable_irq(MDP_DMA3_TERM);
+}

+ 720 - 0
drivers/staging/msm/mdp_hw_init.c

@@ -0,0 +1,720 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "mdp.h"
+
+/* mdp primary csc limit vector */
+uint32 mdp_plv[] = { 0x10, 0xeb, 0x10, 0xf0 };
+
+/* Color Coefficient matrix for YUV -> RGB */
+struct mdp_ccs mdp_ccs_yuv2rgb = {
+	MDP_CCS_YUV2RGB,
+	{
+		0x254,
+		0x000,
+		0x331,
+		0x254,
+		0xff38,
+		0xfe61,
+		0x254,
+		0x409,
+		0x000,
+	},
+	{
+#ifdef CONFIG_FB_MSM_MDP31
+		0x1f0,
+		0x180,
+		0x180
+#else
+		0x10,
+		0x80,
+		0x80
+#endif
+	}
+};
+
+/* Color Coefficient matrix for RGB -> YUV */
+struct mdp_ccs mdp_ccs_rgb2yuv = {
+	MDP_CCS_RGB2YUV,
+	{
+		0x83,
+		0x102,
+		0x32,
+		0xffb5,
+		0xff6c,
+		0xe1,
+		0xe1,
+		0xff45,
+		0xffdc,
+	},
+#ifdef CONFIG_FB_MSM_MDP31
+	{
+		0x10,
+		0x80,
+		0x80
+	}
+#endif
+};
+
+static void mdp_load_lut_param(void)
+{
+	outpdw(MDP_BASE + 0x40800, 0x0);
+	outpdw(MDP_BASE + 0x40804, 0x151515);
+	outpdw(MDP_BASE + 0x40808, 0x1d1d1d);
+	outpdw(MDP_BASE + 0x4080c, 0x232323);
+	outpdw(MDP_BASE + 0x40810, 0x272727);
+	outpdw(MDP_BASE + 0x40814, 0x2b2b2b);
+	outpdw(MDP_BASE + 0x40818, 0x2f2f2f);
+	outpdw(MDP_BASE + 0x4081c, 0x333333);
+	outpdw(MDP_BASE + 0x40820, 0x363636);
+	outpdw(MDP_BASE + 0x40824, 0x393939);
+	outpdw(MDP_BASE + 0x40828, 0x3b3b3b);
+	outpdw(MDP_BASE + 0x4082c, 0x3e3e3e);
+	outpdw(MDP_BASE + 0x40830, 0x404040);
+	outpdw(MDP_BASE + 0x40834, 0x434343);
+	outpdw(MDP_BASE + 0x40838, 0x454545);
+	outpdw(MDP_BASE + 0x4083c, 0x474747);
+	outpdw(MDP_BASE + 0x40840, 0x494949);
+	outpdw(MDP_BASE + 0x40844, 0x4b4b4b);
+	outpdw(MDP_BASE + 0x40848, 0x4d4d4d);
+	outpdw(MDP_BASE + 0x4084c, 0x4f4f4f);
+	outpdw(MDP_BASE + 0x40850, 0x515151);
+	outpdw(MDP_BASE + 0x40854, 0x535353);
+	outpdw(MDP_BASE + 0x40858, 0x555555);
+	outpdw(MDP_BASE + 0x4085c, 0x565656);
+	outpdw(MDP_BASE + 0x40860, 0x585858);
+	outpdw(MDP_BASE + 0x40864, 0x5a5a5a);
+	outpdw(MDP_BASE + 0x40868, 0x5b5b5b);
+	outpdw(MDP_BASE + 0x4086c, 0x5d5d5d);
+	outpdw(MDP_BASE + 0x40870, 0x5e5e5e);
+	outpdw(MDP_BASE + 0x40874, 0x606060);
+	outpdw(MDP_BASE + 0x40878, 0x616161);
+	outpdw(MDP_BASE + 0x4087c, 0x636363);
+	outpdw(MDP_BASE + 0x40880, 0x646464);
+	outpdw(MDP_BASE + 0x40884, 0x666666);
+	outpdw(MDP_BASE + 0x40888, 0x676767);
+	outpdw(MDP_BASE + 0x4088c, 0x686868);
+	outpdw(MDP_BASE + 0x40890, 0x6a6a6a);
+	outpdw(MDP_BASE + 0x40894, 0x6b6b6b);
+	outpdw(MDP_BASE + 0x40898, 0x6c6c6c);
+	outpdw(MDP_BASE + 0x4089c, 0x6e6e6e);
+	outpdw(MDP_BASE + 0x408a0, 0x6f6f6f);
+	outpdw(MDP_BASE + 0x408a4, 0x707070);
+	outpdw(MDP_BASE + 0x408a8, 0x717171);
+	outpdw(MDP_BASE + 0x408ac, 0x727272);
+	outpdw(MDP_BASE + 0x408b0, 0x747474);
+	outpdw(MDP_BASE + 0x408b4, 0x757575);
+	outpdw(MDP_BASE + 0x408b8, 0x767676);
+	outpdw(MDP_BASE + 0x408bc, 0x777777);
+	outpdw(MDP_BASE + 0x408c0, 0x787878);
+	outpdw(MDP_BASE + 0x408c4, 0x797979);
+	outpdw(MDP_BASE + 0x408c8, 0x7a7a7a);
+	outpdw(MDP_BASE + 0x408cc, 0x7c7c7c);
+	outpdw(MDP_BASE + 0x408d0, 0x7d7d7d);
+	outpdw(MDP_BASE + 0x408d4, 0x7e7e7e);
+	outpdw(MDP_BASE + 0x408d8, 0x7f7f7f);
+	outpdw(MDP_BASE + 0x408dc, 0x808080);
+	outpdw(MDP_BASE + 0x408e0, 0x818181);
+	outpdw(MDP_BASE + 0x408e4, 0x828282);
+	outpdw(MDP_BASE + 0x408e8, 0x838383);
+	outpdw(MDP_BASE + 0x408ec, 0x848484);
+	outpdw(MDP_BASE + 0x408f0, 0x858585);
+	outpdw(MDP_BASE + 0x408f4, 0x868686);
+	outpdw(MDP_BASE + 0x408f8, 0x878787);
+	outpdw(MDP_BASE + 0x408fc, 0x888888);
+	outpdw(MDP_BASE + 0x40900, 0x898989);
+	outpdw(MDP_BASE + 0x40904, 0x8a8a8a);
+	outpdw(MDP_BASE + 0x40908, 0x8b8b8b);
+	outpdw(MDP_BASE + 0x4090c, 0x8c8c8c);
+	outpdw(MDP_BASE + 0x40910, 0x8d8d8d);
+	outpdw(MDP_BASE + 0x40914, 0x8e8e8e);
+	outpdw(MDP_BASE + 0x40918, 0x8f8f8f);
+	outpdw(MDP_BASE + 0x4091c, 0x8f8f8f);
+	outpdw(MDP_BASE + 0x40920, 0x909090);
+	outpdw(MDP_BASE + 0x40924, 0x919191);
+	outpdw(MDP_BASE + 0x40928, 0x929292);
+	outpdw(MDP_BASE + 0x4092c, 0x939393);
+	outpdw(MDP_BASE + 0x40930, 0x949494);
+	outpdw(MDP_BASE + 0x40934, 0x959595);
+	outpdw(MDP_BASE + 0x40938, 0x969696);
+	outpdw(MDP_BASE + 0x4093c, 0x969696);
+	outpdw(MDP_BASE + 0x40940, 0x979797);
+	outpdw(MDP_BASE + 0x40944, 0x989898);
+	outpdw(MDP_BASE + 0x40948, 0x999999);
+	outpdw(MDP_BASE + 0x4094c, 0x9a9a9a);
+	outpdw(MDP_BASE + 0x40950, 0x9b9b9b);
+	outpdw(MDP_BASE + 0x40954, 0x9c9c9c);
+	outpdw(MDP_BASE + 0x40958, 0x9c9c9c);
+	outpdw(MDP_BASE + 0x4095c, 0x9d9d9d);
+	outpdw(MDP_BASE + 0x40960, 0x9e9e9e);
+	outpdw(MDP_BASE + 0x40964, 0x9f9f9f);
+	outpdw(MDP_BASE + 0x40968, 0xa0a0a0);
+	outpdw(MDP_BASE + 0x4096c, 0xa0a0a0);
+	outpdw(MDP_BASE + 0x40970, 0xa1a1a1);
+	outpdw(MDP_BASE + 0x40974, 0xa2a2a2);
+	outpdw(MDP_BASE + 0x40978, 0xa3a3a3);
+	outpdw(MDP_BASE + 0x4097c, 0xa4a4a4);
+	outpdw(MDP_BASE + 0x40980, 0xa4a4a4);
+	outpdw(MDP_BASE + 0x40984, 0xa5a5a5);
+	outpdw(MDP_BASE + 0x40988, 0xa6a6a6);
+	outpdw(MDP_BASE + 0x4098c, 0xa7a7a7);
+	outpdw(MDP_BASE + 0x40990, 0xa7a7a7);
+	outpdw(MDP_BASE + 0x40994, 0xa8a8a8);
+	outpdw(MDP_BASE + 0x40998, 0xa9a9a9);
+	outpdw(MDP_BASE + 0x4099c, 0xaaaaaa);
+	outpdw(MDP_BASE + 0x409a0, 0xaaaaaa);
+	outpdw(MDP_BASE + 0x409a4, 0xababab);
+	outpdw(MDP_BASE + 0x409a8, 0xacacac);
+	outpdw(MDP_BASE + 0x409ac, 0xadadad);
+	outpdw(MDP_BASE + 0x409b0, 0xadadad);
+	outpdw(MDP_BASE + 0x409b4, 0xaeaeae);
+	outpdw(MDP_BASE + 0x409b8, 0xafafaf);
+	outpdw(MDP_BASE + 0x409bc, 0xafafaf);
+	outpdw(MDP_BASE + 0x409c0, 0xb0b0b0);
+	outpdw(MDP_BASE + 0x409c4, 0xb1b1b1);
+	outpdw(MDP_BASE + 0x409c8, 0xb2b2b2);
+	outpdw(MDP_BASE + 0x409cc, 0xb2b2b2);
+	outpdw(MDP_BASE + 0x409d0, 0xb3b3b3);
+	outpdw(MDP_BASE + 0x409d4, 0xb4b4b4);
+	outpdw(MDP_BASE + 0x409d8, 0xb4b4b4);
+	outpdw(MDP_BASE + 0x409dc, 0xb5b5b5);
+	outpdw(MDP_BASE + 0x409e0, 0xb6b6b6);
+	outpdw(MDP_BASE + 0x409e4, 0xb6b6b6);
+	outpdw(MDP_BASE + 0x409e8, 0xb7b7b7);
+	outpdw(MDP_BASE + 0x409ec, 0xb8b8b8);
+	outpdw(MDP_BASE + 0x409f0, 0xb8b8b8);
+	outpdw(MDP_BASE + 0x409f4, 0xb9b9b9);
+	outpdw(MDP_BASE + 0x409f8, 0xbababa);
+	outpdw(MDP_BASE + 0x409fc, 0xbababa);
+	outpdw(MDP_BASE + 0x40a00, 0xbbbbbb);
+	outpdw(MDP_BASE + 0x40a04, 0xbcbcbc);
+	outpdw(MDP_BASE + 0x40a08, 0xbcbcbc);
+	outpdw(MDP_BASE + 0x40a0c, 0xbdbdbd);
+	outpdw(MDP_BASE + 0x40a10, 0xbebebe);
+	outpdw(MDP_BASE + 0x40a14, 0xbebebe);
+	outpdw(MDP_BASE + 0x40a18, 0xbfbfbf);
+	outpdw(MDP_BASE + 0x40a1c, 0xc0c0c0);
+	outpdw(MDP_BASE + 0x40a20, 0xc0c0c0);
+	outpdw(MDP_BASE + 0x40a24, 0xc1c1c1);
+	outpdw(MDP_BASE + 0x40a28, 0xc1c1c1);
+	outpdw(MDP_BASE + 0x40a2c, 0xc2c2c2);
+	outpdw(MDP_BASE + 0x40a30, 0xc3c3c3);
+	outpdw(MDP_BASE + 0x40a34, 0xc3c3c3);
+	outpdw(MDP_BASE + 0x40a38, 0xc4c4c4);
+	outpdw(MDP_BASE + 0x40a3c, 0xc5c5c5);
+	outpdw(MDP_BASE + 0x40a40, 0xc5c5c5);
+	outpdw(MDP_BASE + 0x40a44, 0xc6c6c6);
+	outpdw(MDP_BASE + 0x40a48, 0xc6c6c6);
+	outpdw(MDP_BASE + 0x40a4c, 0xc7c7c7);
+	outpdw(MDP_BASE + 0x40a50, 0xc8c8c8);
+	outpdw(MDP_BASE + 0x40a54, 0xc8c8c8);
+	outpdw(MDP_BASE + 0x40a58, 0xc9c9c9);
+	outpdw(MDP_BASE + 0x40a5c, 0xc9c9c9);
+	outpdw(MDP_BASE + 0x40a60, 0xcacaca);
+	outpdw(MDP_BASE + 0x40a64, 0xcbcbcb);
+	outpdw(MDP_BASE + 0x40a68, 0xcbcbcb);
+	outpdw(MDP_BASE + 0x40a6c, 0xcccccc);
+	outpdw(MDP_BASE + 0x40a70, 0xcccccc);
+	outpdw(MDP_BASE + 0x40a74, 0xcdcdcd);
+	outpdw(MDP_BASE + 0x40a78, 0xcecece);
+	outpdw(MDP_BASE + 0x40a7c, 0xcecece);
+	outpdw(MDP_BASE + 0x40a80, 0xcfcfcf);
+	outpdw(MDP_BASE + 0x40a84, 0xcfcfcf);
+	outpdw(MDP_BASE + 0x40a88, 0xd0d0d0);
+	outpdw(MDP_BASE + 0x40a8c, 0xd0d0d0);
+	outpdw(MDP_BASE + 0x40a90, 0xd1d1d1);
+	outpdw(MDP_BASE + 0x40a94, 0xd2d2d2);
+	outpdw(MDP_BASE + 0x40a98, 0xd2d2d2);
+	outpdw(MDP_BASE + 0x40a9c, 0xd3d3d3);
+	outpdw(MDP_BASE + 0x40aa0, 0xd3d3d3);
+	outpdw(MDP_BASE + 0x40aa4, 0xd4d4d4);
+	outpdw(MDP_BASE + 0x40aa8, 0xd4d4d4);
+	outpdw(MDP_BASE + 0x40aac, 0xd5d5d5);
+	outpdw(MDP_BASE + 0x40ab0, 0xd6d6d6);
+	outpdw(MDP_BASE + 0x40ab4, 0xd6d6d6);
+	outpdw(MDP_BASE + 0x40ab8, 0xd7d7d7);
+	outpdw(MDP_BASE + 0x40abc, 0xd7d7d7);
+	outpdw(MDP_BASE + 0x40ac0, 0xd8d8d8);
+	outpdw(MDP_BASE + 0x40ac4, 0xd8d8d8);
+	outpdw(MDP_BASE + 0x40ac8, 0xd9d9d9);
+	outpdw(MDP_BASE + 0x40acc, 0xd9d9d9);
+	outpdw(MDP_BASE + 0x40ad0, 0xdadada);
+	outpdw(MDP_BASE + 0x40ad4, 0xdbdbdb);
+	outpdw(MDP_BASE + 0x40ad8, 0xdbdbdb);
+	outpdw(MDP_BASE + 0x40adc, 0xdcdcdc);
+	outpdw(MDP_BASE + 0x40ae0, 0xdcdcdc);
+	outpdw(MDP_BASE + 0x40ae4, 0xdddddd);
+	outpdw(MDP_BASE + 0x40ae8, 0xdddddd);
+	outpdw(MDP_BASE + 0x40aec, 0xdedede);
+	outpdw(MDP_BASE + 0x40af0, 0xdedede);
+	outpdw(MDP_BASE + 0x40af4, 0xdfdfdf);
+	outpdw(MDP_BASE + 0x40af8, 0xdfdfdf);
+	outpdw(MDP_BASE + 0x40afc, 0xe0e0e0);
+	outpdw(MDP_BASE + 0x40b00, 0xe0e0e0);
+	outpdw(MDP_BASE + 0x40b04, 0xe1e1e1);
+	outpdw(MDP_BASE + 0x40b08, 0xe1e1e1);
+	outpdw(MDP_BASE + 0x40b0c, 0xe2e2e2);
+	outpdw(MDP_BASE + 0x40b10, 0xe3e3e3);
+	outpdw(MDP_BASE + 0x40b14, 0xe3e3e3);
+	outpdw(MDP_BASE + 0x40b18, 0xe4e4e4);
+	outpdw(MDP_BASE + 0x40b1c, 0xe4e4e4);
+	outpdw(MDP_BASE + 0x40b20, 0xe5e5e5);
+	outpdw(MDP_BASE + 0x40b24, 0xe5e5e5);
+	outpdw(MDP_BASE + 0x40b28, 0xe6e6e6);
+	outpdw(MDP_BASE + 0x40b2c, 0xe6e6e6);
+	outpdw(MDP_BASE + 0x40b30, 0xe7e7e7);
+	outpdw(MDP_BASE + 0x40b34, 0xe7e7e7);
+	outpdw(MDP_BASE + 0x40b38, 0xe8e8e8);
+	outpdw(MDP_BASE + 0x40b3c, 0xe8e8e8);
+	outpdw(MDP_BASE + 0x40b40, 0xe9e9e9);
+	outpdw(MDP_BASE + 0x40b44, 0xe9e9e9);
+	outpdw(MDP_BASE + 0x40b48, 0xeaeaea);
+	outpdw(MDP_BASE + 0x40b4c, 0xeaeaea);
+	outpdw(MDP_BASE + 0x40b50, 0xebebeb);
+	outpdw(MDP_BASE + 0x40b54, 0xebebeb);
+	outpdw(MDP_BASE + 0x40b58, 0xececec);
+	outpdw(MDP_BASE + 0x40b5c, 0xececec);
+	outpdw(MDP_BASE + 0x40b60, 0xededed);
+	outpdw(MDP_BASE + 0x40b64, 0xededed);
+	outpdw(MDP_BASE + 0x40b68, 0xeeeeee);
+	outpdw(MDP_BASE + 0x40b6c, 0xeeeeee);
+	outpdw(MDP_BASE + 0x40b70, 0xefefef);
+	outpdw(MDP_BASE + 0x40b74, 0xefefef);
+	outpdw(MDP_BASE + 0x40b78, 0xf0f0f0);
+	outpdw(MDP_BASE + 0x40b7c, 0xf0f0f0);
+	outpdw(MDP_BASE + 0x40b80, 0xf1f1f1);
+	outpdw(MDP_BASE + 0x40b84, 0xf1f1f1);
+	outpdw(MDP_BASE + 0x40b88, 0xf2f2f2);
+	outpdw(MDP_BASE + 0x40b8c, 0xf2f2f2);
+	outpdw(MDP_BASE + 0x40b90, 0xf2f2f2);
+	outpdw(MDP_BASE + 0x40b94, 0xf3f3f3);
+	outpdw(MDP_BASE + 0x40b98, 0xf3f3f3);
+	outpdw(MDP_BASE + 0x40b9c, 0xf4f4f4);
+	outpdw(MDP_BASE + 0x40ba0, 0xf4f4f4);
+	outpdw(MDP_BASE + 0x40ba4, 0xf5f5f5);
+	outpdw(MDP_BASE + 0x40ba8, 0xf5f5f5);
+	outpdw(MDP_BASE + 0x40bac, 0xf6f6f6);
+	outpdw(MDP_BASE + 0x40bb0, 0xf6f6f6);
+	outpdw(MDP_BASE + 0x40bb4, 0xf7f7f7);
+	outpdw(MDP_BASE + 0x40bb8, 0xf7f7f7);
+	outpdw(MDP_BASE + 0x40bbc, 0xf8f8f8);
+	outpdw(MDP_BASE + 0x40bc0, 0xf8f8f8);
+	outpdw(MDP_BASE + 0x40bc4, 0xf9f9f9);
+	outpdw(MDP_BASE + 0x40bc8, 0xf9f9f9);
+	outpdw(MDP_BASE + 0x40bcc, 0xfafafa);
+	outpdw(MDP_BASE + 0x40bd0, 0xfafafa);
+	outpdw(MDP_BASE + 0x40bd4, 0xfafafa);
+	outpdw(MDP_BASE + 0x40bd8, 0xfbfbfb);
+	outpdw(MDP_BASE + 0x40bdc, 0xfbfbfb);
+	outpdw(MDP_BASE + 0x40be0, 0xfcfcfc);
+	outpdw(MDP_BASE + 0x40be4, 0xfcfcfc);
+	outpdw(MDP_BASE + 0x40be8, 0xfdfdfd);
+	outpdw(MDP_BASE + 0x40bec, 0xfdfdfd);
+	outpdw(MDP_BASE + 0x40bf0, 0xfefefe);
+	outpdw(MDP_BASE + 0x40bf4, 0xfefefe);
+	outpdw(MDP_BASE + 0x40bf8, 0xffffff);
+	outpdw(MDP_BASE + 0x40bfc, 0xffffff);
+	outpdw(MDP_BASE + 0x40c00, 0x0);
+	outpdw(MDP_BASE + 0x40c04, 0x0);
+	outpdw(MDP_BASE + 0x40c08, 0x0);
+	outpdw(MDP_BASE + 0x40c0c, 0x0);
+	outpdw(MDP_BASE + 0x40c10, 0x0);
+	outpdw(MDP_BASE + 0x40c14, 0x0);
+	outpdw(MDP_BASE + 0x40c18, 0x0);
+	outpdw(MDP_BASE + 0x40c1c, 0x0);
+	outpdw(MDP_BASE + 0x40c20, 0x0);
+	outpdw(MDP_BASE + 0x40c24, 0x0);
+	outpdw(MDP_BASE + 0x40c28, 0x0);
+	outpdw(MDP_BASE + 0x40c2c, 0x0);
+	outpdw(MDP_BASE + 0x40c30, 0x0);
+	outpdw(MDP_BASE + 0x40c34, 0x0);
+	outpdw(MDP_BASE + 0x40c38, 0x0);
+	outpdw(MDP_BASE + 0x40c3c, 0x0);
+	outpdw(MDP_BASE + 0x40c40, 0x10101);
+	outpdw(MDP_BASE + 0x40c44, 0x10101);
+	outpdw(MDP_BASE + 0x40c48, 0x10101);
+	outpdw(MDP_BASE + 0x40c4c, 0x10101);
+	outpdw(MDP_BASE + 0x40c50, 0x10101);
+	outpdw(MDP_BASE + 0x40c54, 0x10101);
+	outpdw(MDP_BASE + 0x40c58, 0x10101);
+	outpdw(MDP_BASE + 0x40c5c, 0x10101);
+	outpdw(MDP_BASE + 0x40c60, 0x10101);
+	outpdw(MDP_BASE + 0x40c64, 0x10101);
+	outpdw(MDP_BASE + 0x40c68, 0x20202);
+	outpdw(MDP_BASE + 0x40c6c, 0x20202);
+	outpdw(MDP_BASE + 0x40c70, 0x20202);
+	outpdw(MDP_BASE + 0x40c74, 0x20202);
+	outpdw(MDP_BASE + 0x40c78, 0x20202);
+	outpdw(MDP_BASE + 0x40c7c, 0x20202);
+	outpdw(MDP_BASE + 0x40c80, 0x30303);
+	outpdw(MDP_BASE + 0x40c84, 0x30303);
+	outpdw(MDP_BASE + 0x40c88, 0x30303);
+	outpdw(MDP_BASE + 0x40c8c, 0x30303);
+	outpdw(MDP_BASE + 0x40c90, 0x30303);
+	outpdw(MDP_BASE + 0x40c94, 0x40404);
+	outpdw(MDP_BASE + 0x40c98, 0x40404);
+	outpdw(MDP_BASE + 0x40c9c, 0x40404);
+	outpdw(MDP_BASE + 0x40ca0, 0x40404);
+	outpdw(MDP_BASE + 0x40ca4, 0x40404);
+	outpdw(MDP_BASE + 0x40ca8, 0x50505);
+	outpdw(MDP_BASE + 0x40cac, 0x50505);
+	outpdw(MDP_BASE + 0x40cb0, 0x50505);
+	outpdw(MDP_BASE + 0x40cb4, 0x50505);
+	outpdw(MDP_BASE + 0x40cb8, 0x60606);
+	outpdw(MDP_BASE + 0x40cbc, 0x60606);
+	outpdw(MDP_BASE + 0x40cc0, 0x60606);
+	outpdw(MDP_BASE + 0x40cc4, 0x70707);
+	outpdw(MDP_BASE + 0x40cc8, 0x70707);
+	outpdw(MDP_BASE + 0x40ccc, 0x70707);
+	outpdw(MDP_BASE + 0x40cd0, 0x70707);
+	outpdw(MDP_BASE + 0x40cd4, 0x80808);
+	outpdw(MDP_BASE + 0x40cd8, 0x80808);
+	outpdw(MDP_BASE + 0x40cdc, 0x80808);
+	outpdw(MDP_BASE + 0x40ce0, 0x90909);
+	outpdw(MDP_BASE + 0x40ce4, 0x90909);
+	outpdw(MDP_BASE + 0x40ce8, 0xa0a0a);
+	outpdw(MDP_BASE + 0x40cec, 0xa0a0a);
+	outpdw(MDP_BASE + 0x40cf0, 0xa0a0a);
+	outpdw(MDP_BASE + 0x40cf4, 0xb0b0b);
+	outpdw(MDP_BASE + 0x40cf8, 0xb0b0b);
+	outpdw(MDP_BASE + 0x40cfc, 0xb0b0b);
+	outpdw(MDP_BASE + 0x40d00, 0xc0c0c);
+	outpdw(MDP_BASE + 0x40d04, 0xc0c0c);
+	outpdw(MDP_BASE + 0x40d08, 0xd0d0d);
+	outpdw(MDP_BASE + 0x40d0c, 0xd0d0d);
+	outpdw(MDP_BASE + 0x40d10, 0xe0e0e);
+	outpdw(MDP_BASE + 0x40d14, 0xe0e0e);
+	outpdw(MDP_BASE + 0x40d18, 0xe0e0e);
+	outpdw(MDP_BASE + 0x40d1c, 0xf0f0f);
+	outpdw(MDP_BASE + 0x40d20, 0xf0f0f);
+	outpdw(MDP_BASE + 0x40d24, 0x101010);
+	outpdw(MDP_BASE + 0x40d28, 0x101010);
+	outpdw(MDP_BASE + 0x40d2c, 0x111111);
+	outpdw(MDP_BASE + 0x40d30, 0x111111);
+	outpdw(MDP_BASE + 0x40d34, 0x121212);
+	outpdw(MDP_BASE + 0x40d38, 0x121212);
+	outpdw(MDP_BASE + 0x40d3c, 0x131313);
+	outpdw(MDP_BASE + 0x40d40, 0x131313);
+	outpdw(MDP_BASE + 0x40d44, 0x141414);
+	outpdw(MDP_BASE + 0x40d48, 0x151515);
+	outpdw(MDP_BASE + 0x40d4c, 0x151515);
+	outpdw(MDP_BASE + 0x40d50, 0x161616);
+	outpdw(MDP_BASE + 0x40d54, 0x161616);
+	outpdw(MDP_BASE + 0x40d58, 0x171717);
+	outpdw(MDP_BASE + 0x40d5c, 0x171717);
+	outpdw(MDP_BASE + 0x40d60, 0x181818);
+	outpdw(MDP_BASE + 0x40d64, 0x191919);
+	outpdw(MDP_BASE + 0x40d68, 0x191919);
+	outpdw(MDP_BASE + 0x40d6c, 0x1a1a1a);
+	outpdw(MDP_BASE + 0x40d70, 0x1b1b1b);
+	outpdw(MDP_BASE + 0x40d74, 0x1b1b1b);
+	outpdw(MDP_BASE + 0x40d78, 0x1c1c1c);
+	outpdw(MDP_BASE + 0x40d7c, 0x1c1c1c);
+	outpdw(MDP_BASE + 0x40d80, 0x1d1d1d);
+	outpdw(MDP_BASE + 0x40d84, 0x1e1e1e);
+	outpdw(MDP_BASE + 0x40d88, 0x1f1f1f);
+	outpdw(MDP_BASE + 0x40d8c, 0x1f1f1f);
+	outpdw(MDP_BASE + 0x40d90, 0x202020);
+	outpdw(MDP_BASE + 0x40d94, 0x212121);
+	outpdw(MDP_BASE + 0x40d98, 0x212121);
+	outpdw(MDP_BASE + 0x40d9c, 0x222222);
+	outpdw(MDP_BASE + 0x40da0, 0x232323);
+	outpdw(MDP_BASE + 0x40da4, 0x242424);
+	outpdw(MDP_BASE + 0x40da8, 0x242424);
+	outpdw(MDP_BASE + 0x40dac, 0x252525);
+	outpdw(MDP_BASE + 0x40db0, 0x262626);
+	outpdw(MDP_BASE + 0x40db4, 0x272727);
+	outpdw(MDP_BASE + 0x40db8, 0x272727);
+	outpdw(MDP_BASE + 0x40dbc, 0x282828);
+	outpdw(MDP_BASE + 0x40dc0, 0x292929);
+	outpdw(MDP_BASE + 0x40dc4, 0x2a2a2a);
+	outpdw(MDP_BASE + 0x40dc8, 0x2b2b2b);
+	outpdw(MDP_BASE + 0x40dcc, 0x2c2c2c);
+	outpdw(MDP_BASE + 0x40dd0, 0x2c2c2c);
+	outpdw(MDP_BASE + 0x40dd4, 0x2d2d2d);
+	outpdw(MDP_BASE + 0x40dd8, 0x2e2e2e);
+	outpdw(MDP_BASE + 0x40ddc, 0x2f2f2f);
+	outpdw(MDP_BASE + 0x40de0, 0x303030);
+	outpdw(MDP_BASE + 0x40de4, 0x313131);
+	outpdw(MDP_BASE + 0x40de8, 0x323232);
+	outpdw(MDP_BASE + 0x40dec, 0x333333);
+	outpdw(MDP_BASE + 0x40df0, 0x333333);
+	outpdw(MDP_BASE + 0x40df4, 0x343434);
+	outpdw(MDP_BASE + 0x40df8, 0x353535);
+	outpdw(MDP_BASE + 0x40dfc, 0x363636);
+	outpdw(MDP_BASE + 0x40e00, 0x373737);
+	outpdw(MDP_BASE + 0x40e04, 0x383838);
+	outpdw(MDP_BASE + 0x40e08, 0x393939);
+	outpdw(MDP_BASE + 0x40e0c, 0x3a3a3a);
+	outpdw(MDP_BASE + 0x40e10, 0x3b3b3b);
+	outpdw(MDP_BASE + 0x40e14, 0x3c3c3c);
+	outpdw(MDP_BASE + 0x40e18, 0x3d3d3d);
+	outpdw(MDP_BASE + 0x40e1c, 0x3e3e3e);
+	outpdw(MDP_BASE + 0x40e20, 0x3f3f3f);
+	outpdw(MDP_BASE + 0x40e24, 0x404040);
+	outpdw(MDP_BASE + 0x40e28, 0x414141);
+	outpdw(MDP_BASE + 0x40e2c, 0x424242);
+	outpdw(MDP_BASE + 0x40e30, 0x434343);
+	outpdw(MDP_BASE + 0x40e34, 0x444444);
+	outpdw(MDP_BASE + 0x40e38, 0x464646);
+	outpdw(MDP_BASE + 0x40e3c, 0x474747);
+	outpdw(MDP_BASE + 0x40e40, 0x484848);
+	outpdw(MDP_BASE + 0x40e44, 0x494949);
+	outpdw(MDP_BASE + 0x40e48, 0x4a4a4a);
+	outpdw(MDP_BASE + 0x40e4c, 0x4b4b4b);
+	outpdw(MDP_BASE + 0x40e50, 0x4c4c4c);
+	outpdw(MDP_BASE + 0x40e54, 0x4d4d4d);
+	outpdw(MDP_BASE + 0x40e58, 0x4f4f4f);
+	outpdw(MDP_BASE + 0x40e5c, 0x505050);
+	outpdw(MDP_BASE + 0x40e60, 0x515151);
+	outpdw(MDP_BASE + 0x40e64, 0x525252);
+	outpdw(MDP_BASE + 0x40e68, 0x535353);
+	outpdw(MDP_BASE + 0x40e6c, 0x545454);
+	outpdw(MDP_BASE + 0x40e70, 0x565656);
+	outpdw(MDP_BASE + 0x40e74, 0x575757);
+	outpdw(MDP_BASE + 0x40e78, 0x585858);
+	outpdw(MDP_BASE + 0x40e7c, 0x595959);
+	outpdw(MDP_BASE + 0x40e80, 0x5b5b5b);
+	outpdw(MDP_BASE + 0x40e84, 0x5c5c5c);
+	outpdw(MDP_BASE + 0x40e88, 0x5d5d5d);
+	outpdw(MDP_BASE + 0x40e8c, 0x5e5e5e);
+	outpdw(MDP_BASE + 0x40e90, 0x606060);
+	outpdw(MDP_BASE + 0x40e94, 0x616161);
+	outpdw(MDP_BASE + 0x40e98, 0x626262);
+	outpdw(MDP_BASE + 0x40e9c, 0x646464);
+	outpdw(MDP_BASE + 0x40ea0, 0x656565);
+	outpdw(MDP_BASE + 0x40ea4, 0x666666);
+	outpdw(MDP_BASE + 0x40ea8, 0x686868);
+	outpdw(MDP_BASE + 0x40eac, 0x696969);
+	outpdw(MDP_BASE + 0x40eb0, 0x6a6a6a);
+	outpdw(MDP_BASE + 0x40eb4, 0x6c6c6c);
+	outpdw(MDP_BASE + 0x40eb8, 0x6d6d6d);
+	outpdw(MDP_BASE + 0x40ebc, 0x6f6f6f);
+	outpdw(MDP_BASE + 0x40ec0, 0x707070);
+	outpdw(MDP_BASE + 0x40ec4, 0x717171);
+	outpdw(MDP_BASE + 0x40ec8, 0x737373);
+	outpdw(MDP_BASE + 0x40ecc, 0x747474);
+	outpdw(MDP_BASE + 0x40ed0, 0x767676);
+	outpdw(MDP_BASE + 0x40ed4, 0x777777);
+	outpdw(MDP_BASE + 0x40ed8, 0x797979);
+	outpdw(MDP_BASE + 0x40edc, 0x7a7a7a);
+	outpdw(MDP_BASE + 0x40ee0, 0x7c7c7c);
+	outpdw(MDP_BASE + 0x40ee4, 0x7d7d7d);
+	outpdw(MDP_BASE + 0x40ee8, 0x7f7f7f);
+	outpdw(MDP_BASE + 0x40eec, 0x808080);
+	outpdw(MDP_BASE + 0x40ef0, 0x828282);
+	outpdw(MDP_BASE + 0x40ef4, 0x838383);
+	outpdw(MDP_BASE + 0x40ef8, 0x858585);
+	outpdw(MDP_BASE + 0x40efc, 0x868686);
+	outpdw(MDP_BASE + 0x40f00, 0x888888);
+	outpdw(MDP_BASE + 0x40f04, 0x898989);
+	outpdw(MDP_BASE + 0x40f08, 0x8b8b8b);
+	outpdw(MDP_BASE + 0x40f0c, 0x8d8d8d);
+	outpdw(MDP_BASE + 0x40f10, 0x8e8e8e);
+	outpdw(MDP_BASE + 0x40f14, 0x909090);
+	outpdw(MDP_BASE + 0x40f18, 0x919191);
+	outpdw(MDP_BASE + 0x40f1c, 0x939393);
+	outpdw(MDP_BASE + 0x40f20, 0x959595);
+	outpdw(MDP_BASE + 0x40f24, 0x969696);
+	outpdw(MDP_BASE + 0x40f28, 0x989898);
+	outpdw(MDP_BASE + 0x40f2c, 0x9a9a9a);
+	outpdw(MDP_BASE + 0x40f30, 0x9b9b9b);
+	outpdw(MDP_BASE + 0x40f34, 0x9d9d9d);
+	outpdw(MDP_BASE + 0x40f38, 0x9f9f9f);
+	outpdw(MDP_BASE + 0x40f3c, 0xa1a1a1);
+	outpdw(MDP_BASE + 0x40f40, 0xa2a2a2);
+	outpdw(MDP_BASE + 0x40f44, 0xa4a4a4);
+	outpdw(MDP_BASE + 0x40f48, 0xa6a6a6);
+	outpdw(MDP_BASE + 0x40f4c, 0xa7a7a7);
+	outpdw(MDP_BASE + 0x40f50, 0xa9a9a9);
+	outpdw(MDP_BASE + 0x40f54, 0xababab);
+	outpdw(MDP_BASE + 0x40f58, 0xadadad);
+	outpdw(MDP_BASE + 0x40f5c, 0xafafaf);
+	outpdw(MDP_BASE + 0x40f60, 0xb0b0b0);
+	outpdw(MDP_BASE + 0x40f64, 0xb2b2b2);
+	outpdw(MDP_BASE + 0x40f68, 0xb4b4b4);
+	outpdw(MDP_BASE + 0x40f6c, 0xb6b6b6);
+	outpdw(MDP_BASE + 0x40f70, 0xb8b8b8);
+	outpdw(MDP_BASE + 0x40f74, 0xbababa);
+	outpdw(MDP_BASE + 0x40f78, 0xbbbbbb);
+	outpdw(MDP_BASE + 0x40f7c, 0xbdbdbd);
+	outpdw(MDP_BASE + 0x40f80, 0xbfbfbf);
+	outpdw(MDP_BASE + 0x40f84, 0xc1c1c1);
+	outpdw(MDP_BASE + 0x40f88, 0xc3c3c3);
+	outpdw(MDP_BASE + 0x40f8c, 0xc5c5c5);
+	outpdw(MDP_BASE + 0x40f90, 0xc7c7c7);
+	outpdw(MDP_BASE + 0x40f94, 0xc9c9c9);
+	outpdw(MDP_BASE + 0x40f98, 0xcbcbcb);
+	outpdw(MDP_BASE + 0x40f9c, 0xcdcdcd);
+	outpdw(MDP_BASE + 0x40fa0, 0xcfcfcf);
+	outpdw(MDP_BASE + 0x40fa4, 0xd1d1d1);
+	outpdw(MDP_BASE + 0x40fa8, 0xd3d3d3);
+	outpdw(MDP_BASE + 0x40fac, 0xd5d5d5);
+	outpdw(MDP_BASE + 0x40fb0, 0xd7d7d7);
+	outpdw(MDP_BASE + 0x40fb4, 0xd9d9d9);
+	outpdw(MDP_BASE + 0x40fb8, 0xdbdbdb);
+	outpdw(MDP_BASE + 0x40fbc, 0xdddddd);
+	outpdw(MDP_BASE + 0x40fc0, 0xdfdfdf);
+	outpdw(MDP_BASE + 0x40fc4, 0xe1e1e1);
+	outpdw(MDP_BASE + 0x40fc8, 0xe3e3e3);
+	outpdw(MDP_BASE + 0x40fcc, 0xe5e5e5);
+	outpdw(MDP_BASE + 0x40fd0, 0xe7e7e7);
+	outpdw(MDP_BASE + 0x40fd4, 0xe9e9e9);
+	outpdw(MDP_BASE + 0x40fd8, 0xebebeb);
+	outpdw(MDP_BASE + 0x40fdc, 0xeeeeee);
+	outpdw(MDP_BASE + 0x40fe0, 0xf0f0f0);
+	outpdw(MDP_BASE + 0x40fe4, 0xf2f2f2);
+	outpdw(MDP_BASE + 0x40fe8, 0xf4f4f4);
+	outpdw(MDP_BASE + 0x40fec, 0xf6f6f6);
+	outpdw(MDP_BASE + 0x40ff0, 0xf8f8f8);
+	outpdw(MDP_BASE + 0x40ff4, 0xfbfbfb);
+	outpdw(MDP_BASE + 0x40ff8, 0xfdfdfd);
+	outpdw(MDP_BASE + 0x40ffc, 0xffffff);
+}
+
+#define   IRQ_EN_1__MDP_IRQ___M    0x00000800
+
+void mdp_hw_init(void)
+{
+	int i;
+
+	/* MDP cmd block enable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+	/* debug interface write access */
+	outpdw(MDP_BASE + 0x60, 1);
+
+	outp32(MDP_INTR_ENABLE, MDP_ANY_INTR_MASK);
+	outp32(MDP_EBI2_PORTMAP_MODE, 0x3);
+	outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8, 0x0);
+	outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc, 0x0);
+	outpdw(MDP_BASE + 0x60, 0x1);
+	mdp_load_lut_param();
+
+	/*
+	 * clear up unused fg/main registers
+	 */
+	/* comp.plane 2&3 ystride */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0120, 0x0);
+	/* unpacked pattern */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x012c, 0x0);
+	/* unpacked pattern */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0130, 0x0);
+	/* unpacked pattern */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0134, 0x0);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0158, 0x0);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x15c, 0x0);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0160, 0x0);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0170, 0x0);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0174, 0x0);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x017c, 0x0);
+
+	/* comp.plane 2 */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0114, 0x0);
+	/* comp.plane 3 */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0118, 0x0);
+
+	/* clear up unused bg registers */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8, 0);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0, 0);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc, 0);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0, 0);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4, 0);
+
+#ifndef CONFIG_FB_MSM_MDP22
+	MDP_OUTP(MDP_BASE + 0xE0000, 0);
+	MDP_OUTP(MDP_BASE + 0x100, 0xffffffff);
+	MDP_OUTP(MDP_BASE + 0x90070, 0);
+	MDP_OUTP(MDP_BASE + 0x94010, 1);
+	MDP_OUTP(MDP_BASE + 0x9401c, 2);
+#endif
+
+	/*
+	 * limit vector
+	 * pre gets applied before color matrix conversion
+	 * post is after ccs
+	 */
+	writel(mdp_plv[0], MDP_CSC_PRE_LV1n(0));
+	writel(mdp_plv[1], MDP_CSC_PRE_LV1n(1));
+	writel(mdp_plv[2], MDP_CSC_PRE_LV1n(2));
+	writel(mdp_plv[3], MDP_CSC_PRE_LV1n(3));
+
+#ifdef CONFIG_FB_MSM_MDP31
+	writel(mdp_plv[2], MDP_CSC_PRE_LV1n(4));
+	writel(mdp_plv[3], MDP_CSC_PRE_LV1n(5));
+
+	writel(0, MDP_CSC_POST_LV1n(0));
+	writel(0xff, MDP_CSC_POST_LV1n(1));
+	writel(0, MDP_CSC_POST_LV1n(2));
+	writel(0xff, MDP_CSC_POST_LV1n(3));
+	writel(0, MDP_CSC_POST_LV1n(4));
+	writel(0xff, MDP_CSC_POST_LV1n(5));
+
+	writel(0, MDP_CSC_PRE_LV2n(0));
+	writel(0xff, MDP_CSC_PRE_LV2n(1));
+	writel(0, MDP_CSC_PRE_LV2n(2));
+	writel(0xff, MDP_CSC_PRE_LV2n(3));
+	writel(0, MDP_CSC_PRE_LV2n(4));
+	writel(0xff, MDP_CSC_PRE_LV2n(5));
+
+	writel(mdp_plv[0], MDP_CSC_POST_LV2n(0));
+	writel(mdp_plv[1], MDP_CSC_POST_LV2n(1));
+	writel(mdp_plv[2], MDP_CSC_POST_LV2n(2));
+	writel(mdp_plv[3], MDP_CSC_POST_LV2n(3));
+	writel(mdp_plv[2], MDP_CSC_POST_LV2n(4));
+	writel(mdp_plv[3], MDP_CSC_POST_LV2n(5));
+#endif
+
+	/* primary forward matrix */
+	for (i = 0; i < MDP_CCS_SIZE; i++)
+		writel(mdp_ccs_rgb2yuv.ccs[i], MDP_CSC_PFMVn(i));
+
+#ifdef CONFIG_FB_MSM_MDP31
+	for (i = 0; i < MDP_BV_SIZE; i++)
+		writel(mdp_ccs_rgb2yuv.bv[i], MDP_CSC_POST_BV2n(i));
+
+	writel(0, MDP_CSC_PRE_BV2n(0));
+	writel(0, MDP_CSC_PRE_BV2n(1));
+	writel(0, MDP_CSC_PRE_BV2n(2));
+#endif
+	/* primary reverse matrix */
+	for (i = 0; i < MDP_CCS_SIZE; i++)
+		writel(mdp_ccs_yuv2rgb.ccs[i], MDP_CSC_PRMVn(i));
+
+	for (i = 0; i < MDP_BV_SIZE; i++)
+		writel(mdp_ccs_yuv2rgb.bv[i], MDP_CSC_PRE_BV1n(i));
+
+#ifdef CONFIG_FB_MSM_MDP31
+	writel(0, MDP_CSC_POST_BV1n(0));
+	writel(0, MDP_CSC_POST_BV1n(1));
+	writel(0, MDP_CSC_POST_BV1n(2));
+
+	outpdw(MDP_BASE + 0x30010, 0x03e0);
+	outpdw(MDP_BASE + 0x30014, 0x0360);
+	outpdw(MDP_BASE + 0x30018, 0x0120);
+	outpdw(MDP_BASE + 0x3001c, 0x0140);
+#endif
+	mdp_init_scale_table();
+
+#ifndef CONFIG_FB_MSM_MDP31
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0104,
+		 ((16 << 6) << 16) | (16) << 6);
+#endif
+
+	/* MDP cmd block disable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+}

+ 1502 - 0
drivers/staging/msm/mdp_ppp.c

@@ -0,0 +1,1502 @@
+/* drivers/video/msm/src/drv/mdp/mdp_ppp.c
+ *
+ * Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <msm_mdp.h>
+#include <linux/file.h>
+#include <linux/major.h>
+
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+#define MDP_IS_IMGTYPE_BAD(x) (((x) >= MDP_IMGTYPE_LIMIT) && \
+				(((x) < MDP_IMGTYPE2_START) || \
+				 ((x) >= MDP_IMGTYPE_LIMIT2)))
+
+static uint32_t bytes_per_pixel[] = {
+	[MDP_RGB_565] = 2,
+	[MDP_RGB_888] = 3,
+	[MDP_XRGB_8888] = 4,
+	[MDP_ARGB_8888] = 4,
+	[MDP_RGBA_8888] = 4,
+	[MDP_BGRA_8888] = 4,
+	[MDP_Y_CBCR_H2V1] = 1,
+	[MDP_Y_CBCR_H2V2] = 1,
+	[MDP_Y_CRCB_H2V1] = 1,
+	[MDP_Y_CRCB_H2V2] = 1,
+	[MDP_YCRYCB_H2V1] = 2,
+	[MDP_BGR_565] = 2
+};
+
+extern uint32 mdp_plv[];
+extern struct semaphore mdp_ppp_mutex;
+
+uint32_t mdp_get_bytes_per_pixel(uint32_t format)
+{
+	uint32_t bpp = 0;
+	if (format < ARRAY_SIZE(bytes_per_pixel))
+		bpp = bytes_per_pixel[format];
+
+	BUG_ON(!bpp);
+	return bpp;
+}
+
+static uint32 mdp_conv_matx_rgb2yuv(uint32 input_pixel,
+				    uint16 *matrix_and_bias_vector,
+				    uint32 *clamp_vector,
+				    uint32 *look_up_table)
+{
+	uint8 input_C2, input_C0, input_C1;
+	uint32 output;
+	int32 comp_C2, comp_C1, comp_C0, temp;
+	int32 temp1, temp2, temp3;
+	int32 matrix[9];
+	int32 bias_vector[3];
+	int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
+	int32 i;
+	uint32 _is_lookup_table_enabled;
+
+	input_C2 = (input_pixel >> 16) & 0xFF;
+	input_C1 = (input_pixel >> 8) & 0xFF;
+	input_C0 = (input_pixel >> 0) & 0xFF;
+
+	comp_C0 = input_C0;
+	comp_C1 = input_C1;
+	comp_C2 = input_C2;
+
+	for (i = 0; i < 9; i++)
+		matrix[i] =
+		    ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
+
+	bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
+	bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
+	bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
+
+	Y_low_limit = (int32) clamp_vector[0];
+	Y_high_limit = (int32) clamp_vector[1];
+	C_low_limit = (int32) clamp_vector[2];
+	C_high_limit = (int32) clamp_vector[3];
+
+	if (look_up_table == 0)	/* check for NULL point */
+		_is_lookup_table_enabled = 0;
+	else
+		_is_lookup_table_enabled = 1;
+
+	if (_is_lookup_table_enabled == 1) {
+		comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
+		comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
+		comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
+	}
+	/*
+	 * Color Conversion
+	 * reorder input colors
+	 */
+	temp = comp_C2;
+	comp_C2 = comp_C1;
+	comp_C1 = comp_C0;
+	comp_C0 = temp;
+
+	/* matrix multiplication */
+	temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
+	temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
+	temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
+
+	comp_C0 = temp1 + 0x100;
+	comp_C1 = temp2 + 0x100;
+	comp_C2 = temp3 + 0x100;
+
+	/* take interger part */
+	comp_C0 >>= 9;
+	comp_C1 >>= 9;
+	comp_C2 >>= 9;
+
+	/* post bias (+) */
+	comp_C0 += bias_vector[0];
+	comp_C1 += bias_vector[1];
+	comp_C2 += bias_vector[2];
+
+	/* limit pixel to 8-bit */
+	if (comp_C0 < 0)
+		comp_C0 = 0;
+
+	if (comp_C0 > 255)
+		comp_C0 = 255;
+
+	if (comp_C1 < 0)
+		comp_C1 = 0;
+
+	if (comp_C1 > 255)
+		comp_C1 = 255;
+
+	if (comp_C2 < 0)
+		comp_C2 = 0;
+
+	if (comp_C2 > 255)
+		comp_C2 = 255;
+
+	/* clamp */
+	if (comp_C0 < Y_low_limit)
+		comp_C0 = Y_low_limit;
+
+	if (comp_C0 > Y_high_limit)
+		comp_C0 = Y_high_limit;
+
+	if (comp_C1 < C_low_limit)
+		comp_C1 = C_low_limit;
+
+	if (comp_C1 > C_high_limit)
+		comp_C1 = C_high_limit;
+
+	if (comp_C2 < C_low_limit)
+		comp_C2 = C_low_limit;
+
+	if (comp_C2 > C_high_limit)
+		comp_C2 = C_high_limit;
+
+	output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
+	return output;
+}
+
+uint32 mdp_conv_matx_yuv2rgb(uint32 input_pixel,
+			     uint16 *matrix_and_bias_vector,
+			     uint32 *clamp_vector, uint32 *look_up_table)
+{
+	uint8 input_C2, input_C0, input_C1;
+	uint32 output;
+	int32 comp_C2, comp_C1, comp_C0, temp;
+	int32 temp1, temp2, temp3;
+	int32 matrix[9];
+	int32 bias_vector[3];
+	int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
+	int32 i;
+	uint32 _is_lookup_table_enabled;
+
+	input_C2 = (input_pixel >> 16) & 0xFF;
+	input_C1 = (input_pixel >> 8) & 0xFF;
+	input_C0 = (input_pixel >> 0) & 0xFF;
+
+	comp_C0 = input_C0;
+	comp_C1 = input_C1;
+	comp_C2 = input_C2;
+
+	for (i = 0; i < 9; i++)
+		matrix[i] =
+		    ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
+
+	bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
+	bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
+	bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
+
+	Y_low_limit = (int32) clamp_vector[0];
+	Y_high_limit = (int32) clamp_vector[1];
+	C_low_limit = (int32) clamp_vector[2];
+	C_high_limit = (int32) clamp_vector[3];
+
+	if (look_up_table == 0)	/* check for NULL point */
+		_is_lookup_table_enabled = 0;
+	else
+		_is_lookup_table_enabled = 1;
+
+	/* clamp */
+	if (comp_C0 < Y_low_limit)
+		comp_C0 = Y_low_limit;
+
+	if (comp_C0 > Y_high_limit)
+		comp_C0 = Y_high_limit;
+
+	if (comp_C1 < C_low_limit)
+		comp_C1 = C_low_limit;
+
+	if (comp_C1 > C_high_limit)
+		comp_C1 = C_high_limit;
+
+	if (comp_C2 < C_low_limit)
+		comp_C2 = C_low_limit;
+
+	if (comp_C2 > C_high_limit)
+		comp_C2 = C_high_limit;
+
+	/*
+	 * Color Conversion
+	 * pre bias (-)
+	 */
+	comp_C0 -= bias_vector[0];
+	comp_C1 -= bias_vector[1];
+	comp_C2 -= bias_vector[2];
+
+	/* matrix multiplication */
+	temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
+	temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
+	temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
+
+	comp_C0 = temp1 + 0x100;
+	comp_C1 = temp2 + 0x100;
+	comp_C2 = temp3 + 0x100;
+
+	/* take interger part */
+	comp_C0 >>= 9;
+	comp_C1 >>= 9;
+	comp_C2 >>= 9;
+
+	/* reorder output colors */
+	temp = comp_C0;
+	comp_C0 = comp_C1;
+	comp_C1 = comp_C2;
+	comp_C2 = temp;
+
+	/* limit pixel to 8-bit */
+	if (comp_C0 < 0)
+		comp_C0 = 0;
+
+	if (comp_C0 > 255)
+		comp_C0 = 255;
+
+	if (comp_C1 < 0)
+		comp_C1 = 0;
+
+	if (comp_C1 > 255)
+		comp_C1 = 255;
+
+	if (comp_C2 < 0)
+		comp_C2 = 0;
+
+	if (comp_C2 > 255)
+		comp_C2 = 255;
+
+	/* Look-up table */
+	if (_is_lookup_table_enabled == 1) {
+		comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
+		comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
+		comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
+	}
+
+	output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
+	return output;
+}
+
+static uint32 mdp_calc_tpval(MDPIMG *mdpImg)
+{
+	uint32 tpVal;
+	uint8 plane_tp;
+
+	tpVal = 0;
+	if ((mdpImg->imgType == MDP_RGB_565)
+	    || (mdpImg->imgType == MDP_BGR_565)) {
+		/*
+		 * transparent color conversion into 24 bpp
+		 *
+		 * C2R_8BIT
+		 * left shift the entire bit and or it with the upper most bits
+		 */
+		plane_tp = (uint8) ((mdpImg->tpVal & 0xF800) >> 11);
+		tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16;
+
+		/* C1B_8BIT */
+		plane_tp = (uint8) (mdpImg->tpVal & 0x1F);
+		tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8;
+
+		/* C0G_8BIT */
+		plane_tp = (uint8) ((mdpImg->tpVal & 0x7E0) >> 5);
+		tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4));
+	} else {
+		/* 24bit RGB to RBG conversion */
+
+		tpVal = (mdpImg->tpVal & 0xFF00) >> 8;
+		tpVal |= (mdpImg->tpVal & 0xFF) << 8;
+		tpVal |= (mdpImg->tpVal & 0xFF0000);
+	}
+
+	return tpVal;
+}
+
+static uint8 *mdp_get_chroma_addr(MDPIBUF *iBuf)
+{
+	uint8 *dest1;
+
+	dest1 = NULL;
+	switch (iBuf->ibuf_type) {
+	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CRCB_H2V2:
+	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H2V1:
+		dest1 = (uint8 *) iBuf->buf;
+		dest1 += iBuf->ibuf_width * iBuf->ibuf_height * iBuf->bpp;
+		break;
+
+	default:
+		break;
+	}
+
+	return dest1;
+}
+
+static void mdp_ppp_setbg(MDPIBUF *iBuf)
+{
+	uint8 *bg0_addr;
+	uint8 *bg1_addr;
+	uint32 bg0_ystride, bg1_ystride;
+	uint32 ppp_src_cfg_reg, unpack_pattern;
+	int v_slice, h_slice;
+
+	v_slice = h_slice = 1;
+	bg0_addr = (uint8 *) iBuf->buf;
+	bg1_addr = mdp_get_chroma_addr(iBuf);
+
+	bg0_ystride = iBuf->ibuf_width * iBuf->bpp;
+	bg1_ystride = iBuf->ibuf_width * iBuf->bpp;
+
+	switch (iBuf->ibuf_type) {
+	case MDP_BGR_565:
+	case MDP_RGB_565:
+		/* 888 = 3bytes
+		 * RGB = 3Components
+		 * RGB interleaved
+		 */
+		ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
+			PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
+			PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+			PPP_SRC_UNPACK_ALIGN_LSB |
+			PPP_SRC_FETCH_PLANES_INTERLVD;
+
+		if (iBuf->ibuf_type == MDP_RGB_565)
+			unpack_pattern =
+			    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+		else
+			unpack_pattern =
+			    MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+		break;
+
+	case MDP_RGB_888:
+		/*
+		 * 888 = 3bytes
+		 * RGB = 3Components
+		 * RGB interleaved
+		 */
+		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+		PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
+		PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+		PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_INTERLVD;
+
+		unpack_pattern =
+		    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+		break;
+
+	case MDP_BGRA_8888:
+	case MDP_RGBA_8888:
+	case MDP_ARGB_8888:
+	case MDP_XRGB_8888:
+		/*
+		 * 8888 = 4bytes
+		 * ARGB = 4Components
+		 * ARGB interleaved
+		 */
+		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+		PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | PPP_SRC_C3_ALPHA_EN |
+		PPP_SRC_BPP_INTERLVD_4BYTES | PPP_SRC_INTERLVD_4COMPONENTS |
+		PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB |
+		PPP_SRC_FETCH_PLANES_INTERLVD;
+
+		if (iBuf->ibuf_type == MDP_BGRA_8888)
+			unpack_pattern =
+			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+						 8);
+		else if (iBuf->ibuf_type == MDP_RGBA_8888)
+			unpack_pattern =
+			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+						 8);
+		else
+			unpack_pattern =
+			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+						 8);
+		break;
+
+	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CRCB_H2V2:
+		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+		    PPP_SRC_C0G_8BITS |
+		    PPP_SRC_C1B_8BITS |
+		    PPP_SRC_C3A_8BITS |
+		    PPP_SRC_BPP_INTERLVD_2BYTES |
+		    PPP_SRC_INTERLVD_2COMPONENTS |
+		    PPP_SRC_UNPACK_TIGHT |
+		    PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+		if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+			unpack_pattern =
+			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+		else
+			unpack_pattern =
+			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+		v_slice = h_slice = 2;
+		break;
+
+	case MDP_YCRYCB_H2V1:
+		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+		    PPP_SRC_C0G_8BITS |
+		    PPP_SRC_C1B_8BITS |
+		    PPP_SRC_C3A_8BITS |
+		    PPP_SRC_BPP_INTERLVD_2BYTES |
+		    PPP_SRC_INTERLVD_4COMPONENTS |
+		    PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
+
+		unpack_pattern =
+		    MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+		h_slice = 2;
+		break;
+
+	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H2V1:
+		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+		    PPP_SRC_C0G_8BITS |
+		    PPP_SRC_C1B_8BITS |
+		    PPP_SRC_C3A_8BITS |
+		    PPP_SRC_BPP_INTERLVD_2BYTES |
+		    PPP_SRC_INTERLVD_2COMPONENTS |
+		    PPP_SRC_UNPACK_TIGHT |
+		    PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+		if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+			unpack_pattern =
+			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+		else
+			unpack_pattern =
+			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+		h_slice = 2;
+		break;
+
+	default:
+		return;
+	}
+
+	/* starting input address adjustment */
+	mdp_adjust_start_addr(&bg0_addr, &bg1_addr, v_slice, h_slice,
+			      iBuf->roi.lcd_x, iBuf->roi.lcd_y,
+			      iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
+			      iBuf, 1);
+
+	/*
+	 * 0x01c0: background plane 0 addr
+	 * 0x01c4: background plane 1 addr
+	 * 0x01c8: background plane 2 addr
+	 * 0x01cc: bg y stride for plane 0 and 1
+	 * 0x01d0: bg y stride for plane 2
+	 * 0x01d4: bg src PPP config
+	 * 0x01d8: unpack pattern
+	 */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c0, bg0_addr);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c4, bg1_addr);
+
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01cc,
+		 (bg1_ystride << 16) | bg0_ystride);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d4, ppp_src_cfg_reg);
+
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d8, unpack_pattern);
+}
+
+#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
+				(img == MDP_Y_CBCR_H2V2) | \
+				(img == MDP_Y_CRCB_H2V1) | \
+				(img == MDP_Y_CBCR_H2V1))
+
+#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
+
+#define Y_TO_CRCB_RATIO(format) \
+	((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ?  2 :\
+	(format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ?  1 : 1)
+
+static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
+			uint32_t *len0, uint32_t *len1)
+{
+	*len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
+	if (IS_PSEUDOPLNR(img->format))
+		*len1 = *len0/Y_TO_CRCB_RATIO(img->format);
+	else
+		*len1 = 0;
+}
+
+static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp,
+			struct file *p_src_file, struct file *p_dst_file)
+{
+#ifdef CONFIG_ANDROID_PMEM
+	uint32_t src0_len, src1_len, dst0_len, dst1_len;
+
+	/* flush src images to memory before dma to mdp */
+	get_len(&req->src, &req->src_rect, src_bpp,
+	&src0_len, &src1_len);
+
+	flush_pmem_file(p_src_file,
+	req->src.offset, src0_len);
+
+	if (IS_PSEUDOPLNR(req->src.format))
+		flush_pmem_file(p_src_file,
+			req->src.offset + src0_len, src1_len);
+
+	get_len(&req->dst, &req->dst_rect, dst_bpp, &dst0_len, &dst1_len);
+	flush_pmem_file(p_dst_file, req->dst.offset, dst0_len);
+
+	if (IS_PSEUDOPLNR(req->dst.format))
+		flush_pmem_file(p_dst_file,
+			req->dst.offset + dst0_len, dst1_len);
+#endif
+}
+
+static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf,
+struct mdp_blit_req *req, struct file *p_src_file, struct file *p_dst_file)
+{
+	uint8 *src0, *src1;
+	uint8 *dest0, *dest1;
+	uint16 inpBpp;
+	uint32 dest0_ystride;
+	uint32 src_width;
+	uint32 src_height;
+	uint32 src0_ystride;
+	uint32 dst_roi_width;
+	uint32 dst_roi_height;
+	uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg;
+	uint32 alpha, tpVal;
+	uint32 packPattern;
+	uint32 dst_packPattern;
+	boolean inputRGB, outputRGB, pseudoplanr_output;
+	int sv_slice, sh_slice;
+	int dv_slice, dh_slice;
+	boolean perPixelAlpha = FALSE;
+	boolean ppp_lookUp_enable = FALSE;
+
+	sv_slice = sh_slice = dv_slice = dh_slice = 1;
+	alpha = tpVal = 0;
+	src_width = iBuf->mdpImg.width;
+	src_height = iBuf->roi.y + iBuf->roi.height;
+	src1 = NULL;
+	dest1 = NULL;
+
+	inputRGB = outputRGB = TRUE;
+	pseudoplanr_output = FALSE;
+	ppp_operation_reg = 0;
+	ppp_dst_cfg_reg = 0;
+	ppp_src_cfg_reg = 0;
+
+	/* Wait for the pipe to clear */
+	do { } while (mdp_ppp_pipe_wait() <= 0);
+
+	/*
+	 * destination config
+	 */
+	switch (iBuf->ibuf_type) {
+	case MDP_RGB_888:
+		dst_packPattern =
+		    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+		ppp_dst_cfg_reg =
+		    PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | PPP_DST_C2R_8BIT |
+		    PPP_DST_PACKET_CNT_INTERLVD_3ELEM | PPP_DST_PACK_TIGHT |
+		    PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI |
+		    PPP_DST_BPP_3BYTES | PPP_DST_PLANE_INTERLVD;
+		break;
+
+	case MDP_XRGB_8888:
+	case MDP_ARGB_8888:
+	case MDP_RGBA_8888:
+		if (iBuf->ibuf_type == MDP_BGRA_8888)
+			dst_packPattern =
+			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+						 8);
+		else if (iBuf->ibuf_type == MDP_RGBA_8888)
+			dst_packPattern =
+			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+						 8);
+		else
+			dst_packPattern =
+			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+						 8);
+
+		ppp_dst_cfg_reg = PPP_DST_C0G_8BIT |
+		    PPP_DST_C1B_8BIT |
+		    PPP_DST_C2R_8BIT |
+		    PPP_DST_C3A_8BIT |
+		    PPP_DST_C3ALPHA_EN |
+		    PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
+		    PPP_DST_PACK_TIGHT |
+		    PPP_DST_PACK_ALIGN_LSB |
+		    PPP_DST_OUT_SEL_AXI |
+		    PPP_DST_BPP_4BYTES | PPP_DST_PLANE_INTERLVD;
+		break;
+
+	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CRCB_H2V2:
+		if (iBuf->ibuf_type == MDP_Y_CBCR_H2V2)
+			dst_packPattern =
+			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+		else
+			dst_packPattern =
+			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+		ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
+		    PPP_DST_C0G_8BIT |
+		    PPP_DST_C1B_8BIT |
+		    PPP_DST_C3A_8BIT |
+		    PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
+		    PPP_DST_PACK_TIGHT |
+		    PPP_DST_PACK_ALIGN_LSB |
+		    PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
+
+		ppp_operation_reg |= PPP_OP_DST_CHROMA_420;
+		outputRGB = FALSE;
+		pseudoplanr_output = TRUE;
+		/*
+		 * vertically (y direction) and horizontally (x direction)
+		 * sample reduction by 2
+		 */
+
+		/*
+		 * H2V2(YUV420) Cosite
+		 *
+		 * Y    Y    Y    Y
+		 * CbCr      CbCr
+		 * Y    Y    Y    Y
+		 * Y    Y    Y    Y
+		 * CbCr      CbCr
+		 * Y    Y    Y    Y
+		 */
+		dv_slice = dh_slice = 2;
+
+		/* (x,y) and (width,height) must be even numbern */
+		iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+		iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+		iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+		iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+
+		iBuf->roi.lcd_y = (iBuf->roi.lcd_y / 2) * 2;
+		iBuf->roi.dst_height = (iBuf->roi.dst_height / 2) * 2;
+		iBuf->roi.y = (iBuf->roi.y / 2) * 2;
+		iBuf->roi.height = (iBuf->roi.height / 2) * 2;
+		break;
+
+	case MDP_YCRYCB_H2V1:
+		dst_packPattern =
+		    MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+		ppp_dst_cfg_reg =
+		    PPP_DST_C2R_8BIT | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT |
+		    PPP_DST_C3A_8BIT | PPP_DST_PACKET_CNT_INTERLVD_4ELEM |
+		    PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB |
+		    PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES |
+		    PPP_DST_PLANE_INTERLVD;
+
+		ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
+		outputRGB = FALSE;
+		/*
+		 * horizontally (x direction) sample reduction by 2
+		 *
+		 * H2V1(YUV422) Cosite
+		 *
+		 * YCbCr    Y    YCbCr    Y
+		 * YCbCr    Y    YCbCr    Y
+		 * YCbCr    Y    YCbCr    Y
+		 * YCbCr    Y    YCbCr    Y
+		 */
+		dh_slice = 2;
+
+		/*
+		 * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
+		 * preloaded gamma setting of 2.2 when the content is
+		 * non-linear ppp_lookUp_enable = TRUE;
+		 */
+
+		/* x and width must be even number */
+		iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+		iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+		iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+		iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+		break;
+
+	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H2V1:
+		if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+			dst_packPattern =
+			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+		else
+			dst_packPattern =
+			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+		ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
+		    PPP_DST_C0G_8BIT |
+		    PPP_DST_C1B_8BIT |
+		    PPP_DST_C3A_8BIT |
+		    PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
+		    PPP_DST_PACK_TIGHT |
+		    PPP_DST_PACK_ALIGN_LSB |
+		    PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
+
+		ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
+		outputRGB = FALSE;
+		pseudoplanr_output = TRUE;
+		/* horizontally (x direction) sample reduction by 2 */
+		dh_slice = 2;
+
+		/* x and width must be even number */
+		iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+		iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+		iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+		iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+		break;
+
+	case MDP_BGR_565:
+	case MDP_RGB_565:
+	default:
+		if (iBuf->ibuf_type == MDP_RGB_565)
+			dst_packPattern =
+			    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+		else
+			dst_packPattern =
+			    MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+
+		ppp_dst_cfg_reg = PPP_DST_C0G_6BIT |
+		    PPP_DST_C1B_5BIT |
+		    PPP_DST_C2R_5BIT |
+		    PPP_DST_PACKET_CNT_INTERLVD_3ELEM |
+		    PPP_DST_PACK_TIGHT |
+		    PPP_DST_PACK_ALIGN_LSB |
+		    PPP_DST_OUT_SEL_AXI |
+		    PPP_DST_BPP_2BYTES | PPP_DST_PLANE_INTERLVD;
+		break;
+	}
+
+	/* source config */
+	switch (iBuf->mdpImg.imgType) {
+	case MDP_RGB_888:
+		inpBpp = 3;
+		/*
+		 * 565 = 2bytes
+		 * RGB = 3Components
+		 * RGB interleaved
+		 */
+		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+			PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES |
+			PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+			PPP_SRC_UNPACK_ALIGN_LSB |
+			PPP_SRC_FETCH_PLANES_INTERLVD;
+
+		packPattern = MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+
+		ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+		    PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+		break;
+
+	case MDP_BGRA_8888:
+	case MDP_RGBA_8888:
+	case MDP_ARGB_8888:
+		perPixelAlpha = TRUE;
+	case MDP_XRGB_8888:
+		inpBpp = 4;
+		/*
+		 * 8888 = 4bytes
+		 * ARGB = 4Components
+		 * ARGB interleaved
+		 */
+		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+			PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS |
+			PPP_SRC_C3_ALPHA_EN | PPP_SRC_BPP_INTERLVD_4BYTES |
+			PPP_SRC_INTERLVD_4COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+			PPP_SRC_UNPACK_ALIGN_LSB |
+			PPP_SRC_FETCH_PLANES_INTERLVD;
+
+		if (iBuf->mdpImg.imgType == MDP_BGRA_8888)
+			packPattern =
+			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+						 8);
+		else if (iBuf->mdpImg.imgType == MDP_RGBA_8888)
+			packPattern =
+			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+						 8);
+		else
+			packPattern =
+			    MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+						 8);
+
+		ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+		    PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+		break;
+
+	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CRCB_H2V2:
+		inpBpp = 1;
+		src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
+
+		/*
+		 * CbCr = 2bytes
+		 * CbCr = 2Components
+		 * Y+CbCr
+		 */
+		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+			PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
+			PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+			PPP_SRC_UNPACK_ALIGN_LSB |
+			PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+		if (iBuf->mdpImg.imgType == MDP_Y_CRCB_H2V2)
+			packPattern =
+			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+		else
+			packPattern =
+			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+
+		ppp_operation_reg |= PPP_OP_COLOR_SPACE_YCBCR |
+		    PPP_OP_SRC_CHROMA_420 |
+		    PPP_OP_SRC_CHROMA_COSITE |
+		    PPP_OP_DST_CHROMA_RGB | PPP_OP_DST_CHROMA_COSITE;
+
+		inputRGB = FALSE;
+		sh_slice = sv_slice = 2;
+		break;
+
+	case MDP_YCRYCB_H2V1:
+		inpBpp = 2;
+		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+		    PPP_SRC_C0G_8BITS |
+		    PPP_SRC_C1B_8BITS |
+		    PPP_SRC_C3A_8BITS |
+		    PPP_SRC_BPP_INTERLVD_2BYTES |
+		    PPP_SRC_INTERLVD_4COMPONENTS |
+		    PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
+
+		packPattern =
+		    MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+
+		ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
+		    PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
+
+		/*
+		 * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
+		 * preloaded inverse gamma setting of 2.2 since they're
+		 * symetric when the content is non-linear
+		 * ppp_lookUp_enable = TRUE;
+		 */
+
+		/* x and width must be even number */
+		iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+		iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+		iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+		iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+
+		inputRGB = FALSE;
+		sh_slice = 2;
+		break;
+
+	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H2V1:
+		inpBpp = 1;
+		src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
+
+		ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+		    PPP_SRC_C0G_8BITS |
+		    PPP_SRC_C1B_8BITS |
+		    PPP_SRC_C3A_8BITS |
+		    PPP_SRC_BPP_INTERLVD_2BYTES |
+		    PPP_SRC_INTERLVD_2COMPONENTS |
+		    PPP_SRC_UNPACK_TIGHT |
+		    PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR;
+
+		if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V1)
+			packPattern =
+			    MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+		else
+			packPattern =
+			    MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+		ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
+		    PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
+		inputRGB = FALSE;
+		sh_slice = 2;
+		break;
+
+	case MDP_BGR_565:
+	case MDP_RGB_565:
+	default:
+		inpBpp = 2;
+		/*
+		 * 565 = 2bytes
+		 * RGB = 3Components
+		 * RGB interleaved
+		 */
+		ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
+			PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES |
+			PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT |
+			PPP_SRC_UNPACK_ALIGN_LSB |
+			PPP_SRC_FETCH_PLANES_INTERLVD;
+
+		if (iBuf->mdpImg.imgType == MDP_RGB_565)
+			packPattern =
+			    MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+		else
+			packPattern =
+			    MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+
+		ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+		    PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+		break;
+
+	}
+
+	if (pseudoplanr_output)
+		ppp_dst_cfg_reg |= PPP_DST_PLANE_PSEUDOPLN;
+
+	/* YCbCr to RGB color conversion flag */
+	if ((!inputRGB) && (outputRGB)) {
+		ppp_operation_reg |= PPP_OP_CONVERT_YCBCR2RGB |
+		    PPP_OP_CONVERT_ON;
+
+		/*
+		 * primary/secondary is sort of misleading term...but
+		 * in mdp2.2/3.0 we only use primary matrix (forward/rev)
+		 * in mdp3.1 we use set1(prim) and set2(secd)
+		 */
+#ifdef CONFIG_FB_MSM_MDP31
+		ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_SECONDARY |
+					PPP_OP_DST_RGB;
+		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0);
+#endif
+
+		if (ppp_lookUp_enable) {
+			ppp_operation_reg |= PPP_OP_LUT_C0_ON |
+			    PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
+		}
+	}
+	/* RGB to YCbCr color conversion flag */
+	if ((inputRGB) && (!outputRGB)) {
+		ppp_operation_reg |= PPP_OP_CONVERT_RGB2YCBCR |
+		    PPP_OP_CONVERT_ON;
+
+#ifdef CONFIG_FB_MSM_MDP31
+		ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_PRIMARY |
+					PPP_OP_DST_YCBCR;
+		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0x1e);
+#endif
+
+		if (ppp_lookUp_enable) {
+			ppp_operation_reg |= PPP_OP_LUT_C0_ON |
+			    PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
+		}
+	}
+	/* YCbCr to YCbCr color conversion flag */
+	if ((!inputRGB) && (!outputRGB)) {
+		if ((ppp_lookUp_enable) &&
+		    (iBuf->mdpImg.imgType != iBuf->ibuf_type)) {
+			ppp_operation_reg |= PPP_OP_LUT_C0_ON;
+		}
+	}
+
+	ppp_src_cfg_reg |= (iBuf->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0;
+	ppp_src_cfg_reg |= (iBuf->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
+
+	if (req->flags & MDP_DEINTERLACE)
+		ppp_operation_reg |= PPP_OP_DEINT_EN;
+
+	/* Dither at DMA side only since iBuf format is RGB888 */
+	if (iBuf->mdpImg.mdpOp & MDPOP_DITHER)
+		ppp_operation_reg |= PPP_OP_DITHER_EN;
+
+	if (iBuf->mdpImg.mdpOp & MDPOP_ROTATION) {
+		ppp_operation_reg |= PPP_OP_ROT_ON;
+
+		if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+			ppp_operation_reg |= PPP_OP_ROT_90;
+		}
+		if (iBuf->mdpImg.mdpOp & MDPOP_LR) {
+			ppp_operation_reg |= PPP_OP_FLIP_LR;
+		}
+		if (iBuf->mdpImg.mdpOp & MDPOP_UD) {
+			ppp_operation_reg |= PPP_OP_FLIP_UD;
+		}
+	}
+
+	src0_ystride = src_width * inpBpp;
+	dest0_ystride = iBuf->ibuf_width * iBuf->bpp;
+
+	/* no need to care about rotation since it's the real-XY. */
+	dst_roi_width = iBuf->roi.dst_width;
+	dst_roi_height = iBuf->roi.dst_height;
+
+	src0 = (uint8 *) iBuf->mdpImg.bmy_addr;
+	dest0 = (uint8 *) iBuf->buf;
+
+	/* Jumping from Y-Plane to Chroma Plane */
+	dest1 = mdp_get_chroma_addr(iBuf);
+
+	/* first pixel addr calculation */
+	mdp_adjust_start_addr(&src0, &src1, sv_slice, sh_slice, iBuf->roi.x,
+			      iBuf->roi.y, src_width, src_height, inpBpp, iBuf,
+			      0);
+	mdp_adjust_start_addr(&dest0, &dest1, dv_slice, dh_slice,
+			      iBuf->roi.lcd_x, iBuf->roi.lcd_y,
+			      iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
+			      iBuf, 2);
+
+	/* set scale operation */
+	mdp_set_scale(iBuf, dst_roi_width, dst_roi_height,
+		      inputRGB, outputRGB, &ppp_operation_reg);
+
+	/*
+	 * setting background source for blending
+	 */
+	mdp_set_blend_attr(iBuf, &alpha, &tpVal, perPixelAlpha,
+			   &ppp_operation_reg);
+
+	if (ppp_operation_reg & PPP_OP_BLEND_ON) {
+		mdp_ppp_setbg(iBuf);
+
+		if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
+			ppp_operation_reg |= PPP_OP_BG_CHROMA_H2V1;
+
+			if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
+				tpVal = mdp_conv_matx_rgb2yuv(tpVal,
+						      (uint16 *) &
+						      mdp_ccs_rgb2yuv,
+						      &mdp_plv[0], NULL);
+			}
+		}
+	}
+
+	/*
+	 * 0x0004: enable dbg bus
+	 * 0x0100: "don't care" Edge Condit until scaling is on
+	 * 0x0104: xrc tile x&y size u7.6 format = 7bit.6bit
+	 * 0x0108: src pixel size
+	 * 0x010c: component plane 0 starting address
+	 * 0x011c: component plane 0 ystride
+	 * 0x0124: PPP source config register
+	 * 0x0128: unpacked pattern from lsb to msb (eg. RGB->BGR)
+	 */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0108, (iBuf->roi.height << 16 |
+						      iBuf->roi.width));
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c,
+		 (src0_ystride << 16 | src0_ystride));
+
+	/* setup for rgb 565 */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0128, packPattern);
+	/*
+	 * 0x0138: PPP destination operation register
+	 * 0x014c: constant_alpha|transparent_color
+	 * 0x0150: PPP destination config register
+	 * 0x0154: PPP packing pattern
+	 */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0138, ppp_operation_reg);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x014c, alpha << 24 | tpVal);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0150, ppp_dst_cfg_reg);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0154, dst_packPattern);
+
+	/*
+	 * 0x0164: ROI height and width
+	 * 0x0168: Component Plane 0 starting addr
+	 * 0x016c: Component Plane 1 starting addr
+	 * 0x0178: Component Plane 1/0 y stride
+	 */
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0164,
+		 (dst_roi_height << 16 | dst_roi_width));
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0168, dest0);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x016c, dest1);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0178,
+		 (dest0_ystride << 16 | dest0_ystride));
+
+	flush_imgs(req, inpBpp, iBuf->bpp, p_src_file, p_dst_file);
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+	mdp_ppp_process_curr_djob();
+#else
+	mdp_pipe_kickoff(MDP_PPP_TERM, mfd);
+#endif
+}
+
+static int mdp_ppp_verify_req(struct mdp_blit_req *req)
+{
+	u32 src_width, src_height, dst_width, dst_height;
+
+	if (req == NULL)
+		return -1;
+
+	if (MDP_IS_IMGTYPE_BAD(req->src.format) ||
+	    MDP_IS_IMGTYPE_BAD(req->dst.format))
+		return -1;
+
+	if ((req->src.width == 0) || (req->src.height == 0) ||
+	    (req->src_rect.w == 0) || (req->src_rect.h == 0) ||
+	    (req->dst.width == 0) || (req->dst.height == 0) ||
+	    (req->dst_rect.w == 0) || (req->dst_rect.h == 0))
+
+		return -1;
+
+	if (((req->src_rect.x + req->src_rect.w) > req->src.width) ||
+	    ((req->src_rect.y + req->src_rect.h) > req->src.height))
+		return -1;
+
+	if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) ||
+	    ((req->dst_rect.y + req->dst_rect.h) > req->dst.height))
+		return -1;
+
+	/*
+	 * scaling range check
+	 */
+	src_width = req->src_rect.w;
+	src_height = req->src_rect.h;
+
+	if (req->flags & MDP_ROT_90) {
+		dst_width = req->dst_rect.h;
+		dst_height = req->dst_rect.w;
+	} else {
+		dst_width = req->dst_rect.w;
+		dst_height = req->dst_rect.h;
+	}
+
+	switch (req->dst.format) {
+	case MDP_Y_CRCB_H2V2:
+	case MDP_Y_CBCR_H2V2:
+		src_width = (src_width / 2) * 2;
+		src_height = (src_height / 2) * 2;
+		dst_width = (src_width / 2) * 2;
+		dst_height = (src_height / 2) * 2;
+		break;
+
+	case MDP_Y_CRCB_H2V1:
+	case MDP_Y_CBCR_H2V1:
+	case MDP_YCRYCB_H2V1:
+		src_width = (src_width / 2) * 2;
+		dst_width = (src_width / 2) * 2;
+		break;
+
+	default:
+		break;
+	}
+
+	if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width >
+	     MDP_MAX_X_SCALE_FACTOR)
+	    || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width <
+		MDP_MIN_X_SCALE_FACTOR))
+		return -1;
+
+	if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height >
+	     MDP_MAX_Y_SCALE_FACTOR)
+	    || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height <
+		MDP_MIN_Y_SCALE_FACTOR))
+		return -1;
+
+	return 0;
+}
+
+/**
+ * get_gem_img() - retrieve drm obj's start address and size
+ * @img:	contains drm file descriptor and gem handle
+ * @start:	repository of starting address of drm obj allocated memory
+ * @len:	repository of size of drm obj alloacted memory
+ *
+ **/
+int get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len)
+{
+	panic("waaaaaaaah");
+	//return kgsl_gem_obj_addr(img->memory_id, (int)img->priv, start, len);
+}
+
+int get_img(struct mdp_img *img, struct fb_info *info, unsigned long *start,
+	    unsigned long *len, struct file **pp_file)
+{
+	int put_needed, ret = 0;
+	struct file *file;
+	unsigned long vstart;
+#ifdef CONFIG_ANDROID_PMEM
+	if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
+		return 0;
+#endif
+	file = fget_light(img->memory_id, &put_needed);
+	if (file == NULL)
+		return -1;
+
+	if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+		*start = info->fix.smem_start;
+		*len = info->fix.smem_len;
+		*pp_file = file;
+	} else {
+		ret = -1;
+		fput_light(file, put_needed);
+	}
+	return ret;
+}
+
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
+	struct file **pp_src_file, struct file **pp_dst_file)
+{
+	unsigned long src_start, dst_start;
+	unsigned long src_len = 0;
+	unsigned long dst_len = 0;
+	MDPIBUF iBuf;
+	u32 dst_width, dst_height;
+	struct file *p_src_file = 0 , *p_dst_file = 0;
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+	if (req->dst.format == MDP_FB_FORMAT)
+		req->dst.format =  mfd->fb_imgType;
+	if (req->src.format == MDP_FB_FORMAT)
+		req->src.format = mfd->fb_imgType;
+
+	if (req->flags & MDP_BLIT_SRC_GEM) {
+		if (get_gem_img(&req->src, &src_start, &src_len) < 0)
+			return -1;
+	} else {
+		get_img(&req->src, info, &src_start, &src_len, &p_src_file);
+	}
+	if (src_len == 0) {
+		printk(KERN_ERR "mdp_ppp: could not retrieve image from "
+		       "memory\n");
+		return -1;
+	}
+
+	if (req->flags & MDP_BLIT_DST_GEM) {
+		if (get_gem_img(&req->dst, &dst_start, &dst_len) < 0)
+			return -1;
+	} else {
+		get_img(&req->dst, info, &dst_start, &dst_len, &p_dst_file);
+	}
+	if (dst_len == 0) {
+		printk(KERN_ERR "mdp_ppp: could not retrieve image from "
+		       "memory\n");
+		return -1;
+	}
+	*pp_src_file = p_src_file;
+	*pp_dst_file = p_dst_file;
+	if (mdp_ppp_verify_req(req)) {
+		printk(KERN_ERR "mdp_ppp: invalid image!\n");
+		return -1;
+	}
+
+	iBuf.ibuf_width = req->dst.width;
+	iBuf.ibuf_height = req->dst.height;
+	iBuf.bpp = bytes_per_pixel[req->dst.format];
+
+	iBuf.ibuf_type = req->dst.format;
+	iBuf.buf = (uint8 *) dst_start;
+	iBuf.buf += req->dst.offset;
+
+	iBuf.roi.lcd_x = req->dst_rect.x;
+	iBuf.roi.lcd_y = req->dst_rect.y;
+	iBuf.roi.dst_width = req->dst_rect.w;
+	iBuf.roi.dst_height = req->dst_rect.h;
+
+	iBuf.roi.x = req->src_rect.x;
+	iBuf.roi.width = req->src_rect.w;
+	iBuf.roi.y = req->src_rect.y;
+	iBuf.roi.height = req->src_rect.h;
+
+	iBuf.mdpImg.width = req->src.width;
+	iBuf.mdpImg.imgType = req->src.format;
+
+	iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset);
+	iBuf.mdpImg.cbcr_addr =
+	    (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
+			req->src.width * req->src.height);
+
+	iBuf.mdpImg.mdpOp = MDPOP_NOP;
+
+	/* blending check */
+	if (req->transp_mask != MDP_TRANSP_NOP) {
+		iBuf.mdpImg.mdpOp |= MDPOP_TRANSP;
+		iBuf.mdpImg.tpVal = req->transp_mask;
+		iBuf.mdpImg.tpVal = mdp_calc_tpval(&iBuf.mdpImg);
+	}
+
+	req->alpha &= 0xff;
+	if (req->alpha < MDP_ALPHA_NOP) {
+		iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB;
+		iBuf.mdpImg.alpha = req->alpha;
+	}
+
+	/* rotation check */
+	if (req->flags & MDP_FLIP_LR)
+		iBuf.mdpImg.mdpOp |= MDPOP_LR;
+	if (req->flags & MDP_FLIP_UD)
+		iBuf.mdpImg.mdpOp |= MDPOP_UD;
+	if (req->flags & MDP_ROT_90)
+		iBuf.mdpImg.mdpOp |= MDPOP_ROT90;
+	if (req->flags & MDP_DITHER)
+		iBuf.mdpImg.mdpOp |= MDPOP_DITHER;
+
+	if (req->flags & MDP_BLEND_FG_PREMULT) {
+#ifdef CONFIG_FB_MSM_MDP31
+		iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA;
+#else
+		return -EINVAL;
+#endif
+	}
+
+	if (req->flags & MDP_DEINTERLACE) {
+#ifdef CONFIG_FB_MSM_MDP31
+		if ((req->src.format != MDP_Y_CBCR_H2V2) &&
+			(req->src.format != MDP_Y_CRCB_H2V2))
+#endif
+		return -EINVAL;
+	}
+
+	/* scale check */
+	if (req->flags & MDP_ROT_90) {
+		dst_width = req->dst_rect.h;
+		dst_height = req->dst_rect.w;
+	} else {
+		dst_width = req->dst_rect.w;
+		dst_height = req->dst_rect.h;
+	}
+
+	if ((iBuf.roi.width != dst_width) || (iBuf.roi.height != dst_height))
+		iBuf.mdpImg.mdpOp |= MDPOP_ASCALE;
+
+	if (req->flags & MDP_BLUR) {
+#ifdef CONFIG_FB_MSM_MDP31
+		if (req->flags & MDP_SHARPENING)
+			printk(KERN_WARNING
+				"mdp: MDP_SHARPENING is set with MDP_BLUR!\n");
+		req->flags |= MDP_SHARPENING;
+		req->sharpening_strength = -127;
+#else
+		iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_BLUR;
+
+#endif
+	}
+
+	if (req->flags & MDP_SHARPENING) {
+#ifdef CONFIG_FB_MSM_MDP31
+		if ((req->sharpening_strength > 127) ||
+			(req->sharpening_strength < -127)) {
+			printk(KERN_ERR
+				"%s: sharpening strength out of range\n",
+				__func__);
+			return -EINVAL;
+		}
+
+		iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING;
+		iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff;
+#else
+		return -EINVAL;
+#endif
+	}
+
+	down(&mdp_ppp_mutex);
+	/* MDP cmd block enable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifdef CONFIG_FB_MSM_MDP31
+	mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+#else
+	/* bg tile fetching HW workaround */
+	if (((iBuf.mdpImg.mdpOp & (MDPOP_TRANSP | MDPOP_ALPHAB)) ||
+	     (req->src.format == MDP_ARGB_8888) ||
+	     (req->src.format == MDP_BGRA_8888) ||
+	     (req->src.format == MDP_RGBA_8888)) &&
+	    (iBuf.mdpImg.mdpOp & MDPOP_ROT90) && (req->dst_rect.w <= 16)) {
+		int dst_h, src_w, i;
+
+		src_w = req->src_rect.w;
+		dst_h = iBuf.roi.dst_height;
+
+		for (i = 0; i < (req->dst_rect.h / 16); i++) {
+			/* this tile size */
+			iBuf.roi.dst_height = 16;
+			iBuf.roi.width =
+			    (16 * req->src_rect.w) / req->dst_rect.h;
+
+			/* if it's out of scale range... */
+			if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+			     iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR)
+				iBuf.roi.width =
+				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+				    MDP_MAX_X_SCALE_FACTOR;
+			else if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+				  iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR)
+				iBuf.roi.width =
+				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+				    MDP_MIN_X_SCALE_FACTOR;
+
+			mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+
+			/* next tile location */
+			iBuf.roi.lcd_y += 16;
+			iBuf.roi.x += iBuf.roi.width;
+
+			/* this is for a remainder update */
+			dst_h -= 16;
+			src_w -= iBuf.roi.width;
+		}
+
+		if ((dst_h < 0) || (src_w < 0))
+			printk
+			    ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n",
+			     __LINE__);
+
+		/* remainder update */
+		if ((dst_h > 0) && (src_w > 0)) {
+			u32 tmp_v;
+
+			iBuf.roi.dst_height = dst_h;
+			iBuf.roi.width = src_w;
+
+			if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+			     iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) {
+				tmp_v =
+				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+				    MDP_MAX_X_SCALE_FACTOR +
+				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
+				    MDP_MAX_X_SCALE_FACTOR ? 1 : 0;
+
+				/* move x location as roi width gets bigger */
+				iBuf.roi.x -= tmp_v - iBuf.roi.width;
+				iBuf.roi.width = tmp_v;
+			} else
+			    if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+				 iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) {
+				tmp_v =
+				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+				    MDP_MIN_X_SCALE_FACTOR +
+				    (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
+				    MDP_MIN_X_SCALE_FACTOR ? 1 : 0;
+
+				/*
+				 * we don't move x location for continuity of
+				 * source image
+				 */
+				iBuf.roi.width = tmp_v;
+			}
+
+			mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+		}
+	} else {
+		mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+	}
+#endif
+
+	/* MDP cmd block disable */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	up(&mdp_ppp_mutex);
+
+	return 0;
+}

+ 347 - 0
drivers/staging/msm/mdp_ppp_dq.c

@@ -0,0 +1,347 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "mdp.h"
+
+static boolean mdp_ppp_intr_flag = FALSE;
+static boolean mdp_ppp_busy_flag = FALSE;
+
+/* Queue to keep track of the completed jobs for cleaning */
+static LIST_HEAD(mdp_ppp_djob_clnrq);
+static DEFINE_SPINLOCK(mdp_ppp_djob_clnrq_lock);
+
+/* Worker to cleanup Display Jobs */
+static struct workqueue_struct *mdp_ppp_djob_clnr;
+
+/* Display Queue (DQ) for MDP PPP Block */
+static LIST_HEAD(mdp_ppp_dq);
+static DEFINE_SPINLOCK(mdp_ppp_dq_lock);
+
+/* Current Display Job for MDP PPP */
+static struct mdp_ppp_djob *curr_djob;
+
+/* Track ret code for the last opeartion */
+static int mdp_ppp_ret_code;
+
+inline int mdp_ppp_get_ret_code(void)
+{
+	return mdp_ppp_ret_code;
+}
+
+/* Push <Reg, Val> pair into DQ (if available) to later
+ * program the MDP PPP Block */
+inline void mdp_ppp_outdw(uint32_t addr, uint32_t data)
+{
+	if (curr_djob) {
+
+		/* get the last node of the list. */
+		struct mdp_ppp_roi_cmd_set *node =
+			list_entry(curr_djob->roi_cmd_list.prev,
+				struct mdp_ppp_roi_cmd_set, node);
+
+		/* If a node is already full, create a new one and add it to
+		 * the list (roi_cmd_list).
+		 */
+		if (node->ncmds == MDP_PPP_ROI_NODE_SIZE) {
+			node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set),
+				GFP_KERNEL);
+			if (!node) {
+				printk(KERN_ERR
+					"MDP_PPP: not enough memory.\n");
+				mdp_ppp_ret_code = -EINVAL;
+				return;
+			}
+
+			/* no ROI commands initially */
+			node->ncmds = 0;
+
+			/* add one node to roi_cmd_list. */
+			list_add_tail(&node->node, &curr_djob->roi_cmd_list);
+		}
+
+		/* register ROI commands */
+		node->cmd[node->ncmds].reg = addr;
+		node->cmd[node->ncmds].val = data;
+		node->ncmds++;
+	} else
+		/* program MDP PPP block now */
+		outpdw((addr), (data));
+}
+
+/* Initialize DQ */
+inline void mdp_ppp_dq_init(void)
+{
+	mdp_ppp_djob_clnr = create_singlethread_workqueue("MDPDJobClnrThrd");
+}
+
+/* Release resources of a job (DJob). */
+static void mdp_ppp_del_djob(struct mdp_ppp_djob *job)
+{
+	struct mdp_ppp_roi_cmd_set *node, *tmp;
+
+	/* release mem */
+	mdp_ppp_put_img(job->p_src_file, job->p_dst_file);
+
+	/* release roi_cmd_list */
+	list_for_each_entry_safe(node, tmp, &job->roi_cmd_list, node) {
+		list_del(&node->node);
+		kfree(node);
+	}
+
+	/* release job struct */
+	kfree(job);
+}
+
+/* Worker thread to reclaim resources once a display job is done */
+static void mdp_ppp_djob_cleaner(struct work_struct *work)
+{
+	struct mdp_ppp_djob *job;
+
+	MDP_PPP_DEBUG_MSG("mdp ppp display job cleaner started \n");
+
+	/* cleanup display job */
+	job = container_of(work, struct mdp_ppp_djob, cleaner.work);
+	if (likely(work && job))
+		mdp_ppp_del_djob(job);
+}
+
+/* Create a new Display Job (DJob) */
+inline struct mdp_ppp_djob *mdp_ppp_new_djob(void)
+{
+	struct mdp_ppp_djob *job;
+	struct mdp_ppp_roi_cmd_set *node;
+
+	/* create a new djob */
+	job = kmalloc(sizeof(struct mdp_ppp_djob), GFP_KERNEL);
+	if (!job)
+		return NULL;
+
+	/* add the first node to curr_djob->roi_cmd_list */
+	node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set), GFP_KERNEL);
+	if (!node) {
+		kfree(job);
+		return NULL;
+	}
+
+	/* make this current djob container to keep track of the curr djob not
+	 * used in the async path i.e. no sync needed
+	 *
+	 * Should not contain any references from the past djob
+	 */
+	BUG_ON(curr_djob);
+	curr_djob = job;
+	INIT_LIST_HEAD(&curr_djob->roi_cmd_list);
+
+	/* no ROI commands initially */
+	node->ncmds = 0;
+	INIT_LIST_HEAD(&node->node);
+	list_add_tail(&node->node, &curr_djob->roi_cmd_list);
+
+	/* register this djob with the djob cleaner
+	 * initializes 'work' data struct
+	 */
+	INIT_DELAYED_WORK(&curr_djob->cleaner, mdp_ppp_djob_cleaner);
+	INIT_LIST_HEAD(&curr_djob->entry);
+
+	curr_djob->p_src_file = 0;
+	curr_djob->p_dst_file = 0;
+
+	return job;
+}
+
+/* Undo the effect of mdp_ppp_new_djob() */
+inline void mdp_ppp_clear_curr_djob(void)
+{
+	if (likely(curr_djob)) {
+		mdp_ppp_del_djob(curr_djob);
+		curr_djob = NULL;
+	}
+}
+
+/* Cleanup dirty djobs */
+static void mdp_ppp_flush_dirty_djobs(void *cond)
+{
+	unsigned long flags;
+	struct mdp_ppp_djob *job;
+
+	/* Flush the jobs from the djob clnr queue */
+	while (cond && test_bit(0, (unsigned long *)cond)) {
+
+		/* Until we are done with the cleanup queue */
+		spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags);
+		if (list_empty(&mdp_ppp_djob_clnrq)) {
+			spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
+			break;
+		}
+
+		MDP_PPP_DEBUG_MSG("flushing djobs ... loop \n");
+
+		/* Retrieve the job that needs to be cleaned */
+		job = list_entry(mdp_ppp_djob_clnrq.next,
+				struct mdp_ppp_djob, entry);
+		list_del_init(&job->entry);
+		spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
+
+		/* Keep mem state coherent */
+		msm_fb_ensure_mem_coherency_after_dma(job->info, &job->req, 1);
+
+		/* Schedule jobs for cleanup
+		 * A seperate worker thread does this */
+		queue_delayed_work(mdp_ppp_djob_clnr, &job->cleaner,
+			mdp_timer_duration);
+	}
+}
+
+/* If MDP PPP engine is busy, wait until it is available again */
+void mdp_ppp_wait(void)
+{
+	unsigned long flags;
+	int cond = 1;
+
+	/* keep flushing dirty djobs as long as MDP PPP engine is busy */
+	mdp_ppp_flush_dirty_djobs(&mdp_ppp_busy_flag);
+
+	/* block if MDP PPP engine is still busy */
+	spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+	if (test_bit(0, (unsigned long *)&mdp_ppp_busy_flag)) {
+
+		/* prepare for the wakeup event */
+		test_and_set_bit(0, (unsigned long *)&mdp_ppp_waiting);
+		INIT_COMPLETION(mdp_ppp_comp);
+		spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+		/* block uninterruptibly until available */
+		MDP_PPP_DEBUG_MSG("waiting for mdp... \n");
+		wait_for_completion_killable(&mdp_ppp_comp);
+
+		/* if MDP PPP engine is still free,
+		 * disable INT_MDP if enabled
+		 */
+		spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+		if (!test_bit(0, (unsigned long *)&mdp_ppp_busy_flag) &&
+		test_and_clear_bit(0, (unsigned long *)&mdp_ppp_intr_flag))
+			mdp_disable_irq(MDP_PPP_TERM);
+	}
+	spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+	/* flush remaining dirty djobs, if any */
+	mdp_ppp_flush_dirty_djobs(&cond);
+}
+
+/* Program MDP PPP block to process this ROI */
+static void mdp_ppp_process_roi(struct list_head *roi_cmd_list)
+{
+
+	/* program PPP engine with registered ROI commands */
+	struct mdp_ppp_roi_cmd_set *node;
+	list_for_each_entry(node, roi_cmd_list, node) {
+		int i = 0;
+		for (; i < node->ncmds; i++) {
+			MDP_PPP_DEBUG_MSG("%d: reg: 0x%x val: 0x%x \n",
+					i, node->cmd[i].reg, node->cmd[i].val);
+			outpdw(node->cmd[i].reg, node->cmd[i].val);
+		}
+	}
+
+	/* kickoff MDP PPP engine */
+	MDP_PPP_DEBUG_MSG("kicking off mdp \n");
+	outpdw(MDP_BASE + 0x30, 0x1000);
+}
+
+/* Submit this display job to MDP PPP engine */
+static void mdp_ppp_dispatch_djob(struct mdp_ppp_djob *job)
+{
+	/* enable INT_MDP if disabled */
+	if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_intr_flag))
+		mdp_enable_irq(MDP_PPP_TERM);
+
+	/* turn on PPP and CMD blocks */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+	/* process this ROI */
+	mdp_ppp_process_roi(&job->roi_cmd_list);
+}
+
+/* Enqueue this display job to be cleaned up later in "mdp_ppp_djob_done" */
+static inline void mdp_ppp_enqueue_djob(struct mdp_ppp_djob *job)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+	list_add_tail(&job->entry, &mdp_ppp_dq);
+	spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+}
+
+/* First enqueue display job for cleanup and dispatch immediately
+ * if MDP PPP engine is free */
+void mdp_ppp_process_curr_djob(void)
+{
+	/* enqueue djob */
+	mdp_ppp_enqueue_djob(curr_djob);
+
+	/* dispatch now if MDP PPP engine is free */
+	if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_busy_flag))
+		mdp_ppp_dispatch_djob(curr_djob);
+
+	/* done with the current djob */
+	curr_djob = NULL;
+}
+
+/* Called from mdp_isr - cleanup finished job and start with next
+ * if available else set MDP PPP engine free */
+void mdp_ppp_djob_done(void)
+{
+	struct mdp_ppp_djob *curr, *next;
+	unsigned long flags;
+
+	/* dequeue current */
+	spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+	curr = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob, entry);
+	list_del_init(&curr->entry);
+	spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+	/* cleanup current - enqueue in the djob clnr queue */
+	spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags);
+	list_add_tail(&curr->entry, &mdp_ppp_djob_clnrq);
+	spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags);
+
+	/* grab next pending */
+	spin_lock_irqsave(&mdp_ppp_dq_lock, flags);
+	if (!list_empty(&mdp_ppp_dq)) {
+		next = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob,
+			entry);
+		spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+		/* process next in the queue */
+		mdp_ppp_process_roi(&next->roi_cmd_list);
+	} else {
+		/* no pending display job */
+		spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags);
+
+		/* turn off PPP and CMD blocks - "in_isr" is TRUE */
+		mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+
+		/* notify if waiting */
+		if (test_and_clear_bit(0, (unsigned long *)&mdp_ppp_waiting))
+			complete(&mdp_ppp_comp);
+
+		/* set free */
+		test_and_clear_bit(0, (unsigned long *)&mdp_ppp_busy_flag);
+	}
+}

+ 86 - 0
drivers/staging/msm/mdp_ppp_dq.h

@@ -0,0 +1,86 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MDP_PPP_DQ_H
+#define MDP_PPP_DQ_H
+
+#include "msm_fb_def.h"
+
+#define MDP_PPP_DEBUG_MSG MSM_FB_DEBUG
+
+/* The maximum number of <Reg,Val> pairs in an mdp_ppp_roi_cmd_set structure (a
+ * node)
+ */
+#define MDP_PPP_ROI_NODE_SIZE 32
+
+/* ROI config command (<Reg,Val> pair) for MDP PPP block */
+struct mdp_ppp_roi_cmd {
+	uint32_t reg;
+	uint32_t val;
+};
+
+/* ROI config commands for MDP PPP block are stored in a list of
+ * mdp_ppp_roi_cmd_set structures (nodes).
+ */
+struct mdp_ppp_roi_cmd_set {
+	struct list_head node;
+	uint32_t ncmds; /* number of commands in this set (node). */
+	struct mdp_ppp_roi_cmd cmd[MDP_PPP_ROI_NODE_SIZE];
+};
+
+/* MDP PPP Display Job (DJob) */
+struct mdp_ppp_djob {
+	struct list_head entry;
+	/* One ROI per MDP PPP DJob */
+	struct list_head roi_cmd_list;
+	struct mdp_blit_req req;
+	struct fb_info *info;
+	struct delayed_work cleaner;
+	struct file *p_src_file, *p_dst_file;
+};
+
+extern struct completion mdp_ppp_comp;
+extern boolean mdp_ppp_waiting;
+extern unsigned long mdp_timer_duration;
+
+unsigned int mdp_ppp_async_op_get(void);
+void mdp_ppp_async_op_set(unsigned int flag);
+void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info,
+	struct mdp_blit_req *req_list, int req_list_count);
+void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file);
+void mdp_ppp_dq_init(void);
+void mdp_ppp_outdw(uint32_t addr, uint32_t data);
+struct mdp_ppp_djob *mdp_ppp_new_djob(void);
+void mdp_ppp_clear_curr_djob(void);
+void mdp_ppp_process_curr_djob(void);
+int mdp_ppp_get_ret_code(void);
+void mdp_ppp_djob_done(void);
+void mdp_ppp_wait(void);
+
+#endif /* MDP_PPP_DQ_H */

+ 2486 - 0
drivers/staging/msm/mdp_ppp_v20.c

@@ -0,0 +1,2486 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <asm/div64.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+static MDP_SCALE_MODE mdp_curr_up_scale_xy;
+static MDP_SCALE_MODE mdp_curr_down_scale_x;
+static MDP_SCALE_MODE mdp_curr_down_scale_y;
+
+static long long mdp_do_div(long long num, long long den)
+{
+	do_div(num, den);
+	return num;
+}
+
+struct mdp_table_entry mdp_gaussian_blur_table[] = {
+	/* max variance */
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50280, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50284, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50288, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5028c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50290, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50294, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50298, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5029c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502a0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502a4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502a8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502ac, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502b0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502b4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502b8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502bc, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502c0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502c4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502c8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502cc, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502d0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502d4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502d8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502dc, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502e0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502e4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502e8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502ec, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502f0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502f4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502f8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502fc, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50300, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50304, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50308, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5030c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50310, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50314, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50318, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5031c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50320, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50324, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50328, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5032c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50330, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50334, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50338, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5033c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50340, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50344, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50348, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5034c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50350, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50354, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50358, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5035c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50360, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50364, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50368, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5036c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50370, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50374, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50378, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5037c, 0x20000080 },
+};
+
+static void load_scale_table(
+	struct mdp_table_entry *table, int len)
+{
+	int i;
+	for (i = 0; i < len; i++)
+		MDP_OUTP(MDP_BASE + table[i].reg, table[i].val);
+}
+
+static void mdp_load_pr_upscale_table(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50204, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50208, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5020c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50210, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50214, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50218, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5021c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50220, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50224, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50228, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5022c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50230, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50234, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50238, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5023c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50240, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50244, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50248, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5024c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50250, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50254, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50258, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5025c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50260, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50264, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50268, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5026c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50270, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50274, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50278, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5027c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point2TOpoint4(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point2TOpoint4(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point4TOpoint6(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point4TOpoint6(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point6TOpoint8(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point6TOpoint8(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_x_point8TO1(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502c0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502c4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502c8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502cc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502d0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502d4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502d8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502dc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502e0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502e4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502e8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502ec, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502f0, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502f4, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502f8, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x502fc, 0x0);
+}
+
+static void mdp_load_pr_downscale_table_y_point8TO1(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50340, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50344, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50348, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5034c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50350, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50354, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50358, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5035c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50360, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50364, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50368, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5036c, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50370, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50374, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x50378, 0x0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff);
+	MDP_OUTP(MDP_BASE + 0x5037c, 0x0);
+}
+
+static void mdp_load_bc_upscale_table(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
+	MDP_OUTP(MDP_BASE + 0x50204, 0x7ec003f9);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
+	MDP_OUTP(MDP_BASE + 0x50208, 0x7d4003f3);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
+	MDP_OUTP(MDP_BASE + 0x5020c, 0x7b8003ed);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
+	MDP_OUTP(MDP_BASE + 0x50210, 0x794003e8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
+	MDP_OUTP(MDP_BASE + 0x50214, 0x76c003e4);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
+	MDP_OUTP(MDP_BASE + 0x50218, 0x73c003e0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
+	MDP_OUTP(MDP_BASE + 0x5021c, 0x708003de);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
+	MDP_OUTP(MDP_BASE + 0x50220, 0x6d0003db);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
+	MDP_OUTP(MDP_BASE + 0x50224, 0x698003d9);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
+	MDP_OUTP(MDP_BASE + 0x50228, 0x654003d8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
+	MDP_OUTP(MDP_BASE + 0x5022c, 0x610003d7);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
+	MDP_OUTP(MDP_BASE + 0x50230, 0x5c8003d7);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
+	MDP_OUTP(MDP_BASE + 0x50234, 0x580003d7);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
+	MDP_OUTP(MDP_BASE + 0x50238, 0x534003d8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
+	MDP_OUTP(MDP_BASE + 0x5023c, 0x4e8003d8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
+	MDP_OUTP(MDP_BASE + 0x50240, 0x494003da);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
+	MDP_OUTP(MDP_BASE + 0x50244, 0x448003db);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
+	MDP_OUTP(MDP_BASE + 0x50248, 0x3f4003dd);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
+	MDP_OUTP(MDP_BASE + 0x5024c, 0x3a4003df);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
+	MDP_OUTP(MDP_BASE + 0x50250, 0x354003e1);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
+	MDP_OUTP(MDP_BASE + 0x50254, 0x304003e3);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
+	MDP_OUTP(MDP_BASE + 0x50258, 0x2b0003e6);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
+	MDP_OUTP(MDP_BASE + 0x5025c, 0x260003e8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
+	MDP_OUTP(MDP_BASE + 0x50260, 0x214003eb);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
+	MDP_OUTP(MDP_BASE + 0x50264, 0x1c4003ee);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
+	MDP_OUTP(MDP_BASE + 0x50268, 0x17c003f1);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
+	MDP_OUTP(MDP_BASE + 0x5026c, 0x134003f3);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
+	MDP_OUTP(MDP_BASE + 0x50270, 0xf0003f6);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
+	MDP_OUTP(MDP_BASE + 0x50274, 0xac003f9);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
+	MDP_OUTP(MDP_BASE + 0x50278, 0x70003fb);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
+	MDP_OUTP(MDP_BASE + 0x5027c, 0x34003fe);
+}
+
+static void mdp_load_bc_downscale_table_x_point2TOpoint4(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084);
+	MDP_OUTP(MDP_BASE + 0x50280, 0x23400083);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084);
+	MDP_OUTP(MDP_BASE + 0x50284, 0x23000083);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084);
+	MDP_OUTP(MDP_BASE + 0x50288, 0x23000082);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085);
+	MDP_OUTP(MDP_BASE + 0x5028c, 0x23000081);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085);
+	MDP_OUTP(MDP_BASE + 0x50290, 0x23000080);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086);
+	MDP_OUTP(MDP_BASE + 0x50294, 0x22c0007f);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086);
+	MDP_OUTP(MDP_BASE + 0x50298, 0x2280007f);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086);
+	MDP_OUTP(MDP_BASE + 0x5029c, 0x2280007e);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086);
+	MDP_OUTP(MDP_BASE + 0x502a0, 0x2280007d);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086);
+	MDP_OUTP(MDP_BASE + 0x502a4, 0x2240007d);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087);
+	MDP_OUTP(MDP_BASE + 0x502a8, 0x2240007c);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087);
+	MDP_OUTP(MDP_BASE + 0x502ac, 0x2240007b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087);
+	MDP_OUTP(MDP_BASE + 0x502b0, 0x2200007b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088);
+	MDP_OUTP(MDP_BASE + 0x502b4, 0x22400079);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088);
+	MDP_OUTP(MDP_BASE + 0x502b8, 0x22400078);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088);
+	MDP_OUTP(MDP_BASE + 0x502bc, 0x22400077);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089);
+	MDP_OUTP(MDP_BASE + 0x502c0, 0x22000077);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089);
+	MDP_OUTP(MDP_BASE + 0x502c4, 0x22000076);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089);
+	MDP_OUTP(MDP_BASE + 0x502c8, 0x22000075);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088);
+	MDP_OUTP(MDP_BASE + 0x502cc, 0x21c00075);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089);
+	MDP_OUTP(MDP_BASE + 0x502d0, 0x21c00074);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089);
+	MDP_OUTP(MDP_BASE + 0x502d4, 0x21c00073);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089);
+	MDP_OUTP(MDP_BASE + 0x502d8, 0x21800073);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a);
+	MDP_OUTP(MDP_BASE + 0x502dc, 0x21800072);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a);
+	MDP_OUTP(MDP_BASE + 0x502e0, 0x21800071);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a);
+	MDP_OUTP(MDP_BASE + 0x502e4, 0x21800070);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b);
+	MDP_OUTP(MDP_BASE + 0x502e8, 0x2180006f);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c);
+	MDP_OUTP(MDP_BASE + 0x502ec, 0x2140006e);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c);
+	MDP_OUTP(MDP_BASE + 0x502f0, 0x2140006d);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c);
+	MDP_OUTP(MDP_BASE + 0x502f4, 0x2100006d);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c);
+	MDP_OUTP(MDP_BASE + 0x502f8, 0x2100006c);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d);
+	MDP_OUTP(MDP_BASE + 0x502fc, 0x2100006b);
+}
+
+static void mdp_load_bc_downscale_table_y_point2TOpoint4(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084);
+	MDP_OUTP(MDP_BASE + 0x50300, 0x23400083);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084);
+	MDP_OUTP(MDP_BASE + 0x50304, 0x23000083);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084);
+	MDP_OUTP(MDP_BASE + 0x50308, 0x23000082);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085);
+	MDP_OUTP(MDP_BASE + 0x5030c, 0x23000081);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085);
+	MDP_OUTP(MDP_BASE + 0x50310, 0x23000080);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086);
+	MDP_OUTP(MDP_BASE + 0x50314, 0x22c0007f);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086);
+	MDP_OUTP(MDP_BASE + 0x50318, 0x2280007f);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086);
+	MDP_OUTP(MDP_BASE + 0x5031c, 0x2280007e);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086);
+	MDP_OUTP(MDP_BASE + 0x50320, 0x2280007d);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086);
+	MDP_OUTP(MDP_BASE + 0x50324, 0x2240007d);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087);
+	MDP_OUTP(MDP_BASE + 0x50328, 0x2240007c);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087);
+	MDP_OUTP(MDP_BASE + 0x5032c, 0x2240007b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087);
+	MDP_OUTP(MDP_BASE + 0x50330, 0x2200007b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088);
+	MDP_OUTP(MDP_BASE + 0x50334, 0x22400079);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088);
+	MDP_OUTP(MDP_BASE + 0x50338, 0x22400078);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088);
+	MDP_OUTP(MDP_BASE + 0x5033c, 0x22400077);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089);
+	MDP_OUTP(MDP_BASE + 0x50340, 0x22000077);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089);
+	MDP_OUTP(MDP_BASE + 0x50344, 0x22000076);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089);
+	MDP_OUTP(MDP_BASE + 0x50348, 0x22000075);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088);
+	MDP_OUTP(MDP_BASE + 0x5034c, 0x21c00075);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089);
+	MDP_OUTP(MDP_BASE + 0x50350, 0x21c00074);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089);
+	MDP_OUTP(MDP_BASE + 0x50354, 0x21c00073);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089);
+	MDP_OUTP(MDP_BASE + 0x50358, 0x21800073);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a);
+	MDP_OUTP(MDP_BASE + 0x5035c, 0x21800072);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a);
+	MDP_OUTP(MDP_BASE + 0x50360, 0x21800071);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a);
+	MDP_OUTP(MDP_BASE + 0x50364, 0x21800070);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b);
+	MDP_OUTP(MDP_BASE + 0x50368, 0x2180006f);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c);
+	MDP_OUTP(MDP_BASE + 0x5036c, 0x2140006e);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c);
+	MDP_OUTP(MDP_BASE + 0x50370, 0x2140006d);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c);
+	MDP_OUTP(MDP_BASE + 0x50374, 0x2100006d);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c);
+	MDP_OUTP(MDP_BASE + 0x50378, 0x2100006c);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d);
+	MDP_OUTP(MDP_BASE + 0x5037c, 0x2100006b);
+}
+
+static void mdp_load_bc_downscale_table_x_point4TOpoint6(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c);
+	MDP_OUTP(MDP_BASE + 0x50280, 0x33800088);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e);
+	MDP_OUTP(MDP_BASE + 0x50284, 0x33400084);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092);
+	MDP_OUTP(MDP_BASE + 0x50288, 0x33000080);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094);
+	MDP_OUTP(MDP_BASE + 0x5028c, 0x3300007b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098);
+	MDP_OUTP(MDP_BASE + 0x50290, 0x32400077);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b);
+	MDP_OUTP(MDP_BASE + 0x50294, 0x32000073);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d);
+	MDP_OUTP(MDP_BASE + 0x50298, 0x31c0006f);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0);
+	MDP_OUTP(MDP_BASE + 0x5029c, 0x3140006b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2);
+	MDP_OUTP(MDP_BASE + 0x502a0, 0x31000067);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5);
+	MDP_OUTP(MDP_BASE + 0x502a4, 0x30800062);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8);
+	MDP_OUTP(MDP_BASE + 0x502a8, 0x2fc0005f);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa);
+	MDP_OUTP(MDP_BASE + 0x502ac, 0x2fc0005b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad);
+	MDP_OUTP(MDP_BASE + 0x502b0, 0x2f400057);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0);
+	MDP_OUTP(MDP_BASE + 0x502b4, 0x2e400054);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2);
+	MDP_OUTP(MDP_BASE + 0x502b8, 0x2e000050);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4);
+	MDP_OUTP(MDP_BASE + 0x502bc, 0x2d80004c);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6);
+	MDP_OUTP(MDP_BASE + 0x502c0, 0x2d000049);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8);
+	MDP_OUTP(MDP_BASE + 0x502c4, 0x2c800045);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9);
+	MDP_OUTP(MDP_BASE + 0x502c8, 0x2c000042);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd);
+	MDP_OUTP(MDP_BASE + 0x502cc, 0x2b40003e);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf);
+	MDP_OUTP(MDP_BASE + 0x502d0, 0x2a80003b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf);
+	MDP_OUTP(MDP_BASE + 0x502d4, 0x2a000039);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2);
+	MDP_OUTP(MDP_BASE + 0x502d8, 0x29400036);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4);
+	MDP_OUTP(MDP_BASE + 0x502dc, 0x28800032);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5);
+	MDP_OUTP(MDP_BASE + 0x502e0, 0x2800002f);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7);
+	MDP_OUTP(MDP_BASE + 0x502e4, 0x2740002c);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8);
+	MDP_OUTP(MDP_BASE + 0x502e8, 0x26c00029);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9);
+	MDP_OUTP(MDP_BASE + 0x502ec, 0x26000027);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc);
+	MDP_OUTP(MDP_BASE + 0x502f0, 0x25000024);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc);
+	MDP_OUTP(MDP_BASE + 0x502f4, 0x24800021);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd);
+	MDP_OUTP(MDP_BASE + 0x502f8, 0x23800020);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce);
+	MDP_OUTP(MDP_BASE + 0x502fc, 0x2300001d);
+}
+
+static void mdp_load_bc_downscale_table_y_point4TOpoint6(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c);
+	MDP_OUTP(MDP_BASE + 0x50300, 0x33800088);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e);
+	MDP_OUTP(MDP_BASE + 0x50304, 0x33400084);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092);
+	MDP_OUTP(MDP_BASE + 0x50308, 0x33000080);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094);
+	MDP_OUTP(MDP_BASE + 0x5030c, 0x3300007b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098);
+	MDP_OUTP(MDP_BASE + 0x50310, 0x32400077);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b);
+	MDP_OUTP(MDP_BASE + 0x50314, 0x32000073);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d);
+	MDP_OUTP(MDP_BASE + 0x50318, 0x31c0006f);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0);
+	MDP_OUTP(MDP_BASE + 0x5031c, 0x3140006b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2);
+	MDP_OUTP(MDP_BASE + 0x50320, 0x31000067);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5);
+	MDP_OUTP(MDP_BASE + 0x50324, 0x30800062);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8);
+	MDP_OUTP(MDP_BASE + 0x50328, 0x2fc0005f);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa);
+	MDP_OUTP(MDP_BASE + 0x5032c, 0x2fc0005b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad);
+	MDP_OUTP(MDP_BASE + 0x50330, 0x2f400057);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0);
+	MDP_OUTP(MDP_BASE + 0x50334, 0x2e400054);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2);
+	MDP_OUTP(MDP_BASE + 0x50338, 0x2e000050);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4);
+	MDP_OUTP(MDP_BASE + 0x5033c, 0x2d80004c);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6);
+	MDP_OUTP(MDP_BASE + 0x50340, 0x2d000049);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8);
+	MDP_OUTP(MDP_BASE + 0x50344, 0x2c800045);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9);
+	MDP_OUTP(MDP_BASE + 0x50348, 0x2c000042);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd);
+	MDP_OUTP(MDP_BASE + 0x5034c, 0x2b40003e);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf);
+	MDP_OUTP(MDP_BASE + 0x50350, 0x2a80003b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf);
+	MDP_OUTP(MDP_BASE + 0x50354, 0x2a000039);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2);
+	MDP_OUTP(MDP_BASE + 0x50358, 0x29400036);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4);
+	MDP_OUTP(MDP_BASE + 0x5035c, 0x28800032);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5);
+	MDP_OUTP(MDP_BASE + 0x50360, 0x2800002f);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7);
+	MDP_OUTP(MDP_BASE + 0x50364, 0x2740002c);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8);
+	MDP_OUTP(MDP_BASE + 0x50368, 0x26c00029);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9);
+	MDP_OUTP(MDP_BASE + 0x5036c, 0x26000027);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc);
+	MDP_OUTP(MDP_BASE + 0x50370, 0x25000024);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc);
+	MDP_OUTP(MDP_BASE + 0x50374, 0x24800021);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd);
+	MDP_OUTP(MDP_BASE + 0x50378, 0x23800020);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce);
+	MDP_OUTP(MDP_BASE + 0x5037c, 0x2300001d);
+}
+
+static void mdp_load_bc_downscale_table_x_point6TOpoint8(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070);
+	MDP_OUTP(MDP_BASE + 0x50280, 0x4bc00068);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078);
+	MDP_OUTP(MDP_BASE + 0x50284, 0x4bc00060);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080);
+	MDP_OUTP(MDP_BASE + 0x50288, 0x4b800059);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089);
+	MDP_OUTP(MDP_BASE + 0x5028c, 0x4b000052);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091);
+	MDP_OUTP(MDP_BASE + 0x50290, 0x4a80004b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a);
+	MDP_OUTP(MDP_BASE + 0x50294, 0x4a000044);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3);
+	MDP_OUTP(MDP_BASE + 0x50298, 0x4940003d);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac);
+	MDP_OUTP(MDP_BASE + 0x5029c, 0x48400037);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4);
+	MDP_OUTP(MDP_BASE + 0x502a0, 0x47800031);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd);
+	MDP_OUTP(MDP_BASE + 0x502a4, 0x4640002b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5);
+	MDP_OUTP(MDP_BASE + 0x502a8, 0x45000026);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce);
+	MDP_OUTP(MDP_BASE + 0x502ac, 0x43800021);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6);
+	MDP_OUTP(MDP_BASE + 0x502b0, 0x4240001c);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df);
+	MDP_OUTP(MDP_BASE + 0x502b4, 0x40800018);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6);
+	MDP_OUTP(MDP_BASE + 0x502b8, 0x3f000014);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee);
+	MDP_OUTP(MDP_BASE + 0x502bc, 0x3d400010);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5);
+	MDP_OUTP(MDP_BASE + 0x502c0, 0x3b80000c);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc);
+	MDP_OUTP(MDP_BASE + 0x502c4, 0x39800009);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102);
+	MDP_OUTP(MDP_BASE + 0x502c8, 0x37c00006);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109);
+	MDP_OUTP(MDP_BASE + 0x502cc, 0x35800004);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e);
+	MDP_OUTP(MDP_BASE + 0x502d0, 0x33800002);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114);
+	MDP_OUTP(MDP_BASE + 0x502d4, 0x31400000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119);
+	MDP_OUTP(MDP_BASE + 0x502d8, 0x2f4003fe);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e);
+	MDP_OUTP(MDP_BASE + 0x502dc, 0x2d0003fc);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121);
+	MDP_OUTP(MDP_BASE + 0x502e0, 0x2b0003fb);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125);
+	MDP_OUTP(MDP_BASE + 0x502e4, 0x28c003fa);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128);
+	MDP_OUTP(MDP_BASE + 0x502e8, 0x268003f9);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a);
+	MDP_OUTP(MDP_BASE + 0x502ec, 0x244003f9);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c);
+	MDP_OUTP(MDP_BASE + 0x502f0, 0x224003f8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e);
+	MDP_OUTP(MDP_BASE + 0x502f4, 0x200003f8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f);
+	MDP_OUTP(MDP_BASE + 0x502f8, 0x1e0003f8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f);
+	MDP_OUTP(MDP_BASE + 0x502fc, 0x1c0003f8);
+}
+
+static void mdp_load_bc_downscale_table_y_point6TOpoint8(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070);
+	MDP_OUTP(MDP_BASE + 0x50300, 0x4bc00068);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078);
+	MDP_OUTP(MDP_BASE + 0x50304, 0x4bc00060);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080);
+	MDP_OUTP(MDP_BASE + 0x50308, 0x4b800059);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089);
+	MDP_OUTP(MDP_BASE + 0x5030c, 0x4b000052);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091);
+	MDP_OUTP(MDP_BASE + 0x50310, 0x4a80004b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a);
+	MDP_OUTP(MDP_BASE + 0x50314, 0x4a000044);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3);
+	MDP_OUTP(MDP_BASE + 0x50318, 0x4940003d);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac);
+	MDP_OUTP(MDP_BASE + 0x5031c, 0x48400037);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4);
+	MDP_OUTP(MDP_BASE + 0x50320, 0x47800031);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd);
+	MDP_OUTP(MDP_BASE + 0x50324, 0x4640002b);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5);
+	MDP_OUTP(MDP_BASE + 0x50328, 0x45000026);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce);
+	MDP_OUTP(MDP_BASE + 0x5032c, 0x43800021);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6);
+	MDP_OUTP(MDP_BASE + 0x50330, 0x4240001c);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df);
+	MDP_OUTP(MDP_BASE + 0x50334, 0x40800018);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6);
+	MDP_OUTP(MDP_BASE + 0x50338, 0x3f000014);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee);
+	MDP_OUTP(MDP_BASE + 0x5033c, 0x3d400010);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5);
+	MDP_OUTP(MDP_BASE + 0x50340, 0x3b80000c);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc);
+	MDP_OUTP(MDP_BASE + 0x50344, 0x39800009);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102);
+	MDP_OUTP(MDP_BASE + 0x50348, 0x37c00006);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109);
+	MDP_OUTP(MDP_BASE + 0x5034c, 0x35800004);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e);
+	MDP_OUTP(MDP_BASE + 0x50350, 0x33800002);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114);
+	MDP_OUTP(MDP_BASE + 0x50354, 0x31400000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119);
+	MDP_OUTP(MDP_BASE + 0x50358, 0x2f4003fe);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e);
+	MDP_OUTP(MDP_BASE + 0x5035c, 0x2d0003fc);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121);
+	MDP_OUTP(MDP_BASE + 0x50360, 0x2b0003fb);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125);
+	MDP_OUTP(MDP_BASE + 0x50364, 0x28c003fa);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128);
+	MDP_OUTP(MDP_BASE + 0x50368, 0x268003f9);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a);
+	MDP_OUTP(MDP_BASE + 0x5036c, 0x244003f9);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c);
+	MDP_OUTP(MDP_BASE + 0x50370, 0x224003f8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e);
+	MDP_OUTP(MDP_BASE + 0x50374, 0x200003f8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f);
+	MDP_OUTP(MDP_BASE + 0x50378, 0x1e0003f8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f);
+	MDP_OUTP(MDP_BASE + 0x5037c, 0x1c0003f8);
+}
+
+static void mdp_load_bc_downscale_table_x_point8TO1(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
+	MDP_OUTP(MDP_BASE + 0x50284, 0x7ec003f9);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
+	MDP_OUTP(MDP_BASE + 0x50288, 0x7d4003f3);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
+	MDP_OUTP(MDP_BASE + 0x5028c, 0x7b8003ed);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
+	MDP_OUTP(MDP_BASE + 0x50290, 0x794003e8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
+	MDP_OUTP(MDP_BASE + 0x50294, 0x76c003e4);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
+	MDP_OUTP(MDP_BASE + 0x50298, 0x73c003e0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
+	MDP_OUTP(MDP_BASE + 0x5029c, 0x708003de);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
+	MDP_OUTP(MDP_BASE + 0x502a0, 0x6d0003db);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
+	MDP_OUTP(MDP_BASE + 0x502a4, 0x698003d9);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
+	MDP_OUTP(MDP_BASE + 0x502a8, 0x654003d8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
+	MDP_OUTP(MDP_BASE + 0x502ac, 0x610003d7);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
+	MDP_OUTP(MDP_BASE + 0x502b0, 0x5c8003d7);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
+	MDP_OUTP(MDP_BASE + 0x502b4, 0x580003d7);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
+	MDP_OUTP(MDP_BASE + 0x502b8, 0x534003d8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
+	MDP_OUTP(MDP_BASE + 0x502bc, 0x4e8003d8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
+	MDP_OUTP(MDP_BASE + 0x502c0, 0x494003da);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
+	MDP_OUTP(MDP_BASE + 0x502c4, 0x448003db);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
+	MDP_OUTP(MDP_BASE + 0x502c8, 0x3f4003dd);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
+	MDP_OUTP(MDP_BASE + 0x502cc, 0x3a4003df);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
+	MDP_OUTP(MDP_BASE + 0x502d0, 0x354003e1);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
+	MDP_OUTP(MDP_BASE + 0x502d4, 0x304003e3);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
+	MDP_OUTP(MDP_BASE + 0x502d8, 0x2b0003e6);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
+	MDP_OUTP(MDP_BASE + 0x502dc, 0x260003e8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
+	MDP_OUTP(MDP_BASE + 0x502e0, 0x214003eb);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
+	MDP_OUTP(MDP_BASE + 0x502e4, 0x1c4003ee);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
+	MDP_OUTP(MDP_BASE + 0x502e8, 0x17c003f1);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
+	MDP_OUTP(MDP_BASE + 0x502ec, 0x134003f3);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
+	MDP_OUTP(MDP_BASE + 0x502f0, 0xf0003f6);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
+	MDP_OUTP(MDP_BASE + 0x502f4, 0xac003f9);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
+	MDP_OUTP(MDP_BASE + 0x502f8, 0x70003fb);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
+	MDP_OUTP(MDP_BASE + 0x502fc, 0x34003fe);
+}
+
+static void mdp_load_bc_downscale_table_y_point8TO1(void)
+{
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0x0);
+	MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d);
+	MDP_OUTP(MDP_BASE + 0x50304, 0x7ec003f9);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c);
+	MDP_OUTP(MDP_BASE + 0x50308, 0x7d4003f3);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b);
+	MDP_OUTP(MDP_BASE + 0x5030c, 0x7b8003ed);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c);
+	MDP_OUTP(MDP_BASE + 0x50310, 0x794003e8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d);
+	MDP_OUTP(MDP_BASE + 0x50314, 0x76c003e4);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f);
+	MDP_OUTP(MDP_BASE + 0x50318, 0x73c003e0);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071);
+	MDP_OUTP(MDP_BASE + 0x5031c, 0x708003de);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085);
+	MDP_OUTP(MDP_BASE + 0x50320, 0x6d0003db);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098);
+	MDP_OUTP(MDP_BASE + 0x50324, 0x698003d9);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac);
+	MDP_OUTP(MDP_BASE + 0x50328, 0x654003d8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1);
+	MDP_OUTP(MDP_BASE + 0x5032c, 0x610003d7);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5);
+	MDP_OUTP(MDP_BASE + 0x50330, 0x5c8003d7);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9);
+	MDP_OUTP(MDP_BASE + 0x50334, 0x580003d7);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd);
+	MDP_OUTP(MDP_BASE + 0x50338, 0x534003d8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112);
+	MDP_OUTP(MDP_BASE + 0x5033c, 0x4e8003d8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126);
+	MDP_OUTP(MDP_BASE + 0x50340, 0x494003da);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a);
+	MDP_OUTP(MDP_BASE + 0x50344, 0x448003db);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d);
+	MDP_OUTP(MDP_BASE + 0x50348, 0x3f4003dd);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160);
+	MDP_OUTP(MDP_BASE + 0x5034c, 0x3a4003df);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172);
+	MDP_OUTP(MDP_BASE + 0x50350, 0x354003e1);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184);
+	MDP_OUTP(MDP_BASE + 0x50354, 0x304003e3);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195);
+	MDP_OUTP(MDP_BASE + 0x50358, 0x2b0003e6);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6);
+	MDP_OUTP(MDP_BASE + 0x5035c, 0x260003e8);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4);
+	MDP_OUTP(MDP_BASE + 0x50360, 0x214003eb);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2);
+	MDP_OUTP(MDP_BASE + 0x50364, 0x1c4003ee);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf);
+	MDP_OUTP(MDP_BASE + 0x50368, 0x17c003f1);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db);
+	MDP_OUTP(MDP_BASE + 0x5036c, 0x134003f3);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5);
+	MDP_OUTP(MDP_BASE + 0x50370, 0xf0003f6);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee);
+	MDP_OUTP(MDP_BASE + 0x50374, 0xac003f9);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5);
+	MDP_OUTP(MDP_BASE + 0x50378, 0x70003fb);
+	MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb);
+	MDP_OUTP(MDP_BASE + 0x5037c, 0x34003fe);
+}
+
+static int mdp_get_edge_cond(MDPIBUF *iBuf, uint32 *dup, uint32 *dup2)
+{
+	uint32 reg;
+	uint32 dst_roi_width;	/* Dimensions of DST ROI. */
+	uint32 dst_roi_height;	/* Used to calculate scaling ratios. */
+
+	/*
+	 * positions of the luma pixel(relative to the image ) required for
+	 * scaling the ROI
+	 */
+	int32 luma_interp_point_left = 0; /* left-most luma pixel needed */
+	int32 luma_interp_point_right = 0; /* right-most luma pixel needed */
+	int32 luma_interp_point_top = 0; /* top-most luma pixel needed */
+	int32 luma_interp_point_bottom = 0; /* bottom-most luma pixel needed */
+
+	/*
+	 * positions of the chroma pixel(relative to the image ) required for
+	 * interpolating a chroma value at all required luma positions
+	 */
+	/* left-most chroma pixel needed */
+	int32 chroma_interp_point_left = 0;
+	/* right-most chroma pixel needed */
+	int32 chroma_interp_point_right = 0;
+	/* top-most chroma pixel needed */
+	int32 chroma_interp_point_top = 0;
+	/* bottom-most chroma pixel needed */
+	int32 chroma_interp_point_bottom = 0;
+
+	/*
+	 * a rectangular region within the chroma plane of the "image".
+	 * Chroma pixels falling inside of this rectangle belongs to the ROI
+	 */
+	int32 chroma_bound_left = 0;
+	int32 chroma_bound_right = 0;
+	int32 chroma_bound_top = 0;
+	int32 chroma_bound_bottom = 0;
+
+	/*
+	 * number of chroma pixels to replicate on the left, right,
+	 * top and bottom edge of the ROI.
+	 */
+	int32 chroma_repeat_left = 0;
+	int32 chroma_repeat_right = 0;
+	int32 chroma_repeat_top = 0;
+	int32 chroma_repeat_bottom = 0;
+
+	/*
+	 * number of luma pixels to replicate on the left, right,
+	 * top and bottom edge of the ROI.
+	 */
+	int32 luma_repeat_left = 0;
+	int32 luma_repeat_right = 0;
+	int32 luma_repeat_top = 0;
+	int32 luma_repeat_bottom = 0;
+
+	boolean chroma_edge_enable;
+
+	uint32 _is_scale_enabled = 0;
+	uint32 _is_yuv_offsite_vertical = 0;
+
+	/* fg edge duplicate */
+	reg = 0x0;
+
+	if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {	/* if scaling enabled */
+
+		_is_scale_enabled = 1;
+
+		/*
+		 * if rotation mode involves a 90 deg rotation, flip
+		 * dst_roi_width with dst_roi_height.
+		 * Scaling ratios is based on source ROI dimensions, and
+		 * dst ROI dimensions before rotation.
+		 */
+		if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+			dst_roi_width = iBuf->roi.dst_height;
+			dst_roi_height = iBuf->roi.dst_width;
+		} else {
+			dst_roi_width = iBuf->roi.dst_width;
+			dst_roi_height = iBuf->roi.dst_height;
+		}
+
+		/*
+		 * Find out the luma pixels needed for scaling in the
+		 * x direction (LEFT and RIGHT).  Locations of pixels are
+		 * relative to the ROI. Upper-left corner of ROI corresponds
+		 * to coordinates (0,0). Also set the number of luma pixel
+		 * to repeat.
+		 */
+		if (iBuf->roi.width > 3 * dst_roi_width) {
+			/* scale factor < 1/3 */
+			luma_interp_point_left = 0;
+			luma_interp_point_right = (iBuf->roi.width - 1);
+			luma_repeat_left = 0;
+			luma_repeat_right = 0;
+		} else if (iBuf->roi.width == 3 * dst_roi_width) {
+			/* scale factor == 1/3 */
+			luma_interp_point_left = 0;
+			luma_interp_point_right = (iBuf->roi.width - 1) + 1;
+			luma_repeat_left = 0;
+			luma_repeat_right = 1;
+		} else if ((iBuf->roi.width > dst_roi_width) &&
+			   (iBuf->roi.width < 3 * dst_roi_width)) {
+			/* 1/3 < scale factor < 1 */
+			luma_interp_point_left = -1;
+			luma_interp_point_right = (iBuf->roi.width - 1) + 1;
+			luma_repeat_left = 1;
+			luma_repeat_right = 1;
+		}
+
+		else if (iBuf->roi.width == dst_roi_width) {
+			/* scale factor == 1 */
+			luma_interp_point_left = -1;
+			luma_interp_point_right = (iBuf->roi.width - 1) + 2;
+			luma_repeat_left = 1;
+			luma_repeat_right = 2;
+		} else {	/* (iBuf->roi.width < dst_roi_width) */
+			  /* scale factor > 1 */
+			luma_interp_point_left = -2;
+			luma_interp_point_right = (iBuf->roi.width - 1) + 2;
+			luma_repeat_left = 2;
+			luma_repeat_right = 2;
+		}
+
+		/*
+		 * Find out the number of pixels needed for scaling in the
+		 * y direction (TOP and BOTTOM).  Locations of pixels are
+		 * relative to the ROI. Upper-left corner of ROI corresponds
+		 * to coordinates (0,0). Also set the number of luma pixel
+		 * to repeat.
+		 */
+		if (iBuf->roi.height > 3 * dst_roi_height) {
+			/* scale factor < 1/3 */
+			luma_interp_point_top = 0;
+			luma_interp_point_bottom = (iBuf->roi.height - 1);
+			luma_repeat_top = 0;
+			luma_repeat_bottom = 0;
+		} else if (iBuf->roi.height == 3 * dst_roi_height) {
+			/* scale factor == 1/3 */
+			luma_interp_point_top = 0;
+			luma_interp_point_bottom = (iBuf->roi.height - 1) + 1;
+			luma_repeat_top = 0;
+			luma_repeat_bottom = 1;
+		} else if ((iBuf->roi.height > dst_roi_height) &&
+			   (iBuf->roi.height < 3 * dst_roi_height)) {
+			/* 1/3 < scale factor < 1 */
+			luma_interp_point_top = -1;
+			luma_interp_point_bottom = (iBuf->roi.height - 1) + 1;
+			luma_repeat_top = 1;
+			luma_repeat_bottom = 1;
+		} else if (iBuf->roi.height == dst_roi_height) {
+			/* scale factor == 1 */
+			luma_interp_point_top = -1;
+			luma_interp_point_bottom = (iBuf->roi.height - 1) + 2;
+			luma_repeat_top = 1;
+			luma_repeat_bottom = 2;
+		} else {	/* (iBuf->roi.height < dst_roi_height) */
+			 /* scale factor > 1 */
+			luma_interp_point_top = -2;
+			luma_interp_point_bottom = (iBuf->roi.height - 1) + 2;
+			luma_repeat_top = 2;
+			luma_repeat_bottom = 2;
+		}
+	}			/* if (iBuf->scale.scale_flag) */
+	else {			/* scaling disabled */
+		/*
+		 * Since no scaling needed, Tile Fetch does not require any
+		 * more luma pixel than what the ROI contains.
+		 */
+		luma_interp_point_left = (int32) 0;
+		luma_interp_point_right = (int32) (iBuf->roi.width - 1);
+		luma_interp_point_top = (int32) 0;
+		luma_interp_point_bottom = (int32) (iBuf->roi.height - 1);
+
+		luma_repeat_left = 0;
+		luma_repeat_right = 0;
+		luma_repeat_top = 0;
+		luma_repeat_bottom = 0;
+	}
+
+	/* After adding the ROI offsets, we have locations of
+	 * luma_interp_points relative to the image.
+	 */
+	luma_interp_point_left += (int32) (iBuf->roi.x);
+	luma_interp_point_right += (int32) (iBuf->roi.x);
+	luma_interp_point_top += (int32) (iBuf->roi.y);
+	luma_interp_point_bottom += (int32) (iBuf->roi.y);
+
+	/*
+	 * After adding the ROI offsets, we have locations of
+	 * chroma_interp_points relative to the image.
+	 */
+	chroma_interp_point_left = luma_interp_point_left;
+	chroma_interp_point_right = luma_interp_point_right;
+	chroma_interp_point_top = luma_interp_point_top;
+	chroma_interp_point_bottom = luma_interp_point_bottom;
+
+	chroma_edge_enable = TRUE;
+	/* find out which chroma pixels are needed for chroma upsampling. */
+	switch (iBuf->mdpImg.imgType) {
+		/*
+		 * cosite in horizontal axis
+		 * fully sampled in vertical axis
+		 */
+	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H2V1:
+	case MDP_YCRYCB_H2V1:
+		/* floor( luma_interp_point_left / 2 ); */
+		chroma_interp_point_left = luma_interp_point_left >> 1;
+		/* floor( ( luma_interp_point_right + 1 ) / 2 ); */
+		chroma_interp_point_right = (luma_interp_point_right + 1) >> 1;
+
+		chroma_interp_point_top = luma_interp_point_top;
+		chroma_interp_point_bottom = luma_interp_point_bottom;
+		break;
+
+		/*
+		 * cosite in horizontal axis
+		 * offsite in vertical axis
+		 */
+	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CRCB_H2V2:
+		/* floor( luma_interp_point_left / 2) */
+		chroma_interp_point_left = luma_interp_point_left >> 1;
+
+		/* floor( ( luma_interp_point_right + 1 )/ 2 ) */
+		chroma_interp_point_right = (luma_interp_point_right + 1) >> 1;
+
+		/* floor( (luma_interp_point_top - 1 ) / 2 ) */
+		chroma_interp_point_top = (luma_interp_point_top - 1) >> 1;
+
+		/* floor( ( luma_interp_point_bottom + 1 ) / 2 ) */
+		chroma_interp_point_bottom =
+		    (luma_interp_point_bottom + 1) >> 1;
+
+		_is_yuv_offsite_vertical = 1;
+		break;
+
+	default:
+		chroma_edge_enable = FALSE;
+		chroma_interp_point_left = luma_interp_point_left;
+		chroma_interp_point_right = luma_interp_point_right;
+		chroma_interp_point_top = luma_interp_point_top;
+		chroma_interp_point_bottom = luma_interp_point_bottom;
+
+		break;
+	}
+
+	/* only if the image type is in YUV domain, we calculate chroma edge */
+	if (chroma_edge_enable) {
+		/* Defines which chroma pixels belongs to the roi */
+		switch (iBuf->mdpImg.imgType) {
+			/*
+			 * Cosite in horizontal direction, and fully sampled
+			 * in vertical direction.
+			 */
+		case MDP_Y_CBCR_H2V1:
+		case MDP_Y_CRCB_H2V1:
+		case MDP_YCRYCB_H2V1:
+			/*
+			 * width of chroma ROI is 1/2 of size of luma ROI
+			 * height of chroma ROI same as size of luma ROI
+			 */
+			chroma_bound_left = iBuf->roi.x / 2;
+
+			/* there are half as many chroma pixel as luma pixels */
+			chroma_bound_right =
+			    (iBuf->roi.width + iBuf->roi.x - 1) / 2;
+			chroma_bound_top = iBuf->roi.y;
+			chroma_bound_bottom =
+			    (iBuf->roi.height + iBuf->roi.y - 1);
+			break;
+
+		case MDP_Y_CBCR_H2V2:
+		case MDP_Y_CRCB_H2V2:
+			/*
+			 * cosite in horizontal dir, and offsite in vertical dir
+			 * width of chroma ROI is 1/2 of size of luma ROI
+			 * height of chroma ROI is 1/2 of size of luma ROI
+			 */
+
+			chroma_bound_left = iBuf->roi.x / 2;
+			chroma_bound_right =
+			    (iBuf->roi.width + iBuf->roi.x - 1) / 2;
+			chroma_bound_top = iBuf->roi.y / 2;
+			chroma_bound_bottom =
+			    (iBuf->roi.height + iBuf->roi.y - 1) / 2;
+			break;
+
+		default:
+			/*
+			 * If no valid chroma sub-sampling format specified,
+			 * assume 4:4:4 ( i.e. fully sampled).  Set ROI
+			 * boundaries for chroma same as ROI boundaries for
+			 * luma.
+			 */
+			chroma_bound_left = iBuf->roi.x;
+			chroma_bound_right = iBuf->roi.width + iBuf->roi.x - 1;
+			chroma_bound_top = iBuf->roi.y;
+			chroma_bound_bottom =
+			    (iBuf->roi.height + iBuf->roi.y - 1);
+			break;
+		}
+
+		/*
+		 * Knowing which chroma pixels are needed, and which chroma
+		 * pixels belong to the ROI (i.e. available for fetching ),
+		 * calculate how many chroma pixels Tile Fetch needs to
+		 * duplicate.  If any required chroma pixels falls outside
+		 * of the ROI, Tile Fetch must obtain them by replicating
+		 * pixels.
+		 */
+		if (chroma_bound_left > chroma_interp_point_left)
+			chroma_repeat_left =
+			    chroma_bound_left - chroma_interp_point_left;
+		else
+			chroma_repeat_left = 0;
+
+		if (chroma_interp_point_right > chroma_bound_right)
+			chroma_repeat_right =
+			    chroma_interp_point_right - chroma_bound_right;
+		else
+			chroma_repeat_right = 0;
+
+		if (chroma_bound_top > chroma_interp_point_top)
+			chroma_repeat_top =
+			    chroma_bound_top - chroma_interp_point_top;
+		else
+			chroma_repeat_top = 0;
+
+		if (chroma_interp_point_bottom > chroma_bound_bottom)
+			chroma_repeat_bottom =
+			    chroma_interp_point_bottom - chroma_bound_bottom;
+		else
+			chroma_repeat_bottom = 0;
+
+		if (_is_scale_enabled && (iBuf->roi.height == 1)
+		    && _is_yuv_offsite_vertical) {
+			chroma_repeat_bottom = 3;
+			chroma_repeat_top = 0;
+		}
+	}
+	/* make sure chroma repeats are non-negative */
+	if ((chroma_repeat_left < 0) || (chroma_repeat_right < 0) ||
+	    (chroma_repeat_top < 0) || (chroma_repeat_bottom < 0))
+		return -1;
+
+	/* make sure chroma repeats are no larger than 3 pixels */
+	if ((chroma_repeat_left > 3) || (chroma_repeat_right > 3) ||
+	    (chroma_repeat_top > 3) || (chroma_repeat_bottom > 3))
+		return -1;
+
+	/* make sure luma repeats are non-negative */
+	if ((luma_repeat_left < 0) || (luma_repeat_right < 0) ||
+	    (luma_repeat_top < 0) || (luma_repeat_bottom < 0))
+		return -1;
+
+	/* make sure luma repeats are no larger than 3 pixels */
+	if ((luma_repeat_left > 3) || (luma_repeat_right > 3) ||
+	    (luma_repeat_top > 3) || (luma_repeat_bottom > 3))
+		return -1;
+
+	/* write chroma_repeat_left to register */
+	reg |= (chroma_repeat_left & 3) << MDP_LEFT_CHROMA;
+
+	/* write chroma_repeat_right to register */
+	reg |= (chroma_repeat_right & 3) << MDP_RIGHT_CHROMA;
+
+	/* write chroma_repeat_top to register */
+	reg |= (chroma_repeat_top & 3) << MDP_TOP_CHROMA;
+
+	/* write chroma_repeat_bottom to register */
+	reg |= (chroma_repeat_bottom & 3) << MDP_BOTTOM_CHROMA;
+
+	/* write luma_repeat_left to register */
+	reg |= (luma_repeat_left & 3) << MDP_LEFT_LUMA;
+
+	/* write luma_repeat_right to register */
+	reg |= (luma_repeat_right & 3) << MDP_RIGHT_LUMA;
+
+	/* write luma_repeat_top to register */
+	reg |= (luma_repeat_top & 3) << MDP_TOP_LUMA;
+
+	/* write luma_repeat_bottom to register */
+	reg |= (luma_repeat_bottom & 3) << MDP_BOTTOM_LUMA;
+
+	/* done with reg */
+	*dup = reg;
+
+	/* bg edge duplicate */
+	reg = 0x0;
+
+	switch (iBuf->ibuf_type) {
+	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CRCB_H2V2:
+		/*
+		 * Edge condition for MDP_Y_CRCB/CBCR_H2V2 cosite only.
+		 * For 420 cosite, 1 chroma replicated on all sides except
+		 * left, so reg 101b8 should be 0x0209. For 420 offsite,
+		 * 1 chroma replicated all sides.
+		 */
+		if (iBuf->roi.lcd_y == 0) {
+			reg |= BIT(MDP_TOP_CHROMA);
+		}
+
+		if ((iBuf->roi.lcd_y + iBuf->roi.dst_height) ==
+		    iBuf->ibuf_height) {
+			reg |= BIT(MDP_BOTTOM_CHROMA);
+		}
+
+		if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) ==
+		     iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) {
+			reg |= BIT(MDP_RIGHT_CHROMA);
+		}
+
+		break;
+
+	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H2V1:
+	case MDP_YCRYCB_H2V1:
+		if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) ==
+		     iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) {
+			reg |= BIT(MDP_RIGHT_CHROMA);
+		}
+		break;
+	default:
+		break;
+	}
+
+	*dup2 = reg;
+
+	return 0;
+}
+
+#define ADJUST_IP		/* for 1/3 scale factor fix */
+
+static int mdp_calc_scale_params(
+/* ROI origin coordinate for the dimension */
+					uint32 org,
+/* src ROI dimension */
+					uint32 dim_in,
+/* scaled ROI dimension*/
+					uint32 dim_out,
+/* is this ROI width dimension? */
+					boolean is_W,
+/* initial phase location address */
+					int32 *phase_init_ptr,
+/* phase increment location address */
+					uint32 *phase_step_ptr,
+/* ROI start over-fetch location address */
+					uint32 *num_repl_beg_ptr,
+/* ROI end over-fetch location address */
+					uint32 *num_repl_end_ptr)
+{
+	boolean rpa_on = FALSE;
+	int init_phase = 0;
+	uint32 beg_of = 0;
+	uint32 end_of = 0;
+	uint64 numer = 0;
+	uint64 denom = 0;
+	/*uint64 inverter = 1; */
+	int64 point5 = 1;
+	int64 one = 1;
+	int64 k1, k2, k3, k4;	/* linear equation coefficients */
+	uint64 int_mask;
+	uint64 fract_mask;
+	uint64 Os;
+	int64 Osprime;
+	int64 Od;
+	int64 Odprime;
+	int64 Oreq;
+	uint64 Es;
+	uint64 Ed;
+	uint64 Ereq;
+#ifdef ADJUST_IP
+	int64 IP64;
+	int64 delta;
+#endif
+	uint32 mult;
+
+	/*
+	 * The phase accumulator should really be rational for all cases in a
+	 * general purpose polyphase scaler for a tiled architecture with
+	 * non-zero * origin capability because there is no way to represent
+	 * certain scale factors in fixed point regardless of precision.
+	 * The error incurred in attempting to use fixed point is most
+	 * eggregious for SF where 1/SF is an integral multiple of 1/3.
+	 *
+	 * However, since the MDP2 has already been committed to HW, we
+	 * only use the rational phase accumulator (RPA) when 1/SF is an
+	 * integral multiple of 1/3.  This will help minimize regressions in
+	 * matching the HW to the C-Sim.
+	 */
+	/*
+	 * Set the RPA flag for this dimension.
+	 *
+	 * In order for 1/SF (dim_in/dim_out) to be an integral multiple of
+	 * 1/3, dim_out must be an integral multiple of 3.
+	 */
+	if (!(dim_out % 3)) {
+		mult = dim_out / 3;
+		rpa_on = (!(dim_in % mult));
+	}
+
+	numer = dim_out;
+	denom = dim_in;
+
+	/*
+	 * convert to U30.34 before division
+	 *
+	 * The K vectors carry 4 extra bits of precision
+	 * and are rounded.
+	 *
+	 * We initially go 5 bits over then round by adding
+	 * 1 and right shifting by 1
+	 * so final result is U31.33
+	 */
+	numer <<= PQF_PLUS_5;
+
+	/* now calculate the scale factor (aka k3) */
+	k3 = ((mdp_do_div(numer, denom) + 1) >> 1);
+
+	/* check scale factor for legal range [0.25 - 4.0] */
+	if (((k3 >> 4) < (1LL << PQF_MINUS_2)) ||
+	    ((k3 >> 4) > (1LL << PQF_PLUS_2))) {
+		return -1;
+	}
+
+	/* calculate inverse scale factor (aka k1) for phase init */
+	numer = dim_in;
+	denom = dim_out;
+	numer <<= PQF_PLUS_5;
+	k1 = ((mdp_do_div(numer, denom) + 1) >> 1);
+
+	/*
+	 * calculate initial phase and ROI overfetch
+	 */
+	/* convert point5 & one to S39.24 (will always be positive) */
+	point5 <<= (PQF_PLUS_4 - 1);
+	one <<= PQF_PLUS_4;
+	k2 = ((k1 - one) >> 1);
+	init_phase = (int)(k2 >> 4);
+	k4 = ((k3 - one) >> 1);
+	if (k3 == one) {
+		/* the simple case; SF = 1.0 */
+		beg_of = 1;
+		end_of = 2;
+	} else {
+		/* calculate the masks */
+		fract_mask = one - 1;
+		int_mask = ~fract_mask;
+
+		if (!rpa_on) {
+			/*
+			 * FIXED POINT IMPLEMENTATION
+			 */
+			if (!org) {
+				/* A fairly simple case; ROI origin = 0 */
+				if (k1 < one) {
+					/* upscaling */
+					beg_of = end_of = 2;
+				}
+				/* 0.33 <= SF < 1.0 */
+				else if (k1 < (3LL << PQF_PLUS_4))
+					beg_of = end_of = 1;
+				/* 0.33 == SF */
+				else if (k1 == (3LL << PQF_PLUS_4)) {
+					beg_of = 0;
+					end_of = 1;
+				}
+				/* 0.25 <= SF < 0.33 */
+				else
+					beg_of = end_of = 0;
+			} else {
+				/*
+				 * The complicated case; ROI origin != 0
+				 * init_phase needs to be adjusted
+				 * OF is also position dependent
+				 */
+
+				/* map (org - .5) into destination space */
+				Os = ((uint64) org << 1) - 1;
+				Od = ((k3 * Os) >> 1) + k4;
+
+				/* take the ceiling */
+				Odprime = (Od & int_mask);
+				if (Odprime != Od)
+					Odprime += one;
+
+				/* now map that back to source space */
+				Osprime = (k1 * (Odprime >> PQF_PLUS_4)) + k2;
+
+				/* then floor & decrement to calculate the required
+				   starting coordinate */
+				Oreq = (Osprime & int_mask) - one;
+
+				/* calculate end coord in destination space then map to
+				   source space */
+				Ed = Odprime +
+				    ((uint64) dim_out << PQF_PLUS_4) - one;
+				Es = (k1 * (Ed >> PQF_PLUS_4)) + k2;
+
+				/* now floor & increment by 2 to calculate the required
+				   ending coordinate */
+				Ereq = (Es & int_mask) + (one << 1);
+
+				/* calculate initial phase */
+#ifdef ADJUST_IP
+
+				IP64 = Osprime - Oreq;
+				delta = ((int64) (org) << PQF_PLUS_4) - Oreq;
+				IP64 -= delta;
+
+				/* limit to valid range before the left shift */
+				delta = (IP64 & (1LL << 63)) ? 4 : -4;
+				delta <<= PQF_PLUS_4;
+				while (abs((int)(IP64 >> PQF_PLUS_4)) > 4)
+					IP64 += delta;
+
+				/* right shift to account for extra bits of precision */
+				init_phase = (int)(IP64 >> 4);
+
+#else /* ADJUST_IP */
+
+				/* just calculate the real initial phase */
+				init_phase = (int)((Osprime - Oreq) >> 4);
+
+#endif /* ADJUST_IP */
+
+				/* calculate the overfetch */
+				beg_of = org - (uint32) (Oreq >> PQF_PLUS_4);
+				end_of =
+				    (uint32) (Ereq >> PQF_PLUS_4) - (org +
+								     dim_in -
+								     1);
+			}
+		} else {
+			/*
+			 * RPA IMPLEMENTATION
+			 *
+			 * init_phase needs to be calculated in all RPA_on cases
+			 * because it's a numerator, not a fixed point value.
+			 */
+
+			/* map (org - .5) into destination space */
+			Os = ((uint64) org << PQF_PLUS_4) - point5;
+			Od = mdp_do_div((dim_out * (Os + point5)),
+					dim_in) - point5;
+
+			/* take the ceiling */
+			Odprime = (Od & int_mask);
+			if (Odprime != Od)
+				Odprime += one;
+
+			/* now map that back to source space */
+			Osprime =
+			    mdp_do_div((dim_in * (Odprime + point5)),
+				       dim_out) - point5;
+
+			/* then floor & decrement to calculate the required
+			   starting coordinate */
+			Oreq = (Osprime & int_mask) - one;
+
+			/* calculate end coord in destination space then map to
+			   source space */
+			Ed = Odprime + ((uint64) dim_out << PQF_PLUS_4) - one;
+			Es = mdp_do_div((dim_in * (Ed + point5)),
+					dim_out) - point5;
+
+			/* now floor & increment by 2 to calculate the required
+			   ending coordinate */
+			Ereq = (Es & int_mask) + (one << 1);
+
+			/* calculate initial phase */
+
+#ifdef ADJUST_IP
+
+			IP64 = Osprime - Oreq;
+			delta = ((int64) (org) << PQF_PLUS_4) - Oreq;
+			IP64 -= delta;
+
+			/* limit to valid range before the left shift */
+			delta = (IP64 & (1LL << 63)) ? 4 : -4;
+			delta <<= PQF_PLUS_4;
+			while (abs((int)(IP64 >> PQF_PLUS_4)) > 4)
+				IP64 += delta;
+
+			/* right shift to account for extra bits of precision */
+			init_phase = (int)(IP64 >> 4);
+
+#else /* ADJUST_IP */
+
+			/* just calculate the real initial phase */
+			init_phase = (int)((Osprime - Oreq) >> 4);
+
+#endif /* ADJUST_IP */
+
+			/* calculate the overfetch */
+			beg_of = org - (uint32) (Oreq >> PQF_PLUS_4);
+			end_of =
+			    (uint32) (Ereq >> PQF_PLUS_4) - (org + dim_in - 1);
+		}
+	}
+
+	/* return the scale parameters */
+	*phase_init_ptr = init_phase;
+	*phase_step_ptr = (uint32) (k1 >> 4);
+	*num_repl_beg_ptr = beg_of;
+	*num_repl_end_ptr = end_of;
+
+	return 0;
+}
+
+static uint8 *mdp_adjust_rot_addr(MDPIBUF *iBuf, uint8 *addr, uint32 uv)
+{
+	uint32 dest_ystride = iBuf->ibuf_width * iBuf->bpp;
+	uint32 h_slice = 1;
+
+	if (uv && ((iBuf->ibuf_type == MDP_Y_CBCR_H2V2) ||
+		(iBuf->ibuf_type == MDP_Y_CRCB_H2V2)))
+		h_slice = 2;
+
+	if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_ROT90) ^
+	    MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_LR)) {
+		addr =
+		    addr + (iBuf->roi.dst_width -
+			    MIN(16, iBuf->roi.dst_width)) * iBuf->bpp;
+	}
+	if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_UD)) {
+		addr =
+		    addr + ((iBuf->roi.dst_height -
+			MIN(16, iBuf->roi.dst_height))/h_slice) * dest_ystride;
+	}
+
+	return addr;
+}
+
+void mdp_set_scale(MDPIBUF *iBuf,
+		   uint32 dst_roi_width,
+		   uint32 dst_roi_height,
+		   boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr)
+{
+	uint32 dst_roi_width_scale;
+	uint32 dst_roi_height_scale;
+	boolean use_pr;
+	uint32 phasex_step = 0;
+	uint32 phasey_step = 0;
+	int32 phasex_init = 0;
+	int32 phasey_init = 0;
+	uint32 lines_dup = 0;
+	uint32 lines_dup_bg = 0;
+	uint32 dummy;
+	uint32 mdp_blur = 0;
+
+	if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {
+		if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+			dst_roi_width_scale = dst_roi_height;
+			dst_roi_height_scale = dst_roi_width;
+		} else {
+			dst_roi_width_scale = dst_roi_width;
+			dst_roi_height_scale = dst_roi_height;
+		}
+
+		mdp_blur = iBuf->mdpImg.mdpOp & MDPOP_BLUR;
+
+		if ((dst_roi_width_scale != iBuf->roi.width) ||
+		    (dst_roi_height_scale != iBuf->roi.height) ||
+			mdp_blur) {
+			*pppop_reg_ptr |=
+			    (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
+
+		/* let's use SHIM logic to calculate the partial ROI scaling */
+#if 0
+			phasex_step =
+			    (uint32) mdp_do_div(0x20000000 * iBuf->roi.width,
+						dst_roi_width_scale);
+			phasey_step =
+			    (uint32) mdp_do_div(0x20000000 * iBuf->roi.height,
+						dst_roi_height_scale);
+
+/*
+    phasex_step= ((long long) iBuf->roi.width * 0x20000000)/dst_roi_width_scale;
+    phasey_step= ((long long)iBuf->roi.height * 0x20000000)/dst_roi_height_scale;
+*/
+
+			phasex_init =
+			    (((long long)phasex_step - 0x20000000) >> 1);
+			phasey_init =
+			    (((long long)phasey_step - 0x20000000) >> 1);
+
+#else
+			mdp_calc_scale_params(iBuf->roi.x, iBuf->roi.width,
+					      dst_roi_width_scale, 1,
+					      &phasex_init, &phasex_step,
+					      &dummy, &dummy);
+			mdp_calc_scale_params(iBuf->roi.y, iBuf->roi.height,
+					      dst_roi_height_scale, 0,
+					      &phasey_init, &phasey_step,
+					      &dummy, &dummy);
+#endif
+			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c,
+				 phasex_init);
+			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140,
+				 phasey_init);
+			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144,
+				 phasex_step);
+			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148,
+				 phasey_step);
+
+			use_pr = (inputRGB) && (outputRGB);
+
+			if ((dst_roi_width_scale > iBuf->roi.width) ||
+			    (dst_roi_height_scale > iBuf->roi.height)) {
+				if ((use_pr)
+				    && (mdp_curr_up_scale_xy !=
+					MDP_PR_SCALE_UP)) {
+					mdp_load_pr_upscale_table();
+					mdp_curr_up_scale_xy = MDP_PR_SCALE_UP;
+				} else if ((!use_pr)
+					   && (mdp_curr_up_scale_xy !=
+					       MDP_BC_SCALE_UP)) {
+					mdp_load_bc_upscale_table();
+					mdp_curr_up_scale_xy = MDP_BC_SCALE_UP;
+				}
+			}
+
+			if (mdp_blur) {
+				load_scale_table(mdp_gaussian_blur_table,
+					ARRAY_SIZE(mdp_gaussian_blur_table));
+				mdp_curr_down_scale_x = MDP_SCALE_BLUR;
+				mdp_curr_down_scale_y = MDP_SCALE_BLUR;
+			}
+
+			/* 0.2 < x <= 1 scaling factor */
+			if ((dst_roi_width_scale <= iBuf->roi.width) &&
+				!mdp_blur) {
+				if (((dst_roi_width_scale * 10) /
+				     iBuf->roi.width) > 8) {
+					if ((use_pr)
+					    && (mdp_curr_down_scale_x !=
+						MDP_PR_SCALE_POINT8_1)) {
+						mdp_load_pr_downscale_table_x_point8TO1
+						    ();
+						mdp_curr_down_scale_x =
+						    MDP_PR_SCALE_POINT8_1;
+					} else if ((!use_pr)
+						   && (mdp_curr_down_scale_x !=
+						       MDP_BC_SCALE_POINT8_1)) {
+						mdp_load_bc_downscale_table_x_point8TO1
+						    ();
+						mdp_curr_down_scale_x =
+						    MDP_BC_SCALE_POINT8_1;
+					}
+				} else
+				    if (((dst_roi_width_scale * 10) /
+					 iBuf->roi.width) > 6) {
+					if ((use_pr)
+					    && (mdp_curr_down_scale_x !=
+						MDP_PR_SCALE_POINT6_POINT8)) {
+						mdp_load_pr_downscale_table_x_point6TOpoint8
+						    ();
+						mdp_curr_down_scale_x =
+						    MDP_PR_SCALE_POINT6_POINT8;
+					} else if ((!use_pr)
+						   && (mdp_curr_down_scale_x !=
+						       MDP_BC_SCALE_POINT6_POINT8))
+					{
+						mdp_load_bc_downscale_table_x_point6TOpoint8
+						    ();
+						mdp_curr_down_scale_x =
+						    MDP_BC_SCALE_POINT6_POINT8;
+					}
+				} else
+				    if (((dst_roi_width_scale * 10) /
+					 iBuf->roi.width) > 4) {
+					if ((use_pr)
+					    && (mdp_curr_down_scale_x !=
+						MDP_PR_SCALE_POINT4_POINT6)) {
+						mdp_load_pr_downscale_table_x_point4TOpoint6
+						    ();
+						mdp_curr_down_scale_x =
+						    MDP_PR_SCALE_POINT4_POINT6;
+					} else if ((!use_pr)
+						   && (mdp_curr_down_scale_x !=
+						       MDP_BC_SCALE_POINT4_POINT6))
+					{
+						mdp_load_bc_downscale_table_x_point4TOpoint6
+						    ();
+						mdp_curr_down_scale_x =
+						    MDP_BC_SCALE_POINT4_POINT6;
+					}
+				} else {
+					if ((use_pr)
+					    && (mdp_curr_down_scale_x !=
+						MDP_PR_SCALE_POINT2_POINT4)) {
+						mdp_load_pr_downscale_table_x_point2TOpoint4
+						    ();
+						mdp_curr_down_scale_x =
+						    MDP_PR_SCALE_POINT2_POINT4;
+					} else if ((!use_pr)
+						   && (mdp_curr_down_scale_x !=
+						       MDP_BC_SCALE_POINT2_POINT4))
+					{
+						mdp_load_bc_downscale_table_x_point2TOpoint4
+						    ();
+						mdp_curr_down_scale_x =
+						    MDP_BC_SCALE_POINT2_POINT4;
+					}
+				}
+			}
+			/* 0.2 < y <= 1 scaling factor */
+			if ((dst_roi_height_scale <= iBuf->roi.height) &&
+				!mdp_blur) {
+				if (((dst_roi_height_scale * 10) /
+				     iBuf->roi.height) > 8) {
+					if ((use_pr)
+					    && (mdp_curr_down_scale_y !=
+						MDP_PR_SCALE_POINT8_1)) {
+						mdp_load_pr_downscale_table_y_point8TO1
+						    ();
+						mdp_curr_down_scale_y =
+						    MDP_PR_SCALE_POINT8_1;
+					} else if ((!use_pr)
+						   && (mdp_curr_down_scale_y !=
+						       MDP_BC_SCALE_POINT8_1)) {
+						mdp_load_bc_downscale_table_y_point8TO1
+						    ();
+						mdp_curr_down_scale_y =
+						    MDP_BC_SCALE_POINT8_1;
+					}
+				} else
+				    if (((dst_roi_height_scale * 10) /
+					 iBuf->roi.height) > 6) {
+					if ((use_pr)
+					    && (mdp_curr_down_scale_y !=
+						MDP_PR_SCALE_POINT6_POINT8)) {
+						mdp_load_pr_downscale_table_y_point6TOpoint8
+						    ();
+						mdp_curr_down_scale_y =
+						    MDP_PR_SCALE_POINT6_POINT8;
+					} else if ((!use_pr)
+						   && (mdp_curr_down_scale_y !=
+						       MDP_BC_SCALE_POINT6_POINT8))
+					{
+						mdp_load_bc_downscale_table_y_point6TOpoint8
+						    ();
+						mdp_curr_down_scale_y =
+						    MDP_BC_SCALE_POINT6_POINT8;
+					}
+				} else
+				    if (((dst_roi_height_scale * 10) /
+					 iBuf->roi.height) > 4) {
+					if ((use_pr)
+					    && (mdp_curr_down_scale_y !=
+						MDP_PR_SCALE_POINT4_POINT6)) {
+						mdp_load_pr_downscale_table_y_point4TOpoint6
+						    ();
+						mdp_curr_down_scale_y =
+						    MDP_PR_SCALE_POINT4_POINT6;
+					} else if ((!use_pr)
+						   && (mdp_curr_down_scale_y !=
+						       MDP_BC_SCALE_POINT4_POINT6))
+					{
+						mdp_load_bc_downscale_table_y_point4TOpoint6
+						    ();
+						mdp_curr_down_scale_y =
+						    MDP_BC_SCALE_POINT4_POINT6;
+					}
+				} else {
+					if ((use_pr)
+					    && (mdp_curr_down_scale_y !=
+						MDP_PR_SCALE_POINT2_POINT4)) {
+						mdp_load_pr_downscale_table_y_point2TOpoint4
+						    ();
+						mdp_curr_down_scale_y =
+						    MDP_PR_SCALE_POINT2_POINT4;
+					} else if ((!use_pr)
+						   && (mdp_curr_down_scale_y !=
+						       MDP_BC_SCALE_POINT2_POINT4))
+					{
+						mdp_load_bc_downscale_table_y_point2TOpoint4
+						    ();
+						mdp_curr_down_scale_y =
+						    MDP_BC_SCALE_POINT2_POINT4;
+					}
+				}
+			}
+		} else {
+			iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE);
+		}
+	}
+	/* setting edge condition here after scaling check */
+	if (mdp_get_edge_cond(iBuf, &lines_dup, &lines_dup_bg))
+		printk(KERN_ERR "msm_fb: mdp_get_edge_cond() error!\n");
+
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01b8, lines_dup);
+	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01bc, lines_dup_bg);
+}
+
+void mdp_init_scale_table(void)
+{
+	mdp_curr_up_scale_xy = MDP_INIT_SCALE;
+	mdp_curr_down_scale_x = MDP_INIT_SCALE;
+	mdp_curr_down_scale_y = MDP_INIT_SCALE;
+}
+
+void mdp_adjust_start_addr(uint8 **src0,
+			   uint8 **src1,
+			   int v_slice,
+			   int h_slice,
+			   int x,
+			   int y,
+			   uint32 width,
+			   uint32 height, int bpp, MDPIBUF *iBuf, int layer)
+{
+	*src0 += (x + y * width) * bpp;
+
+	/* if it's dest/bg buffer, we need to adjust it for rotation */
+	if (layer != 0)
+		*src0 = mdp_adjust_rot_addr(iBuf, *src0, 0);
+
+	if (*src1) {
+		/*
+		 * MDP_Y_CBCR_H2V2/MDP_Y_CRCB_H2V2 cosite for now
+		 * we need to shift x direction same as y dir for offsite
+		 */
+		*src1 +=
+		    ((x / h_slice) * h_slice +
+		     ((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
+
+		/* if it's dest/bg buffer, we need to adjust it for rotation */
+		if (layer != 0)
+			*src1 = mdp_adjust_rot_addr(iBuf, *src1, 1);
+	}
+}
+
+void mdp_set_blend_attr(MDPIBUF *iBuf,
+			uint32 *alpha,
+			uint32 *tpVal,
+			uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
+{
+	if (perPixelAlpha) {
+		*pppop_reg_ptr |= PPP_OP_ROT_ON |
+		    PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
+	} else {
+		if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+		    && (iBuf->mdpImg.alpha == 0xff)) {
+			iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
+		}
+
+		if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+		    && (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+			*pppop_reg_ptr |=
+			    PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+			    PPP_OP_BLEND_CONSTANT_ALPHA |
+			    PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
+			    PPP_BLEND_CALPHA_TRNASP;
+
+			*alpha = iBuf->mdpImg.alpha;
+			*tpVal = iBuf->mdpImg.tpVal;
+		} else {
+			if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
+				*pppop_reg_ptr |= PPP_OP_ROT_ON |
+				    PPP_OP_BLEND_ON |
+				    PPP_OP_BLEND_SRCPIXEL_TRANSP;
+				*tpVal = iBuf->mdpImg.tpVal;
+			} else if (iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) {
+				*pppop_reg_ptr |= PPP_OP_ROT_ON |
+				    PPP_OP_BLEND_ON |
+				    PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
+				    PPP_OP_BLEND_CONSTANT_ALPHA;
+				*alpha = iBuf->mdpImg.alpha;
+			}
+		}
+	}
+}

+ 828 - 0
drivers/staging/msm/mdp_ppp_v31.c

@@ -0,0 +1,828 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <asm/div64.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+#define MDP_SCALE_COEFF_NUM      32
+#define MDP_SCALE_0P2_TO_0P4_INDEX 0
+#define MDP_SCALE_0P4_TO_0P6_INDEX 32
+#define MDP_SCALE_0P6_TO_0P8_INDEX 64
+#define MDP_SCALE_0P8_TO_8P0_INDEX 96
+#define MDP_SCALE_COEFF_MASK 0x3ff
+
+#define MDP_SCALE_PR  0
+#define MDP_SCALE_FIR 1
+
+static uint32 mdp_scale_0p8_to_8p0_mode;
+static uint32 mdp_scale_0p6_to_0p8_mode;
+static uint32 mdp_scale_0p4_to_0p6_mode;
+static uint32 mdp_scale_0p2_to_0p4_mode;
+
+/* -------- All scaling range, "pixel repeat" -------- */
+static int16 mdp_scale_pixel_repeat_C0[MDP_SCALE_COEFF_NUM] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int16 mdp_scale_pixel_repeat_C1[MDP_SCALE_COEFF_NUM] = {
+	511, 511, 511, 511, 511, 511, 511, 511,
+	511, 511, 511, 511, 511, 511, 511, 511,
+	511, 511, 511, 511, 511, 511, 511, 511,
+	511, 511, 511, 511, 511, 511, 511, 511
+};
+
+static int16 mdp_scale_pixel_repeat_C2[MDP_SCALE_COEFF_NUM] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int16 mdp_scale_pixel_repeat_C3[MDP_SCALE_COEFF_NUM] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* --------------------------- FIR ------------------------------------- */
+/* -------- Downscale, ranging from 0.8x to 8.0x of original size -------- */
+
+static int16 mdp_scale_0p8_to_8p0_C0[MDP_SCALE_COEFF_NUM] = {
+	0, -7, -13, -19, -24, -28, -32, -34, -37, -39,
+	-40, -41, -41, -41, -40, -40, -38, -37, -35, -33,
+	-31, -29, -26, -24, -21, -18, -15, -13, -10, -7,
+	-5, -2
+};
+
+static int16 mdp_scale_0p8_to_8p0_C1[MDP_SCALE_COEFF_NUM] = {
+	511, 507, 501, 494, 485, 475, 463, 450, 436, 422,
+	405, 388, 370, 352, 333, 314, 293, 274, 253, 233,
+	213, 193, 172, 152, 133, 113, 95, 77, 60, 43,
+	28, 13
+};
+
+static int16 mdp_scale_0p8_to_8p0_C2[MDP_SCALE_COEFF_NUM] = {
+	0, 13, 28, 43, 60, 77, 95, 113, 133, 152,
+	172, 193, 213, 233, 253, 274, 294, 314, 333, 352,
+	370, 388, 405, 422, 436, 450, 463, 475, 485, 494,
+	501, 507,
+};
+
+static int16 mdp_scale_0p8_to_8p0_C3[MDP_SCALE_COEFF_NUM] = {
+	0, -2, -5, -7, -10, -13, -15, -18, -21, -24,
+	-26, -29, -31, -33, -35, -37, -38, -40, -40, -41,
+	-41, -41, -40, -39, -37, -34, -32, -28, -24, -19,
+	-13, -7
+};
+
+/* -------- Downscale, ranging from 0.6x to 0.8x of original size -------- */
+
+static int16 mdp_scale_0p6_to_0p8_C0[MDP_SCALE_COEFF_NUM] = {
+	104, 96, 89, 82, 75, 68, 61, 55, 49, 43,
+	38, 33, 28, 24, 20, 16, 12, 9, 6, 4,
+	2, 0, -2, -4, -5, -6, -7, -7, -8, -8,
+	-8, -8
+};
+
+static int16 mdp_scale_0p6_to_0p8_C1[MDP_SCALE_COEFF_NUM] = {
+	303, 303, 302, 300, 298, 296, 293, 289, 286, 281,
+	276, 270, 265, 258, 252, 245, 238, 230, 223, 214,
+	206, 197, 189, 180, 172, 163, 154, 145, 137, 128,
+	120, 112
+};
+
+static int16 mdp_scale_0p6_to_0p8_C2[MDP_SCALE_COEFF_NUM] = {
+	112, 120, 128, 137, 145, 154, 163, 172, 180, 189,
+	197, 206, 214, 223, 230, 238, 245, 252, 258, 265,
+	270, 276, 281, 286, 289, 293, 296, 298, 300, 302,
+	303, 303
+};
+
+static int16 mdp_scale_0p6_to_0p8_C3[MDP_SCALE_COEFF_NUM] = {
+	-8, -8, -8, -8, -7, -7, -6, -5, -4, -2,
+	0, 2, 4, 6, 9, 12, 16, 20, 24, 28,
+	33, 38, 43, 49, 55, 61, 68, 75, 82, 89,
+	96, 104
+};
+
+/* -------- Downscale, ranging from 0.4x to 0.6x of original size -------- */
+
+static int16 mdp_scale_0p4_to_0p6_C0[MDP_SCALE_COEFF_NUM] = {
+	136, 132, 128, 123, 119, 115, 111, 107, 103, 98,
+	95, 91, 87, 84, 80, 76, 73, 69, 66, 62,
+	59, 57, 54, 50, 47, 44, 41, 39, 36, 33,
+	32, 29
+};
+
+static int16 mdp_scale_0p4_to_0p6_C1[MDP_SCALE_COEFF_NUM] = {
+	206, 205, 204, 204, 201, 200, 199, 197, 196, 194,
+	191, 191, 189, 185, 184, 182, 180, 178, 176, 173,
+	170, 168, 165, 162, 160, 157, 155, 152, 148, 146,
+	142, 140
+};
+
+static int16 mdp_scale_0p4_to_0p6_C2[MDP_SCALE_COEFF_NUM] = {
+	140, 142, 146, 148, 152, 155, 157, 160, 162, 165,
+	168, 170, 173, 176, 178, 180, 182, 184, 185, 189,
+	191, 191, 194, 196, 197, 199, 200, 201, 204, 204,
+	205, 206
+};
+
+static int16 mdp_scale_0p4_to_0p6_C3[MDP_SCALE_COEFF_NUM] = {
+	29, 32, 33, 36, 39, 41, 44, 47, 50, 54,
+	57, 59, 62, 66, 69, 73, 76, 80, 84, 87,
+	91, 95, 98, 103, 107, 111, 115, 119, 123, 128,
+	132, 136
+};
+
+/* -------- Downscale, ranging from 0.2x to 0.4x of original size -------- */
+
+static int16 mdp_scale_0p2_to_0p4_C0[MDP_SCALE_COEFF_NUM] = {
+	131, 131, 130, 129, 128, 127, 127, 126, 125, 125,
+	124, 123, 123, 121, 120, 119, 119, 118, 117, 117,
+	116, 115, 115, 114, 113, 112, 111, 110, 109, 109,
+	108, 107
+};
+
+static int16 mdp_scale_0p2_to_0p4_C1[MDP_SCALE_COEFF_NUM] = {
+	141, 140, 140, 140, 140, 139, 138, 138, 138, 137,
+	137, 137, 136, 137, 137, 137, 136, 136, 136, 135,
+	135, 135, 134, 134, 134, 134, 134, 133, 133, 132,
+	132, 132
+};
+
+static int16 mdp_scale_0p2_to_0p4_C2[MDP_SCALE_COEFF_NUM] = {
+	132, 132, 132, 133, 133, 134, 134, 134, 134, 134,
+	135, 135, 135, 136, 136, 136, 137, 137, 137, 136,
+	137, 137, 137, 138, 138, 138, 139, 140, 140, 140,
+	140, 141
+};
+
+static int16 mdp_scale_0p2_to_0p4_C3[MDP_SCALE_COEFF_NUM] = {
+	107, 108, 109, 109, 110, 111, 112, 113, 114, 115,
+	115, 116, 117, 117, 118, 119, 119, 120, 121, 123,
+	123, 124, 125, 125, 126, 127, 127, 128, 129, 130,
+	131, 131
+};
+
+static void mdp_update_scale_table(int index, int16 *c0, int16 *c1,
+				   int16 *c2, int16 *c3)
+{
+	int i, val;
+
+	for (i = 0; i < MDP_SCALE_COEFF_NUM; i++) {
+		val =
+		    ((MDP_SCALE_COEFF_MASK & c1[i]) << 16) |
+		    (MDP_SCALE_COEFF_MASK & c0[i]);
+		MDP_OUTP(MDP_PPP_SCALE_COEFF_LSBn(index), val);
+		val =
+		    ((MDP_SCALE_COEFF_MASK & c3[i]) << 16) |
+		    (MDP_SCALE_COEFF_MASK & c2[i]);
+		MDP_OUTP(MDP_PPP_SCALE_COEFF_MSBn(index), val);
+		index++;
+	}
+}
+
+void mdp_init_scale_table(void)
+{
+	mdp_scale_0p2_to_0p4_mode = MDP_SCALE_FIR;
+	mdp_update_scale_table(MDP_SCALE_0P2_TO_0P4_INDEX,
+			       mdp_scale_0p2_to_0p4_C0,
+			       mdp_scale_0p2_to_0p4_C1,
+			       mdp_scale_0p2_to_0p4_C2,
+			       mdp_scale_0p2_to_0p4_C3);
+
+	mdp_scale_0p4_to_0p6_mode = MDP_SCALE_FIR;
+	mdp_update_scale_table(MDP_SCALE_0P4_TO_0P6_INDEX,
+			       mdp_scale_0p4_to_0p6_C0,
+			       mdp_scale_0p4_to_0p6_C1,
+			       mdp_scale_0p4_to_0p6_C2,
+			       mdp_scale_0p4_to_0p6_C3);
+
+	mdp_scale_0p6_to_0p8_mode = MDP_SCALE_FIR;
+	mdp_update_scale_table(MDP_SCALE_0P6_TO_0P8_INDEX,
+			       mdp_scale_0p6_to_0p8_C0,
+			       mdp_scale_0p6_to_0p8_C1,
+			       mdp_scale_0p6_to_0p8_C2,
+			       mdp_scale_0p6_to_0p8_C3);
+
+	mdp_scale_0p8_to_8p0_mode = MDP_SCALE_FIR;
+	mdp_update_scale_table(MDP_SCALE_0P8_TO_8P0_INDEX,
+			       mdp_scale_0p8_to_8p0_C0,
+			       mdp_scale_0p8_to_8p0_C1,
+			       mdp_scale_0p8_to_8p0_C2,
+			       mdp_scale_0p8_to_8p0_C3);
+}
+
+static long long mdp_do_div(long long num, long long den)
+{
+	do_div(num, den);
+	return num;
+}
+
+#define SCALER_PHASE_BITS 29
+#define HAL_MDP_PHASE_STEP_2P50    0x50000000
+#define HAL_MDP_PHASE_STEP_1P66    0x35555555
+#define HAL_MDP_PHASE_STEP_1P25    0x28000000
+
+struct phase_val {
+	int phase_init_x;
+	int phase_init_y;
+	int phase_step_x;
+	int phase_step_y;
+};
+
+static void mdp_calc_scaleInitPhase_3p1(uint32 in_w,
+					uint32 in_h,
+					uint32 out_w,
+					uint32 out_h,
+					boolean is_rotate,
+					boolean is_pp_x,
+					boolean is_pp_y, struct phase_val *pval)
+{
+	uint64 dst_ROI_width;
+	uint64 dst_ROI_height;
+	uint64 src_ROI_width;
+	uint64 src_ROI_height;
+
+	/*
+	 * phase_step_x, phase_step_y, phase_init_x and phase_init_y
+	 * are represented in fixed-point, unsigned 3.29 format
+	 */
+	uint32 phase_step_x = 0;
+	uint32 phase_step_y = 0;
+	uint32 phase_init_x = 0;
+	uint32 phase_init_y = 0;
+	uint32 yscale_filter_sel, xscale_filter_sel;
+	uint32 scale_unit_sel_x, scale_unit_sel_y;
+
+	uint64 numerator, denominator;
+	uint64 temp_dim;
+
+	src_ROI_width = in_w;
+	src_ROI_height = in_h;
+	dst_ROI_width = out_w;
+	dst_ROI_height = out_h;
+
+	/* if there is a 90 degree rotation */
+	if (is_rotate) {
+		/* decide whether to use FIR or M/N for scaling */
+
+		/* if down-scaling by a factor smaller than 1/4 */
+		if (src_ROI_width > (4 * dst_ROI_height))
+			scale_unit_sel_x = 1;	/* use M/N scalar */
+		else
+			scale_unit_sel_x = 0;	/* use FIR scalar */
+
+		/* if down-scaling by a factor smaller than 1/4 */
+		if (src_ROI_height > (4 * dst_ROI_width))
+			scale_unit_sel_y = 1;	/* use M/N scalar */
+		else
+			scale_unit_sel_y = 0;	/* use FIR scalar */
+	} else {
+		/* decide whether to use FIR or M/N for scaling */
+
+		if (src_ROI_width > (4 * dst_ROI_width))
+			scale_unit_sel_x = 1;	/* use M/N scalar */
+		else
+			scale_unit_sel_x = 0;	/* use FIR scalar */
+
+		if (src_ROI_height > (4 * dst_ROI_height))
+			scale_unit_sel_y = 1;	/* use M/N scalar */
+		else
+			scale_unit_sel_y = 0;	/* use FIR scalar */
+
+	}
+
+	/* if there is a 90 degree rotation */
+	if (is_rotate) {
+		/* swap the width and height of dst ROI */
+		temp_dim = dst_ROI_width;
+		dst_ROI_width = dst_ROI_height;
+		dst_ROI_height = temp_dim;
+	}
+
+	/* calculate phase step for the x direction */
+
+	/* if destination is only 1 pixel wide, the value of phase_step_x
+	   is unimportant. Assigning phase_step_x to src ROI width
+	   as an arbitrary value. */
+	if (dst_ROI_width == 1)
+		phase_step_x = (uint32) ((src_ROI_width) << SCALER_PHASE_BITS);
+
+	/* if using FIR scalar */
+	else if (scale_unit_sel_x == 0) {
+
+		/* Calculate the quotient ( src_ROI_width - 1 ) / ( dst_ROI_width - 1)
+		   with u3.29 precision. Quotient is rounded up to the larger
+		   29th decimal point. */
+		numerator = (src_ROI_width - 1) << SCALER_PHASE_BITS;
+		denominator = (dst_ROI_width - 1);	/* never equals to 0 because of the "( dst_ROI_width == 1 ) case" */
+		phase_step_x = (uint32) mdp_do_div((numerator + denominator - 1), denominator);	/* divide and round up to the larger 29th decimal point. */
+
+	}
+
+	/* if M/N scalar */
+	else if (scale_unit_sel_x == 1) {
+		/* Calculate the quotient ( src_ROI_width ) / ( dst_ROI_width)
+		   with u3.29 precision. Quotient is rounded down to the
+		   smaller 29th decimal point. */
+		numerator = (src_ROI_width) << SCALER_PHASE_BITS;
+		denominator = (dst_ROI_width);
+		phase_step_x = (uint32) mdp_do_div(numerator, denominator);
+	}
+	/* calculate phase step for the y direction */
+
+	/* if destination is only 1 pixel wide, the value of
+	   phase_step_x is unimportant. Assigning phase_step_x
+	   to src ROI width as an arbitrary value. */
+	if (dst_ROI_height == 1)
+		phase_step_y = (uint32) ((src_ROI_height) << SCALER_PHASE_BITS);
+
+	/* if FIR scalar */
+	else if (scale_unit_sel_y == 0) {
+		/* Calculate the quotient ( src_ROI_height - 1 ) / ( dst_ROI_height - 1)
+		   with u3.29 precision. Quotient is rounded up to the larger
+		   29th decimal point. */
+		numerator = (src_ROI_height - 1) << SCALER_PHASE_BITS;
+		denominator = (dst_ROI_height - 1);	/* never equals to 0 because of the "( dst_ROI_height == 1 )" case */
+		phase_step_y = (uint32) mdp_do_div((numerator + denominator - 1), denominator);	/* Quotient is rounded up to the larger 29th decimal point. */
+
+	}
+
+	/* if M/N scalar */
+	else if (scale_unit_sel_y == 1) {
+		/* Calculate the quotient ( src_ROI_height ) / ( dst_ROI_height)
+		   with u3.29 precision. Quotient is rounded down to the smaller
+		   29th decimal point. */
+		numerator = (src_ROI_height) << SCALER_PHASE_BITS;
+		denominator = (dst_ROI_height);
+		phase_step_y = (uint32) mdp_do_div(numerator, denominator);
+	}
+
+	/* decide which set of FIR coefficients to use */
+	if (phase_step_x > HAL_MDP_PHASE_STEP_2P50)
+		xscale_filter_sel = 0;
+	else if (phase_step_x > HAL_MDP_PHASE_STEP_1P66)
+		xscale_filter_sel = 1;
+	else if (phase_step_x > HAL_MDP_PHASE_STEP_1P25)
+		xscale_filter_sel = 2;
+	else
+		xscale_filter_sel = 3;
+
+	if (phase_step_y > HAL_MDP_PHASE_STEP_2P50)
+		yscale_filter_sel = 0;
+	else if (phase_step_y > HAL_MDP_PHASE_STEP_1P66)
+		yscale_filter_sel = 1;
+	else if (phase_step_y > HAL_MDP_PHASE_STEP_1P25)
+		yscale_filter_sel = 2;
+	else
+		yscale_filter_sel = 3;
+
+	/* calculate phase init for the x direction */
+
+	/* if using FIR scalar */
+	if (scale_unit_sel_x == 0) {
+		if (dst_ROI_width == 1)
+			phase_init_x =
+			    (uint32) ((src_ROI_width - 1) << SCALER_PHASE_BITS);
+		else
+			phase_init_x = 0;
+
+	}
+	/* M over N scalar  */
+	else if (scale_unit_sel_x == 1)
+		phase_init_x = 0;
+
+	/* calculate phase init for the y direction
+	   if using FIR scalar */
+	if (scale_unit_sel_y == 0) {
+		if (dst_ROI_height == 1)
+			phase_init_y =
+			    (uint32) ((src_ROI_height -
+				       1) << SCALER_PHASE_BITS);
+		else
+			phase_init_y = 0;
+
+	}
+	/* M over N scalar   */
+	else if (scale_unit_sel_y == 1)
+		phase_init_y = 0;
+
+	/* write registers */
+	pval->phase_step_x = (uint32) phase_step_x;
+	pval->phase_step_y = (uint32) phase_step_y;
+	pval->phase_init_x = (uint32) phase_init_x;
+	pval->phase_init_y = (uint32) phase_init_y;
+
+	return;
+}
+
+void mdp_set_scale(MDPIBUF *iBuf,
+		   uint32 dst_roi_width,
+		   uint32 dst_roi_height,
+		   boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr)
+{
+	uint32 dst_roi_width_scale;
+	uint32 dst_roi_height_scale;
+	struct phase_val pval;
+	boolean use_pr;
+	uint32 ppp_scale_config = 0;
+
+	if (!inputRGB)
+		ppp_scale_config |= BIT(6);
+
+	if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {
+		if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+			dst_roi_width_scale = dst_roi_height;
+			dst_roi_height_scale = dst_roi_width;
+		} else {
+			dst_roi_width_scale = dst_roi_width;
+			dst_roi_height_scale = dst_roi_height;
+		}
+
+		if ((dst_roi_width_scale != iBuf->roi.width) ||
+		    (dst_roi_height_scale != iBuf->roi.height) ||
+			(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
+			*pppop_reg_ptr |=
+			    (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
+
+			mdp_calc_scaleInitPhase_3p1(iBuf->roi.width,
+						    iBuf->roi.height,
+						    dst_roi_width,
+						    dst_roi_height,
+						    iBuf->mdpImg.
+						    mdpOp & MDPOP_ROT90, 1, 1,
+						    &pval);
+
+			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c,
+				 pval.phase_init_x);
+			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140,
+				 pval.phase_init_y);
+			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144,
+				 pval.phase_step_x);
+			MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148,
+				 pval.phase_step_y);
+
+			use_pr = (inputRGB) && (outputRGB);
+
+			/* x-direction */
+			if ((dst_roi_width_scale == iBuf->roi.width) &&
+				!(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
+				*pppop_reg_ptr &= ~PPP_OP_SCALE_X_ON;
+			} else
+			    if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
+				8) {
+				if ((use_pr)
+				    && (mdp_scale_0p8_to_8p0_mode !=
+					MDP_SCALE_PR)) {
+					mdp_scale_0p8_to_8p0_mode =
+					    MDP_SCALE_PR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P8_TO_8P0_INDEX,
+					     mdp_scale_pixel_repeat_C0,
+					     mdp_scale_pixel_repeat_C1,
+					     mdp_scale_pixel_repeat_C2,
+					     mdp_scale_pixel_repeat_C3);
+				} else if ((!use_pr)
+					   && (mdp_scale_0p8_to_8p0_mode !=
+					       MDP_SCALE_FIR)) {
+					mdp_scale_0p8_to_8p0_mode =
+					    MDP_SCALE_FIR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P8_TO_8P0_INDEX,
+					     mdp_scale_0p8_to_8p0_C0,
+					     mdp_scale_0p8_to_8p0_C1,
+					     mdp_scale_0p8_to_8p0_C2,
+					     mdp_scale_0p8_to_8p0_C3);
+				}
+				ppp_scale_config |= (SCALE_U1_SET << 2);
+			} else
+			    if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
+				6) {
+				if ((use_pr)
+				    && (mdp_scale_0p6_to_0p8_mode !=
+					MDP_SCALE_PR)) {
+					mdp_scale_0p6_to_0p8_mode =
+					    MDP_SCALE_PR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P6_TO_0P8_INDEX,
+					     mdp_scale_pixel_repeat_C0,
+					     mdp_scale_pixel_repeat_C1,
+					     mdp_scale_pixel_repeat_C2,
+					     mdp_scale_pixel_repeat_C3);
+				} else if ((!use_pr)
+					   && (mdp_scale_0p6_to_0p8_mode !=
+					       MDP_SCALE_FIR)) {
+					mdp_scale_0p6_to_0p8_mode =
+					    MDP_SCALE_FIR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P6_TO_0P8_INDEX,
+					     mdp_scale_0p6_to_0p8_C0,
+					     mdp_scale_0p6_to_0p8_C1,
+					     mdp_scale_0p6_to_0p8_C2,
+					     mdp_scale_0p6_to_0p8_C3);
+				}
+				ppp_scale_config |= (SCALE_D2_SET << 2);
+			} else
+			    if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
+				4) {
+				if ((use_pr)
+				    && (mdp_scale_0p4_to_0p6_mode !=
+					MDP_SCALE_PR)) {
+					mdp_scale_0p4_to_0p6_mode =
+					    MDP_SCALE_PR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P4_TO_0P6_INDEX,
+					     mdp_scale_pixel_repeat_C0,
+					     mdp_scale_pixel_repeat_C1,
+					     mdp_scale_pixel_repeat_C2,
+					     mdp_scale_pixel_repeat_C3);
+				} else if ((!use_pr)
+					   && (mdp_scale_0p4_to_0p6_mode !=
+					       MDP_SCALE_FIR)) {
+					mdp_scale_0p4_to_0p6_mode =
+					    MDP_SCALE_FIR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P4_TO_0P6_INDEX,
+					     mdp_scale_0p4_to_0p6_C0,
+					     mdp_scale_0p4_to_0p6_C1,
+					     mdp_scale_0p4_to_0p6_C2,
+					     mdp_scale_0p4_to_0p6_C3);
+				}
+				ppp_scale_config |= (SCALE_D1_SET << 2);
+			} else
+			    if (((dst_roi_width_scale * 4) / iBuf->roi.width) >=
+				1) {
+				if ((use_pr)
+				    && (mdp_scale_0p2_to_0p4_mode !=
+					MDP_SCALE_PR)) {
+					mdp_scale_0p2_to_0p4_mode =
+					    MDP_SCALE_PR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P2_TO_0P4_INDEX,
+					     mdp_scale_pixel_repeat_C0,
+					     mdp_scale_pixel_repeat_C1,
+					     mdp_scale_pixel_repeat_C2,
+					     mdp_scale_pixel_repeat_C3);
+				} else if ((!use_pr)
+					   && (mdp_scale_0p2_to_0p4_mode !=
+					       MDP_SCALE_FIR)) {
+					mdp_scale_0p2_to_0p4_mode =
+					    MDP_SCALE_FIR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P2_TO_0P4_INDEX,
+					     mdp_scale_0p2_to_0p4_C0,
+					     mdp_scale_0p2_to_0p4_C1,
+					     mdp_scale_0p2_to_0p4_C2,
+					     mdp_scale_0p2_to_0p4_C3);
+				}
+				ppp_scale_config |= (SCALE_D0_SET << 2);
+			} else
+				ppp_scale_config |= BIT(0);
+
+			/* y-direction */
+			if ((dst_roi_height_scale == iBuf->roi.height) &&
+				!(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
+				*pppop_reg_ptr &= ~PPP_OP_SCALE_Y_ON;
+			} else if (((dst_roi_height_scale * 10) /
+					iBuf->roi.height) > 8) {
+				if ((use_pr)
+				    && (mdp_scale_0p8_to_8p0_mode !=
+					MDP_SCALE_PR)) {
+					mdp_scale_0p8_to_8p0_mode =
+					    MDP_SCALE_PR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P8_TO_8P0_INDEX,
+					     mdp_scale_pixel_repeat_C0,
+					     mdp_scale_pixel_repeat_C1,
+					     mdp_scale_pixel_repeat_C2,
+					     mdp_scale_pixel_repeat_C3);
+				} else if ((!use_pr)
+					   && (mdp_scale_0p8_to_8p0_mode !=
+					       MDP_SCALE_FIR)) {
+					mdp_scale_0p8_to_8p0_mode =
+					    MDP_SCALE_FIR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P8_TO_8P0_INDEX,
+					     mdp_scale_0p8_to_8p0_C0,
+					     mdp_scale_0p8_to_8p0_C1,
+					     mdp_scale_0p8_to_8p0_C2,
+					     mdp_scale_0p8_to_8p0_C3);
+				}
+				ppp_scale_config |= (SCALE_U1_SET << 4);
+			} else
+			    if (((dst_roi_height_scale * 10) /
+				 iBuf->roi.height) > 6) {
+				if ((use_pr)
+				    && (mdp_scale_0p6_to_0p8_mode !=
+					MDP_SCALE_PR)) {
+					mdp_scale_0p6_to_0p8_mode =
+					    MDP_SCALE_PR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P6_TO_0P8_INDEX,
+					     mdp_scale_pixel_repeat_C0,
+					     mdp_scale_pixel_repeat_C1,
+					     mdp_scale_pixel_repeat_C2,
+					     mdp_scale_pixel_repeat_C3);
+				} else if ((!use_pr)
+					   && (mdp_scale_0p6_to_0p8_mode !=
+					       MDP_SCALE_FIR)) {
+					mdp_scale_0p6_to_0p8_mode =
+					    MDP_SCALE_FIR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P6_TO_0P8_INDEX,
+					     mdp_scale_0p6_to_0p8_C0,
+					     mdp_scale_0p6_to_0p8_C1,
+					     mdp_scale_0p6_to_0p8_C2,
+					     mdp_scale_0p6_to_0p8_C3);
+				}
+				ppp_scale_config |= (SCALE_D2_SET << 4);
+			} else
+			    if (((dst_roi_height_scale * 10) /
+				 iBuf->roi.height) > 4) {
+				if ((use_pr)
+				    && (mdp_scale_0p4_to_0p6_mode !=
+					MDP_SCALE_PR)) {
+					mdp_scale_0p4_to_0p6_mode =
+					    MDP_SCALE_PR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P4_TO_0P6_INDEX,
+					     mdp_scale_pixel_repeat_C0,
+					     mdp_scale_pixel_repeat_C1,
+					     mdp_scale_pixel_repeat_C2,
+					     mdp_scale_pixel_repeat_C3);
+				} else if ((!use_pr)
+					   && (mdp_scale_0p4_to_0p6_mode !=
+					       MDP_SCALE_FIR)) {
+					mdp_scale_0p4_to_0p6_mode =
+					    MDP_SCALE_FIR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P4_TO_0P6_INDEX,
+					     mdp_scale_0p4_to_0p6_C0,
+					     mdp_scale_0p4_to_0p6_C1,
+					     mdp_scale_0p4_to_0p6_C2,
+					     mdp_scale_0p4_to_0p6_C3);
+				}
+				ppp_scale_config |= (SCALE_D1_SET << 4);
+			} else
+			    if (((dst_roi_height_scale * 4) /
+				 iBuf->roi.height) >= 1) {
+				if ((use_pr)
+				    && (mdp_scale_0p2_to_0p4_mode !=
+					MDP_SCALE_PR)) {
+					mdp_scale_0p2_to_0p4_mode =
+					    MDP_SCALE_PR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P2_TO_0P4_INDEX,
+					     mdp_scale_pixel_repeat_C0,
+					     mdp_scale_pixel_repeat_C1,
+					     mdp_scale_pixel_repeat_C2,
+					     mdp_scale_pixel_repeat_C3);
+				} else if ((!use_pr)
+					   && (mdp_scale_0p2_to_0p4_mode !=
+					       MDP_SCALE_FIR)) {
+					mdp_scale_0p2_to_0p4_mode =
+					    MDP_SCALE_FIR;
+					mdp_update_scale_table
+					    (MDP_SCALE_0P2_TO_0P4_INDEX,
+					     mdp_scale_0p2_to_0p4_C0,
+					     mdp_scale_0p2_to_0p4_C1,
+					     mdp_scale_0p2_to_0p4_C2,
+					     mdp_scale_0p2_to_0p4_C3);
+				}
+				ppp_scale_config |= (SCALE_D0_SET << 4);
+			} else
+				ppp_scale_config |= BIT(1);
+
+			if (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING) {
+				ppp_scale_config |= BIT(7);
+				MDP_OUTP(MDP_BASE + 0x50020,
+						iBuf->mdpImg.sp_value);
+			}
+
+			MDP_OUTP(MDP_BASE + 0x10230, ppp_scale_config);
+		} else {
+			iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE);
+		}
+	}
+}
+
+void mdp_adjust_start_addr(uint8 **src0,
+			   uint8 **src1,
+			   int v_slice,
+			   int h_slice,
+			   int x,
+			   int y,
+			   uint32 width,
+			   uint32 height, int bpp, MDPIBUF *iBuf, int layer)
+{
+	switch (layer) {
+	case 0:
+		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0200, (y << 16) | (x));
+		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0208,
+			 (height << 16) | (width));
+		break;
+
+	case 1:
+		/* MDP 3.1 HW bug workaround */
+		if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
+			*src0 += (x + y * width) * bpp;
+			x = y = 0;
+			width = iBuf->roi.dst_width;
+			height = iBuf->roi.dst_height;
+		}
+
+		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0204, (y << 16) | (x));
+		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x020c,
+			 (height << 16) | (width));
+		break;
+
+	case 2:
+		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x019c, (y << 16) | (x));
+		break;
+	}
+}
+
+void mdp_set_blend_attr(MDPIBUF *iBuf,
+			uint32 *alpha,
+			uint32 *tpVal,
+			uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
+{
+	int bg_alpha;
+
+	*alpha = iBuf->mdpImg.alpha;
+	*tpVal = iBuf->mdpImg.tpVal;
+
+	if (iBuf->mdpImg.mdpOp & MDPOP_FG_PM_ALPHA) {
+		*pppop_reg_ptr |= PPP_OP_ROT_ON |
+		    PPP_OP_BLEND_ON | PPP_OP_BLEND_CONSTANT_ALPHA;
+
+		bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL |
+				PPP_BLEND_BG_ALPHA_REVERSE;
+
+		if (perPixelAlpha)
+			bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA;
+		else
+			bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA;
+
+		outpdw(MDP_BASE + 0x70010, bg_alpha);
+
+		if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
+			*pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
+	} else if (perPixelAlpha) {
+		*pppop_reg_ptr |= PPP_OP_ROT_ON |
+		    PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
+	} else {
+		if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+		    && (iBuf->mdpImg.alpha == 0xff)) {
+			iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
+		}
+
+		if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+		    || (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+			*pppop_reg_ptr |=
+			    PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+			    PPP_OP_BLEND_CONSTANT_ALPHA |
+			    PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
+		}
+
+		if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
+			*pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
+	}
+}

+ 389 - 0
drivers/staging/msm/mdp_vsync.c

@@ -0,0 +1,389 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/vmalloc.h>
+#include <linux/clk.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <mach/gpio.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+#include "mddihost.h"
+
+#ifdef CONFIG_FB_MSM_MDP40
+#define MDP_SYNC_CFG_0		0x100
+#define MDP_SYNC_STATUS_0	0x10c
+#define MDP_PRIM_VSYNC_OUT_CTRL	0x118
+#define MDP_PRIM_VSYNC_INIT_VAL	0x128
+#else
+#define MDP_SYNC_CFG_0		0x300
+#define MDP_SYNC_STATUS_0	0x30c
+#define MDP_PRIM_VSYNC_OUT_CTRL	0x318
+#define MDP_PRIM_VSYNC_INIT_VAL	0x328
+#endif
+
+extern mddi_lcd_type mddi_lcd_idx;
+extern spinlock_t mdp_spin_lock;
+extern struct workqueue_struct *mdp_vsync_wq;
+extern int lcdc_mode;
+extern int vsync_mode;
+
+#ifdef MDP_HW_VSYNC
+int vsync_above_th = 4;
+int vsync_start_th = 1;
+int vsync_load_cnt;
+
+struct clk *mdp_vsync_clk;
+
+void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd)
+{
+	if (mfd->use_mdp_vsync)
+		clk_enable(mdp_vsync_clk);
+}
+
+void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd)
+{
+	if (mfd->use_mdp_vsync)
+		clk_disable(mdp_vsync_clk);
+}
+#endif
+
+static void mdp_set_vsync(unsigned long data)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
+	struct msm_fb_panel_data *pdata = NULL;
+
+	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+	if ((pdata) && (pdata->set_vsync_notifier == NULL))
+		return;
+
+	init_timer(&mfd->vsync_resync_timer);
+	mfd->vsync_resync_timer.function = mdp_set_vsync;
+	mfd->vsync_resync_timer.data = data;
+	mfd->vsync_resync_timer.expires =
+	    jiffies + mfd->panel_info.lcd.vsync_notifier_period;
+	add_timer(&mfd->vsync_resync_timer);
+
+	if ((mfd->panel_info.lcd.vsync_enable) && (mfd->panel_power_on)
+	    && (!mfd->vsync_handler_pending)) {
+		mfd->vsync_handler_pending = TRUE;
+		if (!queue_work(mdp_vsync_wq, &mfd->vsync_resync_worker)) {
+			MSM_FB_INFO
+			    ("mdp_set_vsync: can't queue_work! -> needs to increase vsync_resync_timer_duration\n");
+		}
+	} else {
+		MSM_FB_DEBUG
+		    ("mdp_set_vsync failed!  EN:%d  PWR:%d  PENDING:%d\n",
+		     mfd->panel_info.lcd.vsync_enable, mfd->panel_power_on,
+		     mfd->vsync_handler_pending);
+	}
+}
+
+static void mdp_vsync_handler(void *data)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
+
+	if (mfd->use_mdp_vsync) {
+#ifdef MDP_HW_VSYNC
+		if (mfd->panel_power_on)
+			MDP_OUTP(MDP_BASE + MDP_SYNC_STATUS_0, vsync_load_cnt);
+
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+#endif
+	} else {
+		mfd->last_vsync_timetick = ktime_get_real();
+	}
+
+	mfd->vsync_handler_pending = FALSE;
+}
+
+irqreturn_t mdp_hw_vsync_handler_proxy(int irq, void *data)
+{
+	/*
+	 * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt
+	 * but getting inaccurate timing in mdp_vsync_handler()
+	 * disable_irq(MDP_HW_VSYNC_IRQ);
+	 */
+	mdp_vsync_handler(data);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef MDP_HW_VSYNC
+static void mdp_set_sync_cfg_0(struct msm_fb_data_type *mfd, int vsync_cnt)
+{
+	unsigned long cfg;
+
+	cfg = mfd->total_lcd_lines - 1;
+	cfg <<= MDP_SYNCFG_HGT_LOC;
+	if (mfd->panel_info.lcd.hw_vsync_mode)
+		cfg |= MDP_SYNCFG_VSYNC_EXT_EN;
+	cfg |= (MDP_SYNCFG_VSYNC_INT_EN | vsync_cnt);
+
+	MDP_OUTP(MDP_BASE + MDP_SYNC_CFG_0, cfg);
+}
+#endif
+
+void mdp_config_vsync(struct msm_fb_data_type *mfd)
+{
+
+	/* vsync on primary lcd only for now */
+	if ((mfd->dest != DISPLAY_LCD) || (mfd->panel_info.pdest != DISPLAY_1)
+	    || (!vsync_mode)) {
+		goto err_handle;
+	}
+
+	if (mfd->panel_info.lcd.vsync_enable) {
+		mfd->total_porch_lines = mfd->panel_info.lcd.v_back_porch +
+		    mfd->panel_info.lcd.v_front_porch +
+		    mfd->panel_info.lcd.v_pulse_width;
+		mfd->total_lcd_lines =
+		    mfd->panel_info.yres + mfd->total_porch_lines;
+		mfd->lcd_ref_usec_time =
+		    100000000 / mfd->panel_info.lcd.refx100;
+		mfd->vsync_handler_pending = FALSE;
+		mfd->last_vsync_timetick.tv.sec = 0;
+		mfd->last_vsync_timetick.tv.nsec = 0;
+
+#ifdef MDP_HW_VSYNC
+		if (mdp_vsync_clk == NULL)
+			mdp_vsync_clk = clk_get(NULL, "mdp_vsync_clk");
+
+		if (IS_ERR(mdp_vsync_clk)) {
+			printk(KERN_ERR "error: can't get mdp_vsync_clk!\n");
+			mfd->use_mdp_vsync = 0;
+		} else
+			mfd->use_mdp_vsync = 1;
+
+		if (mfd->use_mdp_vsync) {
+			uint32 vsync_cnt_cfg, vsync_cnt_cfg_dem;
+			uint32 mdp_vsync_clk_speed_hz;
+
+			mdp_vsync_clk_speed_hz = clk_get_rate(mdp_vsync_clk);
+
+			if (mdp_vsync_clk_speed_hz == 0) {
+				mfd->use_mdp_vsync = 0;
+			} else {
+				/*
+				 * Do this calculation in 2 steps for
+				 * rounding uint32 properly.
+				 */
+				vsync_cnt_cfg_dem =
+				    (mfd->panel_info.lcd.refx100 *
+				     mfd->total_lcd_lines) / 100;
+				vsync_cnt_cfg =
+				    (mdp_vsync_clk_speed_hz) /
+				    vsync_cnt_cfg_dem;
+
+				/* MDP cmd block enable */
+				mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON,
+					      FALSE);
+				mdp_hw_vsync_clk_enable(mfd);
+
+				mdp_set_sync_cfg_0(mfd, vsync_cnt_cfg);
+
+				/*
+				 * load the last line + 1 to be in the
+				 * safety zone
+				 */
+				vsync_load_cnt = mfd->panel_info.yres;
+
+				/* line counter init value at the next pulse */
+				MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_INIT_VAL,
+							vsync_load_cnt);
+
+				/*
+				 * external vsync source pulse width and
+				 * polarity flip
+				 */
+				MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_OUT_CTRL,
+							BIT(30) | BIT(0));
+
+
+				/* threshold */
+				MDP_OUTP(MDP_BASE + 0x200,
+					 (vsync_above_th << 16) |
+					 (vsync_start_th));
+
+				mdp_hw_vsync_clk_disable(mfd);
+				/* MDP cmd block disable */
+				mdp_pipe_ctrl(MDP_CMD_BLOCK,
+					      MDP_BLOCK_POWER_OFF, FALSE);
+			}
+		}
+#else
+		mfd->use_mdp_vsync = 0;
+		hrtimer_init(&mfd->dma_hrtimer, CLOCK_MONOTONIC,
+			     HRTIMER_MODE_REL);
+		mfd->dma_hrtimer.function = mdp_dma2_vsync_hrtimer_handler;
+		mfd->vsync_width_boundary = vmalloc(mfd->panel_info.xres * 4);
+#endif
+
+		mfd->channel_irq = 0;
+		if (mfd->panel_info.lcd.hw_vsync_mode) {
+			u32 vsync_gpio = mfd->vsync_gpio;
+			u32 ret;
+
+			if (vsync_gpio == -1) {
+				MSM_FB_INFO("vsync_gpio not defined!\n");
+				goto err_handle;
+			}
+
+			ret = gpio_tlmm_config(GPIO_CFG
+					(vsync_gpio,
+					(mfd->use_mdp_vsync) ? 1 : 0,
+					GPIO_INPUT,
+					GPIO_PULL_DOWN,
+					GPIO_2MA),
+					GPIO_ENABLE);
+			if (ret)
+				goto err_handle;
+
+			if (!mfd->use_mdp_vsync) {
+				mfd->channel_irq = MSM_GPIO_TO_INT(vsync_gpio);
+				if (request_irq
+				    (mfd->channel_irq,
+				     &mdp_hw_vsync_handler_proxy,
+				     IRQF_TRIGGER_FALLING, "VSYNC_GPIO",
+				     (void *)mfd)) {
+					MSM_FB_INFO
+					("irq=%d failed! vsync_gpio=%d\n",
+						mfd->channel_irq,
+						vsync_gpio);
+					goto err_handle;
+				}
+			}
+		}
+
+		mdp_set_vsync((unsigned long)mfd);
+	}
+
+	return;
+
+err_handle:
+	if (mfd->vsync_width_boundary)
+		vfree(mfd->vsync_width_boundary);
+	mfd->panel_info.lcd.vsync_enable = FALSE;
+	printk(KERN_ERR "%s: failed!\n", __func__);
+}
+
+void mdp_vsync_resync_workqueue_handler(struct work_struct *work)
+{
+	struct msm_fb_data_type *mfd = NULL;
+	int vsync_fnc_enabled = FALSE;
+	struct msm_fb_panel_data *pdata = NULL;
+
+	mfd = container_of(work, struct msm_fb_data_type, vsync_resync_worker);
+
+	if (mfd) {
+		if (mfd->panel_power_on) {
+			pdata =
+			    (struct msm_fb_panel_data *)mfd->pdev->dev.
+			    platform_data;
+
+			/*
+			 * we need to turn on MDP power if it uses MDP vsync
+			 * HW block in SW mode
+			 */
+			if ((!mfd->panel_info.lcd.hw_vsync_mode) &&
+			    (mfd->use_mdp_vsync) &&
+			    (pdata) && (pdata->set_vsync_notifier != NULL)) {
+				/*
+				 * enable pwr here since we can't enable it in
+				 * vsync callback in isr mode
+				 */
+				mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON,
+					      FALSE);
+			}
+
+			if (pdata->set_vsync_notifier != NULL) {
+				vsync_fnc_enabled = TRUE;
+				pdata->set_vsync_notifier(mdp_vsync_handler,
+							  (void *)mfd);
+			}
+		}
+	}
+
+	if ((mfd) && (!vsync_fnc_enabled))
+		mfd->vsync_handler_pending = FALSE;
+}
+
+boolean mdp_hw_vsync_set_handler(msm_fb_vsync_handler_type handler, void *data)
+{
+	/*
+	 * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt
+	 * but getting inaccurate timing in mdp_vsync_handler()
+	 * enable_irq(MDP_HW_VSYNC_IRQ);
+	 */
+
+	return TRUE;
+}
+
+uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd)
+{
+	uint32 elapsed_usec_time;
+	uint32 lcd_line;
+	ktime_t last_vsync_timetick_local;
+	ktime_t curr_time;
+	unsigned long flag;
+
+	if ((!mfd->panel_info.lcd.vsync_enable) || (!vsync_mode))
+		return 0;
+
+	spin_lock_irqsave(&mdp_spin_lock, flag);
+	last_vsync_timetick_local = mfd->last_vsync_timetick;
+	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+	curr_time = ktime_get_real();
+	elapsed_usec_time =
+	    ((curr_time.tv.sec - last_vsync_timetick_local.tv.sec) * 1000000) +
+	    ((curr_time.tv.nsec - last_vsync_timetick_local.tv.nsec) / 1000);
+
+	elapsed_usec_time = elapsed_usec_time % mfd->lcd_ref_usec_time;
+
+	/* lcd line calculation referencing to line counter = 0 */
+	lcd_line =
+	    (elapsed_usec_time * mfd->total_lcd_lines) / mfd->lcd_ref_usec_time;
+
+	/* lcd line adjusment referencing to the actual line counter at vsync */
+	lcd_line =
+	    (mfd->total_lcd_lines - mfd->panel_info.lcd.v_back_porch +
+	     lcd_line) % (mfd->total_lcd_lines + 1);
+
+	if (lcd_line > mfd->total_lcd_lines) {
+		MSM_FB_INFO
+		    ("mdp_get_lcd_line_counter: mdp_lcd_rd_cnt >= mfd->total_lcd_lines error!\n");
+	}
+
+	return lcd_line;
+}

+ 214 - 0
drivers/staging/msm/memory.c

@@ -0,0 +1,214 @@
+/* arch/arm/mach-msm/memory.c
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/mm.h>
+#include <linux/mm_types.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/mach/map.h>
+#include "memory_ll.h"
+#include <asm/cacheflush.h>
+#if defined(CONFIG_MSM_NPA_REMOTE)
+#include "npa_remote.h"
+#include <linux/completion.h>
+#include <linux/err.h>
+#endif
+
+int arch_io_remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
+			    unsigned long pfn, unsigned long size, pgprot_t prot)
+{
+	unsigned long pfn_addr = pfn << PAGE_SHIFT;
+/*
+	if ((pfn_addr >= 0x88000000) && (pfn_addr < 0xD0000000)) {
+		prot = pgprot_device(prot);
+		printk("remapping device %lx\n", prot);
+	}
+*/
+	panic("Memory remap PFN stuff not done\n");
+	return remap_pfn_range(vma, addr, pfn, size, prot);
+}
+
+void *zero_page_strongly_ordered;
+
+static void map_zero_page_strongly_ordered(void)
+{
+	if (zero_page_strongly_ordered)
+		return;
+/*
+	zero_page_strongly_ordered =
+		ioremap_strongly_ordered(page_to_pfn(empty_zero_page)
+		<< PAGE_SHIFT, PAGE_SIZE);
+*/
+	panic("Strongly ordered memory functions not implemented\n");
+}
+
+void write_to_strongly_ordered_memory(void)
+{
+	map_zero_page_strongly_ordered();
+	*(int *)zero_page_strongly_ordered = 0;
+}
+EXPORT_SYMBOL(write_to_strongly_ordered_memory);
+
+void flush_axi_bus_buffer(void)
+{
+	__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
+				    : : "r" (0) : "memory");
+	write_to_strongly_ordered_memory();
+}
+
+#define CACHE_LINE_SIZE 32
+
+/* These cache related routines make the assumption that the associated
+ * physical memory is contiguous. They will operate on all (L1
+ * and L2 if present) caches.
+ */
+void clean_and_invalidate_caches(unsigned long vstart,
+	unsigned long length, unsigned long pstart)
+{
+	unsigned long vaddr;
+
+	for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
+		asm ("mcr p15, 0, %0, c7, c14, 1" : : "r" (vaddr));
+#ifdef CONFIG_OUTER_CACHE
+	outer_flush_range(pstart, pstart + length);
+#endif
+	asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
+	asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
+
+	flush_axi_bus_buffer();
+}
+
+void clean_caches(unsigned long vstart,
+	unsigned long length, unsigned long pstart)
+{
+	unsigned long vaddr;
+
+	for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
+		asm ("mcr p15, 0, %0, c7, c10, 1" : : "r" (vaddr));
+#ifdef CONFIG_OUTER_CACHE
+	outer_clean_range(pstart, pstart + length);
+#endif
+	asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
+	asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
+
+	flush_axi_bus_buffer();
+}
+
+void invalidate_caches(unsigned long vstart,
+	unsigned long length, unsigned long pstart)
+{
+	unsigned long vaddr;
+
+	for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE)
+		asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (vaddr));
+#ifdef CONFIG_OUTER_CACHE
+	outer_inv_range(pstart, pstart + length);
+#endif
+	asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
+	asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0));
+
+	flush_axi_bus_buffer();
+}
+
+void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
+{
+	void *unused_addr = NULL;
+	unsigned long addr, tmp_size, unused_size;
+
+	/* Allocate maximum size needed, see where it ends up.
+	 * Then free it -- in this path there are no other allocators
+	 * so we can depend on getting the same address back
+	 * when we allocate a smaller piece that is aligned
+	 * at the end (if necessary) and the piece we really want,
+	 * then free the unused first piece.
+	 */
+
+	tmp_size = size + alignment - PAGE_SIZE;
+	addr = (unsigned long)alloc_bootmem(tmp_size);
+	free_bootmem(__pa(addr), tmp_size);
+
+	unused_size = alignment - (addr % alignment);
+	if (unused_size)
+		unused_addr = alloc_bootmem(unused_size);
+
+	addr = (unsigned long)alloc_bootmem(size);
+	if (unused_size)
+		free_bootmem(__pa(unused_addr), unused_size);
+
+	return (void *)addr;
+}
+
+#if defined(CONFIG_MSM_NPA_REMOTE)
+struct npa_client *npa_memory_client;
+#endif
+
+static int change_memory_power_state(unsigned long start_pfn,
+	unsigned long nr_pages, int state)
+{
+#if defined(CONFIG_MSM_NPA_REMOTE)
+	static atomic_t node_created_flag = ATOMIC_INIT(1);
+#else
+	unsigned long start;
+	unsigned long size;
+	unsigned long virtual;
+#endif
+	int rc = 0;
+
+#if defined(CONFIG_MSM_NPA_REMOTE)
+	if (atomic_dec_and_test(&node_created_flag)) {
+		/* Create NPA 'required' client. */
+		npa_memory_client = npa_create_sync_client(NPA_MEMORY_NODE_NAME,
+			"memory node", NPA_CLIENT_REQUIRED);
+		if (IS_ERR(npa_memory_client)) {
+			rc = PTR_ERR(npa_memory_client);
+			return rc;
+		}
+	}
+
+	rc = npa_issue_required_request(npa_memory_client, state);
+#else
+	if (state == MEMORY_DEEP_POWERDOWN) {
+		/* simulate turning off memory by writing bit pattern into it */
+		start = start_pfn << PAGE_SHIFT;
+		size = nr_pages << PAGE_SHIFT;
+		virtual = __phys_to_virt(start);
+		memset((void *)virtual, 0x27, size);
+	}
+#endif
+	return rc;
+}
+
+int platform_physical_remove_pages(unsigned long start_pfn,
+	unsigned long nr_pages)
+{
+	return change_memory_power_state(start_pfn, nr_pages,
+		MEMORY_DEEP_POWERDOWN);
+}
+
+int platform_physical_add_pages(unsigned long start_pfn,
+	unsigned long nr_pages)
+{
+	return change_memory_power_state(start_pfn, nr_pages, MEMORY_ACTIVE);
+}
+
+int platform_physical_low_power_pages(unsigned long start_pfn,
+	unsigned long nr_pages)
+{
+	return change_memory_power_state(start_pfn, nr_pages,
+		MEMORY_SELF_REFRESH);
+}

+ 61 - 0
drivers/staging/msm/memory_ll.h

@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+#ifndef __ASM_ARCH_MEMORY_LL_H
+#define __ASM_ARCH_MEMORY_LL_H
+
+#define MAX_PHYSMEM_BITS 32
+#define SECTION_SIZE_BITS 25
+
+#define HAS_ARCH_IO_REMAP_PFN_RANGE
+
+#ifndef __ASSEMBLY__
+void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment);
+void clean_and_invalidate_caches(unsigned long, unsigned long, unsigned long);
+void clean_caches(unsigned long, unsigned long, unsigned long);
+void invalidate_caches(unsigned long, unsigned long, unsigned long);
+int platform_physical_remove_pages(unsigned long, unsigned long);
+int platform_physical_add_pages(unsigned long, unsigned long);
+int platform_physical_low_power_pages(unsigned long, unsigned long);
+
+#ifdef CONFIG_ARCH_MSM_ARM11
+void write_to_strongly_ordered_memory(void);
+
+#include <asm/mach-types.h>
+
+#define arch_barrier_extra() do \
+	{ if (machine_is_msm7x27_surf() || machine_is_msm7x27_ffa())  \
+		write_to_strongly_ordered_memory(); \
+	} while (0)
+#endif
+
+#ifdef CONFIG_CACHE_L2X0
+extern void l2x0_cache_sync(void);
+#define finish_arch_switch(prev)     do { l2x0_cache_sync(); } while (0)
+#endif
+
+#endif
+
+#ifdef CONFIG_ARCH_MSM_SCORPION
+#define arch_has_speculative_dfetch()	1
+#endif
+
+#endif
+
+/* these correspond to values known by the modem */
+#define MEMORY_DEEP_POWERDOWN	0
+#define MEMORY_SELF_REFRESH	1
+#define MEMORY_ACTIVE		2
+
+#define NPA_MEMORY_NODE_NAME	"/mem/ebi1/cs1"

+ 2354 - 0
drivers/staging/msm/msm_fb.c

@@ -0,0 +1,2354 @@
+/*
+ *
+ * Core MSM framebuffer driver.
+ *
+ * Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include "msm_mdp.h"
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <mach/board.h>
+#include <linux/uaccess.h>
+
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+#include <linux/console.h>
+#include <linux/leds.h>
+#include <asm/dma-mapping.h>
+
+
+#define MSM_FB_C
+#include "msm_fb.h"
+#include "mddihosti.h"
+#include "tvenc.h"
+#include "mdp.h"
+#include "mdp4.h"
+
+#ifdef CONFIG_FB_MSM_LOGO
+#define INIT_IMAGE_FILE "/logo.rle"
+extern int load_565rle_image(char *filename);
+#endif
+
+
+#define pgprot_noncached(prot) \
+       __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
+#define pgprot_writecombine(prot) \
+       __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
+#define pgprot_device(prot) \
+       __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_DEV_NONSHARED)
+#define pgprot_writethroughcache(prot) \
+       __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITETHROUGH)
+#define pgprot_writebackcache(prot) \
+       __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEBACK)
+#define pgprot_writebackwacache(prot) \
+       __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEALLOC)
+
+static unsigned char *fbram;
+static unsigned char *fbram_phys;
+static int fbram_size;
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+
+int vsync_mode = 1;
+
+#define MAX_FBI_LIST 32
+static struct fb_info *fbi_list[MAX_FBI_LIST];
+static int fbi_list_index;
+
+static struct msm_fb_data_type *mfd_list[MAX_FBI_LIST];
+static int mfd_list_index;
+
+static u32 msm_fb_pseudo_palette[16] = {
+	0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
+};
+
+u32 msm_fb_debug_enabled;
+/* Setting msm_fb_msg_level to 8 prints out ALL messages */
+u32 msm_fb_msg_level = 7;
+
+/* Setting mddi_msg_level to 8 prints out ALL messages */
+u32 mddi_msg_level = 5;
+
+extern int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
+extern unsigned long mdp_timer_duration;
+
+static int msm_fb_register(struct msm_fb_data_type *mfd);
+static int msm_fb_open(struct fb_info *info, int user);
+static int msm_fb_release(struct fb_info *info, int user);
+static int msm_fb_pan_display(struct fb_var_screeninfo *var,
+			      struct fb_info *info);
+static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd);
+int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd);
+static int msm_fb_check_var(struct fb_var_screeninfo *var,
+			    struct fb_info *info);
+static int msm_fb_set_par(struct fb_info *info);
+static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
+			    boolean op_enable);
+static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd);
+static int msm_fb_resume_sub(struct msm_fb_data_type *mfd);
+static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
+			unsigned long arg);
+static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma);
+
+#ifdef MSM_FB_ENABLE_DBGFS
+
+#define MSM_FB_MAX_DBGFS 1024
+#define MAX_BACKLIGHT_BRIGHTNESS 255
+
+int msm_fb_debugfs_file_index;
+struct dentry *msm_fb_debugfs_root;
+struct dentry *msm_fb_debugfs_file[MSM_FB_MAX_DBGFS];
+
+struct dentry *msm_fb_get_debugfs_root(void)
+{
+	if (msm_fb_debugfs_root == NULL)
+		msm_fb_debugfs_root = debugfs_create_dir("msm_fb", NULL);
+
+	return msm_fb_debugfs_root;
+}
+
+void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
+				u32 *var)
+{
+	if (msm_fb_debugfs_file_index >= MSM_FB_MAX_DBGFS)
+		return;
+
+	msm_fb_debugfs_file[msm_fb_debugfs_file_index++] =
+	    debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var);
+}
+#endif
+
+int msm_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+	if (!mfd->cursor_update)
+		return -ENODEV;
+
+	return mfd->cursor_update(info, cursor);
+}
+
+static int msm_fb_resource_initialized;
+
+#ifndef CONFIG_FB_BACKLIGHT
+static int lcd_backlight_registered;
+
+static void msm_fb_set_bl_brightness(struct led_classdev *led_cdev,
+					enum led_brightness value)
+{
+	struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
+	int bl_lvl;
+
+	if (value > MAX_BACKLIGHT_BRIGHTNESS)
+		value = MAX_BACKLIGHT_BRIGHTNESS;
+
+	/* This maps android backlight level 0 to 255 into
+	   driver backlight level 0 to bl_max with rounding */
+	bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS)
+		/(2 * MAX_BACKLIGHT_BRIGHTNESS);
+
+	if (!bl_lvl && value)
+		bl_lvl = 1;
+
+	msm_fb_set_backlight(mfd, bl_lvl, 1);
+}
+
+static struct led_classdev backlight_led = {
+	.name		= "lcd-backlight",
+	.brightness	= MAX_BACKLIGHT_BRIGHTNESS,
+	.brightness_set	= msm_fb_set_bl_brightness,
+};
+#endif
+
+static struct msm_fb_platform_data *msm_fb_pdata;
+
+int msm_fb_detect_client(const char *name)
+{
+	int ret = -EPERM;
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+	u32 id;
+#endif
+
+	if (msm_fb_pdata && msm_fb_pdata->detect_client) {
+		ret = msm_fb_pdata->detect_client(name);
+
+		/* if it's non mddi panel, we need to pre-scan
+		   mddi client to see if we can disable mddi host */
+
+#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
+		if (!ret && msm_fb_pdata->mddi_prescan)
+			id = mddi_get_client_id();
+#endif
+	}
+
+	return ret;
+}
+
+static int msm_fb_probe(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+	int rc;
+
+	MSM_FB_DEBUG("msm_fb_probe\n");
+
+	if ((pdev->id == 0) && (pdev->num_resources > 0)) {
+		msm_fb_pdata = pdev->dev.platform_data;
+		fbram_size =
+			pdev->resource[0].end - pdev->resource[0].start + 1;
+		fbram_phys = (char *)pdev->resource[0].start;
+		fbram = ioremap((unsigned long)fbram_phys, fbram_size);
+
+		if (!fbram) {
+			printk(KERN_ERR "fbram ioremap failed!\n");
+			return -ENOMEM;
+		}
+		MSM_FB_INFO("msm_fb_probe:  phy_Addr = 0x%x virt = 0x%x\n",
+			     (int)fbram_phys, (int)fbram);
+
+		msm_fb_resource_initialized = 1;
+		return 0;
+	}
+
+	if (!msm_fb_resource_initialized)
+		return -EPERM;
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+		return -ENOMEM;
+
+	mfd->panel_info.frame_count = 0;
+	mfd->bl_level = mfd->panel_info.bl_max;
+
+	if (mfd->panel_info.type == LCDC_PANEL)
+		mfd->allow_set_offset =
+		msm_fb_pdata->allow_set_offset != NULL ?
+		msm_fb_pdata->allow_set_offset() : 0;
+	else
+		mfd->allow_set_offset = 0;
+
+	rc = msm_fb_register(mfd);
+	if (rc)
+		return rc;
+
+#ifdef CONFIG_FB_BACKLIGHT
+	msm_fb_config_backlight(mfd);
+#else
+	/* android supports only one lcd-backlight/lcd for now */
+	if (!lcd_backlight_registered) {
+		if (led_classdev_register(&pdev->dev, &backlight_led))
+			printk(KERN_ERR "led_classdev_register failed\n");
+		else
+			lcd_backlight_registered = 1;
+	}
+#endif
+
+	pdev_list[pdev_list_cnt++] = pdev;
+	return 0;
+}
+
+static int msm_fb_remove(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+
+	MSM_FB_DEBUG("msm_fb_remove\n");
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (msm_fb_suspend_sub(mfd))
+		printk(KERN_ERR "msm_fb_remove: can't stop the device %d\n", mfd->index);
+
+	if (mfd->channel_irq != 0)
+		free_irq(mfd->channel_irq, (void *)mfd);
+
+	if (mfd->vsync_width_boundary)
+		vfree(mfd->vsync_width_boundary);
+
+	if (mfd->vsync_resync_timer.function)
+		del_timer(&mfd->vsync_resync_timer);
+
+	if (mfd->refresh_timer.function)
+		del_timer(&mfd->refresh_timer);
+
+	if (mfd->dma_hrtimer.function)
+		hrtimer_cancel(&mfd->dma_hrtimer);
+
+	/* remove /dev/fb* */
+	unregister_framebuffer(mfd->fbi);
+
+#ifdef CONFIG_FB_BACKLIGHT
+	/* remove /sys/class/backlight */
+	backlight_device_unregister(mfd->fbi->bl_dev);
+#else
+	if (lcd_backlight_registered) {
+		lcd_backlight_registered = 0;
+		led_classdev_unregister(&backlight_led);
+	}
+#endif
+
+#ifdef MSM_FB_ENABLE_DBGFS
+	if (mfd->sub_dir)
+		debugfs_remove(mfd->sub_dir);
+#endif
+
+	return 0;
+}
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int msm_fb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct msm_fb_data_type *mfd;
+	int ret = 0;
+
+	MSM_FB_DEBUG("msm_fb_suspend\n");
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+	if ((!mfd) || (mfd->key != MFD_KEY))
+		return 0;
+
+	acquire_console_sem();
+	fb_set_suspend(mfd->fbi, 1);
+
+	ret = msm_fb_suspend_sub(mfd);
+	if (ret != 0) {
+		printk(KERN_ERR "msm_fb: failed to suspend! %d\n", ret);
+		fb_set_suspend(mfd->fbi, 0);
+	} else {
+		pdev->dev.power.power_state = state;
+	}
+
+	release_console_sem();
+	return ret;
+}
+#else
+#define msm_fb_suspend NULL
+#endif
+
+static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd)
+{
+	int ret = 0;
+
+	if ((!mfd) || (mfd->key != MFD_KEY))
+		return 0;
+
+	/*
+	 * suspend this channel
+	 */
+	mfd->suspend.sw_refreshing_enable = mfd->sw_refreshing_enable;
+	mfd->suspend.op_enable = mfd->op_enable;
+	mfd->suspend.panel_power_on = mfd->panel_power_on;
+
+	if (mfd->op_enable) {
+		ret =
+		     msm_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi,
+				      mfd->suspend.op_enable);
+		if (ret) {
+			MSM_FB_INFO
+			    ("msm_fb_suspend: can't turn off display!\n");
+			return ret;
+		}
+		mfd->op_enable = FALSE;
+	}
+	/*
+	 * try to power down
+	 */
+	mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+	/*
+	 * detach display channel irq if there's any
+	 * or wait until vsync-resync completes
+	 */
+	if ((mfd->dest == DISPLAY_LCD)) {
+		if (mfd->panel_info.lcd.vsync_enable) {
+			if (mfd->panel_info.lcd.hw_vsync_mode) {
+				if (mfd->channel_irq != 0)
+					disable_irq(mfd->channel_irq);
+			} else {
+				volatile boolean vh_pending;
+				do {
+					vh_pending = mfd->vsync_handler_pending;
+				} while (vh_pending);
+			}
+		}
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+static int msm_fb_resume(struct platform_device *pdev)
+{
+	/* This resume function is called when interrupt is enabled.
+	 */
+	int ret = 0;
+	struct msm_fb_data_type *mfd;
+
+	MSM_FB_DEBUG("msm_fb_resume\n");
+
+	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+
+	if ((!mfd) || (mfd->key != MFD_KEY))
+		return 0;
+
+	acquire_console_sem();
+	ret = msm_fb_resume_sub(mfd);
+	pdev->dev.power.power_state = PMSG_ON;
+	fb_set_suspend(mfd->fbi, 1);
+	release_console_sem();
+
+	return ret;
+}
+#else
+#define msm_fb_resume NULL
+#endif
+
+static int msm_fb_resume_sub(struct msm_fb_data_type *mfd)
+{
+	int ret = 0;
+
+	if ((!mfd) || (mfd->key != MFD_KEY))
+		return 0;
+
+	/* attach display channel irq if there's any */
+	if (mfd->channel_irq != 0)
+		enable_irq(mfd->channel_irq);
+
+	/* resume state var recover */
+	mfd->sw_refreshing_enable = mfd->suspend.sw_refreshing_enable;
+	mfd->op_enable = mfd->suspend.op_enable;
+
+	if (mfd->suspend.panel_power_on) {
+		ret =
+		     msm_fb_blank_sub(FB_BLANK_UNBLANK, mfd->fbi,
+				      mfd->op_enable);
+		if (ret)
+			MSM_FB_INFO("msm_fb_resume: can't turn on display!\n");
+	}
+
+	return ret;
+}
+
+static struct platform_driver msm_fb_driver = {
+	.probe = msm_fb_probe,
+	.remove = msm_fb_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+	.suspend = msm_fb_suspend,
+	.resume = msm_fb_resume,
+#endif
+	.shutdown = NULL,
+	.driver = {
+		   /* Driver name must match the device name added in platform.c. */
+		   .name = "msm_fb",
+		   },
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void msmfb_early_suspend(struct early_suspend *h)
+{
+	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+						    early_suspend);
+	msm_fb_suspend_sub(mfd);
+}
+
+static void msmfb_early_resume(struct early_suspend *h)
+{
+	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
+						    early_suspend);
+	msm_fb_resume_sub(mfd);
+}
+#endif
+
+void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl, u32 save)
+{
+	struct msm_fb_panel_data *pdata;
+
+	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+	if ((pdata) && (pdata->set_backlight)) {
+		down(&mfd->sem);
+		if ((bkl_lvl != mfd->bl_level) || (!save)) {
+			u32 old_lvl;
+
+			old_lvl = mfd->bl_level;
+			mfd->bl_level = bkl_lvl;
+			pdata->set_backlight(mfd);
+
+			if (!save)
+				mfd->bl_level = old_lvl;
+		}
+		up(&mfd->sem);
+	}
+}
+
+static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
+			    boolean op_enable)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct msm_fb_panel_data *pdata = NULL;
+	int ret = 0;
+
+	if (!op_enable)
+		return -EPERM;
+
+	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+	if ((!pdata) || (!pdata->on) || (!pdata->off)) {
+		printk(KERN_ERR "msm_fb_blank_sub: no panel operation detected!\n");
+		return -ENODEV;
+	}
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		if (!mfd->panel_power_on) {
+			mdelay(100);
+			ret = pdata->on(mfd->pdev);
+			if (ret == 0) {
+				mfd->panel_power_on = TRUE;
+
+				msm_fb_set_backlight(mfd,
+						     mfd->bl_level, 0);
+
+/* ToDo: possible conflict with android which doesn't expect sw refresher */
+/*
+	  if (!mfd->hw_refresh)
+	  {
+	    if ((ret = msm_fb_resume_sw_refresher(mfd)) != 0)
+	    {
+	      MSM_FB_INFO("msm_fb_blank_sub: msm_fb_resume_sw_refresher failed = %d!\n",ret);
+	    }
+	  }
+*/
+			}
+		}
+		break;
+
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+	case FB_BLANK_POWERDOWN:
+	default:
+		if (mfd->panel_power_on) {
+			int curr_pwr_state;
+
+			mfd->op_enable = FALSE;
+			curr_pwr_state = mfd->panel_power_on;
+			mfd->panel_power_on = FALSE;
+
+			mdelay(100);
+			ret = pdata->off(mfd->pdev);
+			if (ret)
+				mfd->panel_power_on = curr_pwr_state;
+
+			msm_fb_set_backlight(mfd, 0, 0);
+			mfd->op_enable = TRUE;
+		}
+		break;
+	}
+
+	return ret;
+}
+
+static void msm_fb_fillrect(struct fb_info *info,
+			    const struct fb_fillrect *rect)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+	cfb_fillrect(info, rect);
+	if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
+		!mfd->sw_currently_refreshing) {
+		struct fb_var_screeninfo var;
+
+		var = info->var;
+		var.reserved[0] = 0x54445055;
+		var.reserved[1] = (rect->dy << 16) | (rect->dx);
+		var.reserved[2] = ((rect->dy + rect->height) << 16) |
+		    (rect->dx + rect->width);
+
+		msm_fb_pan_display(&var, info);
+	}
+}
+
+static void msm_fb_copyarea(struct fb_info *info,
+			    const struct fb_copyarea *area)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+	cfb_copyarea(info, area);
+	if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
+		!mfd->sw_currently_refreshing) {
+		struct fb_var_screeninfo var;
+
+		var = info->var;
+		var.reserved[0] = 0x54445055;
+		var.reserved[1] = (area->dy << 16) | (area->dx);
+		var.reserved[2] = ((area->dy + area->height) << 16) |
+		    (area->dx + area->width);
+
+		msm_fb_pan_display(&var, info);
+	}
+}
+
+static void msm_fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+	cfb_imageblit(info, image);
+	if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
+		!mfd->sw_currently_refreshing) {
+		struct fb_var_screeninfo var;
+
+		var = info->var;
+		var.reserved[0] = 0x54445055;
+		var.reserved[1] = (image->dy << 16) | (image->dx);
+		var.reserved[2] = ((image->dy + image->height) << 16) |
+		    (image->dx + image->width);
+
+		msm_fb_pan_display(&var, info);
+	}
+}
+
+static int msm_fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	return msm_fb_blank_sub(blank_mode, info, mfd->op_enable);
+}
+
+static int msm_fb_set_lut(struct fb_cmap *cmap, struct fb_info *info)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+	if (!mfd->lut_update)
+		return -ENODEV;
+
+	mfd->lut_update(info, cmap);
+	return 0;
+}
+
+/*
+ * Custom Framebuffer mmap() function for MSM driver.
+ * Differs from standard mmap() function by allowing for customized
+ * page-protection.
+ */
+static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma)
+{
+	/* Get frame buffer memory range. */
+	unsigned long start = info->fix.smem_start;
+	u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
+	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	if (off >= len) {
+		/* memory mapped io */
+		off -= len;
+		if (info->var.accel_flags) {
+			mutex_unlock(&info->lock);
+			return -EINVAL;
+		}
+		start = info->fix.mmio_start;
+		len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
+	}
+
+	/* Set VM flags. */
+	start &= PAGE_MASK;
+	if ((vma->vm_end - vma->vm_start + off) > len)
+		return -EINVAL;
+	off += start;
+	vma->vm_pgoff = off >> PAGE_SHIFT;
+	/* This is an IO map - tell maydump to skip this VMA */
+	vma->vm_flags |= VM_IO | VM_RESERVED;
+
+	/* Set VM page protection */
+	if (mfd->mdp_fb_page_protection == MDP_FB_PAGE_PROTECTION_WRITECOMBINE)
+		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	else if (mfd->mdp_fb_page_protection ==
+			MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE)
+		vma->vm_page_prot = pgprot_writethroughcache(vma->vm_page_prot);
+	else if (mfd->mdp_fb_page_protection ==
+			MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE)
+		vma->vm_page_prot = pgprot_writebackcache(vma->vm_page_prot);
+	else if (mfd->mdp_fb_page_protection ==
+			MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE)
+		vma->vm_page_prot = pgprot_writebackwacache(vma->vm_page_prot);
+	else
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	/* Remap the frame buffer I/O range */
+	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+				vma->vm_end - vma->vm_start,
+				vma->vm_page_prot))
+		return -EAGAIN;
+
+	return 0;
+}
+
+static struct fb_ops msm_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_open = msm_fb_open,
+	.fb_release = msm_fb_release,
+	.fb_read = NULL,
+	.fb_write = NULL,
+	.fb_cursor = NULL,
+	.fb_check_var = msm_fb_check_var,	/* vinfo check */
+	.fb_set_par = msm_fb_set_par,	/* set the video mode according to info->var */
+	.fb_setcolreg = NULL,	/* set color register */
+	.fb_blank = msm_fb_blank,	/* blank display */
+	.fb_pan_display = msm_fb_pan_display,	/* pan display */
+	.fb_fillrect = msm_fb_fillrect,	/* Draws a rectangle */
+	.fb_copyarea = msm_fb_copyarea,	/* Copy data from area to another */
+	.fb_imageblit = msm_fb_imageblit,	/* Draws a image to the display */
+	.fb_rotate = NULL,
+	.fb_sync = NULL,	/* wait for blit idle, optional */
+	.fb_ioctl = msm_fb_ioctl,	/* perform fb specific ioctl (optional) */
+	.fb_mmap = msm_fb_mmap,
+};
+
+static int msm_fb_register(struct msm_fb_data_type *mfd)
+{
+	int ret = -ENODEV;
+	int bpp;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
+	struct fb_info *fbi = mfd->fbi;
+	struct fb_fix_screeninfo *fix;
+	struct fb_var_screeninfo *var;
+	int *id;
+	int fbram_offset;
+
+	/*
+	 * fb info initialization
+	 */
+	fix = &fbi->fix;
+	var = &fbi->var;
+
+	fix->type_aux = 0;	/* if type == FB_TYPE_INTERLEAVED_PLANES */
+	fix->visual = FB_VISUAL_TRUECOLOR;	/* True Color */
+	fix->ywrapstep = 0;	/* No support */
+	fix->mmio_start = 0;	/* No MMIO Address */
+	fix->mmio_len = 0;	/* No MMIO Address */
+	fix->accel = FB_ACCEL_NONE;/* FB_ACCEL_MSM needes to be added in fb.h */
+
+	var->xoffset = 0,	/* Offset from virtual to visible */
+	var->yoffset = 0,	/* resolution */
+	var->grayscale = 0,	/* No graylevels */
+	var->nonstd = 0,	/* standard pixel format */
+	var->activate = FB_ACTIVATE_VBL,	/* activate it at vsync */
+	var->height = -1,	/* height of picture in mm */
+	var->width = -1,	/* width of picture in mm */
+	var->accel_flags = 0,	/* acceleration flags */
+	var->sync = 0,	/* see FB_SYNC_* */
+	var->rotate = 0,	/* angle we rotate counter clockwise */
+	mfd->op_enable = FALSE;
+
+	switch (mfd->fb_imgType) {
+	case MDP_RGB_565:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+		var->blue.offset = 0;
+		var->green.offset = 5;
+		var->red.offset = 11;
+		var->blue.length = 5;
+		var->green.length = 6;
+		var->red.length = 5;
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		bpp = 2;
+		break;
+
+	case MDP_RGB_888:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+		var->blue.offset = 0;
+		var->green.offset = 8;
+		var->red.offset = 16;
+		var->blue.length = 8;
+		var->green.length = 8;
+		var->red.length = 8;
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		bpp = 3;
+		break;
+
+	case MDP_ARGB_8888:
+		fix->type = FB_TYPE_PACKED_PIXELS;
+		fix->xpanstep = 1;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+		var->blue.offset = 0;
+		var->green.offset = 8;
+		var->red.offset = 16;
+		var->blue.length = 8;
+		var->green.length = 8;
+		var->red.length = 8;
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		bpp = 3;
+		break;
+
+	case MDP_YCRYCB_H2V1:
+		/* ToDo: need to check TV-Out YUV422i framebuffer format */
+		/*       we might need to create new type define */
+		fix->type = FB_TYPE_INTERLEAVED_PLANES;
+		fix->xpanstep = 2;
+		fix->ypanstep = 1;
+		var->vmode = FB_VMODE_NONINTERLACED;
+
+		/* how about R/G/B offset? */
+		var->blue.offset = 0;
+		var->green.offset = 5;
+		var->red.offset = 11;
+		var->blue.length = 5;
+		var->green.length = 6;
+		var->red.length = 5;
+		var->blue.msb_right = 0;
+		var->green.msb_right = 0;
+		var->red.msb_right = 0;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		bpp = 2;
+		break;
+
+	default:
+		MSM_FB_ERR("msm_fb_init: fb %d unkown image type!\n",
+			   mfd->index);
+		return ret;
+	}
+
+	/* The adreno GPU hardware requires that the pitch be aligned to
+	   32 pixels for color buffers, so for the cases where the GPU
+	   is writing directly to fb0, the framebuffer pitch
+	   also needs to be 32 pixel aligned */
+
+	if (mfd->index == 0)
+		fix->line_length = ALIGN(panel_info->xres * bpp, 32);
+	else
+		fix->line_length = panel_info->xres * bpp;
+
+	fix->smem_len = fix->line_length * panel_info->yres * mfd->fb_page;
+
+	mfd->var_xres = panel_info->xres;
+	mfd->var_yres = panel_info->yres;
+
+	var->pixclock = mfd->panel_info.clk_rate;
+	mfd->var_pixclock = var->pixclock;
+
+	var->xres = panel_info->xres;
+	var->yres = panel_info->yres;
+	var->xres_virtual = panel_info->xres;
+	var->yres_virtual = panel_info->yres * mfd->fb_page;
+	var->bits_per_pixel = bpp * 8,	/* FrameBuffer color depth */
+		/*
+		 * id field for fb app
+		 */
+	    id = (int *)&mfd->panel;
+
+#if defined(CONFIG_FB_MSM_MDP22)
+	snprintf(fix->id, sizeof(fix->id), "msmfb22_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP30)
+	snprintf(fix->id, sizeof(fix->id), "msmfb30_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP31)
+	snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP40)
+	snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id);
+#else
+	error CONFIG_FB_MSM_MDP undefined !
+#endif
+	 fbi->fbops = &msm_fb_ops;
+	fbi->flags = FBINFO_FLAG_DEFAULT;
+	fbi->pseudo_palette = msm_fb_pseudo_palette;
+
+	mfd->ref_cnt = 0;
+	mfd->sw_currently_refreshing = FALSE;
+	mfd->sw_refreshing_enable = TRUE;
+	mfd->panel_power_on = FALSE;
+
+	mfd->pan_waiting = FALSE;
+	init_completion(&mfd->pan_comp);
+	init_completion(&mfd->refresher_comp);
+	init_MUTEX(&mfd->sem);
+
+	fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;
+	fbram += fbram_offset;
+	fbram_phys += fbram_offset;
+	fbram_size -= fbram_offset;
+
+	if (fbram_size < fix->smem_len) {
+		printk(KERN_ERR "error: no more framebuffer memory!\n");
+		return -ENOMEM;
+	}
+
+	fbi->screen_base = fbram;
+	fbi->fix.smem_start = (unsigned long)fbram_phys;
+
+	memset(fbi->screen_base, 0x0, fix->smem_len);
+
+	mfd->op_enable = TRUE;
+	mfd->panel_power_on = FALSE;
+
+	/* cursor memory allocation */
+	if (mfd->cursor_update) {
+		mfd->cursor_buf = dma_alloc_coherent(NULL,
+					MDP_CURSOR_SIZE,
+					(dma_addr_t *) &mfd->cursor_buf_phys,
+					GFP_KERNEL);
+		if (!mfd->cursor_buf)
+			mfd->cursor_update = 0;
+	}
+
+	if (mfd->lut_update) {
+		ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+		if (ret)
+			printk(KERN_ERR "%s: fb_alloc_cmap() failed!\n",
+					__func__);
+	}
+
+	if (register_framebuffer(fbi) < 0) {
+		if (mfd->lut_update)
+			fb_dealloc_cmap(&fbi->cmap);
+
+		if (mfd->cursor_buf)
+			dma_free_coherent(NULL,
+				MDP_CURSOR_SIZE,
+				mfd->cursor_buf,
+				(dma_addr_t) mfd->cursor_buf_phys);
+
+		mfd->op_enable = FALSE;
+		return -EPERM;
+	}
+
+	fbram += fix->smem_len;
+	fbram_phys += fix->smem_len;
+	fbram_size -= fix->smem_len;
+
+	MSM_FB_INFO
+	    ("FrameBuffer[%d] %dx%d size=%d bytes is registered successfully!\n",
+	     mfd->index, fbi->var.xres, fbi->var.yres, fbi->fix.smem_len);
+
+#ifdef CONFIG_FB_MSM_LOGO
+	if (!load_565rle_image(INIT_IMAGE_FILE)) ;	/* Flip buffer */
+#endif
+	ret = 0;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	mfd->early_suspend.suspend = msmfb_early_suspend;
+	mfd->early_suspend.resume = msmfb_early_resume;
+	mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2;
+	register_early_suspend(&mfd->early_suspend);
+#endif
+
+#ifdef MSM_FB_ENABLE_DBGFS
+	{
+		struct dentry *root;
+		struct dentry *sub_dir;
+		char sub_name[2];
+
+		root = msm_fb_get_debugfs_root();
+		if (root != NULL) {
+			sub_name[0] = (char)(mfd->index + 0x30);
+			sub_name[1] = '\0';
+			sub_dir = debugfs_create_dir(sub_name, root);
+		} else {
+			sub_dir = NULL;
+		}
+
+		mfd->sub_dir = sub_dir;
+
+		if (sub_dir) {
+			msm_fb_debugfs_file_create(sub_dir, "op_enable",
+						   (u32 *) &mfd->op_enable);
+			msm_fb_debugfs_file_create(sub_dir, "panel_power_on",
+						   (u32 *) &mfd->
+						   panel_power_on);
+			msm_fb_debugfs_file_create(sub_dir, "ref_cnt",
+						   (u32 *) &mfd->ref_cnt);
+			msm_fb_debugfs_file_create(sub_dir, "fb_imgType",
+						   (u32 *) &mfd->fb_imgType);
+			msm_fb_debugfs_file_create(sub_dir,
+						   "sw_currently_refreshing",
+						   (u32 *) &mfd->
+						   sw_currently_refreshing);
+			msm_fb_debugfs_file_create(sub_dir,
+						   "sw_refreshing_enable",
+						   (u32 *) &mfd->
+						   sw_refreshing_enable);
+
+			msm_fb_debugfs_file_create(sub_dir, "xres",
+						   (u32 *) &mfd->panel_info.
+						   xres);
+			msm_fb_debugfs_file_create(sub_dir, "yres",
+						   (u32 *) &mfd->panel_info.
+						   yres);
+			msm_fb_debugfs_file_create(sub_dir, "bpp",
+						   (u32 *) &mfd->panel_info.
+						   bpp);
+			msm_fb_debugfs_file_create(sub_dir, "type",
+						   (u32 *) &mfd->panel_info.
+						   type);
+			msm_fb_debugfs_file_create(sub_dir, "wait_cycle",
+						   (u32 *) &mfd->panel_info.
+						   wait_cycle);
+			msm_fb_debugfs_file_create(sub_dir, "pdest",
+						   (u32 *) &mfd->panel_info.
+						   pdest);
+			msm_fb_debugfs_file_create(sub_dir, "backbuff",
+						   (u32 *) &mfd->panel_info.
+						   fb_num);
+			msm_fb_debugfs_file_create(sub_dir, "clk_rate",
+						   (u32 *) &mfd->panel_info.
+						   clk_rate);
+			msm_fb_debugfs_file_create(sub_dir, "frame_count",
+						   (u32 *) &mfd->panel_info.
+						   frame_count);
+
+
+			switch (mfd->dest) {
+			case DISPLAY_LCD:
+				msm_fb_debugfs_file_create(sub_dir,
+				"vsync_enable",
+				(u32 *)&mfd->panel_info.lcd.vsync_enable);
+				msm_fb_debugfs_file_create(sub_dir,
+				"refx100",
+				(u32 *) &mfd->panel_info.lcd. refx100);
+				msm_fb_debugfs_file_create(sub_dir,
+				"v_back_porch",
+				(u32 *) &mfd->panel_info.lcd.v_back_porch);
+				msm_fb_debugfs_file_create(sub_dir,
+				"v_front_porch",
+				(u32 *) &mfd->panel_info.lcd.v_front_porch);
+				msm_fb_debugfs_file_create(sub_dir,
+				"v_pulse_width",
+				(u32 *) &mfd->panel_info.lcd.v_pulse_width);
+				msm_fb_debugfs_file_create(sub_dir,
+				"hw_vsync_mode",
+				(u32 *) &mfd->panel_info.lcd.hw_vsync_mode);
+				msm_fb_debugfs_file_create(sub_dir,
+				"vsync_notifier_period", (u32 *)
+				&mfd->panel_info.lcd.vsync_notifier_period);
+				break;
+
+			case DISPLAY_LCDC:
+				msm_fb_debugfs_file_create(sub_dir,
+				"h_back_porch",
+				(u32 *) &mfd->panel_info.lcdc.h_back_porch);
+				msm_fb_debugfs_file_create(sub_dir,
+				"h_front_porch",
+				(u32 *) &mfd->panel_info.lcdc.h_front_porch);
+				msm_fb_debugfs_file_create(sub_dir,
+				"h_pulse_width",
+				(u32 *) &mfd->panel_info.lcdc.h_pulse_width);
+				msm_fb_debugfs_file_create(sub_dir,
+				"v_back_porch",
+				(u32 *) &mfd->panel_info.lcdc.v_back_porch);
+				msm_fb_debugfs_file_create(sub_dir,
+				"v_front_porch",
+				(u32 *) &mfd->panel_info.lcdc.v_front_porch);
+				msm_fb_debugfs_file_create(sub_dir,
+				"v_pulse_width",
+				(u32 *) &mfd->panel_info.lcdc.v_pulse_width);
+				msm_fb_debugfs_file_create(sub_dir,
+				"border_clr",
+				(u32 *) &mfd->panel_info.lcdc.border_clr);
+				msm_fb_debugfs_file_create(sub_dir,
+				"underflow_clr",
+				(u32 *) &mfd->panel_info.lcdc.underflow_clr);
+				msm_fb_debugfs_file_create(sub_dir,
+				"hsync_skew",
+				(u32 *) &mfd->panel_info.lcdc.hsync_skew);
+				break;
+
+			default:
+				break;
+			}
+		}
+	}
+#endif /* MSM_FB_ENABLE_DBGFS */
+
+	return ret;
+}
+
+static int msm_fb_open(struct fb_info *info, int user)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+	if (!mfd->ref_cnt) {
+		mdp_set_dma_pan_info(info, NULL, TRUE);
+
+		if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
+			printk(KERN_ERR "msm_fb_open: can't turn on display!\n");
+			return -1;
+		}
+	}
+
+	mfd->ref_cnt++;
+	return 0;
+}
+
+static int msm_fb_release(struct fb_info *info, int user)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	int ret = 0;
+
+	if (!mfd->ref_cnt) {
+		MSM_FB_INFO("msm_fb_release: try to close unopened fb %d!\n",
+			    mfd->index);
+		return -EINVAL;
+	}
+
+	mfd->ref_cnt--;
+
+	if (!mfd->ref_cnt) {
+		if ((ret =
+		     msm_fb_blank_sub(FB_BLANK_POWERDOWN, info,
+				      mfd->op_enable)) != 0) {
+			printk(KERN_ERR "msm_fb_release: can't turn off display!\n");
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+DECLARE_MUTEX(msm_fb_pan_sem);
+
+static int msm_fb_pan_display(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct mdp_dirty_region dirty;
+	struct mdp_dirty_region *dirtyPtr = NULL;
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+	if ((!mfd->op_enable) || (!mfd->panel_power_on))
+		return -EPERM;
+
+	if (var->xoffset > (info->var.xres_virtual - info->var.xres))
+		return -EINVAL;
+
+	if (var->yoffset > (info->var.yres_virtual - info->var.yres))
+		return -EINVAL;
+
+	if (info->fix.xpanstep)
+		info->var.xoffset =
+		    (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
+
+	if (info->fix.ypanstep)
+		info->var.yoffset =
+		    (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
+
+	/* "UPDT" */
+	if (var->reserved[0] == 0x54445055) {
+		dirty.xoffset = var->reserved[1] & 0xffff;
+		dirty.yoffset = (var->reserved[1] >> 16) & 0xffff;
+
+		if ((var->reserved[2] & 0xffff) <= dirty.xoffset)
+			return -EINVAL;
+		if (((var->reserved[2] >> 16) & 0xffff) <= dirty.yoffset)
+			return -EINVAL;
+
+		dirty.width = (var->reserved[2] & 0xffff) - dirty.xoffset;
+		dirty.height =
+		    ((var->reserved[2] >> 16) & 0xffff) - dirty.yoffset;
+		info->var.yoffset = var->yoffset;
+
+		if (dirty.xoffset < 0)
+			return -EINVAL;
+
+		if (dirty.yoffset < 0)
+			return -EINVAL;
+
+		if ((dirty.xoffset + dirty.width) > info->var.xres)
+			return -EINVAL;
+
+		if ((dirty.yoffset + dirty.height) > info->var.yres)
+			return -EINVAL;
+
+		if ((dirty.width <= 0) || (dirty.height <= 0))
+			return -EINVAL;
+
+		dirtyPtr = &dirty;
+	}
+
+	/* Flip */
+	/* A constant value is used to indicate that we should change the DMA
+	   output buffer instead of just panning */
+
+	if (var->reserved[0] == 0x466c6970) {
+		unsigned long length, address;
+		struct file *p_src_file;
+		struct mdp_img imgdata;
+		int bpp;
+
+		if (mfd->allow_set_offset) {
+			imgdata.memory_id = var->reserved[1];
+			imgdata.priv = var->reserved[2];
+
+			/* If there is no memory ID then we want to reset back
+			   to the original fb visibility */
+			if (var->reserved[1]) {
+				if (var->reserved[4] == MDP_BLIT_SRC_GEM) {
+					panic("waaaaaaaaaaaaaah");
+					if ( /*get_gem_img(&imgdata,
+						(unsigned long *) &address,
+						 &length)*/ -1 < 0) {
+						return -1;
+					}
+				} else {
+					/*get_img(&imgdata, info, &address,
+							&length, &p_src_file);*/
+					panic("waaaaaah");
+				}
+				mfd->ibuf.visible_swapped = TRUE;
+			} else {
+				/* Flip back to the original address
+				   adjusted for xoffset and yoffset */
+
+				bpp = info->var.bits_per_pixel / 8;
+				address = (unsigned long) info->fix.smem_start;
+				address += info->var.xoffset * bpp +
+				info->var.yoffset * info->fix.line_length;
+
+				mfd->ibuf.visible_swapped = FALSE;
+			}
+
+			mdp_set_offset_info(info, address,
+				(var->activate == FB_ACTIVATE_VBL));
+
+			mfd->dma_fnc(mfd);
+			return 0;
+		} else
+			return -EINVAL;
+	}
+
+	down(&msm_fb_pan_sem);
+	mdp_set_dma_pan_info(info, dirtyPtr,
+			     (var->activate == FB_ACTIVATE_VBL));
+	mdp_dma_pan_update(info);
+	up(&msm_fb_pan_sem);
+
+	++mfd->panel_info.frame_count;
+	return 0;
+}
+
+static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+	if (var->rotate != FB_ROTATE_UR)
+		return -EINVAL;
+	if (var->grayscale != info->var.grayscale)
+		return -EINVAL;
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		if ((var->green.offset != 5) ||
+			!((var->blue.offset == 11)
+				|| (var->blue.offset == 0)) ||
+			!((var->red.offset == 11)
+				|| (var->red.offset == 0)) ||
+			(var->blue.length != 5) ||
+			(var->green.length != 6) ||
+			(var->red.length != 5) ||
+			(var->blue.msb_right != 0) ||
+			(var->green.msb_right != 0) ||
+			(var->red.msb_right != 0) ||
+			(var->transp.offset != 0) ||
+			(var->transp.length != 0))
+				return -EINVAL;
+		break;
+
+	case 24:
+		if ((var->blue.offset != 0) ||
+			(var->green.offset != 8) ||
+			(var->red.offset != 16) ||
+			(var->blue.length != 8) ||
+			(var->green.length != 8) ||
+			(var->red.length != 8) ||
+			(var->blue.msb_right != 0) ||
+			(var->green.msb_right != 0) ||
+			(var->red.msb_right != 0) ||
+			!(((var->transp.offset == 0) &&
+				(var->transp.length == 0)) ||
+			  ((var->transp.offset == 24) &&
+				(var->transp.length == 8))))
+				return -EINVAL;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if ((var->xres_virtual <= 0) || (var->yres_virtual <= 0))
+		return -EINVAL;
+
+	if (info->fix.smem_len <
+		(var->xres_virtual*var->yres_virtual*(var->bits_per_pixel/8)))
+		return -EINVAL;
+
+	if ((var->xres == 0) || (var->yres == 0))
+		return -EINVAL;
+
+	if ((var->xres > mfd->panel_info.xres) ||
+		(var->yres > mfd->panel_info.yres))
+		return -EINVAL;
+
+	if (var->xoffset > (var->xres_virtual - var->xres))
+		return -EINVAL;
+
+	if (var->yoffset > (var->yres_virtual - var->yres))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int msm_fb_set_par(struct fb_info *info)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	int old_imgType;
+	int blank = 0;
+
+	old_imgType = mfd->fb_imgType;
+	switch (var->bits_per_pixel) {
+	case 16:
+		if (var->red.offset == 0)
+			mfd->fb_imgType = MDP_BGR_565;
+		else
+			mfd->fb_imgType = MDP_RGB_565;
+		break;
+
+	case 24:
+		if ((var->transp.offset == 0) && (var->transp.length == 0))
+			mfd->fb_imgType = MDP_RGB_888;
+		else if ((var->transp.offset == 24) &&
+				(var->transp.length == 8)) {
+			mfd->fb_imgType = MDP_ARGB_8888;
+			info->var.bits_per_pixel = 32;
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if ((mfd->var_pixclock != var->pixclock) ||
+		(mfd->hw_refresh && ((mfd->fb_imgType != old_imgType) ||
+				(mfd->var_pixclock != var->pixclock) ||
+				(mfd->var_xres != var->xres) ||
+				(mfd->var_yres != var->yres)))) {
+		mfd->var_xres = var->xres;
+		mfd->var_yres = var->yres;
+		mfd->var_pixclock = var->pixclock;
+		blank = 1;
+	}
+
+	if (blank) {
+		msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable);
+		msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable);
+	}
+
+	return 0;
+}
+
+static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd)
+{
+	if (mfd->hw_refresh)
+		return -EPERM;
+
+	if (mfd->sw_currently_refreshing) {
+		down(&mfd->sem);
+		mfd->sw_currently_refreshing = FALSE;
+		up(&mfd->sem);
+
+		/* wait until the refresher finishes the last job */
+		wait_for_completion_killable(&mfd->refresher_comp);
+	}
+
+	return 0;
+}
+
+int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd)
+{
+	boolean do_refresh;
+
+	if (mfd->hw_refresh)
+		return -EPERM;
+
+	down(&mfd->sem);
+	if ((!mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) {
+		do_refresh = TRUE;
+		mfd->sw_currently_refreshing = TRUE;
+	} else {
+		do_refresh = FALSE;
+	}
+	up(&mfd->sem);
+
+	if (do_refresh)
+		mdp_refresh_screen((unsigned long)mfd);
+
+	return 0;
+}
+
+void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file)
+{
+#ifdef CONFIG_ANDROID_PMEM
+	if (p_src_file)
+		put_pmem_file(p_src_file);
+	if (p_dst_file)
+		put_pmem_file(p_dst_file);
+#endif
+}
+
+int mdp_blit(struct fb_info *info, struct mdp_blit_req *req)
+{
+	int ret;
+	struct file *p_src_file = 0, *p_dst_file = 0;
+	if (unlikely(req->src_rect.h == 0 || req->src_rect.w == 0)) {
+		printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
+		return -EINVAL;
+	}
+	if (unlikely(req->dst_rect.h == 0 || req->dst_rect.w == 0))
+		return 0;
+
+	ret = mdp_ppp_blit(info, req, &p_src_file, &p_dst_file);
+	mdp_ppp_put_img(p_src_file, p_dst_file);
+	return ret;
+}
+
+typedef void (*msm_dma_barrier_function_pointer) (void *, size_t);
+
+static inline void msm_fb_dma_barrier_for_rect(struct fb_info *info,
+			struct mdp_img *img, struct mdp_rect *rect,
+			msm_dma_barrier_function_pointer dma_barrier_fp
+			)
+{
+	/*
+	 * Compute the start and end addresses of the rectangles.
+	 * NOTE: As currently implemented, the data between
+	 *       the end of one row and the start of the next is
+	 *       included in the address range rather than
+	 *       doing multiple calls for each row.
+	 */
+
+	char * const pmem_start = info->screen_base;
+/*	int bytes_per_pixel = mdp_get_bytes_per_pixel(img->format);
+	unsigned long start = (unsigned long)pmem_start + img->offset +
+		(img->width * rect->y + rect->x) * bytes_per_pixel;
+	size_t size  = ((rect->h - 1) * img->width + rect->w) * bytes_per_pixel;
+	(*dma_barrier_fp) ((void *) start, size);
+*/
+	panic("waaaaah");
+}
+
+static inline void msm_dma_nc_pre(void)
+{
+	dmb();
+}
+static inline void msm_dma_wt_pre(void)
+{
+	dmb();
+}
+static inline void msm_dma_todevice_wb_pre(void *start, size_t size)
+{
+	#warning this
+//	dma_cache_pre_ops(start, size, DMA_TO_DEVICE);
+}
+
+static inline void msm_dma_fromdevice_wb_pre(void *start, size_t size)
+{
+	#warning this
+//	dma_cache_pre_ops(start, size, DMA_FROM_DEVICE);
+}
+
+static inline void msm_dma_nc_post(void)
+{
+	dmb();
+}
+
+static inline void msm_dma_fromdevice_wt_post(void *start, size_t size)
+{
+	#warning this
+//	dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
+}
+
+static inline void msm_dma_todevice_wb_post(void *start, size_t size)
+{
+	#warning this
+//	dma_cache_post_ops(start, size, DMA_TO_DEVICE);
+}
+
+static inline void msm_dma_fromdevice_wb_post(void *start, size_t size)
+{
+	#warning this
+//	dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
+}
+
+/*
+ * Do the write barriers required to guarantee data is committed to RAM
+ * (from CPU cache or internal buffers) before a DMA operation starts.
+ * NOTE: As currently implemented, the data between
+ *       the end of one row and the start of the next is
+ *       included in the address range rather than
+ *       doing multiple calls for each row.
+*/
+static void msm_fb_ensure_memory_coherency_before_dma(struct fb_info *info,
+		struct mdp_blit_req *req_list,
+		int req_list_count)
+{
+#ifdef CONFIG_ARCH_QSD8X50
+	int i;
+
+	/*
+	 * Normally, do the requested barriers for each address
+	 * range that corresponds to a rectangle.
+	 *
+	 * But if at least one write barrier is requested for data
+	 * going to or from the device but no address range is
+	 * needed for that barrier, then do the barrier, but do it
+	 * only once, no matter how many requests there are.
+	 */
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	switch (mfd->mdp_fb_page_protection)	{
+	default:
+	case MDP_FB_PAGE_PROTECTION_NONCACHED:
+	case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
+		/*
+		 * The following barrier is only done at most once,
+		 * since further calls would be redundant.
+		 */
+		for (i = 0; i < req_list_count; i++) {
+			if (!(req_list[i].flags
+				& MDP_NO_DMA_BARRIER_START)) {
+				msm_dma_nc_pre();
+				break;
+			}
+		}
+		break;
+
+	case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
+		/*
+		 * The following barrier is only done at most once,
+		 * since further calls would be redundant.
+		 */
+		for (i = 0; i < req_list_count; i++) {
+			if (!(req_list[i].flags
+				& MDP_NO_DMA_BARRIER_START)) {
+				msm_dma_wt_pre();
+				break;
+			}
+		}
+		break;
+
+	case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
+	case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
+		for (i = 0; i < req_list_count; i++) {
+			if (!(req_list[i].flags &
+					MDP_NO_DMA_BARRIER_START)) {
+
+				msm_fb_dma_barrier_for_rect(info,
+						&(req_list[i].src),
+						&(req_list[i].src_rect),
+						msm_dma_todevice_wb_pre
+						);
+
+				msm_fb_dma_barrier_for_rect(info,
+						&(req_list[i].dst),
+						&(req_list[i].dst_rect),
+						msm_dma_todevice_wb_pre
+						);
+			}
+		}
+		break;
+	}
+#else
+	dmb();
+#endif
+}
+
+
+/*
+ * Do the write barriers required to guarantee data will be re-read from RAM by
+ * the CPU after a DMA operation ends.
+ * NOTE: As currently implemented, the data between
+ *       the end of one row and the start of the next is
+ *       included in the address range rather than
+ *       doing multiple calls for each row.
+*/
+static void msm_fb_ensure_memory_coherency_after_dma(struct fb_info *info,
+		struct mdp_blit_req *req_list,
+		int req_list_count)
+{
+#ifdef CONFIG_ARCH_QSD8X50
+	int i;
+
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	switch (mfd->mdp_fb_page_protection)	{
+	default:
+	case MDP_FB_PAGE_PROTECTION_NONCACHED:
+	case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
+		/*
+		 * The following barrier is only done at most once,
+		 * since further calls would be redundant.
+		 */
+		for (i = 0; i < req_list_count; i++) {
+			if (!(req_list[i].flags
+				& MDP_NO_DMA_BARRIER_END)) {
+				msm_dma_nc_post();
+				break;
+			}
+		}
+		break;
+
+	case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
+		for (i = 0; i < req_list_count; i++) {
+			if (!(req_list[i].flags &
+					MDP_NO_DMA_BARRIER_END)) {
+
+				msm_fb_dma_barrier_for_rect(info,
+						&(req_list[i].dst),
+						&(req_list[i].dst_rect),
+						msm_dma_fromdevice_wt_post
+						);
+			}
+		}
+		break;
+	case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
+	case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
+		for (i = 0; i < req_list_count; i++) {
+			if (!(req_list[i].flags &
+					MDP_NO_DMA_BARRIER_END)) {
+
+				msm_fb_dma_barrier_for_rect(info,
+						&(req_list[i].dst),
+						&(req_list[i].dst_rect),
+						msm_dma_fromdevice_wb_post
+						);
+			}
+		}
+		break;
+	}
+#else
+	dmb();
+#endif
+}
+
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info,
+	struct mdp_blit_req *req_list, int req_list_count)
+{
+	BUG_ON(!info);
+
+	/*
+	 * Ensure that CPU cache and other internal CPU state is
+	 * updated to reflect any change in memory modified by MDP blit
+	 * DMA.
+	 */
+	msm_fb_ensure_memory_coherency_after_dma(info,
+			req_list, req_list_count);
+}
+
+static int msmfb_async_blit(struct fb_info *info, void __user *p)
+{
+	/*
+	 * CAUTION: The names of the struct types intentionally *DON'T* match
+	 * the names of the variables declared -- they appear to be swapped.
+	 * Read the code carefully and you should see that the variable names
+	 * make sense.
+	 */
+	const int MAX_LIST_WINDOW = 16;
+	struct mdp_blit_req req_list[MAX_LIST_WINDOW];
+	struct mdp_blit_req_list req_list_header;
+
+	int count, i, req_list_count;
+
+	/* Get the count size for the total BLIT request. */
+	if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
+		return -EFAULT;
+	p += sizeof(req_list_header);
+	count = req_list_header.count;
+	while (count > 0) {
+		/*
+		 * Access the requests through a narrow window to decrease copy
+		 * overhead and make larger requests accessible to the
+		 * coherency management code.
+		 * NOTE: The window size is intended to be larger than the
+		 *       typical request size, but not require more than 2
+		 *       kbytes of stack storage.
+		 */
+		req_list_count = count;
+		if (req_list_count > MAX_LIST_WINDOW)
+			req_list_count = MAX_LIST_WINDOW;
+		if (copy_from_user(&req_list, p,
+				sizeof(struct mdp_blit_req)*req_list_count))
+			return -EFAULT;
+
+		/*
+		 * Ensure that any data CPU may have previously written to
+		 * internal state (but not yet committed to memory) is
+		 * guaranteed to be committed to memory now.
+		 */
+		msm_fb_ensure_memory_coherency_before_dma(info,
+				req_list, req_list_count);
+
+		/*
+		 * Do the blit DMA, if required -- returning early only if
+		 * there is a failure.
+		 */
+		for (i = 0; i < req_list_count; i++) {
+			if (!(req_list[i].flags & MDP_NO_BLIT)) {
+				int ret = 0;
+				struct mdp_ppp_djob *job = NULL;
+
+				if (unlikely(req_list[i].src_rect.h == 0 ||
+					req_list[i].src_rect.w == 0)) {
+					MSM_FB_ERR("mpd_ppp: "
+						"src img of zero size!\n");
+					return -EINVAL;
+				}
+
+				if (unlikely(req_list[i].dst_rect.h == 0 ||
+					req_list[i].dst_rect.w == 0))
+					continue;
+
+				/* create a new display job */
+				job = mdp_ppp_new_djob();
+				if (unlikely(!job))
+					return -ENOMEM;
+
+				job->info = info;
+				memcpy(&job->req, &req_list[i],
+					sizeof(struct mdp_blit_req));
+
+				/* Do the actual blit. */
+				ret = mdp_ppp_blit(info, &job->req,
+					&job->p_src_file, &job->p_dst_file);
+
+				/*
+				 * Note that early returns don't guarantee
+				 * memory coherency.
+				 */
+				if (ret || mdp_ppp_get_ret_code()) {
+					mdp_ppp_clear_curr_djob();
+					return ret;
+				}
+			}
+		}
+
+		/* Go to next window of requests. */
+		count -= req_list_count;
+		p += sizeof(struct mdp_blit_req)*req_list_count;
+	}
+	return 0;
+}
+#else
+
+/*
+ * NOTE: The userspace issues blit operations in a sequence, the sequence
+ * start with a operation marked START and ends in an operation marked
+ * END. It is guranteed by the userspace that all the blit operations
+ * between START and END are only within the regions of areas designated
+ * by the START and END operations and that the userspace doesnt modify
+ * those areas. Hence it would be enough to perform barrier/cache operations
+ * only on the START and END operations.
+ */
+static int msmfb_blit(struct fb_info *info, void __user *p)
+{
+	/*
+	 * CAUTION: The names of the struct types intentionally *DON'T* match
+	 * the names of the variables declared -- they appear to be swapped.
+	 * Read the code carefully and you should see that the variable names
+	 * make sense.
+	 */
+	const int MAX_LIST_WINDOW = 16;
+	struct mdp_blit_req req_list[MAX_LIST_WINDOW];
+	struct mdp_blit_req_list req_list_header;
+
+	int count, i, req_list_count;
+
+	/* Get the count size for the total BLIT request. */
+	if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
+		return -EFAULT;
+	p += sizeof(req_list_header);
+	count = req_list_header.count;
+	while (count > 0) {
+		/*
+		 * Access the requests through a narrow window to decrease copy
+		 * overhead and make larger requests accessible to the
+		 * coherency management code.
+		 * NOTE: The window size is intended to be larger than the
+		 *       typical request size, but not require more than 2
+		 *       kbytes of stack storage.
+		 */
+		req_list_count = count;
+		if (req_list_count > MAX_LIST_WINDOW)
+			req_list_count = MAX_LIST_WINDOW;
+		if (copy_from_user(&req_list, p,
+				sizeof(struct mdp_blit_req)*req_list_count))
+			return -EFAULT;
+
+		/*
+		 * Ensure that any data CPU may have previously written to
+		 * internal state (but not yet committed to memory) is
+		 * guaranteed to be committed to memory now.
+		 */
+		msm_fb_ensure_memory_coherency_before_dma(info,
+				req_list, req_list_count);
+
+		/*
+		 * Do the blit DMA, if required -- returning early only if
+		 * there is a failure.
+		 */
+		for (i = 0; i < req_list_count; i++) {
+			if (!(req_list[i].flags & MDP_NO_BLIT)) {
+				/* Do the actual blit. */
+				int ret = mdp_blit(info, &(req_list[i]));
+
+				/*
+				 * Note that early returns don't guarantee
+				 * memory coherency.
+				 */
+				if (ret)
+					return ret;
+			}
+		}
+
+		/*
+		 * Ensure that CPU cache and other internal CPU state is
+		 * updated to reflect any change in memory modified by MDP blit
+		 * DMA.
+		 */
+		msm_fb_ensure_memory_coherency_after_dma(info,
+				req_list,
+				req_list_count);
+
+		/* Go to next window of requests. */
+		count -= req_list_count;
+		p += sizeof(struct mdp_blit_req)*req_list_count;
+	}
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_FB_MSM_OVERLAY
+static int msmfb_overlay_get(struct fb_info *info, void __user *p)
+{
+	struct mdp_overlay req;
+	int ret;
+
+	if (copy_from_user(&req, p, sizeof(req)))
+		return -EFAULT;
+
+	ret = mdp4_overlay_get(info, &req);
+	if (ret) {
+		printk(KERN_ERR "%s: ioctl failed \n",
+			__func__);
+		return ret;
+	}
+	if (copy_to_user(p, &req, sizeof(req))) {
+		printk(KERN_ERR "%s: copy2user failed \n",
+			__func__);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int msmfb_overlay_set(struct fb_info *info, void __user *p)
+{
+	struct mdp_overlay req;
+	int ret;
+
+	if (copy_from_user(&req, p, sizeof(req)))
+		return -EFAULT;
+
+	ret = mdp4_overlay_set(info, &req);
+	if (ret) {
+		printk(KERN_ERR "%s:ioctl failed \n",
+			__func__);
+		return ret;
+	}
+
+	if (copy_to_user(p, &req, sizeof(req))) {
+		printk(KERN_ERR "%s: copy2user failed \n",
+			__func__);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int msmfb_overlay_unset(struct fb_info *info, unsigned long *argp)
+{
+	int	ret, ndx;
+
+	ret = copy_from_user(&ndx, argp, sizeof(ndx));
+	if (ret) {
+		printk(KERN_ERR "%s:msmfb_overlay_unset ioctl failed \n",
+			__func__);
+		return ret;
+	}
+
+	return mdp4_overlay_unset(info, ndx);
+}
+
+static int msmfb_overlay_play(struct fb_info *info, unsigned long *argp)
+{
+	int	ret;
+	struct msmfb_overlay_data req;
+	struct file *p_src_file = 0;
+
+	ret = copy_from_user(&req, argp, sizeof(req));
+	if (ret) {
+		printk(KERN_ERR "%s:msmfb_overlay_play ioctl failed \n",
+			__func__);
+		return ret;
+	}
+
+	ret = mdp4_overlay_play(info, &req, &p_src_file);
+
+	if (p_src_file)
+		put_pmem_file(p_src_file);
+
+	return ret;
+}
+
+#endif
+
+DECLARE_MUTEX(msm_fb_ioctl_ppp_sem);
+DEFINE_MUTEX(msm_fb_ioctl_lut_sem);
+DEFINE_MUTEX(msm_fb_ioctl_hist_sem);
+
+/* Set color conversion matrix from user space */
+
+#ifndef CONFIG_FB_MSM_MDP40
+static void msmfb_set_color_conv(struct mdp_ccs *p)
+{
+	int i;
+
+	if (p->direction == MDP_CCS_RGB2YUV) {
+		/* MDP cmd block enable */
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+		/* RGB->YUV primary forward matrix */
+		for (i = 0; i < MDP_CCS_SIZE; i++)
+			writel(p->ccs[i], MDP_CSC_PFMVn(i));
+
+		#ifdef CONFIG_FB_MSM_MDP31
+		for (i = 0; i < MDP_BV_SIZE; i++)
+			writel(p->bv[i], MDP_CSC_POST_BV2n(i));
+		#endif
+
+		/* MDP cmd block disable */
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	} else {
+		/* MDP cmd block enable */
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+		/* YUV->RGB primary reverse matrix */
+		for (i = 0; i < MDP_CCS_SIZE; i++)
+			writel(p->ccs[i], MDP_CSC_PRMVn(i));
+		for (i = 0; i < MDP_BV_SIZE; i++)
+			writel(p->bv[i], MDP_CSC_PRE_BV1n(i));
+
+		/* MDP cmd block disable */
+		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	}
+}
+#endif
+
+
+static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
+			unsigned long arg)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	void __user *argp = (void __user *)arg;
+	struct fb_cursor cursor;
+	struct fb_cmap cmap;
+	struct mdp_histogram hist;
+#ifndef CONFIG_FB_MSM_MDP40
+	struct mdp_ccs ccs_matrix;
+#endif
+	struct mdp_page_protection fb_page_protection;
+	int ret = 0;
+
+	if (!mfd->op_enable)
+		return -EPERM;
+
+	switch (cmd) {
+#ifdef CONFIG_FB_MSM_OVERLAY
+	case MSMFB_OVERLAY_GET:
+		down(&msm_fb_ioctl_ppp_sem);
+		ret = msmfb_overlay_get(info, argp);
+		up(&msm_fb_ioctl_ppp_sem);
+		break;
+	case MSMFB_OVERLAY_SET:
+		down(&msm_fb_ioctl_ppp_sem);
+		ret = msmfb_overlay_set(info, argp);
+		up(&msm_fb_ioctl_ppp_sem);
+		break;
+	case MSMFB_OVERLAY_UNSET:
+		down(&msm_fb_ioctl_ppp_sem);
+		ret = msmfb_overlay_unset(info, argp);
+		up(&msm_fb_ioctl_ppp_sem);
+		break;
+	case MSMFB_OVERLAY_PLAY:
+		down(&msm_fb_ioctl_ppp_sem);
+		ret = msmfb_overlay_play(info, argp);
+		up(&msm_fb_ioctl_ppp_sem);
+		break;
+#endif
+	case MSMFB_BLIT:
+		down(&msm_fb_ioctl_ppp_sem);
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+		ret = msmfb_async_blit(info, argp);
+		mdp_ppp_wait(); /* Wait for all blits to be finished. */
+#else
+		ret = msmfb_blit(info, argp);
+#endif
+		up(&msm_fb_ioctl_ppp_sem);
+
+		break;
+
+	/* Ioctl for setting ccs matrix from user space */
+	case MSMFB_SET_CCS_MATRIX:
+#ifndef CONFIG_FB_MSM_MDP40
+		ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix));
+		if (ret) {
+			printk(KERN_ERR
+				"%s:MSMFB_SET_CCS_MATRIX ioctl failed \n",
+				__func__);
+			return ret;
+		}
+
+		down(&msm_fb_ioctl_ppp_sem);
+		if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
+			mdp_ccs_rgb2yuv = ccs_matrix;
+		else
+			mdp_ccs_yuv2rgb = ccs_matrix;
+
+		msmfb_set_color_conv(&ccs_matrix) ;
+		up(&msm_fb_ioctl_ppp_sem);
+#else
+		ret = -EINVAL;
+#endif
+
+		break;
+
+	/* Ioctl for getting ccs matrix to user space */
+	case MSMFB_GET_CCS_MATRIX:
+#ifndef CONFIG_FB_MSM_MDP40
+		ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix)) ;
+		if (ret) {
+			printk(KERN_ERR
+				"%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
+				 __func__);
+			return ret;
+		}
+
+		down(&msm_fb_ioctl_ppp_sem);
+		if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
+			ccs_matrix = mdp_ccs_rgb2yuv;
+		 else
+			ccs_matrix =  mdp_ccs_yuv2rgb;
+
+		ret = copy_to_user(argp, &ccs_matrix, sizeof(ccs_matrix));
+
+		if (ret)	{
+			printk(KERN_ERR
+				"%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
+				 __func__);
+			return ret ;
+		}
+		up(&msm_fb_ioctl_ppp_sem);
+#else
+		ret = -EINVAL;
+#endif
+
+		break;
+
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+	case MSMFB_ASYNC_BLIT:
+		down(&msm_fb_ioctl_ppp_sem);
+		ret = msmfb_async_blit(info, argp);
+		up(&msm_fb_ioctl_ppp_sem);
+		break;
+
+	case MSMFB_BLIT_FLUSH:
+		down(&msm_fb_ioctl_ppp_sem);
+		mdp_ppp_wait();
+		up(&msm_fb_ioctl_ppp_sem);
+		break;
+#endif
+
+	case MSMFB_GRP_DISP:
+#ifdef CONFIG_FB_MSM_MDP22
+		{
+			unsigned long grp_id;
+
+			ret = copy_from_user(&grp_id, argp, sizeof(grp_id));
+			if (ret)
+				return ret;
+
+			mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+			writel(grp_id, MDP_FULL_BYPASS_WORD43);
+			mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF,
+				      FALSE);
+			break;
+		}
+#else
+		return -EFAULT;
+#endif
+	case MSMFB_SUSPEND_SW_REFRESHER:
+		if (!mfd->panel_power_on)
+			return -EPERM;
+
+		mfd->sw_refreshing_enable = FALSE;
+		ret = msm_fb_stop_sw_refresher(mfd);
+		break;
+
+	case MSMFB_RESUME_SW_REFRESHER:
+		if (!mfd->panel_power_on)
+			return -EPERM;
+
+		mfd->sw_refreshing_enable = TRUE;
+		ret = msm_fb_resume_sw_refresher(mfd);
+		break;
+
+	case MSMFB_CURSOR:
+		ret = copy_from_user(&cursor, argp, sizeof(cursor));
+		if (ret)
+			return ret;
+
+		ret = msm_fb_cursor(info, &cursor);
+		break;
+
+	case MSMFB_SET_LUT:
+		ret = copy_from_user(&cmap, argp, sizeof(cmap));
+		if (ret)
+			return ret;
+
+		mutex_lock(&msm_fb_ioctl_lut_sem);
+		ret = msm_fb_set_lut(&cmap, info);
+		mutex_unlock(&msm_fb_ioctl_lut_sem);
+		break;
+
+	case MSMFB_HISTOGRAM:
+		if (!mfd->do_histogram)
+			return -ENODEV;
+
+		ret = copy_from_user(&hist, argp, sizeof(hist));
+		if (ret)
+			return ret;
+
+		mutex_lock(&msm_fb_ioctl_hist_sem);
+		ret = mfd->do_histogram(info, &hist);
+		mutex_unlock(&msm_fb_ioctl_hist_sem);
+		break;
+
+	case MSMFB_GET_PAGE_PROTECTION:
+		fb_page_protection.page_protection
+			= mfd->mdp_fb_page_protection;
+		ret = copy_to_user(argp, &fb_page_protection,
+				sizeof(fb_page_protection));
+		if (ret)
+				return ret;
+		break;
+
+	case MSMFB_SET_PAGE_PROTECTION:
+#ifdef CONFIG_ARCH_QSD8X50
+		ret = copy_from_user(&fb_page_protection, argp,
+				sizeof(fb_page_protection));
+		if (ret)
+				return ret;
+
+		/* Validate the proposed page protection settings. */
+		switch (fb_page_protection.page_protection)	{
+		case MDP_FB_PAGE_PROTECTION_NONCACHED:
+		case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
+		case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
+		/* Write-back cache (read allocate)  */
+		case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
+		/* Write-back cache (write allocate) */
+		case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
+			mfd->mdp_fb_page_protection =
+				fb_page_protection.page_protection;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+#else
+		/*
+		 * Don't allow caching until 7k DMA cache operations are
+		 * available.
+		 */
+		ret = -EINVAL;
+#endif
+		break;
+
+	default:
+		MSM_FB_INFO("MDP: unknown ioctl (cmd=%d) received!\n", cmd);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int msm_fb_register_driver(void)
+{
+	return platform_driver_register(&msm_fb_driver);
+}
+
+void msm_fb_add_device(struct platform_device *pdev)
+{
+	struct msm_fb_panel_data *pdata;
+	struct platform_device *this_dev = NULL;
+	struct fb_info *fbi;
+	struct msm_fb_data_type *mfd = NULL;
+	u32 type, id, fb_num;
+
+	if (!pdev)
+		return;
+	id = pdev->id;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata)
+		return;
+	type = pdata->panel_info.type;
+	fb_num = pdata->panel_info.fb_num;
+
+	if (fb_num <= 0)
+		return;
+
+	if (fbi_list_index >= MAX_FBI_LIST) {
+		printk(KERN_ERR "msm_fb: no more framebuffer info list!\n");
+		return;
+	}
+	/*
+	 * alloc panel device data
+	 */
+	this_dev = msm_fb_device_alloc(pdata, type, id);
+
+	if (!this_dev) {
+		printk(KERN_ERR
+		"%s: msm_fb_device_alloc failed!\n", __func__);
+		return;
+	}
+
+	/*
+	 * alloc framebuffer info + par data
+	 */
+	fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), NULL);
+	if (fbi == NULL) {
+		platform_device_put(this_dev);
+		printk(KERN_ERR "msm_fb: can't alloca framebuffer info data!\n");
+		return;
+	}
+
+	mfd = (struct msm_fb_data_type *)fbi->par;
+	mfd->key = MFD_KEY;
+	mfd->fbi = fbi;
+	mfd->panel.type = type;
+	mfd->panel.id = id;
+	mfd->fb_page = fb_num;
+	mfd->index = fbi_list_index;
+	mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
+
+	/* link to the latest pdev */
+	mfd->pdev = this_dev;
+
+	mfd_list[mfd_list_index++] = mfd;
+	fbi_list[fbi_list_index++] = fbi;
+
+	/*
+	 * set driver data
+	 */
+	platform_set_drvdata(this_dev, mfd);
+
+	if (platform_device_add(this_dev)) {
+		printk(KERN_ERR "msm_fb: platform_device_add failed!\n");
+		platform_device_put(this_dev);
+		framebuffer_release(fbi);
+		fbi_list_index--;
+		return;
+	}
+}
+EXPORT_SYMBOL(msm_fb_add_device);
+
+int __init msm_fb_init(void)
+{
+	int rc = -ENODEV;
+
+	if (msm_fb_register_driver())
+		return rc;
+
+#ifdef MSM_FB_ENABLE_DBGFS
+	{
+		struct dentry *root;
+
+		if ((root = msm_fb_get_debugfs_root()) != NULL) {
+			msm_fb_debugfs_file_create(root,
+						   "msm_fb_msg_printing_level",
+						   (u32 *) &msm_fb_msg_level);
+			msm_fb_debugfs_file_create(root,
+						   "mddi_msg_printing_level",
+						   (u32 *) &mddi_msg_level);
+			msm_fb_debugfs_file_create(root, "msm_fb_debug_enabled",
+						   (u32 *) &msm_fb_debug_enabled);
+		}
+	}
+#endif
+
+	return 0;
+}
+
+module_init(msm_fb_init);

+ 174 - 0
drivers/staging/msm/msm_fb.h

@@ -0,0 +1,174 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MSM_FB_H
+#define MSM_FB_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <mach/board.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/memory.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/hrtimer.h>
+
+#include <linux/fb.h>
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#include "msm_fb_panel.h"
+#include "mdp.h"
+
+#define MSM_FB_DEFAULT_PAGE_SIZE 2
+#define MFD_KEY  0x11161126
+#define MSM_FB_MAX_DEV_LIST 32
+
+struct disp_info_type_suspend {
+	boolean op_enable;
+	boolean sw_refreshing_enable;
+	boolean panel_power_on;
+};
+
+struct msm_fb_data_type {
+	__u32 key;
+	__u32 index;
+	__u32 ref_cnt;
+	__u32 fb_page;
+
+	panel_id_type panel;
+	struct msm_panel_info panel_info;
+
+	DISP_TARGET dest;
+	struct fb_info *fbi;
+
+	boolean op_enable;
+	uint32 fb_imgType;
+	boolean sw_currently_refreshing;
+	boolean sw_refreshing_enable;
+	boolean hw_refresh;
+
+	MDPIBUF ibuf;
+	boolean ibuf_flushed;
+	struct timer_list refresh_timer;
+	struct completion refresher_comp;
+
+	boolean pan_waiting;
+	struct completion pan_comp;
+
+	/* vsync */
+	boolean use_mdp_vsync;
+	__u32 vsync_gpio;
+	__u32 total_lcd_lines;
+	__u32 total_porch_lines;
+	__u32 lcd_ref_usec_time;
+	__u32 refresh_timer_duration;
+
+	struct hrtimer dma_hrtimer;
+
+	boolean panel_power_on;
+	struct work_struct dma_update_worker;
+	struct semaphore sem;
+
+	struct timer_list vsync_resync_timer;
+	boolean vsync_handler_pending;
+	struct work_struct vsync_resync_worker;
+
+	ktime_t last_vsync_timetick;
+
+	__u32 *vsync_width_boundary;
+
+	unsigned int pmem_id;
+	struct disp_info_type_suspend suspend;
+
+	__u32 channel_irq;
+
+	struct mdp_dma_data *dma;
+	void (*dma_fnc) (struct msm_fb_data_type *mfd);
+	int (*cursor_update) (struct fb_info *info,
+			      struct fb_cursor *cursor);
+	int (*lut_update) (struct fb_info *info,
+			      struct fb_cmap *cmap);
+	int (*do_histogram) (struct fb_info *info,
+			      struct mdp_histogram *hist);
+	void *cursor_buf;
+	void *cursor_buf_phys;
+
+	void *cmd_port;
+	void *data_port;
+	void *data_port_phys;
+
+	__u32 bl_level;
+
+	struct platform_device *pdev;
+
+	__u32 var_xres;
+	__u32 var_yres;
+	__u32 var_pixclock;
+
+#ifdef MSM_FB_ENABLE_DBGFS
+	struct dentry *sub_dir;
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	struct early_suspend early_suspend;
+	struct early_suspend mddi_early_suspend;
+	struct early_suspend mddi_ext_early_suspend;
+#endif
+	u32 mdp_fb_page_protection;
+	int allow_set_offset;
+};
+
+struct dentry *msm_fb_get_debugfs_root(void);
+void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
+				u32 *var);
+void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl,
+				u32 save);
+
+void msm_fb_add_device(struct platform_device *pdev);
+
+int msm_fb_detect_client(const char *name);
+
+#ifdef CONFIG_FB_BACKLIGHT
+void msm_fb_config_backlight(struct msm_fb_data_type *mfd);
+#endif
+
+#endif /* MSM_FB_H */

+ 79 - 0
drivers/staging/msm/msm_fb_bl.c

@@ -0,0 +1,79 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/backlight.h>
+
+#include "msm_fb.h"
+
+static int msm_fb_bl_get_brightness(struct backlight_device *pbd)
+{
+	return pbd->props.brightness;
+}
+
+static int msm_fb_bl_update_status(struct backlight_device *pbd)
+{
+	struct msm_fb_data_type *mfd = bl_get_data(pbd);
+	__u32 bl_lvl;
+
+	bl_lvl = pbd->props.brightness;
+	bl_lvl = mfd->fbi->bl_curve[bl_lvl];
+	msm_fb_set_backlight(mfd, bl_lvl, 1);
+	return 0;
+}
+
+static struct backlight_ops msm_fb_bl_ops = {
+	.get_brightness = msm_fb_bl_get_brightness,
+	.update_status = msm_fb_bl_update_status,
+};
+
+void msm_fb_config_backlight(struct msm_fb_data_type *mfd)
+{
+	struct msm_fb_panel_data *pdata;
+	struct backlight_device *pbd;
+	struct fb_info *fbi;
+	char name[16];
+
+	fbi = mfd->fbi;
+	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+
+	if ((pdata) && (pdata->set_backlight)) {
+		snprintf(name, sizeof(name), "msmfb_bl%d", mfd->index);
+		pbd =
+		    backlight_device_register(name, fbi->dev, mfd,
+					      &msm_fb_bl_ops);
+		if (!IS_ERR(pbd)) {
+			fbi->bl_dev = pbd;
+			fb_bl_default_curve(fbi,
+					    0,
+					    mfd->panel_info.bl_min,
+					    mfd->panel_info.bl_max);
+			pbd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+			pbd->props.brightness = FB_BACKLIGHT_LEVELS - 1;
+			backlight_update_status(pbd);
+		} else {
+			fbi->bl_dev = NULL;
+			printk(KERN_ERR "msm_fb: backlight_device_register failed!\n");
+		}
+	}
+}

+ 201 - 0
drivers/staging/msm/msm_fb_def.h

@@ -0,0 +1,201 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MSM_FB_DEF_H
+#define MSM_FB_DEF_H
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include "msm_mdp.h"
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+#include <linux/console.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <linux/fb.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/platform_device.h>
+
+typedef s64 int64;
+typedef s32 int32;
+typedef s16 int16;
+typedef s8 int8;
+
+typedef u64 uint64;
+typedef u32 uint32;
+typedef u16 uint16;
+typedef u8 uint8;
+
+typedef s32 int4;
+typedef s16 int2;
+typedef s8 int1;
+
+typedef u32 uint4;
+typedef u16 uint2;
+typedef u8 uint1;
+
+typedef u32 dword;
+typedef u16 word;
+typedef u8 byte;
+
+typedef unsigned int boolean;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define MSM_FB_ENABLE_DBGFS
+#define FEATURE_MDDI
+
+#define outp32(addr, val) writel(val, addr)
+#define outp16(addr, val) writew(val, addr)
+#define outp8(addr, val) writeb(val, addr)
+#define outp(addr, val) outp32(addr, val)
+
+#ifndef MAX
+#define  MAX( x, y ) (((x) > (y)) ? (x) : (y))
+#endif
+
+#ifndef MIN
+#define  MIN( x, y ) (((x) < (y)) ? (x) : (y))
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#define inp32(addr) readl(addr)
+#define inp16(addr) readw(addr)
+#define inp8(addr) readb(addr)
+#define inp(addr) inp32(addr)
+
+#define inpw(port)             readw(port)
+#define outpw(port, val)       writew(val, port)
+#define inpdw(port)            readl(port)
+#define outpdw(port, val)      writel(val, port)
+
+
+#define clk_busy_wait(x) msleep_interruptible((x)/1000)
+
+#define memory_barrier()
+
+#define assert(expr) \
+	if(!(expr)) { \
+		printk(KERN_ERR "msm_fb: assertion failed! %s,%s,%s,line=%d\n",\
+			#expr, __FILE__, __func__, __LINE__); \
+	}
+
+#define ASSERT(x)   assert(x)
+
+#define DISP_EBI2_LOCAL_DEFINE
+#ifdef DISP_EBI2_LOCAL_DEFINE
+#define LCD_PRIM_BASE_PHYS 0x98000000
+#define LCD_SECD_BASE_PHYS 0x9c000000
+#define EBI2_PRIM_LCD_RS_PIN 0x20000
+#define EBI2_SECD_LCD_RS_PIN 0x20000
+
+#define EBI2_PRIM_LCD_CLR 0xC0
+#define EBI2_PRIM_LCD_SEL 0x40
+
+#define EBI2_SECD_LCD_CLR 0x300
+#define EBI2_SECD_LCD_SEL 0x100
+#endif
+
+extern u32 msm_fb_msg_level;
+
+/*
+ * Message printing priorities:
+ * LEVEL 0 KERN_EMERG (highest priority)
+ * LEVEL 1 KERN_ALERT
+ * LEVEL 2 KERN_CRIT
+ * LEVEL 3 KERN_ERR
+ * LEVEL 4 KERN_WARNING
+ * LEVEL 5 KERN_NOTICE
+ * LEVEL 6 KERN_INFO
+ * LEVEL 7 KERN_DEBUG (Lowest priority)
+ */
+#define MSM_FB_EMERG(msg, ...)    \
+	if (msm_fb_msg_level > 0)  \
+		printk(KERN_EMERG msg, ## __VA_ARGS__);
+#define MSM_FB_ALERT(msg, ...)    \
+	if (msm_fb_msg_level > 1)  \
+		printk(KERN_ALERT msg, ## __VA_ARGS__);
+#define MSM_FB_CRIT(msg, ...)    \
+	if (msm_fb_msg_level > 2)  \
+		printk(KERN_CRIT msg, ## __VA_ARGS__);
+#define MSM_FB_ERR(msg, ...)    \
+	if (msm_fb_msg_level > 3)  \
+		printk(KERN_ERR msg, ## __VA_ARGS__);
+#define MSM_FB_WARNING(msg, ...)    \
+	if (msm_fb_msg_level > 4)  \
+		printk(KERN_WARNING msg, ## __VA_ARGS__);
+#define MSM_FB_NOTICE(msg, ...)    \
+	if (msm_fb_msg_level > 5)  \
+		printk(KERN_NOTICE msg, ## __VA_ARGS__);
+#define MSM_FB_INFO(msg, ...)    \
+	if (msm_fb_msg_level > 6)  \
+		printk(KERN_INFO msg, ## __VA_ARGS__);
+#define MSM_FB_DEBUG(msg, ...)    \
+	if (msm_fb_msg_level > 7)  \
+		printk(KERN_DEBUG msg, ## __VA_ARGS__);
+
+#ifdef MSM_FB_C
+unsigned char *msm_mdp_base;
+unsigned char *msm_pmdh_base;
+unsigned char *msm_emdh_base;
+#else
+extern unsigned char *msm_mdp_base;
+extern unsigned char *msm_pmdh_base;
+extern unsigned char *msm_emdh_base;
+#endif
+
+#endif /* MSM_FB_DEF_H */

+ 136 - 0
drivers/staging/msm/msm_fb_panel.c

@@ -0,0 +1,136 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/vmalloc.h>
+#include <linux/debugfs.h>
+
+#include "msm_fb_panel.h"
+
+int panel_next_on(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct msm_fb_panel_data *pdata;
+	struct msm_fb_panel_data *next_pdata;
+	struct platform_device *next_pdev;
+
+	pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data;
+
+	if (pdata) {
+		next_pdev = pdata->next;
+		if (next_pdev) {
+			next_pdata =
+			    (struct msm_fb_panel_data *)next_pdev->dev.
+			    platform_data;
+			if ((next_pdata) && (next_pdata->on))
+				ret = next_pdata->on(next_pdev);
+		}
+	}
+
+	return ret;
+}
+
+int panel_next_off(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct msm_fb_panel_data *pdata;
+	struct msm_fb_panel_data *next_pdata;
+	struct platform_device *next_pdev;
+
+	pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data;
+
+	if (pdata) {
+		next_pdev = pdata->next;
+		if (next_pdev) {
+			next_pdata =
+			    (struct msm_fb_panel_data *)next_pdev->dev.
+			    platform_data;
+			if ((next_pdata) && (next_pdata->on))
+				ret = next_pdata->off(next_pdev);
+		}
+	}
+
+	return ret;
+}
+
+struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
+						u32 type, u32 id)
+{
+	struct platform_device *this_dev = NULL;
+	char dev_name[16];
+
+	switch (type) {
+	case EBI2_PANEL:
+		snprintf(dev_name, sizeof(dev_name), "ebi2_lcd");
+		break;
+
+	case MDDI_PANEL:
+		snprintf(dev_name, sizeof(dev_name), "mddi");
+		break;
+
+	case EXT_MDDI_PANEL:
+		snprintf(dev_name, sizeof(dev_name), "mddi_ext");
+		break;
+
+	case TV_PANEL:
+		snprintf(dev_name, sizeof(dev_name), "tvenc");
+		break;
+
+	case HDMI_PANEL:
+	case LCDC_PANEL:
+		snprintf(dev_name, sizeof(dev_name), "lcdc");
+		break;
+
+	default:
+		return NULL;
+	}
+
+	if (pdata != NULL)
+		pdata->next = NULL;
+	else
+		return NULL;
+
+	this_dev =
+	    platform_device_alloc(dev_name, ((u32) type << 16) | (u32) id);
+
+	if (this_dev) {
+		if (platform_device_add_data
+		    (this_dev, pdata, sizeof(struct msm_fb_panel_data))) {
+			printk
+			    ("msm_fb_device_alloc: platform_device_add_data failed!\n");
+			platform_device_put(this_dev);
+			return NULL;
+		}
+	}
+
+	return this_dev;
+}

+ 145 - 0
drivers/staging/msm/msm_fb_panel.h

@@ -0,0 +1,145 @@
+/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef MSM_FB_PANEL_H
+#define MSM_FB_PANEL_H
+
+#include "msm_fb_def.h"
+
+struct msm_fb_data_type;
+
+typedef void (*msm_fb_vsync_handler_type) (void *arg);
+
+/* panel id type */
+typedef struct panel_id_s {
+	uint16 id;
+	uint16 type;
+} panel_id_type;
+
+/* panel type list */
+#define NO_PANEL       0xffff	/* No Panel */
+#define MDDI_PANEL     1	/* MDDI */
+#define EBI2_PANEL     2	/* EBI2 */
+#define LCDC_PANEL     3	/* internal LCDC type */
+#define EXT_MDDI_PANEL 4	/* Ext.MDDI */
+#define TV_PANEL       5	/* TV */
+#define HDMI_PANEL     6	/* HDMI TV */
+
+/* panel class */
+typedef enum {
+	DISPLAY_LCD = 0,	/* lcd = ebi2/mddi */
+	DISPLAY_LCDC,		/* lcdc */
+	DISPLAY_TV,		/* TV Out */
+	DISPLAY_EXT_MDDI,	/* External MDDI */
+} DISP_TARGET;
+
+/* panel device locaiton */
+typedef enum {
+	DISPLAY_1 = 0,		/* attached as first device */
+	DISPLAY_2,		/* attached on second device */
+	MAX_PHYS_TARGET_NUM,
+} DISP_TARGET_PHYS;
+
+/* panel info type */
+struct lcd_panel_info {
+	__u32 vsync_enable;
+	__u32 refx100;
+	__u32 v_back_porch;
+	__u32 v_front_porch;
+	__u32 v_pulse_width;
+	__u32 hw_vsync_mode;
+	__u32 vsync_notifier_period;
+};
+
+struct lcdc_panel_info {
+	__u32 h_back_porch;
+	__u32 h_front_porch;
+	__u32 h_pulse_width;
+	__u32 v_back_porch;
+	__u32 v_front_porch;
+	__u32 v_pulse_width;
+	__u32 border_clr;
+	__u32 underflow_clr;
+	__u32 hsync_skew;
+};
+
+struct mddi_panel_info {
+	__u32 vdopkt;
+};
+
+struct msm_panel_info {
+	__u32 xres;
+	__u32 yres;
+	__u32 bpp;
+	__u32 type;
+	__u32 wait_cycle;
+	DISP_TARGET_PHYS pdest;
+	__u32 bl_max;
+	__u32 bl_min;
+	__u32 fb_num;
+	__u32 clk_rate;
+	__u32 clk_min;
+	__u32 clk_max;
+	__u32 frame_count;
+
+	union {
+		struct mddi_panel_info mddi;
+	};
+
+	union {
+		struct lcd_panel_info lcd;
+		struct lcdc_panel_info lcdc;
+	};
+};
+
+struct msm_fb_panel_data {
+	struct msm_panel_info panel_info;
+	void (*set_rect) (int x, int y, int xres, int yres);
+	void (*set_vsync_notifier) (msm_fb_vsync_handler_type, void *arg);
+	void (*set_backlight) (struct msm_fb_data_type *);
+
+	/* function entry chain */
+	int (*on) (struct platform_device *pdev);
+	int (*off) (struct platform_device *pdev);
+	struct platform_device *next;
+};
+
+/*===========================================================================
+  FUNCTIONS PROTOTYPES
+============================================================================*/
+struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
+						u32 type, u32 id);
+int panel_next_on(struct platform_device *pdev);
+int panel_next_off(struct platform_device *pdev);
+
+int lcdc_device_register(struct msm_panel_info *pinfo);
+
+int mddi_toshiba_device_register(struct msm_panel_info *pinfo,
+					u32 channel, u32 panel);
+
+#endif /* MSM_FB_PANEL_H */

Some files were not shown because too many files changed in this diff