mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-20 08:38:24 +08:00
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 ...
This commit is contained in:
commit
a094c0afc3
@ -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
|
||||
|
@ -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,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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,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"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_1032 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_1032"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_1500 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_1500"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_1516 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_1516"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_1564 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_1564"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_16XX 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_16xx"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_1710 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_1710"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_2016 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_2016"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_2032 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_2032"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_2200 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_2200"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_3001 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3001"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_3120 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3120"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_3200 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3200"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_3300 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3300"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_3501 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3501"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define CONFIG_APCI_3XXX 1
|
||||
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3xxx"
|
||||
|
||||
#include "addi-data/addi_common.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;
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
|
@ -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",
|
||||
|
@ -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
drivers/staging/mrst-touchscreen/Kconfig
Normal file
7
drivers/staging/mrst-touchscreen/Kconfig
Normal file
@ -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
drivers/staging/mrst-touchscreen/Makefile
Normal file
3
drivers/staging/mrst-touchscreen/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) := intel_mid_touch.o
|
||||
|
||||
|
2
drivers/staging/mrst-touchscreen/TODO
Normal file
2
drivers/staging/mrst-touchscreen/TODO
Normal file
@ -0,0 +1,2 @@
|
||||
- Move the driver to not think it is SPI (requires fixing some of the SFI
|
||||
and firmware side)
|
864
drivers/staging/mrst-touchscreen/intel-mid-touch.c
Normal file
864
drivers/staging/mrst-touchscreen/intel-mid-touch.c
Normal file
@ -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, ®);
|
||||
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
drivers/staging/msm/Kconfig
Normal file
134
drivers/staging/msm/Kconfig
Normal file
@ -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
drivers/staging/msm/Makefile
Normal file
93
drivers/staging/msm/Makefile
Normal file
@ -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
drivers/staging/msm/TODO
Normal file
3
drivers/staging/msm/TODO
Normal file
@ -0,0 +1,3 @@
|
||||
- Merge this code with the existing MSM framebuffer
|
||||
- General style clean ups.
|
||||
|
569
drivers/staging/msm/ebi2_l2f.c
Normal file
569
drivers/staging/msm/ebi2_l2f.c
Normal file
@ -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
drivers/staging/msm/ebi2_lcd.c
Normal file
250
drivers/staging/msm/ebi2_lcd.c
Normal file
@ -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
drivers/staging/msm/ebi2_tmd20.c
Normal file
1122
drivers/staging/msm/ebi2_tmd20.c
Normal file
File diff suppressed because it is too large
Load Diff
248
drivers/staging/msm/hdmi_sii9022.c
Normal file
248
drivers/staging/msm/hdmi_sii9022.c
Normal file
@ -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
drivers/staging/msm/lcdc.c
Normal file
239
drivers/staging/msm/lcdc.c
Normal file
@ -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
drivers/staging/msm/lcdc_external.c
Normal file
54
drivers/staging/msm/lcdc_external.c
Normal file
@ -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
drivers/staging/msm/lcdc_gordon.c
Normal file
446
drivers/staging/msm/lcdc_gordon.c
Normal file
@ -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
drivers/staging/msm/lcdc_grapefruit.c
Normal file
60
drivers/staging/msm/lcdc_grapefruit.c
Normal file
@ -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
drivers/staging/msm/lcdc_panel.c
Normal file
88
drivers/staging/msm/lcdc_panel.c
Normal file
@ -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
drivers/staging/msm/lcdc_prism.c
Normal file
64
drivers/staging/msm/lcdc_prism.c
Normal file
@ -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
drivers/staging/msm/lcdc_sharp_wvga_pt.c
Normal file
290
drivers/staging/msm/lcdc_sharp_wvga_pt.c
Normal file
@ -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
drivers/staging/msm/lcdc_st15.c
Normal file
237
drivers/staging/msm/lcdc_st15.c
Normal file
@ -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
drivers/staging/msm/lcdc_st1_wxga.c
Normal file
54
drivers/staging/msm/lcdc_st1_wxga.c
Normal file
@ -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
drivers/staging/msm/lcdc_toshiba_wvga_pt.c
Normal file
374
drivers/staging/msm/lcdc_toshiba_wvga_pt.c
Normal file
@ -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
drivers/staging/msm/lcdc_wxga.c
Normal file
56
drivers/staging/msm/lcdc_wxga.c
Normal file
@ -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
drivers/staging/msm/logo.c
Normal file
98
drivers/staging/msm/logo.c
Normal file
@ -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
drivers/staging/msm/mddi.c
Normal file
375
drivers/staging/msm/mddi.c
Normal file
@ -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
drivers/staging/msm/mddi_ext.c
Normal file
320
drivers/staging/msm/mddi_ext.c
Normal file
@ -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
drivers/staging/msm/mddi_ext_lcd.c
Normal file
91
drivers/staging/msm/mddi_ext_lcd.c
Normal file
@ -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
drivers/staging/msm/mddi_prism.c
Normal file
114
drivers/staging/msm/mddi_prism.c
Normal file
@ -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
drivers/staging/msm/mddi_sharp.c
Normal file
892
drivers/staging/msm/mddi_sharp.c
Normal file
@ -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, ®data, TRUE, 0);
|
||||
mddi_queue_register_write(REG_GIOA, regdata & 0xfff8, TRUE, 0);
|
||||
|
||||
/* Set lower 3 GPIOs as level */
|
||||
mddi_queue_register_read(REG_GIOD, ®data, 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
drivers/staging/msm/mddi_toshiba.c
Normal file
1741
drivers/staging/msm/mddi_toshiba.c
Normal file
File diff suppressed because it is too large
Load Diff
52
drivers/staging/msm/mddi_toshiba.h
Normal file
52
drivers/staging/msm/mddi_toshiba.h
Normal file
@ -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
drivers/staging/msm/mddi_toshiba_vga.c
Normal file
136
drivers/staging/msm/mddi_toshiba_vga.c
Normal file
@ -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
drivers/staging/msm/mddi_toshiba_wvga.c
Normal file
63
drivers/staging/msm/mddi_toshiba_wvga.c
Normal file
@ -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
drivers/staging/msm/mddi_toshiba_wvga_pt.c
Normal file
64
drivers/staging/msm/mddi_toshiba_wvga_pt.c
Normal file
@ -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
drivers/staging/msm/mddihost.c
Normal file
377
drivers/staging/msm/mddihost.c
Normal file
@ -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 *)(®acc_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
drivers/staging/msm/mddihost.h
Normal file
225
drivers/staging/msm/mddihost.h
Normal file
@ -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
drivers/staging/msm/mddihost_e.c
Normal file
63
drivers/staging/msm/mddihost_e.c
Normal file
@ -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
drivers/staging/msm/mddihosti.c
Normal file
2239
drivers/staging/msm/mddihosti.c
Normal file
File diff suppressed because it is too large
Load Diff
547
drivers/staging/msm/mddihosti.h
Normal file
547
drivers/staging/msm/mddihosti.h
Normal file
@ -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
drivers/staging/msm/mdp.c
Normal file
1113
drivers/staging/msm/mdp.c
Normal file
File diff suppressed because it is too large
Load Diff
695
drivers/staging/msm/mdp.h
Normal file
695
drivers/staging/msm/mdp.h
Normal file
@ -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
drivers/staging/msm/mdp4.h
Normal file
352
drivers/staging/msm/mdp4.h
Normal file
@ -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
drivers/staging/msm/mdp4_debugfs.c
Normal file
181
drivers/staging/msm/mdp4_debugfs.c
Normal file
@ -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
drivers/staging/msm/mdp4_overlay.c
Normal file
1259
drivers/staging/msm/mdp4_overlay.c
Normal file
File diff suppressed because it is too large
Load Diff
313
drivers/staging/msm/mdp4_overlay_lcdc.c
Normal file
313
drivers/staging/msm/mdp4_overlay_lcdc.c
Normal file
@ -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
drivers/staging/msm/mdp4_overlay_mddi.c
Normal file
254
drivers/staging/msm/mdp4_overlay_mddi.c
Normal file
@ -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
drivers/staging/msm/mdp4_util.c
Normal file
1686
drivers/staging/msm/mdp4_util.c
Normal file
File diff suppressed because it is too large
Load Diff
104
drivers/staging/msm/mdp_cursor.c
Normal file
104
drivers/staging/msm/mdp_cursor.c
Normal file
@ -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
drivers/staging/msm/mdp_dma.c
Normal file
561
drivers/staging/msm/mdp_dma.c
Normal file
@ -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
drivers/staging/msm/mdp_dma_lcdc.c
Normal file
379
drivers/staging/msm/mdp_dma_lcdc.c
Normal file
@ -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
drivers/staging/msm/mdp_dma_s.c
Normal file
139
drivers/staging/msm/mdp_dma_s.c
Normal file
@ -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
drivers/staging/msm/mdp_dma_tv.c
Normal file
142
drivers/staging/msm/mdp_dma_tv.c
Normal file
@ -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
drivers/staging/msm/mdp_hw_init.c
Normal file
720
drivers/staging/msm/mdp_hw_init.c
Normal file
@ -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
drivers/staging/msm/mdp_ppp.c
Normal file
1502
drivers/staging/msm/mdp_ppp.c
Normal file
File diff suppressed because it is too large
Load Diff
347
drivers/staging/msm/mdp_ppp_dq.c
Normal file
347
drivers/staging/msm/mdp_ppp_dq.c
Normal file
@ -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
drivers/staging/msm/mdp_ppp_dq.h
Normal file
86
drivers/staging/msm/mdp_ppp_dq.h
Normal file
@ -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
drivers/staging/msm/mdp_ppp_v20.c
Normal file
2486
drivers/staging/msm/mdp_ppp_v20.c
Normal file
File diff suppressed because it is too large
Load Diff
828
drivers/staging/msm/mdp_ppp_v31.c
Normal file
828
drivers/staging/msm/mdp_ppp_v31.c
Normal file
@ -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
drivers/staging/msm/mdp_vsync.c
Normal file
389
drivers/staging/msm/mdp_vsync.c
Normal file
@ -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
drivers/staging/msm/memory.c
Normal file
214
drivers/staging/msm/memory.c
Normal file
@ -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
drivers/staging/msm/memory_ll.h
Normal file
61
drivers/staging/msm/memory_ll.h
Normal file
@ -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
drivers/staging/msm/msm_fb.c
Normal file
2354
drivers/staging/msm/msm_fb.c
Normal file
File diff suppressed because it is too large
Load Diff
174
drivers/staging/msm/msm_fb.h
Normal file
174
drivers/staging/msm/msm_fb.h
Normal file
@ -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
drivers/staging/msm/msm_fb_bl.c
Normal file
79
drivers/staging/msm/msm_fb_bl.c
Normal file
@ -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
drivers/staging/msm/msm_fb_def.h
Normal file
201
drivers/staging/msm/msm_fb_def.h
Normal file
@ -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
drivers/staging/msm/msm_fb_panel.c
Normal file
136
drivers/staging/msm/msm_fb_panel.c
Normal file
@ -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
drivers/staging/msm/msm_fb_panel.h
Normal file
145
drivers/staging/msm/msm_fb_panel.h
Normal file
@ -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 have changed in this diff Show More
Loading…
Reference in New Issue
Block a user