diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-08-16 14:40:44 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-08-16 14:40:44 -0400 |
commit | 9714d315d28aef77a097fe905b25cc273c3d72ad (patch) | |
tree | 0ae1150b0723e925785ce774c3554f29fda050f6 /drivers/staging | |
parent | 84c164a34ffe67908a932a2d641ec1a80c2d5435 (diff) | |
parent | 6ccf15a1a76d2ff915cdef6ae4d12d0170087118 (diff) | |
download | talos-op-linux-9714d315d28aef77a097fe905b25cc273c3d72ad.tar.gz talos-op-linux-9714d315d28aef77a097fe905b25cc273c3d72ad.zip |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
Diffstat (limited to 'drivers/staging')
227 files changed, 75282 insertions, 8044 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index b5c3b3013037..0e4122ed1b36 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -109,8 +109,6 @@ source "drivers/staging/hv/Kconfig" source "drivers/staging/vme/Kconfig" -source "drivers/staging/rar_register/Kconfig" - source "drivers/staging/memrar/Kconfig" source "drivers/staging/sep/Kconfig" @@ -141,5 +139,13 @@ 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" + +source "drivers/staging/lirc/Kconfig" + endif # !STAGING_EXCLUDE_BUILD endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index e330dd5e843d..ecfb0bb990b6 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_VIDEO_GO7007) += go7007/ obj-$(CONFIG_VIDEO_CX25821) += cx25821/ obj-$(CONFIG_VIDEO_TM6000) += tm6000/ +obj-$(CONFIG_LIRC_STAGING) += lirc/ obj-$(CONFIG_USB_IP_COMMON) += usbip/ obj-$(CONFIG_W35UND) += winbond/ obj-$(CONFIG_PRISM2_USB) += wlan-ng/ @@ -35,7 +36,6 @@ obj-$(CONFIG_VT6656) += vt6656/ obj-$(CONFIG_FB_UDL) += udlfb/ obj-$(CONFIG_HYPERV) += hv/ obj-$(CONFIG_VME_BUS) += vme/ -obj-$(CONFIG_RAR_REGISTER) += rar_register/ obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/ obj-$(CONFIG_DX_SEP) += sep/ obj-$(CONFIG_IIO) += iio/ @@ -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/ diff --git a/drivers/staging/adis16255/Kconfig b/drivers/staging/adis16255/Kconfig index a642be66adea..a883c1f4478b 100644 --- a/drivers/staging/adis16255/Kconfig +++ b/drivers/staging/adis16255/Kconfig @@ -1,5 +1,5 @@ config ADIS16255 - tristate "Ananlog Devices ADIS16250/16255" + tristate "Analog Devices ADIS16250/16255" depends on SPI && SYSFS ---help--- If you say yes here you get support for the Analog Devices diff --git a/drivers/staging/adis16255/adis16255.c b/drivers/staging/adis16255/adis16255.c index 1ba11f00b2e7..55d66e290f7d 100644 --- a/drivers/staging/adis16255/adis16255.c +++ b/drivers/staging/adis16255/adis16255.c @@ -361,7 +361,7 @@ err: /*-------------------------------------------------------------------------*/ -static int spi_adis16255_probe(struct spi_device *spi) +static int __devinit spi_adis16255_probe(struct spi_device *spi) { struct adis16255_init_data *init_data = spi->dev.platform_data; @@ -421,7 +421,7 @@ err: return status; } -static int spi_adis16255_remove(struct spi_device *spi) +static int __devexit spi_adis16255_remove(struct spi_device *spi) { struct spi_adis16255_data *spiadis = dev_get_drvdata(&spi->dev); diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index e2c000b80ca0..212bc21e6d68 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -225,9 +225,9 @@ static struct bat_attribute *mesh_attrs[] = { NULL, }; -static ssize_t transtable_local_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) +static ssize_t transtable_local_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buff, loff_t off, size_t count) { struct device *dev = to_dev(kobj->parent); struct net_device *net_dev = to_net_dev(dev); @@ -235,9 +235,9 @@ static ssize_t transtable_local_read(struct kobject *kobj, return hna_local_fill_buffer_text(net_dev, buff, count, off); } -static ssize_t transtable_global_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) +static ssize_t transtable_global_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buff, loff_t off, size_t count) { struct device *dev = to_dev(kobj->parent); struct net_device *net_dev = to_net_dev(dev); @@ -245,9 +245,9 @@ static ssize_t transtable_global_read(struct kobject *kobj, return hna_global_fill_buffer_text(net_dev, buff, count, off); } -static ssize_t originators_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) +static ssize_t originators_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buff, loff_t off, size_t count) { struct device *dev = to_dev(kobj->parent); struct net_device *net_dev = to_net_dev(dev); @@ -255,9 +255,9 @@ static ssize_t originators_read(struct kobject *kobj, return orig_fill_buffer_text(net_dev, buff, count, off); } -static ssize_t vis_data_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buff, loff_t off, size_t count) +static ssize_t vis_data_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buff, loff_t off, size_t count) { struct device *dev = to_dev(kobj->parent); struct net_device *net_dev = to_net_dev(dev); diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c index ad82ec4a4856..32204b5572d0 100644 --- a/drivers/staging/batman-adv/device.c +++ b/drivers/staging/batman-adv/device.c @@ -196,7 +196,7 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, kfree(device_packet); if (error) - return error; + return -EFAULT; return sizeof(struct icmp_packet); } @@ -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; diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index 9d13979c2d8e..74c70d589a93 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -127,7 +127,10 @@ int init_module(void) return 0; unreg_soft_device: - unregister_netdevice(soft_device); + unregister_netdev(soft_device); + soft_device = NULL; + return -ENOMEM; + free_soft_device: free_netdev(soft_device); soft_device = NULL; diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index d8536e277a26..ac69ed871a76 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -440,6 +440,9 @@ void send_outstanding_bcast_packet(struct work_struct *work) hlist_del(&forw_packet->list); spin_unlock_irqrestore(&forw_bcast_list_lock, flags); + if (atomic_read(&module_state) == MODULE_DEACTIVATING) + goto out; + /* rebroadcast packet */ rcu_read_lock(); list_for_each_entry_rcu(batman_if, &if_list, list) { @@ -453,15 +456,15 @@ void send_outstanding_bcast_packet(struct work_struct *work) forw_packet->num_packets++; - /* if we still have some more bcasts to send and we are not shutting - * down */ - if ((forw_packet->num_packets < 3) && - (atomic_read(&module_state) != MODULE_DEACTIVATING)) + /* if we still have some more bcasts to send */ + if (forw_packet->num_packets < 3) { _add_bcast_packet_to_list(forw_packet, ((5 * HZ) / 1000)); - else { - forw_packet_free(forw_packet); - atomic_inc(&bcast_queue_left); + return; } + +out: + forw_packet_free(forw_packet); + atomic_inc(&bcast_queue_left); } void send_outstanding_bat_packet(struct work_struct *work) @@ -476,6 +479,9 @@ void send_outstanding_bat_packet(struct work_struct *work) hlist_del(&forw_packet->list); spin_unlock_irqrestore(&forw_bat_list_lock, flags); + if (atomic_read(&module_state) == MODULE_DEACTIVATING) + goto out; + send_packet(forw_packet); /** @@ -483,10 +489,10 @@ void send_outstanding_bat_packet(struct work_struct *work) * to determine the queues wake up time unless we are * shutting down */ - if ((forw_packet->own) && - (atomic_read(&module_state) != MODULE_DEACTIVATING)) + if (forw_packet->own) schedule_own_packet(forw_packet->if_incoming); +out: /* don't count own packet */ if (!forw_packet->own) atomic_inc(&batman_queue_left); diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 8ce307e64b58..aad47326d6dc 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -100,15 +100,6 @@ menuconfig COMEDI_ISA_DRIVERS if COMEDI_ISA_DRIVERS && ISA -config COMEDI_8255 - tristate "Generic 8255 support" - default N - ---help--- - Enable generic 8255 support. - - To compile this driver as a module, choose M here: the module will be - called 8255. - config COMEDI_ACL7225B tristate "ADlink NuDAQ ACL-7225b and compatibles support" default N @@ -130,6 +121,7 @@ config COMEDI_PCL711 config COMEDI_PCL724 tristate "Advantech PCL-722/724/731 and ADlink ACL-7122/7124/PET-48DIO" + select COMEDI_8255 default N ---help--- Enable support for Advantech PCL-724, PCL-722, PCL-731 and @@ -198,6 +190,7 @@ config COMEDI_PCL818 config COMEDI_PCM3724 tristate "Advantech PCM-3724 PC/104 card support" + select COMEDI_8255 default N ---help--- Enable support for Advantech PCM-3724 PC/104 cards. @@ -232,18 +225,9 @@ config COMEDI_RTI802 To compile this driver as a module, choose M here: the module will be called rti802. -config COMEDI_DAS08 - tristate "DAS-08 compatible ISA, PC/104 and PCMCIA card support" - default N - ---help--- - Enable support for Keithley Metrabyte/ComputerBoards DAS08 - and compatible ISA and PC/104 cards - - To compile this driver as a module, choose M here: the module will be - called das08. - config COMEDI_DAS16M1 tristate "MeasurementComputing CIO-DAS16/M1DAS-16 ISA card support" + select COMEDI_8255 select COMEDI_FC default N ---help--- @@ -254,6 +238,7 @@ config COMEDI_DAS16M1 config COMEDI_DAS16 tristate "DAS-16 compatible ISA and PC/104 card support" + select COMEDI_8255 select COMEDI_FC default N ---help--- @@ -385,6 +370,7 @@ config COMEDI_FL512 config COMEDI_AIO_AIO12_8 tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support" + select COMEDI_8255 default N ---help--- Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board @@ -466,6 +452,7 @@ config COMEDI_NI_ATMIO config COMEDI_NI_ATMIO16D tristate "NI AT-MIO16/AT-MIO16D series ISA-PNP card support" depends on ISAPNP && COMEDI_NI_COMMON + select COMEDI_8255 default N ---help--- Enable support for National Instruments AT-MIO16/AT-MIO16D cards. @@ -667,6 +654,7 @@ config COMEDI_ADDI_APCI_3XXX config COMEDI_ADL_PCI6208 tristate "ADLink PCI-6208A support" + select COMEDI_8255 default N ---help--- Enable support for ADLink PCI-6208A cards @@ -751,6 +739,7 @@ config COMEDI_ADV_PCI1723 config COMEDI_ADV_PCI_DIO tristate "Advantech PCI DIO card support" + select COMEDI_8255 default N ---help--- Enable support for Advantech PCI DIO cards @@ -762,6 +751,7 @@ config COMEDI_ADV_PCI_DIO config COMEDI_AMPLC_DIO200 tristate "Amplicon PC272E and PCI272 DIO board support" + select COMEDI_8255 default N ---help--- Enable support for Amplicon PC272E and PCI272 DIO boards @@ -771,6 +761,7 @@ config COMEDI_AMPLC_DIO200 config COMEDI_AMPLC_PC236 tristate "Amplicon PC36AT and PCI236 DIO board support" + select COMEDI_8255 default N ---help--- Enable support for Amplicon PC36AT and PCI236 DIO boards @@ -799,6 +790,7 @@ config COMEDI_AMPLC_PCI224 config COMEDI_AMPLC_PCI230 tristate "Amplicon PCI230 and PCI260 support" + select COMEDI_8255 default N ---help--- Enable support for Amplicon PCI230 and PCI260 Multifunction I/O @@ -869,6 +861,7 @@ config COMEDI_II_PCI20KC config COMEDI_DAQBOARD2000 tristate "IOtech DAQboard/2000 support" + select COMEDI_8255 default N ---help--- Enable support for the IOtech DAQboard/2000 @@ -896,6 +889,7 @@ config COMEDI_KE_COUNTER config COMEDI_CB_PCIDAS64 tristate "MeasurementComputing PCI-DAS 64xx, 60xx, and 4020 support" + select COMEDI_8255 select COMEDI_FC default N ---help--- @@ -907,6 +901,7 @@ config COMEDI_CB_PCIDAS64 config COMEDI_CB_PCIDAS tristate "MeasurementComputing PCI-DAS support" + select COMEDI_8255 select COMEDI_FC default N ---help--- @@ -920,6 +915,7 @@ config COMEDI_CB_PCIDAS config COMEDI_CB_PCIDDA tristate "MeasurementComputing PCI-DDA series support" + select COMEDI_8255 default N ---help--- Enable support for ComputerBoards/MeasurementComputing PCI-DDA @@ -931,6 +927,7 @@ config COMEDI_CB_PCIDDA config COMEDI_CB_PCIDIO tristate "MeasurementComputing PCI-DIO series support" + select COMEDI_8255 default N ---help--- Enable support for ComputerBoards/MeasurementComputing PCI-DIO series @@ -941,6 +938,7 @@ config COMEDI_CB_PCIDIO config COMEDI_CB_PCIMDAS tristate "MeasurementComputing PCIM-DAS1602/16 support" + select COMEDI_8255 default N ---help--- Enable support for ComputerBoards/MeasurementComputing PCI Migration @@ -951,6 +949,7 @@ config COMEDI_CB_PCIMDAS config COMEDI_CB_PCIMDDA tristate "MeasurementComputing PCIM-DDA06-16 support" + select COMEDI_8255 default N ---help--- Enable support for ComputerBoards/MeasurementComputing PCIM-DDA06-16 @@ -1026,6 +1025,7 @@ config COMEDI_NI_670X config COMEDI_NI_PCIDIO tristate "NI PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503 support" depends on COMEDI_MITE + select COMEDI_8255 default N ---help--- Enable support for National Instruments PCI-DIO-32HS, PXI-6533, @@ -1058,6 +1058,7 @@ config COMEDI_NI_PCIMIO config COMEDI_RTD520 tristate "Real Time Devices PCI4520/DM7520 support" + select COMEDI_8255 default N ---help--- Enable support for Real Time Devices PCI4520/DM7520 @@ -1097,7 +1098,7 @@ endif # COMEDI_PCI_DRIVERS menuconfig COMEDI_PCMCIA_DRIVERS tristate "Comedi PCMCIA drivers" - depends on COMEDI && PCMCIA && PCCARD + depends on COMEDI && (PCMCIA || PCCARD) default N ---help--- Enable comedi PCMCIA and PCCARD drivers to be built @@ -1142,6 +1143,7 @@ config COMEDI_NI_DAQ_700_CS config COMEDI_NI_DAQ_DIO24_CS tristate "NI DAQ-Card DIO-24 PCMCIA support" depends on COMEDI_NI_COMMON + select COMEDI_8255 default N ---help--- Enable support for the National Instruments PCMCIA DAQ-Card DIO-24 @@ -1162,8 +1164,8 @@ config COMEDI_NI_LABPC_CS config COMEDI_NI_MIO_CS tristate "NI DAQCard E series PCMCIA support" depends on COMEDI_NI_TIO && COMEDI_NI_COMMON - default N select COMEDI_FC + default N ---help--- Enable support for the National Instruments PCMCIA DAQCard E series DAQCard-ai-16xe-50, DAQCard-ai-16e-4, DAQCard-6062E, DAQCard-6024E @@ -1265,7 +1267,8 @@ config COMEDI_MITE config COMEDI_NI_TIO tristate "NI general purpose counter support" - select COMEDI_MITE + depends on COMEDI_MITE + select COMEDI_8255 default N ---help--- Enable support for National Instruments general purpose counters. @@ -1278,6 +1281,8 @@ config COMEDI_NI_TIO config COMEDI_NI_LABPC tristate "NI Lab-PC and compatibles ISA and PCI support" + depends on COMEDI_MITE + select COMEDI_8255 select COMEDI_FC default N ---help--- @@ -1291,8 +1296,40 @@ config COMEDI_NI_LABPC endif # COMEDI_NI_COMMON +config COMEDI_8255 + tristate "Generic 8255 support" + depends on COMEDI + default N + ---help--- + Enable generic 8255 support. + + You should enable compilation this driver if you plan to use a board + that has an 8255 chip. For multifunction boards, the main driver will + configure the 8255 subdevice automatically. + + Note that most PCI 8255 boards do NOT work with this driver, and + need a separate driver as a wrapper. + + To compile this driver as a module, choose M here: the module will be + called 8255. + +config COMEDI_DAS08 + tristate "DAS-08 compatible support" + depends on COMEDI + select COMEDI_8255 + default N + ---help--- + Enable support for DAS08 and compatible ISA, PC/104 and PCI cards. + + Note that PCMCIA DAS08 cards are not directly supported by this + driver, and need a separate driver as a wrapper. + + To compile this driver as a module, choose M here: the module will be + called das08. + config COMEDI_FC tristate "Comedi shared functions for low-level driver support" + depends on COMEDI default N ---help--- Enable support for shared functions for low-level drivers. diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index aced00e5cd10..aeb2c00875cd 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -83,7 +83,7 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo __user *arg); static int do_bufinfo_ioctl(struct comedi_device *dev, - struct comedi_bufinfo __user *arg); + struct comedi_bufinfo __user *arg, void *file); static int do_cmd_ioctl(struct comedi_device *dev, struct comedi_cmd __user *arg, void *file); static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg, @@ -169,7 +169,8 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, break; case COMEDI_BUFINFO: rc = do_bufinfo_ioctl(dev, - (struct comedi_bufinfo __user *)arg); + (struct comedi_bufinfo __user *)arg, + file); break; case COMEDI_LOCK: rc = do_lock_ioctl(dev, arg, file); @@ -563,7 +564,7 @@ static int do_chaninfo_ioctl(struct comedi_device *dev, */ static int do_bufinfo_ioctl(struct comedi_device *dev, - struct comedi_bufinfo __user *arg) + struct comedi_bufinfo __user *arg, void *file) { struct comedi_bufinfo bi; struct comedi_subdevice *s; @@ -576,6 +577,10 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, return -EINVAL; s = dev->subdevices + bi.subdevice; + + if (s->lock && s->lock != file) + return -EACCES; + async = s->async; if (!async) { @@ -584,8 +589,17 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, bi.buf_read_ptr = 0; bi.buf_write_count = 0; bi.buf_read_count = 0; + bi.bytes_read = 0; + bi.bytes_written = 0; goto copyback; } + if (!s->busy) { + bi.bytes_read = 0; + bi.bytes_written = 0; + goto copyback_position; + } + if (s->busy != file) + return -EACCES; if (bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)) { bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read); @@ -604,6 +618,7 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, comedi_buf_write_free(async, bi.bytes_written); } +copyback_position: bi.buf_write_count = async->buf_write_count; bi.buf_write_ptr = async->buf_write_ptr; bi.buf_read_count = async->buf_read_count; @@ -1576,6 +1591,19 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, while (nbytes > 0 && !retval) { set_current_state(TASK_INTERRUPTIBLE); + if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) { + if (count == 0) { + if (comedi_get_subdevice_runflags(s) & + SRF_ERROR) { + retval = -EPIPE; + } else { + retval = 0; + } + do_become_nonbusy(dev, s); + } + break; + } + n = nbytes; m = n; @@ -1588,16 +1616,6 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, n = m; if (n == 0) { - if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) { - if (comedi_get_subdevice_runflags(s) & - SRF_ERROR) { - retval = -EPIPE; - } else { - retval = 0; - } - do_become_nonbusy(dev, s); - break; - } if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile index 5ccf246e2526..354fb7d29841 100644 --- a/drivers/staging/comedi/drivers/Makefile +++ b/drivers/staging/comedi/drivers/Makefile @@ -12,7 +12,6 @@ obj-$(CONFIG_COMEDI_SERIAL2002) += serial2002.o obj-$(CONFIG_COMEDI_SKEL) += skel.o # Comedi ISA drivers -obj-$(CONFIG_COMEDI_8255) += 8255.o obj-$(CONFIG_COMEDI_ACL7225B) += acl7225b.o obj-$(CONFIG_COMEDI_PCL711) += pcl711.o obj-$(CONFIG_COMEDI_PCL724) += pcl724.o @@ -26,7 +25,6 @@ obj-$(CONFIG_COMEDI_PCM3724) += pcm3724.o obj-$(CONFIG_COMEDI_PCM3730) += pcm3730.o obj-$(CONFIG_COMEDI_RTI800) += rti800.o obj-$(CONFIG_COMEDI_RTI802) += rti802.o -obj-$(CONFIG_COMEDI_DAS08) += das08.o obj-$(CONFIG_COMEDI_DAS16M1) += das16m1.o obj-$(CONFIG_COMEDI_DAS16) += das16.o obj-$(CONFIG_COMEDI_DAS800) += das800.o @@ -135,4 +133,6 @@ obj-$(CONFIG_COMEDI_NI_TIO) += ni_tio.o obj-$(CONFIG_COMEDI_NI_TIO) += ni_tiocmd.o obj-$(CONFIG_COMEDI_NI_LABPC) += ni_labpc.o +obj-$(CONFIG_COMEDI_8255) += 8255.o +obj-$(CONFIG_COMEDI_DAS08) += das08.o obj-$(CONFIG_COMEDI_FC) += comedi_fc.o diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c index 2c986413a81a..b18e81d8cf8a 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.c +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c @@ -68,6 +68,10 @@ You should also find the complete GPL in the COPYING file accompanying this sour #include "addi_common.h" #include "addi_amcc_s5933.h" +#ifndef ADDIDATA_DRIVER_NAME +#define ADDIDATA_DRIVER_NAME "addi_common" +#endif + /* Update-0.7.57->0.7.68MODULE_AUTHOR("ADDI-DATA GmbH <info@addi-data.com>"); */ /* Update-0.7.57->0.7.68MODULE_DESCRIPTION("Comedi ADDI-DATA module"); */ /* Update-0.7.57->0.7.68MODULE_LICENSE("GPL"); */ @@ -2528,7 +2532,7 @@ static const struct addi_board boardtypes[] = { #define n_boardtypes (sizeof(boardtypes)/sizeof(struct addi_board)) static struct comedi_driver driver_addi = { - .driver_name = "addi_common", + .driver_name = ADDIDATA_DRIVER_NAME, .module = THIS_MODULE, .attach = i_ADDI_Attach, .detach = i_ADDI_Detach, @@ -2570,10 +2574,6 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) struct pcilst_struct *card = NULL; unsigned char pci_bus, pci_slot, pci_func; int i_Dma = 0; - static char c_Identifier[150]; - - sprintf(c_Identifier, "Addi-Data GmbH Comedi %s", - this_board->pc_DriverName); ret = alloc_private(dev, sizeof(struct addi_private)); if (ret < 0) @@ -2583,7 +2583,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) v_pci_card_list_init(this_board->i_VendorId, 1); /* 1 for displaying the list.. */ pci_list_builded = 1; } - /* printk("comedi%d: addi_common: board=%s",dev->minor,this_board->pc_DriverName); */ + /* printk("comedi%d: "ADDIDATA_DRIVER_NAME": board=%s",dev->minor,this_board->pc_DriverName); */ if ((this_board->i_Dma) && (it->options[2] == 0)) { i_Dma = 1; @@ -2648,7 +2648,7 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) if (irq > 0) { if (request_irq(irq, v_ADDI_Interrupt, IRQF_SHARED, - c_Identifier, dev) < 0) { + this_board->pc_DriverName, dev) < 0) { printk(", unable to allocate IRQ %u, DISABLING IT", irq); irq = 0; /* Can't use IRQ */ diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c index da454e854c4c..6dfcbe803f2d 100644 --- a/drivers/staging/comedi/drivers/addi_apci_035.c +++ b/drivers/staging/comedi/drivers/addi_apci_035.c @@ -2,4 +2,6 @@ #define ADDIDATA_WATCHDOG 2 /* Or shold it be something else */ +#define ADDIDATA_DRIVER_NAME "addi_apci_035" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index fa2056e8aa0e..4722ec834f7b 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_1032 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_1032" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 7a5cae599ef8..db3dafdcf691 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_1500 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_1500" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c index 8d414844009f..f591baff6a0b 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1516.c +++ b/drivers/staging/comedi/drivers/addi_apci_1516.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_1516 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_1516" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c index 0351cdde1026..6f5c923ac226 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1564.c +++ b/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_1564 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_1564" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c index 506799041294..1d926add9e6d 100644 --- a/drivers/staging/comedi/drivers/addi_apci_16xx.c +++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_16XX 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_16xx" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c index c433445913dd..df6ba8ccf56f 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1710.c +++ b/drivers/staging/comedi/drivers/addi_apci_1710.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_1710 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_1710" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_2016.c b/drivers/staging/comedi/drivers/addi_apci_2016.c index 271c47c8cad3..7266e412f0a6 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2016.c +++ b/drivers/staging/comedi/drivers/addi_apci_2016.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_2016 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_2016" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c index 5108ea2a3924..f67da94119e8 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2032.c +++ b/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_2032 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_2032" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c index e439f835cf4f..bc7f7d653503 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2200.c +++ b/drivers/staging/comedi/drivers/addi_apci_2200.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_2200 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_2200" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_3001.c b/drivers/staging/comedi/drivers/addi_apci_3001.c index df97c305828b..d86c4209cb90 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3001.c +++ b/drivers/staging/comedi/drivers/addi_apci_3001.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_3001 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_3001" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index 9183125ddde4..0b22cf10415d 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_3120 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_3120" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c index f25a70b3290b..159313997dcf 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3200.c +++ b/drivers/staging/comedi/drivers/addi_apci_3200.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_3200 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_3200" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_3300.c b/drivers/staging/comedi/drivers/addi_apci_3300.c index 1ee4778ad45b..733c69abc43a 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3300.c +++ b/drivers/staging/comedi/drivers/addi_apci_3300.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_3300 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_3300" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index 1049e20237e8..d8a01b154e35 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_3501 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_3501" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c index fb9deb7083bd..942bc9e259a8 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -1,3 +1,5 @@ #define CONFIG_APCI_3XXX 1 +#define ADDIDATA_DRIVER_NAME "addi_apci_3xxx" + #include "addi-data/addi_common.c" diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 36a254cd4413..39d112b708e3 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -824,9 +824,12 @@ static int pci9111_ai_do_cmd(struct comedi_device *dev, plx9050_interrupt_control(dev_private->lcr_io_base, true, true, false, true, true); - dev_private->scan_delay = - (async_cmd->scan_begin_arg / (async_cmd->convert_arg * - async_cmd->chanlist_len)) - 1; + if (async_cmd->scan_begin_src == TRIG_TIMER) { + dev_private->scan_delay = + (async_cmd->scan_begin_arg / + (async_cmd->convert_arg * + async_cmd->chanlist_len)) - 1; + } break; diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index 40eeecf5347f..e424a0c7d34f 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -7,17 +7,17 @@ */ /* Driver: adv_pci_dio -Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1736UP, - PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754, - PCI-1756, PCI-1762 +Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U, + PCI-1736UP, PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, + PCI-1754, PCI-1756, PCI-1762 Author: Michal Dobes <dobes@tesnet.cz> Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733, - PCI-1734, PCI-1736UP, PCI-1750, + PCI-1734, PCI-1735U, PCI-1736UP, PCI-1750, PCI-1751, PCI-1752, PCI-1753, PCI-1753+PCI-1753E, PCI-1754, PCI-1756, PCI-1760, PCI-1762 Status: untested -Updated: Mon, 14 Apr 2008 10:43:08 +0100 +Updated: Tue, 04 May 2010 13:00:00 +0000 This driver supports now only insn interface for DI/DO/DIO. @@ -35,6 +35,7 @@ Configuration options: #include "comedi_pci.h" #include "8255.h" +#include "8253.h" #undef PCI_DIO_EXTDEBUG /* if defined, enable extensive debug logging */ @@ -49,7 +50,7 @@ Configuration options: /* hardware types of the cards */ enum hw_cards_id { - TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1736, + TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736, TYPE_PCI1750, TYPE_PCI1751, TYPE_PCI1752, @@ -67,7 +68,10 @@ enum hw_io_access { #define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */ #define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */ #define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per card */ +#define MAX_8254_SUBDEVS 1 /* max number of 8254 counter subdevs per card */ + /* (could be more than one 8254 per subdevice) */ +#define SIZE_8254 4 /* 8254 IO space length */ #define SIZE_8255 4 /* 8255 IO space length */ #define PCIDIO_MAINREG 2 /* main I/O region for all Advantech cards? */ @@ -85,6 +89,12 @@ enum hw_io_access { #define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */ #define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */ +/* Advantech PCI-1735U */ +#define PCI1735_DI 0 /* R: Digital input 0-31 */ +#define PCI1735_DO 0 /* W: Digital output 0-31 */ +#define PCI1735_C8254 4 /* R/W: 8254 counter */ +#define PCI1735_BOARDID 8 /* R: Board I/D switch for 1735U */ + /* Advantech PCI-1736UP */ #define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */ #define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */ @@ -192,7 +202,8 @@ static int pci_dio_detach(struct comedi_device *dev); struct diosubd_data { int chans; /* num of chans */ int addr; /* PCI address ofset */ - int regs; /* number of registers to read or 8255 subdevices */ + int regs; /* number of registers to read or 8255 + subdevices or 8254 chips */ unsigned int specflags; /* addon subdevice flags */ }; @@ -206,6 +217,7 @@ struct dio_boardtype { struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */ struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */ struct diosubd_data boardid; /* card supports board ID switch */ + struct diosubd_data s8254[MAX_8254_SUBDEVS]; /* 8254 subdevices */ enum hw_io_access io_access; }; @@ -214,6 +226,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci_dio_pci_table) = { PCI_VENDOR_ID_ADVANTECH, 0x1730, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_ADVANTECH, 0x1733, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_ADVANTECH, 0x1734, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { + PCI_VENDOR_ID_ADVANTECH, 0x1735, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_ADVANTECH, 0x1750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_ADVANTECH, 0x1751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { @@ -235,14 +248,15 @@ static const struct dio_boardtype boardtypes[] = { {{16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}}, {4, PCI173x_BOARDID, 1, SDF_INTERNAL}, - IO_8b, - }, + {{0, 0, 0, 0}}, + IO_8b}, {"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG, TYPE_PCI1733, {{0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}}, {4, PCI173x_BOARDID, 1, SDF_INTERNAL}, + {{0, 0, 0, 0}}, IO_8b}, {"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG, TYPE_PCI1734, @@ -250,6 +264,15 @@ static const struct dio_boardtype boardtypes[] = { {{0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}}, {4, PCI173x_BOARDID, 1, SDF_INTERNAL}, + {{0, 0, 0, 0}}, + IO_8b}, + {"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG, + TYPE_PCI1735, + {{32, PCI1735_DI, 4, 0}, {0, 0, 0, 0}}, + {{32, PCI1735_DO, 4, 0}, {0, 0, 0, 0}}, + {{0, 0, 0, 0}, {0, 0, 0, 0}}, + { 4, PCI1735_BOARDID, 1, SDF_INTERNAL}, + {{3, PCI1735_C8254, 1, 0}}, IO_8b}, {"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG, TYPE_PCI1736, @@ -257,14 +280,15 @@ static const struct dio_boardtype boardtypes[] = { {{0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}}, {4, PCI1736_BOARDID, 1, SDF_INTERNAL}, - IO_8b, - }, + {{0, 0, 0, 0}}, + IO_8b}, {"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG, TYPE_PCI1750, {{0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0}}, {{0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}}, {0, 0, 0, 0}, + {{0, 0, 0, 0}}, IO_8b}, {"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG, TYPE_PCI1751, @@ -272,6 +296,7 @@ static const struct dio_boardtype boardtypes[] = { {{0, 0, 0, 0}, {0, 0, 0, 0}}, {{48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0}}, {0, 0, 0, 0}, + {{0, 0, 0, 0}}, IO_8b}, {"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG, TYPE_PCI1752, @@ -279,6 +304,7 @@ static const struct dio_boardtype boardtypes[] = { {{32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}}, {4, PCI175x_BOARDID, 1, SDF_INTERNAL}, + {{0, 0, 0, 0}}, IO_16b}, {"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG, TYPE_PCI1753, @@ -286,6 +312,7 @@ static const struct dio_boardtype boardtypes[] = { {{0, 0, 0, 0}, {0, 0, 0, 0}}, {{96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0}}, {0, 0, 0, 0}, + {{0, 0, 0, 0}}, IO_8b}, {"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG, TYPE_PCI1753E, @@ -293,6 +320,7 @@ static const struct dio_boardtype boardtypes[] = { {{0, 0, 0, 0}, {0, 0, 0, 0}}, {{96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0}}, {0, 0, 0, 0}, + {{0, 0, 0, 0}}, IO_8b}, {"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG, TYPE_PCI1754, @@ -300,6 +328,7 @@ static const struct dio_boardtype boardtypes[] = { {{0, 0, 0, 0}, {0, 0, 0, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}}, {4, PCI175x_BOARDID, 1, SDF_INTERNAL}, + {{0, 0, 0, 0}}, IO_16b}, {"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG, TYPE_PCI1756, @@ -307,6 +336,7 @@ static const struct dio_boardtype boardtypes[] = { {{0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}}, {4, PCI175x_BOARDID, 1, SDF_INTERNAL}, + {{0, 0, 0, 0}}, IO_16b}, {"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0, TYPE_PCI1760, @@ -314,6 +344,7 @@ static const struct dio_boardtype boardtypes[] = { {{0, 0, 0, 0}, {0, 0, 0, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}}, {0, 0, 0, 0}, + {{0, 0, 0, 0}}, IO_8b}, {"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG, TYPE_PCI1762, @@ -321,6 +352,7 @@ static const struct dio_boardtype boardtypes[] = { {{0, 0, 0, 0}, {16, PCI1762_RO, 1, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}}, {4, PCI1762_BOARDID, 1, SDF_INTERNAL}, + {{0, 0, 0, 0}}, IO_16b} }; @@ -440,6 +472,83 @@ static int pci_dio_insn_bits_do_w(struct comedi_device *dev, /* ============================================================================== */ +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; +} + +/* +============================================================================== +*/ static int pci1760_unchecked_mbxrequest(struct comedi_device *dev, unsigned char *omb, unsigned char *imb, int repeats) @@ -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); @@ -877,6 +995,26 @@ static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s, /* ============================================================================== */ +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; +} + +/* +============================================================================== +*/ static int CheckAndAllocCard(struct comedi_device *dev, struct comedi_devconfig *it, struct pci_dev *pcidev) @@ -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; diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 8eb67651486a..bf27617aa62d 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -460,6 +460,7 @@ struct dio200_subdev_8254 { int has_clk_gat_sce; unsigned clock_src[3]; /* Current clock sources */ unsigned gate_src[3]; /* Current gate sources */ + spinlock_t spinlock; }; struct dio200_subdev_intr { @@ -1042,8 +1043,11 @@ dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s, { struct dio200_subdev_8254 *subpriv = s->private; int chan = CR_CHAN(insn->chanspec); + unsigned long flags; + spin_lock_irqsave(&subpriv->spinlock, flags); data[0] = i8254_read(subpriv->iobase, 0, chan); + spin_unlock_irqrestore(&subpriv->spinlock, flags); return 1; } @@ -1057,8 +1061,11 @@ dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s, { struct dio200_subdev_8254 *subpriv = s->private; int chan = CR_CHAN(insn->chanspec); + unsigned long flags; + spin_lock_irqsave(&subpriv->spinlock, flags); i8254_write(subpriv->iobase, 0, chan, data[0]); + spin_unlock_irqrestore(&subpriv->spinlock, flags); return 1; } @@ -1151,14 +1158,16 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { struct dio200_subdev_8254 *subpriv = s->private; - int ret; + int ret = 0; int chan = CR_CHAN(insn->chanspec); + unsigned long flags; + spin_lock_irqsave(&subpriv->spinlock, flags); switch (data[0]) { case INSN_CONFIG_SET_COUNTER_MODE: ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]); if (ret < 0) - return -EINVAL; + ret = -EINVAL; break; case INSN_CONFIG_8254_READ_STATUS: data[1] = i8254_status(subpriv->iobase, 0, chan); @@ -1166,30 +1175,35 @@ dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s, case INSN_CONFIG_SET_GATE_SRC: ret = dio200_set_gate_src(subpriv, chan, data[2]); if (ret < 0) - return -EINVAL; + ret = -EINVAL; break; case INSN_CONFIG_GET_GATE_SRC: ret = dio200_get_gate_src(subpriv, chan); - if (ret < 0) - return -EINVAL; + if (ret < 0) { + ret = -EINVAL; + break; + } data[2] = ret; break; case INSN_CONFIG_SET_CLOCK_SRC: ret = dio200_set_clock_src(subpriv, chan, data[1]); if (ret < 0) - return -EINVAL; + ret = -EINVAL; break; case INSN_CONFIG_GET_CLOCK_SRC: ret = dio200_get_clock_src(subpriv, chan, &data[2]); - if (ret < 0) - return -EINVAL; + if (ret < 0) { + ret = -EINVAL; + break; + } data[1] = ret; break; default: - return -EINVAL; + ret = -EINVAL; break; } - return insn->n; + spin_unlock_irqrestore(&subpriv->spinlock, flags); + return ret < 0 ? ret : insn->n; } /* @@ -1222,6 +1236,7 @@ dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s, s->insn_write = dio200_subdev_8254_write; s->insn_config = dio200_subdev_8254_config; + spin_lock_init(&subpriv->spinlock); subpriv->iobase = offset + iobase; subpriv->has_clk_gat_sce = has_clk_gat_sce; if (has_clk_gat_sce) { diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 81829d6fd287..c374bee25068 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -52,7 +52,6 @@ Please report success/failure with other different cards to #include "8255.h" #define PCI_VENDOR_ID_CB 0x1307 /* PCI vendor number of ComputerBoards */ -#define N_BOARDS 10 /* Number of boards in cb_pcidda_boards */ #define EEPROM_SIZE 128 /* number of entries in eeprom */ #define MAX_AO_CHANNELS 8 /* maximum number of ao channels for supported boards */ @@ -307,7 +306,7 @@ static int cb_pcidda_attach(struct comedi_device *dev, continue; } } - for (index = 0; index < N_BOARDS; index++) { + for (index = 0; index < ARRAY_SIZE(cb_pcidda_boards); index++) { if (cb_pcidda_boards[index].device_id == pcidev->device) { goto found; diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index cedb02d40f95..3a46f0c0bff9 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -123,7 +123,7 @@ static const struct ni_board_struct ni_boards[] = { .adbits = 12, .ai_fifo_depth = 1024, .alwaysdither = 0, - .gainlkup = ai_gain_16, + .gainlkup = ai_gain_4, .ai_speed = 5000, .n_aochan = 2, .aobits = 12, diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 86f035d00675..27b4cb2e2ec2 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -351,8 +351,7 @@ static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink) int ret = 0; if (!this_usbduxsub) { - dev_err(&this_usbduxsub->interface->dev, - "comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n"); + pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n"); return -EFAULT; } dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n"); diff --git a/drivers/staging/cx25821/Makefile b/drivers/staging/cx25821/Makefile index 10f87f05d8e8..d0eb16eac092 100644 --- a/drivers/staging/cx25821/Makefile +++ b/drivers/staging/cx25821/Makefile @@ -1,9 +1,8 @@ -cx25821-objs := cx25821-core.o cx25821-cards.o cx25821-i2c.o cx25821-gpio.o \ - cx25821-medusa-video.o cx25821-video.o cx25821-video0.o cx25821-video1.o \ - cx25821-video2.o cx25821-video3.o cx25821-video4.o cx25821-video5.o \ - cx25821-video6.o cx25821-video7.o cx25821-vidups9.o cx25821-vidups10.o \ - cx25821-audups11.o cx25821-video-upstream.o cx25821-video-upstream-ch2.o \ - cx25821-audio-upstream.o cx25821-videoioctl.o +cx25821-objs := cx25821-core.o cx25821-cards.o cx25821-i2c.o \ + cx25821-gpio.o cx25821-medusa-video.o \ + cx25821-video.o cx25821-video-upstream.o \ + cx25821-video-upstream-ch2.o \ + cx25821-audio-upstream.o obj-$(CONFIG_VIDEO_CX25821) += cx25821.o obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o diff --git a/drivers/staging/cx25821/cx25821-alsa.c b/drivers/staging/cx25821/cx25821-alsa.c index 1798975a69bd..a43b18816fa5 100644 --- a/drivers/staging/cx25821/cx25821-alsa.c +++ b/drivers/staging/cx25821/cx25821-alsa.c @@ -55,6 +55,12 @@ static struct snd_card *snd_cx25821_cards[SNDRV_CARDS]; static int devno; +struct cx25821_audio_buffer { + unsigned int bpl; + struct btcx_riscmem risc; + struct videobuf_dmabuf dma; +}; + struct cx25821_audio_dev { struct cx25821_dev *dev; struct cx25821_dmaqueue q; @@ -77,7 +83,7 @@ struct cx25821_audio_dev { struct videobuf_dmabuf *dma_risc; - struct cx25821_buffer *buf; + struct cx25821_audio_buffer *buf; struct snd_pcm_substream *substream; }; @@ -136,7 +142,7 @@ MODULE_PARM_DESC(debug, "enable debug messages"); static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip) { - struct cx25821_buffer *buf = chip->buf; + struct cx25821_audio_buffer *buf = chip->buf; struct cx25821_dev *dev = chip->dev; struct sram_channel *audio_ch = &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]; @@ -331,7 +337,7 @@ static int dsp_buffer_free(struct cx25821_audio_dev *chip) BUG_ON(!chip->dma_size); dprintk(2, "Freeing buffer\n"); - videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc); + videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc); videobuf_dma_free(chip->dma_risc); btcx_riscmem_free(chip->pci, &chip->buf->risc); kfree(chip->buf); @@ -432,7 +438,7 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream); struct videobuf_dmabuf *dma; - struct cx25821_buffer *buf; + struct cx25821_audio_buffer *buf; int ret; if (substream->runtime->dma_area) { @@ -447,36 +453,31 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, BUG_ON(!chip->dma_size); BUG_ON(chip->num_periods & (chip->num_periods - 1)); - buf = videobuf_sg_alloc(sizeof(*buf)); + buf = kzalloc(sizeof(*buf), GFP_KERNEL); if (NULL == buf) return -ENOMEM; if (chip->period_size > AUDIO_LINE_SIZE) chip->period_size = AUDIO_LINE_SIZE; - buf->vb.memory = V4L2_MEMORY_MMAP; - buf->vb.field = V4L2_FIELD_NONE; - buf->vb.width = chip->period_size; buf->bpl = chip->period_size; - buf->vb.height = chip->num_periods; - buf->vb.size = chip->dma_size; - dma = videobuf_to_dma(&buf->vb); + dma = &buf->dma; videobuf_dma_init(dma); - ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, - (PAGE_ALIGN(buf->vb.size) >> + (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); if (ret < 0) goto error; - ret = videobuf_sg_dma_map(&chip->pci->dev, dma); + ret = videobuf_dma_map(&chip->pci->dev, dma); if (ret < 0) goto error; ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist, - buf->vb.width, buf->vb.height, 1); + chip->period_size, chip->num_periods, + 1); if (ret < 0) { printk(KERN_INFO "DEBUG: ERROR after cx25821_risc_databuffer_audio()\n"); @@ -488,12 +489,10 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - buf->vb.state = VIDEOBUF_PREPARED; - chip->buf = buf; chip->dma_risc = dma; - substream->runtime->dma_area = chip->dma_risc->vmalloc; + substream->runtime->dma_area = chip->dma_risc->vaddr; substream->runtime->dma_bytes = chip->dma_size; substream->runtime->dma_addr = 0; diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.c b/drivers/staging/cx25821/cx25821-audio-upstream.c index eb39d13f7d75..cdff49f409f2 100644 --- a/drivers/staging/cx25821/cx25821-audio-upstream.c +++ b/drivers/staging/cx25821/cx25821-audio-upstream.c @@ -106,7 +106,7 @@ static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev, { unsigned int line; struct sram_channel *sram_ch = - &dev->sram_channels[dev->_audio_upstream_channel_select]; + dev->channels[dev->_audio_upstream_channel_select].sram_channels; int offset = 0; /* scan lines */ @@ -217,7 +217,7 @@ void cx25821_free_memory_audio(struct cx25821_dev *dev) void cx25821_stop_upstream_audio(struct cx25821_dev *dev) { struct sram_channel *sram_ch = - &dev->sram_channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B]; + dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels; u32 tmp = 0; if (!dev->_audio_is_running) { @@ -287,14 +287,14 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, return PTR_ERR(myfile); } else { if (!(myfile->f_op)) { - printk("%s: File has no file operations registered!\n", + printk(KERN_ERR "%s: File has no file operations registered!\n", __func__); filp_close(myfile, NULL); return -EIO; } if (!myfile->f_op->read) { - printk("%s: File has no READ operations registered!\n", + printk(KERN_ERR "%s: File has no READ operations registered!\n", __func__); filp_close(myfile, NULL); return -EIO; @@ -353,8 +353,9 @@ static void cx25821_audioups_handler(struct work_struct *work) } cx25821_get_audio_data(dev, - &dev->sram_channels[dev-> - _audio_upstream_channel_select]); + dev->channels[dev-> + _audio_upstream_channel_select]. + sram_channels); } int cx25821_openfile_audio(struct cx25821_dev *dev, @@ -378,14 +379,14 @@ int cx25821_openfile_audio(struct cx25821_dev *dev, return PTR_ERR(myfile); } else { if (!(myfile->f_op)) { - printk("%s: File has no file operations registered!\n", + printk(KERN_ERR "%s: File has no file operations registered!\n", __func__); filp_close(myfile, NULL); return -EIO; } if (!myfile->f_op->read) { - printk("%s: File has no READ operations registered!\n", + printk(KERN_ERR "%s: File has no READ operations registered!\n", __func__); filp_close(myfile, NULL); return -EIO; @@ -505,7 +506,7 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, { int i = 0; u32 int_msk_tmp; - struct sram_channel *channel = &dev->sram_channels[chan_num]; + struct sram_channel *channel = dev->channels[chan_num].sram_channels; dma_addr_t risc_phys_jump_addr; __le32 *rp; @@ -569,15 +570,15 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, spin_unlock(&dev->slock); } else { if (status & FLD_AUD_SRC_OF) - printk("%s: Audio Received Overflow Error Interrupt!\n", + printk(KERN_WARNING "%s: Audio Received Overflow Error Interrupt!\n", __func__); if (status & FLD_AUD_SRC_SYNC) - printk("%s: Audio Received Sync Error Interrupt!\n", + printk(KERN_WARNING "%s: Audio Received Sync Error Interrupt!\n", __func__); if (status & FLD_AUD_SRC_OPC_ERR) - printk("%s: Audio Received OpCode Error Interrupt!\n", + printk(KERN_WARNING "%s: Audio Received OpCode Error Interrupt!\n", __func__); /* Read and write back the interrupt status register to clear @@ -586,7 +587,7 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, } if (dev->_audiofile_status == END_OF_FILE) { - printk("cx25821: EOF Channel Audio Framecount = %d\n", + printk(KERN_WARNING "cx25821: EOF Channel Audio Framecount = %d\n", dev->_audioframe_count); return -1; } @@ -607,7 +608,8 @@ static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) if (!dev) return -1; - sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select]; + sram_ch = dev->channels[dev->_audio_upstream_channel_select]. + sram_channels; msk_stat = cx_read(sram_ch->int_mstat); audio_status = cx_read(sram_ch->int_stat); @@ -644,8 +646,8 @@ static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, /* 10 millisecond timeout */ if (count++ > 1000) { - printk - ("cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n", + printk(KERN_ERR + "cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n", __func__); return; } @@ -726,12 +728,12 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) int str_length = 0; if (dev->_audio_is_running) { - printk("Audio Channel is still running so return!\n"); + printk(KERN_WARNING "Audio Channel is still running so return!\n"); return 0; } dev->_audio_upstream_channel_select = channel_select; - sram_ch = &dev->sram_channels[channel_select]; + sram_ch = dev->channels[channel_select].sram_channels; /* Work queue */ INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler); diff --git a/drivers/staging/cx25821/cx25821-audio.h b/drivers/staging/cx25821/cx25821-audio.h index 503f42f036a8..434b2a312a80 100644 --- a/drivers/staging/cx25821/cx25821-audio.h +++ b/drivers/staging/cx25821/cx25821-audio.h @@ -27,24 +27,25 @@ #define LINES_PER_BUFFER 15 #define AUDIO_LINE_SIZE 128 -//Number of buffer programs to use at once. +/* Number of buffer programs to use at once. */ #define NUMBER_OF_PROGRAMS 8 -//Max size of the RISC program for a buffer. - worst case is 2 writes per line -// Space is also added for the 4 no-op instructions added on the end. - +/* + Max size of the RISC program for a buffer. - worst case is 2 writes per line + Space is also added for the 4 no-op instructions added on the end. +*/ #ifndef USE_RISC_NOOP #define MAX_BUFFER_PROGRAM_SIZE \ (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE*4) #endif -// MAE 12 July 2005 Try to use NOOP RISC instruction instead +/* MAE 12 July 2005 Try to use NOOP RISC instruction instead */ #ifdef USE_RISC_NOOP #define MAX_BUFFER_PROGRAM_SIZE \ (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_NOOP_INSTRUCTION_SIZE*4) #endif -//Sizes of various instructions in bytes. Used when adding instructions. +/* Sizes of various instructions in bytes. Used when adding instructions. */ #define RISC_WRITE_INSTRUCTION_SIZE 12 #define RISC_JUMP_INSTRUCTION_SIZE 12 #define RISC_SKIP_INSTRUCTION_SIZE 4 diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c deleted file mode 100644 index e49ead982f39..000000000000 --- a/drivers/staging/cx25821/cx25821-audups11.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> - * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/slab.h> - -#include "cx25821-video.h" - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH11]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, - buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, - &dev->sram_channels[SRAM_CH11]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - dprintk(2, - "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb.i, buf->count, q->count); - } else { - prev = - list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width - && prev->vb.height == buf->vb.height - && prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, - "[%p/%d] buffer_queue - append to active, buf->count=%d\n", - buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, - buf->vb.i); - } - } - - if (list_empty(&q->active)) { - dprintk(2, "active queue empty!\n"); - } -} - -static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = cx25821_buffer_setup, - .buf_prepare = cx25821_buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = cx25821_buffer_release, -}; - -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx25821_dev *dev = video_drvdata(file); - struct cx25821_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - printk("open dev=%s type=%s\n", video_device_node_name(vdev), - v4l2_type_names[type]); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - - lock_kernel(); - - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = 10; - fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); - - v4l2_prio_open(&dev->prio, &fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; -} - -static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t * ppos) -{ - struct cx25821_fh *fh = file->private_data; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO11)) - return -EBUSY; - - return videobuf_read_one(&fh->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - - default: - BUG(); - return 0; - } -} - -static unsigned int video_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (cx25821_res_check(fh, RESOURCE_VIDEO11)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN | POLLRDNORM; - return 0; -} - -static int video_release(struct file *file) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - - //stop the risc engine and fifo - //cx_write(channel11->dma_ctl, 0); - - /* stop video capture */ - if (cx25821_res_check(fh, RESOURCE_VIDEO11)) { - videobuf_queue_cancel(&fh->vidq); - cx25821_res_free(dev, fh, RESOURCE_VIDEO11); - } - - if (fh->vidq.read_buf) { - cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } - - videobuf_mmap_free(&fh->vidq); - - v4l2_prio_close(&dev->prio, fh->prio); - - file->private_data = NULL; - kfree(fh); - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; - } - - if (unlikely(i != fh->type)) { - return -EINVAL; - } - - if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO11)))) { - return -EBUSY; - } - - return videobuf_streamon(get_queue(fh)); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = cx25821_get_resource(fh, RESOURCE_VIDEO11); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - cx25821_res_free(dev, fh, res); - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vidq.field = f->fmt.pix.field; - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, - fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - return 0; -} - -static long video_ioctl_upstream11(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - int command = 0; - struct upstream_user_struct *data_from_user; - - data_from_user = (struct upstream_user_struct *)arg; - - if (!data_from_user) { - printk - ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", - __func__); - return 0; - } - - command = data_from_user->command; - - if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO) { - return 0; - } - - dev->input_filename = data_from_user->input_filename; - dev->input_audiofilename = data_from_user->input_filename; - dev->vid_stdname = data_from_user->vid_stdname; - dev->pixel_format = data_from_user->pixel_format; - dev->channel_select = data_from_user->channel_select; - dev->command = data_from_user->command; - - switch (command) { - case UPSTREAM_START_AUDIO: - cx25821_start_upstream_audio(dev, data_from_user); - break; - - case UPSTREAM_STOP_AUDIO: - cx25821_stop_upstream_audio(dev); - break; - } - - return 0; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct cx25821_fh *fh = priv; - return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); -} - -static int vidioc_log_status(struct file *file, void *priv) -{ - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; - - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", - dev->name); - cx25821_call_all(dev, core, log_status); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", - dev->name); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev; - int err; - - if (fh) { - dev = fh->dev; - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - return 0; -} - -// exported stuff -static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = cx25821_video_mmap, - .ioctl = video_ioctl_upstream11, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = cx25821_vidioc_querycap, - .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = cx25821_vidioc_reqbufs, - .vidioc_querybuf = cx25821_vidioc_querybuf, - .vidioc_qbuf = cx25821_vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -#ifdef TUNER_FLAG - .vidioc_s_std = cx25821_vidioc_s_std, - .vidioc_querystd = cx25821_vidioc_querystd, -#endif - .vidioc_cropcap = cx25821_vidioc_cropcap, - .vidioc_s_crop = cx25821_vidioc_s_crop, - .vidioc_g_crop = cx25821_vidioc_g_crop, - .vidioc_enum_input = cx25821_vidioc_enum_input, - .vidioc_g_input = cx25821_vidioc_g_input, - .vidioc_s_input = cx25821_vidioc_s_input, - .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = cx25821_vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = cx25821_vidioc_g_priority, - .vidioc_s_priority = cx25821_vidioc_s_priority, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = cx25821_vidiocgmbuf, -#endif -#ifdef TUNER_FLAG - .vidioc_g_tuner = cx25821_vidioc_g_tuner, - .vidioc_s_tuner = cx25821_vidioc_s_tuner, - .vidioc_g_frequency = cx25821_vidioc_g_frequency, - .vidioc_s_frequency = cx25821_vidioc_s_frequency, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = cx25821_vidioc_g_register, - .vidioc_s_register = cx25821_vidioc_s_register, -#endif -}; - -struct video_device cx25821_video_template11 = { - .name = "cx25821-audioupstream", - .fops = &video_fops, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, -}; diff --git a/drivers/staging/cx25821/cx25821-core.c b/drivers/staging/cx25821/cx25821-core.c index d90abb383fc8..c487c19256b9 100644 --- a/drivers/staging/cx25821/cx25821-core.c +++ b/drivers/staging/cx25821/cx25821-core.c @@ -781,14 +781,14 @@ static void cx25821_shutdown(struct cx25821_dev *dev) /* Disable Video A/B activity */ for (i = 0; i < VID_CHANNEL_NUM; i++) { - cx_write(dev->sram_channels[i].dma_ctl, 0); - cx_write(dev->sram_channels[i].int_msk, 0); + cx_write(dev->channels[i].sram_channels->dma_ctl, 0); + cx_write(dev->channels[i].sram_channels->int_msk, 0); } for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) { - cx_write(dev->sram_channels[i].dma_ctl, 0); - cx_write(dev->sram_channels[i].int_msk, 0); + cx_write(dev->channels[i].sram_channels->dma_ctl, 0); + cx_write(dev->channels[i].sram_channels->int_msk, 0); } /* Disable Audio activity */ @@ -805,12 +805,10 @@ static void cx25821_shutdown(struct cx25821_dev *dev) void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select, u32 format) { - struct sram_channel *ch; - if (channel_select <= 7 && channel_select >= 0) { - ch = &cx25821_sram_channels[channel_select]; - cx_write(ch->pix_frmt, format); - dev->pixel_formats[channel_select] = format; + cx_write(dev->channels[channel_select]. + sram_channels->pix_frmt, format); + dev->channels[channel_select].pixel_formats = format; } } @@ -831,7 +829,7 @@ static void cx25821_initialize(struct cx25821_dev *dev) cx_write(PCI_INT_STAT, 0xffffffff); for (i = 0; i < VID_CHANNEL_NUM; i++) - cx_write(dev->sram_channels[i].int_stat, 0xffffffff); + cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff); cx_write(AUD_A_INT_STAT, 0xffffffff); cx_write(AUD_B_INT_STAT, 0xffffffff); @@ -845,21 +843,22 @@ static void cx25821_initialize(struct cx25821_dev *dev) mdelay(100); for (i = 0; i < VID_CHANNEL_NUM; i++) { - cx25821_set_vip_mode(dev, &dev->sram_channels[i]); - cx25821_sram_channel_setup(dev, &dev->sram_channels[i], 1440, - 0); - dev->pixel_formats[i] = PIXEL_FRMT_422; - dev->use_cif_resolution[i] = FALSE; + cx25821_set_vip_mode(dev, dev->channels[i].sram_channels); + cx25821_sram_channel_setup(dev, dev->channels[i].sram_channels, + 1440, 0); + dev->channels[i].pixel_formats = PIXEL_FRMT_422; + dev->channels[i].use_cif_resolution = FALSE; } /* Probably only affect Downstream */ for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) { - cx25821_set_vip_mode(dev, &dev->sram_channels[i]); + cx25821_set_vip_mode(dev, dev->channels[i].sram_channels); } - cx25821_sram_channel_setup_audio(dev, &dev->sram_channels[SRAM_CH08], - 128, 0); + cx25821_sram_channel_setup_audio(dev, + dev->channels[SRAM_CH08].sram_channels, + 128, 0); cx25821_gpio_init(dev); } @@ -902,21 +901,6 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) { int io_size = 0, i; - struct video_device *video_template[] = { - &cx25821_video_template0, - &cx25821_video_template1, - &cx25821_video_template2, - &cx25821_video_template3, - &cx25821_video_template4, - &cx25821_video_template5, - &cx25821_video_template6, - &cx25821_video_template7, - &cx25821_video_template9, - &cx25821_video_template10, - &cx25821_video_template11, - &cx25821_videoioctl_template, - }; - printk(KERN_INFO "\n***********************************\n"); printk(KERN_INFO "cx25821 set up\n"); printk(KERN_INFO "***********************************\n\n"); @@ -947,7 +931,8 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) /* Apply a sensible clock frequency for the PCIe bridge */ dev->clk_freq = 28000000; - dev->sram_channels = cx25821_sram_channels; + for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) + dev->channels[i].sram_channels = &cx25821_sram_channels[i]; if (dev->nr > 1) CX25821_INFO("dev->nr > 1!"); @@ -970,7 +955,6 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) dev->i2c_bus[0].reg_wdata = I2C1_WDATA; dev->i2c_bus[0].i2c_period = (0x07 << 24); /* 1.95MHz */ - if (cx25821_get_resources(dev) < 0) { printk(KERN_ERR "%s No more PCIe resources for " "subsystem: %04x:%04x\n", @@ -1018,37 +1002,24 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) dev->i2c_bus[0].i2c_rc); cx25821_card_setup(dev); - medusa_video_init(dev); - for (i = 0; i < VID_CHANNEL_NUM; i++) { - if (cx25821_video_register(dev, i, video_template[i]) < 0) { - printk(KERN_ERR - "%s() Failed to register analog video adapters on VID channel %d\n", - __func__, i); - } - } + if (medusa_video_init(dev) < 0) + CX25821_ERR("%s() Failed to initialize medusa!\n" + , __func__); - for (i = VID_UPSTREAM_SRAM_CHANNEL_I; - i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) { - /* Since we don't have template8 for Audio Downstream */ - if (cx25821_video_register(dev, i, video_template[i - 1]) < 0) { - printk(KERN_ERR - "%s() Failed to register analog video adapters for Upstream channel %d.\n", - __func__, i); - } - } + cx25821_video_register(dev); /* register IOCTL device */ dev->ioctl_dev = - cx25821_vdev_init(dev, dev->pci, video_template[VIDEO_IOCTL_CH], + cx25821_vdev_init(dev, dev->pci, &cx25821_videoioctl_template, "video"); if (video_register_device (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) { cx25821_videoioctl_unregister(dev); printk(KERN_ERR - "%s() Failed to register video adapter for IOCTL so releasing.\n", - __func__); + "%s() Failed to register video adapter for IOCTL, so \ + unregistering videoioctl device.\n", __func__); } cx25821_dev_checkrevision(dev); @@ -1349,7 +1320,7 @@ void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf) BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb, 0, 0); - videobuf_dma_unmap(q, dma); + videobuf_dma_unmap(q->dev, dma); videobuf_dma_free(dma); btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); buf->vb.state = VIDEOBUF_NEEDS_INIT; @@ -1371,7 +1342,8 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id) for (i = 0; i < VID_CHANNEL_NUM; i++) { if (pci_status & mask[i]) { - vid_status = cx_read(dev->sram_channels[i].int_stat); + vid_status = cx_read(dev->channels[i]. + sram_channels->int_stat); if (vid_status) handled += diff --git a/drivers/staging/cx25821/cx25821-i2c.c b/drivers/staging/cx25821/cx25821-i2c.c index 08f45b52df6a..e43572e61ece 100644 --- a/drivers/staging/cx25821/cx25821-i2c.c +++ b/drivers/staging/cx25821/cx25821-i2c.c @@ -282,6 +282,9 @@ static u32 cx25821_functionality(struct i2c_adapter *adap) static struct i2c_algorithm cx25821_i2c_algo_template = { .master_xfer = i2c_xfer, .functionality = cx25821_functionality, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif }; static struct i2c_adapter cx25821_i2c_adap_template = { diff --git a/drivers/staging/cx25821/cx25821-medusa-defines.h b/drivers/staging/cx25821/cx25821-medusa-defines.h index b0d216ba7f81..60d197f57556 100644 --- a/drivers/staging/cx25821/cx25821-medusa-defines.h +++ b/drivers/staging/cx25821/cx25821-medusa-defines.h @@ -23,7 +23,7 @@ #ifndef _MEDUSA_DEF_H_ #define _MEDUSA_DEF_H_ -// Video deocder that we supported +/* Video deocder that we supported */ #define VDEC_A 0 #define VDEC_B 1 #define VDEC_C 2 @@ -33,19 +33,10 @@ #define VDEC_G 6 #define VDEC_H 7 -//#define AUTO_SWITCH_BIT[] = { 8, 9, 10, 11, 12, 13, 14, 15 }; - -// The following bit position enables automatic source switching for decoder A-H. -// Display index per camera. -//#define VDEC_INDEX[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7}; - -// Select input bit to video decoder A-H. -//#define CH_SRC_SEL_BIT[] = {24, 25, 26, 27, 28, 29, 30, 31}; - -// end of display sequence +/* end of display sequence */ #define END_OF_SEQ 0xF; -// registry string size +/* registry string size */ #define MAX_REGISTRY_SZ 40; #endif diff --git a/drivers/staging/cx25821/cx25821-medusa-reg.h b/drivers/staging/cx25821/cx25821-medusa-reg.h index 12c90f831b22..f7f33b3e7058 100644 --- a/drivers/staging/cx25821/cx25821-medusa-reg.h +++ b/drivers/staging/cx25821/cx25821-medusa-reg.h @@ -23,11 +23,11 @@ #ifndef __MEDUSA_REGISTERS__ #define __MEDUSA_REGISTERS__ -// Serial Slave Registers +/* Serial Slave Registers */ #define HOST_REGISTER1 0x0000 #define HOST_REGISTER2 0x0001 -// Chip Configuration Registers +/* Chip Configuration Registers */ #define CHIP_CTRL 0x0100 #define AFE_AB_CTRL 0x0104 #define AFE_CD_CTRL 0x0108 @@ -92,7 +92,7 @@ #define ABIST_CLAMP_E 0x01F4 #define ABIST_CLAMP_F 0x01F8 -// Digital Video Encoder A Registers +/* Digital Video Encoder A Registers */ #define DENC_A_REG_1 0x0200 #define DENC_A_REG_2 0x0204 #define DENC_A_REG_3 0x0208 @@ -102,7 +102,7 @@ #define DENC_A_REG_7 0x0218 #define DENC_A_REG_8 0x021C -// Digital Video Encoder B Registers +/* Digital Video Encoder B Registers */ #define DENC_B_REG_1 0x0300 #define DENC_B_REG_2 0x0304 #define DENC_B_REG_3 0x0308 @@ -112,7 +112,7 @@ #define DENC_B_REG_7 0x0318 #define DENC_B_REG_8 0x031C -// Video Decoder A Registers +/* Video Decoder A Registers */ #define MODE_CTRL 0x1000 #define OUT_CTRL1 0x1004 #define OUT_CTRL_NS 0x1008 @@ -153,7 +153,7 @@ #define VERSION 0x11F8 #define SOFT_RST_CTRL 0x11FC -// Video Decoder B Registers +/* Video Decoder B Registers */ #define VDEC_B_MODE_CTRL 0x1200 #define VDEC_B_OUT_CTRL1 0x1204 #define VDEC_B_OUT_CTRL_NS 0x1208 @@ -194,7 +194,7 @@ #define VDEC_B_VERSION 0x13F8 #define VDEC_B_SOFT_RST_CTRL 0x13FC -// Video Decoder C Registers +/* Video Decoder C Registers */ #define VDEC_C_MODE_CTRL 0x1400 #define VDEC_C_OUT_CTRL1 0x1404 #define VDEC_C_OUT_CTRL_NS 0x1408 @@ -235,7 +235,7 @@ #define VDEC_C_VERSION 0x15F8 #define VDEC_C_SOFT_RST_CTRL 0x15FC -// Video Decoder D Registers +/* Video Decoder D Registers */ #define VDEC_D_MODE_CTRL 0x1600 #define VDEC_D_OUT_CTRL1 0x1604 #define VDEC_D_OUT_CTRL_NS 0x1608 @@ -276,7 +276,7 @@ #define VDEC_D_VERSION 0x17F8 #define VDEC_D_SOFT_RST_CTRL 0x17FC -// Video Decoder E Registers +/* Video Decoder E Registers */ #define VDEC_E_MODE_CTRL 0x1800 #define VDEC_E_OUT_CTRL1 0x1804 #define VDEC_E_OUT_CTRL_NS 0x1808 @@ -317,7 +317,7 @@ #define VDEC_E_VERSION 0x19F8 #define VDEC_E_SOFT_RST_CTRL 0x19FC -// Video Decoder F Registers +/* Video Decoder F Registers */ #define VDEC_F_MODE_CTRL 0x1A00 #define VDEC_F_OUT_CTRL1 0x1A04 #define VDEC_F_OUT_CTRL_NS 0x1A08 @@ -358,7 +358,7 @@ #define VDEC_F_VERSION 0x1BF8 #define VDEC_F_SOFT_RST_CTRL 0x1BFC -// Video Decoder G Registers +/* Video Decoder G Registers */ #define VDEC_G_MODE_CTRL 0x1C00 #define VDEC_G_OUT_CTRL1 0x1C04 #define VDEC_G_OUT_CTRL_NS 0x1C08 @@ -399,7 +399,7 @@ #define VDEC_G_VERSION 0x1DF8 #define VDEC_G_SOFT_RST_CTRL 0x1DFC -// Video Decoder H Registers +/* Video Decoder H Registers */ #define VDEC_H_MODE_CTRL 0x1E00 #define VDEC_H_OUT_CTRL1 0x1E04 #define VDEC_H_OUT_CTRL_NS 0x1E08 @@ -440,14 +440,14 @@ #define VDEC_H_VERSION 0x1FF8 #define VDEC_H_SOFT_RST_CTRL 0x1FFC -//***************************************************************************** -// LUMA_CTRL register fields +/*****************************************************************************/ +/* LUMA_CTRL register fields */ #define VDEC_A_BRITE_CTRL 0x1014 #define VDEC_A_CNTRST_CTRL 0x1015 #define VDEC_A_PEAK_SEL 0x1016 -//***************************************************************************** -// CHROMA_CTRL register fields +/*****************************************************************************/ +/* CHROMA_CTRL register fields */ #define VDEC_A_USAT_CTRL 0x1018 #define VDEC_A_VSAT_CTRL 0x1019 #define VDEC_A_HUE_CTRL 0x101A diff --git a/drivers/staging/cx25821/cx25821-medusa-video.c b/drivers/staging/cx25821/cx25821-medusa-video.c index 34616dc507f9..ef9f2b82a860 100644 --- a/drivers/staging/cx25821/cx25821-medusa-video.c +++ b/drivers/staging/cx25821/cx25821-medusa-video.c @@ -778,9 +778,9 @@ int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) int medusa_video_init(struct cx25821_dev *dev) { - u32 value, tmp = 0; - int ret_val; - int i; + u32 value = 0, tmp = 0; + int ret_val = 0; + int i = 0; mutex_lock(&dev->lock); @@ -790,6 +790,7 @@ int medusa_video_init(struct cx25821_dev *dev) value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); value &= 0xFFFFF0FF; ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); + if (ret_val < 0) goto error; @@ -797,6 +798,7 @@ int medusa_video_init(struct cx25821_dev *dev) value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); value &= 0xFFFFFFDF; ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); + if (ret_val < 0) goto error; @@ -812,6 +814,7 @@ int medusa_video_init(struct cx25821_dev *dev) value &= 0xFF70FF70; value |= 0x00090008; /* set en_active */ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value); + if (ret_val < 0) goto error; @@ -826,8 +829,10 @@ int medusa_video_init(struct cx25821_dev *dev) /* select AFE clock to output mode */ value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); value &= 0x83FFFFFF; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, - value | 0x10000000); + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, + value | 0x10000000); + if (ret_val < 0) goto error; @@ -849,12 +854,15 @@ int medusa_video_init(struct cx25821_dev *dev) value |= 7; ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value); + if (ret_val < 0) goto error; + mutex_unlock(&dev->lock); ret_val = medusa_set_videostandard(dev); + return ret_val; error: diff --git a/drivers/staging/cx25821/cx25821-medusa-video.h b/drivers/staging/cx25821/cx25821-medusa-video.h index 2fab4b2f251c..6175e0961855 100644 --- a/drivers/staging/cx25821/cx25821-medusa-video.h +++ b/drivers/staging/cx25821/cx25821-medusa-video.h @@ -25,7 +25,7 @@ #include "cx25821-medusa-defines.h" -// Color control constants +/* Color control constants */ #define VIDEO_PROCAMP_MIN 0 #define VIDEO_PROCAMP_MAX 10000 #define UNSIGNED_BYTE_MIN 0 @@ -33,7 +33,7 @@ #define SIGNED_BYTE_MIN -128 #define SIGNED_BYTE_MAX 127 -// Default video color settings +/* Default video color settings */ #define SHARPNESS_DEFAULT 50 #define SATURATION_DEFAULT 5000 #define BRIGHTNESS_DEFAULT 6200 diff --git a/drivers/staging/cx25821/cx25821-reg.h b/drivers/staging/cx25821/cx25821-reg.h index 7241e7ee3fd3..cfe0f32db377 100644 --- a/drivers/staging/cx25821/cx25821-reg.h +++ b/drivers/staging/cx25821/cx25821-reg.h @@ -48,24 +48,24 @@ #define RISC_SYNC_EVEN_VBI 0x00000207 #define RISC_NOOP 0xF0000000 -//***************************************************************************** -// ASB SRAM -//***************************************************************************** -#define TX_SRAM 0x000000 // Transmit SRAM - -//***************************************************************************** -#define RX_RAM 0x010000 // Receive SRAM - -//***************************************************************************** -// Application Layer (AL) -//***************************************************************************** -#define DEV_CNTRL2 0x040000 // Device control +/***************************************************************************** +* ASB SRAM + *****************************************************************************/ +#define TX_SRAM 0x000000 /* Transmit SRAM */ + +/*****************************************************************************/ +#define RX_RAM 0x010000 /* Receive SRAM */ + +/***************************************************************************** +* Application Layer (AL) + *****************************************************************************/ +#define DEV_CNTRL2 0x040000 /* Device control */ #define FLD_RUN_RISC 0x00000020 -//***************************************************************************** -#define PCI_INT_MSK 0x040010 // PCI interrupt mask -#define PCI_INT_STAT 0x040014 // PCI interrupt status -#define PCI_INT_MSTAT 0x040018 // PCI interrupt masked status +/* ***************************************************************************** */ +#define PCI_INT_MSK 0x040010 /* PCI interrupt mask */ +#define PCI_INT_STAT 0x040014 /* PCI interrupt status */ +#define PCI_INT_MSTAT 0x040018 /* PCI interrupt masked status */ #define FLD_HAMMERHEAD_INT (1 << 27) #define FLD_UART_INT (1 << 26) #define FLD_IRQN_INT (1 << 25) @@ -93,65 +93,65 @@ #define FLD_VID_B_INT (1 << 1) #define FLD_VID_A_INT (1 << 0) -//***************************************************************************** -#define VID_A_INT_MSK 0x040020 // Video A interrupt mask -#define VID_A_INT_STAT 0x040024 // Video A interrupt status -#define VID_A_INT_MSTAT 0x040028 // Video A interrupt masked status -#define VID_A_INT_SSTAT 0x04002C // Video A interrupt set status - -//***************************************************************************** -#define VID_B_INT_MSK 0x040030 // Video B interrupt mask -#define VID_B_INT_STAT 0x040034 // Video B interrupt status -#define VID_B_INT_MSTAT 0x040038 // Video B interrupt masked status -#define VID_B_INT_SSTAT 0x04003C // Video B interrupt set status - -//***************************************************************************** -#define VID_C_INT_MSK 0x040040 // Video C interrupt mask -#define VID_C_INT_STAT 0x040044 // Video C interrupt status -#define VID_C_INT_MSTAT 0x040048 // Video C interrupt masked status -#define VID_C_INT_SSTAT 0x04004C // Video C interrupt set status - -//***************************************************************************** -#define VID_D_INT_MSK 0x040050 // Video D interrupt mask -#define VID_D_INT_STAT 0x040054 // Video D interrupt status -#define VID_D_INT_MSTAT 0x040058 // Video D interrupt masked status -#define VID_D_INT_SSTAT 0x04005C // Video D interrupt set status - -//***************************************************************************** -#define VID_E_INT_MSK 0x040060 // Video E interrupt mask -#define VID_E_INT_STAT 0x040064 // Video E interrupt status -#define VID_E_INT_MSTAT 0x040068 // Video E interrupt masked status -#define VID_E_INT_SSTAT 0x04006C // Video E interrupt set status - -//***************************************************************************** -#define VID_F_INT_MSK 0x040070 // Video F interrupt mask -#define VID_F_INT_STAT 0x040074 // Video F interrupt status -#define VID_F_INT_MSTAT 0x040078 // Video F interrupt masked status -#define VID_F_INT_SSTAT 0x04007C // Video F interrupt set status - -//***************************************************************************** -#define VID_G_INT_MSK 0x040080 // Video G interrupt mask -#define VID_G_INT_STAT 0x040084 // Video G interrupt status -#define VID_G_INT_MSTAT 0x040088 // Video G interrupt masked status -#define VID_G_INT_SSTAT 0x04008C // Video G interrupt set status - -//***************************************************************************** -#define VID_H_INT_MSK 0x040090 // Video H interrupt mask -#define VID_H_INT_STAT 0x040094 // Video H interrupt status -#define VID_H_INT_MSTAT 0x040098 // Video H interrupt masked status -#define VID_H_INT_SSTAT 0x04009C // Video H interrupt set status - -//***************************************************************************** -#define VID_I_INT_MSK 0x0400A0 // Video I interrupt mask -#define VID_I_INT_STAT 0x0400A4 // Video I interrupt status -#define VID_I_INT_MSTAT 0x0400A8 // Video I interrupt masked status -#define VID_I_INT_SSTAT 0x0400AC // Video I interrupt set status - -//***************************************************************************** -#define VID_J_INT_MSK 0x0400B0 // Video J interrupt mask -#define VID_J_INT_STAT 0x0400B4 // Video J interrupt status -#define VID_J_INT_MSTAT 0x0400B8 // Video J interrupt masked status -#define VID_J_INT_SSTAT 0x0400BC // Video J interrupt set status +/* ***************************************************************************** */ +#define VID_A_INT_MSK 0x040020 /* Video A interrupt mask */ +#define VID_A_INT_STAT 0x040024 /* Video A interrupt status */ +#define VID_A_INT_MSTAT 0x040028 /* Video A interrupt masked status */ +#define VID_A_INT_SSTAT 0x04002C /* Video A interrupt set status */ + +/* ***************************************************************************** */ +#define VID_B_INT_MSK 0x040030 /* Video B interrupt mask */ +#define VID_B_INT_STAT 0x040034 /* Video B interrupt status */ +#define VID_B_INT_MSTAT 0x040038 /* Video B interrupt masked status */ +#define VID_B_INT_SSTAT 0x04003C /* Video B interrupt set status */ + +/* ***************************************************************************** */ +#define VID_C_INT_MSK 0x040040 /* Video C interrupt mask */ +#define VID_C_INT_STAT 0x040044 /* Video C interrupt status */ +#define VID_C_INT_MSTAT 0x040048 /* Video C interrupt masked status */ +#define VID_C_INT_SSTAT 0x04004C /* Video C interrupt set status */ + +/* ***************************************************************************** */ +#define VID_D_INT_MSK 0x040050 /* Video D interrupt mask */ +#define VID_D_INT_STAT 0x040054 /* Video D interrupt status */ +#define VID_D_INT_MSTAT 0x040058 /* Video D interrupt masked status */ +#define VID_D_INT_SSTAT 0x04005C /* Video D interrupt set status */ + +/* ***************************************************************************** */ +#define VID_E_INT_MSK 0x040060 /* Video E interrupt mask */ +#define VID_E_INT_STAT 0x040064 /* Video E interrupt status */ +#define VID_E_INT_MSTAT 0x040068 /* Video E interrupt masked status */ +#define VID_E_INT_SSTAT 0x04006C /* Video E interrupt set status */ + +/* ***************************************************************************** */ +#define VID_F_INT_MSK 0x040070 /* Video F interrupt mask */ +#define VID_F_INT_STAT 0x040074 /* Video F interrupt status */ +#define VID_F_INT_MSTAT 0x040078 /* Video F interrupt masked status */ +#define VID_F_INT_SSTAT 0x04007C /* Video F interrupt set status */ + +/* ***************************************************************************** */ +#define VID_G_INT_MSK 0x040080 /* Video G interrupt mask */ +#define VID_G_INT_STAT 0x040084 /* Video G interrupt status */ +#define VID_G_INT_MSTAT 0x040088 /* Video G interrupt masked status */ +#define VID_G_INT_SSTAT 0x04008C /* Video G interrupt set status */ + +/* ***************************************************************************** */ +#define VID_H_INT_MSK 0x040090 /* Video H interrupt mask */ +#define VID_H_INT_STAT 0x040094 /* Video H interrupt status */ +#define VID_H_INT_MSTAT 0x040098 /* Video H interrupt masked status */ +#define VID_H_INT_SSTAT 0x04009C /* Video H interrupt set status */ + +/* ***************************************************************************** */ +#define VID_I_INT_MSK 0x0400A0 /* Video I interrupt mask */ +#define VID_I_INT_STAT 0x0400A4 /* Video I interrupt status */ +#define VID_I_INT_MSTAT 0x0400A8 /* Video I interrupt masked status */ +#define VID_I_INT_SSTAT 0x0400AC /* Video I interrupt set status */ + +/* ***************************************************************************** */ +#define VID_J_INT_MSK 0x0400B0 /* Video J interrupt mask */ +#define VID_J_INT_STAT 0x0400B4 /* Video J interrupt status */ +#define VID_J_INT_MSTAT 0x0400B8 /* Video J interrupt masked status */ +#define VID_J_INT_SSTAT 0x0400BC /* Video J interrupt set status */ #define FLD_VID_SRC_OPC_ERR 0x00020000 #define FLD_VID_DST_OPC_ERR 0x00010000 @@ -166,35 +166,35 @@ #define FLD_VID_SRC_ERRORS FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF #define FLD_VID_DST_ERRORS FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF -//***************************************************************************** -#define AUD_A_INT_MSK 0x0400C0 // Audio Int interrupt mask -#define AUD_A_INT_STAT 0x0400C4 // Audio Int interrupt status -#define AUD_A_INT_MSTAT 0x0400C8 // Audio Int interrupt masked status -#define AUD_A_INT_SSTAT 0x0400CC // Audio Int interrupt set status - -//***************************************************************************** -#define AUD_B_INT_MSK 0x0400D0 // Audio Int interrupt mask -#define AUD_B_INT_STAT 0x0400D4 // Audio Int interrupt status -#define AUD_B_INT_MSTAT 0x0400D8 // Audio Int interrupt masked status -#define AUD_B_INT_SSTAT 0x0400DC // Audio Int interrupt set status - -//***************************************************************************** -#define AUD_C_INT_MSK 0x0400E0 // Audio Int interrupt mask -#define AUD_C_INT_STAT 0x0400E4 // Audio Int interrupt status -#define AUD_C_INT_MSTAT 0x0400E8 // Audio Int interrupt masked status -#define AUD_C_INT_SSTAT 0x0400EC // Audio Int interrupt set status - -//***************************************************************************** -#define AUD_D_INT_MSK 0x0400F0 // Audio Int interrupt mask -#define AUD_D_INT_STAT 0x0400F4 // Audio Int interrupt status -#define AUD_D_INT_MSTAT 0x0400F8 // Audio Int interrupt masked status -#define AUD_D_INT_SSTAT 0x0400FC // Audio Int interrupt set status - -//***************************************************************************** -#define AUD_E_INT_MSK 0x040100 // Audio Int interrupt mask -#define AUD_E_INT_STAT 0x040104 // Audio Int interrupt status -#define AUD_E_INT_MSTAT 0x040108 // Audio Int interrupt masked status -#define AUD_E_INT_SSTAT 0x04010C // Audio Int interrupt set status +/* ***************************************************************************** */ +#define AUD_A_INT_MSK 0x0400C0 /* Audio Int interrupt mask */ +#define AUD_A_INT_STAT 0x0400C4 /* Audio Int interrupt status */ +#define AUD_A_INT_MSTAT 0x0400C8 /* Audio Int interrupt masked status */ +#define AUD_A_INT_SSTAT 0x0400CC /* Audio Int interrupt set status */ + +/* ***************************************************************************** */ +#define AUD_B_INT_MSK 0x0400D0 /* Audio Int interrupt mask */ +#define AUD_B_INT_STAT 0x0400D4 /* Audio Int interrupt status */ +#define AUD_B_INT_MSTAT 0x0400D8 /* Audio Int interrupt masked status */ +#define AUD_B_INT_SSTAT 0x0400DC /* Audio Int interrupt set status */ + +/* ***************************************************************************** */ +#define AUD_C_INT_MSK 0x0400E0 /* Audio Int interrupt mask */ +#define AUD_C_INT_STAT 0x0400E4 /* Audio Int interrupt status */ +#define AUD_C_INT_MSTAT 0x0400E8 /* Audio Int interrupt masked status */ +#define AUD_C_INT_SSTAT 0x0400EC /* Audio Int interrupt set status */ + +/* ***************************************************************************** */ +#define AUD_D_INT_MSK 0x0400F0 /* Audio Int interrupt mask */ +#define AUD_D_INT_STAT 0x0400F4 /* Audio Int interrupt status */ +#define AUD_D_INT_MSTAT 0x0400F8 /* Audio Int interrupt masked status */ +#define AUD_D_INT_SSTAT 0x0400FC /* Audio Int interrupt set status */ + +/* ***************************************************************************** */ +#define AUD_E_INT_MSK 0x040100 /* Audio Int interrupt mask */ +#define AUD_E_INT_STAT 0x040104 /* Audio Int interrupt status */ +#define AUD_E_INT_MSTAT 0x040108 /* Audio Int interrupt masked status */ +#define AUD_E_INT_SSTAT 0x04010C /* Audio Int interrupt set status */ #define FLD_AUD_SRC_OPC_ERR 0x00020000 #define FLD_AUD_DST_OPC_ERR 0x00010000 @@ -207,17 +207,17 @@ #define FLD_AUD_SRC_RISCI1 0x00000002 #define FLD_AUD_DST_RISCI1 0x00000001 -//***************************************************************************** -#define MBIF_A_INT_MSK 0x040110 // MBIF Int interrupt mask -#define MBIF_A_INT_STAT 0x040114 // MBIF Int interrupt status -#define MBIF_A_INT_MSTAT 0x040118 // MBIF Int interrupt masked status -#define MBIF_A_INT_SSTAT 0x04011C // MBIF Int interrupt set status +/* ***************************************************************************** */ +#define MBIF_A_INT_MSK 0x040110 /* MBIF Int interrupt mask */ +#define MBIF_A_INT_STAT 0x040114 /* MBIF Int interrupt status */ +#define MBIF_A_INT_MSTAT 0x040118 /* MBIF Int interrupt masked status */ +#define MBIF_A_INT_SSTAT 0x04011C /* MBIF Int interrupt set status */ -//***************************************************************************** -#define MBIF_B_INT_MSK 0x040120 // MBIF Int interrupt mask -#define MBIF_B_INT_STAT 0x040124 // MBIF Int interrupt status -#define MBIF_B_INT_MSTAT 0x040128 // MBIF Int interrupt masked status -#define MBIF_B_INT_SSTAT 0x04012C // MBIF Int interrupt set status +/* ***************************************************************************** */ +#define MBIF_B_INT_MSK 0x040120 /* MBIF Int interrupt mask */ +#define MBIF_B_INT_STAT 0x040124 /* MBIF Int interrupt status */ +#define MBIF_B_INT_MSTAT 0x040128 /* MBIF Int interrupt masked status */ +#define MBIF_B_INT_SSTAT 0x04012C /* MBIF Int interrupt set status */ #define FLD_MBIF_DST_OPC_ERR 0x00010000 #define FLD_MBIF_DST_SYNC 0x00001000 @@ -225,35 +225,35 @@ #define FLD_MBIF_DST_RISCI2 0x00000010 #define FLD_MBIF_DST_RISCI1 0x00000001 -//***************************************************************************** -#define AUD_EXT_INT_MSK 0x040060 // Audio Ext interrupt mask -#define AUD_EXT_INT_STAT 0x040064 // Audio Ext interrupt status -#define AUD_EXT_INT_MSTAT 0x040068 // Audio Ext interrupt masked status -#define AUD_EXT_INT_SSTAT 0x04006C // Audio Ext interrupt set status +/* ***************************************************************************** */ +#define AUD_EXT_INT_MSK 0x040060 /* Audio Ext interrupt mask */ +#define AUD_EXT_INT_STAT 0x040064 /* Audio Ext interrupt status */ +#define AUD_EXT_INT_MSTAT 0x040068 /* Audio Ext interrupt masked status */ +#define AUD_EXT_INT_SSTAT 0x04006C /* Audio Ext interrupt set status */ #define FLD_AUD_EXT_OPC_ERR 0x00010000 #define FLD_AUD_EXT_SYNC 0x00001000 #define FLD_AUD_EXT_OF 0x00000100 #define FLD_AUD_EXT_RISCI2 0x00000010 #define FLD_AUD_EXT_RISCI1 0x00000001 -//***************************************************************************** -#define GPIO_LO 0x110010 // Lower of GPIO pins [31:0] -#define GPIO_HI 0x110014 // Upper WORD of GPIO pins [47:31] +/* ***************************************************************************** */ +#define GPIO_LO 0x110010 /* Lower of GPIO pins [31:0] */ +#define GPIO_HI 0x110014 /* Upper WORD of GPIO pins [47:31] */ -#define GPIO_LO_OE 0x110018 // Lower of GPIO output enable [31:0] -#define GPIO_HI_OE 0x11001C // Upper word of GPIO output enable [47:32] +#define GPIO_LO_OE 0x110018 /* Lower of GPIO output enable [31:0] */ +#define GPIO_HI_OE 0x11001C /* Upper word of GPIO output enable [47:32] */ -#define GPIO_LO_INT_MSK 0x11003C // GPIO interrupt mask -#define GPIO_LO_INT_STAT 0x110044 // GPIO interrupt status -#define GPIO_LO_INT_MSTAT 0x11004C // GPIO interrupt masked status -#define GPIO_LO_ISM_SNS 0x110054 // GPIO interrupt sensitivity -#define GPIO_LO_ISM_POL 0x11005C // GPIO interrupt polarity +#define GPIO_LO_INT_MSK 0x11003C /* GPIO interrupt mask */ +#define GPIO_LO_INT_STAT 0x110044 /* GPIO interrupt status */ +#define GPIO_LO_INT_MSTAT 0x11004C /* GPIO interrupt masked status */ +#define GPIO_LO_ISM_SNS 0x110054 /* GPIO interrupt sensitivity */ +#define GPIO_LO_ISM_POL 0x11005C /* GPIO interrupt polarity */ -#define GPIO_HI_INT_MSK 0x110040 // GPIO interrupt mask -#define GPIO_HI_INT_STAT 0x110048 // GPIO interrupt status -#define GPIO_HI_INT_MSTAT 0x110050 // GPIO interrupt masked status -#define GPIO_HI_ISM_SNS 0x110058 // GPIO interrupt sensitivity -#define GPIO_HI_ISM_POL 0x110060 // GPIO interrupt polarity +#define GPIO_HI_INT_MSK 0x110040 /* GPIO interrupt mask */ +#define GPIO_HI_INT_STAT 0x110048 /* GPIO interrupt status */ +#define GPIO_HI_INT_MSTAT 0x110050 /* GPIO interrupt masked status */ +#define GPIO_HI_ISM_SNS 0x110058 /* GPIO interrupt sensitivity */ +#define GPIO_HI_ISM_POL 0x110060 /* GPIO interrupt polarity */ #define FLD_GPIO43_INT (1 << 11) #define FLD_GPIO42_INT (1 << 10) @@ -271,236 +271,236 @@ #define FLD_GPIO1_INT (1 << 1) #define FLD_GPIO0_INT (1 << 0) -//***************************************************************************** -#define TC_REQ 0x040090 // Rider PCI Express traFFic class request +/* ***************************************************************************** */ +#define TC_REQ 0x040090 /* Rider PCI Express traFFic class request */ -//***************************************************************************** -#define TC_REQ_SET 0x040094 // Rider PCI Express traFFic class request set +/* ***************************************************************************** */ +#define TC_REQ_SET 0x040094 /* Rider PCI Express traFFic class request set */ -//***************************************************************************** -// Rider -//***************************************************************************** +/* ***************************************************************************** */ +/* Rider */ +/* ***************************************************************************** */ -// PCI Compatible Header -//***************************************************************************** +/* PCI Compatible Header */ +/* ***************************************************************************** */ #define RDR_CFG0 0x050000 #define RDR_VENDOR_DEVICE_ID_CFG 0x050000 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFG1 0x050004 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFG2 0x050008 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFG3 0x05000C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFG4 0x050010 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFG5 0x050014 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFG6 0x050018 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFG7 0x05001C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFG8 0x050020 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFG9 0x050024 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFGA 0x050028 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFGB 0x05002C #define RDR_SUSSYSTEM_ID_CFG 0x05002C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFGC 0x050030 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFGD 0x050034 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFGE 0x050038 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_CFGF 0x05003C -//***************************************************************************** -// PCI-Express Capabilities -//***************************************************************************** +/* ***************************************************************************** */ +/* PCI-Express Capabilities */ +/* ***************************************************************************** */ #define RDR_PECAP 0x050040 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_PEDEVCAP 0x050044 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_PEDEVSC 0x050048 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_PELINKCAP 0x05004C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_PELINKSC 0x050050 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_PMICAP 0x050080 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_PMCSR 0x050084 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VPDCAP 0x050090 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VPDDATA 0x050094 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_MSICAP 0x0500A0 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_MSIARL 0x0500A4 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_MSIARU 0x0500A8 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_MSIDATA 0x0500AC -//***************************************************************************** -// PCI Express Extended Capabilities -//***************************************************************************** +/* ***************************************************************************** */ +/* PCI Express Extended Capabilities */ +/* ***************************************************************************** */ #define RDR_AERXCAP 0x050100 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_AERUESTA 0x050104 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_AERUEMSK 0x050108 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_AERUESEV 0x05010C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_AERCESTA 0x050110 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_AERCEMSK 0x050114 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_AERCC 0x050118 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_AERHL0 0x05011C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_AERHL1 0x050120 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_AERHL2 0x050124 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_AERHL3 0x050128 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCXCAP 0x050200 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCCAP1 0x050204 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCCAP2 0x050208 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCSC 0x05020C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR0_CAP 0x050210 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR0_CTRL 0x050214 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR0_STAT 0x050218 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR1_CAP 0x05021C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR1_CTRL 0x050220 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR1_STAT 0x050224 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR2_CAP 0x050228 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR2_CTRL 0x05022C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR2_STAT 0x050230 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR3_CAP 0x050234 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR3_CTRL 0x050238 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR3_STAT 0x05023C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCARB0 0x050240 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCARB1 0x050244 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCARB2 0x050248 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCARB3 0x05024C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCARB4 0x050250 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCARB5 0x050254 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCARB6 0x050258 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCARB7 0x05025C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_RDRSTAT0 0x050300 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_RDRSTAT1 0x050304 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_RDRCTL0 0x050308 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_RDRCTL1 0x05030C -//***************************************************************************** -// Transaction Layer Registers -//***************************************************************************** +/* ***************************************************************************** */ +/* Transaction Layer Registers */ +/* ***************************************************************************** */ #define RDR_TLSTAT0 0x050310 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_TLSTAT1 0x050314 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_TLCTL0 0x050318 #define FLD_CFG_UR_CPL_MODE 0x00000040 #define FLD_CFG_CORR_ERR_QUITE 0x00000020 @@ -510,569 +510,569 @@ #define FLD_CFG_RELAX_ORDER_MSK 0x00000002 #define FLD_CFG_TAG_ORDER_EN 0x00000001 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_TLCTL1 0x05031C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_REQRCAL 0x050320 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_REQRCAU 0x050324 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_REQEPA 0x050328 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_REQCTRL 0x05032C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_REQSTAT 0x050330 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_TL_TEST 0x050334 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR01_CTL 0x050348 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_VCR23_CTL 0x05034C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_RX_VCR0_FC 0x050350 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_RX_VCR1_FC 0x050354 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_RX_VCR2_FC 0x050358 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_RX_VCR3_FC 0x05035C -//***************************************************************************** -// Data Link Layer Registers -//***************************************************************************** +/* ***************************************************************************** */ +/* Data Link Layer Registers */ +/* ***************************************************************************** */ #define RDR_DLLSTAT 0x050360 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_DLLCTRL 0x050364 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_REPLAYTO 0x050368 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_ACKLATTO 0x05036C -//***************************************************************************** -// MAC Layer Registers -//***************************************************************************** +/* ***************************************************************************** */ +/* MAC Layer Registers */ +/* ***************************************************************************** */ #define RDR_MACSTAT0 0x050380 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_MACSTAT1 0x050384 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_MACCTRL0 0x050388 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_MACCTRL1 0x05038C -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_MACCTRL2 0x050390 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_MAC_LB_DATA 0x050394 -//***************************************************************************** +/* ***************************************************************************** */ #define RDR_L0S_EXIT_LAT 0x050398 -//***************************************************************************** -// DMAC -//***************************************************************************** -#define DMA1_PTR1 0x100000 // DMA Current Ptr : Ch#1 +/* ***************************************************************************** */ +/* DMAC */ +/* ***************************************************************************** */ +#define DMA1_PTR1 0x100000 /* DMA Current Ptr : Ch#1 */ -//***************************************************************************** -#define DMA2_PTR1 0x100004 // DMA Current Ptr : Ch#2 +/* ***************************************************************************** */ +#define DMA2_PTR1 0x100004 /* DMA Current Ptr : Ch#2 */ -//***************************************************************************** -#define DMA3_PTR1 0x100008 // DMA Current Ptr : Ch#3 +/* ***************************************************************************** */ +#define DMA3_PTR1 0x100008 /* DMA Current Ptr : Ch#3 */ -//***************************************************************************** -#define DMA4_PTR1 0x10000C // DMA Current Ptr : Ch#4 +/* ***************************************************************************** */ +#define DMA4_PTR1 0x10000C /* DMA Current Ptr : Ch#4 */ -//***************************************************************************** -#define DMA5_PTR1 0x100010 // DMA Current Ptr : Ch#5 +/* ***************************************************************************** */ +#define DMA5_PTR1 0x100010 /* DMA Current Ptr : Ch#5 */ -//***************************************************************************** -#define DMA6_PTR1 0x100014 // DMA Current Ptr : Ch#6 +/* ***************************************************************************** */ +#define DMA6_PTR1 0x100014 /* DMA Current Ptr : Ch#6 */ -//***************************************************************************** -#define DMA7_PTR1 0x100018 // DMA Current Ptr : Ch#7 +/* ***************************************************************************** */ +#define DMA7_PTR1 0x100018 /* DMA Current Ptr : Ch#7 */ -//***************************************************************************** -#define DMA8_PTR1 0x10001C // DMA Current Ptr : Ch#8 +/* ***************************************************************************** */ +#define DMA8_PTR1 0x10001C /* DMA Current Ptr : Ch#8 */ -//***************************************************************************** -#define DMA9_PTR1 0x100020 // DMA Current Ptr : Ch#9 +/* ***************************************************************************** */ +#define DMA9_PTR1 0x100020 /* DMA Current Ptr : Ch#9 */ -//***************************************************************************** -#define DMA10_PTR1 0x100024 // DMA Current Ptr : Ch#10 +/* ***************************************************************************** */ +#define DMA10_PTR1 0x100024 /* DMA Current Ptr : Ch#10 */ -//***************************************************************************** -#define DMA11_PTR1 0x100028 // DMA Current Ptr : Ch#11 +/* ***************************************************************************** */ +#define DMA11_PTR1 0x100028 /* DMA Current Ptr : Ch#11 */ -//***************************************************************************** -#define DMA12_PTR1 0x10002C // DMA Current Ptr : Ch#12 +/* ***************************************************************************** */ +#define DMA12_PTR1 0x10002C /* DMA Current Ptr : Ch#12 */ -//***************************************************************************** -#define DMA13_PTR1 0x100030 // DMA Current Ptr : Ch#13 +/* ***************************************************************************** */ +#define DMA13_PTR1 0x100030 /* DMA Current Ptr : Ch#13 */ -//***************************************************************************** -#define DMA14_PTR1 0x100034 // DMA Current Ptr : Ch#14 +/* ***************************************************************************** */ +#define DMA14_PTR1 0x100034 /* DMA Current Ptr : Ch#14 */ -//***************************************************************************** -#define DMA15_PTR1 0x100038 // DMA Current Ptr : Ch#15 +/* ***************************************************************************** */ +#define DMA15_PTR1 0x100038 /* DMA Current Ptr : Ch#15 */ -//***************************************************************************** -#define DMA16_PTR1 0x10003C // DMA Current Ptr : Ch#16 +/* ***************************************************************************** */ +#define DMA16_PTR1 0x10003C /* DMA Current Ptr : Ch#16 */ -//***************************************************************************** -#define DMA17_PTR1 0x100040 // DMA Current Ptr : Ch#17 +/* ***************************************************************************** */ +#define DMA17_PTR1 0x100040 /* DMA Current Ptr : Ch#17 */ -//***************************************************************************** -#define DMA18_PTR1 0x100044 // DMA Current Ptr : Ch#18 +/* ***************************************************************************** */ +#define DMA18_PTR1 0x100044 /* DMA Current Ptr : Ch#18 */ -//***************************************************************************** -#define DMA19_PTR1 0x100048 // DMA Current Ptr : Ch#19 +/* ***************************************************************************** */ +#define DMA19_PTR1 0x100048 /* DMA Current Ptr : Ch#19 */ -//***************************************************************************** -#define DMA20_PTR1 0x10004C // DMA Current Ptr : Ch#20 +/* ***************************************************************************** */ +#define DMA20_PTR1 0x10004C /* DMA Current Ptr : Ch#20 */ -//***************************************************************************** -#define DMA21_PTR1 0x100050 // DMA Current Ptr : Ch#21 +/* ***************************************************************************** */ +#define DMA21_PTR1 0x100050 /* DMA Current Ptr : Ch#21 */ -//***************************************************************************** -#define DMA22_PTR1 0x100054 // DMA Current Ptr : Ch#22 +/* ***************************************************************************** */ +#define DMA22_PTR1 0x100054 /* DMA Current Ptr : Ch#22 */ -//***************************************************************************** -#define DMA23_PTR1 0x100058 // DMA Current Ptr : Ch#23 +/* ***************************************************************************** */ +#define DMA23_PTR1 0x100058 /* DMA Current Ptr : Ch#23 */ -//***************************************************************************** -#define DMA24_PTR1 0x10005C // DMA Current Ptr : Ch#24 +/* ***************************************************************************** */ +#define DMA24_PTR1 0x10005C /* DMA Current Ptr : Ch#24 */ -//***************************************************************************** -#define DMA25_PTR1 0x100060 // DMA Current Ptr : Ch#25 +/* ***************************************************************************** */ +#define DMA25_PTR1 0x100060 /* DMA Current Ptr : Ch#25 */ -//***************************************************************************** -#define DMA26_PTR1 0x100064 // DMA Current Ptr : Ch#26 +/* ***************************************************************************** */ +#define DMA26_PTR1 0x100064 /* DMA Current Ptr : Ch#26 */ -//***************************************************************************** -#define DMA1_PTR2 0x100080 // DMA Tab Ptr : Ch#1 +/* ***************************************************************************** */ +#define DMA1_PTR2 0x100080 /* DMA Tab Ptr : Ch#1 */ -//***************************************************************************** -#define DMA2_PTR2 0x100084 // DMA Tab Ptr : Ch#2 +/* ***************************************************************************** */ +#define DMA2_PTR2 0x100084 /* DMA Tab Ptr : Ch#2 */ -//***************************************************************************** -#define DMA3_PTR2 0x100088 // DMA Tab Ptr : Ch#3 +/* ***************************************************************************** */ +#define DMA3_PTR2 0x100088 /* DMA Tab Ptr : Ch#3 */ -//***************************************************************************** -#define DMA4_PTR2 0x10008C // DMA Tab Ptr : Ch#4 +/* ***************************************************************************** */ +#define DMA4_PTR2 0x10008C /* DMA Tab Ptr : Ch#4 */ -//***************************************************************************** -#define DMA5_PTR2 0x100090 // DMA Tab Ptr : Ch#5 +/* ***************************************************************************** */ +#define DMA5_PTR2 0x100090 /* DMA Tab Ptr : Ch#5 */ -//***************************************************************************** -#define DMA6_PTR2 0x100094 // DMA Tab Ptr : Ch#6 +/* ***************************************************************************** */ +#define DMA6_PTR2 0x100094 /* DMA Tab Ptr : Ch#6 */ -//***************************************************************************** -#define DMA7_PTR2 0x100098 // DMA Tab Ptr : Ch#7 +/* ***************************************************************************** */ +#define DMA7_PTR2 0x100098 /* DMA Tab Ptr : Ch#7 */ -//***************************************************************************** -#define DMA8_PTR2 0x10009C // DMA Tab Ptr : Ch#8 +/* ***************************************************************************** */ +#define DMA8_PTR2 0x10009C /* DMA Tab Ptr : Ch#8 */ -//***************************************************************************** -#define DMA9_PTR2 0x1000A0 // DMA Tab Ptr : Ch#9 +/* ***************************************************************************** */ +#define DMA9_PTR2 0x1000A0 /* DMA Tab Ptr : Ch#9 */ -//***************************************************************************** -#define DMA10_PTR2 0x1000A4 // DMA Tab Ptr : Ch#10 +/* ***************************************************************************** */ +#define DMA10_PTR2 0x1000A4 /* DMA Tab Ptr : Ch#10 */ -//***************************************************************************** -#define DMA11_PTR2 0x1000A8 // DMA Tab Ptr : Ch#11 +/* ***************************************************************************** */ +#define DMA11_PTR2 0x1000A8 /* DMA Tab Ptr : Ch#11 */ -//***************************************************************************** -#define DMA12_PTR2 0x1000AC // DMA Tab Ptr : Ch#12 +/* ***************************************************************************** */ +#define DMA12_PTR2 0x1000AC /* DMA Tab Ptr : Ch#12 */ -//***************************************************************************** -#define DMA13_PTR2 0x1000B0 // DMA Tab Ptr : Ch#13 +/* ***************************************************************************** */ +#define DMA13_PTR2 0x1000B0 /* DMA Tab Ptr : Ch#13 */ -//***************************************************************************** -#define DMA14_PTR2 0x1000B4 // DMA Tab Ptr : Ch#14 +/* ***************************************************************************** */ +#define DMA14_PTR2 0x1000B4 /* DMA Tab Ptr : Ch#14 */ -//***************************************************************************** -#define DMA15_PTR2 0x1000B8 // DMA Tab Ptr : Ch#15 +/* ***************************************************************************** */ +#define DMA15_PTR2 0x1000B8 /* DMA Tab Ptr : Ch#15 */ -//***************************************************************************** -#define DMA16_PTR2 0x1000BC // DMA Tab Ptr : Ch#16 +/* ***************************************************************************** */ +#define DMA16_PTR2 0x1000BC /* DMA Tab Ptr : Ch#16 */ -//***************************************************************************** -#define DMA17_PTR2 0x1000C0 // DMA Tab Ptr : Ch#17 +/* ***************************************************************************** */ +#define DMA17_PTR2 0x1000C0 /* DMA Tab Ptr : Ch#17 */ -//***************************************************************************** -#define DMA18_PTR2 0x1000C4 // DMA Tab Ptr : Ch#18 +/* ***************************************************************************** */ +#define DMA18_PTR2 0x1000C4 /* DMA Tab Ptr : Ch#18 */ -//***************************************************************************** -#define DMA19_PTR2 0x1000C8 // DMA Tab Ptr : Ch#19 +/* ***************************************************************************** */ +#define DMA19_PTR2 0x1000C8 /* DMA Tab Ptr : Ch#19 */ -//***************************************************************************** -#define DMA20_PTR2 0x1000CC // DMA Tab Ptr : Ch#20 +/* ***************************************************************************** */ +#define DMA20_PTR2 0x1000CC /* DMA Tab Ptr : Ch#20 */ -//***************************************************************************** -#define DMA21_PTR2 0x1000D0 // DMA Tab Ptr : Ch#21 +/* ***************************************************************************** */ +#define DMA21_PTR2 0x1000D0 /* DMA Tab Ptr : Ch#21 */ -//***************************************************************************** -#define DMA22_PTR2 0x1000D4 // DMA Tab Ptr : Ch#22 +/* ***************************************************************************** */ +#define DMA22_PTR2 0x1000D4 /* DMA Tab Ptr : Ch#22 */ -//***************************************************************************** -#define DMA23_PTR2 0x1000D8 // DMA Tab Ptr : Ch#23 +/* ***************************************************************************** */ +#define DMA23_PTR2 0x1000D8 /* DMA Tab Ptr : Ch#23 */ -//***************************************************************************** -#define DMA24_PTR2 0x1000DC // DMA Tab Ptr : Ch#24 +/* ***************************************************************************** */ +#define DMA24_PTR2 0x1000DC /* DMA Tab Ptr : Ch#24 */ -//***************************************************************************** -#define DMA25_PTR2 0x1000E0 // DMA Tab Ptr : Ch#25 +/* ***************************************************************************** */ +#define DMA25_PTR2 0x1000E0 /* DMA Tab Ptr : Ch#25 */ -//***************************************************************************** -#define DMA26_PTR2 0x1000E4 // DMA Tab Ptr : Ch#26 +/* ***************************************************************************** */ +#define DMA26_PTR2 0x1000E4 /* DMA Tab Ptr : Ch#26 */ -//***************************************************************************** -#define DMA1_CNT1 0x100100 // DMA BuFFer Size : Ch#1 +/* ***************************************************************************** */ +#define DMA1_CNT1 0x100100 /* DMA BuFFer Size : Ch#1 */ -//***************************************************************************** -#define DMA2_CNT1 0x100104 // DMA BuFFer Size : Ch#2 +/* ***************************************************************************** */ +#define DMA2_CNT1 0x100104 /* DMA BuFFer Size : Ch#2 */ -//***************************************************************************** -#define DMA3_CNT1 0x100108 // DMA BuFFer Size : Ch#3 +/* ***************************************************************************** */ +#define DMA3_CNT1 0x100108 /* DMA BuFFer Size : Ch#3 */ -//***************************************************************************** -#define DMA4_CNT1 0x10010C // DMA BuFFer Size : Ch#4 +/* ***************************************************************************** */ +#define DMA4_CNT1 0x10010C /* DMA BuFFer Size : Ch#4 */ -//***************************************************************************** -#define DMA5_CNT1 0x100110 // DMA BuFFer Size : Ch#5 +/* ***************************************************************************** */ +#define DMA5_CNT1 0x100110 /* DMA BuFFer Size : Ch#5 */ -//***************************************************************************** -#define DMA6_CNT1 0x100114 // DMA BuFFer Size : Ch#6 +/* ***************************************************************************** */ +#define DMA6_CNT1 0x100114 /* DMA BuFFer Size : Ch#6 */ -//***************************************************************************** -#define DMA7_CNT1 0x100118 // DMA BuFFer Size : Ch#7 +/* ***************************************************************************** */ +#define DMA7_CNT1 0x100118 /* DMA BuFFer Size : Ch#7 */ -//***************************************************************************** -#define DMA8_CNT1 0x10011C // DMA BuFFer Size : Ch#8 +/* ***************************************************************************** */ +#define DMA8_CNT1 0x10011C /* DMA BuFFer Size : Ch#8 */ -//***************************************************************************** -#define DMA9_CNT1 0x100120 // DMA BuFFer Size : Ch#9 +/* ***************************************************************************** */ +#define DMA9_CNT1 0x100120 /* DMA BuFFer Size : Ch#9 */ -//***************************************************************************** -#define DMA10_CNT1 0x100124 // DMA BuFFer Size : Ch#10 +/* ***************************************************************************** */ +#define DMA10_CNT1 0x100124 /* DMA BuFFer Size : Ch#10 */ -//***************************************************************************** -#define DMA11_CNT1 0x100128 // DMA BuFFer Size : Ch#11 +/* ***************************************************************************** */ +#define DMA11_CNT1 0x100128 /* DMA BuFFer Size : Ch#11 */ -//***************************************************************************** -#define DMA12_CNT1 0x10012C // DMA BuFFer Size : Ch#12 +/* ***************************************************************************** */ +#define DMA12_CNT1 0x10012C /* DMA BuFFer Size : Ch#12 */ -//***************************************************************************** -#define DMA13_CNT1 0x100130 // DMA BuFFer Size : Ch#13 +/* ***************************************************************************** */ +#define DMA13_CNT1 0x100130 /* DMA BuFFer Size : Ch#13 */ -//***************************************************************************** -#define DMA14_CNT1 0x100134 // DMA BuFFer Size : Ch#14 +/* ***************************************************************************** */ +#define DMA14_CNT1 0x100134 /* DMA BuFFer Size : Ch#14 */ -//***************************************************************************** -#define DMA15_CNT1 0x100138 // DMA BuFFer Size : Ch#15 +/* ***************************************************************************** */ +#define DMA15_CNT1 0x100138 /* DMA BuFFer Size : Ch#15 */ -//***************************************************************************** -#define DMA16_CNT1 0x10013C // DMA BuFFer Size : Ch#16 +/* ***************************************************************************** */ +#define DMA16_CNT1 0x10013C /* DMA BuFFer Size : Ch#16 */ -//***************************************************************************** -#define DMA17_CNT1 0x100140 // DMA BuFFer Size : Ch#17 +/* ***************************************************************************** */ +#define DMA17_CNT1 0x100140 /* DMA BuFFer Size : Ch#17 */ -//***************************************************************************** -#define DMA18_CNT1 0x100144 // DMA BuFFer Size : Ch#18 +/* ***************************************************************************** */ +#define DMA18_CNT1 0x100144 /* DMA BuFFer Size : Ch#18 */ -//***************************************************************************** -#define DMA19_CNT1 0x100148 // DMA BuFFer Size : Ch#19 +/* ***************************************************************************** */ +#define DMA19_CNT1 0x100148 /* DMA BuFFer Size : Ch#19 */ -//***************************************************************************** -#define DMA20_CNT1 0x10014C // DMA BuFFer Size : Ch#20 +/* ***************************************************************************** */ +#define DMA20_CNT1 0x10014C /* DMA BuFFer Size : Ch#20 */ -//***************************************************************************** -#define DMA21_CNT1 0x100150 // DMA BuFFer Size : Ch#21 +/* ***************************************************************************** */ +#define DMA21_CNT1 0x100150 /* DMA BuFFer Size : Ch#21 */ -//***************************************************************************** -#define DMA22_CNT1 0x100154 // DMA BuFFer Size : Ch#22 +/* ***************************************************************************** */ +#define DMA22_CNT1 0x100154 /* DMA BuFFer Size : Ch#22 */ -//***************************************************************************** -#define DMA23_CNT1 0x100158 // DMA BuFFer Size : Ch#23 +/* ***************************************************************************** */ +#define DMA23_CNT1 0x100158 /* DMA BuFFer Size : Ch#23 */ -//***************************************************************************** -#define DMA24_CNT1 0x10015C // DMA BuFFer Size : Ch#24 +/* ***************************************************************************** */ +#define DMA24_CNT1 0x10015C /* DMA BuFFer Size : Ch#24 */ -//***************************************************************************** -#define DMA25_CNT1 0x100160 // DMA BuFFer Size : Ch#25 +/* ***************************************************************************** */ +#define DMA25_CNT1 0x100160 /* DMA BuFFer Size : Ch#25 */ -//***************************************************************************** -#define DMA26_CNT1 0x100164 // DMA BuFFer Size : Ch#26 +/* ***************************************************************************** */ +#define DMA26_CNT1 0x100164 /* DMA BuFFer Size : Ch#26 */ -//***************************************************************************** -#define DMA1_CNT2 0x100180 // DMA Table Size : Ch#1 +/* ***************************************************************************** */ +#define DMA1_CNT2 0x100180 /* DMA Table Size : Ch#1 */ -//***************************************************************************** -#define DMA2_CNT2 0x100184 // DMA Table Size : Ch#2 +/* ***************************************************************************** */ +#define DMA2_CNT2 0x100184 /* DMA Table Size : Ch#2 */ -//***************************************************************************** -#define DMA3_CNT2 0x100188 // DMA Table Size : Ch#3 +/* ***************************************************************************** */ +#define DMA3_CNT2 0x100188 /* DMA Table Size : Ch#3 */ -//***************************************************************************** -#define DMA4_CNT2 0x10018C // DMA Table Size : Ch#4 +/* ***************************************************************************** */ +#define DMA4_CNT2 0x10018C /* DMA Table Size : Ch#4 */ -//***************************************************************************** -#define DMA5_CNT2 0x100190 // DMA Table Size : Ch#5 +/* ***************************************************************************** */ +#define DMA5_CNT2 0x100190 /* DMA Table Size : Ch#5 */ -//***************************************************************************** -#define DMA6_CNT2 0x100194 // DMA Table Size : Ch#6 +/* ***************************************************************************** */ +#define DMA6_CNT2 0x100194 /* DMA Table Size : Ch#6 */ -//***************************************************************************** -#define DMA7_CNT2 0x100198 // DMA Table Size : Ch#7 +/* ***************************************************************************** */ +#define DMA7_CNT2 0x100198 /* DMA Table Size : Ch#7 */ -//***************************************************************************** -#define DMA8_CNT2 0x10019C // DMA Table Size : Ch#8 +/* ***************************************************************************** */ +#define DMA8_CNT2 0x10019C /* DMA Table Size : Ch#8 */ -//***************************************************************************** -#define DMA9_CNT2 0x1001A0 // DMA Table Size : Ch#9 +/* ***************************************************************************** */ +#define DMA9_CNT2 0x1001A0 /* DMA Table Size : Ch#9 */ -//***************************************************************************** -#define DMA10_CNT2 0x1001A4 // DMA Table Size : Ch#10 +/* ***************************************************************************** */ +#define DMA10_CNT2 0x1001A4 /* DMA Table Size : Ch#10 */ -//***************************************************************************** -#define DMA11_CNT2 0x1001A8 // DMA Table Size : Ch#11 +/* ***************************************************************************** */ +#define DMA11_CNT2 0x1001A8 /* DMA Table Size : Ch#11 */ -//***************************************************************************** -#define DMA12_CNT2 0x1001AC // DMA Table Size : Ch#12 +/* ***************************************************************************** */ +#define DMA12_CNT2 0x1001AC /* DMA Table Size : Ch#12 */ -//***************************************************************************** -#define DMA13_CNT2 0x1001B0 // DMA Table Size : Ch#13 +/* ***************************************************************************** */ +#define DMA13_CNT2 0x1001B0 /* DMA Table Size : Ch#13 */ -//***************************************************************************** -#define DMA14_CNT2 0x1001B4 // DMA Table Size : Ch#14 +/* ***************************************************************************** */ +#define DMA14_CNT2 0x1001B4 /* DMA Table Size : Ch#14 */ -//***************************************************************************** -#define DMA15_CNT2 0x1001B8 // DMA Table Size : Ch#15 +/* ***************************************************************************** */ +#define DMA15_CNT2 0x1001B8 /* DMA Table Size : Ch#15 */ -//***************************************************************************** -#define DMA16_CNT2 0x1001BC // DMA Table Size : Ch#16 +/* ***************************************************************************** */ +#define DMA16_CNT2 0x1001BC /* DMA Table Size : Ch#16 */ -//***************************************************************************** -#define DMA17_CNT2 0x1001C0 // DMA Table Size : Ch#17 +/* ***************************************************************************** */ +#define DMA17_CNT2 0x1001C0 /* DMA Table Size : Ch#17 */ -//***************************************************************************** -#define DMA18_CNT2 0x1001C4 // DMA Table Size : Ch#18 +/* ***************************************************************************** */ +#define DMA18_CNT2 0x1001C4 /* DMA Table Size : Ch#18 */ -//***************************************************************************** -#define DMA19_CNT2 0x1001C8 // DMA Table Size : Ch#19 +/* ***************************************************************************** */ +#define DMA19_CNT2 0x1001C8 /* DMA Table Size : Ch#19 */ -//***************************************************************************** -#define DMA20_CNT2 0x1001CC // DMA Table Size : Ch#20 +/* ***************************************************************************** */ +#define DMA20_CNT2 0x1001CC /* DMA Table Size : Ch#20 */ -//***************************************************************************** -#define DMA21_CNT2 0x1001D0 // DMA Table Size : Ch#21 +/* ***************************************************************************** */ +#define DMA21_CNT2 0x1001D0 /* DMA Table Size : Ch#21 */ -//***************************************************************************** -#define DMA22_CNT2 0x1001D4 // DMA Table Size : Ch#22 +/* ***************************************************************************** */ +#define DMA22_CNT2 0x1001D4 /* DMA Table Size : Ch#22 */ -//***************************************************************************** -#define DMA23_CNT2 0x1001D8 // DMA Table Size : Ch#23 +/* ***************************************************************************** */ +#define DMA23_CNT2 0x1001D8 /* DMA Table Size : Ch#23 */ -//***************************************************************************** -#define DMA24_CNT2 0x1001DC // DMA Table Size : Ch#24 +/* ***************************************************************************** */ +#define DMA24_CNT2 0x1001DC /* DMA Table Size : Ch#24 */ -//***************************************************************************** -#define DMA25_CNT2 0x1001E0 // DMA Table Size : Ch#25 +/* ***************************************************************************** */ +#define DMA25_CNT2 0x1001E0 /* DMA Table Size : Ch#25 */ -//***************************************************************************** -#define DMA26_CNT2 0x1001E4 // DMA Table Size : Ch#26 +/* ***************************************************************************** */ +#define DMA26_CNT2 0x1001E4 /* DMA Table Size : Ch#26 */ -//***************************************************************************** - // ITG -//***************************************************************************** -#define TM_CNT_LDW 0x110000 // Timer : Counter low +/* ***************************************************************************** */ + /* ITG */ +/* ***************************************************************************** */ +#define TM_CNT_LDW 0x110000 /* Timer : Counter low */ -//***************************************************************************** -#define TM_CNT_UW 0x110004 // Timer : Counter high word +/* ***************************************************************************** */ +#define TM_CNT_UW 0x110004 /* Timer : Counter high word */ -//***************************************************************************** -#define TM_LMT_LDW 0x110008 // Timer : Limit low +/* ***************************************************************************** */ +#define TM_LMT_LDW 0x110008 /* Timer : Limit low */ -//***************************************************************************** -#define TM_LMT_UW 0x11000C // Timer : Limit high word +/* ***************************************************************************** */ +#define TM_LMT_UW 0x11000C /* Timer : Limit high word */ -//***************************************************************************** -#define GP0_IO 0x110010 // GPIO output enables data I/O -#define FLD_GP_OE 0x00FF0000 // GPIO: GP_OE output enable -#define FLD_GP_IN 0x0000FF00 // GPIO: GP_IN status -#define FLD_GP_OUT 0x000000FF // GPIO: GP_OUT control +/* ***************************************************************************** */ +#define GP0_IO 0x110010 /* GPIO output enables data I/O */ +#define FLD_GP_OE 0x00FF0000 /* GPIO: GP_OE output enable */ +#define FLD_GP_IN 0x0000FF00 /* GPIO: GP_IN status */ +#define FLD_GP_OUT 0x000000FF /* GPIO: GP_OUT control */ -//***************************************************************************** -#define GPIO_ISM 0x110014 // GPIO interrupt sensitivity mode +/* ***************************************************************************** */ +#define GPIO_ISM 0x110014 /* GPIO interrupt sensitivity mode */ #define FLD_GP_ISM_SNS 0x00000070 #define FLD_GP_ISM_POL 0x00000007 -//***************************************************************************** -#define SOFT_RESET 0x11001C // Output system reset reg +/* ***************************************************************************** */ +#define SOFT_RESET 0x11001C /* Output system reset reg */ #define FLD_PECOS_SOFT_RESET 0x00000001 -//***************************************************************************** -#define MC416_RWD 0x110020 // MC416 GPIO[18:3] pin -#define MC416_OEN 0x110024 // Output enable of GPIO[18:3] +/* ***************************************************************************** */ +#define MC416_RWD 0x110020 /* MC416 GPIO[18:3] pin */ +#define MC416_OEN 0x110024 /* Output enable of GPIO[18:3] */ #define MC416_CTL 0x110028 -//***************************************************************************** -#define ALT_PIN_OUT_SEL 0x11002C // Alternate GPIO output select +/* ***************************************************************************** */ +#define ALT_PIN_OUT_SEL 0x11002C /* Alternate GPIO output select */ #define FLD_ALT_GPIO_OUT_SEL 0xF0000000 -// 0 Disabled <-- default -// 1 GPIO[0] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] -// 8 ATT_IF +/* 0 Disabled <-- default */ +/* 1 GPIO[0] */ +/* 2 GPIO[10] */ +/* 3 VIP_656_DATA_VAL */ +/* 4 VIP_656_DATA[0] */ +/* 5 VIP_656_CLK */ +/* 6 VIP_656_DATA_EXT[1] */ +/* 7 VIP_656_DATA_EXT[0] */ +/* 8 ATT_IF */ #define FLD_AUX_PLL_CLK_ALT_SEL 0x0F000000 -// 0 AUX_PLL_CLK<-- default -// 1 GPIO[2] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] +/* 0 AUX_PLL_CLK<-- default */ +/* 1 GPIO[2] */ +/* 2 GPIO[10] */ +/* 3 VIP_656_DATA_VAL */ +/* 4 VIP_656_DATA[0] */ +/* 5 VIP_656_CLK */ +/* 6 VIP_656_DATA_EXT[1] */ +/* 7 VIP_656_DATA_EXT[0] */ #define FLD_IR_TX_ALT_SEL 0x00F00000 -// 0 IR_TX <-- default -// 1 GPIO[1] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] +/* 0 IR_TX <-- default */ +/* 1 GPIO[1] */ +/* 2 GPIO[10] */ +/* 3 VIP_656_DATA_VAL */ +/* 4 VIP_656_DATA[0] */ +/* 5 VIP_656_CLK */ +/* 6 VIP_656_DATA_EXT[1] */ +/* 7 VIP_656_DATA_EXT[0] */ #define FLD_IR_RX_ALT_SEL 0x000F0000 -// 0 IR_RX <-- default -// 1 GPIO[0] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] +/* 0 IR_RX <-- default */ +/* 1 GPIO[0] */ +/* 2 GPIO[10] */ +/* 3 VIP_656_DATA_VAL */ +/* 4 VIP_656_DATA[0] */ +/* 5 VIP_656_CLK */ +/* 6 VIP_656_DATA_EXT[1] */ +/* 7 VIP_656_DATA_EXT[0] */ #define FLD_GPIO10_ALT_SEL 0x0000F000 -// 0 GPIO[10] <-- default -// 1 GPIO[0] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] +/* 0 GPIO[10] <-- default */ +/* 1 GPIO[0] */ +/* 2 GPIO[10] */ +/* 3 VIP_656_DATA_VAL */ +/* 4 VIP_656_DATA[0] */ +/* 5 VIP_656_CLK */ +/* 6 VIP_656_DATA_EXT[1] */ +/* 7 VIP_656_DATA_EXT[0] */ #define FLD_GPIO2_ALT_SEL 0x00000F00 -// 0 GPIO[2] <-- default -// 1 GPIO[1] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] +/* 0 GPIO[2] <-- default */ +/* 1 GPIO[1] */ +/* 2 GPIO[10] */ +/* 3 VIP_656_DATA_VAL */ +/* 4 VIP_656_DATA[0] */ +/* 5 VIP_656_CLK */ +/* 6 VIP_656_DATA_EXT[1] */ +/* 7 VIP_656_DATA_EXT[0] */ #define FLD_GPIO1_ALT_SEL 0x000000F0 -// 0 GPIO[1] <-- default -// 1 GPIO[0] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] +/* 0 GPIO[1] <-- default */ +/* 1 GPIO[0] */ +/* 2 GPIO[10] */ +/* 3 VIP_656_DATA_VAL */ +/* 4 VIP_656_DATA[0] */ +/* 5 VIP_656_CLK */ +/* 6 VIP_656_DATA_EXT[1] */ +/* 7 VIP_656_DATA_EXT[0] */ #define FLD_GPIO0_ALT_SEL 0x0000000F -// 0 GPIO[0] <-- default -// 1 GPIO[1] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] +/* 0 GPIO[0] <-- default */ +/* 1 GPIO[1] */ +/* 2 GPIO[10] */ +/* 3 VIP_656_DATA_VAL */ +/* 4 VIP_656_DATA[0] */ +/* 5 VIP_656_CLK */ +/* 6 VIP_656_DATA_EXT[1] */ +/* 7 VIP_656_DATA_EXT[0] */ -#define ALT_PIN_IN_SEL 0x110030 // Alternate GPIO input select +#define ALT_PIN_IN_SEL 0x110030 /* Alternate GPIO input select */ #define FLD_GPIO10_ALT_IN_SEL 0x0000F000 -// 0 GPIO[10] <-- default -// 1 IR_RX -// 2 IR_TX -// 3 AUX_PLL_CLK -// 4 IF_ATT_SEL -// 5 GPIO[0] -// 6 GPIO[1] -// 7 GPIO[2] +/* 0 GPIO[10] <-- default */ +/* 1 IR_RX */ +/* 2 IR_TX */ +/* 3 AUX_PLL_CLK */ +/* 4 IF_ATT_SEL */ +/* 5 GPIO[0] */ +/* 6 GPIO[1] */ +/* 7 GPIO[2] */ #define FLD_GPIO2_ALT_IN_SEL 0x00000F00 -// 0 GPIO[2] <-- default -// 1 IR_RX -// 2 IR_TX -// 3 AUX_PLL_CLK -// 4 IF_ATT_SEL +/* 0 GPIO[2] <-- default */ +/* 1 IR_RX */ +/* 2 IR_TX */ +/* 3 AUX_PLL_CLK */ +/* 4 IF_ATT_SEL */ #define FLD_GPIO1_ALT_IN_SEL 0x000000F0 -// 0 GPIO[1] <-- default -// 1 IR_RX -// 2 IR_TX -// 3 AUX_PLL_CLK -// 4 IF_ATT_SEL +/* 0 GPIO[1] <-- default */ +/* 1 IR_RX */ +/* 2 IR_TX */ +/* 3 AUX_PLL_CLK */ +/* 4 IF_ATT_SEL */ #define FLD_GPIO0_ALT_IN_SEL 0x0000000F -// 0 GPIO[0] <-- default -// 1 IR_RX -// 2 IR_TX -// 3 AUX_PLL_CLK -// 4 IF_ATT_SEL +/* 0 GPIO[0] <-- default */ +/* 1 IR_RX */ +/* 2 IR_TX */ +/* 3 AUX_PLL_CLK */ +/* 4 IF_ATT_SEL */ -//***************************************************************************** -#define TEST_BUS_CTL1 0x110040 // Test bus control register #1 +/* ***************************************************************************** */ +#define TEST_BUS_CTL1 0x110040 /* Test bus control register #1 */ -//***************************************************************************** -#define TEST_BUS_CTL2 0x110044 // Test bus control register #2 +/* ***************************************************************************** */ +#define TEST_BUS_CTL2 0x110044 /* Test bus control register #2 */ -//***************************************************************************** -#define CLK_DELAY 0x110048 // Clock delay -#define FLD_MOE_CLK_DIS 0x80000000 // Disable MoE clock +/* ***************************************************************************** */ +#define CLK_DELAY 0x110048 /* Clock delay */ +#define FLD_MOE_CLK_DIS 0x80000000 /* Disable MoE clock */ -//***************************************************************************** -#define PAD_CTRL 0x110068 // Pad drive strength control +/* ***************************************************************************** */ +#define PAD_CTRL 0x110068 /* Pad drive strength control */ -//***************************************************************************** -#define MBIST_CTRL 0x110050 // SRAM memory built-in self test control +/* ***************************************************************************** */ +#define MBIST_CTRL 0x110050 /* SRAM memory built-in self test control */ -//***************************************************************************** -#define MBIST_STAT 0x110054 // SRAM memory built-in self test status +/* ***************************************************************************** */ +#define MBIST_STAT 0x110054 /* SRAM memory built-in self test status */ -//***************************************************************************** -// PLL registers -//***************************************************************************** +/* ***************************************************************************** */ +/* PLL registers */ +/* ***************************************************************************** */ #define PLL_A_INT_FRAC 0x110088 #define PLL_A_POST_STAT_BIST 0x11008C #define PLL_B_INT_FRAC 0x110090 @@ -1090,260 +1090,260 @@ #define VID_CH_MODE_SEL 0x110078 #define VID_CH_CLK_SEL 0x11007C -//***************************************************************************** -#define VBI_A_DMA 0x130008 // VBI A DMA data port +/* ***************************************************************************** */ +#define VBI_A_DMA 0x130008 /* VBI A DMA data port */ -//***************************************************************************** -#define VID_A_VIP_CTL 0x130080 // Video A VIP format control +/* ***************************************************************************** */ +#define VID_A_VIP_CTL 0x130080 /* Video A VIP format control */ #define FLD_VIP_MODE 0x00000001 -//***************************************************************************** -#define VID_A_PIXEL_FRMT 0x130084 // Video A pixel format +/* ***************************************************************************** */ +#define VID_A_PIXEL_FRMT 0x130084 /* Video A pixel format */ #define FLD_VID_A_GAMMA_DIS 0x00000008 #define FLD_VID_A_FORMAT 0x00000007 #define FLD_VID_A_GAMMA_FACTOR 0x00000010 -//***************************************************************************** -#define VID_A_VBI_CTL 0x130088 // Video A VBI miscellaneous control +/* ***************************************************************************** */ +#define VID_A_VBI_CTL 0x130088 /* Video A VBI miscellaneous control */ #define FLD_VID_A_VIP_EXT 0x00000003 -//***************************************************************************** -#define VID_B_DMA 0x130100 // Video B DMA data port +/* ***************************************************************************** */ +#define VID_B_DMA 0x130100 /* Video B DMA data port */ -//***************************************************************************** -#define VBI_B_DMA 0x130108 // VBI B DMA data port +/* ***************************************************************************** */ +#define VBI_B_DMA 0x130108 /* VBI B DMA data port */ -//***************************************************************************** -#define VID_B_SRC_SEL 0x130144 // Video B source select +/* ***************************************************************************** */ +#define VID_B_SRC_SEL 0x130144 /* Video B source select */ #define FLD_VID_B_SRC_SEL 0x00000000 -//***************************************************************************** -#define VID_B_LNGTH 0x130150 // Video B line length +/* ***************************************************************************** */ +#define VID_B_LNGTH 0x130150 /* Video B line length */ #define FLD_VID_B_LN_LNGTH 0x00000FFF -//***************************************************************************** -#define VID_B_VIP_CTL 0x130180 // Video B VIP format control +/* ***************************************************************************** */ +#define VID_B_VIP_CTL 0x130180 /* Video B VIP format control */ -//***************************************************************************** -#define VID_B_PIXEL_FRMT 0x130184 // Video B pixel format +/* ***************************************************************************** */ +#define VID_B_PIXEL_FRMT 0x130184 /* Video B pixel format */ #define FLD_VID_B_GAMMA_DIS 0x00000008 #define FLD_VID_B_FORMAT 0x00000007 #define FLD_VID_B_GAMMA_FACTOR 0x00000010 -//***************************************************************************** -#define VID_C_DMA 0x130200 // Video C DMA data port +/* ***************************************************************************** */ +#define VID_C_DMA 0x130200 /* Video C DMA data port */ -//***************************************************************************** -#define VID_C_LNGTH 0x130250 // Video C line length +/* ***************************************************************************** */ +#define VID_C_LNGTH 0x130250 /* Video C line length */ #define FLD_VID_C_LN_LNGTH 0x00000FFF -//***************************************************************************** -// Video Destination Channels -//***************************************************************************** - -#define VID_DST_A_GPCNT 0x130020 // Video A general purpose counter -#define VID_DST_B_GPCNT 0x130120 // Video B general purpose counter -#define VID_DST_C_GPCNT 0x130220 // Video C general purpose counter -#define VID_DST_D_GPCNT 0x130320 // Video D general purpose counter -#define VID_DST_E_GPCNT 0x130420 // Video E general purpose counter -#define VID_DST_F_GPCNT 0x130520 // Video F general purpose counter -#define VID_DST_G_GPCNT 0x130620 // Video G general purpose counter -#define VID_DST_H_GPCNT 0x130720 // Video H general purpose counter - -//***************************************************************************** - -#define VID_DST_A_GPCNT_CTL 0x130030 // Video A general purpose control -#define VID_DST_B_GPCNT_CTL 0x130130 // Video B general purpose control -#define VID_DST_C_GPCNT_CTL 0x130230 // Video C general purpose control -#define VID_DST_D_GPCNT_CTL 0x130330 // Video D general purpose control -#define VID_DST_E_GPCNT_CTL 0x130430 // Video E general purpose control -#define VID_DST_F_GPCNT_CTL 0x130530 // Video F general purpose control -#define VID_DST_G_GPCNT_CTL 0x130630 // Video G general purpose control -#define VID_DST_H_GPCNT_CTL 0x130730 // Video H general purpose control - -//***************************************************************************** - -#define VID_DST_A_DMA_CTL 0x130040 // Video A DMA control -#define VID_DST_B_DMA_CTL 0x130140 // Video B DMA control -#define VID_DST_C_DMA_CTL 0x130240 // Video C DMA control -#define VID_DST_D_DMA_CTL 0x130340 // Video D DMA control -#define VID_DST_E_DMA_CTL 0x130440 // Video E DMA control -#define VID_DST_F_DMA_CTL 0x130540 // Video F DMA control -#define VID_DST_G_DMA_CTL 0x130640 // Video G DMA control -#define VID_DST_H_DMA_CTL 0x130740 // Video H DMA control +/* ***************************************************************************** */ +/* Video Destination Channels */ +/* ***************************************************************************** */ + +#define VID_DST_A_GPCNT 0x130020 /* Video A general purpose counter */ +#define VID_DST_B_GPCNT 0x130120 /* Video B general purpose counter */ +#define VID_DST_C_GPCNT 0x130220 /* Video C general purpose counter */ +#define VID_DST_D_GPCNT 0x130320 /* Video D general purpose counter */ +#define VID_DST_E_GPCNT 0x130420 /* Video E general purpose counter */ +#define VID_DST_F_GPCNT 0x130520 /* Video F general purpose counter */ +#define VID_DST_G_GPCNT 0x130620 /* Video G general purpose counter */ +#define VID_DST_H_GPCNT 0x130720 /* Video H general purpose counter */ + +/* ***************************************************************************** */ + +#define VID_DST_A_GPCNT_CTL 0x130030 /* Video A general purpose control */ +#define VID_DST_B_GPCNT_CTL 0x130130 /* Video B general purpose control */ +#define VID_DST_C_GPCNT_CTL 0x130230 /* Video C general purpose control */ +#define VID_DST_D_GPCNT_CTL 0x130330 /* Video D general purpose control */ +#define VID_DST_E_GPCNT_CTL 0x130430 /* Video E general purpose control */ +#define VID_DST_F_GPCNT_CTL 0x130530 /* Video F general purpose control */ +#define VID_DST_G_GPCNT_CTL 0x130630 /* Video G general purpose control */ +#define VID_DST_H_GPCNT_CTL 0x130730 /* Video H general purpose control */ + +/* ***************************************************************************** */ + +#define VID_DST_A_DMA_CTL 0x130040 /* Video A DMA control */ +#define VID_DST_B_DMA_CTL 0x130140 /* Video B DMA control */ +#define VID_DST_C_DMA_CTL 0x130240 /* Video C DMA control */ +#define VID_DST_D_DMA_CTL 0x130340 /* Video D DMA control */ +#define VID_DST_E_DMA_CTL 0x130440 /* Video E DMA control */ +#define VID_DST_F_DMA_CTL 0x130540 /* Video F DMA control */ +#define VID_DST_G_DMA_CTL 0x130640 /* Video G DMA control */ +#define VID_DST_H_DMA_CTL 0x130740 /* Video H DMA control */ #define FLD_VID_RISC_EN 0x00000010 #define FLD_VID_FIFO_EN 0x00000001 -//***************************************************************************** - -#define VID_DST_A_VIP_CTL 0x130080 // Video A VIP control -#define VID_DST_B_VIP_CTL 0x130180 // Video B VIP control -#define VID_DST_C_VIP_CTL 0x130280 // Video C VIP control -#define VID_DST_D_VIP_CTL 0x130380 // Video D VIP control -#define VID_DST_E_VIP_CTL 0x130480 // Video E VIP control -#define VID_DST_F_VIP_CTL 0x130580 // Video F VIP control -#define VID_DST_G_VIP_CTL 0x130680 // Video G VIP control -#define VID_DST_H_VIP_CTL 0x130780 // Video H VIP control - -//***************************************************************************** - -#define VID_DST_A_PIX_FRMT 0x130084 // Video A Pixel format -#define VID_DST_B_PIX_FRMT 0x130184 // Video B Pixel format -#define VID_DST_C_PIX_FRMT 0x130284 // Video C Pixel format -#define VID_DST_D_PIX_FRMT 0x130384 // Video D Pixel format -#define VID_DST_E_PIX_FRMT 0x130484 // Video E Pixel format -#define VID_DST_F_PIX_FRMT 0x130584 // Video F Pixel format -#define VID_DST_G_PIX_FRMT 0x130684 // Video G Pixel format -#define VID_DST_H_PIX_FRMT 0x130784 // Video H Pixel format - -//***************************************************************************** -// Video Source Channels -//***************************************************************************** - -#define VID_SRC_A_GPCNT_CTL 0x130804 // Video A general purpose control -#define VID_SRC_B_GPCNT_CTL 0x130904 // Video B general purpose control -#define VID_SRC_C_GPCNT_CTL 0x130A04 // Video C general purpose control -#define VID_SRC_D_GPCNT_CTL 0x130B04 // Video D general purpose control -#define VID_SRC_E_GPCNT_CTL 0x130C04 // Video E general purpose control -#define VID_SRC_F_GPCNT_CTL 0x130D04 // Video F general purpose control -#define VID_SRC_I_GPCNT_CTL 0x130E04 // Video I general purpose control -#define VID_SRC_J_GPCNT_CTL 0x130F04 // Video J general purpose control - -//***************************************************************************** - -#define VID_SRC_A_GPCNT 0x130808 // Video A general purpose counter -#define VID_SRC_B_GPCNT 0x130908 // Video B general purpose counter -#define VID_SRC_C_GPCNT 0x130A08 // Video C general purpose counter -#define VID_SRC_D_GPCNT 0x130B08 // Video D general purpose counter -#define VID_SRC_E_GPCNT 0x130C08 // Video E general purpose counter -#define VID_SRC_F_GPCNT 0x130D08 // Video F general purpose counter -#define VID_SRC_I_GPCNT 0x130E08 // Video I general purpose counter -#define VID_SRC_J_GPCNT 0x130F08 // Video J general purpose counter - -//***************************************************************************** - -#define VID_SRC_A_DMA_CTL 0x13080C // Video A DMA control -#define VID_SRC_B_DMA_CTL 0x13090C // Video B DMA control -#define VID_SRC_C_DMA_CTL 0x130A0C // Video C DMA control -#define VID_SRC_D_DMA_CTL 0x130B0C // Video D DMA control -#define VID_SRC_E_DMA_CTL 0x130C0C // Video E DMA control -#define VID_SRC_F_DMA_CTL 0x130D0C // Video F DMA control -#define VID_SRC_I_DMA_CTL 0x130E0C // Video I DMA control -#define VID_SRC_J_DMA_CTL 0x130F0C // Video J DMA control +/* ***************************************************************************** */ + +#define VID_DST_A_VIP_CTL 0x130080 /* Video A VIP control */ +#define VID_DST_B_VIP_CTL 0x130180 /* Video B VIP control */ +#define VID_DST_C_VIP_CTL 0x130280 /* Video C VIP control */ +#define VID_DST_D_VIP_CTL 0x130380 /* Video D VIP control */ +#define VID_DST_E_VIP_CTL 0x130480 /* Video E VIP control */ +#define VID_DST_F_VIP_CTL 0x130580 /* Video F VIP control */ +#define VID_DST_G_VIP_CTL 0x130680 /* Video G VIP control */ +#define VID_DST_H_VIP_CTL 0x130780 /* Video H VIP control */ + +/* ***************************************************************************** */ + +#define VID_DST_A_PIX_FRMT 0x130084 /* Video A Pixel format */ +#define VID_DST_B_PIX_FRMT 0x130184 /* Video B Pixel format */ +#define VID_DST_C_PIX_FRMT 0x130284 /* Video C Pixel format */ +#define VID_DST_D_PIX_FRMT 0x130384 /* Video D Pixel format */ +#define VID_DST_E_PIX_FRMT 0x130484 /* Video E Pixel format */ +#define VID_DST_F_PIX_FRMT 0x130584 /* Video F Pixel format */ +#define VID_DST_G_PIX_FRMT 0x130684 /* Video G Pixel format */ +#define VID_DST_H_PIX_FRMT 0x130784 /* Video H Pixel format */ + +/* ***************************************************************************** */ +/* Video Source Channels */ +/* ***************************************************************************** */ + +#define VID_SRC_A_GPCNT_CTL 0x130804 /* Video A general purpose control */ +#define VID_SRC_B_GPCNT_CTL 0x130904 /* Video B general purpose control */ +#define VID_SRC_C_GPCNT_CTL 0x130A04 /* Video C general purpose control */ +#define VID_SRC_D_GPCNT_CTL 0x130B04 /* Video D general purpose control */ +#define VID_SRC_E_GPCNT_CTL 0x130C04 /* Video E general purpose control */ +#define VID_SRC_F_GPCNT_CTL 0x130D04 /* Video F general purpose control */ +#define VID_SRC_I_GPCNT_CTL 0x130E04 /* Video I general purpose control */ +#define VID_SRC_J_GPCNT_CTL 0x130F04 /* Video J general purpose control */ + +/* ***************************************************************************** */ + +#define VID_SRC_A_GPCNT 0x130808 /* Video A general purpose counter */ +#define VID_SRC_B_GPCNT 0x130908 /* Video B general purpose counter */ +#define VID_SRC_C_GPCNT 0x130A08 /* Video C general purpose counter */ +#define VID_SRC_D_GPCNT 0x130B08 /* Video D general purpose counter */ +#define VID_SRC_E_GPCNT 0x130C08 /* Video E general purpose counter */ +#define VID_SRC_F_GPCNT 0x130D08 /* Video F general purpose counter */ +#define VID_SRC_I_GPCNT 0x130E08 /* Video I general purpose counter */ +#define VID_SRC_J_GPCNT 0x130F08 /* Video J general purpose counter */ + +/* ***************************************************************************** */ + +#define VID_SRC_A_DMA_CTL 0x13080C /* Video A DMA control */ +#define VID_SRC_B_DMA_CTL 0x13090C /* Video B DMA control */ +#define VID_SRC_C_DMA_CTL 0x130A0C /* Video C DMA control */ +#define VID_SRC_D_DMA_CTL 0x130B0C /* Video D DMA control */ +#define VID_SRC_E_DMA_CTL 0x130C0C /* Video E DMA control */ +#define VID_SRC_F_DMA_CTL 0x130D0C /* Video F DMA control */ +#define VID_SRC_I_DMA_CTL 0x130E0C /* Video I DMA control */ +#define VID_SRC_J_DMA_CTL 0x130F0C /* Video J DMA control */ #define FLD_APB_RISC_EN 0x00000010 #define FLD_APB_FIFO_EN 0x00000001 -//***************************************************************************** - -#define VID_SRC_A_FMT_CTL 0x130810 // Video A format control -#define VID_SRC_B_FMT_CTL 0x130910 // Video B format control -#define VID_SRC_C_FMT_CTL 0x130A10 // Video C format control -#define VID_SRC_D_FMT_CTL 0x130B10 // Video D format control -#define VID_SRC_E_FMT_CTL 0x130C10 // Video E format control -#define VID_SRC_F_FMT_CTL 0x130D10 // Video F format control -#define VID_SRC_I_FMT_CTL 0x130E10 // Video I format control -#define VID_SRC_J_FMT_CTL 0x130F10 // Video J format control - -//***************************************************************************** - -#define VID_SRC_A_ACTIVE_CTL1 0x130814 // Video A active control 1 -#define VID_SRC_B_ACTIVE_CTL1 0x130914 // Video B active control 1 -#define VID_SRC_C_ACTIVE_CTL1 0x130A14 // Video C active control 1 -#define VID_SRC_D_ACTIVE_CTL1 0x130B14 // Video D active control 1 -#define VID_SRC_E_ACTIVE_CTL1 0x130C14 // Video E active control 1 -#define VID_SRC_F_ACTIVE_CTL1 0x130D14 // Video F active control 1 -#define VID_SRC_I_ACTIVE_CTL1 0x130E14 // Video I active control 1 -#define VID_SRC_J_ACTIVE_CTL1 0x130F14 // Video J active control 1 - -//***************************************************************************** - -#define VID_SRC_A_ACTIVE_CTL2 0x130818 // Video A active control 2 -#define VID_SRC_B_ACTIVE_CTL2 0x130918 // Video B active control 2 -#define VID_SRC_C_ACTIVE_CTL2 0x130A18 // Video C active control 2 -#define VID_SRC_D_ACTIVE_CTL2 0x130B18 // Video D active control 2 -#define VID_SRC_E_ACTIVE_CTL2 0x130C18 // Video E active control 2 -#define VID_SRC_F_ACTIVE_CTL2 0x130D18 // Video F active control 2 -#define VID_SRC_I_ACTIVE_CTL2 0x130E18 // Video I active control 2 -#define VID_SRC_J_ACTIVE_CTL2 0x130F18 // Video J active control 2 - -//***************************************************************************** - -#define VID_SRC_A_CDT_SZ 0x13081C // Video A CDT size -#define VID_SRC_B_CDT_SZ 0x13091C // Video B CDT size -#define VID_SRC_C_CDT_SZ 0x130A1C // Video C CDT size -#define VID_SRC_D_CDT_SZ 0x130B1C // Video D CDT size -#define VID_SRC_E_CDT_SZ 0x130C1C // Video E CDT size -#define VID_SRC_F_CDT_SZ 0x130D1C // Video F CDT size -#define VID_SRC_I_CDT_SZ 0x130E1C // Video I CDT size -#define VID_SRC_J_CDT_SZ 0x130F1C // Video J CDT size - -//***************************************************************************** -// Audio I/F -//***************************************************************************** -#define AUD_DST_A_DMA 0x140000 // Audio Int A DMA data port -#define AUD_SRC_A_DMA 0x140008 // Audio Int A DMA data port - -#define AUD_A_GPCNT 0x140010 // Audio Int A gp counter +/* ***************************************************************************** */ + +#define VID_SRC_A_FMT_CTL 0x130810 /* Video A format control */ +#define VID_SRC_B_FMT_CTL 0x130910 /* Video B format control */ +#define VID_SRC_C_FMT_CTL 0x130A10 /* Video C format control */ +#define VID_SRC_D_FMT_CTL 0x130B10 /* Video D format control */ +#define VID_SRC_E_FMT_CTL 0x130C10 /* Video E format control */ +#define VID_SRC_F_FMT_CTL 0x130D10 /* Video F format control */ +#define VID_SRC_I_FMT_CTL 0x130E10 /* Video I format control */ +#define VID_SRC_J_FMT_CTL 0x130F10 /* Video J format control */ + +/* ***************************************************************************** */ + +#define VID_SRC_A_ACTIVE_CTL1 0x130814 /* Video A active control 1 */ +#define VID_SRC_B_ACTIVE_CTL1 0x130914 /* Video B active control 1 */ +#define VID_SRC_C_ACTIVE_CTL1 0x130A14 /* Video C active control 1 */ +#define VID_SRC_D_ACTIVE_CTL1 0x130B14 /* Video D active control 1 */ +#define VID_SRC_E_ACTIVE_CTL1 0x130C14 /* Video E active control 1 */ +#define VID_SRC_F_ACTIVE_CTL1 0x130D14 /* Video F active control 1 */ +#define VID_SRC_I_ACTIVE_CTL1 0x130E14 /* Video I active control 1 */ +#define VID_SRC_J_ACTIVE_CTL1 0x130F14 /* Video J active control 1 */ + +/* ***************************************************************************** */ + +#define VID_SRC_A_ACTIVE_CTL2 0x130818 /* Video A active control 2 */ +#define VID_SRC_B_ACTIVE_CTL2 0x130918 /* Video B active control 2 */ +#define VID_SRC_C_ACTIVE_CTL2 0x130A18 /* Video C active control 2 */ +#define VID_SRC_D_ACTIVE_CTL2 0x130B18 /* Video D active control 2 */ +#define VID_SRC_E_ACTIVE_CTL2 0x130C18 /* Video E active control 2 */ +#define VID_SRC_F_ACTIVE_CTL2 0x130D18 /* Video F active control 2 */ +#define VID_SRC_I_ACTIVE_CTL2 0x130E18 /* Video I active control 2 */ +#define VID_SRC_J_ACTIVE_CTL2 0x130F18 /* Video J active control 2 */ + +/* ***************************************************************************** */ + +#define VID_SRC_A_CDT_SZ 0x13081C /* Video A CDT size */ +#define VID_SRC_B_CDT_SZ 0x13091C /* Video B CDT size */ +#define VID_SRC_C_CDT_SZ 0x130A1C /* Video C CDT size */ +#define VID_SRC_D_CDT_SZ 0x130B1C /* Video D CDT size */ +#define VID_SRC_E_CDT_SZ 0x130C1C /* Video E CDT size */ +#define VID_SRC_F_CDT_SZ 0x130D1C /* Video F CDT size */ +#define VID_SRC_I_CDT_SZ 0x130E1C /* Video I CDT size */ +#define VID_SRC_J_CDT_SZ 0x130F1C /* Video J CDT size */ + +/* ***************************************************************************** */ +/* Audio I/F */ +/* ***************************************************************************** */ +#define AUD_DST_A_DMA 0x140000 /* Audio Int A DMA data port */ +#define AUD_SRC_A_DMA 0x140008 /* Audio Int A DMA data port */ + +#define AUD_A_GPCNT 0x140010 /* Audio Int A gp counter */ #define FLD_AUD_A_GP_CNT 0x0000FFFF -#define AUD_A_GPCNT_CTL 0x140014 // Audio Int A gp control +#define AUD_A_GPCNT_CTL 0x140014 /* Audio Int A gp control */ -#define AUD_A_LNGTH 0x140018 // Audio Int A line length +#define AUD_A_LNGTH 0x140018 /* Audio Int A line length */ -#define AUD_A_CFG 0x14001C // Audio Int A configuration +#define AUD_A_CFG 0x14001C /* Audio Int A configuration */ -//***************************************************************************** -#define AUD_DST_B_DMA 0x140100 // Audio Int B DMA data port -#define AUD_SRC_B_DMA 0x140108 // Audio Int B DMA data port +/* ***************************************************************************** */ +#define AUD_DST_B_DMA 0x140100 /* Audio Int B DMA data port */ +#define AUD_SRC_B_DMA 0x140108 /* Audio Int B DMA data port */ -#define AUD_B_GPCNT 0x140110 // Audio Int B gp counter +#define AUD_B_GPCNT 0x140110 /* Audio Int B gp counter */ #define FLD_AUD_B_GP_CNT 0x0000FFFF -#define AUD_B_GPCNT_CTL 0x140114 // Audio Int B gp control +#define AUD_B_GPCNT_CTL 0x140114 /* Audio Int B gp control */ -#define AUD_B_LNGTH 0x140118 // Audio Int B line length +#define AUD_B_LNGTH 0x140118 /* Audio Int B line length */ -#define AUD_B_CFG 0x14011C // Audio Int B configuration +#define AUD_B_CFG 0x14011C /* Audio Int B configuration */ -//***************************************************************************** -#define AUD_DST_C_DMA 0x140200 // Audio Int C DMA data port -#define AUD_SRC_C_DMA 0x140208 // Audio Int C DMA data port +/* ***************************************************************************** */ +#define AUD_DST_C_DMA 0x140200 /* Audio Int C DMA data port */ +#define AUD_SRC_C_DMA 0x140208 /* Audio Int C DMA data port */ -#define AUD_C_GPCNT 0x140210 // Audio Int C gp counter +#define AUD_C_GPCNT 0x140210 /* Audio Int C gp counter */ #define FLD_AUD_C_GP_CNT 0x0000FFFF -#define AUD_C_GPCNT_CTL 0x140214 // Audio Int C gp control +#define AUD_C_GPCNT_CTL 0x140214 /* Audio Int C gp control */ -#define AUD_C_LNGTH 0x140218 // Audio Int C line length +#define AUD_C_LNGTH 0x140218 /* Audio Int C line length */ -#define AUD_C_CFG 0x14021C // Audio Int C configuration +#define AUD_C_CFG 0x14021C /* Audio Int C configuration */ -//***************************************************************************** -#define AUD_DST_D_DMA 0x140300 // Audio Int D DMA data port -#define AUD_SRC_D_DMA 0x140308 // Audio Int D DMA data port +/* ***************************************************************************** */ +#define AUD_DST_D_DMA 0x140300 /* Audio Int D DMA data port */ +#define AUD_SRC_D_DMA 0x140308 /* Audio Int D DMA data port */ -#define AUD_D_GPCNT 0x140310 // Audio Int D gp counter +#define AUD_D_GPCNT 0x140310 /* Audio Int D gp counter */ #define FLD_AUD_D_GP_CNT 0x0000FFFF -#define AUD_D_GPCNT_CTL 0x140314 // Audio Int D gp control +#define AUD_D_GPCNT_CTL 0x140314 /* Audio Int D gp control */ -#define AUD_D_LNGTH 0x140318 // Audio Int D line length +#define AUD_D_LNGTH 0x140318 /* Audio Int D line length */ -#define AUD_D_CFG 0x14031C // Audio Int D configuration +#define AUD_D_CFG 0x14031C /* Audio Int D configuration */ -//***************************************************************************** -#define AUD_SRC_E_DMA 0x140400 // Audio Int E DMA data port +/* ***************************************************************************** */ +#define AUD_SRC_E_DMA 0x140400 /* Audio Int E DMA data port */ -#define AUD_E_GPCNT 0x140410 // Audio Int E gp counter +#define AUD_E_GPCNT 0x140410 /* Audio Int E gp counter */ #define FLD_AUD_E_GP_CNT 0x0000FFFF -#define AUD_E_GPCNT_CTL 0x140414 // Audio Int E gp control +#define AUD_E_GPCNT_CTL 0x140414 /* Audio Int E gp control */ -#define AUD_E_CFG 0x14041C // Audio Int E configuration +#define AUD_E_CFG 0x14041C /* Audio Int E configuration */ -//***************************************************************************** +/* ***************************************************************************** */ #define FLD_AUD_DST_LN_LNGTH 0x00000FFF @@ -1361,8 +1361,8 @@ #define FLD_AUD_SRC_ENABLE 0x00010000 -//***************************************************************************** -#define AUD_INT_DMA_CTL 0x140500 // Audio Int DMA control +/* ***************************************************************************** */ +#define AUD_INT_DMA_CTL 0x140500 /* Audio Int DMA control */ #define FLD_AUD_SRC_E_RISC_EN 0x00008000 #define FLD_AUD_SRC_C_RISC_EN 0x00004000 @@ -1384,15 +1384,15 @@ #define FLD_AUD_DST_B_FIFO_EN 0x00000002 #define FLD_AUD_DST_A_FIFO_EN 0x00000001 -//***************************************************************************** -// -// Mobilygen Interface Registers -// -//***************************************************************************** -// Mobilygen Interface A -//***************************************************************************** -#define MB_IF_A_DMA 0x150000 // MBIF A DMA data port -#define MB_IF_A_GPCN 0x150008 // MBIF A GP counter +/* ***************************************************************************** */ +/* */ +/* Mobilygen Interface Registers */ +/* */ +/* ***************************************************************************** */ +/* Mobilygen Interface A */ +/* ***************************************************************************** */ +#define MB_IF_A_DMA 0x150000 /* MBIF A DMA data port */ +#define MB_IF_A_GPCN 0x150008 /* MBIF A GP counter */ #define MB_IF_A_GPCN_CTRL 0x15000C #define MB_IF_A_DMA_CTRL 0x150010 #define MB_IF_A_LENGTH 0x150014 @@ -1415,11 +1415,11 @@ #define MB_IF_A_DATA_STRUCT_D 0x150058 #define MB_IF_A_DATA_STRUCT_E 0x15005C #define MB_IF_A_DATA_STRUCT_F 0x150060 -//***************************************************************************** -// Mobilygen Interface B -//***************************************************************************** -#define MB_IF_B_DMA 0x160000 // MBIF A DMA data port -#define MB_IF_B_GPCN 0x160008 // MBIF A GP counter +/* ***************************************************************************** */ +/* Mobilygen Interface B */ +/* ***************************************************************************** */ +#define MB_IF_B_DMA 0x160000 /* MBIF A DMA data port */ +#define MB_IF_B_GPCN 0x160008 /* MBIF A GP counter */ #define MB_IF_B_GPCN_CTRL 0x16000C #define MB_IF_B_DMA_CTRL 0x160010 #define MB_IF_B_LENGTH 0x160014 @@ -1443,14 +1443,14 @@ #define MB_IF_B_DATA_STRUCT_E 0x16005C #define MB_IF_B_DATA_STRUCT_F 0x160060 -// MB_DMA_CTRL +/* MB_DMA_CTRL */ #define FLD_MB_IF_RISC_EN 0x00000010 #define FLD_MB_IF_FIFO_EN 0x00000001 -// MB_LENGTH +/* MB_LENGTH */ #define FLD_MB_IF_LN_LNGTH 0x00000FFF -// MB_HCMD register +/* MB_HCMD register */ #define FLD_MB_HCMD_H_GO 0x80000000 #define FLD_MB_HCMD_H_BUSY 0x40000000 #define FLD_MB_HCMD_H_DMA_HOLD 0x10000000 @@ -1461,118 +1461,118 @@ #define FLD_MB_HCMD_H_ADDR 0x00FF0000 #define FLD_MB_HCMD_H_DATA 0x0000FFFF -//***************************************************************************** -// I2C #1 -//***************************************************************************** -#define I2C1_ADDR 0x180000 // I2C #1 address -#define FLD_I2C_DADDR 0xfe000000 // RW [31:25] I2C Device Address - // RO [24] reserved -//***************************************************************************** -#define FLD_I2C_SADDR 0x00FFFFFF // RW [23:0] I2C Sub-address - -//***************************************************************************** -#define I2C1_WDATA 0x180004 // I2C #1 write data -#define FLD_I2C_WDATA 0xFFFFFFFF // RW [31:0] - -//***************************************************************************** -#define I2C1_CTRL 0x180008 // I2C #1 control -#define FLD_I2C_PERIOD 0xFF000000 // RW [31:24] -#define FLD_I2C_SCL_IN 0x00200000 // RW [21] -#define FLD_I2C_SDA_IN 0x00100000 // RW [20] - // RO [19:18] reserved -#define FLD_I2C_SCL_OUT 0x00020000 // RW [17] -#define FLD_I2C_SDA_OUT 0x00010000 // RW [16] - // RO [15] reserved -#define FLD_I2C_DATA_LEN 0x00007000 // RW [14:12] -#define FLD_I2C_SADDR_INC 0x00000800 // RW [11] - // RO [10:9] reserved -#define FLD_I2C_SADDR_LEN 0x00000300 // RW [9:8] - // RO [7:6] reserved -#define FLD_I2C_SOFT 0x00000020 // RW [5] -#define FLD_I2C_NOSTOP 0x00000010 // RW [4] -#define FLD_I2C_EXTEND 0x00000008 // RW [3] -#define FLD_I2C_SYNC 0x00000004 // RW [2] -#define FLD_I2C_READ_SA 0x00000002 // RW [1] -#define FLD_I2C_READ_WRN 0x00000001 // RW [0] - -//***************************************************************************** -#define I2C1_RDATA 0x18000C // I2C #1 read data -#define FLD_I2C_RDATA 0xFFFFFFFF // RO [31:0] - -//***************************************************************************** -#define I2C1_STAT 0x180010 // I2C #1 status -#define FLD_I2C_XFER_IN_PROG 0x00000002 // RO [1] -#define FLD_I2C_RACK 0x00000001 // RO [0] - -//***************************************************************************** -// I2C #2 -//***************************************************************************** -#define I2C2_ADDR 0x190000 // I2C #2 address - -//***************************************************************************** -#define I2C2_WDATA 0x190004 // I2C #2 write data - -//***************************************************************************** -#define I2C2_CTRL 0x190008 // I2C #2 control - -//***************************************************************************** -#define I2C2_RDATA 0x19000C // I2C #2 read data - -//***************************************************************************** -#define I2C2_STAT 0x190010 // I2C #2 status - -//***************************************************************************** -// I2C #3 -//***************************************************************************** -#define I2C3_ADDR 0x1A0000 // I2C #3 address - -//***************************************************************************** -#define I2C3_WDATA 0x1A0004 // I2C #3 write data - -//***************************************************************************** -#define I2C3_CTRL 0x1A0008 // I2C #3 control - -//***************************************************************************** -#define I2C3_RDATA 0x1A000C // I2C #3 read data - -//***************************************************************************** -#define I2C3_STAT 0x1A0010 // I2C #3 status - -//***************************************************************************** -// UART -//***************************************************************************** -#define UART_CTL 0x1B0000 // UART Control Register -#define FLD_LOOP_BACK_EN (1 << 7) // RW field - default 0 -#define FLD_RX_TRG_SZ (3 << 2) // RW field - default 0 -#define FLD_RX_EN (1 << 1) // RW field - default 0 -#define FLD_TX_EN (1 << 0) // RW field - default 0 - -//***************************************************************************** -#define UART_BRD 0x1B0004 // UART Baud Rate Divisor -#define FLD_BRD 0x0000FFFF // RW field - default 0x197 - -//***************************************************************************** -#define UART_DBUF 0x1B0008 // UART Tx/Rx Data BuFFer -#define FLD_DB 0xFFFFFFFF // RW field - default 0 - -//***************************************************************************** -#define UART_ISR 0x1B000C // UART Interrupt Status -#define FLD_RXD_TIMEOUT_EN (1 << 7) // RW field - default 0 -#define FLD_FRM_ERR_EN (1 << 6) // RW field - default 0 -#define FLD_RXD_RDY_EN (1 << 5) // RW field - default 0 -#define FLD_TXD_EMPTY_EN (1 << 4) // RW field - default 0 -#define FLD_RXD_OVERFLOW (1 << 3) // RW field - default 0 -#define FLD_FRM_ERR (1 << 2) // RW field - default 0 -#define FLD_RXD_RDY (1 << 1) // RW field - default 0 -#define FLD_TXD_EMPTY (1 << 0) // RW field - default 0 - -//***************************************************************************** -#define UART_CNT 0x1B0010 // UART Tx/Rx FIFO Byte Count -#define FLD_TXD_CNT (0x1F << 8) // RW field - default 0 -#define FLD_RXD_CNT (0x1F << 0) // RW field - default 0 - -//***************************************************************************** -// Motion Detection +/* ***************************************************************************** */ +/* I2C #1 */ +/* ***************************************************************************** */ +#define I2C1_ADDR 0x180000 /* I2C #1 address */ +#define FLD_I2C_DADDR 0xfe000000 /* RW [31:25] I2C Device Address */ + /* RO [24] reserved */ +/* ***************************************************************************** */ +#define FLD_I2C_SADDR 0x00FFFFFF /* RW [23:0] I2C Sub-address */ + +/* ***************************************************************************** */ +#define I2C1_WDATA 0x180004 /* I2C #1 write data */ +#define FLD_I2C_WDATA 0xFFFFFFFF /* RW [31:0] */ + +/* ***************************************************************************** */ +#define I2C1_CTRL 0x180008 /* I2C #1 control */ +#define FLD_I2C_PERIOD 0xFF000000 /* RW [31:24] */ +#define FLD_I2C_SCL_IN 0x00200000 /* RW [21] */ +#define FLD_I2C_SDA_IN 0x00100000 /* RW [20] */ + /* RO [19:18] reserved */ +#define FLD_I2C_SCL_OUT 0x00020000 /* RW [17] */ +#define FLD_I2C_SDA_OUT 0x00010000 /* RW [16] */ + /* RO [15] reserved */ +#define FLD_I2C_DATA_LEN 0x00007000 /* RW [14:12] */ +#define FLD_I2C_SADDR_INC 0x00000800 /* RW [11] */ + /* RO [10:9] reserved */ +#define FLD_I2C_SADDR_LEN 0x00000300 /* RW [9:8] */ + /* RO [7:6] reserved */ +#define FLD_I2C_SOFT 0x00000020 /* RW [5] */ +#define FLD_I2C_NOSTOP 0x00000010 /* RW [4] */ +#define FLD_I2C_EXTEND 0x00000008 /* RW [3] */ +#define FLD_I2C_SYNC 0x00000004 /* RW [2] */ +#define FLD_I2C_READ_SA 0x00000002 /* RW [1] */ +#define FLD_I2C_READ_WRN 0x00000001 /* RW [0] */ + +/* ***************************************************************************** */ +#define I2C1_RDATA 0x18000C /* I2C #1 read data */ +#define FLD_I2C_RDATA 0xFFFFFFFF /* RO [31:0] */ + +/* ***************************************************************************** */ +#define I2C1_STAT 0x180010 /* I2C #1 status */ +#define FLD_I2C_XFER_IN_PROG 0x00000002 /* RO [1] */ +#define FLD_I2C_RACK 0x00000001 /* RO [0] */ + +/* ***************************************************************************** */ +/* I2C #2 */ +/* ***************************************************************************** */ +#define I2C2_ADDR 0x190000 /* I2C #2 address */ + +/* ***************************************************************************** */ +#define I2C2_WDATA 0x190004 /* I2C #2 write data */ + +/* ***************************************************************************** */ +#define I2C2_CTRL 0x190008 /* I2C #2 control */ + +/* ***************************************************************************** */ +#define I2C2_RDATA 0x19000C /* I2C #2 read data */ + +/* ***************************************************************************** */ +#define I2C2_STAT 0x190010 /* I2C #2 status */ + +/* ***************************************************************************** */ +/* I2C #3 */ +/* ***************************************************************************** */ +#define I2C3_ADDR 0x1A0000 /* I2C #3 address */ + +/* ***************************************************************************** */ +#define I2C3_WDATA 0x1A0004 /* I2C #3 write data */ + +/* ***************************************************************************** */ +#define I2C3_CTRL 0x1A0008 /* I2C #3 control */ + +/* ***************************************************************************** */ +#define I2C3_RDATA 0x1A000C /* I2C #3 read data */ + +/* ***************************************************************************** */ +#define I2C3_STAT 0x1A0010 /* I2C #3 status */ + +/* ***************************************************************************** */ +/* UART */ +/* ***************************************************************************** */ +#define UART_CTL 0x1B0000 /* UART Control Register */ +#define FLD_LOOP_BACK_EN (1 << 7) /* RW field - default 0 */ +#define FLD_RX_TRG_SZ (3 << 2) /* RW field - default 0 */ +#define FLD_RX_EN (1 << 1) /* RW field - default 0 */ +#define FLD_TX_EN (1 << 0) /* RW field - default 0 */ + +/* ***************************************************************************** */ +#define UART_BRD 0x1B0004 /* UART Baud Rate Divisor */ +#define FLD_BRD 0x0000FFFF /* RW field - default 0x197 */ + +/* ***************************************************************************** */ +#define UART_DBUF 0x1B0008 /* UART Tx/Rx Data BuFFer */ +#define FLD_DB 0xFFFFFFFF /* RW field - default 0 */ + +/* ***************************************************************************** */ +#define UART_ISR 0x1B000C /* UART Interrupt Status */ +#define FLD_RXD_TIMEOUT_EN (1 << 7) /* RW field - default 0 */ +#define FLD_FRM_ERR_EN (1 << 6) /* RW field - default 0 */ +#define FLD_RXD_RDY_EN (1 << 5) /* RW field - default 0 */ +#define FLD_TXD_EMPTY_EN (1 << 4) /* RW field - default 0 */ +#define FLD_RXD_OVERFLOW (1 << 3) /* RW field - default 0 */ +#define FLD_FRM_ERR (1 << 2) /* RW field - default 0 */ +#define FLD_RXD_RDY (1 << 1) /* RW field - default 0 */ +#define FLD_TXD_EMPTY (1 << 0) /* RW field - default 0 */ + +/* ***************************************************************************** */ +#define UART_CNT 0x1B0010 /* UART Tx/Rx FIFO Byte Count */ +#define FLD_TXD_CNT (0x1F << 8) /* RW field - default 0 */ +#define FLD_RXD_CNT (0x1F << 0) /* RW field - default 0 */ + +/* ***************************************************************************** */ +/* Motion Detection */ #define MD_CH0_GRID_BLOCK_YCNT 0x170014 #define MD_CH1_GRID_BLOCK_YCNT 0x170094 #define MD_CH2_GRID_BLOCK_YCNT 0x170114 @@ -1589,4 +1589,4 @@ #define PIXEL_ENGINE_VIP1 0 #define PIXEL_ENGINE_VIP2 1 -#endif //Athena_REGISTERS +#endif /* Athena_REGISTERS */ diff --git a/drivers/staging/cx25821/cx25821-sram.h b/drivers/staging/cx25821/cx25821-sram.h index bd677ee22996..5f05d153bc4d 100644 --- a/drivers/staging/cx25821/cx25821-sram.h +++ b/drivers/staging/cx25821/cx25821-sram.h @@ -23,34 +23,34 @@ #ifndef __ATHENA_SRAM_H__ #define __ATHENA_SRAM_H__ -//#define RX_SRAM_START_SIZE = 0; // Start of reserved SRAM -#define VID_CMDS_SIZE 80 // Video CMDS size in bytes -#define AUDIO_CMDS_SIZE 80 // AUDIO CMDS size in bytes -#define MBIF_CMDS_SIZE 80 // MBIF CMDS size in bytes +/* #define RX_SRAM_START_SIZE = 0; // Start of reserved SRAM */ +#define VID_CMDS_SIZE 80 /* Video CMDS size in bytes */ +#define AUDIO_CMDS_SIZE 80 /* AUDIO CMDS size in bytes */ +#define MBIF_CMDS_SIZE 80 /* MBIF CMDS size in bytes */ -//#define RX_SRAM_POOL_START_SIZE = 0; // Start of useable RX SRAM for buffers -#define VID_IQ_SIZE 64 // VID instruction queue size in bytes +/* #define RX_SRAM_POOL_START_SIZE = 0; // Start of useable RX SRAM for buffers */ +#define VID_IQ_SIZE 64 /* VID instruction queue size in bytes */ #define MBIF_IQ_SIZE 64 -#define AUDIO_IQ_SIZE 64 // AUD instruction queue size in bytes +#define AUDIO_IQ_SIZE 64 /* AUD instruction queue size in bytes */ -#define VID_CDT_SIZE 64 // VID cluster descriptor table size in bytes -#define MBIF_CDT_SIZE 64 // MBIF/HBI cluster descriptor table size in bytes -#define AUDIO_CDT_SIZE 48 // AUD cluster descriptor table size in bytes +#define VID_CDT_SIZE 64 /* VID cluster descriptor table size in bytes */ +#define MBIF_CDT_SIZE 64 /* MBIF/HBI cluster descriptor table size in bytes */ +#define AUDIO_CDT_SIZE 48 /* AUD cluster descriptor table size in bytes */ -//#define RX_SRAM_POOL_FREE_SIZE = 16; // Start of available RX SRAM -//#define RX_SRAM_END_SIZE = 0; // End of RX SRAM +/* #define RX_SRAM_POOL_FREE_SIZE = 16; // Start of available RX SRAM */ +/* #define RX_SRAM_END_SIZE = 0; // End of RX SRAM */ -//#define TX_SRAM_POOL_START_SIZE = 0; // Start of transmit pool SRAM -//#define MSI_DATA_SIZE = 64; // Reserved (MSI Data, RISC working stora +/* #define TX_SRAM_POOL_START_SIZE = 0; // Start of transmit pool SRAM */ +/* #define MSI_DATA_SIZE = 64; // Reserved (MSI Data, RISC working stora */ -#define VID_CLUSTER_SIZE 1440 // VID cluster data line -#define AUDIO_CLUSTER_SIZE 128 // AUDIO cluster data line -#define MBIF_CLUSTER_SIZE 1440 // MBIF/HBI cluster data line +#define VID_CLUSTER_SIZE 1440 /* VID cluster data line */ +#define AUDIO_CLUSTER_SIZE 128 /* AUDIO cluster data line */ +#define MBIF_CLUSTER_SIZE 1440 /* MBIF/HBI cluster data line */ -//#define TX_SRAM_POOL_FREE_SIZE = 704; // Start of available TX SRAM -//#define TX_SRAM_END_SIZE = 0; // End of TX SRAM +/* #define TX_SRAM_POOL_FREE_SIZE = 704; // Start of available TX SRAM */ +/* #define TX_SRAM_END_SIZE = 0; // End of TX SRAM */ -// Receive SRAM +/* Receive SRAM */ #define RX_SRAM_START 0x10000 #define VID_A_DOWN_CMDS 0x10000 #define VID_B_DOWN_CMDS 0x10050 @@ -78,9 +78,9 @@ #define AUD_E_UP_CMDS 0x10730 #define MBIF_A_DOWN_CMDS 0x10780 #define MBIF_B_DOWN_CMDS 0x107D0 -#define DMA_SCRATCH_PAD 0x10820 // Scratch pad area from 0x10820 to 0x10B40 +#define DMA_SCRATCH_PAD 0x10820 /* Scratch pad area from 0x10820 to 0x10B40 */ -//#define RX_SRAM_POOL_START = 0x105B0; +/* #define RX_SRAM_POOL_START = 0x105B0; */ #define VID_A_IQ 0x11000 #define VID_B_IQ 0x11040 @@ -118,7 +118,7 @@ #define MBIF_A_CDT 0x10C00 #define MBIF_B_CDT 0x10CC0 -// Cluster Buffer for RX +/* Cluster Buffer for RX */ #define VID_A_UP_CLUSTER_1 0x11400 #define VID_A_UP_CLUSTER_2 0x119A0 #define VID_A_UP_CLUSTER_3 0x11F40 @@ -178,9 +178,9 @@ #define RX_SRAM_POOL_FREE 0x1CE00 #define RX_SRAM_END 0x1D000 -// Free Receive SRAM 144 Bytes +/* Free Receive SRAM 144 Bytes */ -// Transmit SRAM +/* Transmit SRAM */ #define TX_SRAM_POOL_START 0x00000 #define VID_A_DOWN_CLUSTER_1 0x00040 diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c index 343df6619fe8..d12dbb572e8b 100644 --- a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c +++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c @@ -84,7 +84,7 @@ static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev, { unsigned int line, i; struct sram_channel *sram_ch = - &dev->sram_channels[dev->_channel2_upstream_select]; + dev->channels[dev->_channel2_upstream_select].sram_channels; int dist_betwn_starts = bpl * 2; /* sync instruction */ @@ -110,8 +110,11 @@ static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev, offset += dist_betwn_starts; } - // check if we need to enable the FIFO after the first 4 lines - // For the upstream video channel, the risc engine will enable the FIFO. + /* + check if we need to enable the FIFO after the first 4 lines + For the upstream video channel, the risc engine will enable + the FIFO. + */ if (fifo_enable && line == 3) { *(rp++) = RISC_WRITECR; *(rp++) = sram_ch->dma_ctl; @@ -130,7 +133,7 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, { __le32 *rp; int fifo_enable = 0; - int singlefield_lines = lines >> 1; //get line count for single field + int singlefield_lines = lines >> 1; /*get line count for single field */ int odd_num_lines = singlefield_lines; int frame = 0; int frame_size = 0; @@ -174,7 +177,7 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, fifo_enable = FIFO_DISABLE; - //Even field + /* Even field */ rp = cx25821_risc_field_upstream_ch2(dev, rp, dev-> _data_buf_phys_addr_ch2 + @@ -192,7 +195,10 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2; } - // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ + /* + Loop to 2ndFrameRISC or to Start of + Risc program & generate IRQ + */ *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); *(rp++) = cpu_to_le32(risc_phys_jump_addr); *(rp++) = cpu_to_le32(0); @@ -204,7 +210,7 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) { struct sram_channel *sram_ch = - &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_J]; + dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels; u32 tmp = 0; if (!dev->_is_running_ch2) { @@ -212,15 +218,15 @@ void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) ("cx25821: No video file is currently running so return!\n"); return; } - //Disable RISC interrupts + /* Disable RISC interrupts */ tmp = cx_read(sram_ch->int_msk); cx_write(sram_ch->int_msk, tmp & ~_intr_msk); - //Turn OFF risc and fifo + /* Turn OFF risc and fifo */ tmp = cx_read(sram_ch->dma_ctl); cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN)); - //Clear data buffer memory + /* Clear data buffer memory */ if (dev->_data_buf_virt_addr_ch2) memset(dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2); @@ -371,8 +377,8 @@ static void cx25821_vidups_handler_ch2(struct work_struct *work) } cx25821_get_frame_ch2(dev, - &dev->sram_channels[dev-> - _channel2_upstream_select]); + dev->channels[dev-> + _channel2_upstream_select].sram_channels); } int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) @@ -488,7 +494,7 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, return -ENOMEM; } - //Iniitize at this address until n bytes to 0 + /* Iniitize at this address until n bytes to 0 */ memset(dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2); if (dev->_data_buf_virt_addr_ch2 != NULL) { @@ -496,7 +502,7 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, dev->_data_buf_virt_addr_ch2, dev->_data_buf_phys_addr_ch2); } - //For Video Data buffer allocation + /* For Video Data buffer allocation */ dev->_data_buf_virt_addr_ch2 = pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2, &data_dma_addr); @@ -509,14 +515,14 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, return -ENOMEM; } - //Initialize at this address until n bytes to 0 + /* Initialize at this address until n bytes to 0 */ memset(dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2); ret = cx25821_openfile_ch2(dev, sram_ch); if (ret < 0) return ret; - //Creating RISC programs + /* Creating RISC programs */ ret = cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl, dev->_lines_count_ch2); @@ -536,7 +542,7 @@ int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, u32 status) { u32 int_msk_tmp; - struct sram_channel *channel = &dev->sram_channels[chan_num]; + struct sram_channel *channel = dev->channels[chan_num].sram_channels; int singlefield_lines = NTSC_FIELD_HEIGHT; int line_size_in_bytes = Y422_LINE_SZ; int odd_risc_prog_size = 0; @@ -544,10 +550,13 @@ int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, __le32 *rp; if (status & FLD_VID_SRC_RISC1) { - // We should only process one program per call + /* We should only process one program per call */ u32 prog_cnt = cx_read(channel->gpcnt); - //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers + /* + Since we've identified our IRQ, clear our bits from the + interrupt mask and interrupt status registers + */ int_msk_tmp = cx_read(channel->int_msk); cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); cx_write(channel->int_stat, _intr_msk); @@ -588,7 +597,7 @@ int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, FIFO_DISABLE, ODD_FIELD); - // Jump to Even Risc program of 1st Frame + /* Jump to Even Risc program of 1st Frame */ *(rp++) = cpu_to_le32(RISC_JUMP); *(rp++) = cpu_to_le32(risc_phys_jump_addr); *(rp++) = cpu_to_le32(0); @@ -603,7 +612,7 @@ int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, dev->_frame_count_ch2); return -1; } - //ElSE, set the interrupt mask register, re-enable irq. + /* ElSE, set the interrupt mask register, re-enable irq. */ int_msk_tmp = cx_read(channel->int_msk); cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); @@ -623,12 +632,12 @@ static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id) channel_num = VID_UPSTREAM_SRAM_CHANNEL_J; - sram_ch = &dev->sram_channels[channel_num]; + sram_ch = dev->channels[channel_num].sram_channels; msk_stat = cx_read(sram_ch->int_mstat); vid_status = cx_read(sram_ch->int_stat); - // Only deal with our interrupt + /* Only deal with our interrupt */ if (vid_status) { handled = cx25821_video_upstream_irq_ch2(dev, channel_num, @@ -658,7 +667,10 @@ static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev, value |= dev->_isNTSC_ch2 ? 0 : 0x10; cx_write(ch->vid_fmt_ctl, value); - // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format + /* + set number of active pixels in each line. Default is 720 + pixels in both NTSC and PAL format + */ cx_write(ch->vid_active_ctl1, width); num_lines = (height / 2) & 0x3FF; @@ -670,7 +682,7 @@ static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev, value = (num_lines << 16) | odd_num_lines; - // set number of active lines in field 0 (top) and field 1 (bottom) + /* set number of active lines in field 0 (top) and field 1 (bottom) */ cx_write(ch->vid_active_ctl2, value); cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3); @@ -682,21 +694,27 @@ int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, u32 tmp = 0; int err = 0; - // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C + /* + 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface + for channel A-C + */ tmp = cx_read(VID_CH_MODE_SEL); cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); - // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds. + /* + Set the physical start address of the RISC program in the initial + program counter(IPC) member of the cmds. + */ cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2); - cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ + cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ /* reset counter */ cx_write(sram_ch->gpcnt_ctl, 3); - // Clear our bits from the interrupt status register. + /* Clear our bits from the interrupt status register. */ cx_write(sram_ch->int_stat, _intr_msk); - //Set the interrupt mask register, enable irq. + /* Set the interrupt mask register, enable irq. */ cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); tmp = cx_read(sram_ch->int_msk); cx_write(sram_ch->int_msk, tmp |= _intr_msk); @@ -709,7 +727,7 @@ int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, dev->pci->irq); goto fail_irq; } - // Start the DMA engine + /* Start the DMA engine */ tmp = cx_read(sram_ch->dma_ctl); cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN); @@ -740,7 +758,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, } dev->_channel2_upstream_select = channel_select; - sram_ch = &dev->sram_channels[channel_select]; + sram_ch = dev->channels[channel_select].sram_channels; INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2); dev->_irq_queues_ch2 = @@ -751,7 +769,10 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, ("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); return -ENOMEM; } - // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C + /* + 656/VIP SRC Upstream Channel I & J and 7 - + Host Bus Interface for channel A-C + */ tmp = cx_read(VID_CH_MODE_SEL); cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); @@ -787,7 +808,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, str_length + 1); } - //Default if filename is empty string + /* Default if filename is empty string */ if (strcmp(dev->input_filename_ch2, "") == 0) { if (dev->_isNTSC_ch2) { dev->_filename_ch2 = @@ -812,7 +833,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2; dev->upstream_databuf_size_ch2 = data_frame_size * 2; - //Allocating buffers and prepare RISC program + /* Allocating buffers and prepare RISC program */ retval = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch, dev->_line_size_ch2); diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.h b/drivers/staging/cx25821/cx25821-video-upstream-ch2.h index 73feea114c1c..62340636c916 100644 --- a/drivers/staging/cx25821/cx25821-video-upstream-ch2.h +++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.h @@ -37,7 +37,7 @@ #define RESET_STATUS -1 #define NUM_NO_OPS 5 -// PAL and NTSC line sizes and number of lines. +/* PAL and NTSC line sizes and number of lines. */ #define WIDTH_D1 720 #define NTSC_LINES_PER_FRAME 480 #define PAL_LINES_PER_FRAME 576 diff --git a/drivers/staging/cx25821/cx25821-video-upstream.c b/drivers/staging/cx25821/cx25821-video-upstream.c index 7a3dad91eba8..756a820a76cb 100644 --- a/drivers/staging/cx25821/cx25821-video-upstream.c +++ b/drivers/staging/cx25821/cx25821-video-upstream.c @@ -134,7 +134,7 @@ static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp, { unsigned int line, i; struct sram_channel *sram_ch = - &dev->sram_channels[dev->_channel_upstream_select]; + dev->channels[dev->_channel_upstream_select].sram_channels; int dist_betwn_starts = bpl * 2; /* sync instruction */ @@ -253,7 +253,7 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) { struct sram_channel *sram_ch = - &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_I]; + dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels; u32 tmp = 0; if (!dev->_is_running) { @@ -346,20 +346,23 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) if (IS_ERR(myfile)) { const int open_errno = -PTR_ERR(myfile); - printk(KERN_ERR "%s(): ERROR opening file(%s) with errno = %d!\n", - __func__, dev->_filename, open_errno); + printk(KERN_ERR + "%s(): ERROR opening file(%s) with errno = %d!\n", + __func__, dev->_filename, open_errno); return PTR_ERR(myfile); } else { if (!(myfile->f_op)) { - printk(KERN_ERR "%s: File has no file operations registered!", - __func__); + printk(KERN_ERR + "%s: File has no file operations registered!", + __func__); filp_close(myfile, NULL); return -EIO; } if (!myfile->f_op->read) { - printk(KERN_ERR "%s: File has no READ operations registered!", - __func__); + printk(KERN_ERR + "%s: File has no READ operations registered!", + __func__); filp_close(myfile, NULL); return -EIO; } @@ -386,7 +389,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) if (vfs_read_retval < line_size) { printk(KERN_INFO - "Done: exit %s() since no more bytes to read from Video file.\n", + "Done: exit %s() since no more bytes to \ + read from Video file.\n", __func__); break; } @@ -411,13 +415,15 @@ static void cx25821_vidups_handler(struct work_struct *work) container_of(work, struct cx25821_dev, _irq_work_entry); if (!dev) { - printk(KERN_ERR "ERROR %s(): since container_of(work_struct) FAILED!\n", - __func__); + printk(KERN_ERR + "ERROR %s(): since container_of(work_struct) FAILED!\n", + __func__); return; } cx25821_get_frame(dev, - &dev->sram_channels[dev->_channel_upstream_select]); + dev->channels[dev->_channel_upstream_select]. + sram_channels); } int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) @@ -437,20 +443,22 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) if (IS_ERR(myfile)) { const int open_errno = -PTR_ERR(myfile); - printk(KERN_ERR "%s(): ERROR opening file(%s) with errno = %d!\n", + printk(KERN_ERR "%s(): ERROR opening file(%s) with errno = %d!\n", __func__, dev->_filename, open_errno); return PTR_ERR(myfile); } else { if (!(myfile->f_op)) { - printk(KERN_ERR "%s: File has no file operations registered!", - __func__); + printk(KERN_ERR + "%s: File has no file operations registered!", + __func__); filp_close(myfile, NULL); return -EIO; } if (!myfile->f_op->read) { - printk - (KERN_ERR "%s: File has no READ operations registered! Returning.", + printk(KERN_ERR + "%s: File has no READ operations registered! \ + Returning.", __func__); filp_close(myfile, NULL); return -EIO; @@ -480,7 +488,8 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) if (vfs_read_retval < line_size) { printk(KERN_INFO - "Done: exit %s() since no more bytes to read from Video file.\n", + "Done: exit %s() since no more \ + bytes to read from Video file.\n", __func__); break; } @@ -526,7 +535,8 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, if (!dev->_dma_virt_addr) { printk - (KERN_ERR "cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); + (KERN_ERR "cx25821: FAILED to allocate memory for Risc \ + buffer! Returning.\n"); return -ENOMEM; } @@ -547,7 +557,8 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, if (!dev->_data_buf_virt_addr) { printk - (KERN_ERR "cx25821: FAILED to allocate memory for data buffer! Returning.\n"); + (KERN_ERR "cx25821: FAILED to allocate memory for data \ + buffer! Returning.\n"); return -ENOMEM; } @@ -578,7 +589,7 @@ int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, u32 status) { u32 int_msk_tmp; - struct sram_channel *channel = &dev->sram_channels[chan_num]; + struct sram_channel *channel = dev->channels[chan_num].sram_channels; int singlefield_lines = NTSC_FIELD_HEIGHT; int line_size_in_bytes = Y422_LINE_SZ; int odd_risc_prog_size = 0; @@ -642,16 +653,16 @@ int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, } else { if (status & FLD_VID_SRC_UF) printk - (KERN_ERR "%s: Video Received Underflow Error Interrupt!\n", - __func__); + (KERN_ERR "%s: Video Received Underflow Error \ + Interrupt!\n", __func__); if (status & FLD_VID_SRC_SYNC) - printk(KERN_ERR "%s: Video Received Sync Error Interrupt!\n", - __func__); + printk(KERN_ERR "%s: Video Received Sync Error \ + Interrupt!\n", __func__); if (status & FLD_VID_SRC_OPC_ERR) - printk(KERN_ERR "%s: Video Received OpCode Error Interrupt!\n", - __func__); + printk(KERN_ERR "%s: Video Received OpCode Error \ + Interrupt!\n", __func__); } if (dev->_file_status == END_OF_FILE) { @@ -679,7 +690,7 @@ static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) channel_num = VID_UPSTREAM_SRAM_CHANNEL_I; - sram_ch = &dev->sram_channels[channel_num]; + sram_ch = dev->channels[channel_num].sram_channels; msk_stat = cx_read(sram_ch->int_mstat); vid_status = cx_read(sram_ch->int_stat); @@ -800,14 +811,15 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, } dev->_channel_upstream_select = channel_select; - sram_ch = &dev->sram_channels[channel_select]; + sram_ch = dev->channels[channel_select].sram_channels; INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler); dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue"); if (!dev->_irq_queues) { printk - (KERN_ERR "cx25821: create_singlethread_workqueue() for Video FAILED!\n"); + (KERN_ERR "cx25821: create_singlethread_workqueue() for \ + Video FAILED!\n"); return -ENOMEM; } /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for diff --git a/drivers/staging/cx25821/cx25821-video-upstream.h b/drivers/staging/cx25821/cx25821-video-upstream.h index cc9f93842514..10dee5c24a81 100644 --- a/drivers/staging/cx25821/cx25821-video-upstream.h +++ b/drivers/staging/cx25821/cx25821-video-upstream.h @@ -38,7 +38,7 @@ #define RESET_STATUS -1 #define NUM_NO_OPS 5 -// PAL and NTSC line sizes and number of lines. +/* PAL and NTSC line sizes and number of lines. */ #define WIDTH_D1 720 #define NTSC_LINES_PER_FRAME 480 #define PAL_LINES_PER_FRAME 576 diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c index 791212c1a661..1d5e8796d383 100644 --- a/drivers/staging/cx25821/cx25821-video.c +++ b/drivers/staging/cx25821/cx25821-video.c @@ -4,6 +4,9 @@ * Copyright (C) 2009 Conexant Systems Inc. * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver + * Parts adapted/taken from Eduardo Moscoso Rubino + * Copyright (C) 2009 Eduardo Moscoso Rubino <moscoso@TopoLogica.com> + * * * 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 @@ -24,7 +27,7 @@ #include "cx25821-video.h" MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); -MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); +MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); MODULE_LICENSE("GPL"); static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; @@ -48,7 +51,10 @@ unsigned int vid_limit = 16; module_param(vid_limit, int, 0644); MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); -static void init_controls(struct cx25821_dev *dev, int chan_num); +static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num); + +static const struct v4l2_file_operations video_fops; +static const struct v4l2_ioctl_ops video_ioctl_ops; #define FORMAT_FLAGS_PACKED 0x01 @@ -211,7 +217,7 @@ static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) } */ -// resource management +/* resource management */ int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit) { dprintk(1, "%s()\n", __func__); @@ -221,14 +227,14 @@ int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int /* is it free? */ mutex_lock(&dev->lock); - if (dev->resources & bit) { + if (dev->channels[fh->channel_id].resources & bit) { /* no, someone else uses it */ mutex_unlock(&dev->lock); return 0; } /* it's free, grab it */ fh->resources |= bit; - dev->resources |= bit; + dev->channels[fh->channel_id].resources |= bit; dprintk(1, "res: get %d\n", bit); mutex_unlock(&dev->lock); return 1; @@ -239,9 +245,9 @@ int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit) return fh->resources & bit; } -int cx25821_res_locked(struct cx25821_dev *dev, unsigned int bit) +int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit) { - return dev->resources & bit; + return fh->dev->channels[fh->channel_id].resources & bit; } void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits) @@ -251,7 +257,7 @@ void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned i mutex_lock(&dev->lock); fh->resources &= ~bits; - dev->resources &= ~bits; + dev->channels[fh->channel_id].resources &= ~bits; dprintk(1, "res: put %d\n", bits); mutex_unlock(&dev->lock); } @@ -358,11 +364,11 @@ void cx25821_vid_timeout(unsigned long data) struct cx25821_data *timeout_data = (struct cx25821_data *)data; struct cx25821_dev *dev = timeout_data->dev; struct sram_channel *channel = timeout_data->channel; - struct cx25821_dmaqueue *q = &dev->vidq[channel->i]; + struct cx25821_dmaqueue *q = &dev->channels[channel->i].vidq; struct cx25821_buffer *buf; unsigned long flags; - //cx25821_sram_channel_dump(dev, channel); + /* cx25821_sram_channel_dump(dev, channel); */ cx_clear(channel->dma_ctl, 0x11); spin_lock_irqsave(&dev->slock, flags); @@ -384,7 +390,7 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) u32 count = 0; int handled = 0; u32 mask; - struct sram_channel *channel = &dev->sram_channels[chan_num]; + struct sram_channel *channel = dev->channels[chan_num].sram_channels; mask = cx_read(channel->int_msk); if (0 == (status & mask)) @@ -404,7 +410,8 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) if (status & FLD_VID_DST_RISC1) { spin_lock(&dev->slock); count = cx_read(channel->gpcnt); - cx25821_video_wakeup(dev, &dev->vidq[channel->i], count); + cx25821_video_wakeup(dev, + &dev->channels[channel->i].vidq, count); spin_unlock(&dev->slock); handled++; } @@ -413,8 +420,9 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) if (status & 0x10) { dprintk(2, "stopper video\n"); spin_lock(&dev->slock); - cx25821_restart_video_queue(dev, &dev->vidq[channel->i], - channel); + cx25821_restart_video_queue(dev, + &dev->channels[channel->i].vidq, + channel); spin_unlock(&dev->slock); handled++; } @@ -437,72 +445,95 @@ void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) { cx_clear(PCI_INT_MSK, 1); - if (dev->video_dev[chan_num]) { - if (video_is_registered(dev->video_dev[chan_num])) - video_unregister_device(dev->video_dev[chan_num]); + if (dev->channels[chan_num].video_dev) { + if (video_is_registered(dev->channels[chan_num].video_dev)) + video_unregister_device( + dev->channels[chan_num].video_dev); else - video_device_release(dev->video_dev[chan_num]); + video_device_release( + dev->channels[chan_num].video_dev); - dev->video_dev[chan_num] = NULL; + dev->channels[chan_num].video_dev = NULL; - btcx_riscmem_free(dev->pci, &dev->vidq[chan_num].stopper); + btcx_riscmem_free(dev->pci, + &dev->channels[chan_num].vidq.stopper); printk(KERN_WARNING "device %d released!\n", chan_num); } } -int cx25821_video_register(struct cx25821_dev *dev, int chan_num, - struct video_device *video_template) +int cx25821_video_register(struct cx25821_dev *dev) { int err; + int i; + + struct video_device cx25821_video_device = { + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, + }; spin_lock_init(&dev->slock); - //printk(KERN_WARNING "Channel %d\n", chan_num); + for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; ++i) { + cx25821_init_controls(dev, i); -#ifdef TUNER_FLAG - dev->tvnorm = video_template->current_norm; -#endif + cx25821_risc_stopper(dev->pci, + &dev->channels[i].vidq.stopper, + dev->channels[i].sram_channels->dma_ctl, + 0x11, 0); + + dev->channels[i].sram_channels = &cx25821_sram_channels[i]; + dev->channels[i].video_dev = NULL; + dev->channels[i].resources = 0; + + cx_write(dev->channels[i].sram_channels->int_stat, + 0xffffffff); + + INIT_LIST_HEAD(&dev->channels[i].vidq.active); + INIT_LIST_HEAD(&dev->channels[i].vidq.queued); + + dev->channels[i].timeout_data.dev = dev; + dev->channels[i].timeout_data.channel = + &cx25821_sram_channels[i]; + dev->channels[i].vidq.timeout.function = + cx25821_vid_timeout; + dev->channels[i].vidq.timeout.data = + (unsigned long)&dev->channels[i].timeout_data; + init_timer(&dev->channels[i].vidq.timeout); + + /* register v4l devices */ + dev->channels[i].video_dev = cx25821_vdev_init(dev, + dev->pci, &cx25821_video_device, "video"); + + err = video_register_device(dev->channels[i].video_dev, + VFL_TYPE_GRABBER, video_nr[dev->nr]); + + if (err < 0) + goto fail_unreg; - /* init video dma queues */ - dev->timeout_data[chan_num].dev = dev; - dev->timeout_data[chan_num].channel = &dev->sram_channels[chan_num]; - INIT_LIST_HEAD(&dev->vidq[chan_num].active); - INIT_LIST_HEAD(&dev->vidq[chan_num].queued); - dev->vidq[chan_num].timeout.function = cx25821_vid_timeout; - dev->vidq[chan_num].timeout.data = - (unsigned long)&dev->timeout_data[chan_num]; - init_timer(&dev->vidq[chan_num].timeout); - cx25821_risc_stopper(dev->pci, &dev->vidq[chan_num].stopper, - dev->sram_channels[chan_num].dma_ctl, 0x11, 0); - - /* register v4l devices */ - dev->video_dev[chan_num] = - cx25821_vdev_init(dev, dev->pci, video_template, "video"); - err = - video_register_device(dev->video_dev[chan_num], VFL_TYPE_GRABBER, - video_nr[dev->nr]); - - if (err < 0) { - goto fail_unreg; } - //set PCI interrupt + + /* set PCI interrupt */ cx_set(PCI_INT_MSK, 0xff); /* initial device configuration */ mutex_lock(&dev->lock); #ifdef TUNER_FLAG + dev->tvnorm = cx25821_video_device.current_norm; cx25821_set_tvnorm(dev, dev->tvnorm); #endif mutex_unlock(&dev->lock); - init_controls(dev, chan_num); - return 0; + return 0; - fail_unreg: - cx25821_video_unregister(dev, chan_num); +fail_unreg: + cx25821_video_unregister(dev, i); return err; } @@ -533,7 +564,7 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, u32 line0_offset, line1_offset; struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); int bpl_local = LINE_SIZE_D1; - int channel_opened = 0; + int channel_opened = fh->channel_id; BUG_ON(NULL == fh->fmt); if (fh->width < 48 || fh->width > 720 || @@ -572,26 +603,29 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, channel_opened = (channel_opened < 0 || channel_opened > 7) ? 7 : channel_opened; - if (dev->pixel_formats[channel_opened] == PIXEL_FRMT_411) + if (dev->channels[channel_opened] + .pixel_formats == PIXEL_FRMT_411) buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3; else buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width); - if (dev->pixel_formats[channel_opened] == PIXEL_FRMT_411) { + if (dev->channels[channel_opened] + .pixel_formats == PIXEL_FRMT_411) { bpl_local = buf->bpl; } else { - bpl_local = buf->bpl; //Default + bpl_local = buf->bpl; /* Default */ if (channel_opened >= 0 && channel_opened <= 7) { - if (dev->use_cif_resolution[channel_opened]) { + if (dev->channels[channel_opened] + .use_cif_resolution) { if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) bpl_local = 352 << 1; else bpl_local = - dev-> - cif_width[channel_opened] << - 1; + dev->channels[channel_opened]. + cif_width << + 1; } } } @@ -685,6 +719,383 @@ int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma) return videobuf_mmap_mapper(get_queue(fh), vma); } + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->channels[fh->channel_id].vidq; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, + buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, + dev->channels[fh->channel_id]. + sram_channels); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + dprintk(2, + "[%p/%d] buffer_queue - first active, buf cnt = %d, \ + q->count = %d\n", + buf, buf->vb.i, buf->count, q->count); + } else { + prev = + list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width + && prev->vb.height == buf->vb.height + && prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, + "[%p/%d] buffer_queue - append to active, \ + buf->count=%d\n", + buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, + buf->vb.i); + } + } + + if (list_empty(&q->active)) + dprintk(2, "active queue empty!\n"); +} + +static struct videobuf_queue_ops cx25821_video_qops = { + .buf_setup = cx25821_buffer_setup, + .buf_prepare = cx25821_buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = cx25821_buffer_release, +}; + +static int video_open(struct file *file) +{ + struct video_device *vdev = video_devdata(file); + struct cx25821_dev *h, *dev = video_drvdata(file); + struct cx25821_fh *fh; + struct list_head *list; + int minor = video_devdata(file)->minor; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + u32 pix_format; + int ch_id = 0; + int i; + + dprintk(1, "open dev=%s type=%s\n", + video_device_node_name(vdev), + v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) + return -ENOMEM; + + lock_kernel(); + + list_for_each(list, &cx25821_devlist) + { + h = list_entry(list, struct cx25821_dev, devlist); + + for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) { + if (h->channels[i].video_dev && + h->channels[i].video_dev->minor == minor) { + dev = h; + ch_id = i; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + } + + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } + + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + fh->channel_id = ch_id; + + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = fh->channel_id; + pix_format = + (dev->channels[ch_id].pixel_formats == + PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), fh); + + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); + + return 0; +} + +static ssize_t video_read(struct file *file, char __user * data, size_t count, + loff_t *ppos) +{ + struct cx25821_fh *fh = file->private_data; + + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (cx25821_res_locked(fh, RESOURCE_VIDEO0)) + return -EBUSY; + + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); + + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (cx25821_res_check(fh, RESOURCE_VIDEO0)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { + if (buf->vb.state == VIDEOBUF_DONE) { + struct cx25821_dev *dev = fh->dev; + + if (dev && dev->channels[fh->channel_id] + .use_cif_resolution) { + u8 cam_id = *((char *)buf->vb.baddr + 3); + memcpy((char *)buf->vb.baddr, + (char *)buf->vb.baddr + (fh->width * 2), + (fh->width * 2)); + *((char *)buf->vb.baddr + 3) = cam_id; + } + } + + return POLLIN | POLLRDNORM; + } + + return 0; +} + +static int video_release(struct file *file) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + + /* stop the risc engine and fifo */ + cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */ + + /* stop video capture */ + if (cx25821_res_check(fh, RESOURCE_VIDEO0)) { + videobuf_queue_cancel(&fh->vidq); + cx25821_res_free(dev, fh, RESOURCE_VIDEO0); + } + + if (fh->vidq.read_buf) { + cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + videobuf_mmap_free(&fh->vidq); + + v4l2_prio_close(&dev->channels[fh->channel_id].prio, fh->prio); + file->private_data = NULL; + kfree(fh); + + return 0; +} + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + return -EINVAL; + + if (unlikely(i != fh->type)) + return -EINVAL; + + if (unlikely(!cx25821_res_get(dev, fh, + cx25821_get_resource(fh, RESOURCE_VIDEO0)))) + return -EBUSY; + + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = cx25821_get_resource(fh, RESOURCE_VIDEO0); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + cx25821_res_free(dev, fh, res); + return 0; +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = PIXEL_FRMT_422; + + if (fh) { + err = v4l2_prio_check(&dev->channels[fh->channel_id] + .prio, fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); + + if (0 != err) + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + /* check if width and height is valid based on set standard */ + if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) + fh->width = f->fmt.pix.width; + + if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) + fh->height = f->fmt.pix.height; + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format(dev, SRAM_CH00, pix_format); + + /* check if cif resolution */ + if (fh->width == 320 || fh->width == 352) + dev->channels[fh->channel_id].use_cif_resolution = 1; + else + dev->channels[fh->channel_id].use_cif_resolution = 0; + + dev->channels[fh->channel_id].cif_width = fh->width; + medusa_set_resolution(dev, fh->width, SRAM_CH00); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + + p->sequence = dev->channels[fh->channel_id].vidq.count; + + return ret_val; +} + +static int vidioc_log_status(struct file *file, void *priv) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + struct cx25821_fh *fh = priv; + char name[32 + 2]; + + struct sram_channel *sram_ch = dev->channels[fh->channel_id] + .sram_channels; + u32 tmp = 0; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + dev->name); + cx25821_call_all(dev, core, log_status); + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 0 is %s\n", + (tmp & 0x11) ? "streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->channels[fh->channel_id] + .prio, fh->prio); + if (0 != err) + return err; + } + + return cx25821_set_control(dev, ctl, fh->channel_id); +} + /* VIDEO IOCTLS */ int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { @@ -822,8 +1233,9 @@ int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) int cx25821_vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p) { struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; + struct cx25821_fh *fh = f; - *p = v4l2_prio_max(&dev->prio); + *p = v4l2_prio_max(&dev->channels[fh->channel_id].prio); return 0; } @@ -833,7 +1245,8 @@ int cx25821_vidioc_s_priority(struct file *file, void *f, enum v4l2_priority pri struct cx25821_fh *fh = f; struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; - return v4l2_prio_change(&dev->prio, &fh->prio, prio); + return v4l2_prio_change(&dev->channels[fh->channel_id] + .prio, &fh->prio, prio); } #ifdef TUNER_FLAG @@ -846,7 +1259,8 @@ int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms) dprintk(1, "%s()\n", __func__); if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); + err = v4l2_prio_check(&dev->channels[fh->channel_id] + .prio, fh->prio); if (0 != err) return err; } @@ -916,7 +1330,8 @@ int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i) dprintk(1, "%s(%d)\n", __func__, i); if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); + err = v4l2_prio_check(&dev->channels[fh->channel_id] + .prio, fh->prio); if (0 != err) return err; } @@ -967,9 +1382,14 @@ int cx25821_vidioc_s_frequency(struct file *file, void *priv, struct v4l2_freque int err; if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); + dev = fh->dev; + err = v4l2_prio_check(&dev->channels[fh->channel_id] + .prio, fh->prio); if (0 != err) return err; + } else { + printk(KERN_ERR "Invalid fh pointer!\n"); + return -EINVAL; } return cx25821_set_freq(dev, f); @@ -1031,7 +1451,8 @@ int cx25821_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) int err; if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); + err = v4l2_prio_check(&dev->channels[fh->channel_id] + .prio, fh->prio); if (0 != err) return err; } @@ -1046,7 +1467,7 @@ int cx25821_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) } #endif -// ****************************************************************************************** +/*****************************************************************************/ static const struct v4l2_queryctrl no_ctl = { .name = "42", .flags = V4L2_CTRL_FLAG_DISABLED, @@ -1129,6 +1550,7 @@ static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id) int cx25821_vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) { struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + struct cx25821_fh *fh = priv; const struct v4l2_queryctrl *ctrl; @@ -1138,16 +1560,16 @@ int cx25821_vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ct return -EINVAL; switch (ctl->id) { case V4L2_CID_BRIGHTNESS: - ctl->value = dev->ctl_bright; + ctl->value = dev->channels[fh->channel_id].ctl_bright; break; case V4L2_CID_HUE: - ctl->value = dev->ctl_hue; + ctl->value = dev->channels[fh->channel_id].ctl_hue; break; case V4L2_CID_CONTRAST: - ctl->value = dev->ctl_contrast; + ctl->value = dev->channels[fh->channel_id].ctl_contrast; break; case V4L2_CID_SATURATION: - ctl->value = dev->ctl_saturation; + ctl->value = dev->channels[fh->channel_id].ctl_saturation; break; } return 0; @@ -1181,19 +1603,19 @@ int cx25821_set_control(struct cx25821_dev *dev, switch (ctl->id) { case V4L2_CID_BRIGHTNESS: - dev->ctl_bright = ctl->value; + dev->channels[chan_num].ctl_bright = ctl->value; medusa_set_brightness(dev, ctl->value, chan_num); break; case V4L2_CID_HUE: - dev->ctl_hue = ctl->value; + dev->channels[chan_num].ctl_hue = ctl->value; medusa_set_hue(dev, ctl->value, chan_num); break; case V4L2_CID_CONTRAST: - dev->ctl_contrast = ctl->value; + dev->channels[chan_num].ctl_contrast = ctl->value; medusa_set_contrast(dev, ctl->value, chan_num); break; case V4L2_CID_SATURATION: - dev->ctl_saturation = ctl->value; + dev->channels[chan_num].ctl_saturation = ctl->value; medusa_set_saturation(dev, ctl->value, chan_num); break; } @@ -1203,7 +1625,7 @@ int cx25821_set_control(struct cx25821_dev *dev, return err; } -static void init_controls(struct cx25821_dev *dev, int chan_num) +static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num) { struct v4l2_control ctrl; int i; @@ -1239,23 +1661,24 @@ int cx25821_vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop) int err; if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); + err = v4l2_prio_check(&dev->channels[fh->channel_id]. + prio, fh->prio); if (0 != err) return err; } - // cx25821_vidioc_s_crop not supported + /* cx25821_vidioc_s_crop not supported */ return -EINVAL; } int cx25821_vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) { - // cx25821_vidioc_g_crop not supported + /* cx25821_vidioc_g_crop not supported */ return -EINVAL; } int cx25821_vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm) { - // medusa does not support video standard sensing of current input + /* medusa does not support video standard sensing of current input */ *norm = CX25821_NORMS; return 0; @@ -1297,3 +1720,325 @@ int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm) return 0; } + +static long video_ioctl_upstream9(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + int command = 0; + struct upstream_user_struct *data_from_user; + + data_from_user = (struct upstream_user_struct *)arg; + + if (!data_from_user) { + printk + ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", + __func__); + return 0; + } + + command = data_from_user->command; + + if (command != UPSTREAM_START_VIDEO && + command != UPSTREAM_STOP_VIDEO) + return 0; + + dev->input_filename = data_from_user->input_filename; + dev->input_audiofilename = data_from_user->input_filename; + dev->vid_stdname = data_from_user->vid_stdname; + dev->pixel_format = data_from_user->pixel_format; + dev->channel_select = data_from_user->channel_select; + dev->command = data_from_user->command; + + switch (command) { + case UPSTREAM_START_VIDEO: + cx25821_start_upstream_video_ch1(dev, data_from_user); + break; + + case UPSTREAM_STOP_VIDEO: + cx25821_stop_upstream_video_ch1(dev); + break; + } + + return 0; +} + +static long video_ioctl_upstream10(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + int command = 0; + struct upstream_user_struct *data_from_user; + + data_from_user = (struct upstream_user_struct *)arg; + + if (!data_from_user) { + printk + ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", + __func__); + return 0; + } + + command = data_from_user->command; + + if (command != UPSTREAM_START_VIDEO && + command != UPSTREAM_STOP_VIDEO) + return 0; + + dev->input_filename_ch2 = data_from_user->input_filename; + dev->input_audiofilename = data_from_user->input_filename; + dev->vid_stdname_ch2 = data_from_user->vid_stdname; + dev->pixel_format_ch2 = data_from_user->pixel_format; + dev->channel_select_ch2 = data_from_user->channel_select; + dev->command_ch2 = data_from_user->command; + + switch (command) { + case UPSTREAM_START_VIDEO: + cx25821_start_upstream_video_ch2(dev, data_from_user); + break; + + case UPSTREAM_STOP_VIDEO: + cx25821_stop_upstream_video_ch2(dev); + break; + } + + return 0; +} + +static long video_ioctl_upstream11(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + int command = 0; + struct upstream_user_struct *data_from_user; + + data_from_user = (struct upstream_user_struct *)arg; + + if (!data_from_user) { + printk + ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", + __func__); + return 0; + } + + command = data_from_user->command; + + if (command != UPSTREAM_START_AUDIO && + command != UPSTREAM_STOP_AUDIO) + return 0; + + dev->input_filename = data_from_user->input_filename; + dev->input_audiofilename = data_from_user->input_filename; + dev->vid_stdname = data_from_user->vid_stdname; + dev->pixel_format = data_from_user->pixel_format; + dev->channel_select = data_from_user->channel_select; + dev->command = data_from_user->command; + + switch (command) { + case UPSTREAM_START_AUDIO: + cx25821_start_upstream_audio(dev, data_from_user); + break; + + case UPSTREAM_STOP_AUDIO: + cx25821_stop_upstream_audio(dev); + break; + } + + return 0; +} + +static long video_ioctl_set(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + struct downstream_user_struct *data_from_user; + int command; + int width = 720; + int selected_channel = 0, pix_format = 0, i = 0; + int cif_enable = 0, cif_width = 0; + u32 value = 0; + + data_from_user = (struct downstream_user_struct *)arg; + + if (!data_from_user) { + printk( + "cx25821 in %s(): User data is INVALID. Returning.\n", + __func__); + return 0; + } + + command = data_from_user->command; + + if (command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT + && command != ENABLE_CIF_RESOLUTION && command != REG_READ + && command != REG_WRITE && command != MEDUSA_READ + && command != MEDUSA_WRITE) { + return 0; + } + + switch (command) { + case SET_VIDEO_STD: + dev->tvnorm = + !strcmp(data_from_user->vid_stdname, + "PAL") ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; + medusa_set_videostandard(dev); + break; + + case SET_PIXEL_FORMAT: + selected_channel = data_from_user->decoder_select; + pix_format = data_from_user->pixel_format; + + if (!(selected_channel <= 7 && selected_channel >= 0)) { + selected_channel -= 4; + selected_channel = selected_channel % 8; + } + + if (selected_channel >= 0) + cx25821_set_pixel_format(dev, selected_channel, + pix_format); + + break; + + case ENABLE_CIF_RESOLUTION: + selected_channel = data_from_user->decoder_select; + cif_enable = data_from_user->cif_resolution_enable; + cif_width = data_from_user->cif_width; + + if (cif_enable) { + if (dev->tvnorm & V4L2_STD_PAL_BG + || dev->tvnorm & V4L2_STD_PAL_DK) + width = 352; + else + width = (cif_width == 320 + || cif_width == 352) ? cif_width : 320; + } + + if (!(selected_channel <= 7 && selected_channel >= 0)) { + selected_channel -= 4; + selected_channel = selected_channel % 8; + } + + if (selected_channel <= 7 && selected_channel >= 0) { + dev->channels[selected_channel]. + use_cif_resolution = cif_enable; + dev->channels[selected_channel].cif_width = width; + } else { + for (i = 0; i < VID_CHANNEL_NUM; i++) { + dev->channels[i].use_cif_resolution = + cif_enable; + dev->channels[i].cif_width = width; + } + } + + medusa_set_resolution(dev, width, selected_channel); + break; + case REG_READ: + data_from_user->reg_data = cx_read(data_from_user->reg_address); + break; + case REG_WRITE: + cx_write(data_from_user->reg_address, data_from_user->reg_data); + break; + case MEDUSA_READ: + value = + cx25821_i2c_read(&dev->i2c_bus[0], + (u16) data_from_user->reg_address, + &data_from_user->reg_data); + break; + case MEDUSA_WRITE: + cx25821_i2c_write(&dev->i2c_bus[0], + (u16) data_from_user->reg_address, + data_from_user->reg_data); + break; + } + + return 0; +} + +static long cx25821_video_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + int ret = 0; + + struct cx25821_fh *fh = file->private_data; + + /* check to see if it's the video upstream */ + if (fh->channel_id == SRAM_CH09) { + ret = video_ioctl_upstream9(file, cmd, arg); + return ret; + } else if (fh->channel_id == SRAM_CH10) { + ret = video_ioctl_upstream10(file, cmd, arg); + return ret; + } else if (fh->channel_id == SRAM_CH11) { + ret = video_ioctl_upstream11(file, cmd, arg); + ret = video_ioctl_set(file, cmd, arg); + return ret; + } + + return video_ioctl2(file, cmd, arg); +} + +/* exported stuff */ +static const struct v4l2_file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = cx25821_video_mmap, + .ioctl = cx25821_video_ioctl, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = cx25821_vidioc_querycap, + .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = cx25821_vidioc_reqbufs, + .vidioc_querybuf = cx25821_vidioc_querybuf, + .vidioc_qbuf = cx25821_vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, +#ifdef TUNER_FLAG + .vidioc_s_std = cx25821_vidioc_s_std, + .vidioc_querystd = cx25821_vidioc_querystd, +#endif + .vidioc_cropcap = cx25821_vidioc_cropcap, + .vidioc_s_crop = cx25821_vidioc_s_crop, + .vidioc_g_crop = cx25821_vidioc_g_crop, + .vidioc_enum_input = cx25821_vidioc_enum_input, + .vidioc_g_input = cx25821_vidioc_g_input, + .vidioc_s_input = cx25821_vidioc_s_input, + .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = cx25821_vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = cx25821_vidioc_g_priority, + .vidioc_s_priority = cx25821_vidioc_s_priority, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = cx25821_vidiocgmbuf, +#endif +#ifdef TUNER_FLAG + .vidioc_g_tuner = cx25821_vidioc_g_tuner, + .vidioc_s_tuner = cx25821_vidioc_s_tuner, + .vidioc_g_frequency = cx25821_vidioc_g_frequency, + .vidioc_s_frequency = cx25821_vidioc_s_frequency, +#endif +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = cx25821_vidioc_g_register, + .vidioc_s_register = cx25821_vidioc_s_register, +#endif +}; + +struct video_device cx25821_videoioctl_template = { + .name = "cx25821-videoioctl", + .fops = &video_fops, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; diff --git a/drivers/staging/cx25821/cx25821-video.h b/drivers/staging/cx25821/cx25821-video.h index 0bddc02be57d..cc6034b1a95d 100644 --- a/drivers/staging/cx25821/cx25821-video.h +++ b/drivers/staging/cx25821/cx25821-video.h @@ -54,7 +54,7 @@ printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ } while (0) -//For IOCTL to identify running upstream +/* For IOCTL to identify running upstream */ #define UPSTREAM_START_VIDEO 700 #define UPSTREAM_STOP_VIDEO 701 #define UPSTREAM_START_AUDIO 702 @@ -80,19 +80,8 @@ extern struct sram_channel *channel7; extern struct sram_channel *channel9; extern struct sram_channel *channel10; extern struct sram_channel *channel11; -extern struct video_device cx25821_video_template0; -extern struct video_device cx25821_video_template1; -extern struct video_device cx25821_video_template2; -extern struct video_device cx25821_video_template3; -extern struct video_device cx25821_video_template4; -extern struct video_device cx25821_video_template5; -extern struct video_device cx25821_video_template6; -extern struct video_device cx25821_video_template7; -extern struct video_device cx25821_video_template9; -extern struct video_device cx25821_video_template10; -extern struct video_device cx25821_video_template11; extern struct video_device cx25821_videoioctl_template; -//extern const u32 *ctrl_classes[]; +/* extern const u32 *ctrl_classes[]; */ extern unsigned int vid_limit; @@ -113,7 +102,7 @@ extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm); extern int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit); extern int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit); -extern int cx25821_res_locked(struct cx25821_dev *dev, unsigned int bit); +extern int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit); extern void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits); extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input); @@ -126,8 +115,7 @@ extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width, unsigned int height, enum v4l2_field field); extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status); extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num); -extern int cx25821_video_register(struct cx25821_dev *dev, int chan_num, - struct video_device *video_template); +extern int cx25821_video_register(struct cx25821_dev *dev); extern int cx25821_get_format_size(void); extern int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count, diff --git a/drivers/staging/cx25821/cx25821-video0.c b/drivers/staging/cx25821/cx25821-video0.c deleted file mode 100644 index 0be2cc15d856..000000000000 --- a/drivers/staging/cx25821/cx25821-video0.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> - * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "cx25821-video.h" - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH00]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, - buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, - &dev->sram_channels[SRAM_CH00]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - dprintk(2, - "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb.i, buf->count, q->count); - } else { - prev = - list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width - && prev->vb.height == buf->vb.height - && prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, - "[%p/%d] buffer_queue - append to active, buf->count=%d\n", - buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, - buf->vb.i); - } - } - - if (list_empty(&q->active)) { - dprintk(2, "active queue empty!\n"); - } -} - -static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = cx25821_buffer_setup, - .buf_prepare = cx25821_buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = cx25821_buffer_release, -}; - -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx25821_dev *dev = video_drvdata(file); - struct cx25821_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - u32 pix_format; - - printk("open dev=%s type=%s\n", video_device_node_name(vdev), - v4l2_type_names[type]); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - - lock_kernel(); - - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH00; - pix_format = - (dev->pixel_formats[dev->channel_opened] == - PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio, &fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; -} - -static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t * ppos) -{ - struct cx25821_fh *fh = file->private_data; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO0)) - return -EBUSY; - - return videobuf_read_one(&fh->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - - default: - BUG(); - return 0; - } -} - -static unsigned int video_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (cx25821_res_check(fh, RESOURCE_VIDEO0)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { - if (buf->vb.state == VIDEOBUF_DONE) { - struct cx25821_dev *dev = fh->dev; - - if (dev && dev->use_cif_resolution[SRAM_CH00]) { - u8 cam_id = *((char *)buf->vb.baddr + 3); - memcpy((char *)buf->vb.baddr, - (char *)buf->vb.baddr + (fh->width * 2), - (fh->width * 2)); - *((char *)buf->vb.baddr + 3) = cam_id; - } - } - - return POLLIN | POLLRDNORM; - } - - return 0; -} - -static int video_release(struct file *file) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - - //stop the risc engine and fifo - cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */ - - /* stop video capture */ - if (cx25821_res_check(fh, RESOURCE_VIDEO0)) { - videobuf_queue_cancel(&fh->vidq); - cx25821_res_free(dev, fh, RESOURCE_VIDEO0); - } - - if (fh->vidq.read_buf) { - cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } - - videobuf_mmap_free(&fh->vidq); - - v4l2_prio_close(&dev->prio, fh->prio); - file->private_data = NULL; - kfree(fh); - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; - } - - if (unlikely(i != fh->type)) { - return -EINVAL; - } - - if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO0)))) { - return -EBUSY; - } - - return videobuf_streamon(get_queue(fh)); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = cx25821_get_resource(fh, RESOURCE_VIDEO0); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - cx25821_res_free(dev, fh, res); - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = PIXEL_FRMT_422; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; - } - - if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format(dev, SRAM_CH00, pix_format); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH00] = 1; - } else { - dev->use_cif_resolution[SRAM_CH00] = 0; - } - dev->cif_width[SRAM_CH00] = fh->width; - medusa_set_resolution(dev, fh->width, SRAM_CH00); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, - fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - - p->sequence = dev->vidq[SRAM_CH00].count; - - return ret_val; -} - -static int vidioc_log_status(struct file *file, void *priv) -{ - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; - - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH00]; - u32 tmp = 0; - - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", - dev->name); - cx25821_call_all(dev, core, log_status); - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 0 is %s\n", - (tmp & 0x11) ? "streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", - dev->name); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - return cx25821_set_control(dev, ctl, SRAM_CH00); -} - -// exported stuff -static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = cx25821_video_mmap, - .ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = cx25821_vidioc_querycap, - .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = cx25821_vidioc_reqbufs, - .vidioc_querybuf = cx25821_vidioc_querybuf, - .vidioc_qbuf = cx25821_vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -#ifdef TUNER_FLAG - .vidioc_s_std = cx25821_vidioc_s_std, - .vidioc_querystd = cx25821_vidioc_querystd, -#endif - .vidioc_cropcap = cx25821_vidioc_cropcap, - .vidioc_s_crop = cx25821_vidioc_s_crop, - .vidioc_g_crop = cx25821_vidioc_g_crop, - .vidioc_enum_input = cx25821_vidioc_enum_input, - .vidioc_g_input = cx25821_vidioc_g_input, - .vidioc_s_input = cx25821_vidioc_s_input, - .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = cx25821_vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = cx25821_vidioc_g_priority, - .vidioc_s_priority = cx25821_vidioc_s_priority, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = cx25821_vidiocgmbuf, -#endif -#ifdef TUNER_FLAG - .vidioc_g_tuner = cx25821_vidioc_g_tuner, - .vidioc_s_tuner = cx25821_vidioc_s_tuner, - .vidioc_g_frequency = cx25821_vidioc_g_frequency, - .vidioc_s_frequency = cx25821_vidioc_s_frequency, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = cx25821_vidioc_g_register, - .vidioc_s_register = cx25821_vidioc_s_register, -#endif -}; - -struct video_device cx25821_video_template0 = { - .name = "cx25821-video", - .fops = &video_fops, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, -}; diff --git a/drivers/staging/cx25821/cx25821-video1.c b/drivers/staging/cx25821/cx25821-video1.c deleted file mode 100644 index b0bae627bfb1..000000000000 --- a/drivers/staging/cx25821/cx25821-video1.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> - * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "cx25821-video.h" - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH01]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, - buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, - &dev->sram_channels[SRAM_CH01]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - dprintk(2, - "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb.i, buf->count, q->count); - } else { - prev = - list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width - && prev->vb.height == buf->vb.height - && prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, - "[%p/%d] buffer_queue - append to active, buf->count=%d\n", - buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, - buf->vb.i); - } - } - - if (list_empty(&q->active)) { - dprintk(2, "active queue empty!\n"); - } -} - -static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = cx25821_buffer_setup, - .buf_prepare = cx25821_buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = cx25821_buffer_release, -}; - -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx25821_dev *dev = video_drvdata(file); - struct cx25821_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - u32 pix_format; - - printk("open dev=%s type=%s\n", video_device_node_name(vdev), - v4l2_type_names[type]); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - - lock_kernel(); - - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH01; - pix_format = - (dev->pixel_formats[dev->channel_opened] == - PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio, &fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; -} - -static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t * ppos) -{ - struct cx25821_fh *fh = file->private_data; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO1)) - return -EBUSY; - - return videobuf_read_one(&fh->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - - default: - BUG(); - return 0; - } -} - -static unsigned int video_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (cx25821_res_check(fh, RESOURCE_VIDEO1)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { - if (buf->vb.state == VIDEOBUF_DONE) { - struct cx25821_dev *dev = fh->dev; - - if (dev && dev->use_cif_resolution[SRAM_CH01]) { - u8 cam_id = *((char *)buf->vb.baddr + 3); - memcpy((char *)buf->vb.baddr, - (char *)buf->vb.baddr + (fh->width * 2), - (fh->width * 2)); - *((char *)buf->vb.baddr + 3) = cam_id; - } - } - - return POLLIN | POLLRDNORM; - } - - return 0; -} - -static int video_release(struct file *file) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - - //stop the risc engine and fifo - cx_write(channel1->dma_ctl, 0); /* FIFO and RISC disable */ - - /* stop video capture */ - if (cx25821_res_check(fh, RESOURCE_VIDEO1)) { - videobuf_queue_cancel(&fh->vidq); - cx25821_res_free(dev, fh, RESOURCE_VIDEO1); - } - - if (fh->vidq.read_buf) { - cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } - - videobuf_mmap_free(&fh->vidq); - - v4l2_prio_close(&dev->prio, fh->prio); - file->private_data = NULL; - kfree(fh); - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; - } - - if (unlikely(i != fh->type)) { - return -EINVAL; - } - - if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO1)))) { - return -EBUSY; - } - - return videobuf_streamon(get_queue(fh)); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = cx25821_get_resource(fh, RESOURCE_VIDEO1); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - cx25821_res_free(dev, fh, res); - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; - } - - if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format(dev, SRAM_CH01, pix_format); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH01] = 1; - } else { - dev->use_cif_resolution[SRAM_CH01] = 0; - } - dev->cif_width[SRAM_CH01] = fh->width; - medusa_set_resolution(dev, fh->width, SRAM_CH01); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, - fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - - p->sequence = dev->vidq[SRAM_CH01].count; - - return ret_val; -} - -static int vidioc_log_status(struct file *file, void *priv) -{ - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; - - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH01]; - u32 tmp = 0; - - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", - dev->name); - cx25821_call_all(dev, core, log_status); - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 1 is %s\n", - (tmp & 0x11) ? "streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", - dev->name); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - return cx25821_set_control(dev, ctl, SRAM_CH01); -} - -//exported stuff -static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = cx25821_video_mmap, - .ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = cx25821_vidioc_querycap, - .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = cx25821_vidioc_reqbufs, - .vidioc_querybuf = cx25821_vidioc_querybuf, - .vidioc_qbuf = cx25821_vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -#ifdef TUNER_FLAG - .vidioc_s_std = cx25821_vidioc_s_std, - .vidioc_querystd = cx25821_vidioc_querystd, -#endif - .vidioc_cropcap = cx25821_vidioc_cropcap, - .vidioc_s_crop = cx25821_vidioc_s_crop, - .vidioc_g_crop = cx25821_vidioc_g_crop, - .vidioc_enum_input = cx25821_vidioc_enum_input, - .vidioc_g_input = cx25821_vidioc_g_input, - .vidioc_s_input = cx25821_vidioc_s_input, - .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = cx25821_vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = cx25821_vidioc_g_priority, - .vidioc_s_priority = cx25821_vidioc_s_priority, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = cx25821_vidiocgmbuf, -#endif -#ifdef TUNER_FLAG - .vidioc_g_tuner = cx25821_vidioc_g_tuner, - .vidioc_s_tuner = cx25821_vidioc_s_tuner, - .vidioc_g_frequency = cx25821_vidioc_g_frequency, - .vidioc_s_frequency = cx25821_vidioc_s_frequency, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = cx25821_vidioc_g_register, - .vidioc_s_register = cx25821_vidioc_s_register, -#endif -}; - -struct video_device cx25821_video_template1 = { - .name = "cx25821-video", - .fops = &video_fops, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, -}; diff --git a/drivers/staging/cx25821/cx25821-video2.c b/drivers/staging/cx25821/cx25821-video2.c deleted file mode 100644 index 400cdb80674e..000000000000 --- a/drivers/staging/cx25821/cx25821-video2.c +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> - * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "cx25821-video.h" - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH02]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, - buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, - &dev->sram_channels[SRAM_CH02]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - dprintk(2, - "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb.i, buf->count, q->count); - } else { - prev = - list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width - && prev->vb.height == buf->vb.height - && prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, - "[%p/%d] buffer_queue - append to active, buf->count=%d\n", - buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, - buf->vb.i); - } - } - - if (list_empty(&q->active)) { - dprintk(2, "active queue empty!\n"); - } -} - -static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = cx25821_buffer_setup, - .buf_prepare = cx25821_buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = cx25821_buffer_release, -}; - -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx25821_dev *dev = video_drvdata(file); - struct cx25821_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - u32 pix_format; - - printk("open dev=%s type=%s\n", video_device_node_name(vdev), - v4l2_type_names[type]); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - - lock_kernel(); - - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH02; - pix_format = - (dev->pixel_formats[dev->channel_opened] == - PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio, &fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; -} - -static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t * ppos) -{ - struct cx25821_fh *fh = file->private_data; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO2)) - return -EBUSY; - - return videobuf_read_one(&fh->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - - default: - BUG(); - return 0; - } -} - -static unsigned int video_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (cx25821_res_check(fh, RESOURCE_VIDEO2)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { - if (buf->vb.state == VIDEOBUF_DONE) { - struct cx25821_dev *dev = fh->dev; - - if (dev && dev->use_cif_resolution[SRAM_CH02]) { - u8 cam_id = *((char *)buf->vb.baddr + 3); - memcpy((char *)buf->vb.baddr, - (char *)buf->vb.baddr + (fh->width * 2), - (fh->width * 2)); - *((char *)buf->vb.baddr + 3) = cam_id; - } - } - - return POLLIN | POLLRDNORM; - } - - return 0; -} - -static int video_release(struct file *file) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - - //stop the risc engine and fifo - cx_write(channel2->dma_ctl, 0); /* FIFO and RISC disable */ - - /* stop video capture */ - if (cx25821_res_check(fh, RESOURCE_VIDEO2)) { - videobuf_queue_cancel(&fh->vidq); - cx25821_res_free(dev, fh, RESOURCE_VIDEO2); - } - - if (fh->vidq.read_buf) { - cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } - - videobuf_mmap_free(&fh->vidq); - - v4l2_prio_close(&dev->prio, fh->prio); - file->private_data = NULL; - kfree(fh); - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; - } - - if (unlikely(i != fh->type)) { - return -EINVAL; - } - - if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO2)))) { - return -EBUSY; - } - - return videobuf_streamon(get_queue(fh)); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = cx25821_get_resource(fh, RESOURCE_VIDEO2); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - cx25821_res_free(dev, fh, res); - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; - } - - if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format(dev, SRAM_CH02, pix_format); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH02] = 1; - } else { - dev->use_cif_resolution[SRAM_CH02] = 0; - } - dev->cif_width[SRAM_CH02] = fh->width; - medusa_set_resolution(dev, fh->width, SRAM_CH02); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, - fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - - p->sequence = dev->vidq[SRAM_CH02].count; - - return ret_val; -} - -static int vidioc_log_status(struct file *file, void *priv) -{ - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; - - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH02]; - u32 tmp = 0; - - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", - dev->name); - - cx25821_call_all(dev, core, log_status); - - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 2 is %s\n", - (tmp & 0x11) ? "streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", - dev->name); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - return cx25821_set_control(dev, ctl, SRAM_CH02); -} - -// exported stuff -static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = cx25821_video_mmap, - .ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = cx25821_vidioc_querycap, - .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = cx25821_vidioc_reqbufs, - .vidioc_querybuf = cx25821_vidioc_querybuf, - .vidioc_qbuf = cx25821_vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -#ifdef TUNER_FLAG - .vidioc_s_std = cx25821_vidioc_s_std, - .vidioc_querystd = cx25821_vidioc_querystd, -#endif - .vidioc_cropcap = cx25821_vidioc_cropcap, - .vidioc_s_crop = cx25821_vidioc_s_crop, - .vidioc_g_crop = cx25821_vidioc_g_crop, - .vidioc_enum_input = cx25821_vidioc_enum_input, - .vidioc_g_input = cx25821_vidioc_g_input, - .vidioc_s_input = cx25821_vidioc_s_input, - .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = cx25821_vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = cx25821_vidioc_g_priority, - .vidioc_s_priority = cx25821_vidioc_s_priority, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = cx25821_vidiocgmbuf, -#endif -#ifdef TUNER_FLAG - .vidioc_g_tuner = cx25821_vidioc_g_tuner, - .vidioc_s_tuner = cx25821_vidioc_s_tuner, - .vidioc_g_frequency = cx25821_vidioc_g_frequency, - .vidioc_s_frequency = cx25821_vidioc_s_frequency, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = cx25821_vidioc_g_register, - .vidioc_s_register = cx25821_vidioc_s_register, -#endif -}; - -struct video_device cx25821_video_template2 = { - .name = "cx25821-video", - .fops = &video_fops, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, -}; diff --git a/drivers/staging/cx25821/cx25821-video3.c b/drivers/staging/cx25821/cx25821-video3.c deleted file mode 100644 index 3b216ed0906e..000000000000 --- a/drivers/staging/cx25821/cx25821-video3.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> - * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "cx25821-video.h" - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH03]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, - buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, - &dev->sram_channels[SRAM_CH03]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - dprintk(2, - "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb.i, buf->count, q->count); - } else { - prev = - list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width - && prev->vb.height == buf->vb.height - && prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, - "[%p/%d] buffer_queue - append to active, buf->count=%d\n", - buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, - buf->vb.i); - } - } - - if (list_empty(&q->active)) { - dprintk(2, "active queue empty!\n"); - } -} - -static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = cx25821_buffer_setup, - .buf_prepare = cx25821_buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = cx25821_buffer_release, -}; - -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx25821_dev *dev = video_drvdata(file); - struct cx25821_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - u32 pix_format; - - printk("open dev=%s type=%s\n", video_device_node_name(vdev), - v4l2_type_names[type]); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - - lock_kernel(); - - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH03; - pix_format = - (dev->pixel_formats[dev->channel_opened] == - PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio, &fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; -} - -static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t * ppos) -{ - struct cx25821_fh *fh = file->private_data; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO3)) - return -EBUSY; - - return videobuf_read_one(&fh->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - - default: - BUG(); - return 0; - } -} - -static unsigned int video_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (cx25821_res_check(fh, RESOURCE_VIDEO3)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { - if (buf->vb.state == VIDEOBUF_DONE) { - struct cx25821_dev *dev = fh->dev; - - if (dev && dev->use_cif_resolution[SRAM_CH03]) { - u8 cam_id = *((char *)buf->vb.baddr + 3); - memcpy((char *)buf->vb.baddr, - (char *)buf->vb.baddr + (fh->width * 2), - (fh->width * 2)); - *((char *)buf->vb.baddr + 3) = cam_id; - } - } - - return POLLIN | POLLRDNORM; - } - - return 0; -} - -static int video_release(struct file *file) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - - //stop the risc engine and fifo - cx_write(channel3->dma_ctl, 0); /* FIFO and RISC disable */ - - /* stop video capture */ - if (cx25821_res_check(fh, RESOURCE_VIDEO3)) { - videobuf_queue_cancel(&fh->vidq); - cx25821_res_free(dev, fh, RESOURCE_VIDEO3); - } - - if (fh->vidq.read_buf) { - cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } - - videobuf_mmap_free(&fh->vidq); - - v4l2_prio_close(&dev->prio, fh->prio); - file->private_data = NULL; - kfree(fh); - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; - } - - if (unlikely(i != fh->type)) { - return -EINVAL; - } - - if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO3)))) { - return -EBUSY; - } - - return videobuf_streamon(get_queue(fh)); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = cx25821_get_resource(fh, RESOURCE_VIDEO3); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - cx25821_res_free(dev, fh, res); - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; - } - - if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format(dev, SRAM_CH03, pix_format); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH03] = 1; - } else { - dev->use_cif_resolution[SRAM_CH03] = 0; - } - dev->cif_width[SRAM_CH03] = fh->width; - medusa_set_resolution(dev, fh->width, SRAM_CH03); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, - fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - - p->sequence = dev->vidq[SRAM_CH03].count; - - return ret_val; -} - -static int vidioc_log_status(struct file *file, void *priv) -{ - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; - - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH03]; - u32 tmp = 0; - - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", - dev->name); - cx25821_call_all(dev, core, log_status); - - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 3 is %s\n", - (tmp & 0x11) ? "streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", - dev->name); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - return cx25821_set_control(dev, ctl, SRAM_CH03); -} - -// exported stuff -static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = cx25821_video_mmap, - .ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = cx25821_vidioc_querycap, - .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = cx25821_vidioc_reqbufs, - .vidioc_querybuf = cx25821_vidioc_querybuf, - .vidioc_qbuf = cx25821_vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -#ifdef TUNER_FLAG - .vidioc_s_std = cx25821_vidioc_s_std, - .vidioc_querystd = cx25821_vidioc_querystd, -#endif - .vidioc_cropcap = cx25821_vidioc_cropcap, - .vidioc_s_crop = cx25821_vidioc_s_crop, - .vidioc_g_crop = cx25821_vidioc_g_crop, - .vidioc_enum_input = cx25821_vidioc_enum_input, - .vidioc_g_input = cx25821_vidioc_g_input, - .vidioc_s_input = cx25821_vidioc_s_input, - .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = cx25821_vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = cx25821_vidioc_g_priority, - .vidioc_s_priority = cx25821_vidioc_s_priority, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = cx25821_vidiocgmbuf, -#endif -#ifdef TUNER_FLAG - .vidioc_g_tuner = cx25821_vidioc_g_tuner, - .vidioc_s_tuner = cx25821_vidioc_s_tuner, - .vidioc_g_frequency = cx25821_vidioc_g_frequency, - .vidioc_s_frequency = cx25821_vidioc_s_frequency, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = cx25821_vidioc_g_register, - .vidioc_s_register = cx25821_vidioc_s_register, -#endif -}; - -struct video_device cx25821_video_template3 = { - .name = "cx25821-video", - .fops = &video_fops, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, -}; diff --git a/drivers/staging/cx25821/cx25821-video4.c b/drivers/staging/cx25821/cx25821-video4.c deleted file mode 100644 index f7b08c51868a..000000000000 --- a/drivers/staging/cx25821/cx25821-video4.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> - * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "cx25821-video.h" - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH04]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, - buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, - &dev->sram_channels[SRAM_CH04]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - dprintk(2, - "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb.i, buf->count, q->count); - } else { - prev = - list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width - && prev->vb.height == buf->vb.height - && prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, - "[%p/%d] buffer_queue - append to active, buf->count=%d\n", - buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, - buf->vb.i); - } - } - - if (list_empty(&q->active)) { - dprintk(2, "active queue empty!\n"); - } -} - -static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = cx25821_buffer_setup, - .buf_prepare = cx25821_buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = cx25821_buffer_release, -}; - -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx25821_dev *dev = video_drvdata(file); - struct cx25821_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - u32 pix_format; - - printk("open dev=%s type=%s\n", video_device_node_name(vdev), - v4l2_type_names[type]); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - - lock_kernel(); - - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH04; - pix_format = - (dev->pixel_formats[dev->channel_opened] == - PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio, &fh->prio); - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; -} - -static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t * ppos) -{ - struct cx25821_fh *fh = file->private_data; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO4)) - return -EBUSY; - - return videobuf_read_one(&fh->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - - default: - BUG(); - return 0; - } -} - -static unsigned int video_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (cx25821_res_check(fh, RESOURCE_VIDEO4)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { - if (buf->vb.state == VIDEOBUF_DONE) { - struct cx25821_dev *dev = fh->dev; - - if (dev && dev->use_cif_resolution[SRAM_CH04]) { - u8 cam_id = *((char *)buf->vb.baddr + 3); - memcpy((char *)buf->vb.baddr, - (char *)buf->vb.baddr + (fh->width * 2), - (fh->width * 2)); - *((char *)buf->vb.baddr + 3) = cam_id; - } - } - - return POLLIN | POLLRDNORM; - } - - return 0; -} - -static int video_release(struct file *file) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - - //stop the risc engine and fifo - cx_write(channel4->dma_ctl, 0); /* FIFO and RISC disable */ - - /* stop video capture */ - if (cx25821_res_check(fh, RESOURCE_VIDEO4)) { - videobuf_queue_cancel(&fh->vidq); - cx25821_res_free(dev, fh, RESOURCE_VIDEO4); - } - - if (fh->vidq.read_buf) { - cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } - - videobuf_mmap_free(&fh->vidq); - - v4l2_prio_close(&dev->prio, fh->prio); - file->private_data = NULL; - kfree(fh); - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; - } - - if (unlikely(i != fh->type)) { - return -EINVAL; - } - - if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO4)))) { - return -EBUSY; - } - - return videobuf_streamon(get_queue(fh)); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = cx25821_get_resource(fh, RESOURCE_VIDEO4); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - cx25821_res_free(dev, fh, res); - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - // check priority - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - dprintk(2, "%s()\n", __func__); - err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; - } - - if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format(dev, SRAM_CH04, pix_format); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH04] = 1; - } else { - dev->use_cif_resolution[SRAM_CH04] = 0; - } - dev->cif_width[SRAM_CH04] = fh->width; - medusa_set_resolution(dev, fh->width, SRAM_CH04); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, - fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - - p->sequence = dev->vidq[SRAM_CH04].count; - - return ret_val; -} - -static int vidioc_log_status(struct file *file, void *priv) -{ - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; - - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH04]; - u32 tmp = 0; - - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", - dev->name); - cx25821_call_all(dev, core, log_status); - - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 4 is %s\n", - (tmp & 0x11) ? "streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", - dev->name); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - return cx25821_set_control(dev, ctl, SRAM_CH04); -} - -// exported stuff -static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = cx25821_video_mmap, - .ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = cx25821_vidioc_querycap, - .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = cx25821_vidioc_reqbufs, - .vidioc_querybuf = cx25821_vidioc_querybuf, - .vidioc_qbuf = cx25821_vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -#ifdef TUNER_FLAG - .vidioc_s_std = cx25821_vidioc_s_std, - .vidioc_querystd = cx25821_vidioc_querystd, -#endif - .vidioc_cropcap = cx25821_vidioc_cropcap, - .vidioc_s_crop = cx25821_vidioc_s_crop, - .vidioc_g_crop = cx25821_vidioc_g_crop, - .vidioc_enum_input = cx25821_vidioc_enum_input, - .vidioc_g_input = cx25821_vidioc_g_input, - .vidioc_s_input = cx25821_vidioc_s_input, - .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = cx25821_vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = cx25821_vidioc_g_priority, - .vidioc_s_priority = cx25821_vidioc_s_priority, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = cx25821_vidiocgmbuf, -#endif -#ifdef TUNER_FLAG - .vidioc_g_tuner = cx25821_vidioc_g_tuner, - .vidioc_s_tuner = cx25821_vidioc_s_tuner, - .vidioc_g_frequency = cx25821_vidioc_g_frequency, - .vidioc_s_frequency = cx25821_vidioc_s_frequency, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = cx25821_vidioc_g_register, - .vidioc_s_register = cx25821_vidioc_s_register, -#endif -}; - -struct video_device cx25821_video_template4 = { - .name = "cx25821-video", - .fops = &video_fops, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, -}; diff --git a/drivers/staging/cx25821/cx25821-video5.c b/drivers/staging/cx25821/cx25821-video5.c deleted file mode 100644 index 59370337b076..000000000000 --- a/drivers/staging/cx25821/cx25821-video5.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> - * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "cx25821-video.h" - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH05]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, - buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, - &dev->sram_channels[SRAM_CH05]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - dprintk(2, - "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb.i, buf->count, q->count); - } else { - prev = - list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width - && prev->vb.height == buf->vb.height - && prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, - "[%p/%d] buffer_queue - append to active, buf->count=%d\n", - buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, - buf->vb.i); - } - } - - if (list_empty(&q->active)) { - dprintk(2, "active queue empty!\n"); - } -} - -static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = cx25821_buffer_setup, - .buf_prepare = cx25821_buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = cx25821_buffer_release, -}; - -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx25821_dev *dev = video_drvdata(file); - struct cx25821_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - u32 pix_format; - - printk("open dev=%s type=%s\n", video_device_node_name(vdev), - v4l2_type_names[type]); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - - lock_kernel(); - - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH05; - pix_format = - (dev->pixel_formats[dev->channel_opened] == - PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio, &fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; -} - -static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t * ppos) -{ - struct cx25821_fh *fh = file->private_data; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO5)) - return -EBUSY; - - return videobuf_read_one(&fh->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - - default: - BUG(); - return 0; - } -} - -static unsigned int video_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (cx25821_res_check(fh, RESOURCE_VIDEO5)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { - if (buf->vb.state == VIDEOBUF_DONE) { - struct cx25821_dev *dev = fh->dev; - - if (dev && dev->use_cif_resolution[SRAM_CH05]) { - u8 cam_id = *((char *)buf->vb.baddr + 3); - memcpy((char *)buf->vb.baddr, - (char *)buf->vb.baddr + (fh->width * 2), - (fh->width * 2)); - *((char *)buf->vb.baddr + 3) = cam_id; - } - } - - return POLLIN | POLLRDNORM; - } - - return 0; -} - -static int video_release(struct file *file) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - - //stop the risc engine and fifo - cx_write(channel5->dma_ctl, 0); /* FIFO and RISC disable */ - - /* stop video capture */ - if (cx25821_res_check(fh, RESOURCE_VIDEO5)) { - videobuf_queue_cancel(&fh->vidq); - cx25821_res_free(dev, fh, RESOURCE_VIDEO5); - } - - if (fh->vidq.read_buf) { - cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } - - videobuf_mmap_free(&fh->vidq); - - v4l2_prio_close(&dev->prio, fh->prio); - file->private_data = NULL; - kfree(fh); - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; - } - - if (unlikely(i != fh->type)) { - return -EINVAL; - } - - if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO5)))) { - return -EBUSY; - } - - return videobuf_streamon(get_queue(fh)); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = cx25821_get_resource(fh, RESOURCE_VIDEO5); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - cx25821_res_free(dev, fh, res); - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; - } - - if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format(dev, SRAM_CH05, pix_format); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH05] = 1; - } else { - dev->use_cif_resolution[SRAM_CH05] = 0; - } - dev->cif_width[SRAM_CH05] = fh->width; - medusa_set_resolution(dev, fh->width, SRAM_CH05); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, - fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - - p->sequence = dev->vidq[SRAM_CH05].count; - - return ret_val; -} -static int vidioc_log_status(struct file *file, void *priv) -{ - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; - - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH05]; - u32 tmp = 0; - - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", - dev->name); - cx25821_call_all(dev, core, log_status); - - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 5 is %s\n", - (tmp & 0x11) ? "streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", - dev->name); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - return cx25821_set_control(dev, ctl, SRAM_CH05); -} - -// exported stuff -static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = cx25821_video_mmap, - .ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = cx25821_vidioc_querycap, - .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = cx25821_vidioc_reqbufs, - .vidioc_querybuf = cx25821_vidioc_querybuf, - .vidioc_qbuf = cx25821_vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -#ifdef TUNER_FLAG - .vidioc_s_std = cx25821_vidioc_s_std, - .vidioc_querystd = cx25821_vidioc_querystd, -#endif - .vidioc_cropcap = cx25821_vidioc_cropcap, - .vidioc_s_crop = cx25821_vidioc_s_crop, - .vidioc_g_crop = cx25821_vidioc_g_crop, - .vidioc_enum_input = cx25821_vidioc_enum_input, - .vidioc_g_input = cx25821_vidioc_g_input, - .vidioc_s_input = cx25821_vidioc_s_input, - .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = cx25821_vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = cx25821_vidioc_g_priority, - .vidioc_s_priority = cx25821_vidioc_s_priority, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = cx25821_vidiocgmbuf, -#endif -#ifdef TUNER_FLAG - .vidioc_g_tuner = cx25821_vidioc_g_tuner, - .vidioc_s_tuner = cx25821_vidioc_s_tuner, - .vidioc_g_frequency = cx25821_vidioc_g_frequency, - .vidioc_s_frequency = cx25821_vidioc_s_frequency, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = cx25821_vidioc_g_register, - .vidioc_s_register = cx25821_vidioc_s_register, -#endif -}; - -struct video_device cx25821_video_template5 = { - .name = "cx25821-video", - .fops = &video_fops, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, -}; diff --git a/drivers/staging/cx25821/cx25821-video6.c b/drivers/staging/cx25821/cx25821-video6.c deleted file mode 100644 index 4db2eb83d35a..000000000000 --- a/drivers/staging/cx25821/cx25821-video6.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> - * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "cx25821-video.h" - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH06]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, - buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, - &dev->sram_channels[SRAM_CH06]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - dprintk(2, - "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb.i, buf->count, q->count); - } else { - prev = - list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width - && prev->vb.height == buf->vb.height - && prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, - "[%p/%d] buffer_queue - append to active, buf->count=%d\n", - buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, - buf->vb.i); - } - } - - if (list_empty(&q->active)) { - dprintk(2, "active queue empty!\n"); - } -} - -static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = cx25821_buffer_setup, - .buf_prepare = cx25821_buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = cx25821_buffer_release, -}; - -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx25821_dev *dev = video_drvdata(file); - struct cx25821_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - u32 pix_format; - - printk("open dev=%s type=%s\n", video_device_node_name(vdev), - v4l2_type_names[type]); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - - lock_kernel(); - - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH06; - pix_format = - (dev->pixel_formats[dev->channel_opened] == - PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio, &fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; -} - -static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t * ppos) -{ - struct cx25821_fh *fh = file->private_data; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO6)) - return -EBUSY; - - return videobuf_read_one(&fh->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - - default: - BUG(); - return 0; - } -} - -static unsigned int video_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (cx25821_res_check(fh, RESOURCE_VIDEO6)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { - if (buf->vb.state == VIDEOBUF_DONE) { - struct cx25821_dev *dev = fh->dev; - - if (dev && dev->use_cif_resolution[SRAM_CH06]) { - u8 cam_id = *((char *)buf->vb.baddr + 3); - memcpy((char *)buf->vb.baddr, - (char *)buf->vb.baddr + (fh->width * 2), - (fh->width * 2)); - *((char *)buf->vb.baddr + 3) = cam_id; - } - } - - return POLLIN | POLLRDNORM; - } - - return 0; -} - -static int video_release(struct file *file) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - - //stop the risc engine and fifo - cx_write(channel6->dma_ctl, 0); /* FIFO and RISC disable */ - - /* stop video capture */ - if (cx25821_res_check(fh, RESOURCE_VIDEO6)) { - videobuf_queue_cancel(&fh->vidq); - cx25821_res_free(dev, fh, RESOURCE_VIDEO6); - } - if (fh->vidq.read_buf) { - cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } - - videobuf_mmap_free(&fh->vidq); - - v4l2_prio_close(&dev->prio, fh->prio); - file->private_data = NULL; - kfree(fh); - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; - } - - if (unlikely(i != fh->type)) { - return -EINVAL; - } - - if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO6)))) { - return -EBUSY; - } - - return videobuf_streamon(get_queue(fh)); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = cx25821_get_resource(fh, RESOURCE_VIDEO6); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - cx25821_res_free(dev, fh, res); - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; - } - - if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format(dev, SRAM_CH06, pix_format); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH06] = 1; - } else { - dev->use_cif_resolution[SRAM_CH06] = 0; - } - dev->cif_width[SRAM_CH06] = fh->width; - medusa_set_resolution(dev, fh->width, SRAM_CH06); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, - fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - - p->sequence = dev->vidq[SRAM_CH06].count; - - return ret_val; -} - -static int vidioc_log_status(struct file *file, void *priv) -{ - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; - - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH06]; - u32 tmp = 0; - - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", - dev->name); - cx25821_call_all(dev, core, log_status); - - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 6 is %s\n", - (tmp & 0x11) ? "streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", - dev->name); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - return cx25821_set_control(dev, ctl, SRAM_CH06); -} - -// exported stuff -static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = cx25821_video_mmap, - .ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = cx25821_vidioc_querycap, - .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = cx25821_vidioc_reqbufs, - .vidioc_querybuf = cx25821_vidioc_querybuf, - .vidioc_qbuf = cx25821_vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -#ifdef TUNER_FLAG - .vidioc_s_std = cx25821_vidioc_s_std, - .vidioc_querystd = cx25821_vidioc_querystd, -#endif - .vidioc_cropcap = cx25821_vidioc_cropcap, - .vidioc_s_crop = cx25821_vidioc_s_crop, - .vidioc_g_crop = cx25821_vidioc_g_crop, - .vidioc_enum_input = cx25821_vidioc_enum_input, - .vidioc_g_input = cx25821_vidioc_g_input, - .vidioc_s_input = cx25821_vidioc_s_input, - .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = cx25821_vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = cx25821_vidioc_g_priority, - .vidioc_s_priority = cx25821_vidioc_s_priority, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = cx25821_vidiocgmbuf, -#endif -#ifdef TUNER_FLAG - .vidioc_g_tuner = cx25821_vidioc_g_tuner, - .vidioc_s_tuner = cx25821_vidioc_s_tuner, - .vidioc_g_frequency = cx25821_vidioc_g_frequency, - .vidioc_s_frequency = cx25821_vidioc_s_frequency, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = cx25821_vidioc_g_register, - .vidioc_s_register = cx25821_vidioc_s_register, -#endif -}; - -struct video_device cx25821_video_template6 = { - .name = "cx25821-video", - .fops = &video_fops, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, -}; diff --git a/drivers/staging/cx25821/cx25821-video7.c b/drivers/staging/cx25821/cx25821-video7.c deleted file mode 100644 index 5e4a769badad..000000000000 --- a/drivers/staging/cx25821/cx25821-video7.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> - * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "cx25821-video.h" - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH07]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, - buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, - &dev->sram_channels[SRAM_CH07]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - dprintk(2, - "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb.i, buf->count, q->count); - } else { - prev = - list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width - && prev->vb.height == buf->vb.height - && prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, - "[%p/%d] buffer_queue - append to active, buf->count=%d\n", - buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, - buf->vb.i); - } - } - - if (list_empty(&q->active)) { - dprintk(2, "active queue empty!\n"); - } -} - -static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = cx25821_buffer_setup, - .buf_prepare = cx25821_buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = cx25821_buffer_release, -}; - -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx25821_dev *dev = video_drvdata(file); - struct cx25821_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - u32 pix_format; - - printk("open dev=%s type=%s\n", video_device_node_name(vdev), - v4l2_type_names[type]); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - - lock_kernel(); - - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH07; - pix_format = - (dev->pixel_formats[dev->channel_opened] == - PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio, &fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; -} - -static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t * ppos) -{ - struct cx25821_fh *fh = file->private_data; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO7)) - return -EBUSY; - - return videobuf_read_one(&fh->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - - default: - BUG(); - return 0; - } -} - -static unsigned int video_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (cx25821_res_check(fh, RESOURCE_VIDEO7)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { - if (buf->vb.state == VIDEOBUF_DONE) { - struct cx25821_dev *dev = fh->dev; - - if (dev && dev->use_cif_resolution[SRAM_CH07]) { - u8 cam_id = *((char *)buf->vb.baddr + 3); - memcpy((char *)buf->vb.baddr, - (char *)buf->vb.baddr + (fh->width * 2), - (fh->width * 2)); - *((char *)buf->vb.baddr + 3) = cam_id; - } - } - - return POLLIN | POLLRDNORM; - } - - return 0; -} - -static int video_release(struct file *file) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - - //stop the risc engine and fifo - cx_write(channel7->dma_ctl, 0); /* FIFO and RISC disable */ - - /* stop video capture */ - if (cx25821_res_check(fh, RESOURCE_VIDEO7)) { - videobuf_queue_cancel(&fh->vidq); - cx25821_res_free(dev, fh, RESOURCE_VIDEO7); - } - - if (fh->vidq.read_buf) { - cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } - - videobuf_mmap_free(&fh->vidq); - - v4l2_prio_close(&dev->prio, fh->prio); - file->private_data = NULL; - kfree(fh); - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; - } - - if (unlikely(i != fh->type)) { - return -EINVAL; - } - - if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO7)))) { - return -EBUSY; - } - - return videobuf_streamon(get_queue(fh)); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = cx25821_get_resource(fh, RESOURCE_VIDEO7); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - cx25821_res_free(dev, fh, res); - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; - } - - if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format(dev, SRAM_CH07, pix_format); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH07] = 1; - } else { - dev->use_cif_resolution[SRAM_CH07] = 0; - } - dev->cif_width[SRAM_CH07] = fh->width; - medusa_set_resolution(dev, fh->width, SRAM_CH07); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, - fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - - p->sequence = dev->vidq[SRAM_CH07].count; - - return ret_val; -} -static int vidioc_log_status(struct file *file, void *priv) -{ - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; - - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH07]; - u32 tmp = 0; - - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", - dev->name); - cx25821_call_all(dev, core, log_status); - - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 7 is %s\n", - (tmp & 0x11) ? "streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", - dev->name); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - return cx25821_set_control(dev, ctl, SRAM_CH07); -} - -// exported stuff -static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = cx25821_video_mmap, - .ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = cx25821_vidioc_querycap, - .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = cx25821_vidioc_reqbufs, - .vidioc_querybuf = cx25821_vidioc_querybuf, - .vidioc_qbuf = cx25821_vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -#ifdef TUNER_FLAG - .vidioc_s_std = cx25821_vidioc_s_std, - .vidioc_querystd = cx25821_vidioc_querystd, -#endif - .vidioc_cropcap = cx25821_vidioc_cropcap, - .vidioc_s_crop = cx25821_vidioc_s_crop, - .vidioc_g_crop = cx25821_vidioc_g_crop, - .vidioc_enum_input = cx25821_vidioc_enum_input, - .vidioc_g_input = cx25821_vidioc_g_input, - .vidioc_s_input = cx25821_vidioc_s_input, - .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = cx25821_vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = cx25821_vidioc_g_priority, - .vidioc_s_priority = cx25821_vidioc_s_priority, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = cx25821_vidiocgmbuf, -#endif -#ifdef TUNER_FLAG - .vidioc_g_tuner = cx25821_vidioc_g_tuner, - .vidioc_s_tuner = cx25821_vidioc_s_tuner, - .vidioc_g_frequency = cx25821_vidioc_g_frequency, - .vidioc_s_frequency = cx25821_vidioc_s_frequency, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = cx25821_vidioc_g_register, - .vidioc_s_register = cx25821_vidioc_s_register, -#endif -}; - -struct video_device cx25821_video_template7 = { - .name = "cx25821-video", - .fops = &video_fops, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, -}; diff --git a/drivers/staging/cx25821/cx25821-videoioctl.c b/drivers/staging/cx25821/cx25821-videoioctl.c deleted file mode 100644 index d16807d88be0..000000000000 --- a/drivers/staging/cx25821/cx25821-videoioctl.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> - * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "cx25821-video.h" - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[VIDEO_IOCTL_CH]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, - buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, - &dev->sram_channels[VIDEO_IOCTL_CH]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - dprintk(2, - "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb.i, buf->count, q->count); - } else { - prev = - list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width - && prev->vb.height == buf->vb.height - && prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, - "[%p/%d] buffer_queue - append to active, buf->count=%d\n", - buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, - buf->vb.i); - } - } - - if (list_empty(&q->active)) { - dprintk(2, "active queue empty!\n"); - } -} - -static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = cx25821_buffer_setup, - .buf_prepare = cx25821_buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = cx25821_buffer_release, -}; - -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx25821_dev *dev = video_drvdata(file); - struct cx25821_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - u32 pix_format; - - printk("open dev=%s type=%s\n", video_device_node_name(vdev), - v4l2_type_names[type]); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - - lock_kernel(); - - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = VIDEO_IOCTL_CH; - pix_format = V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio, &fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; -} - -static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t * ppos) -{ - struct cx25821_fh *fh = file->private_data; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO_IOCTL)) - return -EBUSY; - - return videobuf_read_one(&fh->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - - default: - BUG(); - return 0; - } -} - -static unsigned int video_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (cx25821_res_check(fh, RESOURCE_VIDEO_IOCTL)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN | POLLRDNORM; - - return 0; -} - -static int video_release(struct file *file) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - - /* stop video capture */ - if (cx25821_res_check(fh, RESOURCE_VIDEO_IOCTL)) { - videobuf_queue_cancel(&fh->vidq); - cx25821_res_free(dev, fh, RESOURCE_VIDEO_IOCTL); - } - - if (fh->vidq.read_buf) { - cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } - - videobuf_mmap_free(&fh->vidq); - - v4l2_prio_close(&dev->prio, fh->prio); - - file->private_data = NULL; - kfree(fh); - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; - } - - if (unlikely(i != fh->type)) { - return -EINVAL; - } - - if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO_IOCTL)))) { - return -EBUSY; - } - - return videobuf_streamon(get_queue(fh)); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = cx25821_get_resource(fh, RESOURCE_VIDEO_IOCTL); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - cx25821_res_free(dev, fh, res); - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vidq.field = f->fmt.pix.field; - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, - fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - return 0; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct cx25821_fh *fh = priv; - return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); -} - -static long video_ioctl_set(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - struct downstream_user_struct *data_from_user; - int command; - int width = 720; - int selected_channel = 0, pix_format = 0, i = 0; - int cif_enable = 0, cif_width = 0; - u32 value = 0; - - data_from_user = (struct downstream_user_struct *)arg; - - if (!data_from_user) { - printk("cx25821 in %s(): User data is INVALID. Returning.\n", - __func__); - return 0; - } - - command = data_from_user->command; - - if (command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT - && command != ENABLE_CIF_RESOLUTION && command != REG_READ - && command != REG_WRITE && command != MEDUSA_READ - && command != MEDUSA_WRITE) { - return 0; - } - - switch (command) { - case SET_VIDEO_STD: - dev->tvnorm = - !strcmp(data_from_user->vid_stdname, - "PAL") ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; - medusa_set_videostandard(dev); - break; - - case SET_PIXEL_FORMAT: - selected_channel = data_from_user->decoder_select; - pix_format = data_from_user->pixel_format; - - if (!(selected_channel <= 7 && selected_channel >= 0)) { - selected_channel -= 4; - selected_channel = selected_channel % 8; - } - - if (selected_channel >= 0) - cx25821_set_pixel_format(dev, selected_channel, - pix_format); - - break; - - case ENABLE_CIF_RESOLUTION: - selected_channel = data_from_user->decoder_select; - cif_enable = data_from_user->cif_resolution_enable; - cif_width = data_from_user->cif_width; - - if (cif_enable) { - if (dev->tvnorm & V4L2_STD_PAL_BG - || dev->tvnorm & V4L2_STD_PAL_DK) - width = 352; - else - width = (cif_width == 320 - || cif_width == 352) ? cif_width : 320; - } - - if (!(selected_channel <= 7 && selected_channel >= 0)) { - selected_channel -= 4; - selected_channel = selected_channel % 8; - } - - if (selected_channel <= 7 && selected_channel >= 0) { - dev->use_cif_resolution[selected_channel] = cif_enable; - dev->cif_width[selected_channel] = width; - } else { - for (i = 0; i < VID_CHANNEL_NUM; i++) { - dev->use_cif_resolution[i] = cif_enable; - dev->cif_width[i] = width; - } - } - - medusa_set_resolution(dev, width, selected_channel); - break; - case REG_READ: - data_from_user->reg_data = cx_read(data_from_user->reg_address); - break; - case REG_WRITE: - cx_write(data_from_user->reg_address, data_from_user->reg_data); - break; - case MEDUSA_READ: - value = - cx25821_i2c_read(&dev->i2c_bus[0], - (u16) data_from_user->reg_address, - &data_from_user->reg_data); - break; - case MEDUSA_WRITE: - cx25821_i2c_write(&dev->i2c_bus[0], - (u16) data_from_user->reg_address, - data_from_user->reg_data); - break; - } - - return 0; -} - -static int vidioc_log_status(struct file *file, void *priv) -{ - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; - - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", - dev->name); - cx25821_call_all(dev, core, log_status); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", - dev->name); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - return 0; -} - -// exported stuff -static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = cx25821_video_mmap, - .ioctl = video_ioctl_set, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = cx25821_vidioc_querycap, - .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = cx25821_vidioc_reqbufs, - .vidioc_querybuf = cx25821_vidioc_querybuf, - .vidioc_qbuf = cx25821_vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -#ifdef TUNER_FLAG - .vidioc_s_std = cx25821_vidioc_s_std, - .vidioc_querystd = cx25821_vidioc_querystd, -#endif - .vidioc_cropcap = cx25821_vidioc_cropcap, - .vidioc_s_crop = cx25821_vidioc_s_crop, - .vidioc_g_crop = cx25821_vidioc_g_crop, - .vidioc_enum_input = cx25821_vidioc_enum_input, - .vidioc_g_input = cx25821_vidioc_g_input, - .vidioc_s_input = cx25821_vidioc_s_input, - .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = cx25821_vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = cx25821_vidioc_g_priority, - .vidioc_s_priority = cx25821_vidioc_s_priority, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = cx25821_vidiocgmbuf, -#endif -#ifdef TUNER_FLAG - .vidioc_g_tuner = cx25821_vidioc_g_tuner, - .vidioc_s_tuner = cx25821_vidioc_s_tuner, - .vidioc_g_frequency = cx25821_vidioc_g_frequency, - .vidioc_s_frequency = cx25821_vidioc_s_frequency, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = cx25821_vidioc_g_register, - .vidioc_s_register = cx25821_vidioc_s_register, -#endif -}; - -struct video_device cx25821_videoioctl_template = { - .name = "cx25821-videoioctl", - .fops = &video_fops, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, -}; diff --git a/drivers/staging/cx25821/cx25821-vidups10.c b/drivers/staging/cx25821/cx25821-vidups10.c deleted file mode 100644 index c746a17ccbd2..000000000000 --- a/drivers/staging/cx25821/cx25821-vidups10.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> - * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "cx25821-video.h" - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH10]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, - buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, - &dev->sram_channels[SRAM_CH10]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - dprintk(2, - "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb.i, buf->count, q->count); - } else { - prev = - list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width - && prev->vb.height == buf->vb.height - && prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, - "[%p/%d] buffer_queue - append to active, buf->count=%d\n", - buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, - buf->vb.i); - } - } - - if (list_empty(&q->active)) { - dprintk(2, "active queue empty!\n"); - } -} - -static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = cx25821_buffer_setup, - .buf_prepare = cx25821_buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = cx25821_buffer_release, -}; - -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx25821_dev *dev = video_drvdata(file); - struct cx25821_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - printk("open dev=%s type=%s\n", video_device_node_name(vdev), - v4l2_type_names[type]); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - - lock_kernel(); - - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = 9; - fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); - - v4l2_prio_open(&dev->prio, &fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; -} - -static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t * ppos) -{ - struct cx25821_fh *fh = file->private_data; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO10)) - return -EBUSY; - - return videobuf_read_one(&fh->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - - default: - BUG(); - return 0; - } -} - -static unsigned int video_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (cx25821_res_check(fh, RESOURCE_VIDEO10)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN | POLLRDNORM; - return 0; -} - -static int video_release(struct file *file) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - - //stop the risc engine and fifo - //cx_write(channel10->dma_ctl, 0); - - /* stop video capture */ - if (cx25821_res_check(fh, RESOURCE_VIDEO10)) { - videobuf_queue_cancel(&fh->vidq); - cx25821_res_free(dev, fh, RESOURCE_VIDEO10); - } - - if (fh->vidq.read_buf) { - cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } - - videobuf_mmap_free(&fh->vidq); - - v4l2_prio_close(&dev->prio, fh->prio); - - file->private_data = NULL; - kfree(fh); - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; - } - - if (unlikely(i != fh->type)) { - return -EINVAL; - } - - if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO10)))) { - return -EBUSY; - } - - return videobuf_streamon(get_queue(fh)); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = cx25821_get_resource(fh, RESOURCE_VIDEO10); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - cx25821_res_free(dev, fh, res); - return 0; -} - -static long video_ioctl_upstream10(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - int command = 0; - struct upstream_user_struct *data_from_user; - - data_from_user = (struct upstream_user_struct *)arg; - - if (!data_from_user) { - printk - ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", - __func__); - return 0; - } - - command = data_from_user->command; - - if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) { - return 0; - } - - dev->input_filename_ch2 = data_from_user->input_filename; - dev->input_audiofilename = data_from_user->input_filename; - dev->vid_stdname_ch2 = data_from_user->vid_stdname; - dev->pixel_format_ch2 = data_from_user->pixel_format; - dev->channel_select_ch2 = data_from_user->channel_select; - dev->command_ch2 = data_from_user->command; - - switch (command) { - case UPSTREAM_START_VIDEO: - cx25821_start_upstream_video_ch2(dev, data_from_user); - break; - - case UPSTREAM_STOP_VIDEO: - cx25821_stop_upstream_video_ch2(dev); - break; - } - - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vidq.field = f->fmt.pix.field; - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, - fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - return 0; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct cx25821_fh *fh = priv; - return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); -} - -static int vidioc_log_status(struct file *file, void *priv) -{ - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; - - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", - dev->name); - cx25821_call_all(dev, core, log_status); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", - dev->name); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - return 0; -} - -//exported stuff -static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = cx25821_video_mmap, - .ioctl = video_ioctl_upstream10, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = cx25821_vidioc_querycap, - .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = cx25821_vidioc_reqbufs, - .vidioc_querybuf = cx25821_vidioc_querybuf, - .vidioc_qbuf = cx25821_vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -#ifdef TUNER_FLAG - .vidioc_s_std = cx25821_vidioc_s_std, - .vidioc_querystd = cx25821_vidioc_querystd, -#endif - .vidioc_cropcap = cx25821_vidioc_cropcap, - .vidioc_s_crop = cx25821_vidioc_s_crop, - .vidioc_g_crop = cx25821_vidioc_g_crop, - .vidioc_enum_input = cx25821_vidioc_enum_input, - .vidioc_g_input = cx25821_vidioc_g_input, - .vidioc_s_input = cx25821_vidioc_s_input, - .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = cx25821_vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = cx25821_vidioc_g_priority, - .vidioc_s_priority = cx25821_vidioc_s_priority, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = cx25821_vidiocgmbuf, -#endif -#ifdef TUNER_FLAG - .vidioc_g_tuner = cx25821_vidioc_g_tuner, - .vidioc_s_tuner = cx25821_vidioc_s_tuner, - .vidioc_g_frequency = cx25821_vidioc_g_frequency, - .vidioc_s_frequency = cx25821_vidioc_s_frequency, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = cx25821_vidioc_g_register, - .vidioc_s_register = cx25821_vidioc_s_register, -#endif -}; - -struct video_device cx25821_video_template10 = { - .name = "cx25821-upstream10", - .fops = &video_fops, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, -}; diff --git a/drivers/staging/cx25821/cx25821-vidups9.c b/drivers/staging/cx25821/cx25821-vidups9.c deleted file mode 100644 index 466e0f34ae34..000000000000 --- a/drivers/staging/cx25821/cx25821-vidups9.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> - * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "cx25821-video.h" - -static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx25821_buffer *buf = - container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH09]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, - buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, - &dev->sram_channels[SRAM_CH09]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); - dprintk(2, - "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb.i, buf->count, q->count); - } else { - prev = - list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width - && prev->vb.height == buf->vb.height - && prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, - "[%p/%d] buffer_queue - append to active, buf->count=%d\n", - buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, - buf->vb.i); - } - } - - if (list_empty(&q->active)) { - dprintk(2, "active queue empty!\n"); - } -} - -static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = cx25821_buffer_setup, - .buf_prepare = cx25821_buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = cx25821_buffer_release, -}; - -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx25821_dev *dev = video_drvdata(file); - struct cx25821_fh *fh; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - printk("open dev=%s type=%s\n", video_device_node_name(vdev), - v4l2_type_names[type]); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - - lock_kernel(); - - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = 8; - fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); - - v4l2_prio_open(&dev->prio, &fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; -} - -static ssize_t video_read(struct file *file, char __user * data, size_t count, - loff_t * ppos) -{ - struct cx25821_fh *fh = file->private_data; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (cx25821_res_locked(fh->dev, RESOURCE_VIDEO9)) - return -EBUSY; - - return videobuf_read_one(&fh->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - - default: - BUG(); - return 0; - } -} - -static unsigned int video_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (cx25821_res_check(fh, RESOURCE_VIDEO9)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN | POLLRDNORM; - return 0; -} - -static int video_release(struct file *file) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - - //stop the risc engine and fifo - //cx_write(channel9->dma_ctl, 0); - - /* stop video capture */ - if (cx25821_res_check(fh, RESOURCE_VIDEO9)) { - videobuf_queue_cancel(&fh->vidq); - cx25821_res_free(dev, fh, RESOURCE_VIDEO9); - } - - if (fh->vidq.read_buf) { - cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } - - videobuf_mmap_free(&fh->vidq); - - v4l2_prio_close(&dev->prio, fh->prio); - - file->private_data = NULL; - kfree(fh); - - return 0; -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; - } - - if (unlikely(i != fh->type)) { - return -EINVAL; - } - - if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, RESOURCE_VIDEO9)))) { - return -EBUSY; - } - - return videobuf_streamon(get_queue(fh)); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = cx25821_get_resource(fh, RESOURCE_VIDEO9); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - cx25821_res_free(dev, fh, res); - return 0; -} - -static long video_ioctl_upstream9(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - int command = 0; - struct upstream_user_struct *data_from_user; - - data_from_user = (struct upstream_user_struct *)arg; - - if (!data_from_user) { - printk - ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", - __func__); - return 0; - } - - command = data_from_user->command; - - if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) { - return 0; - } - - dev->input_filename = data_from_user->input_filename; - dev->input_audiofilename = data_from_user->input_filename; - dev->vid_stdname = data_from_user->vid_stdname; - dev->pixel_format = data_from_user->pixel_format; - dev->channel_select = data_from_user->channel_select; - dev->command = data_from_user->command; - - switch (command) { - case UPSTREAM_START_VIDEO: - cx25821_start_upstream_video_ch1(dev, data_from_user); - break; - - case UPSTREAM_STOP_VIDEO: - cx25821_stop_upstream_video_ch1(dev); - break; - } - - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vidq.field = f->fmt.pix.field; - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, - fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - return 0; -} - -static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct cx25821_fh *fh = priv; - return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); -} -static int vidioc_log_status(struct file *file, void *priv) -{ - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; - - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", - dev->name); - cx25821_call_all(dev, core, log_status); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", - dev->name); - return 0; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) -{ - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - struct cx25821_fh *fh = priv; - int err; - if (fh) { - err = v4l2_prio_check(&dev->prio, fh->prio); - if (0 != err) - return err; - } - - return 0; -} - -// exported stuff -static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = cx25821_video_mmap, - .ioctl = video_ioctl_upstream9, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = cx25821_vidioc_querycap, - .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = cx25821_vidioc_reqbufs, - .vidioc_querybuf = cx25821_vidioc_querybuf, - .vidioc_qbuf = cx25821_vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, -#ifdef TUNER_FLAG - .vidioc_s_std = cx25821_vidioc_s_std, - .vidioc_querystd = cx25821_vidioc_querystd, -#endif - .vidioc_cropcap = cx25821_vidioc_cropcap, - .vidioc_s_crop = cx25821_vidioc_s_crop, - .vidioc_g_crop = cx25821_vidioc_g_crop, - .vidioc_enum_input = cx25821_vidioc_enum_input, - .vidioc_g_input = cx25821_vidioc_g_input, - .vidioc_s_input = cx25821_vidioc_s_input, - .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = cx25821_vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = cx25821_vidioc_g_priority, - .vidioc_s_priority = cx25821_vidioc_s_priority, -#ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = cx25821_vidiocgmbuf, -#endif -#ifdef TUNER_FLAG - .vidioc_g_tuner = cx25821_vidioc_g_tuner, - .vidioc_s_tuner = cx25821_vidioc_s_tuner, - .vidioc_g_frequency = cx25821_vidioc_g_frequency, - .vidioc_s_frequency = cx25821_vidioc_s_frequency, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = cx25821_vidioc_g_register, - .vidioc_s_register = cx25821_vidioc_s_register, -#endif -}; - -struct video_device cx25821_video_template9 = { - .name = "cx25821-upstream9", - .fops = &video_fops, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, -}; diff --git a/drivers/staging/cx25821/cx25821.h b/drivers/staging/cx25821/cx25821.h index cf2286d83b6a..1b628f61578a 100644 --- a/drivers/staging/cx25821/cx25821.h +++ b/drivers/staging/cx25821/cx25821.h @@ -61,7 +61,7 @@ #define FALSE 0 #define LINE_SIZE_D1 1440 -// Number of decoders and encoders +/* Number of decoders and encoders */ #define MAX_DECODERS 8 #define MAX_ENCODERS 2 #define QUAD_DECODERS 4 @@ -139,6 +139,7 @@ struct cx25821_fh { /* video capture */ struct cx25821_fmt *fmt; unsigned int width, height; + int channel_id; /* vbi capture */ struct videobuf_queue vidq; @@ -236,13 +237,34 @@ struct cx25821_data { struct sram_channel *channel; }; +struct cx25821_channel { + struct v4l2_prio_state prio; + + int ctl_bright; + int ctl_contrast; + int ctl_hue; + int ctl_saturation; + + struct cx25821_data timeout_data; + + struct video_device *video_dev; + struct cx25821_dmaqueue vidq; + + struct sram_channel *sram_channels; + + struct mutex lock; + int resources; + + int pixel_formats; + int use_cif_resolution; + int cif_width; +}; + struct cx25821_dev { struct list_head devlist; atomic_t refcount; struct v4l2_device v4l2_dev; - struct v4l2_prio_state prio; - /* pci stuff */ struct pci_dev *pci; unsigned char pci_rev, pci_lat; @@ -261,13 +283,12 @@ struct cx25821_dev { int nr; struct mutex lock; + struct cx25821_channel channels[MAX_VID_CHANNEL_NUM]; + /* board details */ unsigned int board; char name[32]; - /* sram configuration */ - struct sram_channel *sram_channels; - /* Analog video */ u32 resources; unsigned int input; @@ -282,13 +303,6 @@ struct cx25821_dev { unsigned char videc_addr; unsigned short _max_num_decoders; - int ctl_bright; - int ctl_contrast; - int ctl_hue; - int ctl_saturation; - - struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; - /* Analog Audio Upstream */ int _audio_is_running; int _audiopixel_format; @@ -297,7 +311,7 @@ struct cx25821_dev { int _audio_lines_count; int _audioframe_count; int _audio_upstream_channel_select; - int _last_index_irq; //The last interrupt index processed. + int _last_index_irq; /* The last interrupt index processed. */ __le32 *_risc_audio_jmp_addr; __le32 *_risc_virt_start_addr; @@ -313,12 +327,10 @@ struct cx25821_dev { /* V4l */ u32 freq; - struct video_device *video_dev[MAX_VID_CHANNEL_NUM]; struct video_device *vbi_dev; struct video_device *radio_dev; struct video_device *ioctl_dev; - struct cx25821_dmaqueue vidq[MAX_VID_CHANNEL_NUM]; spinlock_t slock; /* Video Upstream */ @@ -401,9 +413,6 @@ struct cx25821_dev { int pixel_format; int channel_select; int command; - int pixel_formats[VID_CHANNEL_NUM]; - int use_cif_resolution[VID_CHANNEL_NUM]; - int cif_width[VID_CHANNEL_NUM]; int channel_opened; }; @@ -482,7 +491,7 @@ struct sram_channel { u32 fld_aud_fifo_en; u32 fld_aud_risc_en; - //For Upstream Video + /* For Upstream Video */ u32 vid_fmt_ctl; u32 vid_active_ctl1; u32 vid_active_ctl2; diff --git a/drivers/staging/dream/synaptics_i2c_rmi.c b/drivers/staging/dream/synaptics_i2c_rmi.c index 1f020dad6234..3320359408a9 100644 --- a/drivers/staging/dream/synaptics_i2c_rmi.c +++ b/drivers/staging/dream/synaptics_i2c_rmi.c @@ -519,7 +519,6 @@ err_input_register_device_failed: err_input_dev_alloc_failed: err_detect_failed: err_power_failed: - i2c_set_clientdata(client, NULL); kfree(ts); err_alloc_data_failed: err_check_functionality_failed: @@ -537,7 +536,6 @@ static int synaptics_ts_remove(struct i2c_client *client) else hrtimer_cancel(&ts->timer); input_unregister_device(ts->input_dev); - i2c_set_clientdata(client, NULL); kfree(ts); return 0; } diff --git a/drivers/staging/dt3155/allocator.c b/drivers/staging/dt3155/allocator.c index bd5adbc2a238..d33947b0378f 100644 --- a/drivers/staging/dt3155/allocator.c +++ b/drivers/staging/dt3155/allocator.c @@ -176,9 +176,7 @@ int allocator_free_dma(unsigned long address) prev = ptr; ptr = ptr->next; if (!ptr) { - printk(KERN_ERR ALL_MSG - "free_dma(0x%08lx) but add. not allocated\n", - ptr->address); + pr_err(ALL_MSG "free_dma but add. not allocated\n"); return -EINVAL; } PDEBUGG("freeing: %08lx (%li) next %08lx\n", ptr->address, ptr->size, diff --git a/drivers/staging/go7007/wis-saa7113.c b/drivers/staging/go7007/wis-saa7113.c index bd925457f8b7..72f5c1f56d19 100644 --- a/drivers/staging/go7007/wis-saa7113.c +++ b/drivers/staging/go7007/wis-saa7113.c @@ -289,7 +289,6 @@ static int wis_saa7113_probe(struct i2c_client *client, if (write_regs(client, initial_registers) < 0) { printk(KERN_ERR "wis-saa7113: error initializing SAA7113\n"); - i2c_set_clientdata(client, NULL); kfree(dec); return -ENODEV; } @@ -301,7 +300,6 @@ static int wis_saa7113_remove(struct i2c_client *client) { struct wis_saa7113 *dec = i2c_get_clientdata(client); - i2c_set_clientdata(client, NULL); kfree(dec); return 0; } diff --git a/drivers/staging/go7007/wis-saa7115.c b/drivers/staging/go7007/wis-saa7115.c index b2eb804c1954..cd950b61cf70 100644 --- a/drivers/staging/go7007/wis-saa7115.c +++ b/drivers/staging/go7007/wis-saa7115.c @@ -422,7 +422,6 @@ static int wis_saa7115_probe(struct i2c_client *client, if (write_regs(client, initial_registers) < 0) { printk(KERN_ERR "wis-saa7115: error initializing SAA7115\n"); - i2c_set_clientdata(client, NULL); kfree(dec); return -ENODEV; } @@ -434,7 +433,6 @@ static int wis_saa7115_remove(struct i2c_client *client) { struct wis_saa7115 *dec = i2c_get_clientdata(client); - i2c_set_clientdata(client, NULL); kfree(dec); return 0; } diff --git a/drivers/staging/go7007/wis-sony-tuner.c b/drivers/staging/go7007/wis-sony-tuner.c index b1013291190f..981c9b311b8b 100644 --- a/drivers/staging/go7007/wis-sony-tuner.c +++ b/drivers/staging/go7007/wis-sony-tuner.c @@ -684,7 +684,6 @@ static int wis_sony_tuner_remove(struct i2c_client *client) { struct wis_sony_tuner *t = i2c_get_clientdata(client); - i2c_set_clientdata(client, NULL); kfree(t); return 0; } diff --git a/drivers/staging/go7007/wis-tw2804.c b/drivers/staging/go7007/wis-tw2804.c index 315268d130dd..ee28a99dc388 100644 --- a/drivers/staging/go7007/wis-tw2804.c +++ b/drivers/staging/go7007/wis-tw2804.c @@ -323,7 +323,6 @@ static int wis_tw2804_remove(struct i2c_client *client) { struct wis_tw2804 *dec = i2c_get_clientdata(client); - i2c_set_clientdata(client, NULL); kfree(dec); return 0; } diff --git a/drivers/staging/go7007/wis-tw9903.c b/drivers/staging/go7007/wis-tw9903.c index 2afea09091b9..80d47269b1c0 100644 --- a/drivers/staging/go7007/wis-tw9903.c +++ b/drivers/staging/go7007/wis-tw9903.c @@ -294,7 +294,6 @@ static int wis_tw9903_probe(struct i2c_client *client, if (write_regs(client, initial_registers) < 0) { printk(KERN_ERR "wis-tw9903: error initializing TW9903\n"); - i2c_set_clientdata(client, NULL); kfree(dec); return -ENODEV; } @@ -306,7 +305,6 @@ static int wis_tw9903_remove(struct i2c_client *client) { struct wis_tw9903 *dec = i2c_get_clientdata(client); - i2c_set_clientdata(client, NULL); kfree(dec); return 0; } diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c index 3f53b4d1e4cf..12db555a3a5d 100644 --- a/drivers/staging/hv/channel_mgmt.c +++ b/drivers/staging/hv/channel_mgmt.c @@ -23,6 +23,7 @@ #include <linux/slab.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/completion.h> #include "osd.h" #include "logging.h" #include "vmbus_private.h" @@ -293,6 +294,25 @@ void FreeVmbusChannel(struct vmbus_channel *Channel) Channel); } + +DECLARE_COMPLETION(hv_channel_ready); + +/* + * Count initialized channels, and ensure all channels are ready when hv_vmbus + * module loading completes. + */ +static void count_hv_channel(void) +{ + static int counter; + unsigned long flags; + + spin_lock_irqsave(&gVmbusConnection.channel_lock, flags); + if (++counter == MAX_MSG_TYPES) + complete(&hv_channel_ready); + spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags); +} + + /* * VmbusChannelProcessOffer - Process the offer by creating a channel/device * associated with this offer @@ -373,22 +393,21 @@ static void VmbusChannelProcessOffer(void *context) * can cleanup properly */ newChannel->State = CHANNEL_OPEN_STATE; - cnt = 0; - while (cnt != MAX_MSG_TYPES) { + /* Open IC channels */ + for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) { if (memcmp(&newChannel->OfferMsg.Offer.InterfaceType, &hv_cb_utils[cnt].data, - sizeof(struct hv_guid)) == 0) { + sizeof(struct hv_guid)) == 0 && + VmbusChannelOpen(newChannel, 2 * PAGE_SIZE, + 2 * PAGE_SIZE, NULL, 0, + hv_cb_utils[cnt].callback, + newChannel) == 0) { + hv_cb_utils[cnt].channel = newChannel; DPRINT_INFO(VMBUS, "%s", - hv_cb_utils[cnt].log_msg); - - if (VmbusChannelOpen(newChannel, 2 * PAGE_SIZE, - 2 * PAGE_SIZE, NULL, 0, - hv_cb_utils[cnt].callback, - newChannel) == 0) - hv_cb_utils[cnt].channel = newChannel; + hv_cb_utils[cnt].log_msg); + count_hv_channel(); } - cnt++; } } DPRINT_EXIT(VMBUS); diff --git a/drivers/staging/hv/hv_utils.c b/drivers/staging/hv/hv_utils.c index 8a49aafea37a..2adc9b48ca9c 100644 --- a/drivers/staging/hv/hv_utils.c +++ b/drivers/staging/hv/hv_utils.c @@ -24,6 +24,8 @@ #include <linux/slab.h> #include <linux/sysctl.h> #include <linux/reboot.h> +#include <linux/dmi.h> +#include <linux/pci.h> #include "logging.h" #include "osd.h" @@ -251,10 +253,36 @@ static void heartbeat_onchannelcallback(void *context) DPRINT_EXIT(VMBUS); } +static const struct pci_device_id __initconst +hv_utils_pci_table[] __maybe_unused = { + { PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */ + { 0 } +}; +MODULE_DEVICE_TABLE(pci, hv_utils_pci_table); + + +static const struct dmi_system_id __initconst +hv_utils_dmi_table[] __maybe_unused = { + { + .ident = "Hyper-V", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), + DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"), + }, + }, + { }, +}; +MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table); + + static int __init init_hyperv_utils(void) { printk(KERN_INFO "Registering HyperV Utility Driver\n"); + if (!dmi_check_system(hv_utils_dmi_table)) + return -ENODEV; + hv_cb_utils[HV_SHUTDOWN_MSG].channel->OnChannelCallback = &shutdown_onchannelcallback; hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback; diff --git a/drivers/staging/hv/vmbus.h b/drivers/staging/hv/vmbus.h index 0c6ee0f487f3..3c14b2926e00 100644 --- a/drivers/staging/hv/vmbus.h +++ b/drivers/staging/hv/vmbus.h @@ -74,4 +74,6 @@ int vmbus_child_driver_register(struct driver_context *driver_ctx); void vmbus_child_driver_unregister(struct driver_context *driver_ctx); void vmbus_get_interface(struct vmbus_channel_interface *interface); +extern struct completion hv_channel_ready; + #endif /* _VMBUS_H_ */ diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index c21731a12ca7..22c80ece6388 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -27,6 +27,7 @@ #include <linux/pci.h> #include <linux/dmi.h> #include <linux/slab.h> +#include <linux/completion.h> #include "version_info.h" #include "osd.h" #include "logging.h" @@ -356,6 +357,8 @@ static int vmbus_bus_init(int (*drv_init)(struct hv_driver *drv)) vmbus_drv_obj->GetChannelOffers(); + wait_for_completion(&hv_channel_ready); + cleanup: DPRINT_EXIT(VMBUS_DRV); diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h index a4555e6f133f..014f6684faba 100644 --- a/drivers/staging/iio/Documentation/iio_utils.h +++ b/drivers/staging/iio/Documentation/iio_utils.h @@ -62,9 +62,8 @@ inline int find_type_by_name(const char *name, const char *type) 1) != 0) { filename = malloc(strlen(iio_dir) + strlen(type) - + 1 + numstrlen - + 1); + + 6); if (filename == NULL) return -ENOMEM; sprintf(filename, "%s%s%d/name", diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c index 20e267448d1f..905f8560d31f 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363_core.c @@ -1011,7 +1011,6 @@ error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); error_free_st: - i2c_set_clientdata(client, NULL); kfree(st); error_ret: @@ -1030,7 +1029,6 @@ static int max1363_remove(struct i2c_client *client) regulator_disable(st->reg); regulator_put(st->reg); } - i2c_set_clientdata(client, NULL); kfree(st); return 0; diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c index 43aaacff4e74..e4b0a5ef1c1f 100644 --- a/drivers/staging/iio/light/tsl2563.c +++ b/drivers/staging/iio/light/tsl2563.c @@ -694,7 +694,6 @@ static int __devinit tsl2563_probe(struct i2c_client *client, fail2: iio_device_unregister(chip->indio_dev); fail1: - i2c_set_clientdata(client, NULL); kfree(chip); return err; } @@ -705,7 +704,6 @@ static int tsl2563_remove(struct i2c_client *client) iio_device_unregister(chip->indio_dev); - i2c_set_clientdata(client, NULL); kfree(chip); return 0; } diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c index 1f14cd4770e7..294272d0619f 100644 --- a/drivers/staging/iio/ring_sw.c +++ b/drivers/staging/iio/ring_sw.c @@ -20,7 +20,7 @@ static inline int __iio_allocate_sw_ring_buffer(struct iio_sw_ring_buffer *ring, if ((length == 0) || (bytes_per_datum == 0)) return -EINVAL; __iio_update_ring_buffer(&ring->buf, bytes_per_datum, length); - ring->data = kmalloc(length*ring->buf.bpd, GFP_KERNEL); + ring->data = kmalloc(length*ring->buf.bpd, GFP_ATOMIC); ring->read_p = NULL; ring->write_p = NULL; ring->last_written_p = NULL; diff --git a/drivers/staging/lirc/Kconfig b/drivers/staging/lirc/Kconfig new file mode 100644 index 000000000000..968c2adee06b --- /dev/null +++ b/drivers/staging/lirc/Kconfig @@ -0,0 +1,110 @@ +# +# LIRC driver(s) configuration +# +menuconfig LIRC_STAGING + bool "Linux Infrared Remote Control IR receiver/transmitter drivers" + help + Say Y here, and all supported Linux Infrared Remote Control IR and + RF receiver and transmitter drivers will be displayed. When paired + with a remote control and the lirc daemon, the receiver drivers + allow control of your Linux system via remote control. + +if LIRC_STAGING + +config LIRC_BT829 + tristate "BT829 based hardware" + depends on LIRC_STAGING + help + Driver for the IR interface on BT829-based hardware + +config LIRC_ENE0100 + tristate "ENE KB3924/ENE0100 CIR Port Reciever" + depends on LIRC_STAGING + help + This is a driver for CIR port handled by ENE KB3924 embedded + controller found on some notebooks. + It appears on PNP list as ENE0100. + +config LIRC_I2C + tristate "I2C Based IR Receivers" + depends on LIRC_STAGING + help + Driver for I2C-based IR receivers, such as those commonly + found onboard Hauppauge PVR-150/250/350 video capture cards + +config LIRC_IGORPLUGUSB + tristate "Igor Cesko's USB IR Receiver" + depends on LIRC_STAGING && USB + help + Driver for Igor Cesko's USB IR Receiver + +config LIRC_IMON + tristate "Legacy SoundGraph iMON Receiver and Display" + depends on LIRC_STAGING + help + Driver for the original SoundGraph iMON IR Receiver and Display + + Current generation iMON devices use the input layer imon driver. + +config LIRC_IT87 + tristate "ITE IT87XX CIR Port Receiver" + depends on LIRC_STAGING + help + Driver for the ITE IT87xx IR Receiver + +config LIRC_ITE8709 + tristate "ITE8709 CIR Port Receiver" + depends on LIRC_STAGING && PNP + help + Driver for the ITE8709 IR Receiver + +config LIRC_PARALLEL + tristate "Homebrew Parallel Port Receiver" + depends on LIRC_STAGING && !SMP + help + Driver for Homebrew Parallel Port Receivers + +config LIRC_SASEM + tristate "Sasem USB IR Remote" + depends on LIRC_STAGING + help + Driver for the Sasem OnAir Remocon-V or Dign HV5 HTPC IR/VFD Module + +config LIRC_SERIAL + tristate "Homebrew Serial Port Receiver" + depends on LIRC_STAGING + help + Driver for Homebrew Serial Port Receivers + +config LIRC_SERIAL_TRANSMITTER + bool "Serial Port Transmitter" + default y + depends on LIRC_SERIAL + help + Serial Port Transmitter support + +config LIRC_SIR + tristate "Built-in SIR IrDA port" + depends on LIRC_STAGING + help + Driver for the SIR IrDA port + +config LIRC_STREAMZAP + tristate "Streamzap PC Receiver" + depends on LIRC_STAGING + help + Driver for the Streamzap PC Receiver + +config LIRC_TTUSBIR + tristate "Technotrend USB IR Receiver" + depends on LIRC_STAGING && USB + help + Driver for the Technotrend USB IR Receiver + +config LIRC_ZILOG + tristate "Zilog/Hauppauge IR Transmitter" + depends on LIRC_STAGING + help + Driver for the Zilog/Hauppauge IR Transmitter, found on + PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards +endif diff --git a/drivers/staging/lirc/Makefile b/drivers/staging/lirc/Makefile new file mode 100644 index 000000000000..a019182a7a38 --- /dev/null +++ b/drivers/staging/lirc/Makefile @@ -0,0 +1,19 @@ +# Makefile for the lirc drivers. +# + +# Each configuration option enables a list of files. + +obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o +obj-$(CONFIG_LIRC_ENE0100) += lirc_ene0100.o +obj-$(CONFIG_LIRC_I2C) += lirc_i2c.o +obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o +obj-$(CONFIG_LIRC_IMON) += lirc_imon.o +obj-$(CONFIG_LIRC_IT87) += lirc_it87.o +obj-$(CONFIG_LIRC_ITE8709) += lirc_ite8709.o +obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o +obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o +obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o +obj-$(CONFIG_LIRC_SIR) += lirc_sir.o +obj-$(CONFIG_LIRC_STREAMZAP) += lirc_streamzap.o +obj-$(CONFIG_LIRC_TTUSBIR) += lirc_ttusbir.o +obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o diff --git a/drivers/staging/lirc/TODO b/drivers/staging/lirc/TODO new file mode 100644 index 000000000000..b6cb593f55c6 --- /dev/null +++ b/drivers/staging/lirc/TODO @@ -0,0 +1,8 @@ +- All drivers should either be ported to ir-core, or dropped entirely + (see drivers/media/IR/mceusb.c vs. lirc_mceusb.c in lirc cvs for an + example of a previously completed port). + +Please send patches to: +Jarod Wilson <jarod@wilsonet.com> +Greg Kroah-Hartman <greg@kroah.com> + diff --git a/drivers/staging/lirc/TODO.lirc_i2c b/drivers/staging/lirc/TODO.lirc_i2c new file mode 100644 index 000000000000..1f0a6ff65439 --- /dev/null +++ b/drivers/staging/lirc/TODO.lirc_i2c @@ -0,0 +1,3 @@ +lirc_i2c provides support for some drivers that have already a RC +driver under drivers/media/video. It should be integrated into those +drivers, in special with drivers/media/video/ir-kbd-i2c.c. diff --git a/drivers/staging/lirc/lirc_bt829.c b/drivers/staging/lirc/lirc_bt829.c new file mode 100644 index 000000000000..33881025426b --- /dev/null +++ b/drivers/staging/lirc/lirc_bt829.c @@ -0,0 +1,383 @@ +/* + * Remote control driver for the TV-card based on bt829 + * + * by Leonid Froenchenko <lfroen@galileo.co.il> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/threads.h> +#include <linux/sched.h> +#include <linux/ioport.h> +#include <linux/pci.h> +#include <linux/delay.h> + +#include <media/lirc_dev.h> + +static int poll_main(void); +static int atir_init_start(void); + +static void write_index(unsigned char index, unsigned int value); +static unsigned int read_index(unsigned char index); + +static void do_i2c_start(void); +static void do_i2c_stop(void); + +static void seems_wr_byte(unsigned char al); +static unsigned char seems_rd_byte(void); + +static unsigned int read_index(unsigned char al); +static void write_index(unsigned char ah, unsigned int edx); + +static void cycle_delay(int cycle); + +static void do_set_bits(unsigned char bl); +static unsigned char do_get_bits(void); + +#define DATA_PCI_OFF 0x7FFC00 +#define WAIT_CYCLE 20 + +#define DRIVER_NAME "lirc_bt829" + +static int debug; +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG DRIVER_NAME ": "fmt, ## args); \ + } while (0) + +static int atir_minor; +static unsigned long pci_addr_phys; +static unsigned char *pci_addr_lin; + +static struct lirc_driver atir_driver; + +static struct pci_dev *do_pci_probe(void) +{ + struct pci_dev *my_dev; + my_dev = pci_get_device(PCI_VENDOR_ID_ATI, + PCI_DEVICE_ID_ATI_264VT, NULL); + if (my_dev) { + printk(KERN_ERR DRIVER_NAME ": Using device: %s\n", + pci_name(my_dev)); + pci_addr_phys = 0; + if (my_dev->resource[0].flags & IORESOURCE_MEM) { + pci_addr_phys = my_dev->resource[0].start; + printk(KERN_INFO DRIVER_NAME ": memory at 0x%08X\n", + (unsigned int)pci_addr_phys); + } + if (pci_addr_phys == 0) { + printk(KERN_ERR DRIVER_NAME ": no memory resource ?\n"); + return NULL; + } + } else { + printk(KERN_ERR DRIVER_NAME ": pci_probe failed\n"); + return NULL; + } + return my_dev; +} + +static int atir_add_to_buf(void *data, struct lirc_buffer *buf) +{ + unsigned char key; + int status; + status = poll_main(); + key = (status >> 8) & 0xFF; + if (status & 0xFF) { + dprintk("reading key %02X\n", key); + lirc_buffer_write(buf, &key); + return 0; + } + return -ENODATA; +} + +static int atir_set_use_inc(void *data) +{ + dprintk("driver is opened\n"); + return 0; +} + +static void atir_set_use_dec(void *data) +{ + dprintk("driver is closed\n"); +} + +int init_module(void) +{ + struct pci_dev *pdev; + + pdev = do_pci_probe(); + if (pdev == NULL) + return 1; + + if (!atir_init_start()) + return 1; + + strcpy(atir_driver.name, "ATIR"); + atir_driver.minor = -1; + atir_driver.code_length = 8; + atir_driver.sample_rate = 10; + atir_driver.data = 0; + atir_driver.add_to_buf = atir_add_to_buf; + atir_driver.set_use_inc = atir_set_use_inc; + atir_driver.set_use_dec = atir_set_use_dec; + atir_driver.dev = &pdev->dev; + atir_driver.owner = THIS_MODULE; + + atir_minor = lirc_register_driver(&atir_driver); + if (atir_minor < 0) { + printk(KERN_ERR DRIVER_NAME ": failed to register driver!\n"); + return atir_minor; + } + dprintk("driver is registered on minor %d\n", atir_minor); + + return 0; +} + + +void cleanup_module(void) +{ + lirc_unregister_driver(atir_minor); +} + + +static int atir_init_start(void) +{ + pci_addr_lin = ioremap(pci_addr_phys + DATA_PCI_OFF, 0x400); + if (pci_addr_lin == 0) { + printk(KERN_INFO DRIVER_NAME ": pci mem must be mapped\n"); + return 0; + } + return 1; +} + +static void cycle_delay(int cycle) +{ + udelay(WAIT_CYCLE*cycle); +} + + +static int poll_main() +{ + unsigned char status_high, status_low; + + do_i2c_start(); + + seems_wr_byte(0xAA); + seems_wr_byte(0x01); + + do_i2c_start(); + + seems_wr_byte(0xAB); + + status_low = seems_rd_byte(); + status_high = seems_rd_byte(); + + do_i2c_stop(); + + return (status_high << 8) | status_low; +} + +static void do_i2c_start(void) +{ + do_set_bits(3); + cycle_delay(4); + + do_set_bits(1); + cycle_delay(7); + + do_set_bits(0); + cycle_delay(2); +} + +static void do_i2c_stop(void) +{ + unsigned char bits; + bits = do_get_bits() & 0xFD; + do_set_bits(bits); + cycle_delay(1); + + bits |= 1; + do_set_bits(bits); + cycle_delay(2); + + bits |= 2; + do_set_bits(bits); + bits = 3; + do_set_bits(bits); + cycle_delay(2); +} + +static void seems_wr_byte(unsigned char value) +{ + int i; + unsigned char reg; + + reg = do_get_bits(); + for (i = 0; i < 8; i++) { + if (value & 0x80) + reg |= 0x02; + else + reg &= 0xFD; + + do_set_bits(reg); + cycle_delay(1); + + reg |= 1; + do_set_bits(reg); + cycle_delay(1); + + reg &= 0xFE; + do_set_bits(reg); + cycle_delay(1); + value <<= 1; + } + cycle_delay(2); + + reg |= 2; + do_set_bits(reg); + + reg |= 1; + do_set_bits(reg); + + cycle_delay(1); + do_get_bits(); + + reg &= 0xFE; + do_set_bits(reg); + cycle_delay(3); +} + +static unsigned char seems_rd_byte(void) +{ + int i; + int rd_byte; + unsigned char bits_2, bits_1; + + bits_1 = do_get_bits() | 2; + do_set_bits(bits_1); + + rd_byte = 0; + for (i = 0; i < 8; i++) { + bits_1 &= 0xFE; + do_set_bits(bits_1); + cycle_delay(2); + + bits_1 |= 1; + do_set_bits(bits_1); + cycle_delay(1); + + bits_2 = do_get_bits(); + if (bits_2 & 2) + rd_byte |= 1; + + rd_byte <<= 1; + } + + bits_1 = 0; + if (bits_2 == 0) + bits_1 |= 2; + + do_set_bits(bits_1); + cycle_delay(2); + + bits_1 |= 1; + do_set_bits(bits_1); + cycle_delay(3); + + bits_1 &= 0xFE; + do_set_bits(bits_1); + cycle_delay(2); + + rd_byte >>= 1; + rd_byte &= 0xFF; + return rd_byte; +} + +static void do_set_bits(unsigned char new_bits) +{ + int reg_val; + reg_val = read_index(0x34); + if (new_bits & 2) { + reg_val &= 0xFFFFFFDF; + reg_val |= 1; + } else { + reg_val &= 0xFFFFFFFE; + reg_val |= 0x20; + } + reg_val |= 0x10; + write_index(0x34, reg_val); + + reg_val = read_index(0x31); + if (new_bits & 1) + reg_val |= 0x1000000; + else + reg_val &= 0xFEFFFFFF; + + reg_val |= 0x8000000; + write_index(0x31, reg_val); +} + +static unsigned char do_get_bits(void) +{ + unsigned char bits; + int reg_val; + + reg_val = read_index(0x34); + reg_val |= 0x10; + reg_val &= 0xFFFFFFDF; + write_index(0x34, reg_val); + + reg_val = read_index(0x34); + bits = 0; + if (reg_val & 8) + bits |= 2; + else + bits &= 0xFD; + + reg_val = read_index(0x31); + if (reg_val & 0x1000000) + bits |= 1; + else + bits &= 0xFE; + + return bits; +} + +static unsigned int read_index(unsigned char index) +{ + unsigned char *addr; + unsigned int value; + /* addr = pci_addr_lin + DATA_PCI_OFF + ((index & 0xFF) << 2); */ + addr = pci_addr_lin + ((index & 0xFF) << 2); + value = readl(addr); + return value; +} + +static void write_index(unsigned char index, unsigned int reg_val) +{ + unsigned char *addr; + addr = pci_addr_lin + ((index & 0xFF) << 2); + writel(reg_val, addr); +} + +MODULE_AUTHOR("Froenchenko Leonid"); +MODULE_DESCRIPTION("IR remote driver for bt829 based TV cards"); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); diff --git a/drivers/staging/lirc/lirc_ene0100.c b/drivers/staging/lirc/lirc_ene0100.c new file mode 100644 index 000000000000..a152c52b0745 --- /dev/null +++ b/drivers/staging/lirc/lirc_ene0100.c @@ -0,0 +1,646 @@ +/* + * driver for ENE KB3926 B/C/D CIR (also known as ENE0100) + * + * Copyright (C) 2009 Maxim Levitsky <maximlevitsky@gmail.com> + * + * 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; either version 2 of the + * License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pnp.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include "lirc_ene0100.h" + +static int sample_period = 75; +static int enable_idle = 1; +static int enable_learning; + +static void ene_set_idle(struct ene_device *dev, int idle); +static void ene_set_inputs(struct ene_device *dev, int enable); + +/* read a hardware register */ +static u8 ene_hw_read_reg(struct ene_device *dev, u16 reg) +{ + outb(reg >> 8, dev->hw_io + ENE_ADDR_HI); + outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO); + return inb(dev->hw_io + ENE_IO); +} + +/* write a hardware register */ +static void ene_hw_write_reg(struct ene_device *dev, u16 reg, u8 value) +{ + outb(reg >> 8, dev->hw_io + ENE_ADDR_HI); + outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO); + outb(value, dev->hw_io + ENE_IO); +} + +/* change specific bits in hardware register */ +static void ene_hw_write_reg_mask(struct ene_device *dev, + u16 reg, u8 value, u8 mask) +{ + u8 regvalue; + + outb(reg >> 8, dev->hw_io + ENE_ADDR_HI); + outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO); + + regvalue = inb(dev->hw_io + ENE_IO) & ~mask; + regvalue |= (value & mask); + outb(regvalue, dev->hw_io + ENE_IO); +} + +/* read irq status and ack it */ +static int ene_hw_irq_status(struct ene_device *dev, int *buffer_pointer) +{ + u8 irq_status; + u8 fw_flags1, fw_flags2; + + fw_flags2 = ene_hw_read_reg(dev, ENE_FW2); + + if (buffer_pointer) + *buffer_pointer = 4 * (fw_flags2 & ENE_FW2_BUF_HIGH); + + if (dev->hw_revision < ENE_HW_C) { + irq_status = ene_hw_read_reg(dev, ENEB_IRQ_STATUS); + + if (!(irq_status & ENEB_IRQ_STATUS_IR)) + return 0; + ene_hw_write_reg(dev, ENEB_IRQ_STATUS, + irq_status & ~ENEB_IRQ_STATUS_IR); + + /* rev B support only recieving */ + return ENE_IRQ_RX; + } + + irq_status = ene_hw_read_reg(dev, ENEC_IRQ); + + if (!(irq_status & ENEC_IRQ_STATUS)) + return 0; + + /* original driver does that twice - a workaround ? */ + ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS); + ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS); + + /* clear unknown flag in F8F9 */ + if (fw_flags2 & ENE_FW2_IRQ_CLR) + ene_hw_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_IRQ_CLR); + + /* check if this is a TX interrupt */ + fw_flags1 = ene_hw_read_reg(dev, ENE_FW1); + + if (fw_flags1 & ENE_FW1_TXIRQ) { + ene_hw_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ); + return ENE_IRQ_TX; + } else + return ENE_IRQ_RX; +} + +static int ene_hw_detect(struct ene_device *dev) +{ + u8 chip_major, chip_minor; + u8 hw_revision, old_ver; + u8 tmp; + u8 fw_capabilities; + + tmp = ene_hw_read_reg(dev, ENE_HW_UNK); + ene_hw_write_reg(dev, ENE_HW_UNK, tmp & ~ENE_HW_UNK_CLR); + + chip_major = ene_hw_read_reg(dev, ENE_HW_VER_MAJOR); + chip_minor = ene_hw_read_reg(dev, ENE_HW_VER_MINOR); + + ene_hw_write_reg(dev, ENE_HW_UNK, tmp); + hw_revision = ene_hw_read_reg(dev, ENE_HW_VERSION); + old_ver = ene_hw_read_reg(dev, ENE_HW_VER_OLD); + + if (hw_revision == 0xFF) { + + ene_printk(KERN_WARNING, "device seems to be disabled\n"); + ene_printk(KERN_WARNING, + "send a mail to lirc-list@lists.sourceforge.net\n"); + ene_printk(KERN_WARNING, "please attach output of acpidump\n"); + + return -ENODEV; + } + + if (chip_major == 0x33) { + ene_printk(KERN_WARNING, "chips 0x33xx aren't supported yet\n"); + return -ENODEV; + } + + if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) { + dev->hw_revision = ENE_HW_C; + ene_printk(KERN_WARNING, + "KB3926C detected, driver support is not complete!\n"); + + } else if (old_ver == 0x24 && hw_revision == 0xC0) { + dev->hw_revision = ENE_HW_B; + ene_printk(KERN_NOTICE, "KB3926B detected\n"); + } else { + dev->hw_revision = ENE_HW_D; + ene_printk(KERN_WARNING, + "unknown ENE chip detected, assuming KB3926D\n"); + ene_printk(KERN_WARNING, "driver support incomplete"); + + } + + ene_printk(KERN_DEBUG, "chip is 0x%02x%02x - 0x%02x, 0x%02x\n", + chip_major, chip_minor, old_ver, hw_revision); + + + /* detect features hardware supports */ + + if (dev->hw_revision < ENE_HW_C) + return 0; + + fw_capabilities = ene_hw_read_reg(dev, ENE_FW2); + + dev->hw_gpio40_learning = fw_capabilities & ENE_FW2_GP40_AS_LEARN; + dev->hw_learning_and_tx_capable = fw_capabilities & ENE_FW2_LEARNING; + + dev->hw_fan_as_normal_input = dev->hw_learning_and_tx_capable && + fw_capabilities & ENE_FW2_FAN_AS_NRML_IN; + + ene_printk(KERN_NOTICE, "hardware features:\n"); + ene_printk(KERN_NOTICE, + "learning and tx %s, gpio40_learn %s, fan_in %s\n", + dev->hw_learning_and_tx_capable ? "on" : "off", + dev->hw_gpio40_learning ? "on" : "off", + dev->hw_fan_as_normal_input ? "on" : "off"); + + if (!dev->hw_learning_and_tx_capable && enable_learning) + enable_learning = 0; + + if (dev->hw_learning_and_tx_capable) { + ene_printk(KERN_WARNING, + "Device supports transmitting, but the driver doesn't\n"); + ene_printk(KERN_WARNING, + "due to lack of hardware to test against.\n"); + ene_printk(KERN_WARNING, + "Send a mail to: lirc-list@lists.sourceforge.net\n"); + } + return 0; +} + +/* hardware initialization */ +static int ene_hw_init(void *data) +{ + u8 reg_value; + struct ene_device *dev = (struct ene_device *)data; + dev->in_use = 1; + + if (dev->hw_revision < ENE_HW_C) { + ene_hw_write_reg(dev, ENEB_IRQ, dev->irq << 1); + ene_hw_write_reg(dev, ENEB_IRQ_UNK1, 0x01); + } else { + reg_value = ene_hw_read_reg(dev, ENEC_IRQ) & 0xF0; + reg_value |= ENEC_IRQ_UNK_EN; + reg_value &= ~ENEC_IRQ_STATUS; + reg_value |= (dev->irq & ENEC_IRQ_MASK); + ene_hw_write_reg(dev, ENEC_IRQ, reg_value); + ene_hw_write_reg(dev, ENE_TX_UNK1, 0x63); + } + + ene_hw_write_reg(dev, ENE_CIR_CONF2, 0x00); + ene_set_inputs(dev, enable_learning); + + /* set sampling period */ + ene_hw_write_reg(dev, ENE_CIR_SAMPLE_PERIOD, sample_period); + + /* ack any pending irqs - just in case */ + ene_hw_irq_status(dev, NULL); + + /* enter idle mode */ + ene_set_idle(dev, 1); + + /* enable firmware bits */ + ene_hw_write_reg_mask(dev, ENE_FW1, + ENE_FW1_ENABLE | ENE_FW1_IRQ, + ENE_FW1_ENABLE | ENE_FW1_IRQ); + /* clear stats */ + dev->sample = 0; + return 0; +} + +/* this enables gpio40 signal, used if connected to wide band input*/ +static void ene_enable_gpio40(struct ene_device *dev, int enable) +{ + ene_hw_write_reg_mask(dev, ENE_CIR_CONF1, enable ? + 0 : ENE_CIR_CONF2_GPIO40DIS, + ENE_CIR_CONF2_GPIO40DIS); +} + +/* this enables the classic sampler */ +static void ene_enable_normal_recieve(struct ene_device *dev, int enable) +{ + ene_hw_write_reg(dev, ENE_CIR_CONF1, enable ? ENE_CIR_CONF1_ADC_ON : 0); +} + +/* this enables recieve via fan input */ +static void ene_enable_fan_recieve(struct ene_device *dev, int enable) +{ + if (!enable) + ene_hw_write_reg(dev, ENE_FAN_AS_IN1, 0); + else { + ene_hw_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN); + ene_hw_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN); + } + dev->fan_input_inuse = enable; +} + +/* determine which input to use*/ +static void ene_set_inputs(struct ene_device *dev, int learning_enable) +{ + ene_enable_normal_recieve(dev, 1); + + /* old hardware doesn't support learning mode for sure */ + if (dev->hw_revision <= ENE_HW_B) + return; + + /* reciever not learning capable, still set gpio40 correctly */ + if (!dev->hw_learning_and_tx_capable) { + ene_enable_gpio40(dev, !dev->hw_gpio40_learning); + return; + } + + /* enable learning mode */ + if (learning_enable) { + ene_enable_gpio40(dev, dev->hw_gpio40_learning); + + /* fan input is not used for learning */ + if (dev->hw_fan_as_normal_input) + ene_enable_fan_recieve(dev, 0); + + /* disable learning mode */ + } else { + if (dev->hw_fan_as_normal_input) { + ene_enable_fan_recieve(dev, 1); + ene_enable_normal_recieve(dev, 0); + } else + ene_enable_gpio40(dev, !dev->hw_gpio40_learning); + } + + /* set few additional settings for this mode */ + ene_hw_write_reg_mask(dev, ENE_CIR_CONF1, learning_enable ? + ENE_CIR_CONF1_LEARN1 : 0, ENE_CIR_CONF1_LEARN1); + + ene_hw_write_reg_mask(dev, ENE_CIR_CONF2, learning_enable ? + ENE_CIR_CONF2_LEARN2 : 0, ENE_CIR_CONF2_LEARN2); +} + +/* deinitialization */ +static void ene_hw_deinit(void *data) +{ + struct ene_device *dev = (struct ene_device *)data; + + /* disable samplers */ + ene_enable_normal_recieve(dev, 0); + + if (dev->hw_fan_as_normal_input) + ene_enable_fan_recieve(dev, 0); + + /* disable hardware IRQ and firmware flag */ + ene_hw_write_reg_mask(dev, ENE_FW1, 0, ENE_FW1_ENABLE | ENE_FW1_IRQ); + + ene_set_idle(dev, 1); + dev->in_use = 0; +} + +/* sends current sample to userspace */ +static void send_sample(struct ene_device *dev) +{ + int value = abs(dev->sample) & PULSE_MASK; + + if (dev->sample > 0) + value |= PULSE_BIT; + + if (!lirc_buffer_full(dev->lirc_driver->rbuf)) { + lirc_buffer_write(dev->lirc_driver->rbuf, (void *)&value); + wake_up(&dev->lirc_driver->rbuf->wait_poll); + } + dev->sample = 0; +} + +/* this updates current sample */ +static void update_sample(struct ene_device *dev, int sample) +{ + if (!dev->sample) + dev->sample = sample; + else if (same_sign(dev->sample, sample)) + dev->sample += sample; + else { + send_sample(dev); + dev->sample = sample; + } +} + +/* enable or disable idle mode */ +static void ene_set_idle(struct ene_device *dev, int idle) +{ + struct timeval now; + int disable = idle && enable_idle && (dev->hw_revision < ENE_HW_C); + + ene_hw_write_reg_mask(dev, ENE_CIR_SAMPLE_PERIOD, + disable ? 0 : ENE_CIR_SAMPLE_OVERFLOW, + ENE_CIR_SAMPLE_OVERFLOW); + dev->idle = idle; + + /* remember when we have entered the idle mode */ + if (idle) { + do_gettimeofday(&dev->gap_start); + return; + } + + /* send the gap between keypresses now */ + do_gettimeofday(&now); + + if (now.tv_sec - dev->gap_start.tv_sec > 16) + dev->sample = space(PULSE_MASK); + else + dev->sample = dev->sample + + space(1000000ull * (now.tv_sec - dev->gap_start.tv_sec)) + + space(now.tv_usec - dev->gap_start.tv_usec); + + if (abs(dev->sample) > PULSE_MASK) + dev->sample = space(PULSE_MASK); + send_sample(dev); +} + +/* interrupt handler */ +static irqreturn_t ene_hw_irq(int irq, void *data) +{ + u16 hw_value; + int i, hw_sample; + int space; + int buffer_pointer; + int irq_status; + + struct ene_device *dev = (struct ene_device *)data; + irq_status = ene_hw_irq_status(dev, &buffer_pointer); + + if (!irq_status) + return IRQ_NONE; + + /* TODO: only RX for now */ + if (irq_status == ENE_IRQ_TX) + return IRQ_HANDLED; + + for (i = 0; i < ENE_SAMPLES_SIZE; i++) { + + hw_value = ene_hw_read_reg(dev, + ENE_SAMPLE_BUFFER + buffer_pointer + i); + + if (dev->fan_input_inuse) { + /* read high part of the sample */ + hw_value |= ene_hw_read_reg(dev, + ENE_SAMPLE_BUFFER_FAN + buffer_pointer + i) << 8; + + /* test for _space_ bit */ + space = !(hw_value & ENE_FAN_SMPL_PULS_MSK); + + /* clear space bit, and other unused bits */ + hw_value &= ENE_FAN_VALUE_MASK; + hw_sample = hw_value * ENE_SAMPLE_PERIOD_FAN; + + } else { + space = hw_value & ENE_SAMPLE_SPC_MASK; + hw_value &= ENE_SAMPLE_VALUE_MASK; + hw_sample = hw_value * sample_period; + } + + /* no more data */ + if (!(hw_value)) + break; + + if (space) + hw_sample *= -1; + + /* overflow sample recieved, handle it */ + + if (!dev->fan_input_inuse && hw_value == ENE_SAMPLE_OVERFLOW) { + + if (dev->idle) + continue; + + if (dev->sample > 0 || abs(dev->sample) <= ENE_MAXGAP) + update_sample(dev, hw_sample); + else + ene_set_idle(dev, 1); + + continue; + } + + /* normal first sample recieved */ + if (!dev->fan_input_inuse && dev->idle) { + ene_set_idle(dev, 0); + + /* discard first recieved value, its random + since its the time signal was off before + first pulse if idle mode is enabled, HW + does that for us */ + + if (!enable_idle) + continue; + } + update_sample(dev, hw_sample); + send_sample(dev); + } + return IRQ_HANDLED; +} + +static int ene_probe(struct pnp_dev *pnp_dev, + const struct pnp_device_id *dev_id) +{ + struct ene_device *dev; + struct lirc_driver *lirc_driver; + int error = -ENOMEM; + + dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL); + + if (!dev) + goto err1; + + dev->pnp_dev = pnp_dev; + pnp_set_drvdata(pnp_dev, dev); + + + /* prepare lirc interface */ + error = -ENOMEM; + lirc_driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); + + if (!lirc_driver) + goto err2; + + dev->lirc_driver = lirc_driver; + + strcpy(lirc_driver->name, ENE_DRIVER_NAME); + lirc_driver->minor = -1; + lirc_driver->code_length = sizeof(int) * 8; + lirc_driver->features = LIRC_CAN_REC_MODE2; + lirc_driver->data = dev; + lirc_driver->set_use_inc = ene_hw_init; + lirc_driver->set_use_dec = ene_hw_deinit; + lirc_driver->dev = &pnp_dev->dev; + lirc_driver->owner = THIS_MODULE; + + lirc_driver->rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + + if (!lirc_driver->rbuf) + goto err3; + + if (lirc_buffer_init(lirc_driver->rbuf, sizeof(int), sizeof(int) * 256)) + goto err4; + + error = -ENODEV; + if (lirc_register_driver(lirc_driver)) + goto err5; + + /* validate resources */ + if (!pnp_port_valid(pnp_dev, 0) || + pnp_port_len(pnp_dev, 0) < ENE_MAX_IO) + goto err6; + + if (!pnp_irq_valid(pnp_dev, 0)) + goto err6; + + dev->hw_io = pnp_port_start(pnp_dev, 0); + dev->irq = pnp_irq(pnp_dev, 0); + + /* claim the resources */ + error = -EBUSY; + if (!request_region(dev->hw_io, ENE_MAX_IO, ENE_DRIVER_NAME)) + goto err6; + + if (request_irq(dev->irq, ene_hw_irq, + IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) + goto err7; + + /* detect hardware version and features */ + error = ene_hw_detect(dev); + if (error) + goto err8; + + ene_printk(KERN_NOTICE, "driver has been succesfully loaded\n"); + return 0; + +err8: + free_irq(dev->irq, dev); +err7: + release_region(dev->hw_io, ENE_MAX_IO); +err6: + lirc_unregister_driver(lirc_driver->minor); +err5: + lirc_buffer_free(lirc_driver->rbuf); +err4: + kfree(lirc_driver->rbuf); +err3: + kfree(lirc_driver); +err2: + kfree(dev); +err1: + return error; +} + +static void ene_remove(struct pnp_dev *pnp_dev) +{ + struct ene_device *dev = pnp_get_drvdata(pnp_dev); + ene_hw_deinit(dev); + free_irq(dev->irq, dev); + release_region(dev->hw_io, ENE_MAX_IO); + lirc_unregister_driver(dev->lirc_driver->minor); + lirc_buffer_free(dev->lirc_driver->rbuf); + kfree(dev->lirc_driver); + kfree(dev); +} + +#ifdef CONFIG_PM + +/* TODO: make 'wake on IR' configurable and add .shutdown */ +/* currently impossible due to lack of kernel support */ + +static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state) +{ + struct ene_device *dev = pnp_get_drvdata(pnp_dev); + ene_hw_write_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, ENE_FW1_WAKE); + return 0; +} + +static int ene_resume(struct pnp_dev *pnp_dev) +{ + struct ene_device *dev = pnp_get_drvdata(pnp_dev); + if (dev->in_use) + ene_hw_init(dev); + + ene_hw_write_reg_mask(dev, ENE_FW1, 0, ENE_FW1_WAKE); + return 0; +} + +#endif + +static const struct pnp_device_id ene_ids[] = { + {.id = "ENE0100",}, + {}, +}; + +static struct pnp_driver ene_driver = { + .name = ENE_DRIVER_NAME, + .id_table = ene_ids, + .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, + + .probe = ene_probe, + .remove = __devexit_p(ene_remove), + +#ifdef CONFIG_PM + .suspend = ene_suspend, + .resume = ene_resume, +#endif +}; + +static int __init ene_init(void) +{ + if (sample_period < 5) { + ene_printk(KERN_ERR, "sample period must be at\n"); + ene_printk(KERN_ERR, "least 5 us, (at least 30 recommended)\n"); + return -EINVAL; + } + return pnp_register_driver(&ene_driver); +} + +static void ene_exit(void) +{ + pnp_unregister_driver(&ene_driver); +} + +module_param(sample_period, int, S_IRUGO); +MODULE_PARM_DESC(sample_period, "Hardware sample period (75 us default)"); + +module_param(enable_idle, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(enable_idle, + "Enables turning off signal sampling after long inactivity time; " + "if disabled might help detecting input signal (default: enabled)"); + +module_param(enable_learning, bool, S_IRUGO); +MODULE_PARM_DESC(enable_learning, "Use wide band (learning) reciever"); + +MODULE_DEVICE_TABLE(pnp, ene_ids); +MODULE_DESCRIPTION + ("LIRC driver for KB3926B/KB3926C/KB3926D (aka ENE0100) CIR port"); +MODULE_AUTHOR("Maxim Levitsky"); +MODULE_LICENSE("GPL"); + +module_init(ene_init); +module_exit(ene_exit); diff --git a/drivers/staging/lirc/lirc_ene0100.h b/drivers/staging/lirc/lirc_ene0100.h new file mode 100644 index 000000000000..776b693bb307 --- /dev/null +++ b/drivers/staging/lirc/lirc_ene0100.h @@ -0,0 +1,169 @@ +/* + * driver for ENE KB3926 B/C/D CIR (also known as ENE0100) + * + * Copyright (C) 2009 Maxim Levitsky <maximlevitsky@gmail.com> + * + * 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; either version 2 of the + * License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include <media/lirc.h> +#include <media/lirc_dev.h> + +/* hardware address */ +#define ENE_STATUS 0 /* hardware status - unused */ +#define ENE_ADDR_HI 1 /* hi byte of register address */ +#define ENE_ADDR_LO 2 /* low byte of register address */ +#define ENE_IO 3 /* read/write window */ +#define ENE_MAX_IO 4 + +/* 8 bytes of samples, divided in 2 halfs*/ +#define ENE_SAMPLE_BUFFER 0xF8F0 /* regular sample buffer */ +#define ENE_SAMPLE_SPC_MASK (1 << 7) /* sample is space */ +#define ENE_SAMPLE_VALUE_MASK 0x7F +#define ENE_SAMPLE_OVERFLOW 0x7F +#define ENE_SAMPLES_SIZE 4 + +/* fan input sample buffer */ +#define ENE_SAMPLE_BUFFER_FAN 0xF8FB /* this buffer holds high byte of */ + /* each sample of normal buffer */ + +#define ENE_FAN_SMPL_PULS_MSK 0x8000 /* this bit of combined sample */ + /* if set, says that sample is pulse */ +#define ENE_FAN_VALUE_MASK 0x0FFF /* mask for valid bits of the value */ + +/* first firmware register */ +#define ENE_FW1 0xF8F8 +#define ENE_FW1_ENABLE (1 << 0) /* enable fw processing */ +#define ENE_FW1_TXIRQ (1 << 1) /* TX interrupt pending */ +#define ENE_FW1_WAKE (1 << 6) /* enable wake from S3 */ +#define ENE_FW1_IRQ (1 << 7) /* enable interrupt */ + +/* second firmware register */ +#define ENE_FW2 0xF8F9 +#define ENE_FW2_BUF_HIGH (1 << 0) /* which half of the buffer to read */ +#define ENE_FW2_IRQ_CLR (1 << 2) /* clear this on IRQ */ +#define ENE_FW2_GP40_AS_LEARN (1 << 4) /* normal input is used as */ + /* learning input */ +#define ENE_FW2_FAN_AS_NRML_IN (1 << 6) /* fan is used as normal input */ +#define ENE_FW2_LEARNING (1 << 7) /* hardware supports learning and TX */ + +/* fan as input settings - only if learning capable */ +#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */ +#define ENE_FAN_AS_IN1_EN 0xCD +#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */ +#define ENE_FAN_AS_IN2_EN 0x03 +#define ENE_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */ + +/* IRQ registers block (for revision B) */ +#define ENEB_IRQ 0xFD09 /* IRQ number */ +#define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */ +#define ENEB_IRQ_STATUS 0xFD80 /* irq status */ +#define ENEB_IRQ_STATUS_IR (1 << 5) /* IR irq */ + +/* IRQ registers block (for revision C,D) */ +#define ENEC_IRQ 0xFE9B /* new irq settings register */ +#define ENEC_IRQ_MASK 0x0F /* irq number mask */ +#define ENEC_IRQ_UNK_EN (1 << 4) /* always enabled */ +#define ENEC_IRQ_STATUS (1 << 5) /* irq status and ACK */ + +/* CIR block settings */ +#define ENE_CIR_CONF1 0xFEC0 +#define ENE_CIR_CONF1_ADC_ON 0x7 /* reciever on gpio40 enabled */ +#define ENE_CIR_CONF1_LEARN1 (1 << 3) /* enabled on learning mode */ +#define ENE_CIR_CONF1_TX_ON 0x30 /* enabled on transmit */ +#define ENE_CIR_CONF1_TX_CARR (1 << 7) /* send TX carrier or not */ + +#define ENE_CIR_CONF2 0xFEC1 /* unknown setting = 0 */ +#define ENE_CIR_CONF2_LEARN2 (1 << 4) /* set on enable learning */ +#define ENE_CIR_CONF2_GPIO40DIS (1 << 5) /* disable normal input via gpio40 */ + +#define ENE_CIR_SAMPLE_PERIOD 0xFEC8 /* sample period in us */ +#define ENE_CIR_SAMPLE_OVERFLOW (1 << 7) /* interrupt on overflows if set */ + + +/* transmitter - not implemented yet */ +/* KB3926C and higher */ +/* transmission is very similiar to recieving, a byte is written to */ +/* ENE_TX_INPUT, in same manner as it is read from sample buffer */ +/* sample period is fixed*/ + + +/* transmitter ports */ +#define ENE_TX_PORT1 0xFC01 /* this enables one or both */ +#define ENE_TX_PORT1_EN (1 << 5) /* TX ports */ +#define ENE_TX_PORT2 0xFC08 +#define ENE_TX_PORT2_EN (1 << 1) + +#define ENE_TX_INPUT 0xFEC9 /* next byte to transmit */ +#define ENE_TX_SPC_MASK (1 << 7) /* Transmitted sample is space */ +#define ENE_TX_UNK1 0xFECB /* set to 0x63 */ +#define ENE_TX_SMPL_PERIOD 50 /* transmit sample period */ + + +#define ENE_TX_CARRIER 0xFECE /* TX carrier * 2 (khz) */ +#define ENE_TX_CARRIER_UNKBIT 0x80 /* This bit set on transmit */ +#define ENE_TX_CARRIER_LOW 0xFECF /* TX carrier / 2 */ + +/* Hardware versions */ +#define ENE_HW_VERSION 0xFF00 /* hardware revision */ +#define ENE_HW_UNK 0xFF1D +#define ENE_HW_UNK_CLR (1 << 2) +#define ENE_HW_VER_MAJOR 0xFF1E /* chip version */ +#define ENE_HW_VER_MINOR 0xFF1F +#define ENE_HW_VER_OLD 0xFD00 + +#define same_sign(a, b) ((((a) > 0) && (b) > 0) || ((a) < 0 && (b) < 0)) + +#define ENE_DRIVER_NAME "enecir" +#define ENE_MAXGAP 250000 /* this is amount of time we wait + before turning the sampler, chosen + arbitry */ + +#define space(len) (-(len)) /* add a space */ + +/* software defines */ +#define ENE_IRQ_RX 1 +#define ENE_IRQ_TX 2 + +#define ENE_HW_B 1 /* 3926B */ +#define ENE_HW_C 2 /* 3926C */ +#define ENE_HW_D 3 /* 3926D */ + +#define ene_printk(level, text, ...) \ + printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__) + +struct ene_device { + struct pnp_dev *pnp_dev; + struct lirc_driver *lirc_driver; + + /* hw settings */ + unsigned long hw_io; + int irq; + + int hw_revision; /* hardware revision */ + int hw_learning_and_tx_capable; /* learning capable */ + int hw_gpio40_learning; /* gpio40 is learning */ + int hw_fan_as_normal_input; /* fan input is used as regular input */ + + /* device data */ + int idle; + int fan_input_inuse; + + int sample; + int in_use; + + struct timeval gap_start; +}; diff --git a/drivers/staging/lirc/lirc_i2c.c b/drivers/staging/lirc/lirc_i2c.c new file mode 100644 index 000000000000..6df2c0e8d721 --- /dev/null +++ b/drivers/staging/lirc/lirc_i2c.c @@ -0,0 +1,536 @@ +/* + * lirc_i2c.c + * + * i2c IR driver for the onboard IR port on many TV tuner cards, including: + * -Flavors of the Hauppauge PVR-150/250/350 + * -Hauppauge HVR-1300 + * -PixelView (BT878P+W/FM) + * -KNC ONE TV Station/Anubis Typhoon TView Tuner + * -Asus TV-Box and Creative/VisionTek BreakOut-Box + * -Leadtek Winfast PVR2000 + * + * Copyright (c) 2000 Gerd Knorr <kraxel@goldbach.in-berlin.de> + * modified for PixelView (BT878P+W/FM) by + * Michal Kochanowicz <mkochano@pld.org.pl> + * Christoph Bartelmus <lirc@bartelmus.de> + * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by + * Ulrich Mueller <ulrich.mueller42@web.de> + * modified for Asus TV-Box and Creative/VisionTek BreakOut-Box by + * Stefan Jahn <stefan@lkcc.org> + * modified for inclusion into kernel sources by + * Jerome Brock <jbrock@users.sourceforge.net> + * modified for Leadtek Winfast PVR2000 by + * Thomas Reitmayr (treitmayr@yahoo.com) + * modified for Hauppauge HVR-1300 by + * Jan Frey (jfrey@gmx.de) + * + * parts are cut&pasted from the old lirc_haup.c driver + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/kmod.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/string.h> +#include <linux/timer.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/i2c-algo-bit.h> + +#include <media/lirc_dev.h> + +struct IR { + struct lirc_driver l; + struct i2c_client c; + int nextkey; + unsigned char b[3]; + unsigned char bits; + unsigned char flag; +}; + +#define DEVICE_NAME "lirc_i2c" + +/* module parameters */ +static int debug; /* debug output */ +static int minor = -1; /* minor number */ + +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG DEVICE_NAME ": " fmt, \ + ## args); \ + } while (0) + +static int reverse(int data, int bits) +{ + int i; + int c; + + for (c = 0, i = 0; i < bits; i++) + c |= ((data & (1<<i)) ? 1 : 0) << (bits-1-i); + + return c; +} + +static int add_to_buf_adap(void *data, struct lirc_buffer *buf) +{ + struct IR *ir = data; + unsigned char keybuf[4]; + + keybuf[0] = 0x00; + i2c_master_send(&ir->c, keybuf, 1); + /* poll IR chip */ + if (i2c_master_recv(&ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) { + dprintk("read error\n"); + return -EIO; + } + + dprintk("key (0x%02x%02x%02x%02x)\n", + keybuf[0], keybuf[1], keybuf[2], keybuf[3]); + + /* key pressed ? */ + if (keybuf[2] == 0xff) + return -ENODATA; + + /* remove repeat bit */ + keybuf[2] &= 0x7f; + keybuf[3] |= 0x80; + + lirc_buffer_write(buf, keybuf); + return 0; +} + +static int add_to_buf_pcf8574(void *data, struct lirc_buffer *buf) +{ + struct IR *ir = data; + int rc; + unsigned char all, mask; + unsigned char key; + + /* compute all valid bits (key code + pressed/release flag) */ + all = ir->bits | ir->flag; + + /* save IR writable mask bits */ + mask = i2c_smbus_read_byte(&ir->c) & ~all; + + /* send bit mask */ + rc = i2c_smbus_write_byte(&ir->c, (0xff & all) | mask); + + /* receive scan code */ + rc = i2c_smbus_read_byte(&ir->c); + + if (rc == -1) { + dprintk("%s read error\n", ir->c.name); + return -EIO; + } + + /* drop duplicate polls */ + if (ir->b[0] == (rc & all)) + return -ENODATA; + + ir->b[0] = rc & all; + + dprintk("%s key 0x%02X %s\n", ir->c.name, rc & ir->bits, + (rc & ir->flag) ? "released" : "pressed"); + + /* ignore released buttons */ + if (rc & ir->flag) + return -ENODATA; + + /* set valid key code */ + key = rc & ir->bits; + lirc_buffer_write(buf, &key); + return 0; +} + +/* common for Hauppauge IR receivers */ +static int add_to_buf_haup_common(void *data, struct lirc_buffer *buf, + unsigned char *keybuf, int size, int offset) +{ + struct IR *ir = data; + __u16 code; + unsigned char codes[2]; + int ret; + + /* poll IR chip */ + ret = i2c_master_recv(&ir->c, keybuf, size); + if (ret == size) { + ir->b[0] = keybuf[offset]; + ir->b[1] = keybuf[offset+1]; + ir->b[2] = keybuf[offset+2]; + if (ir->b[0] != 0x00 && ir->b[1] != 0x00) + dprintk("key (0x%02x/0x%02x)\n", ir->b[0], ir->b[1]); + } else { + dprintk("read error (ret=%d)\n", ret); + /* keep last successful read buffer */ + } + + /* key pressed ? */ + if ((ir->b[0] & 0x80) == 0) + return -ENODATA; + + /* look what we have */ + code = (((__u16)ir->b[0]&0x7f)<<6) | (ir->b[1]>>2); + + codes[0] = (code >> 8) & 0xff; + codes[1] = code & 0xff; + + /* return it */ + dprintk("sending code 0x%02x%02x to lirc\n", codes[0], codes[1]); + lirc_buffer_write(buf, codes); + return 0; +} + +/* specific for the Hauppauge PVR150 IR receiver */ +static int add_to_buf_haup_pvr150(void *data, struct lirc_buffer *buf) +{ + unsigned char keybuf[6]; + /* fetch 6 bytes, first relevant is at offset 3 */ + return add_to_buf_haup_common(data, buf, keybuf, 6, 3); +} + +/* used for all Hauppauge IR receivers but the PVR150 */ +static int add_to_buf_haup(void *data, struct lirc_buffer *buf) +{ + unsigned char keybuf[3]; + /* fetch 3 bytes, first relevant is at offset 0 */ + return add_to_buf_haup_common(data, buf, keybuf, 3, 0); +} + + +static int add_to_buf_pvr2000(void *data, struct lirc_buffer *buf) +{ + struct IR *ir = data; + unsigned char key; + s32 flags; + s32 code; + + /* poll IR chip */ + flags = i2c_smbus_read_byte_data(&ir->c, 0x10); + if (-1 == flags) { + dprintk("read error\n"); + return -ENODATA; + } + /* key pressed ? */ + if (0 == (flags & 0x80)) + return -ENODATA; + + /* read actual key code */ + code = i2c_smbus_read_byte_data(&ir->c, 0x00); + if (-1 == code) { + dprintk("read error\n"); + return -ENODATA; + } + + key = code & 0xFF; + + dprintk("IR Key/Flags: (0x%02x/0x%02x)\n", key, flags & 0xFF); + + /* return it */ + lirc_buffer_write(buf, &key); + return 0; +} + +static int add_to_buf_pixelview(void *data, struct lirc_buffer *buf) +{ + struct IR *ir = data; + unsigned char key; + + /* poll IR chip */ + if (1 != i2c_master_recv(&ir->c, &key, 1)) { + dprintk("read error\n"); + return -1; + } + dprintk("key %02x\n", key); + + /* return it */ + lirc_buffer_write(buf, &key); + return 0; +} + +static int add_to_buf_pv951(void *data, struct lirc_buffer *buf) +{ + struct IR *ir = data; + unsigned char key; + unsigned char codes[4]; + + /* poll IR chip */ + if (1 != i2c_master_recv(&ir->c, &key, 1)) { + dprintk("read error\n"); + return -ENODATA; + } + /* ignore 0xaa */ + if (key == 0xaa) + return -ENODATA; + dprintk("key %02x\n", key); + + codes[0] = 0x61; + codes[1] = 0xD6; + codes[2] = reverse(key, 8); + codes[3] = (~codes[2])&0xff; + + lirc_buffer_write(buf, codes); + return 0; +} + +static int add_to_buf_knc1(void *data, struct lirc_buffer *buf) +{ + static unsigned char last_key = 0xFF; + struct IR *ir = data; + unsigned char key; + + /* poll IR chip */ + if (1 != i2c_master_recv(&ir->c, &key, 1)) { + dprintk("read error\n"); + return -ENODATA; + } + + /* + * it seems that 0xFE indicates that a button is still held + * down, while 0xFF indicates that no button is held + * down. 0xFE sequences are sometimes interrupted by 0xFF + */ + + dprintk("key %02x\n", key); + + if (key == 0xFF) + return -ENODATA; + + if (key == 0xFE) + key = last_key; + + last_key = key; + lirc_buffer_write(buf, &key); + + return 0; +} + +static int set_use_inc(void *data) +{ + struct IR *ir = data; + + dprintk("%s called\n", __func__); + + /* lock bttv in memory while /dev/lirc is in use */ + i2c_use_client(&ir->c); + + return 0; +} + +static void set_use_dec(void *data) +{ + struct IR *ir = data; + + dprintk("%s called\n", __func__); + + i2c_release_client(&ir->c); +} + +static struct lirc_driver lirc_template = { + .name = "lirc_i2c", + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .dev = NULL, + .owner = THIS_MODULE, +}; + +static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id); +static int ir_remove(struct i2c_client *client); +static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg); + +static const struct i2c_device_id ir_receiver_id[] = { + /* Generic entry for any IR receiver */ + { "ir_video", 0 }, + /* IR device specific entries could be added here */ + { } +}; + +static struct i2c_driver driver = { + .driver = { + .owner = THIS_MODULE, + .name = "i2c ir driver", + }, + .probe = ir_probe, + .remove = ir_remove, + .id_table = ir_receiver_id, + .command = ir_command, +}; + +static void pcf_probe(struct i2c_client *client, struct IR *ir) +{ + int ret1, ret2, ret3, ret4; + + ret1 = i2c_smbus_write_byte(client, 0xff); + ret2 = i2c_smbus_read_byte(client); + ret3 = i2c_smbus_write_byte(client, 0x00); + ret4 = i2c_smbus_read_byte(client); + + /* in the Asus TV-Box: bit 1-0 */ + if (((ret2 & 0x03) == 0x03) && ((ret4 & 0x03) == 0x00)) { + ir->bits = (unsigned char) ~0x07; + ir->flag = 0x04; + /* in the Creative/VisionTek BreakOut-Box: bit 7-6 */ + } else if (((ret2 & 0xc0) == 0xc0) && ((ret4 & 0xc0) == 0x00)) { + ir->bits = (unsigned char) ~0xe0; + ir->flag = 0x20; + } + + return; +} + +static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct IR *ir; + struct i2c_adapter *adap = client->adapter; + unsigned short addr = client->addr; + int retval; + + ir = kzalloc(sizeof(struct IR), GFP_KERNEL); + if (!ir) + return -ENOMEM; + memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); + memcpy(&ir->c, client, sizeof(struct i2c_client)); + + i2c_set_clientdata(client, ir); + ir->l.data = ir; + ir->l.minor = minor; + ir->l.sample_rate = 10; + ir->l.dev = &ir->c.dev; + ir->nextkey = -1; + + switch (addr) { + case 0x64: + strlcpy(ir->c.name, "Pixelview IR", I2C_NAME_SIZE); + ir->l.code_length = 8; + ir->l.add_to_buf = add_to_buf_pixelview; + break; + case 0x4b: + strlcpy(ir->c.name, "PV951 IR", I2C_NAME_SIZE); + ir->l.code_length = 32; + ir->l.add_to_buf = add_to_buf_pv951; + break; + case 0x71: + if (adap->id == I2C_HW_B_CX2388x) + strlcpy(ir->c.name, "Hauppauge HVR1300", I2C_NAME_SIZE); + else /* bt8xx or cx2341x */ + /* + * The PVR150 IR receiver uses the same protocol as + * other Hauppauge cards, but the data flow is + * different, so we need to deal with it by its own. + */ + strlcpy(ir->c.name, "Hauppauge PVR150", I2C_NAME_SIZE); + ir->l.code_length = 13; + ir->l.add_to_buf = add_to_buf_haup_pvr150; + break; + case 0x6b: + strlcpy(ir->c.name, "Adaptec IR", I2C_NAME_SIZE); + ir->l.code_length = 32; + ir->l.add_to_buf = add_to_buf_adap; + break; + case 0x18: + case 0x1a: + if (adap->id == I2C_HW_B_CX2388x) { + strlcpy(ir->c.name, "Leadtek IR", I2C_NAME_SIZE); + ir->l.code_length = 8; + ir->l.add_to_buf = add_to_buf_pvr2000; + } else { /* bt8xx or cx2341x */ + strlcpy(ir->c.name, "Hauppauge IR", I2C_NAME_SIZE); + ir->l.code_length = 13; + ir->l.add_to_buf = add_to_buf_haup; + } + break; + case 0x30: + strlcpy(ir->c.name, "KNC ONE IR", I2C_NAME_SIZE); + ir->l.code_length = 8; + ir->l.add_to_buf = add_to_buf_knc1; + break; + case 0x21: + case 0x23: + pcf_probe(client, ir); + strlcpy(ir->c.name, "TV-Box IR", I2C_NAME_SIZE); + ir->l.code_length = 8; + ir->l.add_to_buf = add_to_buf_pcf8574; + break; + default: + /* shouldn't happen */ + printk("lirc_i2c: Huh? unknown i2c address (0x%02x)?\n", addr); + kfree(ir); + return -EINVAL; + } + printk(KERN_INFO "lirc_i2c: chip 0x%x found @ 0x%02x (%s)\n", + adap->id, addr, ir->c.name); + + retval = lirc_register_driver(&ir->l); + + if (retval < 0) { + printk(KERN_ERR "lirc_i2c: failed to register driver!\n"); + kfree(ir); + return retval; + } + + ir->l.minor = retval; + + return 0; +} + +static int ir_remove(struct i2c_client *client) +{ + struct IR *ir = i2c_get_clientdata(client); + + /* unregister device */ + lirc_unregister_driver(ir->l.minor); + + /* free memory */ + kfree(ir); + return 0; +} + +static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + /* nothing */ + return 0; +} + +static int __init lirc_i2c_init(void) +{ + i2c_add_driver(&driver); + return 0; +} + +static void __exit lirc_i2c_exit(void) +{ + i2c_del_driver(&driver); +} + +MODULE_DESCRIPTION("Infrared receiver driver for Hauppauge and " + "Pixelview cards (i2c stack)"); +MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, " + "Ulrich Mueller, Stefan Jahn, Jerome Brock"); +MODULE_LICENSE("GPL"); + +module_param(minor, int, S_IRUGO); +MODULE_PARM_DESC(minor, "Preferred minor device number"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); + +module_init(lirc_i2c_init); +module_exit(lirc_i2c_exit); diff --git a/drivers/staging/lirc/lirc_igorplugusb.c b/drivers/staging/lirc/lirc_igorplugusb.c new file mode 100644 index 000000000000..bce600ede263 --- /dev/null +++ b/drivers/staging/lirc/lirc_igorplugusb.c @@ -0,0 +1,555 @@ +/* + * lirc_igorplugusb - USB remote support for LIRC + * + * Supports the standard homebrew IgorPlugUSB receiver with Igor's firmware. + * See http://www.cesko.host.sk/IgorPlugUSB/IgorPlug-USB%20(AVR)_eng.htm + * + * The device can only record bursts of up to 36 pulses/spaces. + * Works fine with RC5. Longer commands lead to device buffer overrun. + * (Maybe a better firmware or a microcontroller with more ram can help?) + * + * Version 0.1 [beta status] + * + * Copyright (C) 2004 Jan M. Hochstein + * <hochstein@algo.informatik.tu-darmstadt.de> + * + * This driver was derived from: + * Paul Miller <pmiller9@users.sourceforge.net> + * "lirc_atiusb" module + * Vladimir Dergachev <volodya@minspring.com>'s 2002 + * "USB ATI Remote support" (input device) + * Adrian Dewhurst <sailor-lk@sailorfrag.net>'s 2002 + * "USB StreamZap remote driver" (LIRC) + * Artur Lipowski <alipowski@kki.net.pl>'s 2002 + * "lirc_dev" and "lirc_gpio" LIRC modules + */ + +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/kmod.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/usb.h> +#include <linux/time.h> + +#include <media/lirc.h> +#include <media/lirc_dev.h> + + +/* module identification */ +#define DRIVER_VERSION "0.1" +#define DRIVER_AUTHOR \ + "Jan M. Hochstein <hochstein@algo.informatik.tu-darmstadt.de>" +#define DRIVER_DESC "USB remote driver for LIRC" +#define DRIVER_NAME "lirc_igorplugusb" + +/* debugging support */ +#ifdef CONFIG_USB_DEBUG +static int debug = 1; +#else +static int debug; +#endif + +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG fmt, ## args); \ + } while (0) + +/* One mode2 pulse/space has 4 bytes. */ +#define CODE_LENGTH sizeof(int) + +/* Igor's firmware cannot record bursts longer than 36. */ +#define DEVICE_BUFLEN 36 + +/* + * Header at the beginning of the device's buffer: + * unsigned char data_length + * unsigned char data_start (!=0 means ring-buffer overrun) + * unsigned char counter (incremented by each burst) + */ +#define DEVICE_HEADERLEN 3 + +/* This is for the gap */ +#define ADDITIONAL_LIRC_BYTES 2 + +/* times to poll per second */ +#define SAMPLE_RATE 100 +static int sample_rate = SAMPLE_RATE; + + +/**** Igor's USB Request Codes */ + +#define SET_INFRABUFFER_EMPTY 1 +/** + * Params: none + * Answer: empty + */ + +#define GET_INFRACODE 2 +/** + * Params: + * wValue: offset to begin reading infra buffer + * + * Answer: infra data + */ + +#define SET_DATAPORT_DIRECTION 3 +/** + * Params: + * wValue: (byte) 1 bit for each data port pin (0=in, 1=out) + * + * Answer: empty + */ + +#define GET_DATAPORT_DIRECTION 4 +/** + * Params: none + * + * Answer: (byte) 1 bit for each data port pin (0=in, 1=out) + */ + +#define SET_OUT_DATAPORT 5 +/** + * Params: + * wValue: byte to write to output data port + * + * Answer: empty + */ + +#define GET_OUT_DATAPORT 6 +/** + * Params: none + * + * Answer: least significant 3 bits read from output data port + */ + +#define GET_IN_DATAPORT 7 +/** + * Params: none + * + * Answer: least significant 3 bits read from input data port + */ + +#define READ_EEPROM 8 +/** + * Params: + * wValue: offset to begin reading EEPROM + * + * Answer: EEPROM bytes + */ + +#define WRITE_EEPROM 9 +/** + * Params: + * wValue: offset to EEPROM byte + * wIndex: byte to write + * + * Answer: empty + */ + +#define SEND_RS232 10 +/** + * Params: + * wValue: byte to send + * + * Answer: empty + */ + +#define RECV_RS232 11 +/** + * Params: none + * + * Answer: byte received + */ + +#define SET_RS232_BAUD 12 +/** + * Params: + * wValue: byte to write to UART bit rate register (UBRR) + * + * Answer: empty + */ + +#define GET_RS232_BAUD 13 +/** + * Params: none + * + * Answer: byte read from UART bit rate register (UBRR) + */ + + +/* data structure for each usb remote */ +struct igorplug { + + /* usb */ + struct usb_device *usbdev; + struct urb *urb_in; + int devnum; + + unsigned char *buf_in; + unsigned int len_in; + int in_space; + struct timeval last_time; + + dma_addr_t dma_in; + + /* lirc */ + struct lirc_driver *d; + + /* handle sending (init strings) */ + int send_flags; + wait_queue_head_t wait_out; +}; + +static int unregister_from_lirc(struct igorplug *ir) +{ + struct lirc_driver *d = ir->d; + int devnum; + + if (!ir->d) + return -EINVAL; + + devnum = ir->devnum; + dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); + + lirc_unregister_driver(d->minor); + + printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); + + kfree(d); + ir->d = NULL; + kfree(ir); + return 0; +} + +static int set_use_inc(void *data) +{ + struct igorplug *ir = data; + + if (!ir) { + printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); + return -EIO; + } + dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); + + if (!ir->usbdev) + return -ENODEV; + + return 0; +} + +static void set_use_dec(void *data) +{ + struct igorplug *ir = data; + + if (!ir) { + printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); + return; + } + dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); +} + + +/** + * Called in user context. + * return 0 if data was added to the buffer and + * -ENODATA if none was available. This should add some number of bits + * evenly divisible by code_length to the buffer + */ +static int usb_remote_poll(void *data, struct lirc_buffer *buf) +{ + int ret; + struct igorplug *ir = (struct igorplug *)data; + + if (!ir->usbdev) /* Has the device been removed? */ + return -ENODEV; + + memset(ir->buf_in, 0, ir->len_in); + + ret = usb_control_msg( + ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), + GET_INFRACODE, USB_TYPE_VENDOR|USB_DIR_IN, + 0/* offset */, /*unused*/0, + ir->buf_in, ir->len_in, + /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); + if (ret > 0) { + int i = DEVICE_HEADERLEN; + int code, timediff; + struct timeval now; + + if (ret <= 1) /* ACK packet has 1 byte --> ignore */ + return -ENODATA; + + dprintk(DRIVER_NAME ": Got %d bytes. Header: %02x %02x %02x\n", + ret, ir->buf_in[0], ir->buf_in[1], ir->buf_in[2]); + + if (ir->buf_in[2] != 0) { + printk(DRIVER_NAME "[%d]: Device buffer overrun.\n", + ir->devnum); + /* start at earliest byte */ + i = DEVICE_HEADERLEN + ir->buf_in[2]; + /* where are we now? space, gap or pulse? */ + } + + do_gettimeofday(&now); + timediff = now.tv_sec - ir->last_time.tv_sec; + if (timediff + 1 > PULSE_MASK / 1000000) + timediff = PULSE_MASK; + else { + timediff *= 1000000; + timediff += now.tv_usec - ir->last_time.tv_usec; + } + ir->last_time.tv_sec = now.tv_sec; + ir->last_time.tv_usec = now.tv_usec; + + /* create leading gap */ + code = timediff; + lirc_buffer_write(buf, (unsigned char *)&code); + ir->in_space = 1; /* next comes a pulse */ + + /* MODE2: pulse/space (PULSE_BIT) in 1us units */ + + while (i < ret) { + /* 1 Igor-tick = 85.333333 us */ + code = (unsigned int)ir->buf_in[i] * 85 + + (unsigned int)ir->buf_in[i] / 3; + if (ir->in_space) + code |= PULSE_BIT; + lirc_buffer_write(buf, (unsigned char *)&code); + /* 1 chunk = CODE_LENGTH bytes */ + ir->in_space ^= 1; + ++i; + } + + ret = usb_control_msg( + ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), + SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, + /*unused*/0, /*unused*/0, + /*dummy*/ir->buf_in, /*dummy*/ir->len_in, + /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); + if (ret < 0) + printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: " + "error %d\n", ir->devnum, ret); + return 0; + } else if (ret < 0) + printk(DRIVER_NAME "[%d]: GET_INFRACODE: error %d\n", + ir->devnum, ret); + + return -ENODATA; +} + + + +static int usb_remote_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = NULL; + struct usb_host_interface *idesc = NULL; + struct usb_host_endpoint *ep_ctl2; + struct igorplug *ir = NULL; + struct lirc_driver *driver = NULL; + int devnum, pipe, maxp; + int minor = 0; + char buf[63], name[128] = ""; + int mem_failure = 0; + int ret; + + dprintk(DRIVER_NAME ": usb probe called.\n"); + + dev = interface_to_usbdev(intf); + + idesc = intf->cur_altsetting; + + if (idesc->desc.bNumEndpoints != 1) + return -ENODEV; + ep_ctl2 = idesc->endpoint; + if (((ep_ctl2->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) + != USB_DIR_IN) + || (ep_ctl2->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + != USB_ENDPOINT_XFER_CONTROL) + return -ENODEV; + pipe = usb_rcvctrlpipe(dev, ep_ctl2->desc.bEndpointAddress); + devnum = dev->devnum; + maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + + dprintk(DRIVER_NAME "[%d]: bytes_in_key=%lu maxp=%d\n", + devnum, CODE_LENGTH, maxp); + + + mem_failure = 0; + ir = kzalloc(sizeof(struct igorplug), GFP_KERNEL); + if (!ir) { + mem_failure = 1; + goto mem_failure_switch; + } + driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); + if (!driver) { + mem_failure = 2; + goto mem_failure_switch; + } + + ir->buf_in = usb_alloc_coherent(dev, + DEVICE_BUFLEN+DEVICE_HEADERLEN, + GFP_ATOMIC, &ir->dma_in); + if (!ir->buf_in) { + mem_failure = 3; + goto mem_failure_switch; + } + + strcpy(driver->name, DRIVER_NAME " "); + driver->minor = -1; + driver->code_length = CODE_LENGTH * 8; /* in bits */ + driver->features = LIRC_CAN_REC_MODE2; + driver->data = ir; + driver->chunk_size = CODE_LENGTH; + driver->buffer_size = DEVICE_BUFLEN + ADDITIONAL_LIRC_BYTES; + driver->set_use_inc = &set_use_inc; + driver->set_use_dec = &set_use_dec; + driver->sample_rate = sample_rate; /* per second */ + driver->add_to_buf = &usb_remote_poll; + driver->dev = &intf->dev; + driver->owner = THIS_MODULE; + + init_waitqueue_head(&ir->wait_out); + + minor = lirc_register_driver(driver); + if (minor < 0) + mem_failure = 9; + +mem_failure_switch: + + switch (mem_failure) { + case 9: + usb_free_coherent(dev, DEVICE_BUFLEN+DEVICE_HEADERLEN, + ir->buf_in, ir->dma_in); + case 3: + kfree(driver); + case 2: + kfree(ir); + case 1: + printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", + devnum, mem_failure); + return -ENOMEM; + } + + driver->minor = minor; + ir->d = driver; + ir->devnum = devnum; + ir->usbdev = dev; + ir->len_in = DEVICE_BUFLEN+DEVICE_HEADERLEN; + ir->in_space = 1; /* First mode2 event is a space. */ + do_gettimeofday(&ir->last_time); + + if (dev->descriptor.iManufacturer + && usb_string(dev, dev->descriptor.iManufacturer, + buf, sizeof(buf)) > 0) + strlcpy(name, buf, sizeof(name)); + if (dev->descriptor.iProduct + && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) + snprintf(name + strlen(name), sizeof(name) - strlen(name), + " %s", buf); + printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name, + dev->bus->busnum, devnum); + + /* clear device buffer */ + ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), + SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, + /*unused*/0, /*unused*/0, + /*dummy*/ir->buf_in, /*dummy*/ir->len_in, + /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); + if (ret < 0) + printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n", + devnum, ret); + + usb_set_intfdata(intf, ir); + return 0; +} + + +static void usb_remote_disconnect(struct usb_interface *intf) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct igorplug *ir = usb_get_intfdata(intf); + usb_set_intfdata(intf, NULL); + + if (!ir || !ir->d) + return; + + ir->usbdev = NULL; + wake_up_all(&ir->wait_out); + + usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in); + + unregister_from_lirc(ir); +} + +static struct usb_device_id usb_remote_id_table[] = { + /* Igor Plug USB (Atmel's Manufact. ID) */ + { USB_DEVICE(0x03eb, 0x0002) }, + + /* Terminating entry */ + { } +}; + +static struct usb_driver usb_remote_driver = { + .name = DRIVER_NAME, + .probe = usb_remote_probe, + .disconnect = usb_remote_disconnect, + .id_table = usb_remote_id_table +}; + +static int __init usb_remote_init(void) +{ + int i; + + printk(KERN_INFO "\n" + DRIVER_NAME ": " DRIVER_DESC " v" DRIVER_VERSION "\n"); + printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); + dprintk(DRIVER_NAME ": debug mode enabled\n"); + + i = usb_register(&usb_remote_driver); + if (i < 0) { + printk(DRIVER_NAME ": usb register failed, result = %d\n", i); + return -ENODEV; + } + + return 0; +} + +static void __exit usb_remote_exit(void) +{ + usb_deregister(&usb_remote_driver); +} + +module_init(usb_remote_init); +module_exit(usb_remote_exit); + +#include <linux/vermagic.h> +MODULE_INFO(vermagic, VERMAGIC_STRING); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(usb, usb_remote_id_table); + +module_param(sample_rate, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(sample_rate, "Sampling rate in Hz (default: 100)"); + diff --git a/drivers/staging/lirc/lirc_imon.c b/drivers/staging/lirc/lirc_imon.c new file mode 100644 index 000000000000..66493253042e --- /dev/null +++ b/drivers/staging/lirc/lirc_imon.c @@ -0,0 +1,1058 @@ +/* + * lirc_imon.c: LIRC/VFD/LCD driver for SoundGraph iMON IR/VFD/LCD + * including the iMON PAD model + * + * Copyright(C) 2004 Venky Raju(dev@venky.ws) + * Copyright(C) 2009 Jarod Wilson <jarod@wilsonet.com> + * + * lirc_imon 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/uaccess.h> +#include <linux/usb.h> + +#include <media/lirc.h> +#include <media/lirc_dev.h> + + +#define MOD_AUTHOR "Venky Raju <dev@venky.ws>" +#define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" +#define MOD_NAME "lirc_imon" +#define MOD_VERSION "0.8" + +#define DISPLAY_MINOR_BASE 144 +#define DEVICE_NAME "lcd%d" + +#define BUF_CHUNK_SIZE 4 +#define BUF_SIZE 128 + +#define BIT_DURATION 250 /* each bit received is 250us */ + +/*** P R O T O T Y P E S ***/ + +/* USB Callback prototypes */ +static int imon_probe(struct usb_interface *interface, + const struct usb_device_id *id); +static void imon_disconnect(struct usb_interface *interface); +static void usb_rx_callback(struct urb *urb); +static void usb_tx_callback(struct urb *urb); + +/* suspend/resume support */ +static int imon_resume(struct usb_interface *intf); +static int imon_suspend(struct usb_interface *intf, pm_message_t message); + +/* Display file_operations function prototypes */ +static int display_open(struct inode *inode, struct file *file); +static int display_close(struct inode *inode, struct file *file); + +/* VFD write operation */ +static ssize_t vfd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos); + +/* LIRC driver function prototypes */ +static int ir_open(void *data); +static void ir_close(void *data); + +/* Driver init/exit prototypes */ +static int __init imon_init(void); +static void __exit imon_exit(void); + +/*** G L O B A L S ***/ +#define IMON_DATA_BUF_SZ 35 + +struct imon_context { + struct usb_device *usbdev; + /* Newer devices have two interfaces */ + int display; /* not all controllers do */ + int display_isopen; /* display port has been opened */ + int ir_isopen; /* IR port open */ + int dev_present; /* USB device presence */ + struct mutex ctx_lock; /* to lock this object */ + wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ + + int vfd_proto_6p; /* some VFD require a 6th packet */ + + struct lirc_driver *driver; + struct usb_endpoint_descriptor *rx_endpoint; + struct usb_endpoint_descriptor *tx_endpoint; + struct urb *rx_urb; + struct urb *tx_urb; + unsigned char usb_rx_buf[8]; + unsigned char usb_tx_buf[8]; + + struct rx_data { + int count; /* length of 0 or 1 sequence */ + int prev_bit; /* logic level of sequence */ + int initial_space; /* initial space flag */ + } rx; + + struct tx_t { + unsigned char data_buf[IMON_DATA_BUF_SZ]; /* user data buffer */ + struct completion finished; /* wait for write to finish */ + atomic_t busy; /* write in progress */ + int status; /* status of tx completion */ + } tx; +}; + +static const struct file_operations display_fops = { + .owner = THIS_MODULE, + .open = &display_open, + .write = &vfd_write, + .release = &display_close +}; + +/* + * USB Device ID for iMON USB Control Boards + * + * The Windows drivers contain 6 different inf files, more or less one for + * each new device until the 0x0034-0x0046 devices, which all use the same + * driver. Some of the devices in the 34-46 range haven't been definitively + * identified yet. Early devices have either a TriGem Computer, Inc. or a + * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later + * devices use the SoundGraph vendor ID (0x15c2). + */ +static struct usb_device_id imon_usb_id_table[] = { + /* TriGem iMON (IR only) -- TG_iMON.inf */ + { USB_DEVICE(0x0aa8, 0x8001) }, + + /* SoundGraph iMON (IR only) -- sg_imon.inf */ + { USB_DEVICE(0x04e8, 0xff30) }, + + /* SoundGraph iMON VFD (IR & VFD) -- iMON_VFD.inf */ + { USB_DEVICE(0x0aa8, 0xffda) }, + + /* SoundGraph iMON SS (IR & VFD) -- iMON_SS.inf */ + { USB_DEVICE(0x15c2, 0xffda) }, + + {} +}; + +/* Some iMON VFD models requires a 6th packet for VFD writes */ +static struct usb_device_id vfd_proto_6p_list[] = { + { USB_DEVICE(0x15c2, 0xffda) }, + {} +}; + +/* Some iMON devices have no lcd/vfd, don't set one up */ +static struct usb_device_id ir_only_list[] = { + { USB_DEVICE(0x0aa8, 0x8001) }, + { USB_DEVICE(0x04e8, 0xff30) }, + {} +}; + +/* USB Device data */ +static struct usb_driver imon_driver = { + .name = MOD_NAME, + .probe = imon_probe, + .disconnect = imon_disconnect, + .suspend = imon_suspend, + .resume = imon_resume, + .id_table = imon_usb_id_table, +}; + +static struct usb_class_driver imon_class = { + .name = DEVICE_NAME, + .fops = &display_fops, + .minor_base = DISPLAY_MINOR_BASE, +}; + +/* to prevent races between open() and disconnect(), probing, etc */ +static DEFINE_MUTEX(driver_lock); + +static int debug; + +/*** M O D U L E C O D E ***/ + +MODULE_AUTHOR(MOD_AUTHOR); +MODULE_DESCRIPTION(MOD_DESC); +MODULE_VERSION(MOD_VERSION); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(usb, imon_usb_id_table); +module_param(debug, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)"); + +static void free_imon_context(struct imon_context *context) +{ + struct device *dev = context->driver->dev; + usb_free_urb(context->tx_urb); + usb_free_urb(context->rx_urb); + lirc_buffer_free(context->driver->rbuf); + kfree(context->driver->rbuf); + kfree(context->driver); + kfree(context); + + dev_dbg(dev, "%s: iMON context freed\n", __func__); +} + +static void deregister_from_lirc(struct imon_context *context) +{ + int retval; + int minor = context->driver->minor; + + retval = lirc_unregister_driver(minor); + if (retval) + err("%s: unable to deregister from lirc(%d)", + __func__, retval); + else + printk(KERN_INFO MOD_NAME ": Deregistered iMON driver " + "(minor:%d)\n", minor); + +} + +/** + * Called when the Display device (e.g. /dev/lcd0) + * is opened by the application. + */ +static int display_open(struct inode *inode, struct file *file) +{ + struct usb_interface *interface; + struct imon_context *context = NULL; + int subminor; + int retval = 0; + + /* prevent races with disconnect */ + mutex_lock(&driver_lock); + + subminor = iminor(inode); + interface = usb_find_interface(&imon_driver, subminor); + if (!interface) { + err("%s: could not find interface for minor %d", + __func__, subminor); + retval = -ENODEV; + goto exit; + } + context = usb_get_intfdata(interface); + + if (!context) { + err("%s: no context found for minor %d", + __func__, subminor); + retval = -ENODEV; + goto exit; + } + + mutex_lock(&context->ctx_lock); + + if (!context->display) { + err("%s: display not supported by device", __func__); + retval = -ENODEV; + } else if (context->display_isopen) { + err("%s: display port is already open", __func__); + retval = -EBUSY; + } else { + context->display_isopen = 1; + file->private_data = context; + dev_info(context->driver->dev, "display port opened\n"); + } + + mutex_unlock(&context->ctx_lock); + +exit: + mutex_unlock(&driver_lock); + return retval; +} + +/** + * Called when the display device (e.g. /dev/lcd0) + * is closed by the application. + */ +static int display_close(struct inode *inode, struct file *file) +{ + struct imon_context *context = NULL; + int retval = 0; + + context = (struct imon_context *)file->private_data; + + if (!context) { + err("%s: no context for device", __func__); + return -ENODEV; + } + + mutex_lock(&context->ctx_lock); + + if (!context->display) { + err("%s: display not supported by device", __func__); + retval = -ENODEV; + } else if (!context->display_isopen) { + err("%s: display is not open", __func__); + retval = -EIO; + } else { + context->display_isopen = 0; + dev_info(context->driver->dev, "display port closed\n"); + if (!context->dev_present && !context->ir_isopen) { + /* + * Device disconnected before close and IR port is not + * open. If IR port is open, context will be deleted by + * ir_close. + */ + mutex_unlock(&context->ctx_lock); + free_imon_context(context); + return retval; + } + } + + mutex_unlock(&context->ctx_lock); + return retval; +} + +/** + * Sends a packet to the device -- this function must be called + * with context->ctx_lock held. + */ +static int send_packet(struct imon_context *context) +{ + unsigned int pipe; + int interval = 0; + int retval = 0; + struct usb_ctrlrequest *control_req = NULL; + + /* Check if we need to use control or interrupt urb */ + pipe = usb_sndintpipe(context->usbdev, + context->tx_endpoint->bEndpointAddress); + interval = context->tx_endpoint->bInterval; + + usb_fill_int_urb(context->tx_urb, context->usbdev, pipe, + context->usb_tx_buf, + sizeof(context->usb_tx_buf), + usb_tx_callback, context, interval); + + context->tx_urb->actual_length = 0; + + init_completion(&context->tx.finished); + atomic_set(&(context->tx.busy), 1); + + retval = usb_submit_urb(context->tx_urb, GFP_KERNEL); + if (retval) { + atomic_set(&(context->tx.busy), 0); + err("%s: error submitting urb(%d)", __func__, retval); + } else { + /* Wait for transmission to complete (or abort) */ + mutex_unlock(&context->ctx_lock); + retval = wait_for_completion_interruptible( + &context->tx.finished); + if (retval) + err("%s: task interrupted", __func__); + mutex_lock(&context->ctx_lock); + + retval = context->tx.status; + if (retval) + err("%s: packet tx failed (%d)", __func__, retval); + } + + kfree(control_req); + + return retval; +} + +/** + * Writes data to the VFD. The iMON VFD is 2x16 characters + * and requires data in 5 consecutive USB interrupt packets, + * each packet but the last carrying 7 bytes. + * + * I don't know if the VFD board supports features such as + * scrolling, clearing rows, blanking, etc. so at + * the caller must provide a full screen of data. If fewer + * than 32 bytes are provided spaces will be appended to + * generate a full screen. + */ +static ssize_t vfd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos) +{ + int i; + int offset; + int seq; + int retval = 0; + struct imon_context *context; + const unsigned char vfd_packet6[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; + int *data_buf; + + context = (struct imon_context *)file->private_data; + if (!context) { + err("%s: no context for device", __func__); + return -ENODEV; + } + + mutex_lock(&context->ctx_lock); + + if (!context->dev_present) { + err("%s: no iMON device present", __func__); + retval = -ENODEV; + goto exit; + } + + if (n_bytes <= 0 || n_bytes > IMON_DATA_BUF_SZ - 3) { + err("%s: invalid payload size", __func__); + retval = -EINVAL; + goto exit; + } + + data_buf = memdup_user(buf, n_bytes); + if (IS_ERR(data_buf)) { + retval = PTR_ERR(data_buf); + goto exit; + } + + memcpy(context->tx.data_buf, data_buf, n_bytes); + + /* Pad with spaces */ + for (i = n_bytes; i < IMON_DATA_BUF_SZ - 3; ++i) + context->tx.data_buf[i] = ' '; + + for (i = IMON_DATA_BUF_SZ - 3; i < IMON_DATA_BUF_SZ; ++i) + context->tx.data_buf[i] = 0xFF; + + offset = 0; + seq = 0; + + do { + memcpy(context->usb_tx_buf, context->tx.data_buf + offset, 7); + context->usb_tx_buf[7] = (unsigned char) seq; + + retval = send_packet(context); + if (retval) { + err("%s: send packet failed for packet #%d", + __func__, seq/2); + goto exit; + } else { + seq += 2; + offset += 7; + } + + } while (offset < IMON_DATA_BUF_SZ); + + if (context->vfd_proto_6p) { + /* Send packet #6 */ + memcpy(context->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6)); + context->usb_tx_buf[7] = (unsigned char) seq; + retval = send_packet(context); + if (retval) + err("%s: send packet failed for packet #%d", + __func__, seq/2); + } + +exit: + mutex_unlock(&context->ctx_lock); + + return (!retval) ? n_bytes : retval; +} + +/** + * Callback function for USB core API: transmit data + */ +static void usb_tx_callback(struct urb *urb) +{ + struct imon_context *context; + + if (!urb) + return; + context = (struct imon_context *)urb->context; + if (!context) + return; + + context->tx.status = urb->status; + + /* notify waiters that write has finished */ + atomic_set(&context->tx.busy, 0); + complete(&context->tx.finished); + + return; +} + +/** + * Called by lirc_dev when the application opens /dev/lirc + */ +static int ir_open(void *data) +{ + int retval = 0; + struct imon_context *context; + + /* prevent races with disconnect */ + mutex_lock(&driver_lock); + + context = (struct imon_context *)data; + + /* initial IR protocol decode variables */ + context->rx.count = 0; + context->rx.initial_space = 1; + context->rx.prev_bit = 0; + + context->ir_isopen = 1; + dev_info(context->driver->dev, "IR port opened\n"); + + mutex_unlock(&driver_lock); + return retval; +} + +/** + * Called by lirc_dev when the application closes /dev/lirc + */ +static void ir_close(void *data) +{ + struct imon_context *context; + + context = (struct imon_context *)data; + if (!context) { + err("%s: no context for device", __func__); + return; + } + + mutex_lock(&context->ctx_lock); + + context->ir_isopen = 0; + dev_info(context->driver->dev, "IR port closed\n"); + + if (!context->dev_present) { + /* + * Device disconnected while IR port was still open. Driver + * was not deregistered at disconnect time, so do it now. + */ + deregister_from_lirc(context); + + if (!context->display_isopen) { + mutex_unlock(&context->ctx_lock); + free_imon_context(context); + return; + } + /* + * If display port is open, context will be deleted by + * display_close + */ + } + + mutex_unlock(&context->ctx_lock); + return; +} + +/** + * Convert bit count to time duration (in us) and submit + * the value to lirc_dev. + */ +static void submit_data(struct imon_context *context) +{ + unsigned char buf[4]; + int value = context->rx.count; + int i; + + dev_dbg(context->driver->dev, "submitting data to LIRC\n"); + + value *= BIT_DURATION; + value &= PULSE_MASK; + if (context->rx.prev_bit) + value |= PULSE_BIT; + + for (i = 0; i < 4; ++i) + buf[i] = value>>(i*8); + + lirc_buffer_write(context->driver->rbuf, buf); + wake_up(&context->driver->rbuf->wait_poll); + return; +} + +static inline int tv2int(const struct timeval *a, const struct timeval *b) +{ + int usecs = 0; + int sec = 0; + + if (b->tv_usec > a->tv_usec) { + usecs = 1000000; + sec--; + } + + usecs += a->tv_usec - b->tv_usec; + + sec += a->tv_sec - b->tv_sec; + sec *= 1000; + usecs /= 1000; + sec += usecs; + + if (sec < 0) + sec = 1000; + + return sec; +} + +/** + * Process the incoming packet + */ +static void imon_incoming_packet(struct imon_context *context, + struct urb *urb, int intf) +{ + int len = urb->actual_length; + unsigned char *buf = urb->transfer_buffer; + struct device *dev = context->driver->dev; + int octet, bit; + unsigned char mask; + int i, chunk_num; + + /* + * just bail out if no listening IR client + */ + if (!context->ir_isopen) + return; + + if (len != 8) { + dev_warn(dev, "imon %s: invalid incoming packet " + "size (len = %d, intf%d)\n", __func__, len, intf); + return; + } + + if (debug) { + printk(KERN_INFO "raw packet: "); + for (i = 0; i < len; ++i) + printk("%02x ", buf[i]); + printk("\n"); + } + + /* + * Translate received data to pulse and space lengths. + * Received data is active low, i.e. pulses are 0 and + * spaces are 1. + * + * My original algorithm was essentially similar to + * Changwoo Ryu's with the exception that he switched + * the incoming bits to active high and also fed an + * initial space to LIRC at the start of a new sequence + * if the previous bit was a pulse. + * + * I've decided to adopt his algorithm. + */ + + if (buf[7] == 1 && context->rx.initial_space) { + /* LIRC requires a leading space */ + context->rx.prev_bit = 0; + context->rx.count = 4; + submit_data(context); + context->rx.count = 0; + } + + for (octet = 0; octet < 5; ++octet) { + mask = 0x80; + for (bit = 0; bit < 8; ++bit) { + int curr_bit = !(buf[octet] & mask); + if (curr_bit != context->rx.prev_bit) { + if (context->rx.count) { + submit_data(context); + context->rx.count = 0; + } + context->rx.prev_bit = curr_bit; + } + ++context->rx.count; + mask >>= 1; + } + } + + if (chunk_num == 10) { + if (context->rx.count) { + submit_data(context); + context->rx.count = 0; + } + context->rx.initial_space = context->rx.prev_bit; + } +} + +/** + * Callback function for USB core API: receive data + */ +static void usb_rx_callback(struct urb *urb) +{ + struct imon_context *context; + unsigned char *buf; + int len; + int intfnum = 0; + + if (!urb) + return; + + context = (struct imon_context *)urb->context; + if (!context) + return; + + buf = urb->transfer_buffer; + len = urb->actual_length; + + switch (urb->status) { + case -ENOENT: /* usbcore unlink successful! */ + return; + + case 0: + imon_incoming_packet(context, urb, intfnum); + break; + + default: + dev_warn(context->driver->dev, "imon %s: status(%d): ignored\n", + __func__, urb->status); + break; + } + + usb_submit_urb(context->rx_urb, GFP_ATOMIC); + + return; +} + +/** + * Callback function for USB core API: Probe + */ +static int imon_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *usbdev = NULL; + struct usb_host_interface *iface_desc = NULL; + struct usb_endpoint_descriptor *rx_endpoint = NULL; + struct usb_endpoint_descriptor *tx_endpoint = NULL; + struct urb *rx_urb = NULL; + struct urb *tx_urb = NULL; + struct lirc_driver *driver = NULL; + struct lirc_buffer *rbuf = NULL; + struct device *dev = &interface->dev; + int ifnum; + int lirc_minor = 0; + int num_endpts; + int retval = 0; + int display_ep_found = 0; + int ir_ep_found = 0; + int alloc_status = 0; + int vfd_proto_6p = 0; + int code_length; + struct imon_context *context = NULL; + int i; + u16 vendor, product; + + context = kzalloc(sizeof(struct imon_context), GFP_KERNEL); + if (!context) { + err("%s: kzalloc failed for context", __func__); + alloc_status = 1; + goto alloc_status_switch; + } + + /* + * Try to auto-detect the type of display if the user hasn't set + * it by hand via the display_type modparam. Default is VFD. + */ + if (usb_match_id(interface, ir_only_list)) + context->display = 0; + else + context->display = 1; + + code_length = BUF_CHUNK_SIZE * 8; + + usbdev = usb_get_dev(interface_to_usbdev(interface)); + iface_desc = interface->cur_altsetting; + num_endpts = iface_desc->desc.bNumEndpoints; + ifnum = iface_desc->desc.bInterfaceNumber; + vendor = le16_to_cpu(usbdev->descriptor.idVendor); + product = le16_to_cpu(usbdev->descriptor.idProduct); + + dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n", + __func__, vendor, product, ifnum); + + /* prevent races probing devices w/multiple interfaces */ + mutex_lock(&driver_lock); + + /* + * Scan the endpoint list and set: + * first input endpoint = IR endpoint + * first output endpoint = display endpoint + */ + for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) { + struct usb_endpoint_descriptor *ep; + int ep_dir; + int ep_type; + ep = &iface_desc->endpoint[i].desc; + ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; + ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + + if (!ir_ep_found && + ep_dir == USB_DIR_IN && + ep_type == USB_ENDPOINT_XFER_INT) { + + rx_endpoint = ep; + ir_ep_found = 1; + dev_dbg(dev, "%s: found IR endpoint\n", __func__); + + } else if (!display_ep_found && ep_dir == USB_DIR_OUT && + ep_type == USB_ENDPOINT_XFER_INT) { + tx_endpoint = ep; + display_ep_found = 1; + dev_dbg(dev, "%s: found display endpoint\n", __func__); + } + } + + /* + * Some iMON receivers have no display. Unfortunately, it seems + * that SoundGraph recycles device IDs between devices both with + * and without... :\ + */ + if (context->display == 0) { + display_ep_found = 0; + dev_dbg(dev, "%s: device has no display\n", __func__); + } + + /* Input endpoint is mandatory */ + if (!ir_ep_found) { + err("%s: no valid input (IR) endpoint found.", __func__); + retval = -ENODEV; + alloc_status = 2; + goto alloc_status_switch; + } + + /* Determine if display requires 6 packets */ + if (display_ep_found) { + if (usb_match_id(interface, vfd_proto_6p_list)) + vfd_proto_6p = 1; + + dev_dbg(dev, "%s: vfd_proto_6p: %d\n", + __func__, vfd_proto_6p); + } + + driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); + if (!driver) { + err("%s: kzalloc failed for lirc_driver", __func__); + alloc_status = 2; + goto alloc_status_switch; + } + rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!rbuf) { + err("%s: kmalloc failed for lirc_buffer", __func__); + alloc_status = 3; + goto alloc_status_switch; + } + if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) { + err("%s: lirc_buffer_init failed", __func__); + alloc_status = 4; + goto alloc_status_switch; + } + rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!rx_urb) { + err("%s: usb_alloc_urb failed for IR urb", __func__); + alloc_status = 5; + goto alloc_status_switch; + } + tx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!tx_urb) { + err("%s: usb_alloc_urb failed for display urb", + __func__); + alloc_status = 6; + goto alloc_status_switch; + } + + mutex_init(&context->ctx_lock); + context->vfd_proto_6p = vfd_proto_6p; + + strcpy(driver->name, MOD_NAME); + driver->minor = -1; + driver->code_length = sizeof(int) * 8; + driver->sample_rate = 0; + driver->features = LIRC_CAN_REC_MODE2; + driver->data = context; + driver->rbuf = rbuf; + driver->set_use_inc = ir_open; + driver->set_use_dec = ir_close; + driver->dev = &interface->dev; + driver->owner = THIS_MODULE; + + mutex_lock(&context->ctx_lock); + + context->driver = driver; + /* start out in keyboard mode */ + + lirc_minor = lirc_register_driver(driver); + if (lirc_minor < 0) { + err("%s: lirc_register_driver failed", __func__); + alloc_status = 7; + goto alloc_status_switch; + } else + dev_info(dev, "Registered iMON driver " + "(lirc minor: %d)\n", lirc_minor); + + /* Needed while unregistering! */ + driver->minor = lirc_minor; + + context->usbdev = usbdev; + context->dev_present = 1; + context->rx_endpoint = rx_endpoint; + context->rx_urb = rx_urb; + + /* + * tx is used to send characters to lcd/vfd, associate RF + * remotes, set IR protocol, and maybe more... + */ + context->tx_endpoint = tx_endpoint; + context->tx_urb = tx_urb; + + if (display_ep_found) + context->display = 1; + + usb_fill_int_urb(context->rx_urb, context->usbdev, + usb_rcvintpipe(context->usbdev, + context->rx_endpoint->bEndpointAddress), + context->usb_rx_buf, sizeof(context->usb_rx_buf), + usb_rx_callback, context, + context->rx_endpoint->bInterval); + + retval = usb_submit_urb(context->rx_urb, GFP_KERNEL); + + if (retval) { + err("%s: usb_submit_urb failed for intf0 (%d)", + __func__, retval); + mutex_unlock(&context->ctx_lock); + goto exit; + } + + usb_set_intfdata(interface, context); + + if (context->display && ifnum == 0) { + dev_dbg(dev, "%s: Registering iMON display with sysfs\n", + __func__); + + if (usb_register_dev(interface, &imon_class)) { + /* Not a fatal error, so ignore */ + dev_info(dev, "%s: could not get a minor number for " + "display\n", __func__); + } + } + + dev_info(dev, "iMON device (%04x:%04x, intf%d) on " + "usb<%d:%d> initialized\n", vendor, product, ifnum, + usbdev->bus->busnum, usbdev->devnum); + +alloc_status_switch: + mutex_unlock(&context->ctx_lock); + + switch (alloc_status) { + case 7: + usb_free_urb(tx_urb); + case 6: + usb_free_urb(rx_urb); + case 5: + if (rbuf) + lirc_buffer_free(rbuf); + case 4: + kfree(rbuf); + case 3: + kfree(driver); + case 2: + kfree(context); + context = NULL; + case 1: + if (retval != -ENODEV) + retval = -ENOMEM; + break; + case 0: + retval = 0; + } + +exit: + mutex_unlock(&driver_lock); + + return retval; +} + +/** + * Callback function for USB core API: disconnect + */ +static void imon_disconnect(struct usb_interface *interface) +{ + struct imon_context *context; + int ifnum; + + /* prevent races with ir_open()/display_open() */ + mutex_lock(&driver_lock); + + context = usb_get_intfdata(interface); + ifnum = interface->cur_altsetting->desc.bInterfaceNumber; + + mutex_lock(&context->ctx_lock); + + usb_set_intfdata(interface, NULL); + + /* Abort ongoing write */ + if (atomic_read(&context->tx.busy)) { + usb_kill_urb(context->tx_urb); + complete_all(&context->tx.finished); + } + + context->dev_present = 0; + usb_kill_urb(context->rx_urb); + if (context->display) + usb_deregister_dev(interface, &imon_class); + + if (!context->ir_isopen && !context->dev_present) { + deregister_from_lirc(context); + mutex_unlock(&context->ctx_lock); + if (!context->display_isopen) + free_imon_context(context); + } else + mutex_unlock(&context->ctx_lock); + + mutex_unlock(&driver_lock); + + printk(KERN_INFO "%s: iMON device (intf%d) disconnected\n", + __func__, ifnum); +} + +static int imon_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct imon_context *context = usb_get_intfdata(intf); + + usb_kill_urb(context->rx_urb); + + return 0; +} + +static int imon_resume(struct usb_interface *intf) +{ + int rc = 0; + struct imon_context *context = usb_get_intfdata(intf); + + usb_fill_int_urb(context->rx_urb, context->usbdev, + usb_rcvintpipe(context->usbdev, + context->rx_endpoint->bEndpointAddress), + context->usb_rx_buf, sizeof(context->usb_rx_buf), + usb_rx_callback, context, + context->rx_endpoint->bInterval); + + rc = usb_submit_urb(context->rx_urb, GFP_ATOMIC); + + return rc; +} + +static int __init imon_init(void) +{ + int rc; + + printk(KERN_INFO MOD_NAME ": " MOD_DESC ", v" MOD_VERSION "\n"); + + rc = usb_register(&imon_driver); + if (rc) { + err("%s: usb register failed(%d)", __func__, rc); + return -ENODEV; + } + + return 0; +} + +static void __exit imon_exit(void) +{ + usb_deregister(&imon_driver); + printk(KERN_INFO MOD_NAME ": module removed. Goodbye!\n"); +} + +module_init(imon_init); +module_exit(imon_exit); diff --git a/drivers/staging/lirc/lirc_it87.c b/drivers/staging/lirc/lirc_it87.c new file mode 100644 index 000000000000..09f36961c6d2 --- /dev/null +++ b/drivers/staging/lirc/lirc_it87.c @@ -0,0 +1,1019 @@ +/* + * LIRC driver for ITE IT8712/IT8705 CIR port + * + * Copyright (C) 2001 Hans-Gunter Lutke Uphues <hg_lu@web.de> + * + * 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; either version 2 of the + * License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * ITE IT8705 and IT8712(not tested) and IT8720 CIR-port support for lirc based + * via cut and paste from lirc_sir.c (C) 2000 Milan Pikula + * + * Attention: Sendmode only tested with debugging logs + * + * 2001/02/27 Christoph Bartelmus <lirc@bartelmus.de> : + * reimplemented read function + * 2005/06/05 Andrew Calkin implemented support for Asus Digimatrix, + * based on work of the following member of the Outertrack Digimatrix + * Forum: Art103 <r_tay@hotmail.com> + * 2009/12/24 James Edwards <jimbo-lirc@edwardsclan.net> implemeted support + * for ITE8704/ITE8718, on my machine, the DSDT reports 8704, but the + * chip identifies as 18. + */ + +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/signal.h> +#include <linux/fs.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/kernel.h> +#include <linux/time.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/wait.h> +#include <linux/mm.h> +#include <linux/delay.h> +#include <linux/poll.h> +#include <asm/system.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/fcntl.h> + +#include <linux/timer.h> +#include <linux/pnp.h> + +#include <media/lirc.h> +#include <media/lirc_dev.h> + +#include "lirc_it87.h" + +#ifdef LIRC_IT87_DIGIMATRIX +static int digimatrix = 1; +static int it87_freq = 36; /* kHz */ +static int irq = 9; +#else +static int digimatrix; +static int it87_freq = 38; /* kHz */ +static int irq = IT87_CIR_DEFAULT_IRQ; +#endif + +static unsigned long it87_bits_in_byte_out; +static unsigned long it87_send_counter; +static unsigned char it87_RXEN_mask = IT87_CIR_RCR_RXEN; + +#define RBUF_LEN 1024 + +#define LIRC_DRIVER_NAME "lirc_it87" + +/* timeout for sequences in jiffies (=5/100s) */ +/* must be longer than TIME_CONST */ +#define IT87_TIMEOUT (HZ*5/100) + +/* module parameters */ +static int debug; +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ + fmt, ## args); \ + } while (0) + +static int io = IT87_CIR_DEFAULT_IOBASE; +/* receiver demodulator default: off */ +static int it87_enable_demodulator; + +static int timer_enabled; +static DEFINE_SPINLOCK(timer_lock); +static struct timer_list timerlist; +/* time of last signal change detected */ +static struct timeval last_tv = {0, 0}; +/* time of last UART data ready interrupt */ +static struct timeval last_intr_tv = {0, 0}; +static int last_value; + +static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue); + +static DEFINE_SPINLOCK(hardware_lock); +static DEFINE_SPINLOCK(dev_lock); + +static int rx_buf[RBUF_LEN]; +unsigned int rx_tail, rx_head; + +static struct pnp_driver it87_pnp_driver; + +/* SECTION: Prototypes */ + +/* Communication with user-space */ +static int lirc_open(struct inode *inode, struct file *file); +static int lirc_close(struct inode *inode, struct file *file); +static unsigned int lirc_poll(struct file *file, poll_table *wait); +static ssize_t lirc_read(struct file *file, char *buf, + size_t count, loff_t *ppos); +static ssize_t lirc_write(struct file *file, const char *buf, + size_t n, loff_t *pos); +static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); +static void add_read_queue(int flag, unsigned long val); +static int init_chrdev(void); +static void drop_chrdev(void); +/* Hardware */ +static irqreturn_t it87_interrupt(int irq, void *dev_id); +static void send_space(unsigned long len); +static void send_pulse(unsigned long len); +static void init_send(void); +static void terminate_send(unsigned long len); +static int init_hardware(void); +static void drop_hardware(void); +/* Initialisation */ +static int init_port(void); +static void drop_port(void); + + +/* SECTION: Communication with user-space */ + +static int lirc_open(struct inode *inode, struct file *file) +{ + spin_lock(&dev_lock); + if (module_refcount(THIS_MODULE)) { + spin_unlock(&dev_lock); + return -EBUSY; + } + spin_unlock(&dev_lock); + return 0; +} + + +static int lirc_close(struct inode *inode, struct file *file) +{ + return 0; +} + + +static unsigned int lirc_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &lirc_read_queue, wait); + if (rx_head != rx_tail) + return POLLIN | POLLRDNORM; + return 0; +} + + +static ssize_t lirc_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + int n = 0; + int retval = 0; + + while (n < count) { + if (file->f_flags & O_NONBLOCK && rx_head == rx_tail) { + retval = -EAGAIN; + break; + } + retval = wait_event_interruptible(lirc_read_queue, + rx_head != rx_tail); + if (retval) + break; + + if (copy_to_user((void *) buf + n, (void *) (rx_buf + rx_head), + sizeof(int))) { + retval = -EFAULT; + break; + } + rx_head = (rx_head + 1) & (RBUF_LEN - 1); + n += sizeof(int); + } + if (n) + return n; + return retval; +} + + +static ssize_t lirc_write(struct file *file, const char *buf, + size_t n, loff_t *pos) +{ + int i = 0; + int *tx_buf; + + if (n % sizeof(int)) + return -EINVAL; + tx_buf = memdup_user(buf, n); + if (IS_ERR(tx_buf)) + return PTR_ERR(tx_buf); + n /= sizeof(int); + init_send(); + while (1) { + if (i >= n) + break; + if (tx_buf[i]) + send_pulse(tx_buf[i]); + i++; + if (i >= n) + break; + if (tx_buf[i]) + send_space(tx_buf[i]); + i++; + } + terminate_send(tx_buf[i - 1]); + return n; +} + + +static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +{ + int retval = 0; + unsigned long value = 0; + unsigned int ivalue; + unsigned long hw_flags; + + if (cmd == LIRC_GET_FEATURES) + value = LIRC_CAN_SEND_PULSE | + LIRC_CAN_SET_SEND_CARRIER | + LIRC_CAN_REC_MODE2; + else if (cmd == LIRC_GET_SEND_MODE) + value = LIRC_MODE_PULSE; + else if (cmd == LIRC_GET_REC_MODE) + value = LIRC_MODE_MODE2; + + switch (cmd) { + case LIRC_GET_FEATURES: + case LIRC_GET_SEND_MODE: + case LIRC_GET_REC_MODE: + retval = put_user(value, (unsigned long *) arg); + break; + + case LIRC_SET_SEND_MODE: + case LIRC_SET_REC_MODE: + retval = get_user(value, (unsigned long *) arg); + break; + + case LIRC_SET_SEND_CARRIER: + retval = get_user(ivalue, (unsigned int *) arg); + if (retval) + return retval; + ivalue /= 1000; + if (ivalue > IT87_CIR_FREQ_MAX || + ivalue < IT87_CIR_FREQ_MIN) + return -EINVAL; + + it87_freq = ivalue; + + spin_lock_irqsave(&hardware_lock, hw_flags); + outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) | + (it87_freq - IT87_CIR_FREQ_MIN) << 3), + io + IT87_CIR_TCR2); + spin_unlock_irqrestore(&hardware_lock, hw_flags); + dprintk("demodulation frequency: %d kHz\n", it87_freq); + + break; + + default: + retval = -EINVAL; + } + + if (retval) + return retval; + + if (cmd == LIRC_SET_REC_MODE) { + if (value != LIRC_MODE_MODE2) + retval = -ENOSYS; + } else if (cmd == LIRC_SET_SEND_MODE) { + if (value != LIRC_MODE_PULSE) + retval = -ENOSYS; + } + return retval; +} + +static void add_read_queue(int flag, unsigned long val) +{ + unsigned int new_rx_tail; + int newval; + + dprintk("add flag %d with val %lu\n", flag, val); + + newval = val & PULSE_MASK; + + /* + * statistically, pulses are ~TIME_CONST/2 too long. we could + * maybe make this more exact, but this is good enough + */ + if (flag) { + /* pulse */ + if (newval > TIME_CONST / 2) + newval -= TIME_CONST / 2; + else /* should not ever happen */ + newval = 1; + newval |= PULSE_BIT; + } else + newval += TIME_CONST / 2; + new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1); + if (new_rx_tail == rx_head) { + dprintk("Buffer overrun.\n"); + return; + } + rx_buf[rx_tail] = newval; + rx_tail = new_rx_tail; + wake_up_interruptible(&lirc_read_queue); +} + + +static const struct file_operations lirc_fops = { + .owner = THIS_MODULE, + .read = lirc_read, + .write = lirc_write, + .poll = lirc_poll, + .unlocked_ioctl = lirc_ioctl, + .open = lirc_open, + .release = lirc_close, +}; + +static int set_use_inc(void *data) +{ + return 0; +} + +static void set_use_dec(void *data) +{ +} + +static struct lirc_driver driver = { + .name = LIRC_DRIVER_NAME, + .minor = -1, + .code_length = 1, + .sample_rate = 0, + .data = NULL, + .add_to_buf = NULL, + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .fops = &lirc_fops, + .dev = NULL, + .owner = THIS_MODULE, +}; + + +#ifdef MODULE +static int init_chrdev(void) +{ + driver.minor = lirc_register_driver(&driver); + + if (driver.minor < 0) { + printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); + return -EIO; + } + return 0; +} + + +static void drop_chrdev(void) +{ + lirc_unregister_driver(driver.minor); +} +#endif + + +/* SECTION: Hardware */ +static long delta(struct timeval *tv1, struct timeval *tv2) +{ + unsigned long deltv; + + deltv = tv2->tv_sec - tv1->tv_sec; + if (deltv > 15) + deltv = 0xFFFFFF; + else + deltv = deltv*1000000 + tv2->tv_usec - tv1->tv_usec; + return deltv; +} + +static void it87_timeout(unsigned long data) +{ + unsigned long flags; + + /* avoid interference with interrupt */ + spin_lock_irqsave(&timer_lock, flags); + + if (digimatrix) { + /* We have timed out. Disable the RX mechanism. */ + + outb((inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN) | + IT87_CIR_RCR_RXACT, io + IT87_CIR_RCR); + if (it87_RXEN_mask) + outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, + io + IT87_CIR_RCR); + dprintk(" TIMEOUT\n"); + timer_enabled = 0; + + /* fifo clear */ + outb(inb(io + IT87_CIR_TCR1) | IT87_CIR_TCR1_FIFOCLR, + io+IT87_CIR_TCR1); + + } else { + /* + * if last received signal was a pulse, but receiving stopped + * within the 9 bit frame, we need to finish this pulse and + * simulate a signal change to from pulse to space. Otherwise + * upper layers will receive two sequences next time. + */ + + if (last_value) { + unsigned long pulse_end; + + /* determine 'virtual' pulse end: */ + pulse_end = delta(&last_tv, &last_intr_tv); + dprintk("timeout add %d for %lu usec\n", + last_value, pulse_end); + add_read_queue(last_value, pulse_end); + last_value = 0; + last_tv = last_intr_tv; + } + } + spin_unlock_irqrestore(&timer_lock, flags); +} + +static irqreturn_t it87_interrupt(int irq, void *dev_id) +{ + unsigned char data; + struct timeval curr_tv; + static unsigned long deltv; + unsigned long deltintrtv; + unsigned long flags, hw_flags; + int iir, lsr; + int fifo = 0; + static char lastbit; + char bit; + + /* Bit duration in microseconds */ + const unsigned long bit_duration = 1000000ul / + (115200 / IT87_CIR_BAUDRATE_DIVISOR); + + + iir = inb(io + IT87_CIR_IIR); + + switch (iir & IT87_CIR_IIR_IID) { + case 0x4: + case 0x6: + lsr = inb(io + IT87_CIR_RSR) & (IT87_CIR_RSR_RXFTO | + IT87_CIR_RSR_RXFBC); + fifo = lsr & IT87_CIR_RSR_RXFBC; + dprintk("iir: 0x%x fifo: 0x%x\n", iir, lsr); + + /* avoid interference with timer */ + spin_lock_irqsave(&timer_lock, flags); + spin_lock_irqsave(&hardware_lock, hw_flags); + if (digimatrix) { + static unsigned long acc_pulse; + static unsigned long acc_space; + + do { + data = inb(io + IT87_CIR_DR); + data = ~data; + fifo--; + if (data != 0x00) { + if (timer_enabled) + del_timer(&timerlist); + /* + * start timer for end of + * sequence detection + */ + timerlist.expires = jiffies + + IT87_TIMEOUT; + add_timer(&timerlist); + timer_enabled = 1; + } + /* Loop through */ + for (bit = 0; bit < 8; ++bit) { + if ((data >> bit) & 1) { + ++acc_pulse; + if (lastbit == 0) { + add_read_queue(0, + acc_space * + bit_duration); + acc_space = 0; + } + } else { + ++acc_space; + if (lastbit == 1) { + add_read_queue(1, + acc_pulse * + bit_duration); + acc_pulse = 0; + } + } + lastbit = (data >> bit) & 1; + } + + } while (fifo != 0); + } else { /* Normal Operation */ + do { + del_timer(&timerlist); + data = inb(io + IT87_CIR_DR); + + dprintk("data=%02x\n", data); + do_gettimeofday(&curr_tv); + deltv = delta(&last_tv, &curr_tv); + deltintrtv = delta(&last_intr_tv, &curr_tv); + + dprintk("t %lu , d %d\n", + deltintrtv, (int)data); + + /* + * if nothing came in last 2 cycles, + * it was gap + */ + if (deltintrtv > TIME_CONST * 2) { + if (last_value) { + dprintk("GAP\n"); + + /* simulate signal change */ + add_read_queue(last_value, + deltv - + deltintrtv); + last_value = 0; + last_tv.tv_sec = + last_intr_tv.tv_sec; + last_tv.tv_usec = + last_intr_tv.tv_usec; + deltv = deltintrtv; + } + } + data = 1; + if (data ^ last_value) { + /* + * deltintrtv > 2*TIME_CONST, + * remember ? the other case is + * timeout + */ + add_read_queue(last_value, + deltv-TIME_CONST); + last_value = data; + last_tv = curr_tv; + if (last_tv.tv_usec >= TIME_CONST) + last_tv.tv_usec -= TIME_CONST; + else { + last_tv.tv_sec--; + last_tv.tv_usec += 1000000 - + TIME_CONST; + } + } + last_intr_tv = curr_tv; + if (data) { + /* + * start timer for end of + * sequence detection + */ + timerlist.expires = + jiffies + IT87_TIMEOUT; + add_timer(&timerlist); + } + outb((inb(io + IT87_CIR_RCR) & + ~IT87_CIR_RCR_RXEN) | + IT87_CIR_RCR_RXACT, + io + IT87_CIR_RCR); + if (it87_RXEN_mask) + outb(inb(io + IT87_CIR_RCR) | + IT87_CIR_RCR_RXEN, + io + IT87_CIR_RCR); + fifo--; + } while (fifo != 0); + } + spin_unlock_irqrestore(&hardware_lock, hw_flags); + spin_unlock_irqrestore(&timer_lock, flags); + + return IRQ_RETVAL(IRQ_HANDLED); + + default: + /* not our irq */ + dprintk("unknown IRQ (shouldn't happen) !!\n"); + return IRQ_RETVAL(IRQ_NONE); + } +} + + +static void send_it87(unsigned long len, unsigned long stime, + unsigned char send_byte, unsigned int count_bits) +{ + long count = len / stime; + long time_left = 0; + static unsigned char byte_out; + unsigned long hw_flags; + + dprintk("%s: len=%ld, sb=%d\n", __func__, len, send_byte); + + time_left = (long)len - (long)count * (long)stime; + count += ((2 * time_left) / stime); + while (count) { + long i = 0; + for (i = 0; i < count_bits; i++) { + byte_out = (byte_out << 1) | (send_byte & 1); + it87_bits_in_byte_out++; + } + if (it87_bits_in_byte_out == 8) { + dprintk("out=0x%x, tsr_txfbc: 0x%x\n", + byte_out, + inb(io + IT87_CIR_TSR) & + IT87_CIR_TSR_TXFBC); + + while ((inb(io + IT87_CIR_TSR) & + IT87_CIR_TSR_TXFBC) >= IT87_CIR_FIFO_SIZE) + ; + + spin_lock_irqsave(&hardware_lock, hw_flags); + outb(byte_out, io + IT87_CIR_DR); + spin_unlock_irqrestore(&hardware_lock, hw_flags); + + it87_bits_in_byte_out = 0; + it87_send_counter++; + byte_out = 0; + } + count--; + } +} + + +/*TODO: maybe exchange space and pulse because it8705 only modulates 0-bits */ + +static void send_space(unsigned long len) +{ + send_it87(len, TIME_CONST, IT87_CIR_SPACE, IT87_CIR_BAUDRATE_DIVISOR); +} + +static void send_pulse(unsigned long len) +{ + send_it87(len, TIME_CONST, IT87_CIR_PULSE, IT87_CIR_BAUDRATE_DIVISOR); +} + + +static void init_send() +{ + unsigned long flags; + + spin_lock_irqsave(&hardware_lock, flags); + /* RXEN=0: receiver disable */ + it87_RXEN_mask = 0; + outb(inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN, + io + IT87_CIR_RCR); + spin_unlock_irqrestore(&hardware_lock, flags); + it87_bits_in_byte_out = 0; + it87_send_counter = 0; +} + + +static void terminate_send(unsigned long len) +{ + unsigned long flags; + unsigned long last = 0; + + last = it87_send_counter; + /* make sure all necessary data has been sent */ + while (last == it87_send_counter) + send_space(len); + /* wait until all data sent */ + while ((inb(io + IT87_CIR_TSR) & IT87_CIR_TSR_TXFBC) != 0) + ; + /* then re-enable receiver */ + spin_lock_irqsave(&hardware_lock, flags); + it87_RXEN_mask = IT87_CIR_RCR_RXEN; + outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, + io + IT87_CIR_RCR); + spin_unlock_irqrestore(&hardware_lock, flags); +} + + +static int init_hardware(void) +{ + unsigned long flags; + unsigned char it87_rcr = 0; + + spin_lock_irqsave(&hardware_lock, flags); + /* init cir-port */ + /* enable r/w-access to Baudrate-Register */ + outb(IT87_CIR_IER_BR, io + IT87_CIR_IER); + outb(IT87_CIR_BAUDRATE_DIVISOR % 0x100, io+IT87_CIR_BDLR); + outb(IT87_CIR_BAUDRATE_DIVISOR / 0x100, io+IT87_CIR_BDHR); + /* Baudrate Register off, define IRQs: Input only */ + if (digimatrix) { + outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RFOIE, io + IT87_CIR_IER); + /* RX: HCFS=0, RXDCR = 001b (33,75..38,25 kHz), RXEN=1 */ + } else { + outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RDAIE, io + IT87_CIR_IER); + /* RX: HCFS=0, RXDCR = 001b (35,6..40,3 kHz), RXEN=1 */ + } + it87_rcr = (IT87_CIR_RCR_RXEN & it87_RXEN_mask) | 0x1; + if (it87_enable_demodulator) + it87_rcr |= IT87_CIR_RCR_RXEND; + outb(it87_rcr, io + IT87_CIR_RCR); + if (digimatrix) { + /* Set FIFO depth to 1 byte, and disable TX */ + outb(inb(io + IT87_CIR_TCR1) | 0x00, + io + IT87_CIR_TCR1); + + /* + * TX: it87_freq (36kHz), 'reserved' sensitivity + * setting (0x00) + */ + outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x00, + io + IT87_CIR_TCR2); + } else { + /* TX: 38kHz, 13,3us (pulse-width) */ + outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x06, + io + IT87_CIR_TCR2); + } + spin_unlock_irqrestore(&hardware_lock, flags); + return 0; +} + + +static void drop_hardware(void) +{ + unsigned long flags; + + spin_lock_irqsave(&hardware_lock, flags); + disable_irq(irq); + /* receiver disable */ + it87_RXEN_mask = 0; + outb(0x1, io + IT87_CIR_RCR); + /* turn off irqs */ + outb(0, io + IT87_CIR_IER); + /* fifo clear */ + outb(IT87_CIR_TCR1_FIFOCLR, io+IT87_CIR_TCR1); + /* reset */ + outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); + enable_irq(irq); + spin_unlock_irqrestore(&hardware_lock, flags); +} + + +static unsigned char it87_read(unsigned char port) +{ + outb(port, IT87_ADRPORT); + return inb(IT87_DATAPORT); +} + + +static void it87_write(unsigned char port, unsigned char data) +{ + outb(port, IT87_ADRPORT); + outb(data, IT87_DATAPORT); +} + + +/* SECTION: Initialisation */ + +static int init_port(void) +{ + unsigned long hw_flags; + int retval = 0; + + unsigned char init_bytes[4] = IT87_INIT; + unsigned char it87_chipid = 0; + unsigned char ldn = 0; + unsigned int it87_io = 0; + unsigned int it87_irq = 0; + + /* Enter MB PnP Mode */ + outb(init_bytes[0], IT87_ADRPORT); + outb(init_bytes[1], IT87_ADRPORT); + outb(init_bytes[2], IT87_ADRPORT); + outb(init_bytes[3], IT87_ADRPORT); + + /* 8712 or 8705 ? */ + it87_chipid = it87_read(IT87_CHIP_ID1); + if (it87_chipid != 0x87) { + retval = -ENXIO; + return retval; + } + it87_chipid = it87_read(IT87_CHIP_ID2); + if ((it87_chipid != 0x05) && + (it87_chipid != 0x12) && + (it87_chipid != 0x18) && + (it87_chipid != 0x20)) { + printk(KERN_INFO LIRC_DRIVER_NAME + ": no IT8704/05/12/18/20 found (claimed IT87%02x), " + "exiting..\n", it87_chipid); + retval = -ENXIO; + return retval; + } + printk(KERN_INFO LIRC_DRIVER_NAME + ": found IT87%02x.\n", + it87_chipid); + + /* get I/O-Port and IRQ */ + if (it87_chipid == 0x12 || it87_chipid == 0x18) + ldn = IT8712_CIR_LDN; + else + ldn = IT8705_CIR_LDN; + it87_write(IT87_LDN, ldn); + + it87_io = it87_read(IT87_CIR_BASE_MSB) * 256 + + it87_read(IT87_CIR_BASE_LSB); + if (it87_io == 0) { + if (io == 0) + io = IT87_CIR_DEFAULT_IOBASE; + printk(KERN_INFO LIRC_DRIVER_NAME + ": set default io 0x%x\n", + io); + it87_write(IT87_CIR_BASE_MSB, io / 0x100); + it87_write(IT87_CIR_BASE_LSB, io % 0x100); + } else + io = it87_io; + + it87_irq = it87_read(IT87_CIR_IRQ); + if (digimatrix || it87_irq == 0) { + if (irq == 0) + irq = IT87_CIR_DEFAULT_IRQ; + printk(KERN_INFO LIRC_DRIVER_NAME + ": set default irq 0x%x\n", + irq); + it87_write(IT87_CIR_IRQ, irq); + } else + irq = it87_irq; + + spin_lock_irqsave(&hardware_lock, hw_flags); + /* reset */ + outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); + /* fifo clear */ + outb(IT87_CIR_TCR1_FIFOCLR | + /* IT87_CIR_TCR1_ILE | */ + IT87_CIR_TCR1_TXRLE | + IT87_CIR_TCR1_TXENDF, io+IT87_CIR_TCR1); + spin_unlock_irqrestore(&hardware_lock, hw_flags); + + /* get I/O port access and IRQ line */ + if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) { + printk(KERN_ERR LIRC_DRIVER_NAME + ": i/o port 0x%.4x already in use.\n", io); + /* Leaving MB PnP Mode */ + it87_write(IT87_CFGCTRL, 0x2); + return -EBUSY; + } + + /* activate CIR-Device */ + it87_write(IT87_CIR_ACT, 0x1); + + /* Leaving MB PnP Mode */ + it87_write(IT87_CFGCTRL, 0x2); + + retval = request_irq(irq, it87_interrupt, 0 /*IRQF_DISABLED*/, + LIRC_DRIVER_NAME, NULL); + if (retval < 0) { + printk(KERN_ERR LIRC_DRIVER_NAME + ": IRQ %d already in use.\n", + irq); + release_region(io, 8); + return retval; + } + + printk(KERN_INFO LIRC_DRIVER_NAME + ": I/O port 0x%.4x, IRQ %d.\n", io, irq); + + init_timer(&timerlist); + timerlist.function = it87_timeout; + timerlist.data = 0xabadcafe; + + return 0; +} + + +static void drop_port(void) +{ +#if 0 + unsigned char init_bytes[4] = IT87_INIT; + + /* Enter MB PnP Mode */ + outb(init_bytes[0], IT87_ADRPORT); + outb(init_bytes[1], IT87_ADRPORT); + outb(init_bytes[2], IT87_ADRPORT); + outb(init_bytes[3], IT87_ADRPORT); + + /* deactivate CIR-Device */ + it87_write(IT87_CIR_ACT, 0x0); + + /* Leaving MB PnP Mode */ + it87_write(IT87_CFGCTRL, 0x2); +#endif + + del_timer_sync(&timerlist); + free_irq(irq, NULL); + release_region(io, 8); +} + + +static int init_lirc_it87(void) +{ + int retval; + + init_waitqueue_head(&lirc_read_queue); + retval = init_port(); + if (retval < 0) + return retval; + init_hardware(); + printk(KERN_INFO LIRC_DRIVER_NAME ": Installed.\n"); + return 0; +} + +static int it87_probe(struct pnp_dev *pnp_dev, + const struct pnp_device_id *dev_id) +{ + int retval; + + driver.dev = &pnp_dev->dev; + + retval = init_chrdev(); + if (retval < 0) + return retval; + + retval = init_lirc_it87(); + if (retval) + goto init_lirc_it87_failed; + + return 0; + +init_lirc_it87_failed: + drop_chrdev(); + + return retval; +} + +static int __init lirc_it87_init(void) +{ + return pnp_register_driver(&it87_pnp_driver); +} + + +static void __exit lirc_it87_exit(void) +{ + drop_hardware(); + drop_chrdev(); + drop_port(); + pnp_unregister_driver(&it87_pnp_driver); + printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); +} + +/* SECTION: PNP for ITE8704/18 */ + +static const struct pnp_device_id pnp_dev_table[] = { + {"ITE8704", 0}, + {} +}; + +MODULE_DEVICE_TABLE(pnp, pnp_dev_table); + +static struct pnp_driver it87_pnp_driver = { + .name = LIRC_DRIVER_NAME, + .id_table = pnp_dev_table, + .probe = it87_probe, +}; + +module_init(lirc_it87_init); +module_exit(lirc_it87_exit); + +MODULE_DESCRIPTION("LIRC driver for ITE IT8704/05/12/18/20 CIR port"); +MODULE_AUTHOR("Hans-Gunter Lutke Uphues"); +MODULE_LICENSE("GPL"); + +module_param(io, int, S_IRUGO); +MODULE_PARM_DESC(io, "I/O base address (default: 0x310)"); + +module_param(irq, int, S_IRUGO); +#ifdef LIRC_IT87_DIGIMATRIX +MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 9)"); +#else +MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 7)"); +#endif + +module_param(it87_enable_demodulator, bool, S_IRUGO); +MODULE_PARM_DESC(it87_enable_demodulator, + "Receiver demodulator enable/disable (1/0), default: 0"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); + +module_param(digimatrix, bool, S_IRUGO | S_IWUSR); +#ifdef LIRC_IT87_DIGIMATRIX +MODULE_PARM_DESC(digimatrix, + "Asus Digimatrix it87 compat. enable/disable (1/0), default: 1"); +#else +MODULE_PARM_DESC(digimatrix, + "Asus Digimatrix it87 compat. enable/disable (1/0), default: 0"); +#endif + + +module_param(it87_freq, int, S_IRUGO); +#ifdef LIRC_IT87_DIGIMATRIX +MODULE_PARM_DESC(it87_freq, + "Carrier demodulator frequency (kHz), (default: 36)"); +#else +MODULE_PARM_DESC(it87_freq, + "Carrier demodulator frequency (kHz), (default: 38)"); +#endif diff --git a/drivers/staging/lirc/lirc_it87.h b/drivers/staging/lirc/lirc_it87.h new file mode 100644 index 000000000000..cf021c893a35 --- /dev/null +++ b/drivers/staging/lirc/lirc_it87.h @@ -0,0 +1,116 @@ +/* lirc_it87.h */ +/* SECTION: Definitions */ + +/********************************* ITE IT87xx ************************/ + +/* based on the following documentation from ITE: + a) IT8712F Preliminary CIR Programming Guide V0.1 + b) IT8705F Simple LPC I/O Preliminary Specification V0.3 + c) IT8712F EC-LPC I/O Preliminary Specification V0.5 +*/ + +/* IT8712/05 Ports: */ +#define IT87_ADRPORT 0x2e +#define IT87_DATAPORT 0x2f +#define IT87_INIT {0x87, 0x01, 0x55, 0x55} + +/* alternate Ports: */ +/* +#define IT87_ADRPORT 0x4e +#define IT87_DATAPORT 0x4f +#define IT87_INIT {0x87, 0x01, 0x55, 0xaa} + */ + +/* IT8712/05 Registers */ +#define IT87_CFGCTRL 0x2 +#define IT87_LDN 0x7 +#define IT87_CHIP_ID1 0x20 +#define IT87_CHIP_ID2 0x21 +#define IT87_CFG_VERSION 0x22 +#define IT87_SWSUSPEND 0x23 + +#define IT8712_CIR_LDN 0xa +#define IT8705_CIR_LDN 0x7 + +/* CIR Configuration Registers: */ +#define IT87_CIR_ACT 0x30 +#define IT87_CIR_BASE_MSB 0x60 +#define IT87_CIR_BASE_LSB 0x61 +#define IT87_CIR_IRQ 0x70 +#define IT87_CIR_CONFIG 0xf0 + +/* List of IT87_CIR registers: offset to BaseAddr */ +#define IT87_CIR_DR 0 +#define IT87_CIR_IER 1 +#define IT87_CIR_RCR 2 +#define IT87_CIR_TCR1 3 +#define IT87_CIR_TCR2 4 +#define IT87_CIR_TSR 5 +#define IT87_CIR_RSR 6 +#define IT87_CIR_BDLR 5 +#define IT87_CIR_BDHR 6 +#define IT87_CIR_IIR 7 + +/* Bit Definition */ +/* IER: */ +#define IT87_CIR_IER_TM_EN 0x80 +#define IT87_CIR_IER_RESEVED 0x40 +#define IT87_CIR_IER_RESET 0x20 +#define IT87_CIR_IER_BR 0x10 +#define IT87_CIR_IER_IEC 0x8 +#define IT87_CIR_IER_RFOIE 0x4 +#define IT87_CIR_IER_RDAIE 0x2 +#define IT87_CIR_IER_TLDLIE 0x1 + +/* RCR: */ +#define IT87_CIR_RCR_RDWOS 0x80 +#define IT87_CIR_RCR_HCFS 0x40 +#define IT87_CIR_RCR_RXEN 0x20 +#define IT87_CIR_RCR_RXEND 0x10 +#define IT87_CIR_RCR_RXACT 0x8 +#define IT87_CIR_RCR_RXDCR 0x7 + +/* TCR1: */ +#define IT87_CIR_TCR1_FIFOCLR 0x80 +#define IT87_CIR_TCR1_ILE 0x40 +#define IT87_CIR_TCR1_FIFOTL 0x30 +#define IT87_CIR_TCR1_TXRLE 0x8 +#define IT87_CIR_TCR1_TXENDF 0x4 +#define IT87_CIR_TCR1_TXMPM 0x3 + +/* TCR2: */ +#define IT87_CIR_TCR2_CFQ 0xf8 +#define IT87_CIR_TCR2_TXMPW 0x7 + +/* TSR: */ +#define IT87_CIR_TSR_RESERVED 0xc0 +#define IT87_CIR_TSR_TXFBC 0x3f + +/* RSR: */ +#define IT87_CIR_RSR_RXFTO 0x80 +#define IT87_CIR_RSR_RESERVED 0x40 +#define IT87_CIR_RSR_RXFBC 0x3f + +/* IIR: */ +#define IT87_CIR_IIR_RESERVED 0xf8 +#define IT87_CIR_IIR_IID 0x6 +#define IT87_CIR_IIR_IIP 0x1 + +/* TM: */ +#define IT87_CIR_TM_IL_SEL 0x80 +#define IT87_CIR_TM_RESERVED 0x40 +#define IT87_CIR_TM_TM_REG 0x3f + +#define IT87_CIR_FIFO_SIZE 32 + +/* Baudratedivisor for IT87: power of 2: only 1,2,4 or 8) */ +#define IT87_CIR_BAUDRATE_DIVISOR 0x1 +#define IT87_CIR_DEFAULT_IOBASE 0x310 +#define IT87_CIR_DEFAULT_IRQ 0x7 +#define IT87_CIR_SPACE 0x00 +#define IT87_CIR_PULSE 0xff +#define IT87_CIR_FREQ_MIN 27 +#define IT87_CIR_FREQ_MAX 58 +#define TIME_CONST (IT87_CIR_BAUDRATE_DIVISOR * 8000000ul / 115200ul) + +/********************************* ITE IT87xx ************************/ diff --git a/drivers/staging/lirc/lirc_ite8709.c b/drivers/staging/lirc/lirc_ite8709.c new file mode 100644 index 000000000000..9352f45bbece --- /dev/null +++ b/drivers/staging/lirc/lirc_ite8709.c @@ -0,0 +1,542 @@ +/* + * LIRC driver for ITE8709 CIR port + * + * Copyright (C) 2008 GrĂ©gory Lardière <spmf2004-lirc@yahoo.fr> + * + * 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; either version 2 of the + * License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/pnp.h> +#include <linux/io.h> + +#include <media/lirc.h> +#include <media/lirc_dev.h> + +#define LIRC_DRIVER_NAME "lirc_ite8709" + +#define BUF_CHUNK_SIZE sizeof(int) +#define BUF_SIZE (128*BUF_CHUNK_SIZE) + +/* + * The ITE8709 device seems to be the combination of IT8512 superIO chip and + * a specific firmware running on the IT8512's embedded micro-controller. + * In addition of the embedded micro-controller, the IT8512 chip contains a + * CIR module and several other modules. A few modules are directly accessible + * by the host CPU, but most of them are only accessible by the + * micro-controller. The CIR module is only accessible by the micro-controller. + * The battery-backed SRAM module is accessible by the host CPU and the + * micro-controller. So one of the MC's firmware role is to act as a bridge + * between the host CPU and the CIR module. The firmware implements a kind of + * communication protocol using the SRAM module as a shared memory. The IT8512 + * specification is publicly available on ITE's web site, but the communication + * protocol is not, so it was reverse-engineered. + */ + +/* ITE8709 Registers addresses and values (reverse-engineered) */ +#define ITE8709_MODE 0x1a +#define ITE8709_REG_ADR 0x1b +#define ITE8709_REG_VAL 0x1c +#define ITE8709_IIR 0x1e /* Interrupt identification register */ +#define ITE8709_RFSR 0x1f /* Receiver FIFO status register */ +#define ITE8709_FIFO_START 0x20 + +#define ITE8709_MODE_READY 0X00 +#define ITE8709_MODE_WRITE 0X01 +#define ITE8709_MODE_READ 0X02 +#define ITE8709_IIR_RDAI 0x02 /* Receiver data available interrupt */ +#define ITE8709_IIR_RFOI 0x04 /* Receiver FIFO overrun interrupt */ +#define ITE8709_RFSR_MASK 0x3f /* FIFO byte count mask */ + +/* + * IT8512 CIR-module registers addresses and values + * (from IT8512 E/F specification v0.4.1) + */ +#define IT8512_REG_MSTCR 0x01 /* Master control register */ +#define IT8512_REG_IER 0x02 /* Interrupt enable register */ +#define IT8512_REG_CFR 0x04 /* Carrier frequency register */ +#define IT8512_REG_RCR 0x05 /* Receive control register */ +#define IT8512_REG_BDLR 0x08 /* Baud rate divisor low byte register */ +#define IT8512_REG_BDHR 0x09 /* Baud rate divisor high byte register */ + +#define IT8512_MSTCR_RESET 0x01 /* Reset registers to default value */ +#define IT8512_MSTCR_FIFOCLR 0x02 /* Clear FIFO */ +#define IT8512_MSTCR_FIFOTL_7 0x04 /* FIFO threshold level : 7 */ +#define IT8512_MSTCR_FIFOTL_25 0x0c /* FIFO threshold level : 25 */ +#define IT8512_IER_RDAIE 0x02 /* Enable data interrupt request */ +#define IT8512_IER_RFOIE 0x04 /* Enable FIFO overrun interrupt req */ +#define IT8512_IER_IEC 0x80 /* Enable interrupt request */ +#define IT8512_CFR_CF_36KHZ 0x09 /* Carrier freq : low speed, 36kHz */ +#define IT8512_RCR_RXDCR_1 0x01 /* Demodulation carrier range : 1 */ +#define IT8512_RCR_RXACT 0x08 /* Receiver active */ +#define IT8512_RCR_RXEN 0x80 /* Receiver enable */ +#define IT8512_BDR_6 6 /* Baud rate divisor : 6 */ + +/* Actual values used by this driver */ +#define CFG_FIFOTL IT8512_MSTCR_FIFOTL_25 +#define CFG_CR_FREQ IT8512_CFR_CF_36KHZ +#define CFG_DCR IT8512_RCR_RXDCR_1 +#define CFG_BDR IT8512_BDR_6 +#define CFG_TIMEOUT 100000 /* Rearm interrupt when a space is > 100 ms */ + +static int debug; + +struct ite8709_device { + int use_count; + int io; + int irq; + spinlock_t hardware_lock; + unsigned long long acc_pulse; + unsigned long long acc_space; + char lastbit; + struct timeval last_tv; + struct lirc_driver driver; + struct tasklet_struct tasklet; + char force_rearm; + char rearmed; + char device_busy; +}; + +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ + fmt, ## args); \ + } while (0) + + +static unsigned char ite8709_read(struct ite8709_device *dev, + unsigned char port) +{ + outb(port, dev->io); + return inb(dev->io+1); +} + +static void ite8709_write(struct ite8709_device *dev, unsigned char port, + unsigned char data) +{ + outb(port, dev->io); + outb(data, dev->io+1); +} + +static void ite8709_wait_device(struct ite8709_device *dev) +{ + int i = 0; + /* + * loop until device tells it's ready to continue + * iterations count is usually ~750 but can sometimes achieve 13000 + */ + for (i = 0; i < 15000; i++) { + udelay(2); + if (ite8709_read(dev, ITE8709_MODE) == ITE8709_MODE_READY) + break; + } +} + +static void ite8709_write_register(struct ite8709_device *dev, + unsigned char reg_adr, unsigned char reg_value) +{ + ite8709_wait_device(dev); + + ite8709_write(dev, ITE8709_REG_VAL, reg_value); + ite8709_write(dev, ITE8709_REG_ADR, reg_adr); + ite8709_write(dev, ITE8709_MODE, ITE8709_MODE_WRITE); +} + +static void ite8709_init_hardware(struct ite8709_device *dev) +{ + spin_lock_irq(&dev->hardware_lock); + dev->device_busy = 1; + spin_unlock_irq(&dev->hardware_lock); + + ite8709_write_register(dev, IT8512_REG_BDHR, (CFG_BDR >> 8) & 0xff); + ite8709_write_register(dev, IT8512_REG_BDLR, CFG_BDR & 0xff); + ite8709_write_register(dev, IT8512_REG_CFR, CFG_CR_FREQ); + ite8709_write_register(dev, IT8512_REG_IER, + IT8512_IER_IEC | IT8512_IER_RFOIE | IT8512_IER_RDAIE); + ite8709_write_register(dev, IT8512_REG_RCR, CFG_DCR); + ite8709_write_register(dev, IT8512_REG_MSTCR, + CFG_FIFOTL | IT8512_MSTCR_FIFOCLR); + ite8709_write_register(dev, IT8512_REG_RCR, + IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR); + + spin_lock_irq(&dev->hardware_lock); + dev->device_busy = 0; + spin_unlock_irq(&dev->hardware_lock); + + tasklet_enable(&dev->tasklet); +} + +static void ite8709_drop_hardware(struct ite8709_device *dev) +{ + tasklet_disable(&dev->tasklet); + + spin_lock_irq(&dev->hardware_lock); + dev->device_busy = 1; + spin_unlock_irq(&dev->hardware_lock); + + ite8709_write_register(dev, IT8512_REG_RCR, 0); + ite8709_write_register(dev, IT8512_REG_MSTCR, + IT8512_MSTCR_RESET | IT8512_MSTCR_FIFOCLR); + + spin_lock_irq(&dev->hardware_lock); + dev->device_busy = 0; + spin_unlock_irq(&dev->hardware_lock); +} + +static int ite8709_set_use_inc(void *data) +{ + struct ite8709_device *dev; + dev = data; + if (dev->use_count == 0) + ite8709_init_hardware(dev); + dev->use_count++; + return 0; +} + +static void ite8709_set_use_dec(void *data) +{ + struct ite8709_device *dev; + dev = data; + dev->use_count--; + if (dev->use_count == 0) + ite8709_drop_hardware(dev); +} + +static void ite8709_add_read_queue(struct ite8709_device *dev, int flag, + unsigned long long val) +{ + int value; + + dprintk("add a %llu usec %s\n", val, flag ? "pulse" : "space"); + + value = (val > PULSE_MASK) ? PULSE_MASK : val; + if (flag) + value |= PULSE_BIT; + + if (!lirc_buffer_full(dev->driver.rbuf)) { + lirc_buffer_write(dev->driver.rbuf, (void *) &value); + wake_up(&dev->driver.rbuf->wait_poll); + } +} + +static irqreturn_t ite8709_interrupt(int irq, void *dev_id) +{ + unsigned char data; + int iir, rfsr, i; + int fifo = 0; + char bit; + struct timeval curr_tv; + + /* Bit duration in microseconds */ + const unsigned long bit_duration = 1000000ul / (115200 / CFG_BDR); + + struct ite8709_device *dev; + dev = dev_id; + + /* + * If device is busy, we simply discard data because we are in one of + * these two cases : shutting down or rearming the device, so this + * doesn't really matter and this avoids waiting too long in IRQ ctx + */ + spin_lock(&dev->hardware_lock); + if (dev->device_busy) { + spin_unlock(&dev->hardware_lock); + return IRQ_RETVAL(IRQ_HANDLED); + } + + iir = ite8709_read(dev, ITE8709_IIR); + + switch (iir) { + case ITE8709_IIR_RFOI: + dprintk("fifo overrun, scheduling forced rearm just in case\n"); + dev->force_rearm = 1; + tasklet_schedule(&dev->tasklet); + spin_unlock(&dev->hardware_lock); + return IRQ_RETVAL(IRQ_HANDLED); + + case ITE8709_IIR_RDAI: + rfsr = ite8709_read(dev, ITE8709_RFSR); + fifo = rfsr & ITE8709_RFSR_MASK; + if (fifo > 32) + fifo = 32; + dprintk("iir: 0x%x rfsr: 0x%x fifo: %d\n", iir, rfsr, fifo); + + if (dev->rearmed) { + do_gettimeofday(&curr_tv); + dev->acc_space += 1000000ull + * (curr_tv.tv_sec - dev->last_tv.tv_sec) + + (curr_tv.tv_usec - dev->last_tv.tv_usec); + dev->rearmed = 0; + } + for (i = 0; i < fifo; i++) { + data = ite8709_read(dev, i+ITE8709_FIFO_START); + data = ~data; + /* Loop through */ + for (bit = 0; bit < 8; ++bit) { + if ((data >> bit) & 1) { + dev->acc_pulse += bit_duration; + if (dev->lastbit == 0) { + ite8709_add_read_queue(dev, 0, + dev->acc_space); + dev->acc_space = 0; + } + } else { + dev->acc_space += bit_duration; + if (dev->lastbit == 1) { + ite8709_add_read_queue(dev, 1, + dev->acc_pulse); + dev->acc_pulse = 0; + } + } + dev->lastbit = (data >> bit) & 1; + } + } + ite8709_write(dev, ITE8709_RFSR, 0); + + if (dev->acc_space > CFG_TIMEOUT) { + dprintk("scheduling rearm IRQ\n"); + do_gettimeofday(&dev->last_tv); + dev->force_rearm = 0; + tasklet_schedule(&dev->tasklet); + } + + spin_unlock(&dev->hardware_lock); + return IRQ_RETVAL(IRQ_HANDLED); + + default: + /* not our irq */ + dprintk("unknown IRQ (shouldn't happen) !!\n"); + spin_unlock(&dev->hardware_lock); + return IRQ_RETVAL(IRQ_NONE); + } +} + +static void ite8709_rearm_irq(unsigned long data) +{ + struct ite8709_device *dev; + unsigned long flags; + dev = (struct ite8709_device *) data; + + spin_lock_irqsave(&dev->hardware_lock, flags); + dev->device_busy = 1; + spin_unlock_irqrestore(&dev->hardware_lock, flags); + + if (dev->force_rearm || dev->acc_space > CFG_TIMEOUT) { + dprintk("rearming IRQ\n"); + ite8709_write_register(dev, IT8512_REG_RCR, + IT8512_RCR_RXACT | CFG_DCR); + ite8709_write_register(dev, IT8512_REG_MSTCR, + CFG_FIFOTL | IT8512_MSTCR_FIFOCLR); + ite8709_write_register(dev, IT8512_REG_RCR, + IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR); + if (!dev->force_rearm) + dev->rearmed = 1; + dev->force_rearm = 0; + } + + spin_lock_irqsave(&dev->hardware_lock, flags); + dev->device_busy = 0; + spin_unlock_irqrestore(&dev->hardware_lock, flags); +} + +static int ite8709_cleanup(struct ite8709_device *dev, int stage, int errno, + char *msg) +{ + if (msg != NULL) + printk(KERN_ERR LIRC_DRIVER_NAME ": %s\n", msg); + + switch (stage) { + case 6: + if (dev->use_count > 0) + ite8709_drop_hardware(dev); + case 5: + free_irq(dev->irq, dev); + case 4: + release_region(dev->io, 2); + case 3: + lirc_unregister_driver(dev->driver.minor); + case 2: + lirc_buffer_free(dev->driver.rbuf); + kfree(dev->driver.rbuf); + case 1: + kfree(dev); + case 0: + ; + } + + return errno; +} + +static int __devinit ite8709_pnp_probe(struct pnp_dev *dev, + const struct pnp_device_id *dev_id) +{ + struct lirc_driver *driver; + struct ite8709_device *ite8709_dev; + int ret; + + /* Check resources validity */ + if (!pnp_irq_valid(dev, 0)) + return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IRQ"); + if (!pnp_port_valid(dev, 2)) + return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IO port"); + + /* Allocate memory for device struct */ + ite8709_dev = kzalloc(sizeof(struct ite8709_device), GFP_KERNEL); + if (ite8709_dev == NULL) + return ite8709_cleanup(NULL, 0, -ENOMEM, "kzalloc failed"); + pnp_set_drvdata(dev, ite8709_dev); + + /* Initialize device struct */ + ite8709_dev->use_count = 0; + ite8709_dev->irq = pnp_irq(dev, 0); + ite8709_dev->io = pnp_port_start(dev, 2); + ite8709_dev->hardware_lock = + __SPIN_LOCK_UNLOCKED(ite8709_dev->hardware_lock); + ite8709_dev->acc_pulse = 0; + ite8709_dev->acc_space = 0; + ite8709_dev->lastbit = 0; + do_gettimeofday(&ite8709_dev->last_tv); + tasklet_init(&ite8709_dev->tasklet, ite8709_rearm_irq, + (long) ite8709_dev); + ite8709_dev->force_rearm = 0; + ite8709_dev->rearmed = 0; + ite8709_dev->device_busy = 0; + + /* Initialize driver struct */ + driver = &ite8709_dev->driver; + strcpy(driver->name, LIRC_DRIVER_NAME); + driver->minor = -1; + driver->code_length = sizeof(int) * 8; + driver->sample_rate = 0; + driver->features = LIRC_CAN_REC_MODE2; + driver->data = ite8709_dev; + driver->add_to_buf = NULL; + driver->set_use_inc = ite8709_set_use_inc; + driver->set_use_dec = ite8709_set_use_dec; + driver->dev = &dev->dev; + driver->owner = THIS_MODULE; + + /* Initialize LIRC buffer */ + driver->rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!driver->rbuf) + return ite8709_cleanup(ite8709_dev, 1, -ENOMEM, + "can't allocate lirc_buffer"); + if (lirc_buffer_init(driver->rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) + return ite8709_cleanup(ite8709_dev, 1, -ENOMEM, + "lirc_buffer_init() failed"); + + /* Register LIRC driver */ + ret = lirc_register_driver(driver); + if (ret < 0) + return ite8709_cleanup(ite8709_dev, 2, ret, + "lirc_register_driver() failed"); + + /* Reserve I/O port access */ + if (!request_region(ite8709_dev->io, 2, LIRC_DRIVER_NAME)) + return ite8709_cleanup(ite8709_dev, 3, -EBUSY, + "i/o port already in use"); + + /* Reserve IRQ line */ + ret = request_irq(ite8709_dev->irq, ite8709_interrupt, 0, + LIRC_DRIVER_NAME, ite8709_dev); + if (ret < 0) + return ite8709_cleanup(ite8709_dev, 4, ret, + "IRQ already in use"); + + /* Initialize hardware */ + ite8709_drop_hardware(ite8709_dev); /* Shutdown hw until first use */ + + printk(KERN_INFO LIRC_DRIVER_NAME ": device found : irq=%d io=0x%x\n", + ite8709_dev->irq, ite8709_dev->io); + + return 0; +} + +static void __devexit ite8709_pnp_remove(struct pnp_dev *dev) +{ + struct ite8709_device *ite8709_dev; + ite8709_dev = pnp_get_drvdata(dev); + + ite8709_cleanup(ite8709_dev, 6, 0, NULL); + + printk(KERN_INFO LIRC_DRIVER_NAME ": device removed\n"); +} + +#ifdef CONFIG_PM +static int ite8709_pnp_suspend(struct pnp_dev *dev, pm_message_t state) +{ + struct ite8709_device *ite8709_dev; + ite8709_dev = pnp_get_drvdata(dev); + + if (ite8709_dev->use_count > 0) + ite8709_drop_hardware(ite8709_dev); + + return 0; +} + +static int ite8709_pnp_resume(struct pnp_dev *dev) +{ + struct ite8709_device *ite8709_dev; + ite8709_dev = pnp_get_drvdata(dev); + + if (ite8709_dev->use_count > 0) + ite8709_init_hardware(ite8709_dev); + + return 0; +} +#else +#define ite8709_pnp_suspend NULL +#define ite8709_pnp_resume NULL +#endif + +static const struct pnp_device_id pnp_dev_table[] = { + {"ITE8709", 0}, + {} +}; + +MODULE_DEVICE_TABLE(pnp, pnp_dev_table); + +static struct pnp_driver ite8709_pnp_driver = { + .name = LIRC_DRIVER_NAME, + .probe = ite8709_pnp_probe, + .remove = __devexit_p(ite8709_pnp_remove), + .suspend = ite8709_pnp_suspend, + .resume = ite8709_pnp_resume, + .id_table = pnp_dev_table, +}; + +static int __init ite8709_init_module(void) +{ + return pnp_register_driver(&ite8709_pnp_driver); +} +module_init(ite8709_init_module); + +static void __exit ite8709_cleanup_module(void) +{ + pnp_unregister_driver(&ite8709_pnp_driver); +} +module_exit(ite8709_cleanup_module); + +MODULE_DESCRIPTION("LIRC driver for ITE8709 CIR port"); +MODULE_AUTHOR("GrĂ©gory Lardière"); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); diff --git a/drivers/staging/lirc/lirc_parallel.c b/drivers/staging/lirc/lirc_parallel.c new file mode 100644 index 000000000000..a1ebd071640f --- /dev/null +++ b/drivers/staging/lirc/lirc_parallel.c @@ -0,0 +1,705 @@ +/* + * lirc_parallel.c + * + * lirc_parallel - device driver for infra-red signal receiving and + * transmitting unit built by the author + * + * Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/*** Includes ***/ + +#ifdef CONFIG_SMP +#error "--- Sorry, this driver is not SMP safe. ---" +#endif + +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/signal.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/ioport.h> +#include <linux/time.h> +#include <linux/mm.h> +#include <linux/delay.h> + +#include <linux/io.h> +#include <linux/signal.h> +#include <linux/irq.h> +#include <linux/uaccess.h> +#include <asm/div64.h> + +#include <linux/poll.h> +#include <linux/parport.h> + +#include <media/lirc.h> +#include <media/lirc_dev.h> + +#include "lirc_parallel.h" + +#define LIRC_DRIVER_NAME "lirc_parallel" + +#ifndef LIRC_IRQ +#define LIRC_IRQ 7 +#endif +#ifndef LIRC_PORT +#define LIRC_PORT 0x378 +#endif +#ifndef LIRC_TIMER +#define LIRC_TIMER 65536 +#endif + +/*** Global Variables ***/ + +static int debug; +static int check_pselecd; + +unsigned int irq = LIRC_IRQ; +unsigned int io = LIRC_PORT; +#ifdef LIRC_TIMER +unsigned int timer; +unsigned int default_timer = LIRC_TIMER; +#endif + +#define RBUF_SIZE (256) /* this must be a power of 2 larger than 1 */ + +static int rbuf[RBUF_SIZE]; + +DECLARE_WAIT_QUEUE_HEAD(lirc_wait); + +unsigned int rptr; +unsigned int wptr; +unsigned int lost_irqs; +int is_open; + +struct parport *pport; +struct pardevice *ppdevice; +int is_claimed; + +unsigned int tx_mask = 1; + +/*** Internal Functions ***/ + +static unsigned int in(int offset) +{ + switch (offset) { + case LIRC_LP_BASE: + return parport_read_data(pport); + case LIRC_LP_STATUS: + return parport_read_status(pport); + case LIRC_LP_CONTROL: + return parport_read_control(pport); + } + return 0; /* make compiler happy */ +} + +static void out(int offset, int value) +{ + switch (offset) { + case LIRC_LP_BASE: + parport_write_data(pport, value); + break; + case LIRC_LP_CONTROL: + parport_write_control(pport, value); + break; + case LIRC_LP_STATUS: + printk(KERN_INFO "%s: attempt to write to status register\n", + LIRC_DRIVER_NAME); + break; + } +} + +static unsigned int lirc_get_timer(void) +{ + return in(LIRC_PORT_TIMER) & LIRC_PORT_TIMER_BIT; +} + +static unsigned int lirc_get_signal(void) +{ + return in(LIRC_PORT_SIGNAL) & LIRC_PORT_SIGNAL_BIT; +} + +static void lirc_on(void) +{ + out(LIRC_PORT_DATA, tx_mask); +} + +static void lirc_off(void) +{ + out(LIRC_PORT_DATA, 0); +} + +static unsigned int init_lirc_timer(void) +{ + struct timeval tv, now; + unsigned int level, newlevel, timeelapsed, newtimer; + int count = 0; + + do_gettimeofday(&tv); + tv.tv_sec++; /* wait max. 1 sec. */ + level = lirc_get_timer(); + do { + newlevel = lirc_get_timer(); + if (level == 0 && newlevel != 0) + count++; + level = newlevel; + do_gettimeofday(&now); + } while (count < 1000 && (now.tv_sec < tv.tv_sec + || (now.tv_sec == tv.tv_sec + && now.tv_usec < tv.tv_usec))); + + timeelapsed = ((now.tv_sec + 1 - tv.tv_sec)*1000000 + + (now.tv_usec - tv.tv_usec)); + if (count >= 1000 && timeelapsed > 0) { + if (default_timer == 0) { + /* autodetect timer */ + newtimer = (1000000*count)/timeelapsed; + printk(KERN_INFO "%s: %u Hz timer detected\n", + LIRC_DRIVER_NAME, newtimer); + return newtimer; + } else { + newtimer = (1000000*count)/timeelapsed; + if (abs(newtimer - default_timer) > default_timer/10) { + /* bad timer */ + printk(KERN_NOTICE "%s: bad timer: %u Hz\n", + LIRC_DRIVER_NAME, newtimer); + printk(KERN_NOTICE "%s: using default timer: " + "%u Hz\n", + LIRC_DRIVER_NAME, default_timer); + return default_timer; + } else { + printk(KERN_INFO "%s: %u Hz timer detected\n", + LIRC_DRIVER_NAME, newtimer); + return newtimer; /* use detected value */ + } + } + } else { + printk(KERN_NOTICE "%s: no timer detected\n", LIRC_DRIVER_NAME); + return 0; + } +} + +static int lirc_claim(void) +{ + if (parport_claim(ppdevice) != 0) { + printk(KERN_WARNING "%s: could not claim port\n", + LIRC_DRIVER_NAME); + printk(KERN_WARNING "%s: waiting for port becoming available" + "\n", LIRC_DRIVER_NAME); + if (parport_claim_or_block(ppdevice) < 0) { + printk(KERN_NOTICE "%s: could not claim port, giving" + " up\n", LIRC_DRIVER_NAME); + return 0; + } + } + out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); + is_claimed = 1; + return 1; +} + +/*** interrupt handler ***/ + +static void rbuf_write(int signal) +{ + unsigned int nwptr; + + nwptr = (wptr + 1) & (RBUF_SIZE - 1); + if (nwptr == rptr) { + /* no new signals will be accepted */ + lost_irqs++; + printk(KERN_NOTICE "%s: buffer overrun\n", LIRC_DRIVER_NAME); + return; + } + rbuf[wptr] = signal; + wptr = nwptr; +} + +static void irq_handler(void *blah) +{ + struct timeval tv; + static struct timeval lasttv; + static int init; + long signal; + int data; + unsigned int level, newlevel; + unsigned int timeout; + + if (!module_refcount(THIS_MODULE)) + return; + + if (!is_claimed) + return; + +#if 0 + /* disable interrupt */ + disable_irq(irq); + out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ) & (~LP_PINTEN)); +#endif + if (check_pselecd && (in(1) & LP_PSELECD)) + return; + +#ifdef LIRC_TIMER + if (init) { + do_gettimeofday(&tv); + + signal = tv.tv_sec - lasttv.tv_sec; + if (signal > 15) + /* really long time */ + data = PULSE_MASK; + else + data = (int) (signal*1000000 + + tv.tv_usec - lasttv.tv_usec + + LIRC_SFH506_DELAY); + + rbuf_write(data); /* space */ + } else { + if (timer == 0) { + /* + * wake up; we'll lose this signal, but it will be + * garbage if the device is turned on anyway + */ + timer = init_lirc_timer(); + /* enable_irq(irq); */ + return; + } + init = 1; + } + + timeout = timer/10; /* timeout after 1/10 sec. */ + signal = 1; + level = lirc_get_timer(); + do { + newlevel = lirc_get_timer(); + if (level == 0 && newlevel != 0) + signal++; + level = newlevel; + + /* giving up */ + if (signal > timeout + || (check_pselecd && (in(1) & LP_PSELECD))) { + signal = 0; + printk(KERN_NOTICE "%s: timeout\n", LIRC_DRIVER_NAME); + break; + } + } while (lirc_get_signal()); + + if (signal != 0) { + /* ajust value to usecs */ + unsigned long long helper; + + helper = ((unsigned long long) signal)*1000000; + do_div(helper, timer); + signal = (long) helper; + + if (signal > LIRC_SFH506_DELAY) + data = signal - LIRC_SFH506_DELAY; + else + data = 1; + rbuf_write(PULSE_BIT|data); /* pulse */ + } + do_gettimeofday(&lasttv); +#else + /* add your code here */ +#endif + + wake_up_interruptible(&lirc_wait); + + /* enable interrupt */ + /* + enable_irq(irq); + out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ)|LP_PINTEN); + */ +} + +/*** file operations ***/ + +static loff_t lirc_lseek(struct file *filep, loff_t offset, int orig) +{ + return -ESPIPE; +} + +static ssize_t lirc_read(struct file *filep, char *buf, size_t n, loff_t *ppos) +{ + int result = 0; + int count = 0; + DECLARE_WAITQUEUE(wait, current); + + if (n % sizeof(int)) + return -EINVAL; + + add_wait_queue(&lirc_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + while (count < n) { + if (rptr != wptr) { + if (copy_to_user(buf+count, (char *) &rbuf[rptr], + sizeof(int))) { + result = -EFAULT; + break; + } + rptr = (rptr + 1) & (RBUF_SIZE - 1); + count += sizeof(int); + } else { + if (filep->f_flags & O_NONBLOCK) { + result = -EAGAIN; + break; + } + if (signal_pending(current)) { + result = -ERESTARTSYS; + break; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } + } + remove_wait_queue(&lirc_wait, &wait); + set_current_state(TASK_RUNNING); + return count ? count : result; +} + +static ssize_t lirc_write(struct file *filep, const char *buf, size_t n, + loff_t *ppos) +{ + int count; + unsigned int i; + unsigned int level, newlevel; + unsigned long flags; + int counttimer; + int *wbuf; + + if (!is_claimed) + return -EBUSY; + + count = n / sizeof(int); + + if (n % sizeof(int) || count % 2 == 0) + return -EINVAL; + + wbuf = memdup_user(buf, n); + if (IS_ERR(wbuf)) + return PTR_ERR(wbuf); + +#ifdef LIRC_TIMER + if (timer == 0) { + /* try again if device is ready */ + timer = init_lirc_timer(); + if (timer == 0) + return -EIO; + } + + /* adjust values from usecs */ + for (i = 0; i < count; i++) { + unsigned long long helper; + + helper = ((unsigned long long) wbuf[i])*timer; + do_div(helper, 1000000); + wbuf[i] = (int) helper; + } + + local_irq_save(flags); + i = 0; + while (i < count) { + level = lirc_get_timer(); + counttimer = 0; + lirc_on(); + do { + newlevel = lirc_get_timer(); + if (level == 0 && newlevel != 0) + counttimer++; + level = newlevel; + if (check_pselecd && (in(1) & LP_PSELECD)) { + lirc_off(); + local_irq_restore(flags); + return -EIO; + } + } while (counttimer < wbuf[i]); + i++; + + lirc_off(); + if (i == count) + break; + counttimer = 0; + do { + newlevel = lirc_get_timer(); + if (level == 0 && newlevel != 0) + counttimer++; + level = newlevel; + if (check_pselecd && (in(1) & LP_PSELECD)) { + local_irq_restore(flags); + return -EIO; + } + } while (counttimer < wbuf[i]); + i++; + } + local_irq_restore(flags); +#else + /* place code that handles write without external timer here */ +#endif + return n; +} + +static unsigned int lirc_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &lirc_wait, wait); + if (rptr != wptr) + return POLLIN | POLLRDNORM; + return 0; +} + +static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +{ + int result; + unsigned long features = LIRC_CAN_SET_TRANSMITTER_MASK | + LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2; + unsigned long mode; + unsigned int ivalue; + + switch (cmd) { + case LIRC_GET_FEATURES: + result = put_user(features, (unsigned long *) arg); + if (result) + return result; + break; + case LIRC_GET_SEND_MODE: + result = put_user(LIRC_MODE_PULSE, (unsigned long *) arg); + if (result) + return result; + break; + case LIRC_GET_REC_MODE: + result = put_user(LIRC_MODE_MODE2, (unsigned long *) arg); + if (result) + return result; + break; + case LIRC_SET_SEND_MODE: + result = get_user(mode, (unsigned long *) arg); + if (result) + return result; + if (mode != LIRC_MODE_PULSE) + return -EINVAL; + break; + case LIRC_SET_REC_MODE: + result = get_user(mode, (unsigned long *) arg); + if (result) + return result; + if (mode != LIRC_MODE_MODE2) + return -ENOSYS; + break; + case LIRC_SET_TRANSMITTER_MASK: + result = get_user(ivalue, (unsigned int *) arg); + if (result) + return result; + if ((ivalue & LIRC_PARALLEL_TRANSMITTER_MASK) != ivalue) + return LIRC_PARALLEL_MAX_TRANSMITTERS; + tx_mask = ivalue; + break; + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static int lirc_open(struct inode *node, struct file *filep) +{ + if (module_refcount(THIS_MODULE) || !lirc_claim()) + return -EBUSY; + + parport_enable_irq(pport); + + /* init read ptr */ + rptr = 0; + wptr = 0; + lost_irqs = 0; + + is_open = 1; + return 0; +} + +static int lirc_close(struct inode *node, struct file *filep) +{ + if (is_claimed) { + is_claimed = 0; + parport_release(ppdevice); + } + is_open = 0; + return 0; +} + +static const struct file_operations lirc_fops = { + .owner = THIS_MODULE, + .llseek = lirc_lseek, + .read = lirc_read, + .write = lirc_write, + .poll = lirc_poll, + .unlocked_ioctl = lirc_ioctl, + .open = lirc_open, + .release = lirc_close +}; + +static int set_use_inc(void *data) +{ + return 0; +} + +static void set_use_dec(void *data) +{ +} + +static struct lirc_driver driver = { + .name = LIRC_DRIVER_NAME, + .minor = -1, + .code_length = 1, + .sample_rate = 0, + .data = NULL, + .add_to_buf = NULL, + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .fops = &lirc_fops, + .dev = NULL, + .owner = THIS_MODULE, +}; + +static int pf(void *handle); +static void kf(void *handle); + +static struct timer_list poll_timer; +static void poll_state(unsigned long ignored); + +static void poll_state(unsigned long ignored) +{ + printk(KERN_NOTICE "%s: time\n", + LIRC_DRIVER_NAME); + del_timer(&poll_timer); + if (is_claimed) + return; + kf(NULL); + if (!is_claimed) { + printk(KERN_NOTICE "%s: could not claim port, giving up\n", + LIRC_DRIVER_NAME); + init_timer(&poll_timer); + poll_timer.expires = jiffies + HZ; + poll_timer.data = (unsigned long)current; + poll_timer.function = poll_state; + add_timer(&poll_timer); + } +} + +static int pf(void *handle) +{ + parport_disable_irq(pport); + is_claimed = 0; + return 0; +} + +static void kf(void *handle) +{ + if (!is_open) + return; + if (!lirc_claim()) + return; + parport_enable_irq(pport); + lirc_off(); + /* this is a bit annoying when you actually print...*/ + /* + printk(KERN_INFO "%s: reclaimed port\n", LIRC_DRIVER_NAME); + */ +} + +/*** module initialization and cleanup ***/ + +static int __init lirc_parallel_init(void) +{ + pport = parport_find_base(io); + if (pport == NULL) { + printk(KERN_NOTICE "%s: no port at %x found\n", + LIRC_DRIVER_NAME, io); + return -ENXIO; + } + ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME, + pf, kf, irq_handler, 0, NULL); + parport_put_port(pport); + if (ppdevice == NULL) { + printk(KERN_NOTICE "%s: parport_register_device() failed\n", + LIRC_DRIVER_NAME); + return -ENXIO; + } + if (parport_claim(ppdevice) != 0) + goto skip_init; + is_claimed = 1; + out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); + +#ifdef LIRC_TIMER + if (debug) + out(LIRC_PORT_DATA, tx_mask); + + timer = init_lirc_timer(); + +#if 0 /* continue even if device is offline */ + if (timer == 0) { + is_claimed = 0; + parport_release(pport); + parport_unregister_device(ppdevice); + return -EIO; + } + +#endif + if (debug) + out(LIRC_PORT_DATA, 0); +#endif + + is_claimed = 0; + parport_release(ppdevice); + skip_init: + driver.minor = lirc_register_driver(&driver); + if (driver.minor < 0) { + printk(KERN_NOTICE "%s: register_chrdev() failed\n", + LIRC_DRIVER_NAME); + parport_unregister_device(ppdevice); + return -EIO; + } + printk(KERN_INFO "%s: installed using port 0x%04x irq %d\n", + LIRC_DRIVER_NAME, io, irq); + return 0; +} + +static void __exit lirc_parallel_exit(void) +{ + parport_unregister_device(ppdevice); + lirc_unregister_driver(driver.minor); +} + +module_init(lirc_parallel_init); +module_exit(lirc_parallel_exit); + +MODULE_DESCRIPTION("Infrared receiver driver for parallel ports."); +MODULE_AUTHOR("Christoph Bartelmus"); +MODULE_LICENSE("GPL"); + +module_param(io, int, S_IRUGO); +MODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)"); + +module_param(irq, int, S_IRUGO); +MODULE_PARM_DESC(irq, "Interrupt (7 or 5)"); + +module_param(tx_mask, int, S_IRUGO); +MODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); + +module_param(check_pselecd, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Check for printer (default: 0)"); diff --git a/drivers/staging/lirc/lirc_parallel.h b/drivers/staging/lirc/lirc_parallel.h new file mode 100644 index 000000000000..4bed6afe0632 --- /dev/null +++ b/drivers/staging/lirc/lirc_parallel.h @@ -0,0 +1,26 @@ +/* lirc_parallel.h */ + +#ifndef _LIRC_PARALLEL_H +#define _LIRC_PARALLEL_H + +#include <linux/lp.h> + +#define LIRC_PORT_LEN 3 + +#define LIRC_LP_BASE 0 +#define LIRC_LP_STATUS 1 +#define LIRC_LP_CONTROL 2 + +#define LIRC_PORT_DATA LIRC_LP_BASE /* base */ +#define LIRC_PORT_TIMER LIRC_LP_STATUS /* status port */ +#define LIRC_PORT_TIMER_BIT LP_PBUSY /* busy signal */ +#define LIRC_PORT_SIGNAL LIRC_LP_STATUS /* status port */ +#define LIRC_PORT_SIGNAL_BIT LP_PACK /* ack signal */ +#define LIRC_PORT_IRQ LIRC_LP_CONTROL /* control port */ + +#define LIRC_SFH506_DELAY 0 /* delay t_phl in usecs */ + +#define LIRC_PARALLEL_MAX_TRANSMITTERS 8 +#define LIRC_PARALLEL_TRANSMITTER_MASK ((1<<LIRC_PARALLEL_MAX_TRANSMITTERS) - 1) + +#endif diff --git a/drivers/staging/lirc/lirc_sasem.c b/drivers/staging/lirc/lirc_sasem.c new file mode 100644 index 000000000000..73166c3f581f --- /dev/null +++ b/drivers/staging/lirc/lirc_sasem.c @@ -0,0 +1,933 @@ +/* + * lirc_sasem.c - USB remote support for LIRC + * Version 0.5 + * + * Copyright (C) 2004-2005 Oliver Stabel <oliver.stabel@gmx.de> + * Tim Davies <tim@opensystems.net.au> + * + * This driver was derived from: + * Venky Raju <dev@venky.ws> + * "lirc_imon - "LIRC/VFD driver for Ahanix/Soundgraph IMON IR/VFD" + * Paul Miller <pmiller9@users.sourceforge.net>'s 2003-2004 + * "lirc_atiusb - USB remote support for LIRC" + * Culver Consulting Services <henry@culcon.com>'s 2003 + * "Sasem OnAir VFD/IR USB driver" + * + * + * NOTE - The LCDproc iMon driver should work with this module. More info at + * http://www.frogstorm.info/sasem + */ + +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/uaccess.h> +#include <linux/usb.h> + +#include <media/lirc.h> +#include <media/lirc_dev.h> + + +#define MOD_AUTHOR "Oliver Stabel <oliver.stabel@gmx.de>, " \ + "Tim Davies <tim@opensystems.net.au>" +#define MOD_DESC "USB Driver for Sasem Remote Controller V1.1" +#define MOD_NAME "lirc_sasem" +#define MOD_VERSION "0.5" + +#define VFD_MINOR_BASE 144 /* Same as LCD */ +#define DEVICE_NAME "lcd%d" + +#define BUF_CHUNK_SIZE 8 +#define BUF_SIZE 128 + +#define IOCTL_LCD_CONTRAST 1 + +/*** P R O T O T Y P E S ***/ + +/* USB Callback prototypes */ +static int sasem_probe(struct usb_interface *interface, + const struct usb_device_id *id); +static void sasem_disconnect(struct usb_interface *interface); +static void usb_rx_callback(struct urb *urb); +static void usb_tx_callback(struct urb *urb); + +/* VFD file_operations function prototypes */ +static int vfd_open(struct inode *inode, struct file *file); +static long vfd_ioctl(struct file *file, unsigned cmd, unsigned long arg); +static int vfd_close(struct inode *inode, struct file *file); +static ssize_t vfd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos); + +/* LIRC driver function prototypes */ +static int ir_open(void *data); +static void ir_close(void *data); + +/* Driver init/exit prototypes */ +static int __init sasem_init(void); +static void __exit sasem_exit(void); + +/*** G L O B A L S ***/ +#define SASEM_DATA_BUF_SZ 32 + +struct sasem_context { + + struct usb_device *dev; + int vfd_isopen; /* VFD port has been opened */ + unsigned int vfd_contrast; /* VFD contrast */ + int ir_isopen; /* IR port has been opened */ + int dev_present; /* USB device presence */ + struct mutex ctx_lock; /* to lock this object */ + wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ + + struct lirc_driver *driver; + struct usb_endpoint_descriptor *rx_endpoint; + struct usb_endpoint_descriptor *tx_endpoint; + struct urb *rx_urb; + struct urb *tx_urb; + unsigned char usb_rx_buf[8]; + unsigned char usb_tx_buf[8]; + + struct tx_t { + unsigned char data_buf[SASEM_DATA_BUF_SZ]; /* user data buffer */ + struct completion finished; /* wait for write to finish */ + atomic_t busy; /* write in progress */ + int status; /* status of tx completion */ + } tx; + + /* for dealing with repeat codes (wish there was a toggle bit!) */ + struct timeval presstime; + char lastcode[8]; + int codesaved; +}; + +/* VFD file operations */ +static const struct file_operations vfd_fops = { + .owner = THIS_MODULE, + .open = &vfd_open, + .write = &vfd_write, + .unlocked_ioctl = &vfd_ioctl, + .release = &vfd_close, +}; + +/* USB Device ID for Sasem USB Control Board */ +static struct usb_device_id sasem_usb_id_table[] = { + /* Sasem USB Control Board */ + { USB_DEVICE(0x11ba, 0x0101) }, + /* Terminating entry */ + {} +}; + +/* USB Device data */ +static struct usb_driver sasem_driver = { + .name = MOD_NAME, + .probe = sasem_probe, + .disconnect = sasem_disconnect, + .id_table = sasem_usb_id_table, +}; + +static struct usb_class_driver sasem_class = { + .name = DEVICE_NAME, + .fops = &vfd_fops, + .minor_base = VFD_MINOR_BASE, +}; + +/* to prevent races between open() and disconnect() */ +static DEFINE_MUTEX(disconnect_lock); + +static int debug; + + +/*** M O D U L E C O D E ***/ + +MODULE_AUTHOR(MOD_AUTHOR); +MODULE_DESCRIPTION(MOD_DESC); +MODULE_LICENSE("GPL"); +module_param(debug, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)"); + +static void delete_context(struct sasem_context *context) +{ + usb_free_urb(context->tx_urb); /* VFD */ + usb_free_urb(context->rx_urb); /* IR */ + lirc_buffer_free(context->driver->rbuf); + kfree(context->driver->rbuf); + kfree(context->driver); + kfree(context); + + if (debug) + printk(KERN_INFO "%s: context deleted\n", __func__); +} + +static void deregister_from_lirc(struct sasem_context *context) +{ + int retval; + int minor = context->driver->minor; + + retval = lirc_unregister_driver(minor); + if (retval) + err("%s: unable to deregister from lirc (%d)", + __func__, retval); + else + printk(KERN_INFO "Deregistered Sasem driver (minor:%d)\n", + minor); + +} + +/** + * Called when the VFD device (e.g. /dev/usb/lcd) + * is opened by the application. + */ +static int vfd_open(struct inode *inode, struct file *file) +{ + struct usb_interface *interface; + struct sasem_context *context = NULL; + int subminor; + int retval = 0; + + /* prevent races with disconnect */ + mutex_lock(&disconnect_lock); + + subminor = iminor(inode); + interface = usb_find_interface(&sasem_driver, subminor); + if (!interface) { + err("%s: could not find interface for minor %d", + __func__, subminor); + retval = -ENODEV; + goto exit; + } + context = usb_get_intfdata(interface); + + if (!context) { + err("%s: no context found for minor %d", + __func__, subminor); + retval = -ENODEV; + goto exit; + } + + mutex_lock(&context->ctx_lock); + + if (context->vfd_isopen) { + err("%s: VFD port is already open", __func__); + retval = -EBUSY; + } else { + context->vfd_isopen = 1; + file->private_data = context; + printk(KERN_INFO "VFD port opened\n"); + } + + mutex_unlock(&context->ctx_lock); + +exit: + mutex_unlock(&disconnect_lock); + return retval; +} + +/** + * Called when the VFD device (e.g. /dev/usb/lcd) + * is closed by the application. + */ +static long vfd_ioctl(struct file *file, unsigned cmd, unsigned long arg) +{ + struct sasem_context *context = NULL; + + context = (struct sasem_context *) file->private_data; + + if (!context) { + err("%s: no context for device", __func__); + return -ENODEV; + } + + mutex_lock(&context->ctx_lock); + + switch (cmd) { + case IOCTL_LCD_CONTRAST: + if (arg > 1000) + arg = 1000; + context->vfd_contrast = (unsigned int)arg; + break; + default: + printk(KERN_INFO "Unknown IOCTL command\n"); + mutex_unlock(&context->ctx_lock); + return -ENOIOCTLCMD; /* not supported */ + } + + mutex_unlock(&context->ctx_lock); + return 0; +} + +/** + * Called when the VFD device (e.g. /dev/usb/lcd) + * is closed by the application. + */ +static int vfd_close(struct inode *inode, struct file *file) +{ + struct sasem_context *context = NULL; + int retval = 0; + + context = (struct sasem_context *) file->private_data; + + if (!context) { + err("%s: no context for device", __func__); + return -ENODEV; + } + + mutex_lock(&context->ctx_lock); + + if (!context->vfd_isopen) { + err("%s: VFD is not open", __func__); + retval = -EIO; + } else { + context->vfd_isopen = 0; + printk(KERN_INFO "VFD port closed\n"); + if (!context->dev_present && !context->ir_isopen) { + + /* Device disconnected before close and IR port is + * not open. If IR port is open, context will be + * deleted by ir_close. */ + mutex_unlock(&context->ctx_lock); + delete_context(context); + return retval; + } + } + + mutex_unlock(&context->ctx_lock); + return retval; +} + +/** + * Sends a packet to the VFD. + */ +static int send_packet(struct sasem_context *context) +{ + unsigned int pipe; + int interval = 0; + int retval = 0; + + pipe = usb_sndintpipe(context->dev, + context->tx_endpoint->bEndpointAddress); + interval = context->tx_endpoint->bInterval; + + usb_fill_int_urb(context->tx_urb, context->dev, pipe, + context->usb_tx_buf, sizeof(context->usb_tx_buf), + usb_tx_callback, context, interval); + + context->tx_urb->actual_length = 0; + + init_completion(&context->tx.finished); + atomic_set(&(context->tx.busy), 1); + + retval = usb_submit_urb(context->tx_urb, GFP_KERNEL); + if (retval) { + atomic_set(&(context->tx.busy), 0); + err("%s: error submitting urb (%d)", __func__, retval); + } else { + /* Wait for transmission to complete (or abort) */ + mutex_unlock(&context->ctx_lock); + wait_for_completion(&context->tx.finished); + mutex_lock(&context->ctx_lock); + + retval = context->tx.status; + if (retval) + err("%s: packet tx failed (%d)", __func__, retval); + } + + return retval; +} + +/** + * Writes data to the VFD. The Sasem VFD is 2x16 characters + * and requires data in 9 consecutive USB interrupt packets, + * each packet carrying 8 bytes. + */ +static ssize_t vfd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos) +{ + int i; + int retval = 0; + struct sasem_context *context; + int *data_buf; + + context = (struct sasem_context *) file->private_data; + if (!context) { + err("%s: no context for device", __func__); + return -ENODEV; + } + + mutex_lock(&context->ctx_lock); + + if (!context->dev_present) { + err("%s: no Sasem device present", __func__); + retval = -ENODEV; + goto exit; + } + + if (n_bytes <= 0 || n_bytes > SASEM_DATA_BUF_SZ) { + err("%s: invalid payload size", __func__); + retval = -EINVAL; + goto exit; + } + + data_buf = memdup_user(buf, n_bytes); + if (PTR_ERR(data_buf)) + return PTR_ERR(data_buf); + + memcpy(context->tx.data_buf, data_buf, n_bytes); + + /* Pad with spaces */ + for (i = n_bytes; i < SASEM_DATA_BUF_SZ; ++i) + context->tx.data_buf[i] = ' '; + + /* Nine 8 byte packets to be sent */ + /* NOTE: "\x07\x01\0\0\0\0\0\0" or "\x0c\0\0\0\0\0\0\0" + * will clear the VFD */ + for (i = 0; i < 9; i++) { + switch (i) { + case 0: + memcpy(context->usb_tx_buf, "\x07\0\0\0\0\0\0\0", 8); + context->usb_tx_buf[1] = (context->vfd_contrast) ? + (0x2B - (context->vfd_contrast - 1) / 250) + : 0x2B; + break; + case 1: + memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8); + break; + case 2: + memcpy(context->usb_tx_buf, "\x0b\x01\0\0\0\0\0\0", 8); + break; + case 3: + memcpy(context->usb_tx_buf, context->tx.data_buf, 8); + break; + case 4: + memcpy(context->usb_tx_buf, + context->tx.data_buf + 8, 8); + break; + case 5: + memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8); + break; + case 6: + memcpy(context->usb_tx_buf, "\x0b\x02\0\0\0\0\0\0", 8); + break; + case 7: + memcpy(context->usb_tx_buf, + context->tx.data_buf + 16, 8); + break; + case 8: + memcpy(context->usb_tx_buf, + context->tx.data_buf + 24, 8); + break; + } + retval = send_packet(context); + if (retval) { + + err("%s: send packet failed for packet #%d", + __func__, i); + goto exit; + } + } +exit: + + mutex_unlock(&context->ctx_lock); + + return (!retval) ? n_bytes : retval; +} + +/** + * Callback function for USB core API: transmit data + */ +static void usb_tx_callback(struct urb *urb) +{ + struct sasem_context *context; + + if (!urb) + return; + context = (struct sasem_context *) urb->context; + if (!context) + return; + + context->tx.status = urb->status; + + /* notify waiters that write has finished */ + atomic_set(&context->tx.busy, 0); + complete(&context->tx.finished); + + return; +} + +/** + * Called by lirc_dev when the application opens /dev/lirc + */ +static int ir_open(void *data) +{ + int retval = 0; + struct sasem_context *context; + + /* prevent races with disconnect */ + mutex_lock(&disconnect_lock); + + context = (struct sasem_context *) data; + + mutex_lock(&context->ctx_lock); + + if (context->ir_isopen) { + err("%s: IR port is already open", __func__); + retval = -EBUSY; + goto exit; + } + + usb_fill_int_urb(context->rx_urb, context->dev, + usb_rcvintpipe(context->dev, + context->rx_endpoint->bEndpointAddress), + context->usb_rx_buf, sizeof(context->usb_rx_buf), + usb_rx_callback, context, context->rx_endpoint->bInterval); + + retval = usb_submit_urb(context->rx_urb, GFP_KERNEL); + + if (retval) + err("%s: usb_submit_urb failed for ir_open (%d)", + __func__, retval); + else { + context->ir_isopen = 1; + printk(KERN_INFO "IR port opened\n"); + } + +exit: + mutex_unlock(&context->ctx_lock); + + mutex_unlock(&disconnect_lock); + return 0; +} + +/** + * Called by lirc_dev when the application closes /dev/lirc + */ +static void ir_close(void *data) +{ + struct sasem_context *context; + + context = (struct sasem_context *)data; + if (!context) { + err("%s: no context for device", __func__); + return; + } + + mutex_lock(&context->ctx_lock); + + usb_kill_urb(context->rx_urb); + context->ir_isopen = 0; + printk(KERN_INFO "IR port closed\n"); + + if (!context->dev_present) { + + /* + * Device disconnected while IR port was + * still open. Driver was not deregistered + * at disconnect time, so do it now. + */ + deregister_from_lirc(context); + + if (!context->vfd_isopen) { + + mutex_unlock(&context->ctx_lock); + delete_context(context); + return; + } + /* If VFD port is open, context will be deleted by vfd_close */ + } + + mutex_unlock(&context->ctx_lock); + return; +} + +/** + * Process the incoming packet + */ +static void incoming_packet(struct sasem_context *context, + struct urb *urb) +{ + int len = urb->actual_length; + unsigned char *buf = urb->transfer_buffer; + long ms; + struct timeval tv; + + if (len != 8) { + printk(KERN_WARNING "%s: invalid incoming packet size (%d)\n", + __func__, len); + return; + } + +#ifdef DEBUG + int i; + for (i = 0; i < 8; ++i) + printk(KERN_INFO "%02x ", buf[i]); + printk(KERN_INFO "\n"); +#endif + + /* + * Lirc could deal with the repeat code, but we really need to block it + * if it arrives too late. Otherwise we could repeat the wrong code. + */ + + /* get the time since the last button press */ + do_gettimeofday(&tv); + ms = (tv.tv_sec - context->presstime.tv_sec) * 1000 + + (tv.tv_usec - context->presstime.tv_usec) / 1000; + + if (memcmp(buf, "\x08\0\0\0\0\0\0\0", 8) == 0) { + /* + * the repeat code is being sent, so we copy + * the old code to LIRC + */ + + /* + * NOTE: Only if the last code was less than 250ms ago + * - no one should be able to push another (undetected) button + * in that time and then get a false repeat of the previous + * press but it is long enough for a genuine repeat + */ + if ((ms < 250) && (context->codesaved != 0)) { + memcpy(buf, &context->lastcode, 8); + context->presstime.tv_sec = tv.tv_sec; + context->presstime.tv_usec = tv.tv_usec; + } + } else { + /* save the current valid code for repeats */ + memcpy(&context->lastcode, buf, 8); + /* + * set flag to signal a valid code was save; + * just for safety reasons + */ + context->codesaved = 1; + context->presstime.tv_sec = tv.tv_sec; + context->presstime.tv_usec = tv.tv_usec; + } + + lirc_buffer_write(context->driver->rbuf, buf); + wake_up(&context->driver->rbuf->wait_poll); +} + +/** + * Callback function for USB core API: receive data + */ +static void usb_rx_callback(struct urb *urb) +{ + struct sasem_context *context; + + if (!urb) + return; + context = (struct sasem_context *) urb->context; + if (!context) + return; + + switch (urb->status) { + + case -ENOENT: /* usbcore unlink successful! */ + return; + + case 0: + if (context->ir_isopen) + incoming_packet(context, urb); + break; + + default: + printk(KERN_WARNING "%s: status (%d): ignored", + __func__, urb->status); + break; + } + + usb_submit_urb(context->rx_urb, GFP_ATOMIC); + return; +} + + + +/** + * Callback function for USB core API: Probe + */ +static int sasem_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *dev = NULL; + struct usb_host_interface *iface_desc = NULL; + struct usb_endpoint_descriptor *rx_endpoint = NULL; + struct usb_endpoint_descriptor *tx_endpoint = NULL; + struct urb *rx_urb = NULL; + struct urb *tx_urb = NULL; + struct lirc_driver *driver = NULL; + struct lirc_buffer *rbuf = NULL; + int lirc_minor = 0; + int num_endpoints; + int retval = 0; + int vfd_ep_found; + int ir_ep_found; + int alloc_status; + struct sasem_context *context = NULL; + int i; + + printk(KERN_INFO "%s: found Sasem device\n", __func__); + + + dev = usb_get_dev(interface_to_usbdev(interface)); + iface_desc = interface->cur_altsetting; + num_endpoints = iface_desc->desc.bNumEndpoints; + + /* + * Scan the endpoint list and set: + * first input endpoint = IR endpoint + * first output endpoint = VFD endpoint + */ + + ir_ep_found = 0; + vfd_ep_found = 0; + + for (i = 0; i < num_endpoints && !(ir_ep_found && vfd_ep_found); ++i) { + + struct usb_endpoint_descriptor *ep; + int ep_dir; + int ep_type; + ep = &iface_desc->endpoint [i].desc; + ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; + ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + + if (!ir_ep_found && + ep_dir == USB_DIR_IN && + ep_type == USB_ENDPOINT_XFER_INT) { + + rx_endpoint = ep; + ir_ep_found = 1; + if (debug) + printk(KERN_INFO "%s: found IR endpoint\n", + __func__); + + } else if (!vfd_ep_found && + ep_dir == USB_DIR_OUT && + ep_type == USB_ENDPOINT_XFER_INT) { + + tx_endpoint = ep; + vfd_ep_found = 1; + if (debug) + printk(KERN_INFO "%s: found VFD endpoint\n", + __func__); + } + } + + /* Input endpoint is mandatory */ + if (!ir_ep_found) { + + err("%s: no valid input (IR) endpoint found.", __func__); + retval = -ENODEV; + goto exit; + } + + if (!vfd_ep_found) + printk(KERN_INFO "%s: no valid output (VFD) endpoint found.\n", + __func__); + + + /* Allocate memory */ + alloc_status = 0; + + context = kzalloc(sizeof(struct sasem_context), GFP_KERNEL); + if (!context) { + err("%s: kzalloc failed for context", __func__); + alloc_status = 1; + goto alloc_status_switch; + } + driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); + if (!driver) { + err("%s: kzalloc failed for lirc_driver", __func__); + alloc_status = 2; + goto alloc_status_switch; + } + rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!rbuf) { + err("%s: kmalloc failed for lirc_buffer", __func__); + alloc_status = 3; + goto alloc_status_switch; + } + if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) { + err("%s: lirc_buffer_init failed", __func__); + alloc_status = 4; + goto alloc_status_switch; + } + rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!rx_urb) { + err("%s: usb_alloc_urb failed for IR urb", __func__); + alloc_status = 5; + goto alloc_status_switch; + } + if (vfd_ep_found) { + tx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!tx_urb) { + err("%s: usb_alloc_urb failed for VFD urb", + __func__); + alloc_status = 6; + goto alloc_status_switch; + } + } + + mutex_init(&context->ctx_lock); + + strcpy(driver->name, MOD_NAME); + driver->minor = -1; + driver->code_length = 64; + driver->sample_rate = 0; + driver->features = LIRC_CAN_REC_LIRCCODE; + driver->data = context; + driver->rbuf = rbuf; + driver->set_use_inc = ir_open; + driver->set_use_dec = ir_close; + driver->dev = &interface->dev; + driver->owner = THIS_MODULE; + + mutex_lock(&context->ctx_lock); + + lirc_minor = lirc_register_driver(driver); + if (lirc_minor < 0) { + err("%s: lirc_register_driver failed", __func__); + alloc_status = 7; + mutex_unlock(&context->ctx_lock); + } else + printk(KERN_INFO "%s: Registered Sasem driver (minor:%d)\n", + __func__, lirc_minor); + +alloc_status_switch: + + switch (alloc_status) { + + case 7: + if (vfd_ep_found) + usb_free_urb(tx_urb); + case 6: + usb_free_urb(rx_urb); + case 5: + lirc_buffer_free(rbuf); + case 4: + kfree(rbuf); + case 3: + kfree(driver); + case 2: + kfree(context); + context = NULL; + case 1: + retval = -ENOMEM; + goto exit; + } + + /* Needed while unregistering! */ + driver->minor = lirc_minor; + + context->dev = dev; + context->dev_present = 1; + context->rx_endpoint = rx_endpoint; + context->rx_urb = rx_urb; + if (vfd_ep_found) { + context->tx_endpoint = tx_endpoint; + context->tx_urb = tx_urb; + context->vfd_contrast = 1000; /* range 0 - 1000 */ + } + context->driver = driver; + + usb_set_intfdata(interface, context); + + if (vfd_ep_found) { + + if (debug) + printk(KERN_INFO "Registering VFD with sysfs\n"); + if (usb_register_dev(interface, &sasem_class)) + /* Not a fatal error, so ignore */ + printk(KERN_INFO "%s: could not get a minor number " + "for VFD\n", __func__); + } + + printk(KERN_INFO "%s: Sasem device on usb<%d:%d> initialized\n", + __func__, dev->bus->busnum, dev->devnum); + + mutex_unlock(&context->ctx_lock); +exit: + return retval; +} + +/** + * Callback function for USB core API: disonnect + */ +static void sasem_disconnect(struct usb_interface *interface) +{ + struct sasem_context *context; + + /* prevent races with ir_open()/vfd_open() */ + mutex_lock(&disconnect_lock); + + context = usb_get_intfdata(interface); + mutex_lock(&context->ctx_lock); + + printk(KERN_INFO "%s: Sasem device disconnected\n", __func__); + + usb_set_intfdata(interface, NULL); + context->dev_present = 0; + + /* Stop reception */ + usb_kill_urb(context->rx_urb); + + /* Abort ongoing write */ + if (atomic_read(&context->tx.busy)) { + + usb_kill_urb(context->tx_urb); + wait_for_completion(&context->tx.finished); + } + + /* De-register from lirc_dev if IR port is not open */ + if (!context->ir_isopen) + deregister_from_lirc(context); + + usb_deregister_dev(interface, &sasem_class); + + mutex_unlock(&context->ctx_lock); + + if (!context->ir_isopen && !context->vfd_isopen) + delete_context(context); + + mutex_unlock(&disconnect_lock); +} + +static int __init sasem_init(void) +{ + int rc; + + printk(KERN_INFO MOD_DESC ", v" MOD_VERSION "\n"); + printk(KERN_INFO MOD_AUTHOR "\n"); + + rc = usb_register(&sasem_driver); + if (rc < 0) { + err("%s: usb register failed (%d)", __func__, rc); + return -ENODEV; + } + return 0; +} + +static void __exit sasem_exit(void) +{ + usb_deregister(&sasem_driver); + printk(KERN_INFO "module removed. Goodbye!\n"); +} + + +module_init(sasem_init); +module_exit(sasem_exit); diff --git a/drivers/staging/lirc/lirc_serial.c b/drivers/staging/lirc/lirc_serial.c new file mode 100644 index 000000000000..9456f8e3f9ef --- /dev/null +++ b/drivers/staging/lirc/lirc_serial.c @@ -0,0 +1,1313 @@ +/* + * lirc_serial.c + * + * lirc_serial - Device driver that records pulse- and pause-lengths + * (space-lengths) between DDCD event on a serial port. + * + * Copyright (C) 1996,97 Ralph Metzler <rjkm@thp.uni-koeln.de> + * Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu> + * Copyright (C) 1998 Ben Pfaff <blp@gnu.org> + * Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de> + * Copyright (C) 2007 Andrei Tanas <andrei@tanas.ca> (suspend/resume support) + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * Steve's changes to improve transmission fidelity: + * - for systems with the rdtsc instruction and the clock counter, a + * send_pule that times the pulses directly using the counter. + * This means that the LIRC_SERIAL_TRANSMITTER_LATENCY fudge is + * not needed. Measurement shows very stable waveform, even where + * PCI activity slows the access to the UART, which trips up other + * versions. + * - For other system, non-integer-microsecond pulse/space lengths, + * done using fixed point binary. So, much more accurate carrier + * frequency. + * - fine tuned transmitter latency, taking advantage of fractional + * microseconds in previous change + * - Fixed bug in the way transmitter latency was accounted for by + * tuning the pulse lengths down - the send_pulse routine ignored + * this overhead as it timed the overall pulse length - so the + * pulse frequency was right but overall pulse length was too + * long. Fixed by accounting for latency on each pulse/space + * iteration. + * + * Steve Davies <steve@daviesfam.org> July 2001 + */ + +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/fs.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/kernel.h> +#include <linux/serial_reg.h> +#include <linux/time.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/wait.h> +#include <linux/mm.h> +#include <linux/delay.h> +#include <linux/poll.h> +#include <linux/platform_device.h> + +#include <asm/system.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/fcntl.h> +#include <linux/spinlock.h> + +#ifdef CONFIG_LIRC_SERIAL_NSLU2 +#include <asm/hardware.h> +#endif +/* From Intel IXP42X Developer's Manual (#252480-005): */ +/* ftp://download.intel.com/design/network/manuals/25248005.pdf */ +#define UART_IE_IXP42X_UUE 0x40 /* IXP42X UART Unit enable */ +#define UART_IE_IXP42X_RTOIE 0x10 /* IXP42X Receiver Data Timeout int.enable */ + +#include <media/lirc.h> +#include <media/lirc_dev.h> + +#define LIRC_DRIVER_NAME "lirc_serial" + +struct lirc_serial { + int signal_pin; + int signal_pin_change; + u8 on; + u8 off; + long (*send_pulse)(unsigned long length); + void (*send_space)(long length); + int features; + spinlock_t lock; +}; + +#define LIRC_HOMEBREW 0 +#define LIRC_IRDEO 1 +#define LIRC_IRDEO_REMOTE 2 +#define LIRC_ANIMAX 3 +#define LIRC_IGOR 4 +#define LIRC_NSLU2 5 + +/*** module parameters ***/ +static int type; +static int io; +static int irq; +static int iommap; +static int ioshift; +static int softcarrier = 1; +static int share_irq; +static int debug; +static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */ +static int txsense; /* 0 = active high, 1 = active low */ + +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ + fmt, ## args); \ + } while (0) + +/* forward declarations */ +static long send_pulse_irdeo(unsigned long length); +static long send_pulse_homebrew(unsigned long length); +static void send_space_irdeo(long length); +static void send_space_homebrew(long length); + +static struct lirc_serial hardware[] = { + [LIRC_HOMEBREW] = { + .signal_pin = UART_MSR_DCD, + .signal_pin_change = UART_MSR_DDCD, + .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), + .off = (UART_MCR_RTS | UART_MCR_OUT2), + .send_pulse = send_pulse_homebrew, + .send_space = send_space_homebrew, +#ifdef CONFIG_LIRC_SERIAL_TRANSMITTER + .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | + LIRC_CAN_SET_SEND_CARRIER | + LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) +#else + .features = LIRC_CAN_REC_MODE2 +#endif + }, + + [LIRC_IRDEO] = { + .signal_pin = UART_MSR_DSR, + .signal_pin_change = UART_MSR_DDSR, + .on = UART_MCR_OUT2, + .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), + .send_pulse = send_pulse_irdeo, + .send_space = send_space_irdeo, + .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | + LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) + }, + + [LIRC_IRDEO_REMOTE] = { + .signal_pin = UART_MSR_DSR, + .signal_pin_change = UART_MSR_DDSR, + .on = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), + .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), + .send_pulse = send_pulse_irdeo, + .send_space = send_space_irdeo, + .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | + LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) + }, + + [LIRC_ANIMAX] = { + .signal_pin = UART_MSR_DCD, + .signal_pin_change = UART_MSR_DDCD, + .on = 0, + .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), + .send_pulse = NULL, + .send_space = NULL, + .features = LIRC_CAN_REC_MODE2 + }, + + [LIRC_IGOR] = { + .signal_pin = UART_MSR_DSR, + .signal_pin_change = UART_MSR_DDSR, + .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), + .off = (UART_MCR_RTS | UART_MCR_OUT2), + .send_pulse = send_pulse_homebrew, + .send_space = send_space_homebrew, +#ifdef CONFIG_LIRC_SERIAL_TRANSMITTER + .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | + LIRC_CAN_SET_SEND_CARRIER | + LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) +#else + .features = LIRC_CAN_REC_MODE2 +#endif + }, + +#ifdef CONFIG_LIRC_SERIAL_NSLU2 + /* + * Modified Linksys Network Storage Link USB 2.0 (NSLU2): + * We receive on CTS of the 2nd serial port (R142,LHS), we + * transmit with a IR diode between GPIO[1] (green status LED), + * and ground (Matthias Goebl <matthias.goebl@goebl.net>). + * See also http://www.nslu2-linux.org for this device + */ + [LIRC_NSLU2] = { + .signal_pin = UART_MSR_CTS, + .signal_pin_change = UART_MSR_DCTS, + .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), + .off = (UART_MCR_RTS | UART_MCR_OUT2), + .send_pulse = send_pulse_homebrew, + .send_space = send_space_homebrew, +#ifdef CONFIG_LIRC_SERIAL_TRANSMITTER + .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | + LIRC_CAN_SET_SEND_CARRIER | + LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) +#else + .features = LIRC_CAN_REC_MODE2 +#endif + }, +#endif + +}; + +#define RS_ISR_PASS_LIMIT 256 + +/* + * A long pulse code from a remote might take up to 300 bytes. The + * daemon should read the bytes as soon as they are generated, so take + * the number of keys you think you can push before the daemon runs + * and multiply by 300. The driver will warn you if you overrun this + * buffer. If you have a slow computer or non-busmastering IDE disks, + * maybe you will need to increase this. + */ + +/* This MUST be a power of two! It has to be larger than 1 as well. */ + +#define RBUF_LEN 256 + +static struct timeval lasttv = {0, 0}; + +static struct lirc_buffer rbuf; + +static unsigned int freq = 38000; +static unsigned int duty_cycle = 50; + +/* Initialized in init_timing_params() */ +static unsigned long period; +static unsigned long pulse_width; +static unsigned long space_width; + +#if defined(__i386__) +/* + * From: + * Linux I/O port programming mini-HOWTO + * Author: Riku Saikkonen <Riku.Saikkonen@hut.fi> + * v, 28 December 1997 + * + * [...] + * Actually, a port I/O instruction on most ports in the 0-0x3ff range + * takes almost exactly 1 microsecond, so if you're, for example, using + * the parallel port directly, just do additional inb()s from that port + * to delay. + * [...] + */ +/* transmitter latency 1.5625us 0x1.90 - this figure arrived at from + * comment above plus trimming to match actual measured frequency. + * This will be sensitive to cpu speed, though hopefully most of the 1.5us + * is spent in the uart access. Still - for reference test machine was a + * 1.13GHz Athlon system - Steve + */ + +/* + * changed from 400 to 450 as this works better on slower machines; + * faster machines will use the rdtsc code anyway + */ +#define LIRC_SERIAL_TRANSMITTER_LATENCY 450 + +#else + +/* does anybody have information on other platforms ? */ +/* 256 = 1<<8 */ +#define LIRC_SERIAL_TRANSMITTER_LATENCY 256 + +#endif /* __i386__ */ +/* + * FIXME: should we be using hrtimers instead of this + * LIRC_SERIAL_TRANSMITTER_LATENCY nonsense? + */ + +/* fetch serial input packet (1 byte) from register offset */ +static u8 sinp(int offset) +{ + if (iommap != 0) + /* the register is memory-mapped */ + offset <<= ioshift; + + return inb(io + offset); +} + +/* write serial output packet (1 byte) of value to register offset */ +static void soutp(int offset, u8 value) +{ + if (iommap != 0) + /* the register is memory-mapped */ + offset <<= ioshift; + + outb(value, io + offset); +} + +static void on(void) +{ +#ifdef CONFIG_LIRC_SERIAL_NSLU2 + /* + * On NSLU2, we put the transmit diode between the output of the green + * status LED and ground + */ + if (type == LIRC_NSLU2) { + gpio_line_set(NSLU2_LED_GRN, IXP4XX_GPIO_LOW); + return; + } +#endif + if (txsense) + soutp(UART_MCR, hardware[type].off); + else + soutp(UART_MCR, hardware[type].on); +} + +static void off(void) +{ +#ifdef CONFIG_LIRC_SERIAL_NSLU2 + if (type == LIRC_NSLU2) { + gpio_line_set(NSLU2_LED_GRN, IXP4XX_GPIO_HIGH); + return; + } +#endif + if (txsense) + soutp(UART_MCR, hardware[type].on); + else + soutp(UART_MCR, hardware[type].off); +} + +#ifndef MAX_UDELAY_MS +#define MAX_UDELAY_US 5000 +#else +#define MAX_UDELAY_US (MAX_UDELAY_MS*1000) +#endif + +static void safe_udelay(unsigned long usecs) +{ + while (usecs > MAX_UDELAY_US) { + udelay(MAX_UDELAY_US); + usecs -= MAX_UDELAY_US; + } + udelay(usecs); +} + +#ifdef USE_RDTSC +/* + * This is an overflow/precision juggle, complicated in that we can't + * do long long divide in the kernel + */ + +/* + * When we use the rdtsc instruction to measure clocks, we keep the + * pulse and space widths as clock cycles. As this is CPU speed + * dependent, the widths must be calculated in init_port and ioctl + * time + */ + +/* So send_pulse can quickly convert microseconds to clocks */ +static unsigned long conv_us_to_clocks; + +static int init_timing_params(unsigned int new_duty_cycle, + unsigned int new_freq) +{ + unsigned long long loops_per_sec, work; + + duty_cycle = new_duty_cycle; + freq = new_freq; + + loops_per_sec = current_cpu_data.loops_per_jiffy; + loops_per_sec *= HZ; + + /* How many clocks in a microsecond?, avoiding long long divide */ + work = loops_per_sec; + work *= 4295; /* 4295 = 2^32 / 1e6 */ + conv_us_to_clocks = (work >> 32); + + /* + * Carrier period in clocks, approach good up to 32GHz clock, + * gets carrier frequency within 8Hz + */ + period = loops_per_sec >> 3; + period /= (freq >> 3); + + /* Derive pulse and space from the period */ + pulse_width = period * duty_cycle / 100; + space_width = period - pulse_width; + dprintk("in init_timing_params, freq=%d, duty_cycle=%d, " + "clk/jiffy=%ld, pulse=%ld, space=%ld, " + "conv_us_to_clocks=%ld\n", + freq, duty_cycle, current_cpu_data.loops_per_jiffy, + pulse_width, space_width, conv_us_to_clocks); + return 0; +} +#else /* ! USE_RDTSC */ +static int init_timing_params(unsigned int new_duty_cycle, + unsigned int new_freq) +{ +/* + * period, pulse/space width are kept with 8 binary places - + * IE multiplied by 256. + */ + if (256 * 1000000L / new_freq * new_duty_cycle / 100 <= + LIRC_SERIAL_TRANSMITTER_LATENCY) + return -EINVAL; + if (256 * 1000000L / new_freq * (100 - new_duty_cycle) / 100 <= + LIRC_SERIAL_TRANSMITTER_LATENCY) + return -EINVAL; + duty_cycle = new_duty_cycle; + freq = new_freq; + period = 256 * 1000000L / freq; + pulse_width = period * duty_cycle / 100; + space_width = period - pulse_width; + dprintk("in init_timing_params, freq=%d pulse=%ld, " + "space=%ld\n", freq, pulse_width, space_width); + return 0; +} +#endif /* USE_RDTSC */ + + +/* return value: space length delta */ + +static long send_pulse_irdeo(unsigned long length) +{ + long rawbits, ret; + int i; + unsigned char output; + unsigned char chunk, shifted; + + /* how many bits have to be sent ? */ + rawbits = length * 1152 / 10000; + if (duty_cycle > 50) + chunk = 3; + else + chunk = 1; + for (i = 0, output = 0x7f; rawbits > 0; rawbits -= 3) { + shifted = chunk << (i * 3); + shifted >>= 1; + output &= (~shifted); + i++; + if (i == 3) { + soutp(UART_TX, output); + while (!(sinp(UART_LSR) & UART_LSR_THRE)) + ; + output = 0x7f; + i = 0; + } + } + if (i != 0) { + soutp(UART_TX, output); + while (!(sinp(UART_LSR) & UART_LSR_TEMT)) + ; + } + + if (i == 0) + ret = (-rawbits) * 10000 / 1152; + else + ret = (3 - i) * 3 * 10000 / 1152 + (-rawbits) * 10000 / 1152; + + return ret; +} + +#ifdef USE_RDTSC +/* Version that uses Pentium rdtsc instruction to measure clocks */ + +/* + * This version does sub-microsecond timing using rdtsc instruction, + * and does away with the fudged LIRC_SERIAL_TRANSMITTER_LATENCY + * Implicitly i586 architecture... - Steve + */ + +static long send_pulse_homebrew_softcarrier(unsigned long length) +{ + int flag; + unsigned long target, start, now; + + /* Get going quick as we can */ + rdtscl(start); + on(); + /* Convert length from microseconds to clocks */ + length *= conv_us_to_clocks; + /* And loop till time is up - flipping at right intervals */ + now = start; + target = pulse_width; + flag = 1; + /* + * FIXME: This looks like a hard busy wait, without even an occasional, + * polite, cpu_relax() call. There's got to be a better way? + * + * The i2c code has the result of a lot of bit-banging work, I wonder if + * there's something there which could be helpful here. + */ + while ((now - start) < length) { + /* Delay till flip time */ + do { + rdtscl(now); + } while ((now - start) < target); + + /* flip */ + if (flag) { + rdtscl(now); + off(); + target += space_width; + } else { + rdtscl(now); on(); + target += pulse_width; + } + flag = !flag; + } + rdtscl(now); + return ((now - start) - length) / conv_us_to_clocks; +} +#else /* ! USE_RDTSC */ +/* Version using udelay() */ + +/* + * here we use fixed point arithmetic, with 8 + * fractional bits. that gets us within 0.1% or so of the right average + * frequency, albeit with some jitter in pulse length - Steve + */ + +/* To match 8 fractional bits used for pulse/space length */ + +static long send_pulse_homebrew_softcarrier(unsigned long length) +{ + int flag; + unsigned long actual, target, d; + length <<= 8; + + actual = 0; target = 0; flag = 0; + while (actual < length) { + if (flag) { + off(); + target += space_width; + } else { + on(); + target += pulse_width; + } + d = (target - actual - + LIRC_SERIAL_TRANSMITTER_LATENCY + 128) >> 8; + /* + * Note - we've checked in ioctl that the pulse/space + * widths are big enough so that d is > 0 + */ + udelay(d); + actual += (d << 8) + LIRC_SERIAL_TRANSMITTER_LATENCY; + flag = !flag; + } + return (actual-length) >> 8; +} +#endif /* USE_RDTSC */ + +static long send_pulse_homebrew(unsigned long length) +{ + if (length <= 0) + return 0; + + if (softcarrier) + return send_pulse_homebrew_softcarrier(length); + else { + on(); + safe_udelay(length); + return 0; + } +} + +static void send_space_irdeo(long length) +{ + if (length <= 0) + return; + + safe_udelay(length); +} + +static void send_space_homebrew(long length) +{ + off(); + if (length <= 0) + return; + safe_udelay(length); +} + +static void rbwrite(int l) +{ + if (lirc_buffer_full(&rbuf)) { + /* no new signals will be accepted */ + dprintk("Buffer overrun\n"); + return; + } + lirc_buffer_write(&rbuf, (void *)&l); +} + +static void frbwrite(int l) +{ + /* simple noise filter */ + static int pulse, space; + static unsigned int ptr; + + if (ptr > 0 && (l & PULSE_BIT)) { + pulse += l & PULSE_MASK; + if (pulse > 250) { + rbwrite(space); + rbwrite(pulse | PULSE_BIT); + ptr = 0; + pulse = 0; + } + return; + } + if (!(l & PULSE_BIT)) { + if (ptr == 0) { + if (l > 20000) { + space = l; + ptr++; + return; + } + } else { + if (l > 20000) { + space += pulse; + if (space > PULSE_MASK) + space = PULSE_MASK; + space += l; + if (space > PULSE_MASK) + space = PULSE_MASK; + pulse = 0; + return; + } + rbwrite(space); + rbwrite(pulse | PULSE_BIT); + ptr = 0; + pulse = 0; + } + } + rbwrite(l); +} + +static irqreturn_t irq_handler(int i, void *blah) +{ + struct timeval tv; + int counter, dcd; + u8 status; + long deltv; + int data; + static int last_dcd = -1; + + if ((sinp(UART_IIR) & UART_IIR_NO_INT)) { + /* not our interrupt */ + return IRQ_NONE; + } + + counter = 0; + do { + counter++; + status = sinp(UART_MSR); + if (counter > RS_ISR_PASS_LIMIT) { + printk(KERN_WARNING LIRC_DRIVER_NAME ": AIEEEE: " + "We're caught!\n"); + break; + } + if ((status & hardware[type].signal_pin_change) + && sense != -1) { + /* get current time */ + do_gettimeofday(&tv); + + /* New mode, written by Trent Piepho + <xyzzy@u.washington.edu>. */ + + /* + * The old format was not very portable. + * We now use an int to pass pulses + * and spaces to user space. + * + * If PULSE_BIT is set a pulse has been + * received, otherwise a space has been + * received. The driver needs to know if your + * receiver is active high or active low, or + * the space/pulse sense could be + * inverted. The bits denoted by PULSE_MASK are + * the length in microseconds. Lengths greater + * than or equal to 16 seconds are clamped to + * PULSE_MASK. All other bits are unused. + * This is a much simpler interface for user + * programs, as well as eliminating "out of + * phase" errors with space/pulse + * autodetection. + */ + + /* calc time since last interrupt in microseconds */ + dcd = (status & hardware[type].signal_pin) ? 1 : 0; + + if (dcd == last_dcd) { + printk(KERN_WARNING LIRC_DRIVER_NAME + ": ignoring spike: %d %d %lx %lx %lx %lx\n", + dcd, sense, + tv.tv_sec, lasttv.tv_sec, + tv.tv_usec, lasttv.tv_usec); + continue; + } + + deltv = tv.tv_sec-lasttv.tv_sec; + if (tv.tv_sec < lasttv.tv_sec || + (tv.tv_sec == lasttv.tv_sec && + tv.tv_usec < lasttv.tv_usec)) { + printk(KERN_WARNING LIRC_DRIVER_NAME + ": AIEEEE: your clock just jumped " + "backwards\n"); + printk(KERN_WARNING LIRC_DRIVER_NAME + ": %d %d %lx %lx %lx %lx\n", + dcd, sense, + tv.tv_sec, lasttv.tv_sec, + tv.tv_usec, lasttv.tv_usec); + data = PULSE_MASK; + } else if (deltv > 15) { + data = PULSE_MASK; /* really long time */ + if (!(dcd^sense)) { + /* sanity check */ + printk(KERN_WARNING LIRC_DRIVER_NAME + ": AIEEEE: " + "%d %d %lx %lx %lx %lx\n", + dcd, sense, + tv.tv_sec, lasttv.tv_sec, + tv.tv_usec, lasttv.tv_usec); + /* + * detecting pulse while this + * MUST be a space! + */ + sense = sense ? 0 : 1; + } + } else + data = (int) (deltv*1000000 + + tv.tv_usec - + lasttv.tv_usec); + frbwrite(dcd^sense ? data : (data|PULSE_BIT)); + lasttv = tv; + last_dcd = dcd; + wake_up_interruptible(&rbuf.wait_poll); + } + } while (!(sinp(UART_IIR) & UART_IIR_NO_INT)); /* still pending ? */ + return IRQ_HANDLED; +} + + +static int hardware_init_port(void) +{ + u8 scratch, scratch2, scratch3; + + /* + * This is a simple port existence test, borrowed from the autoconfig + * function in drivers/serial/8250.c + */ + scratch = sinp(UART_IER); + soutp(UART_IER, 0); +#ifdef __i386__ + outb(0xff, 0x080); +#endif + scratch2 = sinp(UART_IER) & 0x0f; + soutp(UART_IER, 0x0f); +#ifdef __i386__ + outb(0x00, 0x080); +#endif + scratch3 = sinp(UART_IER) & 0x0f; + soutp(UART_IER, scratch); + if (scratch2 != 0 || scratch3 != 0x0f) { + /* we fail, there's nothing here */ + printk(KERN_ERR LIRC_DRIVER_NAME ": port existence test " + "failed, cannot continue\n"); + return -EINVAL; + } + + + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* First of all, disable all interrupts */ + soutp(UART_IER, sinp(UART_IER) & + (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); + + /* Clear registers. */ + sinp(UART_LSR); + sinp(UART_RX); + sinp(UART_IIR); + sinp(UART_MSR); + +#ifdef CONFIG_LIRC_SERIAL_NSLU2 + if (type == LIRC_NSLU2) { + /* Setup NSLU2 UART */ + + /* Enable UART */ + soutp(UART_IER, sinp(UART_IER) | UART_IE_IXP42X_UUE); + /* Disable Receiver data Time out interrupt */ + soutp(UART_IER, sinp(UART_IER) & ~UART_IE_IXP42X_RTOIE); + /* set out2 = interrupt unmask; off() doesn't set MCR + on NSLU2 */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); + } +#endif + + /* Set line for power source */ + off(); + + /* Clear registers again to be sure. */ + sinp(UART_LSR); + sinp(UART_RX); + sinp(UART_IIR); + sinp(UART_MSR); + + switch (type) { + case LIRC_IRDEO: + case LIRC_IRDEO_REMOTE: + /* setup port to 7N1 @ 115200 Baud */ + /* 7N1+start = 9 bits at 115200 ~ 3 bits at 38kHz */ + + /* Set DLAB 1. */ + soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); + /* Set divisor to 1 => 115200 Baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 1); + /* Set DLAB 0 + 7N1 */ + soutp(UART_LCR, UART_LCR_WLEN7); + /* THR interrupt already disabled at this point */ + break; + default: + break; + } + + return 0; +} + +static int init_port(void) +{ + int i, nlow, nhigh; + + /* Reserve io region. */ + /* + * Future MMAP-Developers: Attention! + * For memory mapped I/O you *might* need to use ioremap() first, + * for the NSLU2 it's done in boot code. + */ + if (((iommap != 0) + && (request_mem_region(iommap, 8 << ioshift, + LIRC_DRIVER_NAME) == NULL)) + || ((iommap == 0) + && (request_region(io, 8, LIRC_DRIVER_NAME) == NULL))) { + printk(KERN_ERR LIRC_DRIVER_NAME + ": port %04x already in use\n", io); + printk(KERN_WARNING LIRC_DRIVER_NAME + ": use 'setserial /dev/ttySX uart none'\n"); + printk(KERN_WARNING LIRC_DRIVER_NAME + ": or compile the serial port driver as module and\n"); + printk(KERN_WARNING LIRC_DRIVER_NAME + ": make sure this module is loaded first\n"); + return -EBUSY; + } + + if (hardware_init_port() < 0) + return -EINVAL; + + /* Initialize pulse/space widths */ + init_timing_params(duty_cycle, freq); + + /* If pin is high, then this must be an active low receiver. */ + if (sense == -1) { + /* wait 1/2 sec for the power supply */ + msleep(500); + + /* + * probe 9 times every 0.04s, collect "votes" for + * active high/low + */ + nlow = 0; + nhigh = 0; + for (i = 0; i < 9; i++) { + if (sinp(UART_MSR) & hardware[type].signal_pin) + nlow++; + else + nhigh++; + msleep(40); + } + sense = (nlow >= nhigh ? 1 : 0); + printk(KERN_INFO LIRC_DRIVER_NAME ": auto-detected active " + "%s receiver\n", sense ? "low" : "high"); + } else + printk(KERN_INFO LIRC_DRIVER_NAME ": Manually using active " + "%s receiver\n", sense ? "low" : "high"); + + return 0; +} + +static int set_use_inc(void *data) +{ + int result; + unsigned long flags; + + /* initialize timestamp */ + do_gettimeofday(&lasttv); + + result = request_irq(irq, irq_handler, + IRQF_DISABLED | (share_irq ? IRQF_SHARED : 0), + LIRC_DRIVER_NAME, (void *)&hardware); + + switch (result) { + case -EBUSY: + printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq); + return -EBUSY; + case -EINVAL: + printk(KERN_ERR LIRC_DRIVER_NAME + ": Bad irq number or handler\n"); + return -EINVAL; + default: + dprintk("Interrupt %d, port %04x obtained\n", irq, io); + break; + }; + + spin_lock_irqsave(&hardware[type].lock, flags); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI); + + spin_unlock_irqrestore(&hardware[type].lock, flags); + + return 0; +} + +static void set_use_dec(void *data) +{ unsigned long flags; + + spin_lock_irqsave(&hardware[type].lock, flags); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* First of all, disable all interrupts */ + soutp(UART_IER, sinp(UART_IER) & + (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); + spin_unlock_irqrestore(&hardware[type].lock, flags); + + free_irq(irq, (void *)&hardware); + + dprintk("freed IRQ %d\n", irq); +} + +static ssize_t lirc_write(struct file *file, const char *buf, + size_t n, loff_t *ppos) +{ + int i, count; + unsigned long flags; + long delta = 0; + int *wbuf; + + if (!(hardware[type].features & LIRC_CAN_SEND_PULSE)) + return -EBADF; + + count = n / sizeof(int); + if (n % sizeof(int) || count % 2 == 0) + return -EINVAL; + wbuf = memdup_user(buf, n); + if (PTR_ERR(wbuf)) + return PTR_ERR(wbuf); + spin_lock_irqsave(&hardware[type].lock, flags); + if (type == LIRC_IRDEO) { + /* DTR, RTS down */ + on(); + } + for (i = 0; i < count; i++) { + if (i%2) + hardware[type].send_space(wbuf[i] - delta); + else + delta = hardware[type].send_pulse(wbuf[i]); + } + off(); + spin_unlock_irqrestore(&hardware[type].lock, flags); + return n; +} + +static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +{ + int result; + unsigned long value; + unsigned int ivalue; + + switch (cmd) { + case LIRC_GET_SEND_MODE: + if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) + return -ENOIOCTLCMD; + + result = put_user(LIRC_SEND2MODE + (hardware[type].features&LIRC_CAN_SEND_MASK), + (unsigned long *) arg); + if (result) + return result; + break; + + case LIRC_SET_SEND_MODE: + if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) + return -ENOIOCTLCMD; + + result = get_user(value, (unsigned long *) arg); + if (result) + return result; + /* only LIRC_MODE_PULSE supported */ + if (value != LIRC_MODE_PULSE) + return -ENOSYS; + break; + + case LIRC_GET_LENGTH: + return -ENOSYS; + break; + + case LIRC_SET_SEND_DUTY_CYCLE: + dprintk("SET_SEND_DUTY_CYCLE\n"); + if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE)) + return -ENOIOCTLCMD; + + result = get_user(ivalue, (unsigned int *) arg); + if (result) + return result; + if (ivalue <= 0 || ivalue > 100) + return -EINVAL; + return init_timing_params(ivalue, freq); + break; + + case LIRC_SET_SEND_CARRIER: + dprintk("SET_SEND_CARRIER\n"); + if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER)) + return -ENOIOCTLCMD; + + result = get_user(ivalue, (unsigned int *) arg); + if (result) + return result; + if (ivalue > 500000 || ivalue < 20000) + return -EINVAL; + return init_timing_params(duty_cycle, ivalue); + break; + + default: + return lirc_dev_fop_ioctl(filep, cmd, arg); + } + return 0; +} + +static const struct file_operations lirc_fops = { + .owner = THIS_MODULE, + .write = lirc_write, + .unlocked_ioctl = lirc_ioctl, + .read = lirc_dev_fop_read, + .poll = lirc_dev_fop_poll, + .open = lirc_dev_fop_open, + .release = lirc_dev_fop_close, +}; + +static struct lirc_driver driver = { + .name = LIRC_DRIVER_NAME, + .minor = -1, + .code_length = 1, + .sample_rate = 0, + .data = NULL, + .add_to_buf = NULL, + .rbuf = &rbuf, + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .fops = &lirc_fops, + .dev = NULL, + .owner = THIS_MODULE, +}; + +static struct platform_device *lirc_serial_dev; + +static int __devinit lirc_serial_probe(struct platform_device *dev) +{ + return 0; +} + +static int __devexit lirc_serial_remove(struct platform_device *dev) +{ + return 0; +} + +static int lirc_serial_suspend(struct platform_device *dev, + pm_message_t state) +{ + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* Disable all interrupts */ + soutp(UART_IER, sinp(UART_IER) & + (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); + + /* Clear registers. */ + sinp(UART_LSR); + sinp(UART_RX); + sinp(UART_IIR); + sinp(UART_MSR); + + return 0; +} + +/* twisty maze... need a forward-declaration here... */ +static void lirc_serial_exit(void); + +static int lirc_serial_resume(struct platform_device *dev) +{ + unsigned long flags; + + if (hardware_init_port() < 0) { + lirc_serial_exit(); + return -EINVAL; + } + + spin_lock_irqsave(&hardware[type].lock, flags); + /* Enable Interrupt */ + do_gettimeofday(&lasttv); + soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI); + off(); + + lirc_buffer_clear(&rbuf); + + spin_unlock_irqrestore(&hardware[type].lock, flags); + + return 0; +} + +static struct platform_driver lirc_serial_driver = { + .probe = lirc_serial_probe, + .remove = __devexit_p(lirc_serial_remove), + .suspend = lirc_serial_suspend, + .resume = lirc_serial_resume, + .driver = { + .name = "lirc_serial", + .owner = THIS_MODULE, + }, +}; + +static int __init lirc_serial_init(void) +{ + int result; + + /* Init read buffer. */ + result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN); + if (result < 0) + return -ENOMEM; + + result = platform_driver_register(&lirc_serial_driver); + if (result) { + printk("lirc register returned %d\n", result); + goto exit_buffer_free; + } + + lirc_serial_dev = platform_device_alloc("lirc_serial", 0); + if (!lirc_serial_dev) { + result = -ENOMEM; + goto exit_driver_unregister; + } + + result = platform_device_add(lirc_serial_dev); + if (result) + goto exit_device_put; + + return 0; + +exit_device_put: + platform_device_put(lirc_serial_dev); +exit_driver_unregister: + platform_driver_unregister(&lirc_serial_driver); +exit_buffer_free: + lirc_buffer_free(&rbuf); + return result; +} + +static void lirc_serial_exit(void) +{ + platform_device_unregister(lirc_serial_dev); + platform_driver_unregister(&lirc_serial_driver); + lirc_buffer_free(&rbuf); +} + +static int __init lirc_serial_init_module(void) +{ + int result; + + result = lirc_serial_init(); + if (result) + return result; + + switch (type) { + case LIRC_HOMEBREW: + case LIRC_IRDEO: + case LIRC_IRDEO_REMOTE: + case LIRC_ANIMAX: + case LIRC_IGOR: + /* if nothing specified, use ttyS0/com1 and irq 4 */ + io = io ? io : 0x3f8; + irq = irq ? irq : 4; + break; +#ifdef CONFIG_LIRC_SERIAL_NSLU2 + case LIRC_NSLU2: + io = io ? io : IRQ_IXP4XX_UART2; + irq = irq ? irq : (IXP4XX_UART2_BASE_VIRT + REG_OFFSET); + iommap = iommap ? iommap : IXP4XX_UART2_BASE_PHYS; + ioshift = ioshift ? ioshift : 2; + break; +#endif + default: + result = -EINVAL; + goto exit_serial_exit; + } + if (!softcarrier) { + switch (type) { + case LIRC_HOMEBREW: + case LIRC_IGOR: +#ifdef CONFIG_LIRC_SERIAL_NSLU2 + case LIRC_NSLU2: +#endif + hardware[type].features &= + ~(LIRC_CAN_SET_SEND_DUTY_CYCLE| + LIRC_CAN_SET_SEND_CARRIER); + break; + } + } + + result = init_port(); + if (result < 0) + goto exit_serial_exit; + driver.features = hardware[type].features; + driver.dev = &lirc_serial_dev->dev; + driver.minor = lirc_register_driver(&driver); + if (driver.minor < 0) { + printk(KERN_ERR LIRC_DRIVER_NAME + ": register_chrdev failed!\n"); + result = -EIO; + goto exit_release; + } + return 0; +exit_release: + release_region(io, 8); +exit_serial_exit: + lirc_serial_exit(); + return result; +} + +static void __exit lirc_serial_exit_module(void) +{ + lirc_serial_exit(); + if (iommap != 0) + release_mem_region(iommap, 8 << ioshift); + else + release_region(io, 8); + lirc_unregister_driver(driver.minor); + dprintk("cleaned up module\n"); +} + + +module_init(lirc_serial_init_module); +module_exit(lirc_serial_exit_module); + +MODULE_DESCRIPTION("Infra-red receiver driver for serial ports."); +MODULE_AUTHOR("Ralph Metzler, Trent Piepho, Ben Pfaff, " + "Christoph Bartelmus, Andrei Tanas"); +MODULE_LICENSE("GPL"); + +module_param(type, int, S_IRUGO); +MODULE_PARM_DESC(type, "Hardware type (0 = home-brew, 1 = IRdeo," + " 2 = IRdeo Remote, 3 = AnimaX, 4 = IgorPlug," + " 5 = NSLU2 RX:CTS2/TX:GreenLED)"); + +module_param(io, int, S_IRUGO); +MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)"); + +/* some architectures (e.g. intel xscale) have memory mapped registers */ +module_param(iommap, bool, S_IRUGO); +MODULE_PARM_DESC(iommap, "physical base for memory mapped I/O" + " (0 = no memory mapped io)"); + +/* + * some architectures (e.g. intel xscale) align the 8bit serial registers + * on 32bit word boundaries. + * See linux-kernel/serial/8250.c serial_in()/out() + */ +module_param(ioshift, int, S_IRUGO); +MODULE_PARM_DESC(ioshift, "shift I/O register offset (0 = no shift)"); + +module_param(irq, int, S_IRUGO); +MODULE_PARM_DESC(irq, "Interrupt (4 or 3)"); + +module_param(share_irq, bool, S_IRUGO); +MODULE_PARM_DESC(share_irq, "Share interrupts (0 = off, 1 = on)"); + +module_param(sense, bool, S_IRUGO); +MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit" + " (0 = active high, 1 = active low )"); + +#ifdef CONFIG_LIRC_SERIAL_TRANSMITTER +module_param(txsense, bool, S_IRUGO); +MODULE_PARM_DESC(txsense, "Sense of transmitter circuit" + " (0 = active high, 1 = active low )"); +#endif + +module_param(softcarrier, bool, S_IRUGO); +MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on, default on)"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); diff --git a/drivers/staging/lirc/lirc_sir.c b/drivers/staging/lirc/lirc_sir.c new file mode 100644 index 000000000000..eb08fa7138ba --- /dev/null +++ b/drivers/staging/lirc/lirc_sir.c @@ -0,0 +1,1282 @@ +/* + * LIRC SIR driver, (C) 2000 Milan Pikula <www@fornax.sk> + * + * lirc_sir - Device driver for use with SIR (serial infra red) + * mode of IrDA on many notebooks. + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * 2000/09/16 Frank Przybylski <mail@frankprzybylski.de> : + * added timeout and relaxed pulse detection, removed gap bug + * + * 2000/12/15 Christoph Bartelmus <lirc@bartelmus.de> : + * added support for Tekram Irmate 210 (sending does not work yet, + * kind of disappointing that nobody was able to implement that + * before), + * major clean-up + * + * 2001/02/27 Christoph Bartelmus <lirc@bartelmus.de> : + * added support for StrongARM SA1100 embedded microprocessor + * parts cut'n'pasted from sa1100_ir.c (C) 2000 Russell King + */ + +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/signal.h> +#include <linux/fs.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/kernel.h> +#include <linux/serial_reg.h> +#include <linux/time.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/wait.h> +#include <linux/mm.h> +#include <linux/delay.h> +#include <linux/poll.h> +#include <asm/system.h> +#include <linux/io.h> +#include <asm/irq.h> +#include <linux/fcntl.h> +#ifdef LIRC_ON_SA1100 +#include <asm/hardware.h> +#ifdef CONFIG_SA1100_COLLIE +#include <asm/arch/tc35143.h> +#include <asm/ucb1200.h> +#endif +#endif + +#include <linux/timer.h> + +#include <media/lirc.h> +#include <media/lirc_dev.h> + +/* SECTION: Definitions */ + +/*** Tekram dongle ***/ +#ifdef LIRC_SIR_TEKRAM +/* stolen from kernel source */ +/* definitions for Tekram dongle */ +#define TEKRAM_115200 0x00 +#define TEKRAM_57600 0x01 +#define TEKRAM_38400 0x02 +#define TEKRAM_19200 0x03 +#define TEKRAM_9600 0x04 +#define TEKRAM_2400 0x08 + +#define TEKRAM_PW 0x10 /* Pulse select bit */ + +/* 10bit * 1s/115200bit in milliseconds = 87ms*/ +#define TIME_CONST (10000000ul/115200ul) + +#endif + +#ifdef LIRC_SIR_ACTISYS_ACT200L +static void init_act200(void); +#elif defined(LIRC_SIR_ACTISYS_ACT220L) +static void init_act220(void); +#endif + +/*** SA1100 ***/ +#ifdef LIRC_ON_SA1100 +struct sa1100_ser2_registers { + /* HSSP control register */ + unsigned char hscr0; + /* UART registers */ + unsigned char utcr0; + unsigned char utcr1; + unsigned char utcr2; + unsigned char utcr3; + unsigned char utcr4; + unsigned char utdr; + unsigned char utsr0; + unsigned char utsr1; +} sr; + +static int irq = IRQ_Ser2ICP; + +#define LIRC_ON_SA1100_TRANSMITTER_LATENCY 0 + +/* pulse/space ratio of 50/50 */ +static unsigned long pulse_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY); +/* 1000000/freq-pulse_width */ +static unsigned long space_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY); +static unsigned int freq = 38000; /* modulation frequency */ +static unsigned int duty_cycle = 50; /* duty cycle of 50% */ + +#endif + +#define RBUF_LEN 1024 +#define WBUF_LEN 1024 + +#define LIRC_DRIVER_NAME "lirc_sir" + +#define PULSE '[' + +#ifndef LIRC_SIR_TEKRAM +/* 9bit * 1s/115200bit in milli seconds = 78.125ms*/ +#define TIME_CONST (9000000ul/115200ul) +#endif + + +/* timeout for sequences in jiffies (=5/100s), must be longer than TIME_CONST */ +#define SIR_TIMEOUT (HZ*5/100) + +#ifndef LIRC_ON_SA1100 +#ifndef LIRC_IRQ +#define LIRC_IRQ 4 +#endif +#ifndef LIRC_PORT +/* for external dongles, default to com1 */ +#if defined(LIRC_SIR_ACTISYS_ACT200L) || \ + defined(LIRC_SIR_ACTISYS_ACT220L) || \ + defined(LIRC_SIR_TEKRAM) +#define LIRC_PORT 0x3f8 +#else +/* onboard sir ports are typically com3 */ +#define LIRC_PORT 0x3e8 +#endif +#endif + +static int io = LIRC_PORT; +static int irq = LIRC_IRQ; +static int threshold = 3; +#endif + +static DEFINE_SPINLOCK(timer_lock); +static struct timer_list timerlist; +/* time of last signal change detected */ +static struct timeval last_tv = {0, 0}; +/* time of last UART data ready interrupt */ +static struct timeval last_intr_tv = {0, 0}; +static int last_value; + +static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue); + +static DEFINE_SPINLOCK(hardware_lock); + +static int rx_buf[RBUF_LEN]; +static unsigned int rx_tail, rx_head; + +static int debug; +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ + fmt, ## args); \ + } while (0) + +/* SECTION: Prototypes */ + +/* Communication with user-space */ +static unsigned int lirc_poll(struct file *file, poll_table *wait); +static ssize_t lirc_read(struct file *file, char *buf, size_t count, + loff_t *ppos); +static ssize_t lirc_write(struct file *file, const char *buf, size_t n, + loff_t *pos); +static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); +static void add_read_queue(int flag, unsigned long val); +static int init_chrdev(void); +static void drop_chrdev(void); +/* Hardware */ +static irqreturn_t sir_interrupt(int irq, void *dev_id); +static void send_space(unsigned long len); +static void send_pulse(unsigned long len); +static int init_hardware(void); +static void drop_hardware(void); +/* Initialisation */ +static int init_port(void); +static void drop_port(void); + +#ifdef LIRC_ON_SA1100 +static void on(void) +{ + PPSR |= PPC_TXD2; +} + +static void off(void) +{ + PPSR &= ~PPC_TXD2; +} +#else +static inline unsigned int sinp(int offset) +{ + return inb(io + offset); +} + +static inline void soutp(int offset, int value) +{ + outb(value, io + offset); +} +#endif + +#ifndef MAX_UDELAY_MS +#define MAX_UDELAY_US 5000 +#else +#define MAX_UDELAY_US (MAX_UDELAY_MS*1000) +#endif + +static void safe_udelay(unsigned long usecs) +{ + while (usecs > MAX_UDELAY_US) { + udelay(MAX_UDELAY_US); + usecs -= MAX_UDELAY_US; + } + udelay(usecs); +} + +/* SECTION: Communication with user-space */ + +static unsigned int lirc_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &lirc_read_queue, wait); + if (rx_head != rx_tail) + return POLLIN | POLLRDNORM; + return 0; +} + +static ssize_t lirc_read(struct file *file, char *buf, size_t count, + loff_t *ppos) +{ + int n = 0; + int retval = 0; + DECLARE_WAITQUEUE(wait, current); + + if (count % sizeof(int)) + return -EINVAL; + + add_wait_queue(&lirc_read_queue, &wait); + set_current_state(TASK_INTERRUPTIBLE); + while (n < count) { + if (rx_head != rx_tail) { + if (copy_to_user((void *) buf + n, + (void *) (rx_buf + rx_head), + sizeof(int))) { + retval = -EFAULT; + break; + } + rx_head = (rx_head + 1) & (RBUF_LEN - 1); + n += sizeof(int); + } else { + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + break; + } + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } + } + remove_wait_queue(&lirc_read_queue, &wait); + set_current_state(TASK_RUNNING); + return n ? n : retval; +} +static ssize_t lirc_write(struct file *file, const char *buf, size_t n, + loff_t *pos) +{ + unsigned long flags; + int i, count; + int *tx_buf; + + count = n / sizeof(int); + if (n % sizeof(int) || count % 2 == 0) + return -EINVAL; + tx_buf = memdup_user(buf, n); + if (IS_ERR(tx_buf)) + return PTR_ERR(tx_buf); + i = 0; +#ifdef LIRC_ON_SA1100 + /* disable receiver */ + Ser2UTCR3 = 0; +#endif + local_irq_save(flags); + while (1) { + if (i >= count) + break; + if (tx_buf[i]) + send_pulse(tx_buf[i]); + i++; + if (i >= count) + break; + if (tx_buf[i]) + send_space(tx_buf[i]); + i++; + } + local_irq_restore(flags); +#ifdef LIRC_ON_SA1100 + off(); + udelay(1000); /* wait 1ms for IR diode to recover */ + Ser2UTCR3 = 0; + /* clear status register to prevent unwanted interrupts */ + Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); + /* enable receiver */ + Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE; +#endif + return count; +} + +static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +{ + int retval = 0; + unsigned long value = 0; +#ifdef LIRC_ON_SA1100 + unsigned int ivalue; + + if (cmd == LIRC_GET_FEATURES) + value = LIRC_CAN_SEND_PULSE | + LIRC_CAN_SET_SEND_DUTY_CYCLE | + LIRC_CAN_SET_SEND_CARRIER | + LIRC_CAN_REC_MODE2; + else if (cmd == LIRC_GET_SEND_MODE) + value = LIRC_MODE_PULSE; + else if (cmd == LIRC_GET_REC_MODE) + value = LIRC_MODE_MODE2; +#else + if (cmd == LIRC_GET_FEATURES) + value = LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2; + else if (cmd == LIRC_GET_SEND_MODE) + value = LIRC_MODE_PULSE; + else if (cmd == LIRC_GET_REC_MODE) + value = LIRC_MODE_MODE2; +#endif + + switch (cmd) { + case LIRC_GET_FEATURES: + case LIRC_GET_SEND_MODE: + case LIRC_GET_REC_MODE: + retval = put_user(value, (unsigned long *) arg); + break; + + case LIRC_SET_SEND_MODE: + case LIRC_SET_REC_MODE: + retval = get_user(value, (unsigned long *) arg); + break; +#ifdef LIRC_ON_SA1100 + case LIRC_SET_SEND_DUTY_CYCLE: + retval = get_user(ivalue, (unsigned int *) arg); + if (retval) + return retval; + if (ivalue <= 0 || ivalue > 100) + return -EINVAL; + /* (ivalue/100)*(1000000/freq) */ + duty_cycle = ivalue; + pulse_width = (unsigned long) duty_cycle*10000/freq; + space_width = (unsigned long) 1000000L/freq-pulse_width; + if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) + pulse_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; + if (space_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) + space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; + break; + case LIRC_SET_SEND_CARRIER: + retval = get_user(ivalue, (unsigned int *) arg); + if (retval) + return retval; + if (ivalue > 500000 || ivalue < 20000) + return -EINVAL; + freq = ivalue; + pulse_width = (unsigned long) duty_cycle*10000/freq; + space_width = (unsigned long) 1000000L/freq-pulse_width; + if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) + pulse_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; + if (space_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) + space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; + break; +#endif + default: + retval = -ENOIOCTLCMD; + + } + + if (retval) + return retval; + if (cmd == LIRC_SET_REC_MODE) { + if (value != LIRC_MODE_MODE2) + retval = -ENOSYS; + } else if (cmd == LIRC_SET_SEND_MODE) { + if (value != LIRC_MODE_PULSE) + retval = -ENOSYS; + } + + return retval; +} + +static void add_read_queue(int flag, unsigned long val) +{ + unsigned int new_rx_tail; + int newval; + + dprintk("add flag %d with val %lu\n", flag, val); + + newval = val & PULSE_MASK; + + /* + * statistically, pulses are ~TIME_CONST/2 too long. we could + * maybe make this more exact, but this is good enough + */ + if (flag) { + /* pulse */ + if (newval > TIME_CONST/2) + newval -= TIME_CONST/2; + else /* should not ever happen */ + newval = 1; + newval |= PULSE_BIT; + } else { + newval += TIME_CONST/2; + } + new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1); + if (new_rx_tail == rx_head) { + dprintk("Buffer overrun.\n"); + return; + } + rx_buf[rx_tail] = newval; + rx_tail = new_rx_tail; + wake_up_interruptible(&lirc_read_queue); +} + +static const struct file_operations lirc_fops = { + .owner = THIS_MODULE, + .read = lirc_read, + .write = lirc_write, + .poll = lirc_poll, + .unlocked_ioctl = lirc_ioctl, + .open = lirc_dev_fop_open, + .release = lirc_dev_fop_close, +}; + +static int set_use_inc(void *data) +{ + return 0; +} + +static void set_use_dec(void *data) +{ +} + +static struct lirc_driver driver = { + .name = LIRC_DRIVER_NAME, + .minor = -1, + .code_length = 1, + .sample_rate = 0, + .data = NULL, + .add_to_buf = NULL, + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .fops = &lirc_fops, + .dev = NULL, + .owner = THIS_MODULE, +}; + + +static int init_chrdev(void) +{ + driver.minor = lirc_register_driver(&driver); + if (driver.minor < 0) { + printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); + return -EIO; + } + return 0; +} + +static void drop_chrdev(void) +{ + lirc_unregister_driver(driver.minor); +} + +/* SECTION: Hardware */ +static long delta(struct timeval *tv1, struct timeval *tv2) +{ + unsigned long deltv; + + deltv = tv2->tv_sec - tv1->tv_sec; + if (deltv > 15) + deltv = 0xFFFFFF; + else + deltv = deltv*1000000 + + tv2->tv_usec - + tv1->tv_usec; + return deltv; +} + +static void sir_timeout(unsigned long data) +{ + /* + * if last received signal was a pulse, but receiving stopped + * within the 9 bit frame, we need to finish this pulse and + * simulate a signal change to from pulse to space. Otherwise + * upper layers will receive two sequences next time. + */ + + unsigned long flags; + unsigned long pulse_end; + + /* avoid interference with interrupt */ + spin_lock_irqsave(&timer_lock, flags); + if (last_value) { +#ifndef LIRC_ON_SA1100 + /* clear unread bits in UART and restart */ + outb(UART_FCR_CLEAR_RCVR, io + UART_FCR); +#endif + /* determine 'virtual' pulse end: */ + pulse_end = delta(&last_tv, &last_intr_tv); + dprintk("timeout add %d for %lu usec\n", last_value, pulse_end); + add_read_queue(last_value, pulse_end); + last_value = 0; + last_tv = last_intr_tv; + } + spin_unlock_irqrestore(&timer_lock, flags); +} + +static irqreturn_t sir_interrupt(int irq, void *dev_id) +{ + unsigned char data; + struct timeval curr_tv; + static unsigned long deltv; +#ifdef LIRC_ON_SA1100 + int status; + static int n; + + status = Ser2UTSR0; + /* + * Deal with any receive errors first. The bytes in error may be + * the only bytes in the receive FIFO, so we do this first. + */ + while (status & UTSR0_EIF) { + int bstat; + + if (debug) { + dprintk("EIF\n"); + bstat = Ser2UTSR1; + + if (bstat & UTSR1_FRE) + dprintk("frame error\n"); + if (bstat & UTSR1_ROR) + dprintk("receive fifo overrun\n"); + if (bstat & UTSR1_PRE) + dprintk("parity error\n"); + } + + bstat = Ser2UTDR; + n++; + status = Ser2UTSR0; + } + + if (status & (UTSR0_RFS | UTSR0_RID)) { + do_gettimeofday(&curr_tv); + deltv = delta(&last_tv, &curr_tv); + do { + data = Ser2UTDR; + dprintk("%d data: %u\n", n, (unsigned int) data); + n++; + } while (status & UTSR0_RID && /* do not empty fifo in order to + * get UTSR0_RID in any case */ + Ser2UTSR1 & UTSR1_RNE); /* data ready */ + + if (status&UTSR0_RID) { + add_read_queue(0 , deltv - n * TIME_CONST); /*space*/ + add_read_queue(1, n * TIME_CONST); /*pulse*/ + n = 0; + last_tv = curr_tv; + } + } + + if (status & UTSR0_TFS) + printk(KERN_ERR "transmit fifo not full, shouldn't happen\n"); + + /* We must clear certain bits. */ + status &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); + if (status) + Ser2UTSR0 = status; +#else + unsigned long deltintrtv; + unsigned long flags; + int iir, lsr; + + while ((iir = inb(io + UART_IIR) & UART_IIR_ID)) { + switch (iir&UART_IIR_ID) { /* FIXME toto treba preriedit */ + case UART_IIR_MSI: + (void) inb(io + UART_MSR); + break; + case UART_IIR_RLSI: + (void) inb(io + UART_LSR); + break; + case UART_IIR_THRI: +#if 0 + if (lsr & UART_LSR_THRE) /* FIFO is empty */ + outb(data, io + UART_TX) +#endif + break; + case UART_IIR_RDI: + /* avoid interference with timer */ + spin_lock_irqsave(&timer_lock, flags); + do { + del_timer(&timerlist); + data = inb(io + UART_RX); + do_gettimeofday(&curr_tv); + deltv = delta(&last_tv, &curr_tv); + deltintrtv = delta(&last_intr_tv, &curr_tv); + dprintk("t %lu, d %d\n", deltintrtv, (int)data); + /* + * if nothing came in last X cycles, + * it was gap + */ + if (deltintrtv > TIME_CONST * threshold) { + if (last_value) { + dprintk("GAP\n"); + /* simulate signal change */ + add_read_queue(last_value, + deltv - + deltintrtv); + last_value = 0; + last_tv.tv_sec = + last_intr_tv.tv_sec; + last_tv.tv_usec = + last_intr_tv.tv_usec; + deltv = deltintrtv; + } + } + data = 1; + if (data ^ last_value) { + /* + * deltintrtv > 2*TIME_CONST, remember? + * the other case is timeout + */ + add_read_queue(last_value, + deltv-TIME_CONST); + last_value = data; + last_tv = curr_tv; + if (last_tv.tv_usec >= TIME_CONST) { + last_tv.tv_usec -= TIME_CONST; + } else { + last_tv.tv_sec--; + last_tv.tv_usec += 1000000 - + TIME_CONST; + } + } + last_intr_tv = curr_tv; + if (data) { + /* + * start timer for end of + * sequence detection + */ + timerlist.expires = jiffies + + SIR_TIMEOUT; + add_timer(&timerlist); + } + + lsr = inb(io + UART_LSR); + } while (lsr & UART_LSR_DR); /* data ready */ + spin_unlock_irqrestore(&timer_lock, flags); + break; + default: + break; + } + } +#endif + return IRQ_RETVAL(IRQ_HANDLED); +} + +#ifdef LIRC_ON_SA1100 +static void send_pulse(unsigned long length) +{ + unsigned long k, delay; + int flag; + + if (length == 0) + return; + /* + * this won't give us the carrier frequency we really want + * due to integer arithmetic, but we can accept this inaccuracy + */ + + for (k = flag = 0; k < length; k += delay, flag = !flag) { + if (flag) { + off(); + delay = space_width; + } else { + on(); + delay = pulse_width; + } + safe_udelay(delay); + } + off(); +} + +static void send_space(unsigned long length) +{ + if (length == 0) + return; + off(); + safe_udelay(length); +} +#else +static void send_space(unsigned long len) +{ + safe_udelay(len); +} + +static void send_pulse(unsigned long len) +{ + long bytes_out = len / TIME_CONST; + long time_left; + + time_left = (long)len - (long)bytes_out * (long)TIME_CONST; + if (bytes_out == 0) { + bytes_out++; + time_left = 0; + } + while (bytes_out--) { + outb(PULSE, io + UART_TX); + /* FIXME treba seriozne cakanie z char/serial.c */ + while (!(inb(io + UART_LSR) & UART_LSR_THRE)) + ; + } +#if 0 + if (time_left > 0) + safe_udelay(time_left); +#endif +} +#endif + +#ifdef CONFIG_SA1100_COLLIE +static int sa1100_irda_set_power_collie(int state) +{ + if (state) { + /* + * 0 - off + * 1 - short range, lowest power + * 2 - medium range, medium power + * 3 - maximum range, high power + */ + ucb1200_set_io_direction(TC35143_GPIO_IR_ON, + TC35143_IODIR_OUTPUT); + ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_LOW); + udelay(100); + } else { + /* OFF */ + ucb1200_set_io_direction(TC35143_GPIO_IR_ON, + TC35143_IODIR_OUTPUT); + ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_HIGH); + } + return 0; +} +#endif + +static int init_hardware(void) +{ + unsigned long flags; + + spin_lock_irqsave(&hardware_lock, flags); + /* reset UART */ +#ifdef LIRC_ON_SA1100 +#ifdef CONFIG_SA1100_BITSY + if (machine_is_bitsy()) { + printk(KERN_INFO "Power on IR module\n"); + set_bitsy_egpio(EGPIO_BITSY_IR_ON); + } +#endif +#ifdef CONFIG_SA1100_COLLIE + sa1100_irda_set_power_collie(3); /* power on */ +#endif + sr.hscr0 = Ser2HSCR0; + + sr.utcr0 = Ser2UTCR0; + sr.utcr1 = Ser2UTCR1; + sr.utcr2 = Ser2UTCR2; + sr.utcr3 = Ser2UTCR3; + sr.utcr4 = Ser2UTCR4; + + sr.utdr = Ser2UTDR; + sr.utsr0 = Ser2UTSR0; + sr.utsr1 = Ser2UTSR1; + + /* configure GPIO */ + /* output */ + PPDR |= PPC_TXD2; + PSDR |= PPC_TXD2; + /* set output to 0 */ + off(); + + /* Enable HP-SIR modulation, and ensure that the port is disabled. */ + Ser2UTCR3 = 0; + Ser2HSCR0 = sr.hscr0 & (~HSCR0_HSSP); + + /* clear status register to prevent unwanted interrupts */ + Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); + + /* 7N1 */ + Ser2UTCR0 = UTCR0_1StpBit|UTCR0_7BitData; + /* 115200 */ + Ser2UTCR1 = 0; + Ser2UTCR2 = 1; + /* use HPSIR, 1.6 usec pulses */ + Ser2UTCR4 = UTCR4_HPSIR|UTCR4_Z1_6us; + + /* enable receiver, receive fifo interrupt */ + Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE; + + /* clear status register to prevent unwanted interrupts */ + Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); + +#elif defined(LIRC_SIR_TEKRAM) + /* disable FIFO */ + soutp(UART_FCR, + UART_FCR_CLEAR_RCVR| + UART_FCR_CLEAR_XMIT| + UART_FCR_TRIGGER_1); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* First of all, disable all interrupts */ + soutp(UART_IER, sinp(UART_IER) & + (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); + + /* Set DLAB 1. */ + soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); + + /* Set divisor to 12 => 9600 Baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 12); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* power supply */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + safe_udelay(50*1000); + + /* -DTR low -> reset PIC */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); + udelay(1*1000); + + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + udelay(100); + + + /* -RTS low -> send control byte */ + soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); + udelay(7); + soutp(UART_TX, TEKRAM_115200|TEKRAM_PW); + + /* one byte takes ~1042 usec to transmit at 9600,8N1 */ + udelay(1500); + + /* back to normal operation */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + udelay(50); + + udelay(1500); + + /* read previous control byte */ + printk(KERN_INFO LIRC_DRIVER_NAME + ": 0x%02x\n", sinp(UART_RX)); + + /* Set DLAB 1. */ + soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); + + /* Set divisor to 1 => 115200 Baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 1); + + /* Set DLAB 0, 8 Bit */ + soutp(UART_LCR, UART_LCR_WLEN8); + /* enable interrupts */ + soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI); +#else + outb(0, io + UART_MCR); + outb(0, io + UART_IER); + /* init UART */ + /* set DLAB, speed = 115200 */ + outb(UART_LCR_DLAB | UART_LCR_WLEN7, io + UART_LCR); + outb(1, io + UART_DLL); outb(0, io + UART_DLM); + /* 7N1+start = 9 bits at 115200 ~ 3 bits at 44000 */ + outb(UART_LCR_WLEN7, io + UART_LCR); + /* FIFO operation */ + outb(UART_FCR_ENABLE_FIFO, io + UART_FCR); + /* interrupts */ + /* outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, io + UART_IER); */ + outb(UART_IER_RDI, io + UART_IER); + /* turn on UART */ + outb(UART_MCR_DTR|UART_MCR_RTS|UART_MCR_OUT2, io + UART_MCR); +#ifdef LIRC_SIR_ACTISYS_ACT200L + init_act200(); +#elif defined(LIRC_SIR_ACTISYS_ACT220L) + init_act220(); +#endif +#endif + spin_unlock_irqrestore(&hardware_lock, flags); + return 0; +} + +static void drop_hardware(void) +{ + unsigned long flags; + + spin_lock_irqsave(&hardware_lock, flags); + +#ifdef LIRC_ON_SA1100 + Ser2UTCR3 = 0; + + Ser2UTCR0 = sr.utcr0; + Ser2UTCR1 = sr.utcr1; + Ser2UTCR2 = sr.utcr2; + Ser2UTCR4 = sr.utcr4; + Ser2UTCR3 = sr.utcr3; + + Ser2HSCR0 = sr.hscr0; +#ifdef CONFIG_SA1100_BITSY + if (machine_is_bitsy()) + clr_bitsy_egpio(EGPIO_BITSY_IR_ON); +#endif +#ifdef CONFIG_SA1100_COLLIE + sa1100_irda_set_power_collie(0); /* power off */ +#endif +#else + /* turn off interrupts */ + outb(0, io + UART_IER); +#endif + spin_unlock_irqrestore(&hardware_lock, flags); +} + +/* SECTION: Initialisation */ + +static int init_port(void) +{ + int retval; + + /* get I/O port access and IRQ line */ +#ifndef LIRC_ON_SA1100 + if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) { + printk(KERN_ERR LIRC_DRIVER_NAME + ": i/o port 0x%.4x already in use.\n", io); + return -EBUSY; + } +#endif + retval = request_irq(irq, sir_interrupt, IRQF_DISABLED, + LIRC_DRIVER_NAME, NULL); + if (retval < 0) { +# ifndef LIRC_ON_SA1100 + release_region(io, 8); +# endif + printk(KERN_ERR LIRC_DRIVER_NAME + ": IRQ %d already in use.\n", + irq); + return retval; + } +#ifndef LIRC_ON_SA1100 + printk(KERN_INFO LIRC_DRIVER_NAME + ": I/O port 0x%.4x, IRQ %d.\n", + io, irq); +#endif + + init_timer(&timerlist); + timerlist.function = sir_timeout; + timerlist.data = 0xabadcafe; + + return 0; +} + +static void drop_port(void) +{ + free_irq(irq, NULL); + del_timer_sync(&timerlist); +#ifndef LIRC_ON_SA1100 + release_region(io, 8); +#endif +} + +#ifdef LIRC_SIR_ACTISYS_ACT200L +/* Crystal/Cirrus CS8130 IR transceiver, used in Actisys Act200L dongle */ +/* some code borrowed from Linux IRDA driver */ + +/* Register 0: Control register #1 */ +#define ACT200L_REG0 0x00 +#define ACT200L_TXEN 0x01 /* Enable transmitter */ +#define ACT200L_RXEN 0x02 /* Enable receiver */ +#define ACT200L_ECHO 0x08 /* Echo control chars */ + +/* Register 1: Control register #2 */ +#define ACT200L_REG1 0x10 +#define ACT200L_LODB 0x01 /* Load new baud rate count value */ +#define ACT200L_WIDE 0x04 /* Expand the maximum allowable pulse */ + +/* Register 3: Transmit mode register #2 */ +#define ACT200L_REG3 0x30 +#define ACT200L_B0 0x01 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P) */ +#define ACT200L_B1 0x02 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P) */ +#define ACT200L_CHSY 0x04 /* StartBit Synced 0=bittime, 1=startbit */ + +/* Register 4: Output Power register */ +#define ACT200L_REG4 0x40 +#define ACT200L_OP0 0x01 /* Enable LED1C output */ +#define ACT200L_OP1 0x02 /* Enable LED2C output */ +#define ACT200L_BLKR 0x04 + +/* Register 5: Receive Mode register */ +#define ACT200L_REG5 0x50 +#define ACT200L_RWIDL 0x01 /* fixed 1.6us pulse mode */ + /*.. other various IRDA bit modes, and TV remote modes..*/ + +/* Register 6: Receive Sensitivity register #1 */ +#define ACT200L_REG6 0x60 +#define ACT200L_RS0 0x01 /* receive threshold bit 0 */ +#define ACT200L_RS1 0x02 /* receive threshold bit 1 */ + +/* Register 7: Receive Sensitivity register #2 */ +#define ACT200L_REG7 0x70 +#define ACT200L_ENPOS 0x04 /* Ignore the falling edge */ + +/* Register 8,9: Baud Rate Divider register #1,#2 */ +#define ACT200L_REG8 0x80 +#define ACT200L_REG9 0x90 + +#define ACT200L_2400 0x5f +#define ACT200L_9600 0x17 +#define ACT200L_19200 0x0b +#define ACT200L_38400 0x05 +#define ACT200L_57600 0x03 +#define ACT200L_115200 0x01 + +/* Register 13: Control register #3 */ +#define ACT200L_REG13 0xd0 +#define ACT200L_SHDW 0x01 /* Enable access to shadow registers */ + +/* Register 15: Status register */ +#define ACT200L_REG15 0xf0 + +/* Register 21: Control register #4 */ +#define ACT200L_REG21 0x50 +#define ACT200L_EXCK 0x02 /* Disable clock output driver */ +#define ACT200L_OSCL 0x04 /* oscillator in low power, medium accuracy mode */ + +static void init_act200(void) +{ + int i; + __u8 control[] = { + ACT200L_REG15, + ACT200L_REG13 | ACT200L_SHDW, + ACT200L_REG21 | ACT200L_EXCK | ACT200L_OSCL, + ACT200L_REG13, + ACT200L_REG7 | ACT200L_ENPOS, + ACT200L_REG6 | ACT200L_RS0 | ACT200L_RS1, + ACT200L_REG5 | ACT200L_RWIDL, + ACT200L_REG4 | ACT200L_OP0 | ACT200L_OP1 | ACT200L_BLKR, + ACT200L_REG3 | ACT200L_B0, + ACT200L_REG0 | ACT200L_TXEN | ACT200L_RXEN, + ACT200L_REG8 | (ACT200L_115200 & 0x0f), + ACT200L_REG9 | ((ACT200L_115200 >> 4) & 0x0f), + ACT200L_REG1 | ACT200L_LODB | ACT200L_WIDE + }; + + /* Set DLAB 1. */ + soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8); + + /* Set divisor to 12 => 9600 Baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 12); + + /* Set DLAB 0. */ + soutp(UART_LCR, UART_LCR_WLEN8); + /* Set divisor to 12 => 9600 Baud */ + + /* power supply */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + for (i = 0; i < 50; i++) + safe_udelay(1000); + + /* Reset the dongle : set RTS low for 25 ms */ + soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); + for (i = 0; i < 25; i++) + udelay(1000); + + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + udelay(100); + + /* Clear DTR and set RTS to enter command mode */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); + udelay(7); + + /* send out the control register settings for 115K 7N1 SIR operation */ + for (i = 0; i < sizeof(control); i++) { + soutp(UART_TX, control[i]); + /* one byte takes ~1042 usec to transmit at 9600,8N1 */ + udelay(1500); + } + + /* back to normal operation */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + udelay(50); + + udelay(1500); + soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); + + /* Set DLAB 1. */ + soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN7); + + /* Set divisor to 1 => 115200 Baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 1); + + /* Set DLAB 0. */ + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); + + /* Set DLAB 0, 7 Bit */ + soutp(UART_LCR, UART_LCR_WLEN7); + + /* enable interrupts */ + soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI); +} +#endif + +#ifdef LIRC_SIR_ACTISYS_ACT220L +/* + * Derived from linux IrDA driver (net/irda/actisys.c) + * Drop me a mail for any kind of comment: maxx@spaceboyz.net + */ + +void init_act220(void) +{ + int i; + + /* DLAB 1 */ + soutp(UART_LCR, UART_LCR_DLAB|UART_LCR_WLEN7); + + /* 9600 baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 12); + + /* DLAB 0 */ + soutp(UART_LCR, UART_LCR_WLEN7); + + /* reset the dongle, set DTR low for 10us */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); + udelay(10); + + /* back to normal (still 9600) */ + soutp(UART_MCR, UART_MCR_DTR|UART_MCR_RTS|UART_MCR_OUT2); + + /* + * send RTS pulses until we reach 115200 + * i hope this is really the same for act220l/act220l+ + */ + for (i = 0; i < 3; i++) { + udelay(10); + /* set RTS low for 10 us */ + soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); + udelay(10); + /* set RTS high for 10 us */ + soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); + } + + /* back to normal operation */ + udelay(1500); /* better safe than sorry ;) */ + + /* Set DLAB 1. */ + soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN7); + + /* Set divisor to 1 => 115200 Baud */ + soutp(UART_DLM, 0); + soutp(UART_DLL, 1); + + /* Set DLAB 0, 7 Bit */ + /* The dongle doesn't seem to have any problems with operation at 7N1 */ + soutp(UART_LCR, UART_LCR_WLEN7); + + /* enable interrupts */ + soutp(UART_IER, UART_IER_RDI); +} +#endif + +static int init_lirc_sir(void) +{ + int retval; + + init_waitqueue_head(&lirc_read_queue); + retval = init_port(); + if (retval < 0) + return retval; + init_hardware(); + printk(KERN_INFO LIRC_DRIVER_NAME + ": Installed.\n"); + return 0; +} + + +static int __init lirc_sir_init(void) +{ + int retval; + + retval = init_chrdev(); + if (retval < 0) + return retval; + retval = init_lirc_sir(); + if (retval) { + drop_chrdev(); + return retval; + } + return 0; +} + +static void __exit lirc_sir_exit(void) +{ + drop_hardware(); + drop_chrdev(); + drop_port(); + printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); +} + +module_init(lirc_sir_init); +module_exit(lirc_sir_exit); + +#ifdef LIRC_SIR_TEKRAM +MODULE_DESCRIPTION("Infrared receiver driver for Tekram Irmate 210"); +MODULE_AUTHOR("Christoph Bartelmus"); +#elif defined(LIRC_ON_SA1100) +MODULE_DESCRIPTION("LIRC driver for StrongARM SA1100 embedded microprocessor"); +MODULE_AUTHOR("Christoph Bartelmus"); +#elif defined(LIRC_SIR_ACTISYS_ACT200L) +MODULE_DESCRIPTION("LIRC driver for Actisys Act200L"); +MODULE_AUTHOR("Karl Bongers"); +#elif defined(LIRC_SIR_ACTISYS_ACT220L) +MODULE_DESCRIPTION("LIRC driver for Actisys Act220L(+)"); +MODULE_AUTHOR("Jan Roemisch"); +#else +MODULE_DESCRIPTION("Infrared receiver driver for SIR type serial ports"); +MODULE_AUTHOR("Milan Pikula"); +#endif +MODULE_LICENSE("GPL"); + +#ifdef LIRC_ON_SA1100 +module_param(irq, int, S_IRUGO); +MODULE_PARM_DESC(irq, "Interrupt (16)"); +#else +module_param(io, int, S_IRUGO); +MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)"); + +module_param(irq, int, S_IRUGO); +MODULE_PARM_DESC(irq, "Interrupt (4 or 3)"); + +module_param(threshold, int, S_IRUGO); +MODULE_PARM_DESC(threshold, "space detection threshold (3)"); +#endif + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); diff --git a/drivers/staging/lirc/lirc_streamzap.c b/drivers/staging/lirc/lirc_streamzap.c new file mode 100644 index 000000000000..be09c103f0c9 --- /dev/null +++ b/drivers/staging/lirc/lirc_streamzap.c @@ -0,0 +1,821 @@ +/* + * Streamzap Remote Control driver + * + * Copyright (c) 2005 Christoph Bartelmus <lirc@bartelmus.de> + * + * This driver was based on the work of Greg Wickham and Adrian + * Dewhurst. It was substantially rewritten to support correct signal + * gaps and now maintains a delay buffer, which is used to present + * consistent timing behaviour to user space applications. Without the + * delay buffer an ugly hack would be required in lircd, which can + * cause sluggish signal decoding in certain situations. + * + * This driver is based on the USB skeleton driver packaged with the + * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com) + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/smp_lock.h> +#include <linux/completion.h> +#include <linux/uaccess.h> +#include <linux/usb.h> + +#include <media/lirc.h> +#include <media/lirc_dev.h> + +#define DRIVER_VERSION "1.28" +#define DRIVER_NAME "lirc_streamzap" +#define DRIVER_DESC "Streamzap Remote Control driver" + +static int debug; + +#define USB_STREAMZAP_VENDOR_ID 0x0e9c +#define USB_STREAMZAP_PRODUCT_ID 0x0000 + +/* Use our own dbg macro */ +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG DRIVER_NAME "[%d]: " \ + fmt "\n", ## args); \ + } while (0) + +/* table of devices that work with this driver */ +static struct usb_device_id streamzap_table[] = { + /* Streamzap Remote Control */ + { USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) }, + /* Terminating entry */ + { } +}; + +MODULE_DEVICE_TABLE(usb, streamzap_table); + +#define STREAMZAP_PULSE_MASK 0xf0 +#define STREAMZAP_SPACE_MASK 0x0f +#define STREAMZAP_TIMEOUT 0xff +#define STREAMZAP_RESOLUTION 256 + +/* number of samples buffered */ +#define STREAMZAP_BUF_LEN 128 + +enum StreamzapDecoderState { + PulseSpace, + FullPulse, + FullSpace, + IgnorePulse +}; + +/* Structure to hold all of our device specific stuff + * + * some remarks regarding locking: + * theoretically this struct can be accessed from three threads: + * + * - from lirc_dev through set_use_inc/set_use_dec + * + * - from the USB layer throuh probe/disconnect/irq + * + * Careful placement of lirc_register_driver/lirc_unregister_driver + * calls will prevent conflicts. lirc_dev makes sure that + * set_use_inc/set_use_dec are not being executed and will not be + * called after lirc_unregister_driver returns. + * + * - by the timer callback + * + * The timer is only running when the device is connected and the + * LIRC device is open. Making sure the timer is deleted by + * set_use_dec will make conflicts impossible. + */ +struct usb_streamzap { + + /* usb */ + /* save off the usb device pointer */ + struct usb_device *udev; + /* the interface for this device */ + struct usb_interface *interface; + + /* buffer & dma */ + unsigned char *buf_in; + dma_addr_t dma_in; + unsigned int buf_in_len; + + struct usb_endpoint_descriptor *endpoint; + + /* IRQ */ + struct urb *urb_in; + + /* lirc */ + struct lirc_driver *driver; + struct lirc_buffer *delay_buf; + + /* timer used to support delay buffering */ + struct timer_list delay_timer; + int timer_running; + spinlock_t timer_lock; + + /* tracks whether we are currently receiving some signal */ + int idle; + /* sum of signal lengths received since signal start */ + unsigned long sum; + /* start time of signal; necessary for gap tracking */ + struct timeval signal_last; + struct timeval signal_start; + enum StreamzapDecoderState decoder_state; + struct timer_list flush_timer; + int flush; + int in_use; + int timeout_enabled; +}; + + +/* local function prototypes */ +static int streamzap_probe(struct usb_interface *interface, + const struct usb_device_id *id); +static void streamzap_disconnect(struct usb_interface *interface); +static void usb_streamzap_irq(struct urb *urb); +static int streamzap_use_inc(void *data); +static void streamzap_use_dec(void *data); +static long streamzap_ioctl(struct file *filep, unsigned int cmd, + unsigned long arg); +static int streamzap_suspend(struct usb_interface *intf, pm_message_t message); +static int streamzap_resume(struct usb_interface *intf); + +/* usb specific object needed to register this driver with the usb subsystem */ + +static struct usb_driver streamzap_driver = { + .name = DRIVER_NAME, + .probe = streamzap_probe, + .disconnect = streamzap_disconnect, + .suspend = streamzap_suspend, + .resume = streamzap_resume, + .id_table = streamzap_table, +}; + +static void stop_timer(struct usb_streamzap *sz) +{ + unsigned long flags; + + spin_lock_irqsave(&sz->timer_lock, flags); + if (sz->timer_running) { + sz->timer_running = 0; + spin_unlock_irqrestore(&sz->timer_lock, flags); + del_timer_sync(&sz->delay_timer); + } else { + spin_unlock_irqrestore(&sz->timer_lock, flags); + } +} + +static void flush_timeout(unsigned long arg) +{ + struct usb_streamzap *sz = (struct usb_streamzap *) arg; + + /* finally start accepting data */ + sz->flush = 0; +} +static void delay_timeout(unsigned long arg) +{ + unsigned long flags; + /* deliver data every 10 ms */ + static unsigned long timer_inc = + (10000/(1000000/HZ)) == 0 ? 1 : (10000/(1000000/HZ)); + struct usb_streamzap *sz = (struct usb_streamzap *) arg; + int data; + + spin_lock_irqsave(&sz->timer_lock, flags); + + if (!lirc_buffer_empty(sz->delay_buf) && + !lirc_buffer_full(sz->driver->rbuf)) { + lirc_buffer_read(sz->delay_buf, (unsigned char *) &data); + lirc_buffer_write(sz->driver->rbuf, (unsigned char *) &data); + } + if (!lirc_buffer_empty(sz->delay_buf)) { + while (lirc_buffer_available(sz->delay_buf) < + STREAMZAP_BUF_LEN / 2 && + !lirc_buffer_full(sz->driver->rbuf)) { + lirc_buffer_read(sz->delay_buf, + (unsigned char *) &data); + lirc_buffer_write(sz->driver->rbuf, + (unsigned char *) &data); + } + if (sz->timer_running) { + sz->delay_timer.expires = jiffies + timer_inc; + add_timer(&sz->delay_timer); + } + } else { + sz->timer_running = 0; + } + + if (!lirc_buffer_empty(sz->driver->rbuf)) + wake_up(&sz->driver->rbuf->wait_poll); + + spin_unlock_irqrestore(&sz->timer_lock, flags); +} + +static void flush_delay_buffer(struct usb_streamzap *sz) +{ + int data; + int empty = 1; + + while (!lirc_buffer_empty(sz->delay_buf)) { + empty = 0; + lirc_buffer_read(sz->delay_buf, (unsigned char *) &data); + if (!lirc_buffer_full(sz->driver->rbuf)) { + lirc_buffer_write(sz->driver->rbuf, + (unsigned char *) &data); + } else { + dprintk("buffer overflow", sz->driver->minor); + } + } + if (!empty) + wake_up(&sz->driver->rbuf->wait_poll); +} + +static void push(struct usb_streamzap *sz, unsigned char *data) +{ + unsigned long flags; + + spin_lock_irqsave(&sz->timer_lock, flags); + if (lirc_buffer_full(sz->delay_buf)) { + int read_data; + + lirc_buffer_read(sz->delay_buf, + (unsigned char *) &read_data); + if (!lirc_buffer_full(sz->driver->rbuf)) { + lirc_buffer_write(sz->driver->rbuf, + (unsigned char *) &read_data); + } else { + dprintk("buffer overflow", sz->driver->minor); + } + } + + lirc_buffer_write(sz->delay_buf, data); + + if (!sz->timer_running) { + sz->delay_timer.expires = jiffies + HZ/10; + add_timer(&sz->delay_timer); + sz->timer_running = 1; + } + + spin_unlock_irqrestore(&sz->timer_lock, flags); +} + +static void push_full_pulse(struct usb_streamzap *sz, + unsigned char value) +{ + int pulse; + + if (sz->idle) { + long deltv; + int tmp; + + sz->signal_last = sz->signal_start; + do_gettimeofday(&sz->signal_start); + + deltv = sz->signal_start.tv_sec-sz->signal_last.tv_sec; + if (deltv > 15) { + /* really long time */ + tmp = LIRC_SPACE(LIRC_VALUE_MASK); + } else { + tmp = (int) (deltv*1000000+ + sz->signal_start.tv_usec - + sz->signal_last.tv_usec); + tmp -= sz->sum; + tmp = LIRC_SPACE(tmp); + } + dprintk("ls %u", sz->driver->minor, tmp); + push(sz, (char *)&tmp); + + sz->idle = 0; + sz->sum = 0; + } + + pulse = ((int) value) * STREAMZAP_RESOLUTION; + pulse += STREAMZAP_RESOLUTION / 2; + sz->sum += pulse; + pulse = LIRC_PULSE(pulse); + + dprintk("p %u", sz->driver->minor, pulse & PULSE_MASK); + push(sz, (char *)&pulse); +} + +static void push_half_pulse(struct usb_streamzap *sz, + unsigned char value) +{ + push_full_pulse(sz, (value & STREAMZAP_PULSE_MASK)>>4); +} + +static void push_full_space(struct usb_streamzap *sz, + unsigned char value) +{ + int space; + + space = ((int) value)*STREAMZAP_RESOLUTION; + space += STREAMZAP_RESOLUTION/2; + sz->sum += space; + space = LIRC_SPACE(space); + dprintk("s %u", sz->driver->minor, space); + push(sz, (char *)&space); +} + +static void push_half_space(struct usb_streamzap *sz, + unsigned char value) +{ + push_full_space(sz, value & STREAMZAP_SPACE_MASK); +} + +/** + * usb_streamzap_irq - IRQ handler + * + * This procedure is invoked on reception of data from + * the usb remote. + */ +static void usb_streamzap_irq(struct urb *urb) +{ + struct usb_streamzap *sz; + int len; + unsigned int i = 0; + + if (!urb) + return; + + sz = urb->context; + len = urb->actual_length; + + switch (urb->status) { + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* + * this urb is terminated, clean up. + * sz might already be invalid at this point + */ + dprintk("urb status: %d", -1, urb->status); + return; + default: + break; + } + + dprintk("received %d", sz->driver->minor, urb->actual_length); + if (!sz->flush) { + for (i = 0; i < urb->actual_length; i++) { + dprintk("%d: %x", sz->driver->minor, + i, (unsigned char) sz->buf_in[i]); + switch (sz->decoder_state) { + case PulseSpace: + if ((sz->buf_in[i]&STREAMZAP_PULSE_MASK) == + STREAMZAP_PULSE_MASK) { + sz->decoder_state = FullPulse; + continue; + } else if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) + == STREAMZAP_SPACE_MASK) { + push_half_pulse(sz, sz->buf_in[i]); + sz->decoder_state = FullSpace; + continue; + } else { + push_half_pulse(sz, sz->buf_in[i]); + push_half_space(sz, sz->buf_in[i]); + } + break; + case FullPulse: + push_full_pulse(sz, sz->buf_in[i]); + sz->decoder_state = IgnorePulse; + break; + case FullSpace: + if (sz->buf_in[i] == STREAMZAP_TIMEOUT) { + sz->idle = 1; + stop_timer(sz); + if (sz->timeout_enabled) { + int timeout = + LIRC_TIMEOUT + (STREAMZAP_TIMEOUT * + STREAMZAP_RESOLUTION); + push(sz, (char *)&timeout); + } + flush_delay_buffer(sz); + } else + push_full_space(sz, sz->buf_in[i]); + sz->decoder_state = PulseSpace; + break; + case IgnorePulse: + if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) == + STREAMZAP_SPACE_MASK) { + sz->decoder_state = FullSpace; + continue; + } + push_half_space(sz, sz->buf_in[i]); + sz->decoder_state = PulseSpace; + break; + } + } + } + + usb_submit_urb(urb, GFP_ATOMIC); + + return; +} + +static const struct file_operations streamzap_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = streamzap_ioctl, + .read = lirc_dev_fop_read, + .write = lirc_dev_fop_write, + .poll = lirc_dev_fop_poll, + .open = lirc_dev_fop_open, + .release = lirc_dev_fop_close, +}; + + +/** + * streamzap_probe + * + * Called by usb-core to associated with a candidate device + * On any failure the return value is the ERROR + * On success return 0 + */ +static int streamzap_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(interface); + struct usb_host_interface *iface_host; + struct usb_streamzap *sz; + struct lirc_driver *driver; + struct lirc_buffer *lirc_buf; + struct lirc_buffer *delay_buf; + char buf[63], name[128] = ""; + int retval = -ENOMEM; + int minor = 0; + + /* Allocate space for device driver specific data */ + sz = kzalloc(sizeof(struct usb_streamzap), GFP_KERNEL); + if (sz == NULL) + return -ENOMEM; + + sz->udev = udev; + sz->interface = interface; + + /* Check to ensure endpoint information matches requirements */ + iface_host = interface->cur_altsetting; + + if (iface_host->desc.bNumEndpoints != 1) { + err("%s: Unexpected desc.bNumEndpoints (%d)", __func__, + iface_host->desc.bNumEndpoints); + retval = -ENODEV; + goto free_sz; + } + + sz->endpoint = &(iface_host->endpoint[0].desc); + if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + != USB_DIR_IN) { + err("%s: endpoint doesn't match input device 02%02x", + __func__, sz->endpoint->bEndpointAddress); + retval = -ENODEV; + goto free_sz; + } + + if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + != USB_ENDPOINT_XFER_INT) { + err("%s: endpoint attributes don't match xfer 02%02x", + __func__, sz->endpoint->bmAttributes); + retval = -ENODEV; + goto free_sz; + } + + if (sz->endpoint->wMaxPacketSize == 0) { + err("%s: endpoint message size==0? ", __func__); + retval = -ENODEV; + goto free_sz; + } + + /* Allocate the USB buffer and IRQ URB */ + + sz->buf_in_len = sz->endpoint->wMaxPacketSize; + sz->buf_in = usb_alloc_coherent(sz->udev, sz->buf_in_len, + GFP_ATOMIC, &sz->dma_in); + if (sz->buf_in == NULL) + goto free_sz; + + sz->urb_in = usb_alloc_urb(0, GFP_KERNEL); + if (sz->urb_in == NULL) + goto free_sz; + + /* Connect this device to the LIRC sub-system */ + driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); + if (!driver) + goto free_sz; + + lirc_buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!lirc_buf) + goto free_driver; + if (lirc_buffer_init(lirc_buf, sizeof(int), STREAMZAP_BUF_LEN)) + goto kfree_lirc_buf; + + delay_buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!delay_buf) + goto free_lirc_buf; + if (lirc_buffer_init(delay_buf, sizeof(int), STREAMZAP_BUF_LEN)) + goto kfree_delay_buf; + + sz->driver = driver; + strcpy(sz->driver->name, DRIVER_NAME); + sz->driver->minor = -1; + sz->driver->sample_rate = 0; + sz->driver->code_length = sizeof(int) * 8; + sz->driver->features = LIRC_CAN_REC_MODE2 | + LIRC_CAN_GET_REC_RESOLUTION | + LIRC_CAN_SET_REC_TIMEOUT; + sz->driver->data = sz; + sz->driver->min_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION; + sz->driver->max_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION; + sz->driver->rbuf = lirc_buf; + sz->delay_buf = delay_buf; + sz->driver->set_use_inc = &streamzap_use_inc; + sz->driver->set_use_dec = &streamzap_use_dec; + sz->driver->fops = &streamzap_fops; + sz->driver->dev = &interface->dev; + sz->driver->owner = THIS_MODULE; + + sz->idle = 1; + sz->decoder_state = PulseSpace; + init_timer(&sz->delay_timer); + sz->delay_timer.function = delay_timeout; + sz->delay_timer.data = (unsigned long) sz; + sz->timer_running = 0; + spin_lock_init(&sz->timer_lock); + + init_timer(&sz->flush_timer); + sz->flush_timer.function = flush_timeout; + sz->flush_timer.data = (unsigned long) sz; + /* Complete final initialisations */ + + usb_fill_int_urb(sz->urb_in, udev, + usb_rcvintpipe(udev, sz->endpoint->bEndpointAddress), + sz->buf_in, sz->buf_in_len, usb_streamzap_irq, sz, + sz->endpoint->bInterval); + sz->urb_in->transfer_dma = sz->dma_in; + sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + if (udev->descriptor.iManufacturer + && usb_string(udev, udev->descriptor.iManufacturer, + buf, sizeof(buf)) > 0) + strlcpy(name, buf, sizeof(name)); + + if (udev->descriptor.iProduct + && usb_string(udev, udev->descriptor.iProduct, + buf, sizeof(buf)) > 0) + snprintf(name + strlen(name), sizeof(name) - strlen(name), + " %s", buf); + + minor = lirc_register_driver(driver); + + if (minor < 0) + goto free_delay_buf; + + sz->driver->minor = minor; + + usb_set_intfdata(interface, sz); + + printk(KERN_INFO DRIVER_NAME "[%d]: %s on usb%d:%d attached\n", + sz->driver->minor, name, + udev->bus->busnum, sz->udev->devnum); + + return 0; + +free_delay_buf: + lirc_buffer_free(sz->delay_buf); +kfree_delay_buf: + kfree(delay_buf); +free_lirc_buf: + lirc_buffer_free(sz->driver->rbuf); +kfree_lirc_buf: + kfree(lirc_buf); +free_driver: + kfree(driver); +free_sz: + if (retval == -ENOMEM) + err("Out of memory"); + + if (sz) { + usb_free_urb(sz->urb_in); + usb_free_coherent(udev, sz->buf_in_len, sz->buf_in, sz->dma_in); + kfree(sz); + } + + return retval; +} + +static int streamzap_use_inc(void *data) +{ + struct usb_streamzap *sz = data; + + if (!sz) { + dprintk("%s called with no context", -1, __func__); + return -EINVAL; + } + dprintk("set use inc", sz->driver->minor); + + lirc_buffer_clear(sz->driver->rbuf); + lirc_buffer_clear(sz->delay_buf); + + sz->flush_timer.expires = jiffies + HZ; + sz->flush = 1; + add_timer(&sz->flush_timer); + + sz->urb_in->dev = sz->udev; + if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { + dprintk("open result = -EIO error submitting urb", + sz->driver->minor); + return -EIO; + } + sz->in_use++; + + return 0; +} + +static void streamzap_use_dec(void *data) +{ + struct usb_streamzap *sz = data; + + if (!sz) { + dprintk("%s called with no context", -1, __func__); + return; + } + dprintk("set use dec", sz->driver->minor); + + if (sz->flush) { + sz->flush = 0; + del_timer_sync(&sz->flush_timer); + } + + usb_kill_urb(sz->urb_in); + + stop_timer(sz); + + sz->in_use--; +} + +static long streamzap_ioctl(struct file *filep, unsigned int cmd, + unsigned long arg) +{ + int result = 0; + int val; + struct usb_streamzap *sz = lirc_get_pdata(filep); + + switch (cmd) { + case LIRC_GET_REC_RESOLUTION: + result = put_user(STREAMZAP_RESOLUTION, (unsigned int *) arg); + break; + case LIRC_SET_REC_TIMEOUT: + result = get_user(val, (int *)arg); + if (result == 0) { + if (val == STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION) + sz->timeout_enabled = 1; + else if (val == 0) + sz->timeout_enabled = 0; + else + result = -EINVAL; + } + break; + default: + return lirc_dev_fop_ioctl(filep, cmd, arg); + } + return result; +} + +/** + * streamzap_disconnect + * + * Called by the usb core when the device is removed from the system. + * + * This routine guarantees that the driver will not submit any more urbs + * by clearing dev->udev. It is also supposed to terminate any currently + * active urbs. Unfortunately, usb_bulk_msg(), used in streamzap_read(), + * does not provide any way to do this. + */ +static void streamzap_disconnect(struct usb_interface *interface) +{ + struct usb_streamzap *sz; + int errnum; + int minor; + + sz = usb_get_intfdata(interface); + + /* unregister from the LIRC sub-system */ + + errnum = lirc_unregister_driver(sz->driver->minor); + if (errnum != 0) + dprintk("error in lirc_unregister: (returned %d)", + sz->driver->minor, errnum); + + lirc_buffer_free(sz->delay_buf); + lirc_buffer_free(sz->driver->rbuf); + + /* unregister from the USB sub-system */ + + usb_free_urb(sz->urb_in); + + usb_free_coherent(sz->udev, sz->buf_in_len, sz->buf_in, sz->dma_in); + + minor = sz->driver->minor; + kfree(sz->driver->rbuf); + kfree(sz->driver); + kfree(sz->delay_buf); + kfree(sz); + + printk(KERN_INFO DRIVER_NAME "[%d]: disconnected\n", minor); +} + +static int streamzap_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct usb_streamzap *sz = usb_get_intfdata(intf); + + printk(KERN_INFO DRIVER_NAME "[%d]: suspend\n", sz->driver->minor); + if (sz->in_use) { + if (sz->flush) { + sz->flush = 0; + del_timer_sync(&sz->flush_timer); + } + + stop_timer(sz); + + usb_kill_urb(sz->urb_in); + } + return 0; +} + +static int streamzap_resume(struct usb_interface *intf) +{ + struct usb_streamzap *sz = usb_get_intfdata(intf); + + lirc_buffer_clear(sz->driver->rbuf); + lirc_buffer_clear(sz->delay_buf); + + if (sz->in_use) { + sz->flush_timer.expires = jiffies + HZ; + sz->flush = 1; + add_timer(&sz->flush_timer); + + sz->urb_in->dev = sz->udev; + if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { + dprintk("open result = -EIO error submitting urb", + sz->driver->minor); + return -EIO; + } + } + return 0; +} + +/** + * usb_streamzap_init + */ +static int __init usb_streamzap_init(void) +{ + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&streamzap_driver); + + if (result) { + err("usb_register failed. Error number %d", + result); + return result; + } + + printk(KERN_INFO DRIVER_NAME " " DRIVER_VERSION " registered\n"); + return 0; +} + +/** + * usb_streamzap_exit + */ +static void __exit usb_streamzap_exit(void) +{ + usb_deregister(&streamzap_driver); +} + + +module_init(usb_streamzap_init); +module_exit(usb_streamzap_exit); + +MODULE_AUTHOR("Christoph Bartelmus, Greg Wickham, Adrian Dewhurst"); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable debugging messages"); diff --git a/drivers/staging/lirc/lirc_ttusbir.c b/drivers/staging/lirc/lirc_ttusbir.c new file mode 100644 index 000000000000..e345ab9a004c --- /dev/null +++ b/drivers/staging/lirc/lirc_ttusbir.c @@ -0,0 +1,396 @@ +/* + * lirc_ttusbir.c + * + * lirc_ttusbir - LIRC device driver for the TechnoTrend USB IR Receiver + * + * Copyright (C) 2007 Stefan Macher <st_maker-lirc@yahoo.de> + * + * This LIRC driver provides access to the TechnoTrend USB IR Receiver. + * The receiver delivers the IR signal as raw sampled true/false data in + * isochronous USB packets each of size 128 byte. + * Currently the driver reduces the sampling rate by factor of 8 as this + * is still more than enough to decode RC-5 - others should be analyzed. + * But the driver does not rely on RC-5 it should be able to decode every + * IR signal that is not too fast. + */ + +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/version.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/usb.h> + +#include <media/lirc.h> +#include <media/lirc_dev.h> + +MODULE_DESCRIPTION("TechnoTrend USB IR device driver for LIRC"); +MODULE_AUTHOR("Stefan Macher (st_maker-lirc@yahoo.de)"); +MODULE_LICENSE("GPL"); + +/* #define DEBUG */ +#ifdef DEBUG +#define DPRINTK printk +#else +#define DPRINTK(_x_, a...) +#endif + +/* function declarations */ +static int probe(struct usb_interface *intf, const struct usb_device_id *id); +static void disconnect(struct usb_interface *intf); +static void urb_complete(struct urb *urb); +static int set_use_inc(void *data); +static void set_use_dec(void *data); + +static int num_urbs = 2; +module_param(num_urbs, int, S_IRUGO); +MODULE_PARM_DESC(num_urbs, + "Number of URBs in queue. Try to increase to 4 in case " + "of problems (default: 2; minimum: 2)"); + +/* table of devices that work with this driver */ +static struct usb_device_id device_id_table[] = { + /* TechnoTrend USB IR Receiver */ + { USB_DEVICE(0x0B48, 0x2003) }, + /* Terminating entry */ + { } +}; +MODULE_DEVICE_TABLE(usb, device_id_table); + +/* USB driver definition */ +static struct usb_driver usb_driver = { + .name = "TTUSBIR", + .id_table = &(device_id_table[0]), + .probe = probe, + .disconnect = disconnect, +}; + +/* USB device definition */ +struct ttusbir_device { + struct usb_driver *usb_driver; + struct usb_device *udev; + struct usb_interface *interf; + struct usb_class_driver class_driver; + unsigned int ifnum; /* Interface number to use */ + unsigned int alt_setting; /* alternate setting to use */ + unsigned int endpoint; /* Endpoint to use */ + struct urb **urb; /* num_urb URB pointers*/ + char **buffer; /* 128 byte buffer for each URB */ + struct lirc_buffer rbuf; /* Buffer towards LIRC */ + struct lirc_driver driver; + int minor; + int last_pulse; /* remembers if last received byte was pulse or space */ + int last_num; /* remembers how many last bytes appeared */ + int opened; +}; + +/*** LIRC specific functions ***/ +static int set_use_inc(void *data) +{ + int i, retval; + struct ttusbir_device *ttusbir = data; + + DPRINTK("Sending first URBs\n"); + /* @TODO Do I need to check if I am already opened */ + ttusbir->opened = 1; + + for (i = 0; i < num_urbs; i++) { + retval = usb_submit_urb(ttusbir->urb[i], GFP_KERNEL); + if (retval) { + err("%s: usb_submit_urb failed on urb %d", + __func__, i); + return retval; + } + } + return 0; +} + +static void set_use_dec(void *data) +{ + struct ttusbir_device *ttusbir = data; + + DPRINTK("Device closed\n"); + + ttusbir->opened = 0; +} + +/*** USB specific functions ***/ + +/* + * This mapping table is used to do a very simple filtering of the + * input signal. + * For a value with at least 4 bits set it returns 0xFF otherwise + * 0x00. For faster IR signals this can not be used. But for RC-5 we + * still have about 14 samples per pulse/space, i.e. we sample with 14 + * times higher frequency than the signal frequency + */ +const unsigned char map_table[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static void urb_complete(struct urb *urb) +{ + struct ttusbir_device *ttusbir; + unsigned char *buf; + int i; + int l; + + ttusbir = urb->context; + + if (!ttusbir->opened) + return; + + buf = (unsigned char *)urb->transfer_buffer; + + for (i = 0; i < 128; i++) { + /* Here we do the filtering and some kind of down sampling */ + buf[i] = ~map_table[buf[i]]; + if (ttusbir->last_pulse == buf[i]) { + if (ttusbir->last_num < PULSE_MASK/63) + ttusbir->last_num++; + /* + * else we are in a idle period and do not need to + * increment any longer + */ + } else { + l = ttusbir->last_num * 62; /* about 62 = us/byte */ + if (ttusbir->last_pulse) /* pulse or space? */ + l |= PULSE_BIT; + if (!lirc_buffer_full(&ttusbir->rbuf)) { + lirc_buffer_write(&ttusbir->rbuf, (void *)&l); + wake_up_interruptible(&ttusbir->rbuf.wait_poll); + } + ttusbir->last_num = 0; + ttusbir->last_pulse = buf[i]; + } + } + usb_submit_urb(urb, GFP_ATOMIC); /* keep data rolling :-) */ +} + +/* + * Called whenever the USB subsystem thinks we could be the right driver + * to handle this device + */ +static int probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + int alt_set, endp; + int found = 0; + int i, j; + int struct_size; + struct usb_host_interface *host_interf; + struct usb_interface_descriptor *interf_desc; + struct usb_host_endpoint *host_endpoint; + struct ttusbir_device *ttusbir; + + DPRINTK("Module ttusbir probe\n"); + + /* To reduce memory fragmentation we use only one allocation */ + struct_size = sizeof(struct ttusbir_device) + + (sizeof(struct urb *) * num_urbs) + + (sizeof(char *) * num_urbs) + + (num_urbs * 128); + ttusbir = kzalloc(struct_size, GFP_KERNEL); + if (!ttusbir) + return -ENOMEM; + + ttusbir->urb = (struct urb **)((char *)ttusbir + + sizeof(struct ttusbir_device)); + ttusbir->buffer = (char **)((char *)ttusbir->urb + + (sizeof(struct urb *) * num_urbs)); + for (i = 0; i < num_urbs; i++) + ttusbir->buffer[i] = (char *)ttusbir->buffer + + (sizeof(char *)*num_urbs) + (i * 128); + + ttusbir->usb_driver = &usb_driver; + ttusbir->alt_setting = -1; + /* @TODO check if error can be returned */ + ttusbir->udev = usb_get_dev(interface_to_usbdev(intf)); + ttusbir->interf = intf; + ttusbir->last_pulse = 0x00; + ttusbir->last_num = 0; + + /* + * Now look for interface setting we can handle + * We are searching for the alt setting where end point + * 0x82 has max packet size 16 + */ + for (alt_set = 0; alt_set < intf->num_altsetting && !found; alt_set++) { + host_interf = &intf->altsetting[alt_set]; + interf_desc = &host_interf->desc; + for (endp = 0; endp < interf_desc->bNumEndpoints; endp++) { + host_endpoint = &host_interf->endpoint[endp]; + if ((host_endpoint->desc.bEndpointAddress == 0x82) && + (host_endpoint->desc.wMaxPacketSize == 0x10)) { + ttusbir->alt_setting = alt_set; + ttusbir->endpoint = endp; + found = 1; + break; + } + } + } + if (ttusbir->alt_setting != -1) + DPRINTK("alt setting: %d\n", ttusbir->alt_setting); + else { + err("Could not find alternate setting\n"); + kfree(ttusbir); + return -EINVAL; + } + + /* OK lets setup this interface setting */ + usb_set_interface(ttusbir->udev, 0, ttusbir->alt_setting); + + /* Store device info in interface structure */ + usb_set_intfdata(intf, ttusbir); + + /* Register as a LIRC driver */ + if (lirc_buffer_init(&ttusbir->rbuf, sizeof(int), 256) < 0) { + err("Could not get memory for LIRC data buffer\n"); + usb_set_intfdata(intf, NULL); + kfree(ttusbir); + return -ENOMEM; + } + strcpy(ttusbir->driver.name, "TTUSBIR"); + ttusbir->driver.minor = -1; + ttusbir->driver.code_length = 1; + ttusbir->driver.sample_rate = 0; + ttusbir->driver.data = ttusbir; + ttusbir->driver.add_to_buf = NULL; + ttusbir->driver.rbuf = &ttusbir->rbuf; + ttusbir->driver.set_use_inc = set_use_inc; + ttusbir->driver.set_use_dec = set_use_dec; + ttusbir->driver.dev = &intf->dev; + ttusbir->driver.owner = THIS_MODULE; + ttusbir->driver.features = LIRC_CAN_REC_MODE2; + ttusbir->minor = lirc_register_driver(&ttusbir->driver); + if (ttusbir->minor < 0) { + err("Error registering as LIRC driver\n"); + usb_set_intfdata(intf, NULL); + lirc_buffer_free(&ttusbir->rbuf); + kfree(ttusbir); + return -EIO; + } + + /* Allocate and setup the URB that we will use to talk to the device */ + for (i = 0; i < num_urbs; i++) { + ttusbir->urb[i] = usb_alloc_urb(8, GFP_KERNEL); + if (!ttusbir->urb[i]) { + err("Could not allocate memory for the URB\n"); + for (j = i - 1; j >= 0; j--) + kfree(ttusbir->urb[j]); + lirc_buffer_free(&ttusbir->rbuf); + lirc_unregister_driver(ttusbir->minor); + kfree(ttusbir); + usb_set_intfdata(intf, NULL); + return -ENOMEM; + } + ttusbir->urb[i]->dev = ttusbir->udev; + ttusbir->urb[i]->context = ttusbir; + ttusbir->urb[i]->pipe = usb_rcvisocpipe(ttusbir->udev, + ttusbir->endpoint); + ttusbir->urb[i]->interval = 1; + ttusbir->urb[i]->transfer_flags = URB_ISO_ASAP; + ttusbir->urb[i]->transfer_buffer = &ttusbir->buffer[i][0]; + ttusbir->urb[i]->complete = urb_complete; + ttusbir->urb[i]->number_of_packets = 8; + ttusbir->urb[i]->transfer_buffer_length = 128; + for (j = 0; j < 8; j++) { + ttusbir->urb[i]->iso_frame_desc[j].offset = j*16; + ttusbir->urb[i]->iso_frame_desc[j].length = 16; + } + } + return 0; +} + +/** + * Called when the driver is unloaded or the device is unplugged + */ +static void disconnect(struct usb_interface *intf) +{ + int i; + struct ttusbir_device *ttusbir; + + DPRINTK("Module ttusbir disconnect\n"); + + ttusbir = (struct ttusbir_device *) usb_get_intfdata(intf); + usb_set_intfdata(intf, NULL); + lirc_unregister_driver(ttusbir->minor); + DPRINTK("unregistered\n"); + + for (i = 0; i < num_urbs; i++) { + usb_kill_urb(ttusbir->urb[i]); + usb_free_urb(ttusbir->urb[i]); + } + DPRINTK("URBs killed\n"); + lirc_buffer_free(&ttusbir->rbuf); + kfree(ttusbir); +} + +static int ttusbir_init_module(void) +{ + int result; + + DPRINTK(KERN_DEBUG "Module ttusbir init\n"); + + /* register this driver with the USB subsystem */ + result = usb_register(&usb_driver); + if (result) + err("usb_register failed. Error number %d", result); + return result; +} + +static void ttusbir_exit_module(void) +{ + printk(KERN_DEBUG "Module ttusbir exit\n"); + usb_deregister(&usb_driver); +} + +module_init(ttusbir_init_module); +module_exit(ttusbir_exit_module); diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c new file mode 100644 index 000000000000..100caab10451 --- /dev/null +++ b/drivers/staging/lirc/lirc_zilog.c @@ -0,0 +1,1387 @@ +/* + * i2c IR lirc driver for devices with zilog IR processors + * + * Copyright (c) 2000 Gerd Knorr <kraxel@goldbach.in-berlin.de> + * modified for PixelView (BT878P+W/FM) by + * Michal Kochanowicz <mkochano@pld.org.pl> + * Christoph Bartelmus <lirc@bartelmus.de> + * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by + * Ulrich Mueller <ulrich.mueller42@web.de> + * modified for Asus TV-Box and Creative/VisionTek BreakOut-Box by + * Stefan Jahn <stefan@lkcc.org> + * modified for inclusion into kernel sources by + * Jerome Brock <jbrock@users.sourceforge.net> + * modified for Leadtek Winfast PVR2000 by + * Thomas Reitmayr (treitmayr@yahoo.com) + * modified for Hauppauge PVR-150 IR TX device by + * Mark Weaver <mark@npsl.co.uk> + * changed name from lirc_pvr150 to lirc_zilog, works on more than pvr-150 + * Jarod Wilson <jarod@redhat.com> + * + * parts are cut&pasted from the lirc_i2c.c driver + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/kmod.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/fs.h> +#include <linux/poll.h> +#include <linux/string.h> +#include <linux/timer.h> +#include <linux/delay.h> +#include <linux/completion.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/firmware.h> +#include <linux/vmalloc.h> + +#include <linux/mutex.h> +#include <linux/kthread.h> + +#include <media/lirc_dev.h> +#include <media/lirc.h> + +struct IR { + struct lirc_driver l; + + /* Device info */ + struct mutex ir_lock; + int open; + + /* RX device */ + struct i2c_client c_rx; + int have_rx; + + /* RX device buffer & lock */ + struct lirc_buffer buf; + struct mutex buf_lock; + + /* RX polling thread data */ + struct completion *t_notify; + struct completion *t_notify2; + int shutdown; + struct task_struct *task; + + /* RX read data */ + unsigned char b[3]; + + /* TX device */ + struct i2c_client c_tx; + int need_boot; + int have_tx; +}; + +/* Minor -> data mapping */ +static struct IR *ir_devices[MAX_IRCTL_DEVICES]; + +/* Block size for IR transmitter */ +#define TX_BLOCK_SIZE 99 + +/* Hauppauge IR transmitter data */ +struct tx_data_struct { + /* Boot block */ + unsigned char *boot_data; + + /* Start of binary data block */ + unsigned char *datap; + + /* End of binary data block */ + unsigned char *endp; + + /* Number of installed codesets */ + unsigned int num_code_sets; + + /* Pointers to codesets */ + unsigned char **code_sets; + + /* Global fixed data template */ + int fixed[TX_BLOCK_SIZE]; +}; + +static struct tx_data_struct *tx_data; +static struct mutex tx_data_lock; + +#define zilog_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, \ + ## args) +#define zilog_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) + +#define ZILOG_HAUPPAUGE_IR_RX_NAME "Zilog/Hauppauge IR RX" +#define ZILOG_HAUPPAUGE_IR_TX_NAME "Zilog/Hauppauge IR TX" + +/* module parameters */ +static int debug; /* debug output */ +static int disable_rx; /* disable RX device */ +static int disable_tx; /* disable TX device */ +static int minor = -1; /* minor number */ + +#define dprintk(fmt, args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG KBUILD_MODNAME ": " fmt, \ + ## args); \ + } while (0) + +static int add_to_buf(struct IR *ir) +{ + __u16 code; + unsigned char codes[2]; + unsigned char keybuf[6]; + int got_data = 0; + int ret; + int failures = 0; + unsigned char sendbuf[1] = { 0 }; + + if (lirc_buffer_full(&ir->buf)) { + dprintk("buffer overflow\n"); + return -EOVERFLOW; + } + + /* + * service the device as long as it is returning + * data and we have space + */ + do { + /* + * Lock i2c bus for the duration. RX/TX chips interfere so + * this is worth it + */ + mutex_lock(&ir->ir_lock); + + /* + * Send random "poll command" (?) Windows driver does this + * and it is a good point to detect chip failure. + */ + ret = i2c_master_send(&ir->c_rx, sendbuf, 1); + if (ret != 1) { + zilog_error("i2c_master_send failed with %d\n", ret); + if (failures >= 3) { + mutex_unlock(&ir->ir_lock); + zilog_error("unable to read from the IR chip " + "after 3 resets, giving up\n"); + return ret; + } + + /* Looks like the chip crashed, reset it */ + zilog_error("polling the IR receiver chip failed, " + "trying reset\n"); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((100 * HZ + 999) / 1000); + ir->need_boot = 1; + + ++failures; + mutex_unlock(&ir->ir_lock); + continue; + } + + ret = i2c_master_recv(&ir->c_rx, keybuf, sizeof(keybuf)); + mutex_unlock(&ir->ir_lock); + if (ret != sizeof(keybuf)) { + zilog_error("i2c_master_recv failed with %d -- " + "keeping last read buffer\n", ret); + } else { + ir->b[0] = keybuf[3]; + ir->b[1] = keybuf[4]; + ir->b[2] = keybuf[5]; + dprintk("key (0x%02x/0x%02x)\n", ir->b[0], ir->b[1]); + } + + /* key pressed ? */ +#ifdef I2C_HW_B_HDPVR + if (ir->c_rx.adapter->id == I2C_HW_B_HDPVR) { + if (got_data && (keybuf[0] == 0x80)) + return 0; + else if (got_data && (keybuf[0] == 0x00)) + return -ENODATA; + } else if ((ir->b[0] & 0x80) == 0) +#else + if ((ir->b[0] & 0x80) == 0) +#endif + return got_data ? 0 : -ENODATA; + + /* look what we have */ + code = (((__u16)ir->b[0] & 0x7f) << 6) | (ir->b[1] >> 2); + + codes[0] = (code >> 8) & 0xff; + codes[1] = code & 0xff; + + /* return it */ + lirc_buffer_write(&ir->buf, codes); + ++got_data; + } while (!lirc_buffer_full(&ir->buf)); + + return 0; +} + +/* + * Main function of the polling thread -- from lirc_dev. + * We don't fit the LIRC model at all anymore. This is horrible, but + * basically we have a single RX/TX device with a nasty failure mode + * that needs to be accounted for across the pair. lirc lets us provide + * fops, but prevents us from using the internal polling, etc. if we do + * so. Hence the replication. Might be neater to extend the LIRC model + * to account for this but I'd think it's a very special case of seriously + * messed up hardware. + */ +static int lirc_thread(void *arg) +{ + struct IR *ir = arg; + + if (ir->t_notify != NULL) + complete(ir->t_notify); + + dprintk("poll thread started\n"); + + do { + if (ir->open) { + set_current_state(TASK_INTERRUPTIBLE); + + /* + * This is ~113*2 + 24 + jitter (2*repeat gap + + * code length). We use this interval as the chip + * resets every time you poll it (bad!). This is + * therefore just sufficient to catch all of the + * button presses. It makes the remote much more + * responsive. You can see the difference by + * running irw and holding down a button. With + * 100ms, the old polling interval, you'll notice + * breaks in the repeat sequence corresponding to + * lost keypresses. + */ + schedule_timeout((260 * HZ) / 1000); + if (ir->shutdown) + break; + if (!add_to_buf(ir)) + wake_up_interruptible(&ir->buf.wait_poll); + } else { + /* if device not opened so we can sleep half a second */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/2); + } + } while (!ir->shutdown); + + if (ir->t_notify2 != NULL) + wait_for_completion(ir->t_notify2); + + ir->task = NULL; + if (ir->t_notify != NULL) + complete(ir->t_notify); + + dprintk("poll thread ended\n"); + return 0; +} + +static int set_use_inc(void *data) +{ + struct IR *ir = data; + + if (ir->l.owner == NULL || try_module_get(ir->l.owner) == 0) + return -ENODEV; + + /* lock bttv in memory while /dev/lirc is in use */ + /* + * this is completely broken code. lirc_unregister_driver() + * must be possible even when the device is open + */ + if (ir->c_rx.addr) + i2c_use_client(&ir->c_rx); + if (ir->c_tx.addr) + i2c_use_client(&ir->c_tx); + + return 0; +} + +static void set_use_dec(void *data) +{ + struct IR *ir = data; + + if (ir->c_rx.addr) + i2c_release_client(&ir->c_rx); + if (ir->c_tx.addr) + i2c_release_client(&ir->c_tx); + if (ir->l.owner != NULL) + module_put(ir->l.owner); +} + +/* safe read of a uint32 (always network byte order) */ +static int read_uint32(unsigned char **data, + unsigned char *endp, unsigned int *val) +{ + if (*data + 4 > endp) + return 0; + *val = ((*data)[0] << 24) | ((*data)[1] << 16) | + ((*data)[2] << 8) | (*data)[3]; + *data += 4; + return 1; +} + +/* safe read of a uint8 */ +static int read_uint8(unsigned char **data, + unsigned char *endp, unsigned char *val) +{ + if (*data + 1 > endp) + return 0; + *val = *((*data)++); + return 1; +} + +/* safe skipping of N bytes */ +static int skip(unsigned char **data, + unsigned char *endp, unsigned int distance) +{ + if (*data + distance > endp) + return 0; + *data += distance; + return 1; +} + +/* decompress key data into the given buffer */ +static int get_key_data(unsigned char *buf, + unsigned int codeset, unsigned int key) +{ + unsigned char *data, *endp, *diffs, *key_block; + unsigned char keys, ndiffs, id; + unsigned int base, lim, pos, i; + + /* Binary search for the codeset */ + for (base = 0, lim = tx_data->num_code_sets; lim; lim >>= 1) { + pos = base + (lim >> 1); + data = tx_data->code_sets[pos]; + + if (!read_uint32(&data, tx_data->endp, &i)) + goto corrupt; + + if (i == codeset) + break; + else if (codeset > i) { + base = pos + 1; + --lim; + } + } + /* Not found? */ + if (!lim) + return -EPROTO; + + /* Set end of data block */ + endp = pos < tx_data->num_code_sets - 1 ? + tx_data->code_sets[pos + 1] : tx_data->endp; + + /* Read the block header */ + if (!read_uint8(&data, endp, &keys) || + !read_uint8(&data, endp, &ndiffs) || + ndiffs > TX_BLOCK_SIZE || keys == 0) + goto corrupt; + + /* Save diffs & skip */ + diffs = data; + if (!skip(&data, endp, ndiffs)) + goto corrupt; + + /* Read the id of the first key */ + if (!read_uint8(&data, endp, &id)) + goto corrupt; + + /* Unpack the first key's data */ + for (i = 0; i < TX_BLOCK_SIZE; ++i) { + if (tx_data->fixed[i] == -1) { + if (!read_uint8(&data, endp, &buf[i])) + goto corrupt; + } else { + buf[i] = (unsigned char)tx_data->fixed[i]; + } + } + + /* Early out key found/not found */ + if (key == id) + return 0; + if (keys == 1) + return -EPROTO; + + /* Sanity check */ + key_block = data; + if (!skip(&data, endp, (keys - 1) * (ndiffs + 1))) + goto corrupt; + + /* Binary search for the key */ + for (base = 0, lim = keys - 1; lim; lim >>= 1) { + /* Seek to block */ + unsigned char *key_data; + pos = base + (lim >> 1); + key_data = key_block + (ndiffs + 1) * pos; + + if (*key_data == key) { + /* skip key id */ + ++key_data; + + /* found, so unpack the diffs */ + for (i = 0; i < ndiffs; ++i) { + unsigned char val; + if (!read_uint8(&key_data, endp, &val) || + diffs[i] >= TX_BLOCK_SIZE) + goto corrupt; + buf[diffs[i]] = val; + } + + return 0; + } else if (key > *key_data) { + base = pos + 1; + --lim; + } + } + /* Key not found */ + return -EPROTO; + +corrupt: + zilog_error("firmware is corrupt\n"); + return -EFAULT; +} + +/* send a block of data to the IR TX device */ +static int send_data_block(struct IR *ir, unsigned char *data_block) +{ + int i, j, ret; + unsigned char buf[5]; + + for (i = 0; i < TX_BLOCK_SIZE;) { + int tosend = TX_BLOCK_SIZE - i; + if (tosend > 4) + tosend = 4; + buf[0] = (unsigned char)(i + 1); + for (j = 0; j < tosend; ++j) + buf[1 + j] = data_block[i + j]; + dprintk("%02x %02x %02x %02x %02x", + buf[0], buf[1], buf[2], buf[3], buf[4]); + ret = i2c_master_send(&ir->c_tx, buf, tosend + 1); + if (ret != tosend + 1) { + zilog_error("i2c_master_send failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + i += tosend; + } + return 0; +} + +/* send boot data to the IR TX device */ +static int send_boot_data(struct IR *ir) +{ + int ret; + unsigned char buf[4]; + + /* send the boot block */ + ret = send_data_block(ir, tx_data->boot_data); + if (ret != 0) + return ret; + + /* kick it off? */ + buf[0] = 0x00; + buf[1] = 0x20; + ret = i2c_master_send(&ir->c_tx, buf, 2); + if (ret != 2) { + zilog_error("i2c_master_send failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + ret = i2c_master_send(&ir->c_tx, buf, 1); + if (ret != 1) { + zilog_error("i2c_master_send failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + + /* Here comes the firmware version... (hopefully) */ + ret = i2c_master_recv(&ir->c_tx, buf, 4); + if (ret != 4) { + zilog_error("i2c_master_recv failed with %d\n", ret); + return 0; + } + if (buf[0] != 0x80) { + zilog_error("unexpected IR TX response: %02x\n", buf[0]); + return 0; + } + zilog_notify("Zilog/Hauppauge IR blaster firmware version " + "%d.%d.%d loaded\n", buf[1], buf[2], buf[3]); + + return 0; +} + +/* unload "firmware", lock held */ +static void fw_unload_locked(void) +{ + if (tx_data) { + if (tx_data->code_sets) + vfree(tx_data->code_sets); + + if (tx_data->datap) + vfree(tx_data->datap); + + vfree(tx_data); + tx_data = NULL; + dprintk("successfully unloaded IR blaster firmware\n"); + } +} + +/* unload "firmware" for the IR TX device */ +static void fw_unload(void) +{ + mutex_lock(&tx_data_lock); + fw_unload_locked(); + mutex_unlock(&tx_data_lock); +} + +/* load "firmware" for the IR TX device */ +static int fw_load(struct IR *ir) +{ + int ret; + unsigned int i; + unsigned char *data, version, num_global_fixed; + const struct firmware *fw_entry; + + /* Already loaded? */ + mutex_lock(&tx_data_lock); + if (tx_data) { + ret = 0; + goto out; + } + + /* Request codeset data file */ + ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", &ir->c_tx.dev); + if (ret != 0) { + zilog_error("firmware haup-ir-blaster.bin not available " + "(%d)\n", ret); + ret = ret < 0 ? ret : -EFAULT; + goto out; + } + dprintk("firmware of size %zu loaded\n", fw_entry->size); + + /* Parse the file */ + tx_data = vmalloc(sizeof(*tx_data)); + if (tx_data == NULL) { + zilog_error("out of memory\n"); + release_firmware(fw_entry); + ret = -ENOMEM; + goto out; + } + tx_data->code_sets = NULL; + + /* Copy the data so hotplug doesn't get confused and timeout */ + tx_data->datap = vmalloc(fw_entry->size); + if (tx_data->datap == NULL) { + zilog_error("out of memory\n"); + release_firmware(fw_entry); + vfree(tx_data); + ret = -ENOMEM; + goto out; + } + memcpy(tx_data->datap, fw_entry->data, fw_entry->size); + tx_data->endp = tx_data->datap + fw_entry->size; + release_firmware(fw_entry); fw_entry = NULL; + + /* Check version */ + data = tx_data->datap; + if (!read_uint8(&data, tx_data->endp, &version)) + goto corrupt; + if (version != 1) { + zilog_error("unsupported code set file version (%u, expected" + "1) -- please upgrade to a newer driver", + version); + fw_unload_locked(); + ret = -EFAULT; + goto out; + } + + /* Save boot block for later */ + tx_data->boot_data = data; + if (!skip(&data, tx_data->endp, TX_BLOCK_SIZE)) + goto corrupt; + + if (!read_uint32(&data, tx_data->endp, + &tx_data->num_code_sets)) + goto corrupt; + + dprintk("%u IR blaster codesets loaded\n", tx_data->num_code_sets); + + tx_data->code_sets = vmalloc( + tx_data->num_code_sets * sizeof(char *)); + if (tx_data->code_sets == NULL) { + fw_unload_locked(); + ret = -ENOMEM; + goto out; + } + + for (i = 0; i < TX_BLOCK_SIZE; ++i) + tx_data->fixed[i] = -1; + + /* Read global fixed data template */ + if (!read_uint8(&data, tx_data->endp, &num_global_fixed) || + num_global_fixed > TX_BLOCK_SIZE) + goto corrupt; + for (i = 0; i < num_global_fixed; ++i) { + unsigned char pos, val; + if (!read_uint8(&data, tx_data->endp, &pos) || + !read_uint8(&data, tx_data->endp, &val) || + pos >= TX_BLOCK_SIZE) + goto corrupt; + tx_data->fixed[pos] = (int)val; + } + + /* Filch out the position of each code set */ + for (i = 0; i < tx_data->num_code_sets; ++i) { + unsigned int id; + unsigned char keys; + unsigned char ndiffs; + + /* Save the codeset position */ + tx_data->code_sets[i] = data; + + /* Read header */ + if (!read_uint32(&data, tx_data->endp, &id) || + !read_uint8(&data, tx_data->endp, &keys) || + !read_uint8(&data, tx_data->endp, &ndiffs) || + ndiffs > TX_BLOCK_SIZE || keys == 0) + goto corrupt; + + /* skip diff positions */ + if (!skip(&data, tx_data->endp, ndiffs)) + goto corrupt; + + /* + * After the diffs we have the first key id + data - + * global fixed + */ + if (!skip(&data, tx_data->endp, + 1 + TX_BLOCK_SIZE - num_global_fixed)) + goto corrupt; + + /* Then we have keys-1 blocks of key id+diffs */ + if (!skip(&data, tx_data->endp, + (ndiffs + 1) * (keys - 1))) + goto corrupt; + } + ret = 0; + goto out; + +corrupt: + zilog_error("firmware is corrupt\n"); + fw_unload_locked(); + ret = -EFAULT; + +out: + mutex_unlock(&tx_data_lock); + return ret; +} + +/* initialise the IR TX device */ +static int tx_init(struct IR *ir) +{ + int ret; + + /* Load 'firmware' */ + ret = fw_load(ir); + if (ret != 0) + return ret; + + /* Send boot block */ + ret = send_boot_data(ir); + if (ret != 0) + return ret; + ir->need_boot = 0; + + /* Looks good */ + return 0; +} + +/* do nothing stub to make LIRC happy */ +static loff_t lseek(struct file *filep, loff_t offset, int orig) +{ + return -ESPIPE; +} + +/* copied from lirc_dev */ +static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) +{ + struct IR *ir = (struct IR *)filep->private_data; + unsigned char buf[ir->buf.chunk_size]; + int ret = 0, written = 0; + DECLARE_WAITQUEUE(wait, current); + + dprintk("read called\n"); + if (ir->c_rx.addr == 0) + return -ENODEV; + + if (mutex_lock_interruptible(&ir->buf_lock)) + return -ERESTARTSYS; + + if (n % ir->buf.chunk_size) { + dprintk("read result = -EINVAL\n"); + mutex_unlock(&ir->buf_lock); + return -EINVAL; + } + + /* + * we add ourselves to the task queue before buffer check + * to avoid losing scan code (in case when queue is awaken somewhere + * between while condition checking and scheduling) + */ + add_wait_queue(&ir->buf.wait_poll, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + /* + * while we didn't provide 'length' bytes, device is opened in blocking + * mode and 'copy_to_user' is happy, wait for data. + */ + while (written < n && ret == 0) { + if (lirc_buffer_empty(&ir->buf)) { + /* + * According to the read(2) man page, 'written' can be + * returned as less than 'n', instead of blocking + * again, returning -EWOULDBLOCK, or returning + * -ERESTARTSYS + */ + if (written) + break; + if (filep->f_flags & O_NONBLOCK) { + ret = -EWOULDBLOCK; + break; + } + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } else { + lirc_buffer_read(&ir->buf, buf); + ret = copy_to_user((void *)outbuf+written, buf, + ir->buf.chunk_size); + written += ir->buf.chunk_size; + } + } + + remove_wait_queue(&ir->buf.wait_poll, &wait); + set_current_state(TASK_RUNNING); + mutex_unlock(&ir->buf_lock); + + dprintk("read result = %s (%d)\n", + ret ? "-EFAULT" : "OK", ret); + + return ret ? ret : written; +} + +/* send a keypress to the IR TX device */ +static int send_code(struct IR *ir, unsigned int code, unsigned int key) +{ + unsigned char data_block[TX_BLOCK_SIZE]; + unsigned char buf[2]; + int i, ret; + + /* Get data for the codeset/key */ + ret = get_key_data(data_block, code, key); + + if (ret == -EPROTO) { + zilog_error("failed to get data for code %u, key %u -- check " + "lircd.conf entries\n", code, key); + return ret; + } else if (ret != 0) + return ret; + + /* Send the data block */ + ret = send_data_block(ir, data_block); + if (ret != 0) + return ret; + + /* Send data block length? */ + buf[0] = 0x00; + buf[1] = 0x40; + ret = i2c_master_send(&ir->c_tx, buf, 2); + if (ret != 2) { + zilog_error("i2c_master_send failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + ret = i2c_master_send(&ir->c_tx, buf, 1); + if (ret != 1) { + zilog_error("i2c_master_send failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + + /* Send finished download? */ + ret = i2c_master_recv(&ir->c_tx, buf, 1); + if (ret != 1) { + zilog_error("i2c_master_recv failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + if (buf[0] != 0xA0) { + zilog_error("unexpected IR TX response #1: %02x\n", + buf[0]); + return -EFAULT; + } + + /* Send prepare command? */ + buf[0] = 0x00; + buf[1] = 0x80; + ret = i2c_master_send(&ir->c_tx, buf, 2); + if (ret != 2) { + zilog_error("i2c_master_send failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + +#ifdef I2C_HW_B_HDPVR + /* + * The sleep bits aren't necessary on the HD PVR, and in fact, the + * last i2c_master_recv always fails with a -5, so for now, we're + * going to skip this whole mess and say we're done on the HD PVR + */ + if (ir->c_rx.adapter->id == I2C_HW_B_HDPVR) + goto done; +#endif + + /* + * This bit NAKs until the device is ready, so we retry it + * sleeping a bit each time. This seems to be what the windows + * driver does, approximately. + * Try for up to 1s. + */ + for (i = 0; i < 20; ++i) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((50 * HZ + 999) / 1000); + ret = i2c_master_send(&ir->c_tx, buf, 1); + if (ret == 1) + break; + dprintk("NAK expected: i2c_master_send " + "failed with %d (try %d)\n", ret, i+1); + } + if (ret != 1) { + zilog_error("IR TX chip never got ready: last i2c_master_send " + "failed with %d\n", ret); + return ret < 0 ? ret : -EFAULT; + } + + /* Seems to be an 'ok' response */ + i = i2c_master_recv(&ir->c_tx, buf, 1); + if (i != 1) { + zilog_error("i2c_master_recv failed with %d\n", ret); + return -EFAULT; + } + if (buf[0] != 0x80) { + zilog_error("unexpected IR TX response #2: %02x\n", buf[0]); + return -EFAULT; + } + +done: + /* Oh good, it worked */ + dprintk("sent code %u, key %u\n", code, key); + return 0; +} + +/* + * Write a code to the device. We take in a 32-bit number (an int) and then + * decode this to a codeset/key index. The key data is then decompressed and + * sent to the device. We have a spin lock as per i2c documentation to prevent + * multiple concurrent sends which would probably cause the device to explode. + */ +static ssize_t write(struct file *filep, const char *buf, size_t n, + loff_t *ppos) +{ + struct IR *ir = (struct IR *)filep->private_data; + size_t i; + int failures = 0; + + if (ir->c_tx.addr == 0) + return -ENODEV; + + /* Validate user parameters */ + if (n % sizeof(int)) + return -EINVAL; + + /* Lock i2c bus for the duration */ + mutex_lock(&ir->ir_lock); + + /* Send each keypress */ + for (i = 0; i < n;) { + int ret = 0; + int command; + + if (copy_from_user(&command, buf + i, sizeof(command))) { + mutex_unlock(&ir->ir_lock); + return -EFAULT; + } + + /* Send boot data first if required */ + if (ir->need_boot == 1) { + ret = send_boot_data(ir); + if (ret == 0) + ir->need_boot = 0; + } + + /* Send the code */ + if (ret == 0) { + ret = send_code(ir, (unsigned)command >> 16, + (unsigned)command & 0xFFFF); + if (ret == -EPROTO) { + mutex_unlock(&ir->ir_lock); + return ret; + } + } + + /* + * Hmm, a failure. If we've had a few then give up, otherwise + * try a reset + */ + if (ret != 0) { + /* Looks like the chip crashed, reset it */ + zilog_error("sending to the IR transmitter chip " + "failed, trying reset\n"); + + if (failures >= 3) { + zilog_error("unable to send to the IR chip " + "after 3 resets, giving up\n"); + mutex_unlock(&ir->ir_lock); + return ret; + } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((100 * HZ + 999) / 1000); + ir->need_boot = 1; + ++failures; + } else + i += sizeof(int); + } + + /* Release i2c bus */ + mutex_unlock(&ir->ir_lock); + + /* All looks good */ + return n; +} + +/* copied from lirc_dev */ +static unsigned int poll(struct file *filep, poll_table *wait) +{ + struct IR *ir = (struct IR *)filep->private_data; + unsigned int ret; + + dprintk("poll called\n"); + if (ir->c_rx.addr == 0) + return -ENODEV; + + mutex_lock(&ir->buf_lock); + + poll_wait(filep, &ir->buf.wait_poll, wait); + + dprintk("poll result = %s\n", + lirc_buffer_empty(&ir->buf) ? "0" : "POLLIN|POLLRDNORM"); + + ret = lirc_buffer_empty(&ir->buf) ? 0 : (POLLIN|POLLRDNORM); + + mutex_unlock(&ir->buf_lock); + return ret; +} + +static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +{ + struct IR *ir = (struct IR *)filep->private_data; + int result; + unsigned long mode, features = 0; + + if (ir->c_rx.addr != 0) + features |= LIRC_CAN_REC_LIRCCODE; + if (ir->c_tx.addr != 0) + features |= LIRC_CAN_SEND_PULSE; + + switch (cmd) { + case LIRC_GET_LENGTH: + result = put_user((unsigned long)13, + (unsigned long *)arg); + break; + case LIRC_GET_FEATURES: + result = put_user(features, (unsigned long *) arg); + break; + case LIRC_GET_REC_MODE: + if (!(features&LIRC_CAN_REC_MASK)) + return -ENOSYS; + + result = put_user(LIRC_REC2MODE + (features&LIRC_CAN_REC_MASK), + (unsigned long *)arg); + break; + case LIRC_SET_REC_MODE: + if (!(features&LIRC_CAN_REC_MASK)) + return -ENOSYS; + + result = get_user(mode, (unsigned long *)arg); + if (!result && !(LIRC_MODE2REC(mode) & features)) + result = -EINVAL; + break; + case LIRC_GET_SEND_MODE: + if (!(features&LIRC_CAN_SEND_MASK)) + return -ENOSYS; + + result = put_user(LIRC_MODE_PULSE, (unsigned long *) arg); + break; + case LIRC_SET_SEND_MODE: + if (!(features&LIRC_CAN_SEND_MASK)) + return -ENOSYS; + + result = get_user(mode, (unsigned long *) arg); + if (!result && mode != LIRC_MODE_PULSE) + return -EINVAL; + break; + default: + return -EINVAL; + } + return result; +} + +/* + * Open the IR device. Get hold of our IR structure and + * stash it in private_data for the file + */ +static int open(struct inode *node, struct file *filep) +{ + struct IR *ir; + int ret; + + /* find our IR struct */ + unsigned minor = MINOR(node->i_rdev); + if (minor >= MAX_IRCTL_DEVICES) { + dprintk("minor %d: open result = -ENODEV\n", + minor); + return -ENODEV; + } + ir = ir_devices[minor]; + + /* increment in use count */ + mutex_lock(&ir->ir_lock); + ++ir->open; + ret = set_use_inc(ir); + if (ret != 0) { + --ir->open; + mutex_unlock(&ir->ir_lock); + return ret; + } + mutex_unlock(&ir->ir_lock); + + /* stash our IR struct */ + filep->private_data = ir; + + return 0; +} + +/* Close the IR device */ +static int close(struct inode *node, struct file *filep) +{ + /* find our IR struct */ + struct IR *ir = (struct IR *)filep->private_data; + if (ir == NULL) { + zilog_error("close: no private_data attached to the file!\n"); + return -ENODEV; + } + + /* decrement in use count */ + mutex_lock(&ir->ir_lock); + --ir->open; + set_use_dec(ir); + mutex_unlock(&ir->ir_lock); + + return 0; +} + +static struct lirc_driver lirc_template = { + .name = "lirc_zilog", + .set_use_inc = set_use_inc, + .set_use_dec = set_use_dec, + .owner = THIS_MODULE +}; + +static int ir_remove(struct i2c_client *client); +static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id); +static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg); + +static const struct i2c_device_id ir_transceiver_id[] = { + /* Generic entry for any IR transceiver */ + { "ir_video", 0 }, + /* IR device specific entries should be added here */ + { "ir_tx_z8f0811_haup", 0 }, + { "ir_rx_z8f0811_haup", 0 }, + { } +}; + +static struct i2c_driver driver = { + .driver = { + .owner = THIS_MODULE, + .name = "Zilog/Hauppauge i2c IR", + }, + .probe = ir_probe, + .remove = ir_remove, + .command = ir_command, + .id_table = ir_transceiver_id, +}; + +static const struct file_operations lirc_fops = { + .owner = THIS_MODULE, + .llseek = lseek, + .read = read, + .write = write, + .poll = poll, + .unlocked_ioctl = ioctl, + .open = open, + .release = close +}; + +static int ir_remove(struct i2c_client *client) +{ + struct IR *ir = i2c_get_clientdata(client); + + mutex_lock(&ir->ir_lock); + + if (ir->have_rx || ir->have_tx) { + DECLARE_COMPLETION(tn); + DECLARE_COMPLETION(tn2); + + /* end up polling thread */ + if (ir->task && !IS_ERR(ir->task)) { + ir->t_notify = &tn; + ir->t_notify2 = &tn2; + ir->shutdown = 1; + wake_up_process(ir->task); + complete(&tn2); + wait_for_completion(&tn); + ir->t_notify = NULL; + ir->t_notify2 = NULL; + } + + } else { + mutex_unlock(&ir->ir_lock); + zilog_error("%s: detached from something we didn't " + "attach to\n", __func__); + return -ENODEV; + } + + /* unregister lirc driver */ + if (ir->l.minor >= 0 && ir->l.minor < MAX_IRCTL_DEVICES) { + lirc_unregister_driver(ir->l.minor); + ir_devices[ir->l.minor] = NULL; + } + + /* free memory */ + lirc_buffer_free(&ir->buf); + mutex_unlock(&ir->ir_lock); + kfree(ir); + + return 0; +} + +static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct IR *ir = NULL; + struct i2c_adapter *adap = client->adapter; + char buf; + int ret; + int have_rx = 0, have_tx = 0; + + dprintk("%s: adapter id=0x%x, client addr=0x%02x\n", + __func__, adap->id, client->addr); + + /* + * The external IR receiver is at i2c address 0x71. + * The IR transmitter is at 0x70. + */ + client->addr = 0x70; + + if (!disable_tx) { + if (i2c_master_recv(client, &buf, 1) == 1) + have_tx = 1; + dprintk("probe 0x70 @ %s: %s\n", + adap->name, have_tx ? "success" : "failed"); + } + + if (!disable_rx) { + client->addr = 0x71; + if (i2c_master_recv(client, &buf, 1) == 1) + have_rx = 1; + dprintk("probe 0x71 @ %s: %s\n", + adap->name, have_rx ? "success" : "failed"); + } + + if (!(have_rx || have_tx)) { + zilog_error("%s: no devices found\n", adap->name); + goto out_nodev; + } + + printk(KERN_INFO "lirc_zilog: chip found with %s\n", + have_rx && have_tx ? "RX and TX" : + have_rx ? "RX only" : "TX only"); + + ir = kzalloc(sizeof(struct IR), GFP_KERNEL); + + if (!ir) + goto out_nomem; + + ret = lirc_buffer_init(&ir->buf, 2, BUFLEN / 2); + if (ret) + goto out_nomem; + + mutex_init(&ir->ir_lock); + mutex_init(&ir->buf_lock); + ir->need_boot = 1; + + memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); + ir->l.minor = -1; + + /* I2C attach to device */ + i2c_set_clientdata(client, ir); + + /* initialise RX device */ + if (have_rx) { + DECLARE_COMPLETION(tn); + memcpy(&ir->c_rx, client, sizeof(struct i2c_client)); + + ir->c_rx.addr = 0x71; + strlcpy(ir->c_rx.name, ZILOG_HAUPPAUGE_IR_RX_NAME, + I2C_NAME_SIZE); + + /* try to fire up polling thread */ + ir->t_notify = &tn; + ir->task = kthread_run(lirc_thread, ir, "lirc_zilog"); + if (IS_ERR(ir->task)) { + ret = PTR_ERR(ir->task); + zilog_error("lirc_register_driver: cannot run " + "poll thread %d\n", ret); + goto err; + } + wait_for_completion(&tn); + ir->t_notify = NULL; + ir->have_rx = 1; + } + + /* initialise TX device */ + if (have_tx) { + memcpy(&ir->c_tx, client, sizeof(struct i2c_client)); + ir->c_tx.addr = 0x70; + strlcpy(ir->c_tx.name, ZILOG_HAUPPAUGE_IR_TX_NAME, + I2C_NAME_SIZE); + ir->have_tx = 1; + } + + /* set lirc_dev stuff */ + ir->l.code_length = 13; + ir->l.rbuf = &ir->buf; + ir->l.fops = &lirc_fops; + ir->l.data = ir; + ir->l.minor = minor; + ir->l.dev = &adap->dev; + ir->l.sample_rate = 0; + + /* register with lirc */ + ir->l.minor = lirc_register_driver(&ir->l); + if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) { + zilog_error("ir_attach: \"minor\" must be between 0 and %d " + "(%d)!\n", MAX_IRCTL_DEVICES-1, ir->l.minor); + ret = -EBADRQC; + goto err; + } + + /* store this for getting back in open() later on */ + ir_devices[ir->l.minor] = ir; + + /* + * if we have the tx device, load the 'firmware'. We do this + * after registering with lirc as otherwise hotplug seems to take + * 10s to create the lirc device. + */ + if (have_tx) { + /* Special TX init */ + ret = tx_init(ir); + if (ret != 0) + goto err; + } + + return 0; + +err: + /* undo everything, hopefully... */ + if (ir->c_rx.addr) + ir_remove(&ir->c_rx); + if (ir->c_tx.addr) + ir_remove(&ir->c_tx); + return ret; + +out_nodev: + zilog_error("no device found\n"); + return -ENODEV; + +out_nomem: + zilog_error("memory allocation failure\n"); + kfree(ir); + return -ENOMEM; +} + +static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + /* nothing */ + return 0; +} + +static int __init zilog_init(void) +{ + int ret; + + zilog_notify("Zilog/Hauppauge IR driver initializing\n"); + + mutex_init(&tx_data_lock); + + request_module("firmware_class"); + + ret = i2c_add_driver(&driver); + if (ret) + zilog_error("initialization failed\n"); + else + zilog_notify("initialization complete\n"); + + return ret; +} + +static void __exit zilog_exit(void) +{ + i2c_del_driver(&driver); + /* if loaded */ + fw_unload(); + zilog_notify("Zilog/Hauppauge IR driver unloaded\n"); +} + +module_init(zilog_init); +module_exit(zilog_exit); + +MODULE_DESCRIPTION("Zilog/Hauppauge infrared transmitter driver (i2c stack)"); +MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, " + "Ulrich Mueller, Stefan Jahn, Jerome Brock, Mark Weaver"); +MODULE_LICENSE("GPL"); +/* for compat with old name, which isn't all that accurate anymore */ +MODULE_ALIAS("lirc_pvr150"); + +module_param(minor, int, 0444); +MODULE_PARM_DESC(minor, "Preferred minor device number"); + +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Enable debugging messages"); + +module_param(disable_rx, bool, 0644); +MODULE_PARM_DESC(disable_rx, "Disable the IR receiver device"); + +module_param(disable_tx, bool, 0644); +MODULE_PARM_DESC(disable_tx, "Disable the IR transmitter device"); diff --git a/drivers/staging/memrar/memrar_handler.c b/drivers/staging/memrar/memrar_handler.c index efa7fd62d390..41876f2b0e54 100644 --- a/drivers/staging/memrar/memrar_handler.c +++ b/drivers/staging/memrar/memrar_handler.c @@ -47,8 +47,7 @@ #include <linux/mm.h> #include <linux/ioport.h> #include <linux/io.h> - -#include "../rar_register/rar_register.h" +#include <linux/rar_register.h> #include "memrar.h" #include "memrar_allocator.h" diff --git a/drivers/staging/mrst-touchscreen/Kconfig b/drivers/staging/mrst-touchscreen/Kconfig new file mode 100644 index 000000000000..c2af49217084 --- /dev/null +++ b/drivers/staging/mrst-touchscreen/Kconfig @@ -0,0 +1,7 @@ +config TOUCHSCREEN_INTEL_MID + tristate "Intel MID platform resistive touchscreen" + depends on INTEL_SCU_IPC + default y + help + Say Y here if you have a Intel MID based touchscreen + If unsure, say N. diff --git a/drivers/staging/mrst-touchscreen/Makefile b/drivers/staging/mrst-touchscreen/Makefile new file mode 100644 index 000000000000..2d638b0d70bf --- /dev/null +++ b/drivers/staging/mrst-touchscreen/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) := intel_mid_touch.o + + diff --git a/drivers/staging/mrst-touchscreen/TODO b/drivers/staging/mrst-touchscreen/TODO new file mode 100644 index 000000000000..7157028d634a --- /dev/null +++ b/drivers/staging/mrst-touchscreen/TODO @@ -0,0 +1,2 @@ +- Move the driver to not think it is SPI (requires fixing some of the SFI + and firmware side) diff --git a/drivers/staging/mrst-touchscreen/intel-mid-touch.c b/drivers/staging/mrst-touchscreen/intel-mid-touch.c new file mode 100644 index 000000000000..abba22f921be --- /dev/null +++ b/drivers/staging/mrst-touchscreen/intel-mid-touch.c @@ -0,0 +1,864 @@ +/* + * intel_mid_touch.c - Intel MID Resistive Touch Screen Driver + * + * Copyright (C) 2008 Intel Corp + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; ifnot, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Questions/Comments/Bug fixes to Sreedhara (sreedhara.ds@intel.com) + * Ramesh Agarwal (ramesh.agarwal@intel.com) + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * TODO: + * kill off mrstouch_debug eventually + * review conversion of r/m/w sequences + * Replace interrupt mutex abuse + * Kill of mrstouchdevp pointer + * + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/err.h> +#include <linux/param.h> +#include <linux/spi/spi.h> +#include <linux/irq.h> +#include <linux/delay.h> +#include <linux/kthread.h> +#include <asm/intel_scu_ipc.h> + + +#if defined(MRSTOUCH_DEBUG) +#define mrstouch_debug(fmt, args...)\ + do { \ + printk(KERN_DEBUG "\n[MRSTOUCH(%d)] - ", __LINE__); \ + printk(KERN_DEBUG fmt, ##args); \ + } while (0); +#else +#define mrstouch_debug(fmt, args...) +#endif + +/* PMIC Interrupt registers */ +#define PMIC_REG_ID1 0x00 /*PMIC ID1 register */ + +/* PMIC Interrupt registers */ +#define PMIC_REG_INT 0x04 /*PMIC interrupt register */ +#define PMIC_REG_MINT 0x05 /*PMIC interrupt mask register */ + +/* ADC Interrupt registers */ +#define PMIC_REG_ADCINT 0x5F /*ADC interrupt register */ +#define PMIC_REG_MADCINT 0x60 /*ADC interrupt mask register */ + +/* ADC Control registers */ +#define PMIC_REG_ADCCNTL1 0x61 /*ADC control register */ + +/* ADC Channel Selection registers */ +#define PMICADDR0 0xA4 +#define END_OF_CHANNEL 0x1F + +/* ADC Result register */ +#define PMIC_REG_ADCSNS0H 0x64 + +/* ADC channels for touch screen */ +#define MRST_TS_CHAN10 0xA /* Touch screen X+ connection */ +#define MRST_TS_CHAN11 0xB /* Touch screen X- connection */ +#define MRST_TS_CHAN12 0xC /* Touch screen Y+ connection */ +#define MRST_TS_CHAN13 0xD /* Touch screen Y- connection */ + +/* Touch screen coordinate constants */ +#define TOUCH_PRESSURE 50 +#define TOUCH_PRESSURE_FS 100 + +#define XMOVE_LIMIT 5 +#define YMOVE_LIMIT 5 +#define XYMOVE_CNT 3 + +#define MAX_10BIT ((1<<10)-1) + +/* Touch screen channel BIAS constants */ +#define XBIAS 0x20 +#define YBIAS 0x40 +#define ZBIAS 0x80 + +/* Touch screen coordinates */ +#define MIN_X 10 +#define MAX_X 1024 +#define MIN_Y 10 +#define MAX_Y 1024 +#define WAIT_ADC_COMPLETION 10 + +/* PMIC ADC round robin delays */ +#define ADC_LOOP_DELAY0 0x0 /* Continuous loop */ +#define ADC_LOOP_DELAY1 0x1 /* 4.5 ms approximate */ + +/* PMIC Vendor Identifiers */ +#define PMIC_VENDOR_FS 0 /* PMIC vendor FreeScale */ +#define PMIC_VENDOR_MAXIM 1 /* PMIC vendor MAXIM */ +#define PMIC_VENDOR_NEC 2 /* PMIC vendor NEC */ +#define MRSTOUCH_MAX_CHANNELS 32 /* Maximum ADC channels */ + +/* Touch screen device structure */ +struct mrstouch_dev { + struct spi_device *spi; /* SPI device associated with touch screen */ + struct input_dev *input; /* input device for touchscreen*/ + char phys[32]; /* Device name */ + struct task_struct *pendet_thrd; /* PENDET interrupt handler */ + struct mutex lock; /* Sync between interrupt and PENDET handler */ + bool busy; /* Busy flag */ + u16 asr; /* Address selection register */ + int irq; /* Touch screen IRQ # */ + uint vendor; /* PMIC vendor */ + uint rev; /* PMIC revision */ + bool suspended; /* Device suspended status */ + bool disabled; /* Device disabled status */ + u16 x; /* X coordinate */ + u16 y; /* Y coordinate */ + bool pendown; /* PEN position */ +} ; + + +/* Global Pointer to Touch screen device */ +static struct mrstouch_dev *mrstouchdevp; + +/* Utility to read PMIC ID */ +static int mrstouch_pmic_id(uint *vendor, uint *rev) +{ + int err; + u8 r; + + err = intel_scu_ipc_ioread8(PMIC_REG_ID1, &r); + if (err) + return err; + + *vendor = r & 0x7; + *rev = (r >> 3) & 0x7; + + return 0; +} + +/* + * Parse ADC channels to find end of the channel configured by other ADC user + * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels + */ +static int mrstouch_chan_parse(struct mrstouch_dev *tsdev) +{ + int err, i, j, found; + u32 r32; + + found = -1; + + for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) { + if (found >= 0) + break; + + err = intel_scu_ipc_ioread32(PMICADDR0, &r32); + if (err) + return err; + + for (j = 0; j < 32; j+= 8) { + if (((r32 >> j) & 0xFF) == END_OF_CHANNEL) { + found = i; + break; + } + } + } + if (found < 0) + return 0; + + if (tsdev->vendor == PMIC_VENDOR_FS) { + if (found && found > (MRSTOUCH_MAX_CHANNELS - 18)) + return -ENOSPC; + } else { + if (found && found > (MRSTOUCH_MAX_CHANNELS - 4)) + return -ENOSPC; + } + return found; +} + +/* Utility to enable/disable pendet. + * pendet set to true enables PENDET interrupt + * pendet set to false disables PENDET interrupt + * Also clears RND mask bit +*/ +static int pendet_enable(struct mrstouch_dev *tsdev, bool pendet) +{ + u16 reg; + u8 r; + u8 pendet_enabled = 0; + int retry = 0; + int err; + + err = intel_scu_ipc_ioread16(PMIC_REG_MADCINT, ®); + 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); + if (mrstouchdevp->pendet_thrd) + kthread_stop(mrstouchdevp->pendet_thrd); + kfree(mrstouchdevp); + 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"); diff --git a/drivers/staging/msm/Kconfig b/drivers/staging/msm/Kconfig new file mode 100644 index 000000000000..c57039f2060b --- /dev/null +++ b/drivers/staging/msm/Kconfig @@ -0,0 +1,134 @@ +config MSM_STAGING + tristate "MSM Frame Buffer Support" + depends on FB && ARCH_MSM && !FB_MSM + select FB_BACKLIGHT if FB_MSM_BACKLIGHT + select NEW_LEDS + select LEDS_CLASS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Support for MSM Framebuffer. + +if MSM_STAGING + +config FB_MSM_LCDC_HW + bool + default n + +choice + prompt "MDP HW version" + default FB_MSM_MDP31 + +config FB_MSM_MDP31 + select FB_MSM_LCDC_HW + bool "MDP HW ver3.1" + ---help--- + Support for MSM MDP HW revision 3.1 + Say Y here if this is msm8x50 variant platform. +endchoice + +config FB_MSM_LCDC + bool + default n + +config FB_MSM_TVOUT + bool + default n + +config FB_MSM_LCDC_PANEL + bool + select FB_MSM_LCDC + default n + +config FB_MSM_LCDC_PRISM_WVGA + bool + select FB_MSM_LCDC_PANEL + default n + +config FB_MSM_LCDC_ST1_WXGA + bool + select FB_MSM_LCDC_PANEL + default n + +config FB_MSM_LCDC_ST15_WXGA + bool + select FB_MSM_LCDC_PANEL + default n + +config FB_MSM_LCDC_WXGA + bool + select FB_MSM_LCDC_PANEL + default n + +choice + prompt "LCD Panel" + default FB_MSM_LCDC_ST15_PANEL + +config FB_MSM_LCDC_PRISM_WVGA_PANEL + depends on FB_MSM_LCDC_HW + bool "LCDC Prism WVGA Panel" + select FB_MSM_LCDC_PRISM_WVGA + ---help--- + Support for LCDC Prism WVGA (800x480) panel + + +config FB_MSM_LCDC_ST15_PANEL + depends on FB_MSM_LCDC_HW + bool "LCDC ST1.5 Panel" + select FB_MSM_LCDC_ST15_WXGA + ---help--- + Support for ST1.5 WXGA (1366x768) panel + +config FB_MSM_PANEL_NONE + bool "NONE" + ---help--- + This will disable LCD panel +endchoice + +choice + prompt "Secondary LCD Panel" + depends on FB_MSM_MDP31 + default FB_MSM_SECONDARY_PANEL_NONE + +config FB_MSM_SECONDARY_PANEL_NONE + bool "NONE" + ---help--- + No secondary panel +endchoice + +config FB_MSM_TVOUT_NTSC + bool + select FB_MSM_TVOUT + default n + +config FB_MSM_TVOUT_PAL + bool + select FB_MSM_TVOUT + default n + +choice + depends on (FB_MSM_MDP22 || FB_MSM_MDP31) + prompt "TVOut Region" + default FB_MSM_TVOUT_NTSC_M + +config FB_MSM_TVOUT_NTSC_M + bool "NTSC M" + select FB_MSM_TVOUT_NTSC + ---help--- + Support for NTSC M region (North American and Korea) + +config FB_MSM_TVOUT_NONE + bool "NONE" + ---help--- + This will disable TV Out functionality. +endchoice + +config PMEM_KERNEL_SIZE + int "PMEM for kernel components (in MB)" + default 2 + depends on ARCH_QSD8X50 + help + Configures the amount of PMEM for use by kernel components + (in MB; minimum 2MB) +endif diff --git a/drivers/staging/msm/Makefile b/drivers/staging/msm/Makefile new file mode 100644 index 000000000000..98a0ce177cb2 --- /dev/null +++ b/drivers/staging/msm/Makefile @@ -0,0 +1,93 @@ +obj-y := msm_fb.o staging-devices.o memory.o + +obj-$(CONFIG_FB_MSM_LOGO) += logo.o +obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o + +# MDP +obj-y += mdp.o + +ifeq ($(CONFIG_FB_MSM_MDP40),y) +obj-y += mdp4_util.o +obj-$(CONFIG_DEBUG_FS) += mdp4_debugfs.o +else +obj-y += mdp_hw_init.o +obj-y += mdp_ppp.o +ifeq ($(CONFIG_FB_MSM_MDP31),y) +obj-y += mdp_ppp_v31.o +obj-$(CONFIG_MDP_PPP_ASYNC_OP) += mdp_ppp_dq.o +else +obj-y += mdp_ppp_v20.o +endif +endif + +ifeq ($(CONFIG_FB_MSM_OVERLAY),y) +obj-y += mdp4_overlay.o +obj-y += mdp4_overlay_lcdc.o +obj-y += mdp4_overlay_mddi.o +else +obj-y += mdp_dma_lcdc.o +endif + +obj-y += mdp_dma.o +obj-y += mdp_dma_s.o +obj-y += mdp_vsync.o +obj-y += mdp_cursor.o +obj-y += mdp_dma_tv.o + +# EBI2 +obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o + +# LCDC +obj-$(CONFIG_FB_MSM_LCDC) += lcdc.o + +# MDDI +msm_mddi-objs := mddi.o mddihost.o mddihosti.o +obj-$(CONFIG_FB_MSM_MDDI) += msm_mddi.o + +# External MDDI +msm_mddi_ext-objs := mddihost_e.o mddi_ext.o +obj-$(CONFIG_FB_MSM_EXTMDDI) += msm_mddi_ext.o + +# TVEnc +obj-$(CONFIG_FB_MSM_TVOUT) += tvenc.o + +# MSM FB Panel +obj-y += msm_fb_panel.o +obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_tmd20.o +obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_l2f.o + +ifeq ($(CONFIG_FB_MSM_MDDI_AUTO_DETECT),y) +obj-y += mddi_prism.o +obj-y += mddi_toshiba.o +obj-y += mddi_toshiba_vga.o +obj-y += mddi_toshiba_wvga_pt.o +obj-y += mddi_toshiba_wvga.o +obj-y += mddi_sharp.o +else +obj-$(CONFIG_FB_MSM_MDDI_PRISM_WVGA) += mddi_prism.o +obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON) += mddi_toshiba.o +obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON_VGA) += mddi_toshiba_vga.o +obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA_PORTRAIT) += mddi_toshiba_wvga_pt.o +obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA) += mddi_toshiba_wvga.o +obj-$(CONFIG_FB_MSM_MDDI_SHARP_QVGA_128x128) += mddi_sharp.o +endif + +obj-$(CONFIG_FB_MSM_LCDC_PANEL) += lcdc_panel.o +obj-$(CONFIG_FB_MSM_LCDC_PRISM_WVGA) += lcdc_prism.o +obj-$(CONFIG_FB_MSM_LCDC_EXTERNAL_WXGA) += lcdc_external.o +obj-$(CONFIG_FB_MSM_LCDC_GORDON_VGA) += lcdc_gordon.o +obj-$(CONFIG_FB_MSM_LCDC_WXGA) += lcdc_wxga.o +obj-$(CONFIG_FB_MSM_LCDC_TOSHIBA_WVGA_PT) += lcdc_toshiba_wvga_pt.o +obj-$(CONFIG_FB_MSM_LCDC_SHARP_WVGA_PT) += lcdc_sharp_wvga_pt.o +obj-$(CONFIG_FB_MSM_LCDC_GRAPEFRUIT_VGA) += lcdc_grapefruit.o +obj-$(CONFIG_FB_MSM_LCDC_ST1_WXGA) += lcdc_st1_wxga.o +obj-$(CONFIG_FB_MSM_LCDC_ST15_WXGA) += lcdc_st15.o +obj-$(CONFIG_FB_MSM_HDMI_SII_EXTERNAL_720P) += hdmi_sii9022.o + +obj-$(CONFIG_FB_MSM_TVOUT_NTSC) += tv_ntsc.o +obj-$(CONFIG_FB_MSM_TVOUT_PAL) += tv_pal.o + +obj-$(CONFIG_FB_MSM_EXTMDDI_SVGA) += mddi_ext_lcd.o + +clean: + rm *.o .*cmd diff --git a/drivers/staging/msm/TODO b/drivers/staging/msm/TODO new file mode 100644 index 000000000000..05107a7d516a --- /dev/null +++ b/drivers/staging/msm/TODO @@ -0,0 +1,3 @@ +- Merge this code with the existing MSM framebuffer +- General style clean ups. + diff --git a/drivers/staging/msm/ebi2_l2f.c b/drivers/staging/msm/ebi2_l2f.c new file mode 100644 index 000000000000..eea891d8f0f8 --- /dev/null +++ b/drivers/staging/msm/ebi2_l2f.c @@ -0,0 +1,569 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" + +#include <linux/memory.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include "linux/proc_fs.h" + +#include <linux/delay.h> + +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> + +/* The following are for MSM5100 on Gator +*/ +#ifdef FEATURE_PM1000 +#include "pm1000.h" +#endif /* FEATURE_PM1000 */ +/* The following are for MSM6050 on Bambi +*/ +#ifdef FEATURE_PMIC_LCDKBD_LED_DRIVER +#include "pm.h" +#endif /* FEATURE_PMIC_LCDKBD_LED_DRIVER */ + +#ifdef DISP_DEVICE_18BPP +#undef DISP_DEVICE_18BPP +#define DISP_DEVICE_16BPP +#endif + +#define QCIF_WIDTH 176 +#define QCIF_HEIGHT 220 + +static void *DISP_CMD_PORT; +static void *DISP_DATA_PORT; + +#define DISP_CMD_DISON 0xaf +#define DISP_CMD_DISOFF 0xae +#define DISP_CMD_DISNOR 0xa6 +#define DISP_CMD_DISINV 0xa7 +#define DISP_CMD_DISCTL 0xca +#define DISP_CMD_GCP64 0xcb +#define DISP_CMD_GCP16 0xcc +#define DISP_CMD_GSSET 0xcd +#define DISP_GS_2 0x02 +#define DISP_GS_16 0x01 +#define DISP_GS_64 0x00 +#define DISP_CMD_SLPIN 0x95 +#define DISP_CMD_SLPOUT 0x94 +#define DISP_CMD_SD_PSET 0x75 +#define DISP_CMD_MD_PSET 0x76 +#define DISP_CMD_SD_CSET 0x15 +#define DISP_CMD_MD_CSET 0x16 +#define DISP_CMD_DATCTL 0xbc +#define DISP_DATCTL_666 0x08 +#define DISP_DATCTL_565 0x28 +#define DISP_DATCTL_444 0x38 +#define DISP_CMD_RAMWR 0x5c +#define DISP_CMD_RAMRD 0x5d +#define DISP_CMD_PTLIN 0xa8 +#define DISP_CMD_PTLOUT 0xa9 +#define DISP_CMD_ASCSET 0xaa +#define DISP_CMD_SCSTART 0xab +#define DISP_CMD_VOLCTL 0xc6 +#define DISP_VOLCTL_TONE 0x80 +#define DISP_CMD_NOp 0x25 +#define DISP_CMD_OSSEL 0xd0 +#define DISP_CMD_3500KSET 0xd1 +#define DISP_CMD_3500KEND 0xd2 +#define DISP_CMD_14MSET 0xd3 +#define DISP_CMD_14MEND 0xd4 + +#define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, cmd); + +#define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, data); + +#define DISP_DATA_IN() inpw(DISP_DATA_PORT); + +/* Epson device column number starts at 2 +*/ +#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \ + DISP_CMD_OUT(DISP_CMD_SD_PSET) \ + DISP_DATA_OUT((ulhc_row) & 0xFF) \ + DISP_DATA_OUT((ulhc_row) >> 8) \ + DISP_DATA_OUT((lrhc_row) & 0xFF) \ + DISP_DATA_OUT((lrhc_row) >> 8) \ + DISP_CMD_OUT(DISP_CMD_SD_CSET) \ + DISP_DATA_OUT(((ulhc_col)+2) & 0xFF) \ + DISP_DATA_OUT(((ulhc_col)+2) >> 8) \ + DISP_DATA_OUT(((lrhc_col)+2) & 0xFF) \ + DISP_DATA_OUT(((lrhc_col)+2) >> 8) + +#define DISP_MIN_CONTRAST 0 +#define DISP_MAX_CONTRAST 127 +#define DISP_DEFAULT_CONTRAST 80 + +#define DISP_MIN_BACKLIGHT 0 +#define DISP_MAX_BACKLIGHT 15 +#define DISP_DEFAULT_BACKLIGHT 2 + +#define WAIT_SEC(sec) mdelay((sec)/1000) + +static word disp_area_start_row; +static word disp_area_end_row; +static byte disp_contrast = DISP_DEFAULT_CONTRAST; +static boolean disp_powered_up; +static boolean disp_initialized = FALSE; +/* For some reason the contrast set at init time is not good. Need to do + * it again + */ +static boolean display_on = FALSE; +static void epsonQcif_disp_init(struct platform_device *pdev); +static void epsonQcif_disp_set_contrast(word contrast); +static void epsonQcif_disp_set_display_area(word start_row, word end_row); +static int epsonQcif_disp_off(struct platform_device *pdev); +static int epsonQcif_disp_on(struct platform_device *pdev); +static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres); + +volatile word databack; +static void epsonQcif_disp_init(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd; + + int i; + + if (disp_initialized) + return; + + mfd = platform_get_drvdata(pdev); + + DISP_CMD_PORT = mfd->cmd_port; + DISP_DATA_PORT = mfd->data_port; + + /* Sleep in */ + DISP_CMD_OUT(DISP_CMD_SLPIN); + + /* Display off */ + DISP_CMD_OUT(DISP_CMD_DISOFF); + + /* Display normal */ + DISP_CMD_OUT(DISP_CMD_DISNOR); + + /* Set data mode */ + DISP_CMD_OUT(DISP_CMD_DATCTL); + DISP_DATA_OUT(DISP_DATCTL_565); + + /* Set display timing */ + DISP_CMD_OUT(DISP_CMD_DISCTL); + DISP_DATA_OUT(0x1c); /* p1 */ + DISP_DATA_OUT(0x02); /* p1 */ + DISP_DATA_OUT(0x82); /* p2 */ + DISP_DATA_OUT(0x00); /* p3 */ + DISP_DATA_OUT(0x00); /* p4 */ + DISP_DATA_OUT(0xe0); /* p5 */ + DISP_DATA_OUT(0x00); /* p5 */ + DISP_DATA_OUT(0xdc); /* p6 */ + DISP_DATA_OUT(0x00); /* p6 */ + DISP_DATA_OUT(0x02); /* p7 */ + DISP_DATA_OUT(0x00); /* p8 */ + + /* Set 64 gray scale level */ + DISP_CMD_OUT(DISP_CMD_GCP64); + DISP_DATA_OUT(0x08); /* p01 */ + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x2a); /* p02 */ + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x4e); /* p03 */ + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x6b); /* p04 */ + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x88); /* p05 */ + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0xa3); /* p06 */ + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0xba); /* p07 */ + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0xd1); /* p08 */ + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0xe5); /* p09 */ + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0xf3); /* p10 */ + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x03); /* p11 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x13); /* p12 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x22); /* p13 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x2f); /* p14 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x3b); /* p15 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x46); /* p16 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x51); /* p17 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x5b); /* p18 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x64); /* p19 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x6c); /* p20 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x74); /* p21 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x7c); /* p22 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x83); /* p23 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x8a); /* p24 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x91); /* p25 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x98); /* p26 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x9f); /* p27 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xa6); /* p28 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xac); /* p29 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xb2); /* p30 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xb7); /* p31 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xbc); /* p32 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xc1); /* p33 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xc6); /* p34 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xcb); /* p35 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xd0); /* p36 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xd4); /* p37 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xd8); /* p38 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xdc); /* p39 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xe0); /* p40 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xe4); /* p41 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xe8); /* p42 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xec); /* p43 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xf0); /* p44 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xf4); /* p45 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xf8); /* p46 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xfb); /* p47 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xfe); /* p48 */ + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0x01); /* p49 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x03); /* p50 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x05); /* p51 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x07); /* p52 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x09); /* p53 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x0b); /* p54 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x0d); /* p55 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x0f); /* p56 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x11); /* p57 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x13); /* p58 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x15); /* p59 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x17); /* p60 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x19); /* p61 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x1b); /* p62 */ + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x1c); /* p63 */ + DISP_DATA_OUT(0x02); + + /* Set 16 gray scale level */ + DISP_CMD_OUT(DISP_CMD_GCP16); + DISP_DATA_OUT(0x1a); /* p01 */ + DISP_DATA_OUT(0x32); /* p02 */ + DISP_DATA_OUT(0x42); /* p03 */ + DISP_DATA_OUT(0x4c); /* p04 */ + DISP_DATA_OUT(0x58); /* p05 */ + DISP_DATA_OUT(0x5f); /* p06 */ + DISP_DATA_OUT(0x66); /* p07 */ + DISP_DATA_OUT(0x6b); /* p08 */ + DISP_DATA_OUT(0x70); /* p09 */ + DISP_DATA_OUT(0x74); /* p10 */ + DISP_DATA_OUT(0x78); /* p11 */ + DISP_DATA_OUT(0x7b); /* p12 */ + DISP_DATA_OUT(0x7e); /* p13 */ + DISP_DATA_OUT(0x80); /* p14 */ + DISP_DATA_OUT(0x82); /* p15 */ + + /* Set DSP column */ + DISP_CMD_OUT(DISP_CMD_MD_CSET); + DISP_DATA_OUT(0xff); + DISP_DATA_OUT(0x03); + DISP_DATA_OUT(0xff); + DISP_DATA_OUT(0x03); + + /* Set DSP page */ + DISP_CMD_OUT(DISP_CMD_MD_PSET); + DISP_DATA_OUT(0xff); + DISP_DATA_OUT(0x01); + DISP_DATA_OUT(0xff); + DISP_DATA_OUT(0x01); + + /* Set ARM column */ + DISP_CMD_OUT(DISP_CMD_SD_CSET); + DISP_DATA_OUT(0x02); + DISP_DATA_OUT(0x00); + DISP_DATA_OUT((QCIF_WIDTH + 1) & 0xFF); + DISP_DATA_OUT((QCIF_WIDTH + 1) >> 8); + + /* Set ARM page */ + DISP_CMD_OUT(DISP_CMD_SD_PSET); + DISP_DATA_OUT(0x00); + DISP_DATA_OUT(0x00); + DISP_DATA_OUT((QCIF_HEIGHT - 1) & 0xFF); + DISP_DATA_OUT((QCIF_HEIGHT - 1) >> 8); + + /* Set 64 gray scales */ + DISP_CMD_OUT(DISP_CMD_GSSET); + DISP_DATA_OUT(DISP_GS_64); + + DISP_CMD_OUT(DISP_CMD_OSSEL); + DISP_DATA_OUT(0); + + /* Sleep out */ + DISP_CMD_OUT(DISP_CMD_SLPOUT); + + WAIT_SEC(40000); + + /* Initialize power IC */ + DISP_CMD_OUT(DISP_CMD_VOLCTL); + DISP_DATA_OUT(DISP_VOLCTL_TONE); + + WAIT_SEC(40000); + + /* Set electronic volume, d'xx */ + DISP_CMD_OUT(DISP_CMD_VOLCTL); + DISP_DATA_OUT(DISP_DEFAULT_CONTRAST); /* value from 0 to 127 */ + + /* Initialize display data */ + DISP_SET_RECT(0, (QCIF_HEIGHT - 1), 0, (QCIF_WIDTH - 1)); + DISP_CMD_OUT(DISP_CMD_RAMWR); + for (i = 0; i < QCIF_HEIGHT * QCIF_WIDTH; i++) + DISP_DATA_OUT(0xffff); + + DISP_CMD_OUT(DISP_CMD_RAMRD); + databack = DISP_DATA_IN(); + databack = DISP_DATA_IN(); + databack = DISP_DATA_IN(); + databack = DISP_DATA_IN(); + + WAIT_SEC(80000); + + DISP_CMD_OUT(DISP_CMD_DISON); + + disp_area_start_row = 0; + disp_area_end_row = QCIF_HEIGHT - 1; + disp_powered_up = TRUE; + disp_initialized = TRUE; + epsonQcif_disp_set_display_area(0, QCIF_HEIGHT - 1); + display_on = TRUE; +} + +static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres) +{ + if (!disp_initialized) + return; + + DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1); + DISP_CMD_OUT(DISP_CMD_RAMWR); +} + +static void epsonQcif_disp_set_display_area(word start_row, word end_row) +{ + if (!disp_initialized) + return; + + if ((start_row == disp_area_start_row) + && (end_row == disp_area_end_row)) + return; + disp_area_start_row = start_row; + disp_area_end_row = end_row; + + /* Range checking + */ + if (end_row >= QCIF_HEIGHT) + end_row = QCIF_HEIGHT - 1; + if (start_row > end_row) + start_row = end_row; + + /* When display is not the full screen, gray scale is set to + ** 2; otherwise it is set to 64. + */ + if ((start_row == 0) && (end_row == (QCIF_HEIGHT - 1))) { + /* The whole screen */ + DISP_CMD_OUT(DISP_CMD_PTLOUT); + WAIT_SEC(10000); + DISP_CMD_OUT(DISP_CMD_DISOFF); + WAIT_SEC(100000); + DISP_CMD_OUT(DISP_CMD_GSSET); + DISP_DATA_OUT(DISP_GS_64); + WAIT_SEC(100000); + DISP_CMD_OUT(DISP_CMD_DISON); + } else { + /* partial screen */ + DISP_CMD_OUT(DISP_CMD_PTLIN); + DISP_DATA_OUT(start_row); + DISP_DATA_OUT(start_row >> 8); + DISP_DATA_OUT(end_row); + DISP_DATA_OUT(end_row >> 8); + DISP_CMD_OUT(DISP_CMD_GSSET); + DISP_DATA_OUT(DISP_GS_2); + } +} + +static int epsonQcif_disp_off(struct platform_device *pdev) +{ + if (!disp_initialized) + epsonQcif_disp_init(pdev); + + if (display_on) { + DISP_CMD_OUT(DISP_CMD_DISOFF); + DISP_CMD_OUT(DISP_CMD_SLPIN); + display_on = FALSE; + } + + return 0; +} + +static int epsonQcif_disp_on(struct platform_device *pdev) +{ + if (!disp_initialized) + epsonQcif_disp_init(pdev); + + if (!display_on) { + DISP_CMD_OUT(DISP_CMD_SLPOUT); + WAIT_SEC(40000); + DISP_CMD_OUT(DISP_CMD_DISON); + epsonQcif_disp_set_contrast(disp_contrast); + display_on = TRUE; + } + + return 0; +} + +static void epsonQcif_disp_set_contrast(word contrast) +{ + if (!disp_initialized) + return; + + /* Initialize power IC, d'24 */ + DISP_CMD_OUT(DISP_CMD_VOLCTL); + DISP_DATA_OUT(DISP_VOLCTL_TONE); + + WAIT_SEC(40000); + + /* Set electronic volume, d'xx */ + DISP_CMD_OUT(DISP_CMD_VOLCTL); + if (contrast > 127) + contrast = 127; + DISP_DATA_OUT(contrast); /* value from 0 to 127 */ + disp_contrast = (byte) contrast; +} /* End disp_set_contrast */ + +static void epsonQcif_disp_clear_screen_area( + word start_row, word end_row, word start_column, word end_column) { + int32 i; + + /* Clear the display screen */ + DISP_SET_RECT(start_row, end_row, start_column, end_column); + DISP_CMD_OUT(DISP_CMD_RAMWR); + i = (end_row - start_row + 1) * (end_column - start_column + 1); + for (; i > 0; i--) + DISP_DATA_OUT(0xffff); +} + +static int __init epsonQcif_probe(struct platform_device *pdev) +{ + msm_fb_add_device(pdev); + + return 0; +} + +static struct platform_driver this_driver = { + .probe = epsonQcif_probe, + .driver = { + .name = "ebi2_epson_qcif", + }, +}; + +static struct msm_fb_panel_data epsonQcif_panel_data = { + .on = epsonQcif_disp_on, + .off = epsonQcif_disp_off, + .set_rect = epsonQcif_disp_set_rect, +}; + +static struct platform_device this_device = { + .name = "ebi2_epson_qcif", + .id = 0, + .dev = { + .platform_data = &epsonQcif_panel_data, + } +}; + +static int __init epsonQcif_init(void) +{ + int ret; + struct msm_panel_info *pinfo; + + ret = platform_driver_register(&this_driver); + if (!ret) { + pinfo = &epsonQcif_panel_data.panel_info; + pinfo->xres = QCIF_WIDTH; + pinfo->yres = QCIF_HEIGHT; + pinfo->type = EBI2_PANEL; + pinfo->pdest = DISPLAY_2; + pinfo->wait_cycle = 0x808000; + pinfo->bpp = 16; + pinfo->fb_num = 2; + pinfo->lcd.vsync_enable = FALSE; + + ret = platform_device_register(&this_device); + if (ret) + platform_driver_unregister(&this_driver); + } + + return ret; +} + +module_init(epsonQcif_init); diff --git a/drivers/staging/msm/ebi2_lcd.c b/drivers/staging/msm/ebi2_lcd.c new file mode 100644 index 000000000000..b41e1230ceca --- /dev/null +++ b/drivers/staging/msm/ebi2_lcd.c @@ -0,0 +1,250 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/mm.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> +#include <linux/uaccess.h> +#include <linux/workqueue.h> +#include <linux/string.h> +#include <linux/version.h> +#include <linux/proc_fs.h> +#include <linux/vmalloc.h> +#include <linux/debugfs.h> + +#include "msm_fb.h" + +static int ebi2_lcd_probe(struct platform_device *pdev); +static int ebi2_lcd_remove(struct platform_device *pdev); + +static struct platform_driver ebi2_lcd_driver = { + .probe = ebi2_lcd_probe, + .remove = ebi2_lcd_remove, + .suspend = NULL, + .suspend_late = NULL, + .resume_early = NULL, + .resume = NULL, + .shutdown = NULL, + .driver = { + .name = "ebi2_lcd", + }, +}; + +static void *ebi2_base; +static void *ebi2_lcd_cfg0; +static void *ebi2_lcd_cfg1; +static void __iomem *lcd01_base; +static void __iomem *lcd02_base; +static int ebi2_lcd_resource_initialized; + +static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; +static int pdev_list_cnt; + +static int ebi2_lcd_probe(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd; + struct platform_device *mdp_dev = NULL; + struct msm_fb_panel_data *pdata = NULL; + int rc, i; + + if (pdev->id == 0) { + for (i = 0; i < pdev->num_resources; i++) { + if (!strncmp(pdev->resource[i].name, "base", 4)) { + ebi2_base = ioremap(pdev->resource[i].start, + pdev->resource[i].end - + pdev->resource[i].start + 1); + if (!ebi2_base) { + printk(KERN_ERR + "ebi2_base ioremap failed!\n"); + return -ENOMEM; + } + ebi2_lcd_cfg0 = (void *)(ebi2_base + 0x20); + ebi2_lcd_cfg1 = (void *)(ebi2_base + 0x24); + } else if (!strncmp(pdev->resource[i].name, + "lcd01", 5)) { + lcd01_base = ioremap(pdev->resource[i].start, + pdev->resource[i].end - + pdev->resource[i].start + 1); + if (!lcd01_base) { + printk(KERN_ERR + "lcd01_base ioremap failed!\n"); + return -ENOMEM; + } + } else if (!strncmp(pdev->resource[i].name, + "lcd02", 5)) { + lcd02_base = ioremap(pdev->resource[i].start, + pdev->resource[i].end - + pdev->resource[i].start + 1); + if (!lcd02_base) { + printk(KERN_ERR + "lcd02_base ioremap failed!\n"); + return -ENOMEM; + } + } + } + ebi2_lcd_resource_initialized = 1; + return 0; + } + + if (!ebi2_lcd_resource_initialized) + return -EPERM; + + mfd = platform_get_drvdata(pdev); + + if (!mfd) + return -ENODEV; + + if (mfd->key != MFD_KEY) + return -EINVAL; + + if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) + return -ENOMEM; + + if (ebi2_base == NULL) + return -ENOMEM; + + mdp_dev = platform_device_alloc("mdp", pdev->id); + if (!mdp_dev) + return -ENOMEM; + + /* link to the latest pdev */ + mfd->pdev = mdp_dev; + mfd->dest = DISPLAY_LCD; + + /* add panel data */ + if (platform_device_add_data + (mdp_dev, pdev->dev.platform_data, + sizeof(struct msm_fb_panel_data))) { + printk(KERN_ERR "ebi2_lcd_probe: platform_device_add_data failed!\n"); + platform_device_put(mdp_dev); + return -ENOMEM; + } + + /* data chain */ + pdata = mdp_dev->dev.platform_data; + pdata->on = panel_next_on; + pdata->off = panel_next_off; + pdata->next = pdev; + + /* get/set panel specific fb info */ + mfd->panel_info = pdata->panel_info; + + if (mfd->panel_info.bpp == 24) + mfd->fb_imgType = MDP_RGB_888; + else + mfd->fb_imgType = MDP_RGB_565; + + /* config msm ebi2 lcd register */ + if (mfd->panel_info.pdest == DISPLAY_1) { + outp32(ebi2_base, + (inp32(ebi2_base) & (~(EBI2_PRIM_LCD_CLR))) | + EBI2_PRIM_LCD_SEL); + /* + * current design has one set of cfg0/1 register to control + * both EBI2 channels. so, we're using the PRIM channel to + * configure both. + */ + outp32(ebi2_lcd_cfg0, mfd->panel_info.wait_cycle); + if (mfd->panel_info.bpp == 18) + outp32(ebi2_lcd_cfg1, 0x01000000); + else + outp32(ebi2_lcd_cfg1, 0x0); + } else { +#ifdef DEBUG_EBI2_LCD + /* + * confliting with QCOM SURF FPGA CS. + * OEM should enable below for their CS mapping + */ + outp32(ebi2_base, (inp32(ebi2_base)&(~(EBI2_SECD_LCD_CLR))) + |EBI2_SECD_LCD_SEL); +#endif + } + + /* + * map cs (chip select) address + */ + if (mfd->panel_info.pdest == DISPLAY_1) { + mfd->cmd_port = lcd01_base; + mfd->data_port = + (void *)((uint32) mfd->cmd_port + EBI2_PRIM_LCD_RS_PIN); + mfd->data_port_phys = + (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN); + } else { + mfd->cmd_port = lcd01_base; + mfd->data_port = + (void *)((uint32) mfd->cmd_port + EBI2_SECD_LCD_RS_PIN); + mfd->data_port_phys = + (void *)(LCD_SECD_BASE_PHYS + EBI2_SECD_LCD_RS_PIN); + } + + /* + * set driver data + */ + platform_set_drvdata(mdp_dev, mfd); + + /* + * register in mdp driver + */ + rc = platform_device_add(mdp_dev); + if (rc) { + goto ebi2_lcd_probe_err; + } + + pdev_list[pdev_list_cnt++] = pdev; + return 0; + + ebi2_lcd_probe_err: + platform_device_put(mdp_dev); + return rc; +} + +static int ebi2_lcd_remove(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd; + + mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); + + if (!mfd) + return 0; + + if (mfd->key != MFD_KEY) + return 0; + + iounmap(mfd->cmd_port); + + return 0; +} + +static int ebi2_lcd_register_driver(void) +{ + return platform_driver_register(&ebi2_lcd_driver); +} + +static int __init ebi2_lcd_driver_init(void) +{ + return ebi2_lcd_register_driver(); +} + +module_init(ebi2_lcd_driver_init);
\ No newline at end of file diff --git a/drivers/staging/msm/ebi2_tmd20.c b/drivers/staging/msm/ebi2_tmd20.c new file mode 100644 index 000000000000..d66d03978253 --- /dev/null +++ b/drivers/staging/msm/ebi2_tmd20.c @@ -0,0 +1,1122 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" + +#include <linux/memory.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include "linux/proc_fs.h" + +#include <linux/delay.h> + +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> + +/* #define TMD20QVGA_LCD_18BPP */ +#define QVGA_WIDTH 240 +#define QVGA_HEIGHT 320 + +#ifdef TMD20QVGA_LCD_18BPP +#define DISP_QVGA_18BPP(x) ((((x)<<2) & 0x3FC00)|(( (x)<<1)& 0x1FE)) +#define DISP_REG(name) uint32 register_##name; +#define OUTPORT(x, y) outpdw(x, y) +#define INPORT(x) inpdw(x) +#else +#define DISP_QVGA_18BPP(x) (x) +#define DISP_REG(name) uint16 register_##name; +#define OUTPORT(x, y) outpw(x, y) +#define INPORT(x) intpw(x) +#endif + +static void *DISP_CMD_PORT; +static void *DISP_DATA_PORT; + +#define DISP_RNTI 0x10 + +#define DISP_CMD_OUT(cmd) OUTPORT(DISP_CMD_PORT, DISP_QVGA_18BPP(cmd)) +#define DISP_DATA_OUT(data) OUTPORT(DISP_DATA_PORT, data) +#define DISP_DATA_IN() INPORT(DISP_DATA_PORT) + +#if (defined(TMD20QVGA_LCD_18BPP)) +#define DISP_DATA_OUT_16TO18BPP(x) \ + DISP_DATA_OUT((((x)&0xf800)<<2|((x)&0x80000)>>3) \ + | (((x)&0x7e0)<<1) \ + | (((x)&0x1F)<<1|((x)&0x10)>>4)) +#else +#define DISP_DATA_OUT_16TO18BPP(x) \ + DISP_DATA_OUT(x) +#endif + +#define DISP_WRITE_OUT(addr, data) \ + register_##addr = DISP_QVGA_18BPP(data); \ + DISP_CMD_OUT(addr); \ + DISP_DATA_OUT(register_##addr); + +#define DISP_UPDATE_VALUE(addr, bitmask, data) \ + DISP_WRITE_OUT(##addr, (register_##addr & ~(bitmask)) | (data)); + +#define DISP_VAL_IF(bitvalue, bitmask) \ + ((bitvalue) ? (bitmask) : 0) + +/* QVGA = 256 x 320 */ +/* actual display is 240 x 320...offset by 0x10 */ +#define DISP_ROW_COL_TO_ADDR(row, col) ((row) * 0x100 + col) +#define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \ + { \ + DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \ + DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, (lrhc_col) + tmd20qvga_panel_offset); \ + DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, (ulhc_row)); \ + DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, (lrhc_row)); \ + DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \ + DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, (ulhc_row)); \ + } + +#define WAIT_MSEC(msec) mdelay(msec) + +/* + * TMD QVGA Address + */ +/* Display Control */ +#define DISP_START_OSCILLATION_ADDR 0x000 +DISP_REG(DISP_START_OSCILLATION_ADDR) +#define DISP_DRIVER_OUTPUT_CTL_ADDR 0x001 + DISP_REG(DISP_DRIVER_OUTPUT_CTL_ADDR) +#define DISP_LCD_DRIVING_SIG_ADDR 0x002 + DISP_REG(DISP_LCD_DRIVING_SIG_ADDR) +#define DISP_ENTRY_MODE_ADDR 0x003 + DISP_REG(DISP_ENTRY_MODE_ADDR) +#define DISP_DISPLAY_CTL_1_ADDR 0x007 + DISP_REG(DISP_DISPLAY_CTL_1_ADDR) +#define DISP_DISPLAY_CTL_2_ADDR 0x008 + DISP_REG(DISP_DISPLAY_CTL_2_ADDR) + +/* DISPLAY MODE 0x009 partial display not supported */ +#define DISP_POWER_SUPPLY_INTF_ADDR 0x00A + DISP_REG(DISP_POWER_SUPPLY_INTF_ADDR) + +/* DISPLAY MODE 0x00B xZoom feature is not supported */ +#define DISP_EXT_DISPLAY_CTL_1_ADDR 0x00C + DISP_REG(DISP_EXT_DISPLAY_CTL_1_ADDR) + +#define DISP_FRAME_CYCLE_CTL_ADDR 0x00D + DISP_REG(DISP_FRAME_CYCLE_CTL_ADDR) + +#define DISP_EXT_DISPLAY_CTL_2_ADDR 0x00E + DISP_REG(DISP_EXT_DISPLAY_CTL_2_ADDR) + +#define DISP_EXT_DISPLAY_CTL_3_ADDR 0x00F + DISP_REG(DISP_EXT_DISPLAY_CTL_3_ADDR) + +#define DISP_LTPS_CTL_1_ADDR 0x012 + DISP_REG(DISP_LTPS_CTL_1_ADDR) +#define DISP_LTPS_CTL_2_ADDR 0x013 + DISP_REG(DISP_LTPS_CTL_2_ADDR) +#define DISP_LTPS_CTL_3_ADDR 0x014 + DISP_REG(DISP_LTPS_CTL_3_ADDR) +#define DISP_LTPS_CTL_4_ADDR 0x018 + DISP_REG(DISP_LTPS_CTL_4_ADDR) +#define DISP_LTPS_CTL_5_ADDR 0x019 + DISP_REG(DISP_LTPS_CTL_5_ADDR) +#define DISP_LTPS_CTL_6_ADDR 0x01A + DISP_REG(DISP_LTPS_CTL_6_ADDR) +#define DISP_AMP_SETTING_ADDR 0x01C + DISP_REG(DISP_AMP_SETTING_ADDR) +#define DISP_MODE_SETTING_ADDR 0x01D + DISP_REG(DISP_MODE_SETTING_ADDR) +#define DISP_POFF_LN_SETTING_ADDR 0x01E + DISP_REG(DISP_POFF_LN_SETTING_ADDR) +/* Power Contol */ +#define DISP_POWER_CTL_1_ADDR 0x100 + DISP_REG(DISP_POWER_CTL_1_ADDR) +#define DISP_POWER_CTL_2_ADDR 0x101 + DISP_REG(DISP_POWER_CTL_2_ADDR) +#define DISP_POWER_CTL_3_ADDR 0x102 + DISP_REG(DISP_POWER_CTL_3_ADDR) +#define DISP_POWER_CTL_4_ADDR 0x103 + DISP_REG(DISP_POWER_CTL_4_ADDR) +#define DISP_POWER_CTL_5_ADDR 0x104 + DISP_REG(DISP_POWER_CTL_5_ADDR) +#define DISP_POWER_CTL_6_ADDR 0x105 + DISP_REG(DISP_POWER_CTL_6_ADDR) +#define DISP_POWER_CTL_7_ADDR 0x106 + DISP_REG(DISP_POWER_CTL_7_ADDR) +/* RAM Access */ +#define DISP_RAM_ADDR_SET_1_ADDR 0x200 + DISP_REG(DISP_RAM_ADDR_SET_1_ADDR) +#define DISP_RAM_ADDR_SET_2_ADDR 0x201 + DISP_REG(DISP_RAM_ADDR_SET_2_ADDR) +#define DISP_CMD_RAMRD DISP_CMD_RAMWR +#define DISP_CMD_RAMWR 0x202 + DISP_REG(DISP_CMD_RAMWR) +#define DISP_RAM_DATA_MASK_1_ADDR 0x203 + DISP_REG(DISP_RAM_DATA_MASK_1_ADDR) +#define DISP_RAM_DATA_MASK_2_ADDR 0x204 + DISP_REG(DISP_RAM_DATA_MASK_2_ADDR) +/* Gamma Control, Contrast, Gray Scale Setting */ +#define DISP_GAMMA_CONTROL_1_ADDR 0x300 + DISP_REG(DISP_GAMMA_CONTROL_1_ADDR) +#define DISP_GAMMA_CONTROL_2_ADDR 0x301 + DISP_REG(DISP_GAMMA_CONTROL_2_ADDR) +#define DISP_GAMMA_CONTROL_3_ADDR 0x302 + DISP_REG(DISP_GAMMA_CONTROL_3_ADDR) +#define DISP_GAMMA_CONTROL_4_ADDR 0x303 + DISP_REG(DISP_GAMMA_CONTROL_4_ADDR) +#define DISP_GAMMA_CONTROL_5_ADDR 0x304 + DISP_REG(DISP_GAMMA_CONTROL_5_ADDR) +/* Coordinate Control */ +#define DISP_VERT_SCROLL_CTL_1_ADDR 0x400 + DISP_REG(DISP_VERT_SCROLL_CTL_1_ADDR) +#define DISP_VERT_SCROLL_CTL_2_ADDR 0x401 + DISP_REG(DISP_VERT_SCROLL_CTL_2_ADDR) +#define DISP_SCREEN_1_DRV_POS_1_ADDR 0x402 + DISP_REG(DISP_SCREEN_1_DRV_POS_1_ADDR) +#define DISP_SCREEN_1_DRV_POS_2_ADDR 0x403 + DISP_REG(DISP_SCREEN_1_DRV_POS_2_ADDR) +#define DISP_SCREEN_2_DRV_POS_1_ADDR 0x404 + DISP_REG(DISP_SCREEN_2_DRV_POS_1_ADDR) +#define DISP_SCREEN_2_DRV_POS_2_ADDR 0x405 + DISP_REG(DISP_SCREEN_2_DRV_POS_2_ADDR) +#define DISP_HORZ_RAM_ADDR_POS_1_ADDR 0x406 + DISP_REG(DISP_HORZ_RAM_ADDR_POS_1_ADDR) +#define DISP_HORZ_RAM_ADDR_POS_2_ADDR 0x407 + DISP_REG(DISP_HORZ_RAM_ADDR_POS_2_ADDR) +#define DISP_VERT_RAM_ADDR_POS_1_ADDR 0x408 + DISP_REG(DISP_VERT_RAM_ADDR_POS_1_ADDR) +#define DISP_VERT_RAM_ADDR_POS_2_ADDR 0x409 + DISP_REG(DISP_VERT_RAM_ADDR_POS_2_ADDR) +#define DISP_TMD_700_ADDR 0x700 /* 0x700 */ + DISP_REG(DISP_TMD_700_ADDR) +#define DISP_TMD_015_ADDR 0x015 /* 0x700 */ + DISP_REG(DISP_TMD_015_ADDR) +#define DISP_TMD_305_ADDR 0x305 /* 0x700 */ + DISP_REG(DISP_TMD_305_ADDR) + +/* + * TMD QVGA Bit Definations + */ + +#define DISP_BIT_IB15 0x8000 +#define DISP_BIT_IB14 0x4000 +#define DISP_BIT_IB13 0x2000 +#define DISP_BIT_IB12 0x1000 +#define DISP_BIT_IB11 0x0800 +#define DISP_BIT_IB10 0x0400 +#define DISP_BIT_IB09 0x0200 +#define DISP_BIT_IB08 0x0100 +#define DISP_BIT_IB07 0x0080 +#define DISP_BIT_IB06 0x0040 +#define DISP_BIT_IB05 0x0020 +#define DISP_BIT_IB04 0x0010 +#define DISP_BIT_IB03 0x0008 +#define DISP_BIT_IB02 0x0004 +#define DISP_BIT_IB01 0x0002 +#define DISP_BIT_IB00 0x0001 +/* + * Display Control + * DISP_START_OSCILLATION_ADDR Start Oscillation + * DISP_DRIVER_OUTPUT_CTL_ADDR Driver Output Control + */ +#define DISP_BITMASK_SS DISP_BIT_IB08 +#define DISP_BITMASK_NL5 DISP_BIT_IB05 +#define DISP_BITMASK_NL4 DISP_BIT_IB04 +#define DISP_BITMASK_NL3 DISP_BIT_IB03 +#define DISP_BITMASK_NL2 DISP_BIT_IB02 +#define DISP_BITMASK_NL1 DISP_BIT_IB01 +#define DISP_BITMASK_NL0 DISP_BIT_IB00 +/* DISP_LCD_DRIVING_SIG_ADDR LCD Driving Signal Setting */ +#define DISP_BITMASK_BC DISP_BIT_IB09 +/* DISP_ENTRY_MODE_ADDR Entry Mode */ +#define DISP_BITMASK_TRI DISP_BIT_IB15 +#define DISP_BITMASK_DFM1 DISP_BIT_IB14 +#define DISP_BITMASK_DFM0 DISP_BIT_IB13 +#define DISP_BITMASK_BGR DISP_BIT_IB12 +#define DISP_BITMASK_HWM0 DISP_BIT_IB08 +#define DISP_BITMASK_ID1 DISP_BIT_IB05 +#define DISP_BITMASK_ID0 DISP_BIT_IB04 +#define DISP_BITMASK_AM DISP_BIT_IB03 +/* DISP_DISPLAY_CTL_1_ADDR Display Control (1) */ +#define DISP_BITMASK_COL1 DISP_BIT_IB15 +#define DISP_BITMASK_COL0 DISP_BIT_IB14 +#define DISP_BITMASK_VLE2 DISP_BIT_IB10 +#define DISP_BITMASK_VLE1 DISP_BIT_IB09 +#define DISP_BITMASK_SPT DISP_BIT_IB08 +#define DISP_BITMASK_PT1 DISP_BIT_IB07 +#define DISP_BITMASK_PT0 DISP_BIT_IB06 +#define DISP_BITMASK_REV DISP_BIT_IB02 +/* DISP_DISPLAY_CTL_2_ADDR Display Control (2) */ +#define DISP_BITMASK_FP3 DISP_BIT_IB11 +#define DISP_BITMASK_FP2 DISP_BIT_IB10 +#define DISP_BITMASK_FP1 DISP_BIT_IB09 +#define DISP_BITMASK_FP0 DISP_BIT_IB08 +#define DISP_BITMASK_BP3 DISP_BIT_IB03 +#define DISP_BITMASK_BP2 DISP_BIT_IB02 +#define DISP_BITMASK_BP1 DISP_BIT_IB01 +#define DISP_BITMASK_BP0 DISP_BIT_IB00 +/* DISP_POWER_SUPPLY_INTF_ADDR Power Supply IC Interface Control */ +#define DISP_BITMASK_CSE DISP_BIT_IB12 +#define DISP_BITMASK_TE DISP_BIT_IB08 +#define DISP_BITMASK_IX3 DISP_BIT_IB03 +#define DISP_BITMASK_IX2 DISP_BIT_IB02 +#define DISP_BITMASK_IX1 DISP_BIT_IB01 +#define DISP_BITMASK_IX0 DISP_BIT_IB00 +/* DISP_EXT_DISPLAY_CTL_1_ADDR External Display Interface Control (1) */ +#define DISP_BITMASK_RM DISP_BIT_IB08 +#define DISP_BITMASK_DM1 DISP_BIT_IB05 +#define DISP_BITMASK_DM0 DISP_BIT_IB04 +#define DISP_BITMASK_RIM1 DISP_BIT_IB01 +#define DISP_BITMASK_RIM0 DISP_BIT_IB00 +/* DISP_FRAME_CYCLE_CTL_ADDR Frame Frequency Adjustment Control */ +#define DISP_BITMASK_DIVI1 DISP_BIT_IB09 +#define DISP_BITMASK_DIVI0 DISP_BIT_IB08 +#define DISP_BITMASK_RTNI4 DISP_BIT_IB04 +#define DISP_BITMASK_RTNI3 DISP_BIT_IB03 +#define DISP_BITMASK_RTNI2 DISP_BIT_IB02 +#define DISP_BITMASK_RTNI1 DISP_BIT_IB01 +#define DISP_BITMASK_RTNI0 DISP_BIT_IB00 +/* DISP_EXT_DISPLAY_CTL_2_ADDR External Display Interface Control (2) */ +#define DISP_BITMASK_DIVE1 DISP_BIT_IB09 +#define DISP_BITMASK_DIVE0 DISP_BIT_IB08 +#define DISP_BITMASK_RTNE7 DISP_BIT_IB07 +#define DISP_BITMASK_RTNE6 DISP_BIT_IB06 +#define DISP_BITMASK_RTNE5 DISP_BIT_IB05 +#define DISP_BITMASK_RTNE4 DISP_BIT_IB04 +#define DISP_BITMASK_RTNE3 DISP_BIT_IB03 +#define DISP_BITMASK_RTNE2 DISP_BIT_IB02 +#define DISP_BITMASK_RTNE1 DISP_BIT_IB01 +#define DISP_BITMASK_RTNE0 DISP_BIT_IB00 +/* DISP_EXT_DISPLAY_CTL_3_ADDR External Display Interface Control (3) */ +#define DISP_BITMASK_VSPL DISP_BIT_IB04 +#define DISP_BITMASK_HSPL DISP_BIT_IB03 +#define DISP_BITMASK_VPL DISP_BIT_IB02 +#define DISP_BITMASK_EPL DISP_BIT_IB01 +#define DISP_BITMASK_DPL DISP_BIT_IB00 +/* DISP_LTPS_CTL_1_ADDR LTPS Interface Control (1) */ +#define DISP_BITMASK_CLWI3 DISP_BIT_IB11 +#define DISP_BITMASK_CLWI2 DISP_BIT_IB10 +#define DISP_BITMASK_CLWI1 DISP_BIT_IB09 +#define DISP_BITMASK_CLWI0 DISP_BIT_IB08 +#define DISP_BITMASK_CLTI1 DISP_BIT_IB01 +#define DISP_BITMASK_CLTI0 DISP_BIT_IB00 +/* DISP_LTPS_CTL_2_ADDR LTPS Interface Control (2) */ +#define DISP_BITMASK_OEVBI1 DISP_BIT_IB09 +#define DISP_BITMASK_OEVBI0 DISP_BIT_IB08 +#define DISP_BITMASK_OEVFI1 DISP_BIT_IB01 +#define DISP_BITMASK_OEVFI0 DISP_BIT_IB00 +/* DISP_LTPS_CTL_3_ADDR LTPS Interface Control (3) */ +#define DISP_BITMASK_SHI1 DISP_BIT_IB01 +#define DISP_BITMASK_SHI0 DISP_BIT_IB00 +/* DISP_LTPS_CTL_4_ADDR LTPS Interface Control (4) */ +#define DISP_BITMASK_CLWE5 DISP_BIT_IB13 +#define DISP_BITMASK_CLWE4 DISP_BIT_IB12 +#define DISP_BITMASK_CLWE3 DISP_BIT_IB11 +#define DISP_BITMASK_CLWE2 DISP_BIT_IB10 +#define DISP_BITMASK_CLWE1 DISP_BIT_IB09 +#define DISP_BITMASK_CLWE0 DISP_BIT_IB08 +#define DISP_BITMASK_CLTE3 DISP_BIT_IB03 +#define DISP_BITMASK_CLTE2 DISP_BIT_IB02 +#define DISP_BITMASK_CLTE1 DISP_BIT_IB01 +#define DISP_BITMASK_CLTE0 DISP_BIT_IB00 +/* DISP_LTPS_CTL_5_ADDR LTPS Interface Control (5) */ +#define DISP_BITMASK_OEVBE3 DISP_BIT_IB11 +#define DISP_BITMASK_OEVBE2 DISP_BIT_IB10 +#define DISP_BITMASK_OEVBE1 DISP_BIT_IB09 +#define DISP_BITMASK_OEVBE0 DISP_BIT_IB08 +#define DISP_BITMASK_OEVFE3 DISP_BIT_IB03 +#define DISP_BITMASK_OEVFE2 DISP_BIT_IB02 +#define DISP_BITMASK_OEVFE1 DISP_BIT_IB01 +#define DISP_BITMASK_OEVFE0 DISP_BIT_IB00 +/* DISP_LTPS_CTL_6_ADDR LTPS Interface Control (6) */ +#define DISP_BITMASK_SHE3 DISP_BIT_IB03 +#define DISP_BITMASK_SHE2 DISP_BIT_IB02 +#define DISP_BITMASK_SHE1 DISP_BIT_IB01 +#define DISP_BITMASK_SHE0 DISP_BIT_IB00 +/* DISP_AMP_SETTING_ADDR Amplify Setting */ +#define DISP_BITMASK_ABSW1 DISP_BIT_IB01 +#define DISP_BITMASK_ABSW0 DISP_BIT_IB00 +/* DISP_MODE_SETTING_ADDR Mode Setting */ +#define DISP_BITMASK_DSTB DISP_BIT_IB02 +#define DISP_BITMASK_STB DISP_BIT_IB00 +/* DISP_POFF_LN_SETTING_ADDR Power Off Line Setting */ +#define DISP_BITMASK_POFH3 DISP_BIT_IB03 +#define DISP_BITMASK_POFH2 DISP_BIT_IB02 +#define DISP_BITMASK_POFH1 DISP_BIT_IB01 +#define DISP_BITMASK_POFH0 DISP_BIT_IB00 + +/* Power Contol */ +/* DISP_POWER_CTL_1_ADDR Power Control (1) */ +#define DISP_BITMASK_PO DISP_BIT_IB11 +#define DISP_BITMASK_VCD DISP_BIT_IB09 +#define DISP_BITMASK_VSC DISP_BIT_IB08 +#define DISP_BITMASK_CON DISP_BIT_IB07 +#define DISP_BITMASK_ASW1 DISP_BIT_IB06 +#define DISP_BITMASK_ASW0 DISP_BIT_IB05 +#define DISP_BITMASK_OEV DISP_BIT_IB04 +#define DISP_BITMASK_OEVE DISP_BIT_IB03 +#define DISP_BITMASK_FR DISP_BIT_IB02 +#define DISP_BITMASK_D1 DISP_BIT_IB01 +#define DISP_BITMASK_D0 DISP_BIT_IB00 +/* DISP_POWER_CTL_2_ADDR Power Control (2) */ +#define DISP_BITMASK_DC4 DISP_BIT_IB15 +#define DISP_BITMASK_DC3 DISP_BIT_IB14 +#define DISP_BITMASK_SAP2 DISP_BIT_IB13 +#define DISP_BITMASK_SAP1 DISP_BIT_IB12 +#define DISP_BITMASK_SAP0 DISP_BIT_IB11 +#define DISP_BITMASK_BT2 DISP_BIT_IB10 +#define DISP_BITMASK_BT1 DISP_BIT_IB09 +#define DISP_BITMASK_BT0 DISP_BIT_IB08 +#define DISP_BITMASK_DC2 DISP_BIT_IB07 +#define DISP_BITMASK_DC1 DISP_BIT_IB06 +#define DISP_BITMASK_DC0 DISP_BIT_IB05 +#define DISP_BITMASK_AP2 DISP_BIT_IB04 +#define DISP_BITMASK_AP1 DISP_BIT_IB03 +#define DISP_BITMASK_AP0 DISP_BIT_IB02 +/* DISP_POWER_CTL_3_ADDR Power Control (3) */ +#define DISP_BITMASK_VGL4 DISP_BIT_IB10 +#define DISP_BITMASK_VGL3 DISP_BIT_IB09 +#define DISP_BITMASK_VGL2 DISP_BIT_IB08 +#define DISP_BITMASK_VGL1 DISP_BIT_IB07 +#define DISP_BITMASK_VGL0 DISP_BIT_IB06 +#define DISP_BITMASK_VGH4 DISP_BIT_IB04 +#define DISP_BITMASK_VGH3 DISP_BIT_IB03 +#define DISP_BITMASK_VGH2 DISP_BIT_IB02 +#define DISP_BITMASK_VGH1 DISP_BIT_IB01 +#define DISP_BITMASK_VGH0 DISP_BIT_IB00 +/* DISP_POWER_CTL_4_ADDR Power Control (4) */ +#define DISP_BITMASK_VC2 DISP_BIT_IB02 +#define DISP_BITMASK_VC1 DISP_BIT_IB01 +#define DISP_BITMASK_VC0 DISP_BIT_IB00 +/* DISP_POWER_CTL_5_ADDR Power Control (5) */ +#define DISP_BITMASK_VRL3 DISP_BIT_IB11 +#define DISP_BITMASK_VRL2 DISP_BIT_IB10 +#define DISP_BITMASK_VRL1 DISP_BIT_IB09 +#define DISP_BITMASK_VRL0 DISP_BIT_IB08 +#define DISP_BITMASK_PON DISP_BIT_IB04 +#define DISP_BITMASK_VRH3 DISP_BIT_IB03 +#define DISP_BITMASK_VRH2 DISP_BIT_IB02 +#define DISP_BITMASK_VRH1 DISP_BIT_IB01 +#define DISP_BITMASK_VRH0 DISP_BIT_IB00 +/* DISP_POWER_CTL_6_ADDR Power Control (6) */ +#define DISP_BITMASK_VCOMG DISP_BIT_IB13 +#define DISP_BITMASK_VDV4 DISP_BIT_IB12 +#define DISP_BITMASK_VDV3 DISP_BIT_IB11 +#define DISP_BITMASK_VDV2 DISP_BIT_IB10 +#define DISP_BITMASK_VDV1 DISP_BIT_IB09 +#define DISP_BITMASK_VDV0 DISP_BIT_IB08 +#define DISP_BITMASK_VCM4 DISP_BIT_IB04 +#define DISP_BITMASK_VCM3 DISP_BIT_IB03 +#define DISP_BITMASK_VCM2 DISP_BIT_IB02 +#define DISP_BITMASK_VCM1 DISP_BIT_IB01 +#define DISP_BITMASK_VCM0 DISP_BIT_IB00 +/* RAM Access */ +/* DISP_RAM_ADDR_SET_1_ADDR RAM Address Set (1) */ +#define DISP_BITMASK_AD7 DISP_BIT_IB07 +#define DISP_BITMASK_AD6 DISP_BIT_IB06 +#define DISP_BITMASK_AD5 DISP_BIT_IB05 +#define DISP_BITMASK_AD4 DISP_BIT_IB04 +#define DISP_BITMASK_AD3 DISP_BIT_IB03 +#define DISP_BITMASK_AD2 DISP_BIT_IB02 +#define DISP_BITMASK_AD1 DISP_BIT_IB01 +#define DISP_BITMASK_AD0 DISP_BIT_IB00 +/* DISP_RAM_ADDR_SET_2_ADDR RAM Address Set (2) */ +#define DISP_BITMASK_AD16 DISP_BIT_IB08 +#define DISP_BITMASK_AD15 DISP_BIT_IB07 +#define DISP_BITMASK_AD14 DISP_BIT_IB06 +#define DISP_BITMASK_AD13 DISP_BIT_IB05 +#define DISP_BITMASK_AD12 DISP_BIT_IB04 +#define DISP_BITMASK_AD11 DISP_BIT_IB03 +#define DISP_BITMASK_AD10 DISP_BIT_IB02 +#define DISP_BITMASK_AD9 DISP_BIT_IB01 +#define DISP_BITMASK_AD8 DISP_BIT_IB00 +/* + * DISP_CMD_RAMWR RAM Data Read/Write + * Use Data Bit Configuration + */ +/* DISP_RAM_DATA_MASK_1_ADDR RAM Write Data Mask (1) */ +#define DISP_BITMASK_WM11 DISP_BIT_IB13 +#define DISP_BITMASK_WM10 DISP_BIT_IB12 +#define DISP_BITMASK_WM9 DISP_BIT_IB11 +#define DISP_BITMASK_WM8 DISP_BIT_IB10 +#define DISP_BITMASK_WM7 DISP_BIT_IB09 +#define DISP_BITMASK_WM6 DISP_BIT_IB08 +#define DISP_BITMASK_WM5 DISP_BIT_IB05 +#define DISP_BITMASK_WM4 DISP_BIT_IB04 +#define DISP_BITMASK_WM3 DISP_BIT_IB03 +#define DISP_BITMASK_WM2 DISP_BIT_IB02 +#define DISP_BITMASK_WM1 DISP_BIT_IB01 +#define DISP_BITMASK_WM0 DISP_BIT_IB00 +/* DISP_RAM_DATA_MASK_2_ADDR RAM Write Data Mask (2) */ +#define DISP_BITMASK_WM17 DISP_BIT_IB05 +#define DISP_BITMASK_WM16 DISP_BIT_IB04 +#define DISP_BITMASK_WM15 DISP_BIT_IB03 +#define DISP_BITMASK_WM14 DISP_BIT_IB02 +#define DISP_BITMASK_WM13 DISP_BIT_IB01 +#define DISP_BITMASK_WM12 DISP_BIT_IB00 +/*Gamma Control */ +/* DISP_GAMMA_CONTROL_1_ADDR Gamma Control (1) */ +#define DISP_BITMASK_PKP12 DISP_BIT_IB10 +#define DISP_BITMASK_PKP11 DISP_BIT_IB08 +#define DISP_BITMASK_PKP10 DISP_BIT_IB09 +#define DISP_BITMASK_PKP02 DISP_BIT_IB02 +#define DISP_BITMASK_PKP01 DISP_BIT_IB01 +#define DISP_BITMASK_PKP00 DISP_BIT_IB00 +/* DISP_GAMMA_CONTROL_2_ADDR Gamma Control (2) */ +#define DISP_BITMASK_PKP32 DISP_BIT_IB10 +#define DISP_BITMASK_PKP31 DISP_BIT_IB09 +#define DISP_BITMASK_PKP30 DISP_BIT_IB08 +#define DISP_BITMASK_PKP22 DISP_BIT_IB02 +#define DISP_BITMASK_PKP21 DISP_BIT_IB01 +#define DISP_BITMASK_PKP20 DISP_BIT_IB00 +/* DISP_GAMMA_CONTROL_3_ADDR Gamma Control (3) */ +#define DISP_BITMASK_PKP52 DISP_BIT_IB10 +#define DISP_BITMASK_PKP51 DISP_BIT_IB09 +#define DISP_BITMASK_PKP50 DISP_BIT_IB08 +#define DISP_BITMASK_PKP42 DISP_BIT_IB02 +#define DISP_BITMASK_PKP41 DISP_BIT_IB01 +#define DISP_BITMASK_PKP40 DISP_BIT_IB00 +/* DISP_GAMMA_CONTROL_4_ADDR Gamma Control (4) */ +#define DISP_BITMASK_PRP12 DISP_BIT_IB10 +#define DISP_BITMASK_PRP11 DISP_BIT_IB08 +#define DISP_BITMASK_PRP10 DISP_BIT_IB09 +#define DISP_BITMASK_PRP02 DISP_BIT_IB02 +#define DISP_BITMASK_PRP01 DISP_BIT_IB01 +#define DISP_BITMASK_PRP00 DISP_BIT_IB00 +/* DISP_GAMMA_CONTROL_5_ADDR Gamma Control (5) */ +#define DISP_BITMASK_VRP14 DISP_BIT_IB12 +#define DISP_BITMASK_VRP13 DISP_BIT_IB11 +#define DISP_BITMASK_VRP12 DISP_BIT_IB10 +#define DISP_BITMASK_VRP11 DISP_BIT_IB08 +#define DISP_BITMASK_VRP10 DISP_BIT_IB09 +#define DISP_BITMASK_VRP03 DISP_BIT_IB03 +#define DISP_BITMASK_VRP02 DISP_BIT_IB02 +#define DISP_BITMASK_VRP01 DISP_BIT_IB01 +#define DISP_BITMASK_VRP00 DISP_BIT_IB00 +/* DISP_GAMMA_CONTROL_6_ADDR Gamma Control (6) */ +#define DISP_BITMASK_PKN12 DISP_BIT_IB10 +#define DISP_BITMASK_PKN11 DISP_BIT_IB08 +#define DISP_BITMASK_PKN10 DISP_BIT_IB09 +#define DISP_BITMASK_PKN02 DISP_BIT_IB02 +#define DISP_BITMASK_PKN01 DISP_BIT_IB01 +#define DISP_BITMASK_PKN00 DISP_BIT_IB00 +/* DISP_GAMMA_CONTROL_7_ADDR Gamma Control (7) */ +#define DISP_BITMASK_PKN32 DISP_BIT_IB10 +#define DISP_BITMASK_PKN31 DISP_BIT_IB08 +#define DISP_BITMASK_PKN30 DISP_BIT_IB09 +#define DISP_BITMASK_PKN22 DISP_BIT_IB02 +#define DISP_BITMASK_PKN21 DISP_BIT_IB01 +#define DISP_BITMASK_PKN20 DISP_BIT_IB00 +/* DISP_GAMMA_CONTROL_8_ADDR Gamma Control (8) */ +#define DISP_BITMASK_PKN52 DISP_BIT_IB10 +#define DISP_BITMASK_PKN51 DISP_BIT_IB08 +#define DISP_BITMASK_PKN50 DISP_BIT_IB09 +#define DISP_BITMASK_PKN42 DISP_BIT_IB02 +#define DISP_BITMASK_PKN41 DISP_BIT_IB01 +#define DISP_BITMASK_PKN40 DISP_BIT_IB00 +/* DISP_GAMMA_CONTROL_9_ADDR Gamma Control (9) */ +#define DISP_BITMASK_PRN12 DISP_BIT_IB10 +#define DISP_BITMASK_PRN11 DISP_BIT_IB08 +#define DISP_BITMASK_PRN10 DISP_BIT_IB09 +#define DISP_BITMASK_PRN02 DISP_BIT_IB02 +#define DISP_BITMASK_PRN01 DISP_BIT_IB01 +#define DISP_BITMASK_PRN00 DISP_BIT_IB00 +/* DISP_GAMMA_CONTROL_10_ADDR Gamma Control (10) */ +#define DISP_BITMASK_VRN14 DISP_BIT_IB12 +#define DISP_BITMASK_VRN13 DISP_BIT_IB11 +#define DISP_BITMASK_VRN12 DISP_BIT_IB10 +#define DISP_BITMASK_VRN11 DISP_BIT_IB08 +#define DISP_BITMASK_VRN10 DISP_BIT_IB09 +#define DISP_BITMASK_VRN03 DISP_BIT_IB03 +#define DISP_BITMASK_VRN02 DISP_BIT_IB02 +#define DISP_BITMASK_VRN01 DISP_BIT_IB01 +#define DISP_BITMASK_VRN00 DISP_BIT_IB00 +/* Coordinate Control */ +/* DISP_VERT_SCROLL_CTL_1_ADDR Vertical Scroll Control (1) */ +#define DISP_BITMASK_VL18 DISP_BIT_IB08 +#define DISP_BITMASK_VL17 DISP_BIT_IB07 +#define DISP_BITMASK_VL16 DISP_BIT_IB06 +#define DISP_BITMASK_VL15 DISP_BIT_IB05 +#define DISP_BITMASK_VL14 DISP_BIT_IB04 +#define DISP_BITMASK_VL13 DISP_BIT_IB03 +#define DISP_BITMASK_VL12 DISP_BIT_IB02 +#define DISP_BITMASK_VL11 DISP_BIT_IB01 +#define DISP_BITMASK_VL10 DISP_BIT_IB00 +/* DISP_VERT_SCROLL_CTL_2_ADDR Vertical Scroll Control (2) */ +#define DISP_BITMASK_VL28 DISP_BIT_IB08 +#define DISP_BITMASK_VL27 DISP_BIT_IB07 +#define DISP_BITMASK_VL26 DISP_BIT_IB06 +#define DISP_BITMASK_VL25 DISP_BIT_IB05 +#define DISP_BITMASK_VL24 DISP_BIT_IB04 +#define DISP_BITMASK_VL23 DISP_BIT_IB03 +#define DISP_BITMASK_VL22 DISP_BIT_IB02 +#define DISP_BITMASK_VL21 DISP_BIT_IB01 +#define DISP_BITMASK_VL20 DISP_BIT_IB00 +/* DISP_SCREEN_1_DRV_POS_1_ADDR First Screen Driving Position (1) */ +#define DISP_BITMASK_SS18 DISP_BIT_IB08 +#define DISP_BITMASK_SS17 DISP_BIT_IB07 +#define DISP_BITMASK_SS16 DISP_BIT_IB06 +#define DISP_BITMASK_SS15 DISP_BIT_IB05 +#define DISP_BITMASK_SS14 DISP_BIT_IB04 +#define DISP_BITMASK_SS13 DISP_BIT_IB03 +#define DISP_BITMASK_SS12 DISP_BIT_IB02 +#define DISP_BITMASK_SS11 DISP_BIT_IB01 +#define DISP_BITMASK_SS10 DISP_BIT_IB00 +/* DISP_SCREEN_1_DRV_POS_2_ADDR First Screen Driving Position (2) */ +#define DISP_BITMASK_SE18 DISP_BIT_IB08 +#define DISP_BITMASK_SE17 DISP_BIT_IB07 +#define DISP_BITMASK_SE16 DISP_BIT_IB06 +#define DISP_BITMASK_SE15 DISP_BIT_IB05 +#define DISP_BITMASK_SE14 DISP_BIT_IB04 +#define DISP_BITMASK_SE13 DISP_BIT_IB03 +#define DISP_BITMASK_SE12 DISP_BIT_IB02 +#define DISP_BITMASK_SE11 DISP_BIT_IB01 +#define DISP_BITMASK_SE10 DISP_BIT_IB00 +/* DISP_SCREEN_2_DRV_POS_1_ADDR Second Screen Driving Position (1) */ +#define DISP_BITMASK_SS28 DISP_BIT_IB08 +#define DISP_BITMASK_SS27 DISP_BIT_IB07 +#define DISP_BITMASK_SS26 DISP_BIT_IB06 +#define DISP_BITMASK_SS25 DISP_BIT_IB05 +#define DISP_BITMASK_SS24 DISP_BIT_IB04 +#define DISP_BITMASK_SS23 DISP_BIT_IB03 +#define DISP_BITMASK_SS22 DISP_BIT_IB02 +#define DISP_BITMASK_SS21 DISP_BIT_IB01 +#define DISP_BITMASK_SS20 DISP_BIT_IB00 +/* DISP_SCREEN_3_DRV_POS_2_ADDR Second Screen Driving Position (2) */ +#define DISP_BITMASK_SE28 DISP_BIT_IB08 +#define DISP_BITMASK_SE27 DISP_BIT_IB07 +#define DISP_BITMASK_SE26 DISP_BIT_IB06 +#define DISP_BITMASK_SE25 DISP_BIT_IB05 +#define DISP_BITMASK_SE24 DISP_BIT_IB04 +#define DISP_BITMASK_SE23 DISP_BIT_IB03 +#define DISP_BITMASK_SE22 DISP_BIT_IB02 +#define DISP_BITMASK_SE21 DISP_BIT_IB01 +#define DISP_BITMASK_SE20 DISP_BIT_IB00 +/* DISP_HORZ_RAM_ADDR_POS_1_ADDR Horizontal RAM Address Position (1) */ +#define DISP_BITMASK_HSA7 DISP_BIT_IB07 +#define DISP_BITMASK_HSA6 DISP_BIT_IB06 +#define DISP_BITMASK_HSA5 DISP_BIT_IB05 +#define DISP_BITMASK_HSA4 DISP_BIT_IB04 +#define DISP_BITMASK_HSA3 DISP_BIT_IB03 +#define DISP_BITMASK_HSA2 DISP_BIT_IB02 +#define DISP_BITMASK_HSA1 DISP_BIT_IB01 +#define DISP_BITMASK_HSA0 DISP_BIT_IB00 +/* DISP_HORZ_RAM_ADDR_POS_2_ADDR Horizontal RAM Address Position (2) */ +#define DISP_BITMASK_HEA7 DISP_BIT_IB07 +#define DISP_BITMASK_HEA6 DISP_BIT_IB06 +#define DISP_BITMASK_HEA5 DISP_BIT_IB05 +#define DISP_BITMASK_HEA4 DISP_BIT_IB04 +#define DISP_BITMASK_HEA3 DISP_BIT_IB03 +#define DISP_BITMASK_HEA2 DISP_BIT_IB02 +#define DISP_BITMASK_HEA1 DISP_BIT_IB01 +#define DISP_BITMASK_HEA0 DISP_BIT_IB00 +/* DISP_VERT_RAM_ADDR_POS_1_ADDR Vertical RAM Address Position (1) */ +#define DISP_BITMASK_VSA8 DISP_BIT_IB08 +#define DISP_BITMASK_VSA7 DISP_BIT_IB07 +#define DISP_BITMASK_VSA6 DISP_BIT_IB06 +#define DISP_BITMASK_VSA5 DISP_BIT_IB05 +#define DISP_BITMASK_VSA4 DISP_BIT_IB04 +#define DISP_BITMASK_VSA3 DISP_BIT_IB03 +#define DISP_BITMASK_VSA2 DISP_BIT_IB02 +#define DISP_BITMASK_VSA1 DISP_BIT_IB01 +#define DISP_BITMASK_VSA0 DISP_BIT_IB00 +/* DISP_VERT_RAM_ADDR_POS_2_ADDR Vertical RAM Address Position (2) */ +#define DISP_BITMASK_VEA8 DISP_BIT_IB08 +#define DISP_BITMASK_VEA7 DISP_BIT_IB07 +#define DISP_BITMASK_VEA6 DISP_BIT_IB06 +#define DISP_BITMASK_VEA5 DISP_BIT_IB05 +#define DISP_BITMASK_VEA4 DISP_BIT_IB04 +#define DISP_BITMASK_VEA3 DISP_BIT_IB03 +#define DISP_BITMASK_VEA2 DISP_BIT_IB02 +#define DISP_BITMASK_VEA1 DISP_BIT_IB01 +#define DISP_BITMASK_VEA0 DISP_BIT_IB00 +static word disp_area_start_row; +static word disp_area_end_row; +static boolean disp_initialized = FALSE; +/* For some reason the contrast set at init time is not good. Need to do +* it again +*/ +static boolean display_on = FALSE; + +static uint32 tmd20qvga_lcd_rev; +uint16 tmd20qvga_panel_offset; + +#ifdef DISP_DEVICE_8BPP +static word convert_8_to_16_tbl[256] = { + 0x0000, 0x2000, 0x4000, 0x6000, 0x8000, 0xA000, 0xC000, 0xE000, + 0x0100, 0x2100, 0x4100, 0x6100, 0x8100, 0xA100, 0xC100, 0xE100, + 0x0200, 0x2200, 0x4200, 0x6200, 0x8200, 0xA200, 0xC200, 0xE200, + 0x0300, 0x2300, 0x4300, 0x6300, 0x8300, 0xA300, 0xC300, 0xE300, + 0x0400, 0x2400, 0x4400, 0x6400, 0x8400, 0xA400, 0xC400, 0xE400, + 0x0500, 0x2500, 0x4500, 0x6500, 0x8500, 0xA500, 0xC500, 0xE500, + 0x0600, 0x2600, 0x4600, 0x6600, 0x8600, 0xA600, 0xC600, 0xE600, + 0x0700, 0x2700, 0x4700, 0x6700, 0x8700, 0xA700, 0xC700, 0xE700, + 0x0008, 0x2008, 0x4008, 0x6008, 0x8008, 0xA008, 0xC008, 0xE008, + 0x0108, 0x2108, 0x4108, 0x6108, 0x8108, 0xA108, 0xC108, 0xE108, + 0x0208, 0x2208, 0x4208, 0x6208, 0x8208, 0xA208, 0xC208, 0xE208, + 0x0308, 0x2308, 0x4308, 0x6308, 0x8308, 0xA308, 0xC308, 0xE308, + 0x0408, 0x2408, 0x4408, 0x6408, 0x8408, 0xA408, 0xC408, 0xE408, + 0x0508, 0x2508, 0x4508, 0x6508, 0x8508, 0xA508, 0xC508, 0xE508, + 0x0608, 0x2608, 0x4608, 0x6608, 0x8608, 0xA608, 0xC608, 0xE608, + 0x0708, 0x2708, 0x4708, 0x6708, 0x8708, 0xA708, 0xC708, 0xE708, + 0x0010, 0x2010, 0x4010, 0x6010, 0x8010, 0xA010, 0xC010, 0xE010, + 0x0110, 0x2110, 0x4110, 0x6110, 0x8110, 0xA110, 0xC110, 0xE110, + 0x0210, 0x2210, 0x4210, 0x6210, 0x8210, 0xA210, 0xC210, 0xE210, + 0x0310, 0x2310, 0x4310, 0x6310, 0x8310, 0xA310, 0xC310, 0xE310, + 0x0410, 0x2410, 0x4410, 0x6410, 0x8410, 0xA410, 0xC410, 0xE410, + 0x0510, 0x2510, 0x4510, 0x6510, 0x8510, 0xA510, 0xC510, 0xE510, + 0x0610, 0x2610, 0x4610, 0x6610, 0x8610, 0xA610, 0xC610, 0xE610, + 0x0710, 0x2710, 0x4710, 0x6710, 0x8710, 0xA710, 0xC710, 0xE710, + 0x0018, 0x2018, 0x4018, 0x6018, 0x8018, 0xA018, 0xC018, 0xE018, + 0x0118, 0x2118, 0x4118, 0x6118, 0x8118, 0xA118, 0xC118, 0xE118, + 0x0218, 0x2218, 0x4218, 0x6218, 0x8218, 0xA218, 0xC218, 0xE218, + 0x0318, 0x2318, 0x4318, 0x6318, 0x8318, 0xA318, 0xC318, 0xE318, + 0x0418, 0x2418, 0x4418, 0x6418, 0x8418, 0xA418, 0xC418, 0xE418, + 0x0518, 0x2518, 0x4518, 0x6518, 0x8518, 0xA518, 0xC518, 0xE518, + 0x0618, 0x2618, 0x4618, 0x6618, 0x8618, 0xA618, 0xC618, 0xE618, + 0x0718, 0x2718, 0x4718, 0x6718, 0x8718, 0xA718, 0xC718, 0xE718 +}; +#endif /* DISP_DEVICE_8BPP */ + +static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres); +static void tmd20qvga_disp_init(struct platform_device *pdev); +static void tmd20qvga_disp_set_contrast(void); +static void tmd20qvga_disp_set_display_area(word start_row, word end_row); +static int tmd20qvga_disp_off(struct platform_device *pdev); +static int tmd20qvga_disp_on(struct platform_device *pdev); +static void tmd20qvga_set_revId(int); + +/* future use */ +void tmd20qvga_disp_clear_screen_area(word start_row, word end_row, + word start_column, word end_column); + +static void tmd20qvga_set_revId(int id) +{ + + tmd20qvga_lcd_rev = id; + + if (tmd20qvga_lcd_rev == 1) + tmd20qvga_panel_offset = 0x10; + else + tmd20qvga_panel_offset = 0; +} + +static void tmd20qvga_disp_init(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd; + + if (disp_initialized) + return; + + mfd = platform_get_drvdata(pdev); + + DISP_CMD_PORT = mfd->cmd_port; + DISP_DATA_PORT = mfd->data_port; + +#ifdef TMD20QVGA_LCD_18BPP + tmd20qvga_set_revId(2); +#else + tmd20qvga_set_revId(1); +#endif + + disp_initialized = TRUE; + tmd20qvga_disp_set_contrast(); + tmd20qvga_disp_set_display_area(0, QVGA_HEIGHT - 1); +} + +static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres) +{ + if (!disp_initialized) + return; + + DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1); + + DISP_CMD_OUT(DISP_CMD_RAMWR); +} + +static void tmd20qvga_disp_set_display_area(word start_row, word end_row) +{ + word start_driving = start_row; + word end_driving = end_row; + + if (!disp_initialized) + return; + + /* Range checking + */ + if (end_driving >= QVGA_HEIGHT) + end_driving = QVGA_HEIGHT - 1; + if (start_driving > end_driving) { + /* Probably Backwards Switch */ + start_driving = end_driving; + end_driving = start_row; /* Has not changed */ + if (end_driving >= QVGA_HEIGHT) + end_driving = QVGA_HEIGHT - 1; + } + + if ((start_driving == disp_area_start_row) + && (end_driving == disp_area_end_row)) + return; + + disp_area_start_row = start_driving; + disp_area_end_row = end_driving; + + DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, + DISP_VAL_IF(start_driving & 0x100, + DISP_BITMASK_SS18) | + DISP_VAL_IF(start_driving & 0x080, + DISP_BITMASK_SS17) | + DISP_VAL_IF(start_driving & 0x040, + DISP_BITMASK_SS16) | + DISP_VAL_IF(start_driving & 0x020, + DISP_BITMASK_SS15) | + DISP_VAL_IF(start_driving & 0x010, + DISP_BITMASK_SS14) | + DISP_VAL_IF(start_driving & 0x008, + DISP_BITMASK_SS13) | + DISP_VAL_IF(start_driving & 0x004, + DISP_BITMASK_SS12) | + DISP_VAL_IF(start_driving & 0x002, + DISP_BITMASK_SS11) | + DISP_VAL_IF(start_driving & 0x001, DISP_BITMASK_SS10)); + + DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, + DISP_VAL_IF(end_driving & 0x100, DISP_BITMASK_SE18) | + DISP_VAL_IF(end_driving & 0x080, DISP_BITMASK_SE17) | + DISP_VAL_IF(end_driving & 0x040, DISP_BITMASK_SE16) | + DISP_VAL_IF(end_driving & 0x020, DISP_BITMASK_SE15) | + DISP_VAL_IF(end_driving & 0x010, DISP_BITMASK_SE14) | + DISP_VAL_IF(end_driving & 0x008, DISP_BITMASK_SE13) | + DISP_VAL_IF(end_driving & 0x004, DISP_BITMASK_SE12) | + DISP_VAL_IF(end_driving & 0x002, DISP_BITMASK_SE11) | + DISP_VAL_IF(end_driving & 0x001, DISP_BITMASK_SE10)); +} + +static int tmd20qvga_disp_off(struct platform_device *pdev) +{ + if (!disp_initialized) + tmd20qvga_disp_init(pdev); + + if (display_on) { + if (tmd20qvga_lcd_rev == 2) { + DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000A); + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFEE); + WAIT_MSEC(40); + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xF812); + WAIT_MSEC(40); + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xE811); + WAIT_MSEC(40); + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC011); + WAIT_MSEC(40); + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x4011); + WAIT_MSEC(20); + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0010); + + } else { + DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000F); + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFE); + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); + WAIT_MSEC(40); + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BED); + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); + WAIT_MSEC(40); + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x00CD); + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); + WAIT_MSEC(20); + DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0); + } + + DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0004); + DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0000); + + display_on = FALSE; + } + + return 0; +} + +static int tmd20qvga_disp_on(struct platform_device *pdev) +{ + if (!disp_initialized) + tmd20qvga_disp_init(pdev); + + if (!display_on) { + /* Deep Stand-by -> Stand-by */ + DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR); + WAIT_MSEC(1); + DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR); + WAIT_MSEC(1); + DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR); + WAIT_MSEC(1); + + /* OFF -> Deep Stan-By -> Stand-by */ + /* let's change the state from "Stand-by" to "Sleep" */ + DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0005); + WAIT_MSEC(1); + + /* Sleep -> Displaying */ + DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0001); + DISP_WRITE_OUT(DISP_DRIVER_OUTPUT_CTL_ADDR, 0x0127); + DISP_WRITE_OUT(DISP_LCD_DRIVING_SIG_ADDR, 0x200); + /* fast write mode */ + DISP_WRITE_OUT(DISP_ENTRY_MODE_ADDR, 0x0130); + if (tmd20qvga_lcd_rev == 2) + DISP_WRITE_OUT(DISP_TMD_700_ADDR, 0x0003); + /* back porch = 14 + front porch = 2 --> 16 lines */ + if (tmd20qvga_lcd_rev == 2) { +#ifdef TMD20QVGA_LCD_18BPP + /* 256k color */ + DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0000); +#else + /* 65k color */ + DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4000); +#endif + DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x0302); + } else { +#ifdef TMD20QVGA_LCD_18BPP + /* 256k color */ + DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0004); +#else + /* 65k color */ + DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4004); +#endif + DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x020E); + } + /* 16 bit one transfer */ + if (tmd20qvga_lcd_rev == 2) { + DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0000); + DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010); + DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0302); + DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0102); + DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000); + DISP_WRITE_OUT(DISP_TMD_015_ADDR, 0x2000); + + DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0304); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0101); + DISP_WRITE_OUT(DISP_TMD_305_ADDR, 0); + + DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000); + DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F); + + DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x077D); + + DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0005); + DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0000); + DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0015); + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC010); + WAIT_MSEC(1); + + DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x0001); + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFFE); + WAIT_MSEC(60); + } else { + DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0001); + DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010); + DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0301); + DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0001); + DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000); + DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0507); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0405); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0607); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0502); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0301); + DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000); + DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F); + DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x0795); + + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0102); + WAIT_MSEC(1); + + DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0450); + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0103); + WAIT_MSEC(1); + + DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0008); + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0104); + WAIT_MSEC(1); + + DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0C00); + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0105); + WAIT_MSEC(1); + + DISP_WRITE_OUT(DISP_POWER_CTL_7_ADDR, 0x0000); + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0106); + WAIT_MSEC(1); + + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0801); + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); + WAIT_MSEC(1); + + DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x001F); + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101); + WAIT_MSEC(60); + + DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x009F); + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101); + WAIT_MSEC(10); + + DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, 0x0010); + DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, 0x00FF); + DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, 0x0000); + DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, 0x013F); + /* RAM starts at address 0x10 */ + DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, 0x0010); + DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, 0x0000); + + /* lcd controller uses internal clock, not ext. vsync */ + DISP_CMD_OUT(DISP_CMD_RAMWR); + + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0881); + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); + WAIT_MSEC(40); + + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BE1); + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); + WAIT_MSEC(40); + + DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFF); + DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); + } + display_on = TRUE; + } + + return 0; +} + +static void tmd20qvga_disp_set_contrast(void) +{ +#if (defined(TMD20QVGA_LCD_18BPP)) + + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0302); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07); + +#else + int newcontrast = 0x46; + + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403); + + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, + DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP20) | + DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP21) | + DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP22) | + DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP30) | + DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP31) | + DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP32)); + + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, + DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP40) | + DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP41) | + DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP42) | + DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP50) | + DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP51) | + DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP52)); + + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303); + DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07); + +#endif /* defined(TMD20QVGA_LCD_18BPP) */ + +} /* End disp_set_contrast */ + +void tmd20qvga_disp_clear_screen_area + (word start_row, word end_row, word start_column, word end_column) { + int32 i; + + /* Clear the display screen */ + DISP_SET_RECT(start_row, end_row, start_column, end_column); + DISP_CMD_OUT(DISP_CMD_RAMWR); + i = (end_row - start_row + 1) * (end_column - start_column + 1); + for (; i > 0; i--) + DISP_DATA_OUT_16TO18BPP(0x0); +} + +static int __init tmd20qvga_probe(struct platform_device *pdev) +{ + msm_fb_add_device(pdev); + + return 0; +} + +static struct platform_driver this_driver = { + .probe = tmd20qvga_probe, + .driver = { + .name = "ebi2_tmd_qvga", + }, +}; + +static struct msm_fb_panel_data tmd20qvga_panel_data = { + .on = tmd20qvga_disp_on, + .off = tmd20qvga_disp_off, + .set_rect = tmd20qvga_disp_set_rect, +}; + +static struct platform_device this_device = { + .name = "ebi2_tmd_qvga", + .id = 0, + .dev = { + .platform_data = &tmd20qvga_panel_data, + } +}; + +static int __init tmd20qvga_init(void) +{ + int ret; + struct msm_panel_info *pinfo; + + ret = platform_driver_register(&this_driver); + if (!ret) { + pinfo = &tmd20qvga_panel_data.panel_info; + pinfo->xres = 240; + pinfo->yres = 320; + pinfo->type = EBI2_PANEL; + pinfo->pdest = DISPLAY_1; + pinfo->wait_cycle = 0x808000; +#ifdef TMD20QVGA_LCD_18BPP + pinfo->bpp = 18; +#else + pinfo->bpp = 16; +#endif + pinfo->fb_num = 2; + pinfo->lcd.vsync_enable = TRUE; + pinfo->lcd.refx100 = 6000; + pinfo->lcd.v_back_porch = 16; + pinfo->lcd.v_front_porch = 4; + pinfo->lcd.v_pulse_width = 0; + pinfo->lcd.hw_vsync_mode = FALSE; + pinfo->lcd.vsync_notifier_period = 0; + + ret = platform_device_register(&this_device); + if (ret) + platform_driver_unregister(&this_driver); + } + + return ret; +} + +module_init(tmd20qvga_init); diff --git a/drivers/staging/msm/hdmi_sii9022.c b/drivers/staging/msm/hdmi_sii9022.c new file mode 100644 index 000000000000..6b82b56a77b6 --- /dev/null +++ b/drivers/staging/msm/hdmi_sii9022.c @@ -0,0 +1,248 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/i2c.h> +#include <linux/delay.h> +#include "msm_fb.h" + +#define DEVICE_NAME "sii9022" +#define SII9022_DEVICE_ID 0xB0 + +struct sii9022_i2c_addr_data{ + u8 addr; + u8 data; +}; + +/* video mode data */ +static u8 video_mode_data[] = { + 0x00, + 0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02, +}; + +static u8 avi_io_format[] = { + 0x09, + 0x00, 0x00, +}; + +/* power state */ +static struct sii9022_i2c_addr_data regset0[] = { + { 0x60, 0x04 }, + { 0x63, 0x00 }, + { 0x1E, 0x00 }, +}; + +static u8 video_infoframe[] = { + 0x0C, + 0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00, + 0xE9, 0x02, 0x04, 0x01, 0x04, 0x06, +}; + +/* configure audio */ +static struct sii9022_i2c_addr_data regset1[] = { + { 0x26, 0x90 }, + { 0x20, 0x90 }, + { 0x1F, 0x80 }, + { 0x26, 0x80 }, + { 0x24, 0x02 }, + { 0x25, 0x0B }, + { 0xBC, 0x02 }, + { 0xBD, 0x24 }, + { 0xBE, 0x02 }, +}; + +/* enable audio */ +static u8 misc_infoframe[] = { + 0xBF, + 0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* set HDMI, active */ +static struct sii9022_i2c_addr_data regset2[] = { + { 0x1A, 0x01 }, + { 0x3D, 0x00 }, +}; + +static int send_i2c_data(struct i2c_client *client, + struct sii9022_i2c_addr_data *regset, + int size) +{ + int i; + int rc = 0; + + for (i = 0; i < size; i++) { + rc = i2c_smbus_write_byte_data( + client, + regset[i].addr, regset[i].data); + if (rc) + break; + } + return rc; +} + +static int hdmi_sii_enable(struct i2c_client *client) +{ + int rc; + int retries = 10; + int count; + + rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00); + if (rc) + goto enable_exit; + + do { + msleep(1); + rc = i2c_smbus_read_byte_data(client, 0x1B); + } while ((rc != SII9022_DEVICE_ID) && retries--); + + if (rc != SII9022_DEVICE_ID) + return -ENODEV; + + rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11); + if (rc) + goto enable_exit; + + count = ARRAY_SIZE(video_mode_data); + rc = i2c_master_send(client, video_mode_data, count); + if (rc != count) { + rc = -EIO; + goto enable_exit; + } + + rc = i2c_smbus_write_byte_data(client, 0x08, 0x20); + if (rc) + goto enable_exit; + count = ARRAY_SIZE(avi_io_format); + rc = i2c_master_send(client, avi_io_format, count); + if (rc != count) { + rc = -EIO; + goto enable_exit; + } + + rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0)); + if (rc) + goto enable_exit; + + count = ARRAY_SIZE(video_infoframe); + rc = i2c_master_send(client, video_infoframe, count); + if (rc != count) { + rc = -EIO; + goto enable_exit; + } + + rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1)); + if (rc) + goto enable_exit; + + count = ARRAY_SIZE(misc_infoframe); + rc = i2c_master_send(client, misc_infoframe, count); + if (rc != count) { + rc = -EIO; + goto enable_exit; + } + + rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2)); + if (rc) + goto enable_exit; + + return 0; +enable_exit: + printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc); + return rc; +} + +static const struct i2c_device_id hmdi_sii_id[] = { + { DEVICE_NAME, 0 }, + { } +}; + +static int hdmi_sii_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int rc; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C)) + return -ENODEV; + rc = hdmi_sii_enable(client); + return rc; +} + + +static struct i2c_driver hdmi_sii_i2c_driver = { + .driver = { + .name = DEVICE_NAME, + .owner = THIS_MODULE, + }, + .probe = hdmi_sii_probe, + .remove = __exit_p(hdmi_sii_remove), + .id_table = hmdi_sii_id, +}; + +static int __init hdmi_sii_init(void) +{ + int ret; + struct msm_panel_info pinfo; + + if (msm_fb_detect_client("hdmi_sii9022")) + return 0; + + pinfo.xres = 1280; + pinfo.yres = 720; + pinfo.type = HDMI_PANEL; + pinfo.pdest = DISPLAY_1; + pinfo.wait_cycle = 0; + pinfo.bpp = 24; + pinfo.fb_num = 2; + pinfo.clk_rate = 74250000; + + pinfo.lcdc.h_back_porch = 124; + pinfo.lcdc.h_front_porch = 110; + pinfo.lcdc.h_pulse_width = 136; + pinfo.lcdc.v_back_porch = 19; + pinfo.lcdc.v_front_porch = 5; + pinfo.lcdc.v_pulse_width = 6; + pinfo.lcdc.border_clr = 0; + pinfo.lcdc.underflow_clr = 0xff; + pinfo.lcdc.hsync_skew = 0; + + ret = lcdc_device_register(&pinfo); + if (ret) { + printk(KERN_ERR "%s: failed to register device\n", __func__); + goto init_exit; + } + + ret = i2c_add_driver(&hdmi_sii_i2c_driver); + if (ret) + printk(KERN_ERR "%s: failed to add i2c driver\n", __func__); + +init_exit: + return ret; +} + +static void __exit hdmi_sii_exit(void) +{ + i2c_del_driver(&hdmi_sii_i2c_driver); +} + +module_init(hdmi_sii_init); +module_exit(hdmi_sii_exit); +MODULE_LICENSE("GPL v2"); +MODULE_VERSION("0.1"); +MODULE_AUTHOR("Qualcomm Innovation Center, Inc."); +MODULE_DESCRIPTION("SiI9022 HDMI driver"); +MODULE_ALIAS("platform:hdmi-sii9022"); diff --git a/drivers/staging/msm/lcdc.c b/drivers/staging/msm/lcdc.c new file mode 100644 index 000000000000..735280ab72cb --- /dev/null +++ b/drivers/staging/msm/lcdc.c @@ -0,0 +1,239 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/delay.h> +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/uaccess.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/pm_qos_params.h> + +#include "msm_fb.h" + +static int lcdc_probe(struct platform_device *pdev); +static int lcdc_remove(struct platform_device *pdev); + +static int lcdc_off(struct platform_device *pdev); +static int lcdc_on(struct platform_device *pdev); + +static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; +static int pdev_list_cnt; + +static struct clk *mdp_lcdc_pclk_clk; +static struct clk *mdp_lcdc_pad_pclk_clk; + +int mdp_lcdc_pclk_clk_rate; +int mdp_lcdc_pad_pclk_clk_rate; + +static struct platform_driver lcdc_driver = { + .probe = lcdc_probe, + .remove = lcdc_remove, + .suspend = NULL, + .resume = NULL, + .shutdown = NULL, + .driver = { + .name = "lcdc", + }, +}; + +static struct lcdc_platform_data *lcdc_pdata; + +static int lcdc_off(struct platform_device *pdev) +{ + int ret = 0; + + ret = panel_next_off(pdev); + + clk_disable(mdp_lcdc_pclk_clk); + clk_disable(mdp_lcdc_pad_pclk_clk); + + if (lcdc_pdata && lcdc_pdata->lcdc_power_save) + lcdc_pdata->lcdc_power_save(0); + + if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config) + ret = lcdc_pdata->lcdc_gpio_config(0); + +// pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc", +// PM_QOS_DEFAULT_VALUE); + + return ret; +} + +static int lcdc_on(struct platform_device *pdev) +{ + int ret = 0; + struct msm_fb_data_type *mfd; + unsigned long panel_pixclock_freq , pm_qos_freq; + + mfd = platform_get_drvdata(pdev); + panel_pixclock_freq = mfd->fbi->var.pixclock; + + if (panel_pixclock_freq > 58000000) + /* pm_qos_freq should be in Khz */ + pm_qos_freq = panel_pixclock_freq / 1000 ; + else + pm_qos_freq = 58000; + +// pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc", +// pm_qos_freq); + mfd = platform_get_drvdata(pdev); + + clk_enable(mdp_lcdc_pclk_clk); + clk_enable(mdp_lcdc_pad_pclk_clk); + + if (lcdc_pdata && lcdc_pdata->lcdc_power_save) + lcdc_pdata->lcdc_power_save(1); + if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config) + ret = lcdc_pdata->lcdc_gpio_config(1); + + clk_set_rate(mdp_lcdc_pclk_clk, mfd->fbi->var.pixclock); + clk_set_rate(mdp_lcdc_pad_pclk_clk, mfd->fbi->var.pixclock); + mdp_lcdc_pclk_clk_rate = clk_get_rate(mdp_lcdc_pclk_clk); + mdp_lcdc_pad_pclk_clk_rate = clk_get_rate(mdp_lcdc_pad_pclk_clk); + + ret = panel_next_on(pdev); + return ret; +} + +static int lcdc_probe(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd; + struct fb_info *fbi; + struct platform_device *mdp_dev = NULL; + struct msm_fb_panel_data *pdata = NULL; + int rc; + + if (pdev->id == 0) { + lcdc_pdata = pdev->dev.platform_data; + return 0; + } + + mfd = platform_get_drvdata(pdev); + + if (!mfd) + return -ENODEV; + + if (mfd->key != MFD_KEY) + return -EINVAL; + + if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) + return -ENOMEM; + + mdp_dev = platform_device_alloc("mdp", pdev->id); + if (!mdp_dev) + return -ENOMEM; + + /* + * link to the latest pdev + */ + mfd->pdev = mdp_dev; + mfd->dest = DISPLAY_LCDC; + + /* + * alloc panel device data + */ + if (platform_device_add_data + (mdp_dev, pdev->dev.platform_data, + sizeof(struct msm_fb_panel_data))) { + printk(KERN_ERR "lcdc_probe: platform_device_add_data failed!\n"); + platform_device_put(mdp_dev); + return -ENOMEM; + } + /* + * data chain + */ + pdata = (struct msm_fb_panel_data *)mdp_dev->dev.platform_data; + pdata->on = lcdc_on; + pdata->off = lcdc_off; + pdata->next = pdev; + + /* + * get/set panel specific fb info + */ + mfd->panel_info = pdata->panel_info; + mfd->fb_imgType = MDP_RGB_565; + + fbi = mfd->fbi; + fbi->var.pixclock = mfd->panel_info.clk_rate; + fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch; + fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch; + fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch; + fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch; + fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width; + fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width; + + /* + * set driver data + */ + platform_set_drvdata(mdp_dev, mfd); + + /* + * register in mdp driver + */ + rc = platform_device_add(mdp_dev); + if (rc) + goto lcdc_probe_err; + + pdev_list[pdev_list_cnt++] = pdev; + return 0; + +lcdc_probe_err: + platform_device_put(mdp_dev); + return rc; +} + +static int lcdc_remove(struct platform_device *pdev) +{ +// pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc"); + return 0; +} + +static int lcdc_register_driver(void) +{ + return platform_driver_register(&lcdc_driver); +} + +static int __init lcdc_driver_init(void) +{ + mdp_lcdc_pclk_clk = clk_get(NULL, "mdp_lcdc_pclk_clk"); + if (IS_ERR(mdp_lcdc_pclk_clk)) { + printk(KERN_ERR "error: can't get mdp_lcdc_pclk_clk!\n"); + return IS_ERR(mdp_lcdc_pclk_clk); + } + mdp_lcdc_pad_pclk_clk = clk_get(NULL, "mdp_lcdc_pad_pclk_clk"); + if (IS_ERR(mdp_lcdc_pad_pclk_clk)) { + printk(KERN_ERR "error: can't get mdp_lcdc_pad_pclk_clk!\n"); + return IS_ERR(mdp_lcdc_pad_pclk_clk); + } +// pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc", +// PM_QOS_DEFAULT_VALUE); + return lcdc_register_driver(); +} + +module_init(lcdc_driver_init); diff --git a/drivers/staging/msm/lcdc_external.c b/drivers/staging/msm/lcdc_external.c new file mode 100644 index 000000000000..45ff78527111 --- /dev/null +++ b/drivers/staging/msm/lcdc_external.c @@ -0,0 +1,54 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" + +static int __init lcdc_external_init(void) +{ + int ret; + struct msm_panel_info pinfo; + + if (msm_fb_detect_client("lcdc_external")) + return 0; + + pinfo.xres = 1280; + pinfo.yres = 720; + pinfo.type = LCDC_PANEL; + pinfo.pdest = DISPLAY_1; + pinfo.wait_cycle = 0; + pinfo.bpp = 24; + pinfo.fb_num = 2; + pinfo.clk_rate = 74250000; + + pinfo.lcdc.h_back_porch = 124; + pinfo.lcdc.h_front_porch = 110; + pinfo.lcdc.h_pulse_width = 136; + pinfo.lcdc.v_back_porch = 19; + pinfo.lcdc.v_front_porch = 5; + pinfo.lcdc.v_pulse_width = 6; + pinfo.lcdc.border_clr = 0; /* blk */ + pinfo.lcdc.underflow_clr = 0xff; /* blue */ + pinfo.lcdc.hsync_skew = 0; + + ret = lcdc_device_register(&pinfo); + if (ret) + printk(KERN_ERR "%s: failed to register device!\n", __func__); + + return ret; +} + +module_init(lcdc_external_init); diff --git a/drivers/staging/msm/lcdc_gordon.c b/drivers/staging/msm/lcdc_gordon.c new file mode 100644 index 000000000000..399ec8c791ec --- /dev/null +++ b/drivers/staging/msm/lcdc_gordon.c @@ -0,0 +1,446 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/delay.h> +#include <mach/gpio.h> +#include "msm_fb.h" + +/* registers */ +#define GORDON_REG_NOP 0x00 +#define GORDON_REG_IMGCTL1 0x10 +#define GORDON_REG_IMGCTL2 0x11 +#define GORDON_REG_IMGSET1 0x12 +#define GORDON_REG_IMGSET2 0x13 +#define GORDON_REG_IVBP1 0x14 +#define GORDON_REG_IHBP1 0x15 +#define GORDON_REG_IVNUM1 0x16 +#define GORDON_REG_IHNUM1 0x17 +#define GORDON_REG_IVBP2 0x18 +#define GORDON_REG_IHBP2 0x19 +#define GORDON_REG_IVNUM2 0x1A +#define GORDON_REG_IHNUM2 0x1B +#define GORDON_REG_LCDIFCTL1 0x30 +#define GORDON_REG_VALTRAN 0x31 +#define GORDON_REG_AVCTL 0x33 +#define GORDON_REG_LCDIFCTL2 0x34 +#define GORDON_REG_LCDIFCTL3 0x35 +#define GORDON_REG_LCDIFSET1 0x36 +#define GORDON_REG_PCCTL 0x3C +#define GORDON_REG_TPARAM1 0x40 +#define GORDON_REG_TLCDIF1 0x41 +#define GORDON_REG_TSSPB_ST1 0x42 +#define GORDON_REG_TSSPB_ED1 0x43 +#define GORDON_REG_TSCK_ST1 0x44 +#define GORDON_REG_TSCK_WD1 0x45 +#define GORDON_REG_TGSPB_VST1 0x46 +#define GORDON_REG_TGSPB_VED1 0x47 +#define GORDON_REG_TGSPB_CH1 0x48 +#define GORDON_REG_TGCK_ST1 0x49 +#define GORDON_REG_TGCK_ED1 0x4A +#define GORDON_REG_TPCTL_ST1 0x4B +#define GORDON_REG_TPCTL_ED1 0x4C +#define GORDON_REG_TPCHG_ED1 0x4D +#define GORDON_REG_TCOM_CH1 0x4E +#define GORDON_REG_THBP1 0x4F +#define GORDON_REG_TPHCTL1 0x50 +#define GORDON_REG_EVPH1 0x51 +#define GORDON_REG_EVPL1 0x52 +#define GORDON_REG_EVNH1 0x53 +#define GORDON_REG_EVNL1 0x54 +#define GORDON_REG_TBIAS1 0x55 +#define GORDON_REG_TPARAM2 0x56 +#define GORDON_REG_TLCDIF2 0x57 +#define GORDON_REG_TSSPB_ST2 0x58 +#define GORDON_REG_TSSPB_ED2 0x59 +#define GORDON_REG_TSCK_ST2 0x5A +#define GORDON_REG_TSCK_WD2 0x5B +#define GORDON_REG_TGSPB_VST2 0x5C +#define GORDON_REG_TGSPB_VED2 0x5D +#define GORDON_REG_TGSPB_CH2 0x5E +#define GORDON_REG_TGCK_ST2 0x5F +#define GORDON_REG_TGCK_ED2 0x60 +#define GORDON_REG_TPCTL_ST2 0x61 +#define GORDON_REG_TPCTL_ED2 0x62 +#define GORDON_REG_TPCHG_ED2 0x63 +#define GORDON_REG_TCOM_CH2 0x64 +#define GORDON_REG_THBP2 0x65 +#define GORDON_REG_TPHCTL2 0x66 +#define GORDON_REG_POWCTL 0x80 + +static int lcdc_gordon_panel_off(struct platform_device *pdev); + +static int spi_cs; +static int spi_sclk; +static int spi_sdo; +static int spi_sdi; +static int spi_dac; +static unsigned char bit_shift[8] = { (1 << 7), /* MSB */ + (1 << 6), + (1 << 5), + (1 << 4), + (1 << 3), + (1 << 2), + (1 << 1), + (1 << 0) /* LSB */ +}; + +struct gordon_state_type{ + boolean disp_initialized; + boolean display_on; + boolean disp_powered_up; +}; + +static struct gordon_state_type gordon_state = { 0 }; +static struct msm_panel_common_pdata *lcdc_gordon_pdata; + +static void serigo(uint16 reg, uint8 data) +{ + unsigned int tx_val = ((0x00FF & reg) << 8) | data; + unsigned char i, val = 0; + + /* Enable the Chip Select */ + gpio_set_value(spi_cs, 1); + udelay(33); + + /* Transmit it in two parts, Higher Byte first, then Lower Byte */ + val = (unsigned char)((tx_val & 0xFF00) >> 8); + + /* Clock should be Low before entering ! */ + for (i = 0; i < 8; i++) { + /* #1: Drive the Data (High or Low) */ + if (val & bit_shift[i]) + gpio_set_value(spi_sdi, 1); + else + gpio_set_value(spi_sdi, 0); + + /* #2: Drive the Clk High and then Low */ + udelay(33); + gpio_set_value(spi_sclk, 1); + udelay(33); + gpio_set_value(spi_sclk, 0); + } + + /* Idle state of SDO (MOSI) is Low */ + gpio_set_value(spi_sdi, 0); + /* ..then Lower Byte */ + val = (uint8) (tx_val & 0x00FF); + /* Before we enter here the Clock should be Low ! */ + + for (i = 0; i < 8; i++) { + /* #1: Drive the Data (High or Low) */ + if (val & bit_shift[i]) + gpio_set_value(spi_sdi, 1); + else + gpio_set_value(spi_sdi, 0); + + /* #2: Drive the Clk High and then Low */ + udelay(33); + + gpio_set_value(spi_sclk, 1); + udelay(33); + gpio_set_value(spi_sclk, 0); + } + + /* Idle state of SDO (MOSI) is Low */ + gpio_set_value(spi_sdi, 0); + + /* Now Disable the Chip Select */ + udelay(33); + gpio_set_value(spi_cs, 0); +} + +static void spi_init(void) +{ + /* Setting the Default GPIO's */ + spi_sclk = *(lcdc_gordon_pdata->gpio_num); + spi_cs = *(lcdc_gordon_pdata->gpio_num + 1); + spi_sdi = *(lcdc_gordon_pdata->gpio_num + 2); + spi_sdo = *(lcdc_gordon_pdata->gpio_num + 3); + + /* Set the output so that we dont disturb the slave device */ + gpio_set_value(spi_sclk, 0); + gpio_set_value(spi_sdi, 0); + + /* Set the Chip Select De-asserted */ + gpio_set_value(spi_cs, 0); + +} + +static void gordon_disp_powerup(void) +{ + if (!gordon_state.disp_powered_up && !gordon_state.display_on) { + /* Reset the hardware first */ + /* Include DAC power up implementation here */ + gordon_state.disp_powered_up = TRUE; + } +} + +static void gordon_init(void) +{ + /* Image interface settings */ + serigo(GORDON_REG_IMGCTL2, 0x00); + serigo(GORDON_REG_IMGSET1, 0x00); + + /* Exchange the RGB signal for J510(Softbank mobile) */ + serigo(GORDON_REG_IMGSET2, 0x12); + serigo(GORDON_REG_LCDIFSET1, 0x00); + + /* Pre-charge settings */ + serigo(GORDON_REG_PCCTL, 0x09); + serigo(GORDON_REG_LCDIFCTL2, 0x7B); + + mdelay(1); +} + +static void gordon_disp_on(void) +{ + if (gordon_state.disp_powered_up && !gordon_state.display_on) { + gordon_init(); + mdelay(20); + /* gordon_dispmode setting */ + serigo(GORDON_REG_TPARAM1, 0x30); + serigo(GORDON_REG_TLCDIF1, 0x00); + serigo(GORDON_REG_TSSPB_ST1, 0x8B); + serigo(GORDON_REG_TSSPB_ED1, 0x93); + serigo(GORDON_REG_TSCK_ST1, 0x88); + serigo(GORDON_REG_TSCK_WD1, 0x00); + serigo(GORDON_REG_TGSPB_VST1, 0x01); + serigo(GORDON_REG_TGSPB_VED1, 0x02); + serigo(GORDON_REG_TGSPB_CH1, 0x5E); + serigo(GORDON_REG_TGCK_ST1, 0x80); + serigo(GORDON_REG_TGCK_ED1, 0x3C); + serigo(GORDON_REG_TPCTL_ST1, 0x50); + serigo(GORDON_REG_TPCTL_ED1, 0x74); + serigo(GORDON_REG_TPCHG_ED1, 0x78); + serigo(GORDON_REG_TCOM_CH1, 0x50); + serigo(GORDON_REG_THBP1, 0x84); + serigo(GORDON_REG_TPHCTL1, 0x00); + serigo(GORDON_REG_EVPH1, 0x70); + serigo(GORDON_REG_EVPL1, 0x64); + serigo(GORDON_REG_EVNH1, 0x56); + serigo(GORDON_REG_EVNL1, 0x48); + serigo(GORDON_REG_TBIAS1, 0x88); + + /* QVGA settings */ + serigo(GORDON_REG_TPARAM2, 0x28); + serigo(GORDON_REG_TLCDIF2, 0x14); + serigo(GORDON_REG_TSSPB_ST2, 0x49); + serigo(GORDON_REG_TSSPB_ED2, 0x4B); + serigo(GORDON_REG_TSCK_ST2, 0x4A); + serigo(GORDON_REG_TSCK_WD2, 0x02); + serigo(GORDON_REG_TGSPB_VST2, 0x02); + serigo(GORDON_REG_TGSPB_VED2, 0x03); + serigo(GORDON_REG_TGSPB_CH2, 0x2F); + serigo(GORDON_REG_TGCK_ST2, 0x40); + serigo(GORDON_REG_TGCK_ED2, 0x1E); + serigo(GORDON_REG_TPCTL_ST2, 0x2C); + serigo(GORDON_REG_TPCTL_ED2, 0x3A); + serigo(GORDON_REG_TPCHG_ED2, 0x3C); + serigo(GORDON_REG_TCOM_CH2, 0x28); + serigo(GORDON_REG_THBP2, 0x4D); + serigo(GORDON_REG_TPHCTL2, 0x1A); + + /* VGA settings */ + serigo(GORDON_REG_IVBP1, 0x02); + serigo(GORDON_REG_IHBP1, 0x90); + serigo(GORDON_REG_IVNUM1, 0xA0); + serigo(GORDON_REG_IHNUM1, 0x78); + + /* QVGA settings */ + serigo(GORDON_REG_IVBP2, 0x02); + serigo(GORDON_REG_IHBP2, 0x48); + serigo(GORDON_REG_IVNUM2, 0x50); + serigo(GORDON_REG_IHNUM2, 0x3C); + + /* Gordon Charge pump settings and ON */ + serigo(GORDON_REG_POWCTL, 0x03); + mdelay(15); + serigo(GORDON_REG_POWCTL, 0x07); + mdelay(15); + + serigo(GORDON_REG_POWCTL, 0x0F); + mdelay(15); + + serigo(GORDON_REG_AVCTL, 0x03); + mdelay(15); + + serigo(GORDON_REG_POWCTL, 0x1F); + mdelay(15); + + serigo(GORDON_REG_POWCTL, 0x5F); + mdelay(15); + + serigo(GORDON_REG_POWCTL, 0x7F); + mdelay(15); + + serigo(GORDON_REG_LCDIFCTL1, 0x02); + mdelay(15); + + serigo(GORDON_REG_IMGCTL1, 0x00); + mdelay(15); + + serigo(GORDON_REG_LCDIFCTL3, 0x00); + mdelay(15); + + serigo(GORDON_REG_VALTRAN, 0x01); + mdelay(15); + + serigo(GORDON_REG_LCDIFCTL1, 0x03); + mdelay(1); + gordon_state.display_on = TRUE; + } +} + +static int lcdc_gordon_panel_on(struct platform_device *pdev) +{ + if (!gordon_state.disp_initialized) { + /* Configure reset GPIO that drives DAC */ + lcdc_gordon_pdata->panel_config_gpio(1); + spi_dac = *(lcdc_gordon_pdata->gpio_num + 4); + gpio_set_value(spi_dac, 0); + udelay(15); + gpio_set_value(spi_dac, 1); + spi_init(); /* LCD needs SPI */ + gordon_disp_powerup(); + gordon_disp_on(); + gordon_state.disp_initialized = TRUE; + } + return 0; +} + +static int lcdc_gordon_panel_off(struct platform_device *pdev) +{ + if (gordon_state.disp_powered_up && gordon_state.display_on) { + serigo(GORDON_REG_LCDIFCTL2, 0x7B); + serigo(GORDON_REG_VALTRAN, 0x01); + serigo(GORDON_REG_LCDIFCTL1, 0x02); + serigo(GORDON_REG_LCDIFCTL3, 0x01); + mdelay(20); + serigo(GORDON_REG_VALTRAN, 0x01); + serigo(GORDON_REG_IMGCTL1, 0x01); + serigo(GORDON_REG_LCDIFCTL1, 0x00); + mdelay(20); + + serigo(GORDON_REG_POWCTL, 0x1F); + mdelay(40); + + serigo(GORDON_REG_POWCTL, 0x07); + mdelay(40); + + serigo(GORDON_REG_POWCTL, 0x03); + mdelay(40); + + serigo(GORDON_REG_POWCTL, 0x00); + mdelay(40); + lcdc_gordon_pdata->panel_config_gpio(0); + gordon_state.display_on = FALSE; + gordon_state.disp_initialized = FALSE; + } + return 0; +} + +static void lcdc_gordon_set_backlight(struct msm_fb_data_type *mfd) +{ + int bl_level = mfd->bl_level; + + if (bl_level <= 1) { + /* keep back light OFF */ + serigo(GORDON_REG_LCDIFCTL2, 0x0B); + udelay(15); + serigo(GORDON_REG_VALTRAN, 0x01); + } else { + /* keep back light ON */ + serigo(GORDON_REG_LCDIFCTL2, 0x7B); + udelay(15); + serigo(GORDON_REG_VALTRAN, 0x01); + } +} + +static int __init gordon_probe(struct platform_device *pdev) +{ + if (pdev->id == 0) { + lcdc_gordon_pdata = pdev->dev.platform_data; + return 0; + } + msm_fb_add_device(pdev); + return 0; +} + +static struct platform_driver this_driver = { + .probe = gordon_probe, + .driver = { + .name = "lcdc_gordon_vga", + }, +}; + +static struct msm_fb_panel_data gordon_panel_data = { + .on = lcdc_gordon_panel_on, + .off = lcdc_gordon_panel_off, + .set_backlight = lcdc_gordon_set_backlight, +}; + +static struct platform_device this_device = { + .name = "lcdc_gordon_vga", + .id = 1, + .dev = { + .platform_data = &gordon_panel_data, + } +}; + +static int __init lcdc_gordon_panel_init(void) +{ + int ret; + struct msm_panel_info *pinfo; + +#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM + if (msm_fb_detect_client("lcdc_gordon_vga")) + return 0; +#endif + ret = platform_driver_register(&this_driver); + if (ret) + return ret; + + pinfo = &gordon_panel_data.panel_info; + pinfo->xres = 480; + pinfo->yres = 640; + pinfo->type = LCDC_PANEL; + pinfo->pdest = DISPLAY_1; + pinfo->wait_cycle = 0; + pinfo->bpp = 24; + pinfo->fb_num = 2; + pinfo->clk_rate = 24500000; + pinfo->bl_max = 4; + pinfo->bl_min = 1; + + pinfo->lcdc.h_back_porch = 84; + pinfo->lcdc.h_front_porch = 33; + pinfo->lcdc.h_pulse_width = 60; + pinfo->lcdc.v_back_porch = 0; + pinfo->lcdc.v_front_porch = 2; + pinfo->lcdc.v_pulse_width = 2; + pinfo->lcdc.border_clr = 0; /* blk */ + pinfo->lcdc.underflow_clr = 0xff; /* blue */ + pinfo->lcdc.hsync_skew = 0; + + ret = platform_device_register(&this_device); + if (ret) + platform_driver_unregister(&this_driver); + + return ret; +} + +module_init(lcdc_gordon_panel_init); diff --git a/drivers/staging/msm/lcdc_grapefruit.c b/drivers/staging/msm/lcdc_grapefruit.c new file mode 100644 index 000000000000..7284649ea0ae --- /dev/null +++ b/drivers/staging/msm/lcdc_grapefruit.c @@ -0,0 +1,60 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" + +#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM +#include "mddihosti.h" +#endif + +static int __init lcdc_grapefruit_init(void) +{ + int ret; + struct msm_panel_info pinfo; + +#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM + if (msm_fb_detect_client("lcdc_grapefruit_vga")) + return 0; +#endif + + pinfo.xres = 1024; + pinfo.yres = 600; + pinfo.type = LCDC_PANEL; + pinfo.pdest = DISPLAY_1; + pinfo.wait_cycle = 0; + pinfo.bpp = 18; + pinfo.fb_num = 2; + pinfo.clk_rate = 40000000; + + pinfo.lcdc.h_back_porch = 88; + pinfo.lcdc.h_front_porch = 40; + pinfo.lcdc.h_pulse_width = 128; + pinfo.lcdc.v_back_porch = 23; + pinfo.lcdc.v_front_porch = 1; + pinfo.lcdc.v_pulse_width = 4; + pinfo.lcdc.border_clr = 0; /* blk */ + pinfo.lcdc.underflow_clr = 0xff; /* blue */ + pinfo.lcdc.hsync_skew = 0; + + ret = lcdc_device_register(&pinfo); + if (ret) + printk(KERN_ERR "%s: failed to register device!\n", __func__); + + return ret; +} + +module_init(lcdc_grapefruit_init); diff --git a/drivers/staging/msm/lcdc_panel.c b/drivers/staging/msm/lcdc_panel.c new file mode 100644 index 000000000000..b40974e1f27c --- /dev/null +++ b/drivers/staging/msm/lcdc_panel.c @@ -0,0 +1,88 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" + +static int lcdc_panel_on(struct platform_device *pdev) +{ + return 0; +} + +static int lcdc_panel_off(struct platform_device *pdev) +{ + return 0; +} + +static int __init lcdc_panel_probe(struct platform_device *pdev) +{ + msm_fb_add_device(pdev); + + return 0; +} + +static struct platform_driver this_driver = { + .probe = lcdc_panel_probe, + .driver = { + .name = "lcdc_panel", + }, +}; + +static struct msm_fb_panel_data lcdc_panel_data = { + .on = lcdc_panel_on, + .off = lcdc_panel_off, +}; + +static int lcdc_dev_id; + +int lcdc_device_register(struct msm_panel_info *pinfo) +{ + struct platform_device *pdev = NULL; + int ret; + + pdev = platform_device_alloc("lcdc_panel", ++lcdc_dev_id); + if (!pdev) + return -ENOMEM; + + lcdc_panel_data.panel_info = *pinfo; + ret = platform_device_add_data(pdev, &lcdc_panel_data, + sizeof(lcdc_panel_data)); + if (ret) { + printk(KERN_ERR + "%s: platform_device_add_data failed!\n", __func__); + goto err_device_put; + } + + ret = platform_device_add(pdev); + if (ret) { + printk(KERN_ERR + "%s: platform_device_register failed!\n", __func__); + goto err_device_put; + } + + return 0; + +err_device_put: + platform_device_put(pdev); + return ret; +} + +static int __init lcdc_panel_init(void) +{ + return platform_driver_register(&this_driver); +} + +module_init(lcdc_panel_init); diff --git a/drivers/staging/msm/lcdc_prism.c b/drivers/staging/msm/lcdc_prism.c new file mode 100644 index 000000000000..d102c98447c1 --- /dev/null +++ b/drivers/staging/msm/lcdc_prism.c @@ -0,0 +1,64 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" + +#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM +#include "mddihosti.h" +#endif + +static int __init lcdc_prism_init(void) +{ + int ret; + struct msm_panel_info pinfo; + +#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM + ret = msm_fb_detect_client("lcdc_prism_wvga"); + if (ret == -ENODEV) + return 0; + + if (ret && (mddi_get_client_id() != 0)) + return 0; +#endif + + pinfo.xres = 800; + pinfo.yres = 480; + pinfo.type = LCDC_PANEL; + pinfo.pdest = DISPLAY_1; + pinfo.wait_cycle = 0; + pinfo.bpp = 24; + pinfo.fb_num = 2; + pinfo.clk_rate = 38460000; + + pinfo.lcdc.h_back_porch = 21; + pinfo.lcdc.h_front_porch = 81; + pinfo.lcdc.h_pulse_width = 60; + pinfo.lcdc.v_back_porch = 18; + pinfo.lcdc.v_front_porch = 27; + pinfo.lcdc.v_pulse_width = 2; + pinfo.lcdc.border_clr = 0; /* blk */ + pinfo.lcdc.underflow_clr = 0xff; /* blue */ + pinfo.lcdc.hsync_skew = 0; + + ret = lcdc_device_register(&pinfo); + if (ret) + printk(KERN_ERR "%s: failed to register device!\n", __func__); + + return ret; +} + +module_init(lcdc_prism_init); diff --git a/drivers/staging/msm/lcdc_sharp_wvga_pt.c b/drivers/staging/msm/lcdc_sharp_wvga_pt.c new file mode 100644 index 000000000000..1f08cf9bc217 --- /dev/null +++ b/drivers/staging/msm/lcdc_sharp_wvga_pt.c @@ -0,0 +1,290 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/delay.h> +#ifdef CONFIG_ARCH_MSM7X30 +#include <linux/mfd/pmic8058.h> +#endif +#include <mach/gpio.h> +#include "msm_fb.h" + +static int lcdc_sharp_panel_off(struct platform_device *pdev); + +static int spi_cs; +static int spi_sclk; +static int spi_mosi; +static int spi_miso; +static unsigned char bit_shift[8] = { (1 << 7), /* MSB */ + (1 << 6), + (1 << 5), + (1 << 4), + (1 << 3), + (1 << 2), + (1 << 1), + (1 << 0) /* LSB */ +}; + +struct sharp_state_type { + boolean disp_initialized; + boolean display_on; + boolean disp_powered_up; +}; + +struct sharp_spi_data { + u8 addr; + u8 data; +}; + +static struct sharp_spi_data init_sequence[] = { + { 15, 0x01 }, + { 5, 0x01 }, + { 7, 0x10 }, + { 9, 0x1E }, + { 10, 0x04 }, + { 17, 0xFF }, + { 21, 0x8A }, + { 22, 0x00 }, + { 23, 0x82 }, + { 24, 0x24 }, + { 25, 0x22 }, + { 26, 0x6D }, + { 27, 0xEB }, + { 28, 0xB9 }, + { 29, 0x3A }, + { 49, 0x1A }, + { 50, 0x16 }, + { 51, 0x05 }, + { 55, 0x7F }, + { 56, 0x15 }, + { 57, 0x7B }, + { 60, 0x05 }, + { 61, 0x0C }, + { 62, 0x80 }, + { 63, 0x00 }, + { 92, 0x90 }, + { 97, 0x01 }, + { 98, 0xFF }, + { 113, 0x11 }, + { 114, 0x02 }, + { 115, 0x08 }, + { 123, 0xAB }, + { 124, 0x04 }, + { 6, 0x02 }, + { 133, 0x00 }, + { 134, 0xFE }, + { 135, 0x22 }, + { 136, 0x0B }, + { 137, 0xFF }, + { 138, 0x0F }, + { 139, 0x00 }, + { 140, 0xFE }, + { 141, 0x22 }, + { 142, 0x0B }, + { 143, 0xFF }, + { 144, 0x0F }, + { 145, 0x00 }, + { 146, 0xFE }, + { 147, 0x22 }, + { 148, 0x0B }, + { 149, 0xFF }, + { 150, 0x0F }, + { 202, 0x30 }, + { 30, 0x01 }, + { 4, 0x01 }, + { 31, 0x41 }, +}; + +static struct sharp_state_type sharp_state = { 0 }; +static struct msm_panel_common_pdata *lcdc_sharp_pdata; + +static void sharp_spi_write_byte(u8 val) +{ + int i; + + /* Clock should be Low before entering */ + for (i = 0; i < 8; i++) { + /* #1: Drive the Data (High or Low) */ + if (val & bit_shift[i]) + gpio_set_value(spi_mosi, 1); + else + gpio_set_value(spi_mosi, 0); + + /* #2: Drive the Clk High and then Low */ + gpio_set_value(spi_sclk, 1); + gpio_set_value(spi_sclk, 0); + } +} + +static void serigo(u8 reg, u8 data) +{ + /* Enable the Chip Select - low */ + gpio_set_value(spi_cs, 0); + udelay(1); + + /* Transmit register address first, then data */ + sharp_spi_write_byte(reg); + + /* Idle state of MOSI is Low */ + gpio_set_value(spi_mosi, 0); + udelay(1); + sharp_spi_write_byte(data); + + gpio_set_value(spi_mosi, 0); + gpio_set_value(spi_cs, 1); +} + +static void sharp_spi_init(void) +{ + spi_sclk = *(lcdc_sharp_pdata->gpio_num); + spi_cs = *(lcdc_sharp_pdata->gpio_num + 1); + spi_mosi = *(lcdc_sharp_pdata->gpio_num + 2); + spi_miso = *(lcdc_sharp_pdata->gpio_num + 3); + + /* Set the output so that we don't disturb the slave device */ + gpio_set_value(spi_sclk, 0); + gpio_set_value(spi_mosi, 0); + + /* Set the Chip Select deasserted (active low) */ + gpio_set_value(spi_cs, 1); +} + +static void sharp_disp_powerup(void) +{ + if (!sharp_state.disp_powered_up && !sharp_state.display_on) + sharp_state.disp_powered_up = TRUE; +} + +static void sharp_disp_on(void) +{ + int i; + + if (sharp_state.disp_powered_up && !sharp_state.display_on) { + for (i = 0; i < ARRAY_SIZE(init_sequence); i++) { + serigo(init_sequence[i].addr, + init_sequence[i].data); + } + mdelay(10); + serigo(31, 0xC1); + mdelay(10); + serigo(31, 0xD9); + serigo(31, 0xDF); + + sharp_state.display_on = TRUE; + } +} + +static int lcdc_sharp_panel_on(struct platform_device *pdev) +{ + if (!sharp_state.disp_initialized) { + lcdc_sharp_pdata->panel_config_gpio(1); + sharp_spi_init(); + sharp_disp_powerup(); + sharp_disp_on(); + sharp_state.disp_initialized = TRUE; + } + return 0; +} + +static int lcdc_sharp_panel_off(struct platform_device *pdev) +{ + if (sharp_state.disp_powered_up && sharp_state.display_on) { + serigo(4, 0x00); + mdelay(40); + serigo(31, 0xC1); + mdelay(40); + serigo(31, 0x00); + mdelay(100); + sharp_state.display_on = FALSE; + sharp_state.disp_initialized = FALSE; + } + return 0; +} + +static int __init sharp_probe(struct platform_device *pdev) +{ + if (pdev->id == 0) { + lcdc_sharp_pdata = pdev->dev.platform_data; + return 0; + } + msm_fb_add_device(pdev); + return 0; +} + +static struct platform_driver this_driver = { + .probe = sharp_probe, + .driver = { + .name = "lcdc_sharp_wvga", + }, +}; + +static struct msm_fb_panel_data sharp_panel_data = { + .on = lcdc_sharp_panel_on, + .off = lcdc_sharp_panel_off, +}; + +static struct platform_device this_device = { + .name = "lcdc_sharp_wvga", + .id = 1, + .dev = { + .platform_data = &sharp_panel_data, + } +}; + +static int __init lcdc_sharp_panel_init(void) +{ + int ret; + struct msm_panel_info *pinfo; + +#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT + if (msm_fb_detect_client("lcdc_sharp_wvga_pt")) + return 0; +#endif + + ret = platform_driver_register(&this_driver); + if (ret) + return ret; + + pinfo = &sharp_panel_data.panel_info; + pinfo->xres = 480; + pinfo->yres = 800; + pinfo->type = LCDC_PANEL; + pinfo->pdest = DISPLAY_1; + pinfo->wait_cycle = 0; + pinfo->bpp = 18; + pinfo->fb_num = 2; + pinfo->clk_rate = 24500000; + pinfo->bl_max = 4; + pinfo->bl_min = 1; + + pinfo->lcdc.h_back_porch = 20; + pinfo->lcdc.h_front_porch = 10; + pinfo->lcdc.h_pulse_width = 10; + pinfo->lcdc.v_back_porch = 2; + pinfo->lcdc.v_front_porch = 2; + pinfo->lcdc.v_pulse_width = 2; + pinfo->lcdc.border_clr = 0; + pinfo->lcdc.underflow_clr = 0xff; + pinfo->lcdc.hsync_skew = 0; + + ret = platform_device_register(&this_device); + if (ret) + platform_driver_unregister(&this_driver); + + return ret; +} + +module_init(lcdc_sharp_panel_init); diff --git a/drivers/staging/msm/lcdc_st15.c b/drivers/staging/msm/lcdc_st15.c new file mode 100644 index 000000000000..fed8278eb153 --- /dev/null +++ b/drivers/staging/msm/lcdc_st15.c @@ -0,0 +1,237 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/i2c.h> +#include <linux/delay.h> +#include "msm_fb.h" + +#define DEVICE_NAME "sii9022" +#define SII9022_DEVICE_ID 0xB0 + +struct sii9022_i2c_addr_data{ + u8 addr; + u8 data; +}; + +/* video mode data */ +static u8 video_mode_data[] = { + 0x00, + 0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02, +}; + +static u8 avi_io_format[] = { + 0x09, + 0x00, 0x00, +}; + +/* power state */ +static struct sii9022_i2c_addr_data regset0[] = { + { 0x60, 0x04 }, + { 0x63, 0x00 }, + { 0x1E, 0x00 }, +}; + +static u8 video_infoframe[] = { + 0x0C, + 0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00, + 0xE9, 0x02, 0x04, 0x01, 0x04, 0x06, +}; + +/* configure audio */ +static struct sii9022_i2c_addr_data regset1[] = { + { 0x26, 0x90 }, + { 0x20, 0x90 }, + { 0x1F, 0x80 }, + { 0x26, 0x80 }, + { 0x24, 0x02 }, + { 0x25, 0x0B }, + { 0xBC, 0x02 }, + { 0xBD, 0x24 }, + { 0xBE, 0x02 }, +}; + +/* enable audio */ +static u8 misc_infoframe[] = { + 0xBF, + 0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +/* set HDMI, active */ +static struct sii9022_i2c_addr_data regset2[] = { + { 0x1A, 0x01 }, + { 0x3D, 0x00 }, +}; + +static int send_i2c_data(struct i2c_client *client, + struct sii9022_i2c_addr_data *regset, + int size) +{ + int i; + int rc = 0; + + for (i = 0; i < size; i++) { + rc = i2c_smbus_write_byte_data( + client, + regset[i].addr, regset[i].data); + if (rc) + break; + } + return rc; +} + +static int hdmi_sii_enable(struct i2c_client *client) +{ + int rc; + int retries = 10; + int count; + + rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00); + if (rc) + goto enable_exit; + + do { + msleep(1); + rc = i2c_smbus_read_byte_data(client, 0x1B); + } while ((rc != SII9022_DEVICE_ID) && retries--); + + if (rc != SII9022_DEVICE_ID) + return -ENODEV; + + rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11); + if (rc) + goto enable_exit; + + count = ARRAY_SIZE(video_mode_data); + rc = i2c_master_send(client, video_mode_data, count); + if (rc != count) { + rc = -EIO; + goto enable_exit; + } + + rc = i2c_smbus_write_byte_data(client, 0x08, 0x20); + if (rc) + goto enable_exit; + count = ARRAY_SIZE(avi_io_format); + rc = i2c_master_send(client, avi_io_format, count); + if (rc != count) { + rc = -EIO; + goto enable_exit; + } + + rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0)); + if (rc) + goto enable_exit; + + count = ARRAY_SIZE(video_infoframe); + rc = i2c_master_send(client, video_infoframe, count); + if (rc != count) { + rc = -EIO; + goto enable_exit; + } + + rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1)); + if (rc) + goto enable_exit; + + count = ARRAY_SIZE(misc_infoframe); + rc = i2c_master_send(client, misc_infoframe, count); + if (rc != count) { + rc = -EIO; + goto enable_exit; + } + + rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2)); + if (rc) + goto enable_exit; + + return 0; +enable_exit: + printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc); + return rc; +} + +static const struct i2c_device_id hmdi_sii_id[] = { + { DEVICE_NAME, 0 }, + { } +}; + +static int hdmi_sii_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int rc; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C)) + return -ENODEV; + rc = hdmi_sii_enable(client); + return rc; +} + + +static struct i2c_driver hdmi_sii_i2c_driver = { + .driver = { + .name = DEVICE_NAME, + .owner = THIS_MODULE, + }, + .probe = hdmi_sii_probe, + .remove = __exit_p(hdmi_sii_remove), + .id_table = hmdi_sii_id, +}; + +static int __init lcdc_st15_init(void) +{ + int ret; + struct msm_panel_info pinfo; + + if (msm_fb_detect_client("lcdc_st15")) + return 0; + + pinfo.xres = 1366; + pinfo.yres = 768; + pinfo.type = LCDC_PANEL; + pinfo.pdest = DISPLAY_1; + pinfo.wait_cycle = 0; + pinfo.bpp = 24; + pinfo.fb_num = 2; + pinfo.clk_rate = 74250000; + + pinfo.lcdc.h_back_porch = 120; + pinfo.lcdc.h_front_porch = 20; + pinfo.lcdc.h_pulse_width = 40; + pinfo.lcdc.v_back_porch = 25; + pinfo.lcdc.v_front_porch = 1; + pinfo.lcdc.v_pulse_width = 7; + pinfo.lcdc.border_clr = 0; /* blk */ + pinfo.lcdc.underflow_clr = 0xff; /* blue */ + pinfo.lcdc.hsync_skew = 0; + + ret = lcdc_device_register(&pinfo); + if (ret) { + printk(KERN_ERR "%s: failed to register device!\n", __func__); + goto init_exit; + } + + ret = i2c_add_driver(&hdmi_sii_i2c_driver); + if (ret) + printk(KERN_ERR "%s: failed to add i2c driver\n", __func__); + +init_exit: + return ret; +} + +module_init(lcdc_st15_init); diff --git a/drivers/staging/msm/lcdc_st1_wxga.c b/drivers/staging/msm/lcdc_st1_wxga.c new file mode 100644 index 000000000000..73760019cf2e --- /dev/null +++ b/drivers/staging/msm/lcdc_st1_wxga.c @@ -0,0 +1,54 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" + +static int __init lcdc_st1_wxga_init(void) +{ + int ret; + struct msm_panel_info pinfo; + + if (msm_fb_detect_client("lcdc_st1_wxga")) + return 0; + + pinfo.xres = 1280; + pinfo.yres = 720; + pinfo.type = LCDC_PANEL; + pinfo.pdest = DISPLAY_1; + pinfo.wait_cycle = 0; + pinfo.bpp = 18; + pinfo.fb_num = 2; + pinfo.clk_rate = 74250000; + + pinfo.lcdc.h_back_porch = 124; + pinfo.lcdc.h_front_porch = 110; + pinfo.lcdc.h_pulse_width = 136; + pinfo.lcdc.v_back_porch = 19; + pinfo.lcdc.v_front_porch = 5; + pinfo.lcdc.v_pulse_width = 6; + pinfo.lcdc.border_clr = 0; /* blk */ + pinfo.lcdc.underflow_clr = 0xff; /* blue */ + pinfo.lcdc.hsync_skew = 0; + + ret = lcdc_device_register(&pinfo); + if (ret) + printk(KERN_ERR "%s: failed to register device!\n", __func__); + + return ret; +} + +module_init(lcdc_st1_wxga_init); diff --git a/drivers/staging/msm/lcdc_toshiba_wvga_pt.c b/drivers/staging/msm/lcdc_toshiba_wvga_pt.c new file mode 100644 index 000000000000..864d7c18913d --- /dev/null +++ b/drivers/staging/msm/lcdc_toshiba_wvga_pt.c @@ -0,0 +1,374 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/delay.h> +#include <linux/module.h> +#include <mach/gpio.h> +#include <mach/pmic.h> +#include "msm_fb.h" + +#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM +#include "mddihosti.h" +#endif + +static int spi_cs; +static int spi_sclk; +static int spi_mosi; +static int spi_miso; + +struct toshiba_state_type{ + boolean disp_initialized; + boolean display_on; + boolean disp_powered_up; +}; + +static struct toshiba_state_type toshiba_state = { 0 }; +static struct msm_panel_common_pdata *lcdc_toshiba_pdata; + +static void toshiba_spi_write_byte(char dc, uint8 data) +{ + uint32 bit; + int bnum; + + gpio_set_value(spi_sclk, 0); /* clk low */ + /* dc: 0 for command, 1 for parameter */ + gpio_set_value(spi_mosi, dc); + udelay(1); /* at least 20 ns */ + gpio_set_value(spi_sclk, 1); /* clk high */ + udelay(1); /* at least 20 ns */ + bnum = 8; /* 8 data bits */ + bit = 0x80; + while (bnum) { + gpio_set_value(spi_sclk, 0); /* clk low */ + if (data & bit) + gpio_set_value(spi_mosi, 1); + else + gpio_set_value(spi_mosi, 0); + udelay(1); + gpio_set_value(spi_sclk, 1); /* clk high */ + udelay(1); + bit >>= 1; + bnum--; + } +} + +static void toshiba_spi_write(char cmd, uint32 data, int num) +{ + char *bp; + + gpio_set_value(spi_cs, 1); /* cs high */ + + /* command byte first */ + toshiba_spi_write_byte(0, cmd); + + /* followed by parameter bytes */ + if (num) { + bp = (char *)&data;; + bp += (num - 1); + while (num) { + toshiba_spi_write_byte(1, *bp); + num--; + bp--; + } + } + + gpio_set_value(spi_cs, 0); /* cs low */ + udelay(1); +} + +void toshiba_spi_read_bytes(char cmd, uint32 *data, int num) +{ + uint32 dbit, bits; + int bnum; + + gpio_set_value(spi_cs, 1); /* cs high */ + + /* command byte first */ + toshiba_spi_write_byte(0, cmd); + + if (num > 1) { + /* extra dc bit */ + gpio_set_value(spi_sclk, 0); /* clk low */ + udelay(1); + dbit = gpio_get_value(spi_miso);/* dc bit */ + udelay(1); + gpio_set_value(spi_sclk, 1); /* clk high */ + } + + /* followed by data bytes */ + bnum = num * 8; /* number of bits */ + bits = 0; + while (bnum) { + bits <<= 1; + gpio_set_value(spi_sclk, 0); /* clk low */ + udelay(1); + dbit = gpio_get_value(spi_miso); + udelay(1); + gpio_set_value(spi_sclk, 1); /* clk high */ + bits |= dbit; + bnum--; + } + + *data = bits; + + udelay(1); + gpio_set_value(spi_cs, 0); /* cs low */ + udelay(1); +} + +static void spi_pin_assign(void) +{ + /* Setting the Default GPIO's */ + spi_sclk = *(lcdc_toshiba_pdata->gpio_num); + spi_cs = *(lcdc_toshiba_pdata->gpio_num + 1); + spi_mosi = *(lcdc_toshiba_pdata->gpio_num + 2); + spi_miso = *(lcdc_toshiba_pdata->gpio_num + 3); +} + +static void toshiba_disp_powerup(void) +{ + if (!toshiba_state.disp_powered_up && !toshiba_state.display_on) { + /* Reset the hardware first */ + /* Include DAC power up implementation here */ + toshiba_state.disp_powered_up = TRUE; + } +} + +static void toshiba_disp_on(void) +{ + uint32 data; + + gpio_set_value(spi_cs, 0); /* low */ + gpio_set_value(spi_sclk, 1); /* high */ + gpio_set_value(spi_mosi, 0); + gpio_set_value(spi_miso, 0); + + if (toshiba_state.disp_powered_up && !toshiba_state.display_on) { + toshiba_spi_write(0, 0, 0); + mdelay(7); + toshiba_spi_write(0, 0, 0); + mdelay(7); + toshiba_spi_write(0, 0, 0); + mdelay(7); + toshiba_spi_write(0xba, 0x11, 1); + toshiba_spi_write(0x36, 0x00, 1); + mdelay(1); + toshiba_spi_write(0x3a, 0x60, 1); + toshiba_spi_write(0xb1, 0x5d, 1); + mdelay(1); + toshiba_spi_write(0xb2, 0x33, 1); + toshiba_spi_write(0xb3, 0x22, 1); + mdelay(1); + toshiba_spi_write(0xb4, 0x02, 1); + toshiba_spi_write(0xb5, 0x1e, 1); /* vcs -- adjust brightness */ + mdelay(1); + toshiba_spi_write(0xb6, 0x27, 1); + toshiba_spi_write(0xb7, 0x03, 1); + mdelay(1); + toshiba_spi_write(0xb9, 0x24, 1); + toshiba_spi_write(0xbd, 0xa1, 1); + mdelay(1); + toshiba_spi_write(0xbb, 0x00, 1); + toshiba_spi_write(0xbf, 0x01, 1); + mdelay(1); + toshiba_spi_write(0xbe, 0x00, 1); + toshiba_spi_write(0xc0, 0x11, 1); + mdelay(1); + toshiba_spi_write(0xc1, 0x11, 1); + toshiba_spi_write(0xc2, 0x11, 1); + mdelay(1); + toshiba_spi_write(0xc3, 0x3232, 2); + mdelay(1); + toshiba_spi_write(0xc4, 0x3232, 2); + mdelay(1); + toshiba_spi_write(0xc5, 0x3232, 2); + mdelay(1); + toshiba_spi_write(0xc6, 0x3232, 2); + mdelay(1); + toshiba_spi_write(0xc7, 0x6445, 2); + mdelay(1); + toshiba_spi_write(0xc8, 0x44, 1); + toshiba_spi_write(0xc9, 0x52, 1); + mdelay(1); + toshiba_spi_write(0xca, 0x00, 1); + mdelay(1); + toshiba_spi_write(0xec, 0x02a4, 2); /* 0x02a4 */ + mdelay(1); + toshiba_spi_write(0xcf, 0x01, 1); + mdelay(1); + toshiba_spi_write(0xd0, 0xc003, 2); /* c003 */ + mdelay(1); + toshiba_spi_write(0xd1, 0x01, 1); + mdelay(1); + toshiba_spi_write(0xd2, 0x0028, 2); + mdelay(1); + toshiba_spi_write(0xd3, 0x0028, 2); + mdelay(1); + toshiba_spi_write(0xd4, 0x26a4, 2); + mdelay(1); + toshiba_spi_write(0xd5, 0x20, 1); + mdelay(1); + toshiba_spi_write(0xef, 0x3200, 2); + mdelay(32); + toshiba_spi_write(0xbc, 0x80, 1); /* wvga pass through */ + toshiba_spi_write(0x3b, 0x00, 1); + mdelay(1); + toshiba_spi_write(0xb0, 0x16, 1); + mdelay(1); + toshiba_spi_write(0xb8, 0xfff5, 2); + mdelay(1); + toshiba_spi_write(0x11, 0, 0); + mdelay(5); + toshiba_spi_write(0x29, 0, 0); + mdelay(5); + toshiba_state.display_on = TRUE; + } + + data = 0; + toshiba_spi_read_bytes(0x04, &data, 3); + printk(KERN_INFO "toshiba_disp_on: id=%x\n", data); + +} + +static int lcdc_toshiba_panel_on(struct platform_device *pdev) +{ + if (!toshiba_state.disp_initialized) { + /* Configure reset GPIO that drives DAC */ + if (lcdc_toshiba_pdata->panel_config_gpio) + lcdc_toshiba_pdata->panel_config_gpio(1); + toshiba_disp_powerup(); + toshiba_disp_on(); + toshiba_state.disp_initialized = TRUE; + } + return 0; +} + +static int lcdc_toshiba_panel_off(struct platform_device *pdev) +{ + if (toshiba_state.disp_powered_up && toshiba_state.display_on) { + /* Main panel power off (Deep standby in) */ + + toshiba_spi_write(0x28, 0, 0); /* display off */ + mdelay(1); + toshiba_spi_write(0xb8, 0x8002, 2); /* output control */ + mdelay(1); + toshiba_spi_write(0x10, 0x00, 1); /* sleep mode in */ + mdelay(85); /* wait 85 msec */ + toshiba_spi_write(0xb0, 0x00, 1); /* deep standby in */ + mdelay(1); + if (lcdc_toshiba_pdata->panel_config_gpio) + lcdc_toshiba_pdata->panel_config_gpio(0); + toshiba_state.display_on = FALSE; + toshiba_state.disp_initialized = FALSE; + } + return 0; +} + +static void lcdc_toshiba_set_backlight(struct msm_fb_data_type *mfd) +{ + int bl_level; + int ret = -EPERM; + + bl_level = mfd->bl_level; + ret = pmic_set_led_intensity(LED_LCD, bl_level); + + if (ret) + printk(KERN_WARNING "%s: can't set lcd backlight!\n", + __func__); +} + +static int __init toshiba_probe(struct platform_device *pdev) +{ + if (pdev->id == 0) { + lcdc_toshiba_pdata = pdev->dev.platform_data; + spi_pin_assign(); + return 0; + } + msm_fb_add_device(pdev); + return 0; +} + +static struct platform_driver this_driver = { + .probe = toshiba_probe, + .driver = { + .name = "lcdc_toshiba_wvga", + }, +}; + +static struct msm_fb_panel_data toshiba_panel_data = { + .on = lcdc_toshiba_panel_on, + .off = lcdc_toshiba_panel_off, + .set_backlight = lcdc_toshiba_set_backlight, +}; + +static struct platform_device this_device = { + .name = "lcdc_toshiba_wvga", + .id = 1, + .dev = { + .platform_data = &toshiba_panel_data, + } +}; + +static int __init lcdc_toshiba_panel_init(void) +{ + int ret; + struct msm_panel_info *pinfo; +#ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM + if (mddi_get_client_id() != 0) + return 0; + + ret = msm_fb_detect_client("lcdc_toshiba_wvga_pt"); + if (ret) + return 0; + +#endif + + ret = platform_driver_register(&this_driver); + if (ret) + return ret; + + pinfo = &toshiba_panel_data.panel_info; + pinfo->xres = 480; + pinfo->yres = 800; + pinfo->type = LCDC_PANEL; + pinfo->pdest = DISPLAY_1; + pinfo->wait_cycle = 0; + pinfo->bpp = 18; + pinfo->fb_num = 2; + /* 30Mhz mdp_lcdc_pclk and mdp_lcdc_pad_pcl */ + pinfo->clk_rate = 27648000; + pinfo->bl_max = 15; + pinfo->bl_min = 1; + + pinfo->lcdc.h_back_porch = 184; /* hsw = 8 + hbp=184 */ + pinfo->lcdc.h_front_porch = 4; + pinfo->lcdc.h_pulse_width = 8; + pinfo->lcdc.v_back_porch = 2; /* vsw=1 + vbp = 2 */ + pinfo->lcdc.v_front_porch = 3; + pinfo->lcdc.v_pulse_width = 1; + pinfo->lcdc.border_clr = 0; /* blk */ + pinfo->lcdc.underflow_clr = 0xff; /* blue */ + pinfo->lcdc.hsync_skew = 0; + + ret = platform_device_register(&this_device); + if (ret) + platform_driver_unregister(&this_driver); + + return ret; +} + +device_initcall(lcdc_toshiba_panel_init); diff --git a/drivers/staging/msm/lcdc_wxga.c b/drivers/staging/msm/lcdc_wxga.c new file mode 100644 index 000000000000..202c92c0ef54 --- /dev/null +++ b/drivers/staging/msm/lcdc_wxga.c @@ -0,0 +1,56 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" + +static int __init lcdc_wxga_init(void) +{ + int ret; + struct msm_panel_info pinfo; + +#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT + if (msm_fb_detect_client("lcdc_wxga")) + return 0; +#endif + + pinfo.xres = 1280; + pinfo.yres = 720; + pinfo.type = LCDC_PANEL; + pinfo.pdest = DISPLAY_1; + pinfo.wait_cycle = 0; + pinfo.bpp = 24; + pinfo.fb_num = 2; + pinfo.clk_rate = 74250000; + + pinfo.lcdc.h_back_porch = 124; + pinfo.lcdc.h_front_porch = 110; + pinfo.lcdc.h_pulse_width = 136; + pinfo.lcdc.v_back_porch = 19; + pinfo.lcdc.v_front_porch = 5; + pinfo.lcdc.v_pulse_width = 6; + pinfo.lcdc.border_clr = 0; /* blk */ + pinfo.lcdc.underflow_clr = 0xff; /* blue */ + pinfo.lcdc.hsync_skew = 0; + + ret = lcdc_device_register(&pinfo); + if (ret) + printk(KERN_ERR "%s: failed to register device!\n", __func__); + + return ret; +} + +module_init(lcdc_wxga_init); diff --git a/drivers/staging/msm/logo.c b/drivers/staging/msm/logo.c new file mode 100644 index 000000000000..7272765f48cd --- /dev/null +++ b/drivers/staging/msm/logo.c @@ -0,0 +1,98 @@ +/* drivers/video/msm/logo.c + * + * Show Logo in RLE 565 format + * + * Copyright (C) 2008 Google Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include <linux/module.h> +#include <linux/types.h> +#include <linux/fb.h> +#include <linux/vt_kern.h> +#include <linux/unistd.h> +#include <linux/syscalls.h> + +#include <linux/irq.h> +#include <asm/system.h> + +#define fb_width(fb) ((fb)->var.xres) +#define fb_height(fb) ((fb)->var.yres) +#define fb_size(fb) ((fb)->var.xres * (fb)->var.yres * 2) + +static void memset16(void *_ptr, unsigned short val, unsigned count) +{ + unsigned short *ptr = _ptr; + count >>= 1; + while (count--) + *ptr++ = val; +} + +/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ +int load_565rle_image(char *filename) +{ + struct fb_info *info; + int fd, err = 0; + unsigned count, max; + unsigned short *data, *bits, *ptr; + + info = registered_fb[0]; + if (!info) { + printk(KERN_WARNING "%s: Can not access framebuffer\n", + __func__); + return -ENODEV; + } + + fd = sys_open(filename, O_RDONLY, 0); + if (fd < 0) { + printk(KERN_WARNING "%s: Can not open %s\n", + __func__, filename); + return -ENOENT; + } + count = (unsigned)sys_lseek(fd, (off_t)0, 2); + if (count == 0) { + sys_close(fd); + err = -EIO; + goto err_logo_close_file; + } + sys_lseek(fd, (off_t)0, 0); + data = kmalloc(count, GFP_KERNEL); + if (!data) { + printk(KERN_WARNING "%s: Can not alloc data\n", __func__); + err = -ENOMEM; + goto err_logo_close_file; + } + if ((unsigned)sys_read(fd, (char *)data, count) != count) { + err = -EIO; + goto err_logo_free_data; + } + + max = fb_width(info) * fb_height(info); + ptr = data; + bits = (unsigned short *)(info->screen_base); + while (count > 3) { + unsigned n = ptr[0]; + if (n > max) + break; + memset16(bits, ptr[1], n << 1); + bits += n; + max -= n; + ptr += 2; + count -= 4; + } + +err_logo_free_data: + kfree(data); +err_logo_close_file: + sys_close(fd); + return err; +} +EXPORT_SYMBOL(load_565rle_image); diff --git a/drivers/staging/msm/mddi.c b/drivers/staging/msm/mddi.c new file mode 100644 index 000000000000..132eb1adff16 --- /dev/null +++ b/drivers/staging/msm/mddi.c @@ -0,0 +1,375 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/delay.h> +#include <mach/hardware.h> +#include <asm/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/uaccess.h> +#include <linux/clk.h> +#include <linux/platform_device.h> + +#include "msm_fb.h" +#include "mddihosti.h" +#include "mddihost.h" +#include <mach/gpio.h> +#include <mach/clk.h> + +static int mddi_probe(struct platform_device *pdev); +static int mddi_remove(struct platform_device *pdev); + +static int mddi_off(struct platform_device *pdev); +static int mddi_on(struct platform_device *pdev); + +static int mddi_suspend(struct platform_device *pdev, pm_message_t state); +static int mddi_resume(struct platform_device *pdev); + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void mddi_early_suspend(struct early_suspend *h); +static void mddi_early_resume(struct early_suspend *h); +#endif + +static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; +static int pdev_list_cnt; +static struct clk *mddi_clk; +static struct clk *mddi_pclk; +static struct mddi_platform_data *mddi_pdata; + +static struct platform_driver mddi_driver = { + .probe = mddi_probe, + .remove = mddi_remove, +#ifndef CONFIG_HAS_EARLYSUSPEND +#ifdef CONFIG_PM + .suspend = mddi_suspend, + .resume = mddi_resume, +#endif +#endif + .suspend_late = NULL, + .resume_early = NULL, + .shutdown = NULL, + .driver = { + .name = "mddi", + }, +}; + +extern int int_mddi_pri_flag; + +static int mddi_off(struct platform_device *pdev) +{ + int ret = 0; + + ret = panel_next_off(pdev); + + if (mddi_pdata && mddi_pdata->mddi_power_save) + mddi_pdata->mddi_power_save(0); + + return ret; +} + +static int mddi_on(struct platform_device *pdev) +{ + int ret = 0; + u32 clk_rate; + struct msm_fb_data_type *mfd; + + mfd = platform_get_drvdata(pdev); + + if (mddi_pdata && mddi_pdata->mddi_power_save) + mddi_pdata->mddi_power_save(1); + + clk_rate = mfd->fbi->var.pixclock; + clk_rate = min(clk_rate, mfd->panel_info.clk_max); + + if (mddi_pdata && + mddi_pdata->mddi_sel_clk && + mddi_pdata->mddi_sel_clk(&clk_rate)) + printk(KERN_ERR + "%s: can't select mddi io clk targate rate = %d\n", + __func__, clk_rate); + + if (clk_set_min_rate(mddi_clk, clk_rate) < 0) + printk(KERN_ERR "%s: clk_set_min_rate failed\n", + __func__); + + ret = panel_next_on(pdev); + + return ret; +} + +static int mddi_resource_initialized; + +static int mddi_probe(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd; + struct platform_device *mdp_dev = NULL; + struct msm_fb_panel_data *pdata = NULL; + int rc; + resource_size_t size ; + u32 clk_rate; + + if ((pdev->id == 0) && (pdev->num_resources >= 0)) { + mddi_pdata = pdev->dev.platform_data; + + size = resource_size(&pdev->resource[0]); + msm_pmdh_base = ioremap(pdev->resource[0].start, size); + + MSM_FB_INFO("primary mddi base phy_addr = 0x%x virt = 0x%x\n", + pdev->resource[0].start, (int) msm_pmdh_base); + + if (unlikely(!msm_pmdh_base)) + return -ENOMEM; + + if (mddi_pdata && mddi_pdata->mddi_power_save) + mddi_pdata->mddi_power_save(1); + + mddi_resource_initialized = 1; + return 0; + } + + if (!mddi_resource_initialized) + return -EPERM; + + mfd = platform_get_drvdata(pdev); + + if (!mfd) + return -ENODEV; + + if (mfd->key != MFD_KEY) + return -EINVAL; + + if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) + return -ENOMEM; + + mdp_dev = platform_device_alloc("mdp", pdev->id); + if (!mdp_dev) + return -ENOMEM; + + /* + * link to the latest pdev + */ + mfd->pdev = mdp_dev; + mfd->dest = DISPLAY_LCD; + + /* + * alloc panel device data + */ + if (platform_device_add_data + (mdp_dev, pdev->dev.platform_data, + sizeof(struct msm_fb_panel_data))) { + printk(KERN_ERR "mddi_probe: platform_device_add_data failed!\n"); + platform_device_put(mdp_dev); + return -ENOMEM; + } + /* + * data chain + */ + pdata = mdp_dev->dev.platform_data; + pdata->on = mddi_on; + pdata->off = mddi_off; + pdata->next = pdev; + + /* + * get/set panel specific fb info + */ + mfd->panel_info = pdata->panel_info; + mfd->fb_imgType = MDP_RGB_565; + + clk_rate = mfd->panel_info.clk_max; + if (mddi_pdata && + mddi_pdata->mddi_sel_clk && + mddi_pdata->mddi_sel_clk(&clk_rate)) + printk(KERN_ERR + "%s: can't select mddi io clk targate rate = %d\n", + __func__, clk_rate); + + if (clk_set_max_rate(mddi_clk, clk_rate) < 0) + printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__); + mfd->panel_info.clk_rate = mfd->panel_info.clk_min; + + /* + * set driver data + */ + platform_set_drvdata(mdp_dev, mfd); + + /* + * register in mdp driver + */ + rc = platform_device_add(mdp_dev); + if (rc) + goto mddi_probe_err; + + pdev_list[pdev_list_cnt++] = pdev; + +#ifdef CONFIG_HAS_EARLYSUSPEND + mfd->mddi_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB; + mfd->mddi_early_suspend.suspend = mddi_early_suspend; + mfd->mddi_early_suspend.resume = mddi_early_resume; + register_early_suspend(&mfd->mddi_early_suspend); +#endif + + return 0; + +mddi_probe_err: + platform_device_put(mdp_dev); + return rc; +} + +static int mddi_pad_ctrl; +static int mddi_power_locked; +static int mddi_is_in_suspend; + +void mddi_disable(int lock) +{ + mddi_host_type host_idx = MDDI_HOST_PRIM; + + if (mddi_power_locked) + return; + + if (lock) + mddi_power_locked = 1; + + if (mddi_host_timer.function) + del_timer_sync(&mddi_host_timer); + + mddi_pad_ctrl = mddi_host_reg_in(PAD_CTL); + mddi_host_reg_out(PAD_CTL, 0x0); + + if (clk_set_min_rate(mddi_clk, 0) < 0) + printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__); + + clk_disable(mddi_clk); + if (mddi_pclk) + clk_disable(mddi_pclk); + disable_irq(INT_MDDI_PRI); + + if (mddi_pdata && mddi_pdata->mddi_power_save) + mddi_pdata->mddi_power_save(0); +} + +static int mddi_suspend(struct platform_device *pdev, pm_message_t state) +{ + if (mddi_is_in_suspend) + return 0; + + mddi_is_in_suspend = 1; + mddi_disable(0); + return 0; +} + +static int mddi_resume(struct platform_device *pdev) +{ + mddi_host_type host_idx = MDDI_HOST_PRIM; + + if (!mddi_is_in_suspend) + return 0; + + mddi_is_in_suspend = 0; + + if (mddi_power_locked) + return 0; + + enable_irq(INT_MDDI_PRI); + clk_enable(mddi_clk); + if (mddi_pclk) + clk_enable(mddi_pclk); + mddi_host_reg_out(PAD_CTL, mddi_pad_ctrl); + + if (mddi_host_timer.function) + mddi_host_timer_service(0); + + return 0; +} + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void mddi_early_suspend(struct early_suspend *h) +{ + pm_message_t state; + struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, + mddi_early_suspend); + + state.event = PM_EVENT_SUSPEND; + mddi_suspend(mfd->pdev, state); +} + +static void mddi_early_resume(struct early_suspend *h) +{ + struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, + mddi_early_suspend); + mddi_resume(mfd->pdev); +} +#endif + +static int mddi_remove(struct platform_device *pdev) +{ + if (mddi_host_timer.function) + del_timer_sync(&mddi_host_timer); + + iounmap(msm_pmdh_base); + + return 0; +} + +static int mddi_register_driver(void) +{ + return platform_driver_register(&mddi_driver); +} + +static int __init mddi_driver_init(void) +{ + int ret; + + mddi_clk = clk_get(NULL, "mddi_clk"); + if (IS_ERR(mddi_clk)) { + printk(KERN_ERR "can't find mddi_clk \n"); + return PTR_ERR(mddi_clk); + } + clk_enable(mddi_clk); + + mddi_pclk = clk_get(NULL, "mddi_pclk"); + if (IS_ERR(mddi_pclk)) + mddi_pclk = NULL; + else + clk_enable(mddi_pclk); + + ret = mddi_register_driver(); + if (ret) { + clk_disable(mddi_clk); + clk_put(mddi_clk); + if (mddi_pclk) { + clk_disable(mddi_pclk); + clk_put(mddi_pclk); + } + printk(KERN_ERR "mddi_register_driver() failed!\n"); + return ret; + } + + mddi_init(); + + return ret; +} + +module_init(mddi_driver_init); diff --git a/drivers/staging/msm/mddi_ext.c b/drivers/staging/msm/mddi_ext.c new file mode 100644 index 000000000000..c0c168c7199d --- /dev/null +++ b/drivers/staging/msm/mddi_ext.c @@ -0,0 +1,320 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/delay.h> +#include <mach/hardware.h> +#include <asm/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/uaccess.h> +#include <linux/clk.h> +#include <mach/clk.h> +#include <linux/platform_device.h> + +#include "msm_fb.h" +#include "mddihosti.h" + +static int mddi_ext_probe(struct platform_device *pdev); +static int mddi_ext_remove(struct platform_device *pdev); + +static int mddi_ext_off(struct platform_device *pdev); +static int mddi_ext_on(struct platform_device *pdev); + +static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; +static int pdev_list_cnt; + +static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state); +static int mddi_ext_resume(struct platform_device *pdev); + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void mddi_ext_early_suspend(struct early_suspend *h); +static void mddi_ext_early_resume(struct early_suspend *h); +#endif + +static struct platform_driver mddi_ext_driver = { + .probe = mddi_ext_probe, + .remove = mddi_ext_remove, +#ifndef CONFIG_HAS_EARLYSUSPEND +#ifdef CONFIG_PM + .suspend = mddi_ext_suspend, + .resume = mddi_ext_resume, +#endif +#endif + .resume_early = NULL, + .resume = NULL, + .shutdown = NULL, + .driver = { + .name = "mddi_ext", + }, +}; + +static struct clk *mddi_ext_clk; +static struct mddi_platform_data *mddi_ext_pdata; + +extern int int_mddi_ext_flag; + +static int mddi_ext_off(struct platform_device *pdev) +{ + int ret = 0; + + ret = panel_next_off(pdev); + mddi_host_stop_ext_display(); + + return ret; +} + +static int mddi_ext_on(struct platform_device *pdev) +{ + int ret = 0; + u32 clk_rate; + struct msm_fb_data_type *mfd; + + mfd = platform_get_drvdata(pdev); + + clk_rate = mfd->fbi->var.pixclock; + clk_rate = min(clk_rate, mfd->panel_info.clk_max); + + if (mddi_ext_pdata && + mddi_ext_pdata->mddi_sel_clk && + mddi_ext_pdata->mddi_sel_clk(&clk_rate)) + printk(KERN_ERR + "%s: can't select mddi io clk targate rate = %d\n", + __func__, clk_rate); + + if (clk_set_min_rate(mddi_ext_clk, clk_rate) < 0) + printk(KERN_ERR "%s: clk_set_min_rate failed\n", + __func__); + + mddi_host_start_ext_display(); + ret = panel_next_on(pdev); + + return ret; +} + +static int mddi_ext_resource_initialized; + +static int mddi_ext_probe(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd; + struct platform_device *mdp_dev = NULL; + struct msm_fb_panel_data *pdata = NULL; + int rc; + resource_size_t size ; + u32 clk_rate; + + if ((pdev->id == 0) && (pdev->num_resources >= 0)) { + mddi_ext_pdata = pdev->dev.platform_data; + + size = resource_size(&pdev->resource[0]); + msm_emdh_base = ioremap(pdev->resource[0].start, size); + + MSM_FB_INFO("external mddi base address = 0x%x\n", + pdev->resource[0].start); + + if (unlikely(!msm_emdh_base)) + return -ENOMEM; + + mddi_ext_resource_initialized = 1; + return 0; + } + + if (!mddi_ext_resource_initialized) + return -EPERM; + + mfd = platform_get_drvdata(pdev); + + if (!mfd) + return -ENODEV; + + if (mfd->key != MFD_KEY) + return -EINVAL; + + if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) + return -ENOMEM; + + mdp_dev = platform_device_alloc("mdp", pdev->id); + if (!mdp_dev) + return -ENOMEM; + + /* + * link to the latest pdev + */ + mfd->pdev = mdp_dev; + mfd->dest = DISPLAY_EXT_MDDI; + + /* + * alloc panel device data + */ + if (platform_device_add_data + (mdp_dev, pdev->dev.platform_data, + sizeof(struct msm_fb_panel_data))) { + printk(KERN_ERR "mddi_ext_probe: platform_device_add_data failed!\n"); + platform_device_put(mdp_dev); + return -ENOMEM; + } + /* + * data chain + */ + pdata = mdp_dev->dev.platform_data; + pdata->on = mddi_ext_on; + pdata->off = mddi_ext_off; + pdata->next = pdev; + + /* + * get/set panel specific fb info + */ + mfd->panel_info = pdata->panel_info; + mfd->fb_imgType = MDP_RGB_565; + + clk_rate = mfd->panel_info.clk_max; + if (mddi_ext_pdata && + mddi_ext_pdata->mddi_sel_clk && + mddi_ext_pdata->mddi_sel_clk(&clk_rate)) + printk(KERN_ERR + "%s: can't select mddi io clk targate rate = %d\n", + __func__, clk_rate); + + if (clk_set_max_rate(mddi_ext_clk, clk_rate) < 0) + printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__); + mfd->panel_info.clk_rate = mfd->panel_info.clk_min; + + /* + * set driver data + */ + platform_set_drvdata(mdp_dev, mfd); + + /* + * register in mdp driver + */ + rc = platform_device_add(mdp_dev); + if (rc) + goto mddi_ext_probe_err; + + pdev_list[pdev_list_cnt++] = pdev; + +#ifdef CONFIG_HAS_EARLYSUSPEND + mfd->mddi_ext_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB; + mfd->mddi_ext_early_suspend.suspend = mddi_ext_early_suspend; + mfd->mddi_ext_early_suspend.resume = mddi_ext_early_resume; + register_early_suspend(&mfd->mddi_ext_early_suspend); +#endif + + return 0; + +mddi_ext_probe_err: + platform_device_put(mdp_dev); + return rc; +} + +static int mddi_ext_is_in_suspend; + +static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state) +{ + if (mddi_ext_is_in_suspend) + return 0; + + mddi_ext_is_in_suspend = 1; + + if (clk_set_min_rate(mddi_ext_clk, 0) < 0) + printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__); + + clk_disable(mddi_ext_clk); + disable_irq(INT_MDDI_EXT); + + return 0; +} + +static int mddi_ext_resume(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd; + + mfd = platform_get_drvdata(pdev); + + if (!mddi_ext_is_in_suspend) + return 0; + + mddi_ext_is_in_suspend = 0; + enable_irq(INT_MDDI_EXT); + + clk_enable(mddi_ext_clk); + + return 0; +} + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void mddi_ext_early_suspend(struct early_suspend *h) +{ + pm_message_t state; + struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, + mddi_ext_early_suspend); + + state.event = PM_EVENT_SUSPEND; + mddi_ext_suspend(mfd->pdev, state); +} + +static void mddi_ext_early_resume(struct early_suspend *h) +{ + struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, + mddi_ext_early_suspend); + mddi_ext_resume(mfd->pdev); +} +#endif + +static int mddi_ext_remove(struct platform_device *pdev) +{ + iounmap(msm_emdh_base); + return 0; +} + +static int mddi_ext_register_driver(void) +{ + return platform_driver_register(&mddi_ext_driver); +} + +static int __init mddi_ext_driver_init(void) +{ + int ret; + + mddi_ext_clk = clk_get(NULL, "emdh_clk"); + if (IS_ERR(mddi_ext_clk)) { + printk(KERN_ERR "can't find emdh_clk\n"); + return PTR_ERR(mddi_ext_clk); + } + clk_enable(mddi_ext_clk); + + ret = mddi_ext_register_driver(); + if (ret) { + clk_disable(mddi_ext_clk); + clk_put(mddi_ext_clk); + printk(KERN_ERR "mddi_ext_register_driver() failed!\n"); + return ret; + } + mddi_init(); + + return ret; +} + +module_init(mddi_ext_driver_init); diff --git a/drivers/staging/msm/mddi_ext_lcd.c b/drivers/staging/msm/mddi_ext_lcd.c new file mode 100644 index 000000000000..502e80d17ec7 --- /dev/null +++ b/drivers/staging/msm/mddi_ext_lcd.c @@ -0,0 +1,91 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" +#include "mddihost.h" +#include "mddihosti.h" + +static int mddi_ext_lcd_on(struct platform_device *pdev); +static int mddi_ext_lcd_off(struct platform_device *pdev); + +static int mddi_ext_lcd_on(struct platform_device *pdev) +{ + return 0; +} + +static int mddi_ext_lcd_off(struct platform_device *pdev) +{ + return 0; +} + +static int __init mddi_ext_lcd_probe(struct platform_device *pdev) +{ + msm_fb_add_device(pdev); + + return 0; +} + +static struct platform_driver this_driver = { + .probe = mddi_ext_lcd_probe, + .driver = { + .name = "extmddi_svga", + }, +}; + +static struct msm_fb_panel_data mddi_ext_lcd_panel_data = { + .panel_info.xres = 800, + .panel_info.yres = 600, + .panel_info.type = EXT_MDDI_PANEL, + .panel_info.pdest = DISPLAY_1, + .panel_info.wait_cycle = 0, + .panel_info.bpp = 18, + .panel_info.fb_num = 2, + .panel_info.clk_rate = 122880000, + .panel_info.clk_min = 120000000, + .panel_info.clk_max = 125000000, + .on = mddi_ext_lcd_on, + .off = mddi_ext_lcd_off, +}; + +static struct platform_device this_device = { + .name = "extmddi_svga", + .id = 0, + .dev = { + .platform_data = &mddi_ext_lcd_panel_data, + } +}; + +static int __init mddi_ext_lcd_init(void) +{ + int ret; + struct msm_panel_info *pinfo; + + ret = platform_driver_register(&this_driver); + if (!ret) { + pinfo = &mddi_ext_lcd_panel_data.panel_info; + pinfo->lcd.vsync_enable = FALSE; + pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR; + + ret = platform_device_register(&this_device); + if (ret) + platform_driver_unregister(&this_driver); + } + + return ret; +} + +module_init(mddi_ext_lcd_init); diff --git a/drivers/staging/msm/mddi_prism.c b/drivers/staging/msm/mddi_prism.c new file mode 100644 index 000000000000..489d40405a5f --- /dev/null +++ b/drivers/staging/msm/mddi_prism.c @@ -0,0 +1,114 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" +#include "mddihost.h" +#include "mddihosti.h" + +static int prism_lcd_on(struct platform_device *pdev); +static int prism_lcd_off(struct platform_device *pdev); + +static int prism_lcd_on(struct platform_device *pdev) +{ + /* Set the MDP pixel data attributes for Primary Display */ + mddi_host_write_pix_attr_reg(0x00C3); + + return 0; +} + +static int prism_lcd_off(struct platform_device *pdev) +{ + return 0; +} + +static int __init prism_probe(struct platform_device *pdev) +{ + msm_fb_add_device(pdev); + + return 0; +} + +static struct platform_driver this_driver = { + .probe = prism_probe, + .driver = { + .name = "mddi_prism_wvga", + }, +}; + +static struct msm_fb_panel_data prism_panel_data = { + .on = prism_lcd_on, + .off = prism_lcd_off, +}; + +static struct platform_device this_device = { + .name = "mddi_prism_wvga", + .id = 0, + .dev = { + .platform_data = &prism_panel_data, + } +}; + +static int __init prism_init(void) +{ + int ret; + struct msm_panel_info *pinfo; + +#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT + u32 id; + + ret = msm_fb_detect_client("mddi_prism_wvga"); + if (ret == -ENODEV) + return 0; + + if (ret) { + id = mddi_get_client_id(); + + if (((id >> 16) != 0x4474) || ((id & 0xffff) == 0x8960)) + return 0; + } +#endif + ret = platform_driver_register(&this_driver); + if (!ret) { + pinfo = &prism_panel_data.panel_info; + pinfo->xres = 800; + pinfo->yres = 480; + pinfo->type = MDDI_PANEL; + pinfo->pdest = DISPLAY_1; + pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR; + pinfo->wait_cycle = 0; + pinfo->bpp = 18; + pinfo->fb_num = 2; + pinfo->clk_rate = 153600000; + pinfo->clk_min = 150000000; + pinfo->clk_max = 160000000; + pinfo->lcd.vsync_enable = TRUE; + pinfo->lcd.refx100 = 6050; + pinfo->lcd.v_back_porch = 23; + pinfo->lcd.v_front_porch = 20; + pinfo->lcd.v_pulse_width = 105; + pinfo->lcd.hw_vsync_mode = TRUE; + pinfo->lcd.vsync_notifier_period = 0; + + ret = platform_device_register(&this_device); + if (ret) + platform_driver_unregister(&this_driver); + } + + return ret; +} + +module_init(prism_init); diff --git a/drivers/staging/msm/mddi_sharp.c b/drivers/staging/msm/mddi_sharp.c new file mode 100644 index 000000000000..1da1be4052d0 --- /dev/null +++ b/drivers/staging/msm/mddi_sharp.c @@ -0,0 +1,892 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" +#include "mddihost.h" +#include "mddihosti.h" + +#define SHARP_QVGA_PRIM 1 +#define SHARP_128X128_SECD 2 + +extern uint32 mddi_host_core_version; +static boolean mddi_debug_prim_wait = FALSE; +static boolean mddi_sharp_vsync_wake = TRUE; +static boolean mddi_sharp_monitor_refresh_value = TRUE; +static boolean mddi_sharp_report_refresh_measurements = FALSE; +static uint32 mddi_sharp_rows_per_second = 13830; /* 5200000/376 */ +static uint32 mddi_sharp_rows_per_refresh = 338; +static uint32 mddi_sharp_usecs_per_refresh = 24440; /* (376+338)/5200000 */ +static boolean mddi_sharp_debug_60hz_refresh = FALSE; + +extern mddi_gpio_info_type mddi_gpio; +extern boolean mddi_vsync_detect_enabled; +static msm_fb_vsync_handler_type mddi_sharp_vsync_handler; +static void *mddi_sharp_vsync_handler_arg; +static uint16 mddi_sharp_vsync_attempts; + +static void mddi_sharp_prim_lcd_init(void); +static void mddi_sharp_sub_lcd_init(void); +static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd); +static void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler, + void *); +static void mddi_sharp_lcd_vsync_detected(boolean detected); +static struct msm_panel_common_pdata *mddi_sharp_pdata; + +#define REG_SYSCTL 0x0000 +#define REG_INTR 0x0006 +#define REG_CLKCNF 0x000C +#define REG_CLKDIV1 0x000E +#define REG_CLKDIV2 0x0010 + +#define REG_GIOD 0x0040 +#define REG_GIOA 0x0042 + +#define REG_AGM 0x010A +#define REG_FLFT 0x0110 +#define REG_FRGT 0x0112 +#define REG_FTOP 0x0114 +#define REG_FBTM 0x0116 +#define REG_FSTRX 0x0118 +#define REG_FSTRY 0x011A +#define REG_VRAM 0x0202 +#define REG_SSDCTL 0x0330 +#define REG_SSD0 0x0332 +#define REG_PSTCTL1 0x0400 +#define REG_PSTCTL2 0x0402 +#define REG_PTGCTL 0x042A +#define REG_PTHP 0x042C +#define REG_PTHB 0x042E +#define REG_PTHW 0x0430 +#define REG_PTHF 0x0432 +#define REG_PTVP 0x0434 +#define REG_PTVB 0x0436 +#define REG_PTVW 0x0438 +#define REG_PTVF 0x043A +#define REG_VBLKS 0x0458 +#define REG_VBLKE 0x045A +#define REG_SUBCTL 0x0700 +#define REG_SUBTCMD 0x0702 +#define REG_SUBTCMDD 0x0704 +#define REG_REVBYTE 0x0A02 +#define REG_REVCNT 0x0A04 +#define REG_REVATTR 0x0A06 +#define REG_REVFMT 0x0A08 + +#define SHARP_SUB_UNKNOWN 0xffffffff +#define SHARP_SUB_HYNIX 1 +#define SHARP_SUB_ROHM 2 + +static uint32 sharp_subpanel_type = SHARP_SUB_UNKNOWN; + +static void sub_through_write(int sub_rs, uint32 sub_data) +{ + mddi_queue_register_write(REG_SUBTCMDD, sub_data, FALSE, 0); + + /* CS=1,RD=1,WE=1,RS=sub_rs */ + mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0); + + /* CS=0,RD=1,WE=1,RS=sub_rs */ + mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0); + + /* CS=0,RD=1,WE=0,RS=sub_rs */ + mddi_queue_register_write(REG_SUBTCMD, 0x0004 | sub_rs, FALSE, 0); + + /* CS=0,RD=1,WE=1,RS=sub_rs */ + mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0); + + /* CS=1,RD=1,WE=1,RS=sub_rs */ + mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0); +} + +static uint32 sub_through_read(int sub_rs) +{ + uint32 sub_data; + + /* CS=1,RD=1,WE=1,RS=sub_rs */ + mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0); + + /* CS=0,RD=1,WE=1,RS=sub_rs */ + mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0); + + /* CS=0,RD=1,WE=0,RS=sub_rs */ + mddi_queue_register_write(REG_SUBTCMD, 0x0002 | sub_rs, TRUE, 0); + + mddi_queue_register_read(REG_SUBTCMDD, &sub_data, TRUE, 0); + + /* CS=0,RD=1,WE=1,RS=sub_rs */ + mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0); + + /* CS=1,RD=1,WE=1,RS=sub_rs */ + mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0); + + return sub_data; +} + +static void serigo(uint32 ssd) +{ + uint32 ssdctl; + + mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0); + ssdctl = ((ssdctl & 0xE7) | 0x02); + + mddi_queue_register_write(REG_SSD0, ssd, FALSE, 0); + mddi_queue_register_write(REG_SSDCTL, ssdctl, TRUE, 0); + + do { + mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0); + } while ((ssdctl & 0x0002) != 0); + + if (mddi_debug_prim_wait) + mddi_wait(2); +} + +static void mddi_sharp_lcd_powerdown(void) +{ + serigo(0x0131); + serigo(0x0300); + mddi_wait(40); + serigo(0x0135); + mddi_wait(20); + serigo(0x2122); + mddi_wait(20); + serigo(0x0201); + mddi_wait(20); + serigo(0x2100); + mddi_wait(20); + serigo(0x2000); + mddi_wait(20); + + mddi_queue_register_write(REG_PSTCTL1, 0x1, TRUE, 0); + mddi_wait(100); + mddi_queue_register_write(REG_PSTCTL1, 0x0, TRUE, 0); + mddi_wait(2); + mddi_queue_register_write(REG_SYSCTL, 0x1, TRUE, 0); + mddi_wait(2); + mddi_queue_register_write(REG_CLKDIV1, 0x3, TRUE, 0); + mddi_wait(2); + mddi_queue_register_write(REG_SSDCTL, 0x0000, TRUE, 0); /* SSDRESET */ + mddi_queue_register_write(REG_SYSCTL, 0x0, TRUE, 0); + mddi_wait(2); +} + +static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd) +{ + uint32 regdata; + int32 level; + int max = mfd->panel_info.bl_max; + int min = mfd->panel_info.bl_min; + + if (mddi_sharp_pdata && mddi_sharp_pdata->backlight_level) { + level = mddi_sharp_pdata->backlight_level(mfd->bl_level, + max, + min); + + if (level < 0) + return; + + /* use Rodem GPIO(2:0) to give 8 levels of backlight (7-0) */ + /* Set lower 3 GPIOs as Outputs (set to 0) */ + mddi_queue_register_read(REG_GIOA, ®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); diff --git a/drivers/staging/msm/mddi_toshiba.c b/drivers/staging/msm/mddi_toshiba.c new file mode 100644 index 000000000000..e96342d477a2 --- /dev/null +++ b/drivers/staging/msm/mddi_toshiba.c @@ -0,0 +1,1741 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" +#include "mddihost.h" +#include "mddihosti.h" +#include "mddi_toshiba.h" + +#define TM_GET_DID(id) ((id) & 0xff) +#define TM_GET_PID(id) (((id) & 0xff00)>>8) + +#define MDDI_CLIENT_CORE_BASE 0x108000 +#define LCD_CONTROL_BLOCK_BASE 0x110000 +#define SPI_BLOCK_BASE 0x120000 +#define PWM_BLOCK_BASE 0x140000 +#define SYSTEM_BLOCK1_BASE 0x160000 + +#define TTBUSSEL (MDDI_CLIENT_CORE_BASE|0x18) +#define DPSET0 (MDDI_CLIENT_CORE_BASE|0x1C) +#define DPSET1 (MDDI_CLIENT_CORE_BASE|0x20) +#define DPSUS (MDDI_CLIENT_CORE_BASE|0x24) +#define DPRUN (MDDI_CLIENT_CORE_BASE|0x28) +#define SYSCKENA (MDDI_CLIENT_CORE_BASE|0x2C) + +#define BITMAP0 (MDDI_CLIENT_CORE_BASE|0x44) +#define BITMAP1 (MDDI_CLIENT_CORE_BASE|0x48) +#define BITMAP2 (MDDI_CLIENT_CORE_BASE|0x4C) +#define BITMAP3 (MDDI_CLIENT_CORE_BASE|0x50) +#define BITMAP4 (MDDI_CLIENT_CORE_BASE|0x54) + +#define SRST (LCD_CONTROL_BLOCK_BASE|0x00) +#define PORT_ENB (LCD_CONTROL_BLOCK_BASE|0x04) +#define START (LCD_CONTROL_BLOCK_BASE|0x08) +#define PORT (LCD_CONTROL_BLOCK_BASE|0x0C) + +#define INTFLG (LCD_CONTROL_BLOCK_BASE|0x18) +#define INTMSK (LCD_CONTROL_BLOCK_BASE|0x1C) +#define MPLFBUF (LCD_CONTROL_BLOCK_BASE|0x20) + +#define PXL (LCD_CONTROL_BLOCK_BASE|0x30) +#define HCYCLE (LCD_CONTROL_BLOCK_BASE|0x34) +#define HSW (LCD_CONTROL_BLOCK_BASE|0x38) +#define HDE_START (LCD_CONTROL_BLOCK_BASE|0x3C) +#define HDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x40) +#define VCYCLE (LCD_CONTROL_BLOCK_BASE|0x44) +#define VSW (LCD_CONTROL_BLOCK_BASE|0x48) +#define VDE_START (LCD_CONTROL_BLOCK_BASE|0x4C) +#define VDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x50) +#define WAKEUP (LCD_CONTROL_BLOCK_BASE|0x54) +#define REGENB (LCD_CONTROL_BLOCK_BASE|0x5C) +#define VSYNIF (LCD_CONTROL_BLOCK_BASE|0x60) +#define WRSTB (LCD_CONTROL_BLOCK_BASE|0x64) +#define RDSTB (LCD_CONTROL_BLOCK_BASE|0x68) +#define ASY_DATA (LCD_CONTROL_BLOCK_BASE|0x6C) +#define ASY_DATB (LCD_CONTROL_BLOCK_BASE|0x70) +#define ASY_DATC (LCD_CONTROL_BLOCK_BASE|0x74) +#define ASY_DATD (LCD_CONTROL_BLOCK_BASE|0x78) +#define ASY_DATE (LCD_CONTROL_BLOCK_BASE|0x7C) +#define ASY_DATF (LCD_CONTROL_BLOCK_BASE|0x80) +#define ASY_DATG (LCD_CONTROL_BLOCK_BASE|0x84) +#define ASY_DATH (LCD_CONTROL_BLOCK_BASE|0x88) +#define ASY_CMDSET (LCD_CONTROL_BLOCK_BASE|0x8C) +#define MONI (LCD_CONTROL_BLOCK_BASE|0xB0) +#define VPOS (LCD_CONTROL_BLOCK_BASE|0xC0) + +#define SSICTL (SPI_BLOCK_BASE|0x00) +#define SSITIME (SPI_BLOCK_BASE|0x04) +#define SSITX (SPI_BLOCK_BASE|0x08) +#define SSIINTS (SPI_BLOCK_BASE|0x14) + +#define TIMER0LOAD (PWM_BLOCK_BASE|0x00) +#define TIMER0CTRL (PWM_BLOCK_BASE|0x08) +#define PWM0OFF (PWM_BLOCK_BASE|0x1C) +#define TIMER1LOAD (PWM_BLOCK_BASE|0x20) +#define TIMER1CTRL (PWM_BLOCK_BASE|0x28) +#define PWM1OFF (PWM_BLOCK_BASE|0x3C) +#define TIMER2LOAD (PWM_BLOCK_BASE|0x40) +#define TIMER2CTRL (PWM_BLOCK_BASE|0x48) +#define PWM2OFF (PWM_BLOCK_BASE|0x5C) +#define PWMCR (PWM_BLOCK_BASE|0x68) + +#define GPIOIS (GPIO_BLOCK_BASE|0x08) +#define GPIOIEV (GPIO_BLOCK_BASE|0x10) +#define GPIOIC (GPIO_BLOCK_BASE|0x20) + +#define WKREQ (SYSTEM_BLOCK1_BASE|0x00) +#define CLKENB (SYSTEM_BLOCK1_BASE|0x04) +#define DRAMPWR (SYSTEM_BLOCK1_BASE|0x08) +#define INTMASK (SYSTEM_BLOCK1_BASE|0x0C) +#define CNT_DIS (SYSTEM_BLOCK1_BASE|0x10) + +typedef enum { + TOSHIBA_STATE_OFF, + TOSHIBA_STATE_PRIM_SEC_STANDBY, + TOSHIBA_STATE_PRIM_SEC_READY, + TOSHIBA_STATE_PRIM_NORMAL_MODE, + TOSHIBA_STATE_SEC_NORMAL_MODE +} mddi_toshiba_state_t; + +static uint32 mddi_toshiba_curr_vpos; +static boolean mddi_toshiba_monitor_refresh_value = FALSE; +static boolean mddi_toshiba_report_refresh_measurements = FALSE; + +boolean mddi_toshiba_61Hz_refresh = TRUE; + +/* Modifications to timing to increase refresh rate to > 60Hz. + * 20MHz dot clock. + * 646 total rows. + * 506 total columns. + * refresh rate = 61.19Hz + */ +static uint32 mddi_toshiba_rows_per_second = 39526; +static uint32 mddi_toshiba_usecs_per_refresh = 16344; +static uint32 mddi_toshiba_rows_per_refresh = 646; +extern boolean mddi_vsync_detect_enabled; + +static msm_fb_vsync_handler_type mddi_toshiba_vsync_handler; +static void *mddi_toshiba_vsync_handler_arg; +static uint16 mddi_toshiba_vsync_attempts; + +static mddi_toshiba_state_t toshiba_state = TOSHIBA_STATE_OFF; + +static struct msm_panel_common_pdata *mddi_toshiba_pdata; + +static int mddi_toshiba_lcd_on(struct platform_device *pdev); +static int mddi_toshiba_lcd_off(struct platform_device *pdev); + +static void mddi_toshiba_state_transition(mddi_toshiba_state_t a, + mddi_toshiba_state_t b) +{ + if (toshiba_state != a) { + MDDI_MSG_ERR("toshiba state trans. (%d->%d) found %d\n", a, b, + toshiba_state); + } + toshiba_state = b; +} + +#define GORDON_REG_IMGCTL1 0x10 /* Image interface control 1 */ +#define GORDON_REG_IMGCTL2 0x11 /* Image interface control 2 */ +#define GORDON_REG_IMGSET1 0x12 /* Image interface settings 1 */ +#define GORDON_REG_IMGSET2 0x13 /* Image interface settings 2 */ +#define GORDON_REG_IVBP1 0x14 /* DM0: Vert back porch */ +#define GORDON_REG_IHBP1 0x15 /* DM0: Horiz back porch */ +#define GORDON_REG_IVNUM1 0x16 /* DM0: Num of vert lines */ +#define GORDON_REG_IHNUM1 0x17 /* DM0: Num of pixels per line */ +#define GORDON_REG_IVBP2 0x18 /* DM1: Vert back porch */ +#define GORDON_REG_IHBP2 0x19 /* DM1: Horiz back porch */ +#define GORDON_REG_IVNUM2 0x1A /* DM1: Num of vert lines */ +#define GORDON_REG_IHNUM2 0x1B /* DM1: Num of pixels per line */ +#define GORDON_REG_LCDIFCTL1 0x30 /* LCD interface control 1 */ +#define GORDON_REG_VALTRAN 0x31 /* LCD IF ctl: VALTRAN sync flag */ +#define GORDON_REG_AVCTL 0x33 +#define GORDON_REG_LCDIFCTL2 0x34 /* LCD interface control 2 */ +#define GORDON_REG_LCDIFCTL3 0x35 /* LCD interface control 3 */ +#define GORDON_REG_LCDIFSET1 0x36 /* LCD interface settings 1 */ +#define GORDON_REG_PCCTL 0x3C +#define GORDON_REG_TPARAM1 0x40 +#define GORDON_REG_TLCDIF1 0x41 +#define GORDON_REG_TSSPB_ST1 0x42 +#define GORDON_REG_TSSPB_ED1 0x43 +#define GORDON_REG_TSCK_ST1 0x44 +#define GORDON_REG_TSCK_WD1 0x45 +#define GORDON_REG_TGSPB_VST1 0x46 +#define GORDON_REG_TGSPB_VED1 0x47 +#define GORDON_REG_TGSPB_CH1 0x48 +#define GORDON_REG_TGCK_ST1 0x49 +#define GORDON_REG_TGCK_ED1 0x4A +#define GORDON_REG_TPCTL_ST1 0x4B +#define GORDON_REG_TPCTL_ED1 0x4C +#define GORDON_REG_TPCHG_ED1 0x4D +#define GORDON_REG_TCOM_CH1 0x4E +#define GORDON_REG_THBP1 0x4F +#define GORDON_REG_TPHCTL1 0x50 +#define GORDON_REG_EVPH1 0x51 +#define GORDON_REG_EVPL1 0x52 +#define GORDON_REG_EVNH1 0x53 +#define GORDON_REG_EVNL1 0x54 +#define GORDON_REG_TBIAS1 0x55 +#define GORDON_REG_TPARAM2 0x56 +#define GORDON_REG_TLCDIF2 0x57 +#define GORDON_REG_TSSPB_ST2 0x58 +#define GORDON_REG_TSSPB_ED2 0x59 +#define GORDON_REG_TSCK_ST2 0x5A +#define GORDON_REG_TSCK_WD2 0x5B +#define GORDON_REG_TGSPB_VST2 0x5C +#define GORDON_REG_TGSPB_VED2 0x5D +#define GORDON_REG_TGSPB_CH2 0x5E +#define GORDON_REG_TGCK_ST2 0x5F +#define GORDON_REG_TGCK_ED2 0x60 +#define GORDON_REG_TPCTL_ST2 0x61 +#define GORDON_REG_TPCTL_ED2 0x62 +#define GORDON_REG_TPCHG_ED2 0x63 +#define GORDON_REG_TCOM_CH2 0x64 +#define GORDON_REG_THBP2 0x65 +#define GORDON_REG_TPHCTL2 0x66 +#define GORDON_REG_EVPH2 0x67 +#define GORDON_REG_EVPL2 0x68 +#define GORDON_REG_EVNH2 0x69 +#define GORDON_REG_EVNL2 0x6A +#define GORDON_REG_TBIAS2 0x6B +#define GORDON_REG_POWCTL 0x80 +#define GORDON_REG_POWOSC1 0x81 +#define GORDON_REG_POWOSC2 0x82 +#define GORDON_REG_POWSET 0x83 +#define GORDON_REG_POWTRM1 0x85 +#define GORDON_REG_POWTRM2 0x86 +#define GORDON_REG_POWTRM3 0x87 +#define GORDON_REG_POWTRMSEL 0x88 +#define GORDON_REG_POWHIZ 0x89 + +void serigo(uint16 reg, uint8 data) +{ + uint32 mddi_val = 0; + mddi_queue_register_read(SSIINTS, &mddi_val, TRUE, 0); + if (mddi_val & (1 << 8)) + mddi_wait(1); + /* No De-assert of CS and send 2 bytes */ + mddi_val = 0x90000 | ((0x00FF & reg) << 8) | data; + mddi_queue_register_write(SSITX, mddi_val, TRUE, 0); +} + +void gordon_init(void) +{ + /* Image interface settings ***/ + serigo(GORDON_REG_IMGCTL2, 0x00); + serigo(GORDON_REG_IMGSET1, 0x01); + + /* Exchange the RGB signal for J510(Softbank mobile) */ + serigo(GORDON_REG_IMGSET2, 0x12); + serigo(GORDON_REG_LCDIFSET1, 0x00); + mddi_wait(2); + + /* Pre-charge settings */ + serigo(GORDON_REG_PCCTL, 0x09); + serigo(GORDON_REG_LCDIFCTL2, 0x1B); + mddi_wait(1); +} + +void gordon_disp_on(void) +{ + /*gordon_dispmode setting */ + /*VGA settings */ + serigo(GORDON_REG_TPARAM1, 0x30); + serigo(GORDON_REG_TLCDIF1, 0x00); + serigo(GORDON_REG_TSSPB_ST1, 0x8B); + serigo(GORDON_REG_TSSPB_ED1, 0x93); + mddi_wait(2); + serigo(GORDON_REG_TSCK_ST1, 0x88); + serigo(GORDON_REG_TSCK_WD1, 0x00); + serigo(GORDON_REG_TGSPB_VST1, 0x01); + serigo(GORDON_REG_TGSPB_VED1, 0x02); + mddi_wait(2); + serigo(GORDON_REG_TGSPB_CH1, 0x5E); + serigo(GORDON_REG_TGCK_ST1, 0x80); + serigo(GORDON_REG_TGCK_ED1, 0x3C); + serigo(GORDON_REG_TPCTL_ST1, 0x50); + mddi_wait(2); + serigo(GORDON_REG_TPCTL_ED1, 0x74); + serigo(GORDON_REG_TPCHG_ED1, 0x78); + serigo(GORDON_REG_TCOM_CH1, 0x50); + serigo(GORDON_REG_THBP1, 0x84); + mddi_wait(2); + serigo(GORDON_REG_TPHCTL1, 0x00); + serigo(GORDON_REG_EVPH1, 0x70); + serigo(GORDON_REG_EVPL1, 0x64); + serigo(GORDON_REG_EVNH1, 0x56); + mddi_wait(2); + serigo(GORDON_REG_EVNL1, 0x48); + serigo(GORDON_REG_TBIAS1, 0x88); + mddi_wait(2); + serigo(GORDON_REG_TPARAM2, 0x28); + serigo(GORDON_REG_TLCDIF2, 0x14); + serigo(GORDON_REG_TSSPB_ST2, 0x49); + serigo(GORDON_REG_TSSPB_ED2, 0x4B); + mddi_wait(2); + serigo(GORDON_REG_TSCK_ST2, 0x4A); + serigo(GORDON_REG_TSCK_WD2, 0x02); + serigo(GORDON_REG_TGSPB_VST2, 0x02); + serigo(GORDON_REG_TGSPB_VED2, 0x03); + mddi_wait(2); + serigo(GORDON_REG_TGSPB_CH2, 0x2F); + serigo(GORDON_REG_TGCK_ST2, 0x40); + serigo(GORDON_REG_TGCK_ED2, 0x1E); + serigo(GORDON_REG_TPCTL_ST2, 0x2C); + mddi_wait(2); + serigo(GORDON_REG_TPCTL_ED2, 0x3A); + serigo(GORDON_REG_TPCHG_ED2, 0x3C); + serigo(GORDON_REG_TCOM_CH2, 0x28); + serigo(GORDON_REG_THBP2, 0x4D); + mddi_wait(2); + serigo(GORDON_REG_TPHCTL2, 0x1A); + mddi_wait(2); + serigo(GORDON_REG_IVBP1, 0x02); + serigo(GORDON_REG_IHBP1, 0x90); + serigo(GORDON_REG_IVNUM1, 0xA0); + serigo(GORDON_REG_IHNUM1, 0x78); + mddi_wait(2); + serigo(GORDON_REG_IVBP2, 0x02); + serigo(GORDON_REG_IHBP2, 0x48); + serigo(GORDON_REG_IVNUM2, 0x50); + serigo(GORDON_REG_IHNUM2, 0x3C); + mddi_wait(2); + serigo(GORDON_REG_POWCTL, 0x03); + mddi_wait(15); + serigo(GORDON_REG_POWCTL, 0x07); + mddi_wait(15); + serigo(GORDON_REG_POWCTL, 0x0F); + mddi_wait(15); + serigo(GORDON_REG_AVCTL, 0x03); + mddi_wait(15); + serigo(GORDON_REG_POWCTL, 0x1F); + mddi_wait(15); + serigo(GORDON_REG_POWCTL, 0x5F); + mddi_wait(15); + serigo(GORDON_REG_POWCTL, 0x7F); + mddi_wait(15); + serigo(GORDON_REG_LCDIFCTL1, 0x02); + mddi_wait(15); + serigo(GORDON_REG_IMGCTL1, 0x00); + mddi_wait(15); + serigo(GORDON_REG_LCDIFCTL3, 0x00); + mddi_wait(15); + serigo(GORDON_REG_VALTRAN, 0x01); + mddi_wait(15); + serigo(GORDON_REG_LCDIFCTL1, 0x03); + serigo(GORDON_REG_LCDIFCTL1, 0x03); + mddi_wait(1); +} + +void gordon_disp_off(void) +{ + serigo(GORDON_REG_LCDIFCTL2, 0x7B); + serigo(GORDON_REG_VALTRAN, 0x01); + serigo(GORDON_REG_LCDIFCTL1, 0x02); + serigo(GORDON_REG_LCDIFCTL3, 0x01); + mddi_wait(20); + serigo(GORDON_REG_VALTRAN, 0x01); + serigo(GORDON_REG_IMGCTL1, 0x01); + serigo(GORDON_REG_LCDIFCTL1, 0x00); + mddi_wait(20); + serigo(GORDON_REG_POWCTL, 0x1F); + mddi_wait(40); + serigo(GORDON_REG_POWCTL, 0x07); + mddi_wait(40); + serigo(GORDON_REG_POWCTL, 0x03); + mddi_wait(40); + serigo(GORDON_REG_POWCTL, 0x00); + mddi_wait(40); +} + +void gordon_disp_init(void) +{ + gordon_init(); + mddi_wait(20); + gordon_disp_on(); +} + +static void toshiba_common_initial_setup(struct msm_fb_data_type *mfd) +{ + if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) { + write_client_reg(DPSET0 , 0x4bec0066, TRUE); + write_client_reg(DPSET1 , 0x00000113, TRUE); + write_client_reg(DPSUS , 0x00000000, TRUE); + write_client_reg(DPRUN , 0x00000001, TRUE); + mddi_wait(5); + write_client_reg(SYSCKENA , 0x00000001, TRUE); + write_client_reg(CLKENB , 0x0000a0e9, TRUE); + + write_client_reg(GPIODATA , 0x03FF0000, TRUE); + write_client_reg(GPIODIR , 0x0000024D, TRUE); + write_client_reg(GPIOSEL , 0x00000173, TRUE); + write_client_reg(GPIOPC , 0x03C300C0, TRUE); + write_client_reg(WKREQ , 0x00000000, TRUE); + write_client_reg(GPIOIS , 0x00000000, TRUE); + write_client_reg(GPIOIEV , 0x00000001, TRUE); + write_client_reg(GPIOIC , 0x000003FF, TRUE); + write_client_reg(GPIODATA , 0x00040004, TRUE); + + write_client_reg(GPIODATA , 0x00080008, TRUE); + write_client_reg(DRAMPWR , 0x00000001, TRUE); + write_client_reg(CLKENB , 0x0000a0eb, TRUE); + write_client_reg(PWMCR , 0x00000000, TRUE); + mddi_wait(1); + + write_client_reg(SSICTL , 0x00060399, TRUE); + write_client_reg(SSITIME , 0x00000100, TRUE); + write_client_reg(CNT_DIS , 0x00000002, TRUE); + write_client_reg(SSICTL , 0x0006039b, TRUE); + + write_client_reg(SSITX , 0x00000000, TRUE); + mddi_wait(7); + write_client_reg(SSITX , 0x00000000, TRUE); + mddi_wait(7); + write_client_reg(SSITX , 0x00000000, TRUE); + mddi_wait(7); + + write_client_reg(SSITX , 0x000800BA, TRUE); + write_client_reg(SSITX , 0x00000111, TRUE); + write_client_reg(SSITX , 0x00080036, TRUE); + write_client_reg(SSITX , 0x00000100, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x0008003A, TRUE); + write_client_reg(SSITX , 0x00000160, TRUE); + write_client_reg(SSITX , 0x000800B1, TRUE); + write_client_reg(SSITX , 0x0000015D, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800B2, TRUE); + write_client_reg(SSITX , 0x00000133, TRUE); + write_client_reg(SSITX , 0x000800B3, TRUE); + write_client_reg(SSITX , 0x00000122, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800B4, TRUE); + write_client_reg(SSITX , 0x00000102, TRUE); + write_client_reg(SSITX , 0x000800B5, TRUE); + write_client_reg(SSITX , 0x0000011E, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800B6, TRUE); + write_client_reg(SSITX , 0x00000127, TRUE); + write_client_reg(SSITX , 0x000800B7, TRUE); + write_client_reg(SSITX , 0x00000103, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800B9, TRUE); + write_client_reg(SSITX , 0x00000124, TRUE); + write_client_reg(SSITX , 0x000800BD, TRUE); + write_client_reg(SSITX , 0x000001A1, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800BB, TRUE); + write_client_reg(SSITX , 0x00000100, TRUE); + write_client_reg(SSITX , 0x000800BF, TRUE); + write_client_reg(SSITX , 0x00000101, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800BE, TRUE); + write_client_reg(SSITX , 0x00000100, TRUE); + write_client_reg(SSITX , 0x000800C0, TRUE); + write_client_reg(SSITX , 0x00000111, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800C1, TRUE); + write_client_reg(SSITX , 0x00000111, TRUE); + write_client_reg(SSITX , 0x000800C2, TRUE); + write_client_reg(SSITX , 0x00000111, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800C3, TRUE); + write_client_reg(SSITX , 0x00080132, TRUE); + write_client_reg(SSITX , 0x00000132, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800C4, TRUE); + write_client_reg(SSITX , 0x00080132, TRUE); + write_client_reg(SSITX , 0x00000132, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800C5, TRUE); + write_client_reg(SSITX , 0x00080132, TRUE); + write_client_reg(SSITX , 0x00000132, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800C6, TRUE); + write_client_reg(SSITX , 0x00080132, TRUE); + write_client_reg(SSITX , 0x00000132, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800C7, TRUE); + write_client_reg(SSITX , 0x00080164, TRUE); + write_client_reg(SSITX , 0x00000145, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800C8, TRUE); + write_client_reg(SSITX , 0x00000144, TRUE); + write_client_reg(SSITX , 0x000800C9, TRUE); + write_client_reg(SSITX , 0x00000152, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800CA, TRUE); + write_client_reg(SSITX , 0x00000100, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800EC, TRUE); + write_client_reg(SSITX , 0x00080101, TRUE); + write_client_reg(SSITX , 0x000001FC, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800CF, TRUE); + write_client_reg(SSITX , 0x00000101, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800D0, TRUE); + write_client_reg(SSITX , 0x00080110, TRUE); + write_client_reg(SSITX , 0x00000104, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800D1, TRUE); + write_client_reg(SSITX , 0x00000101, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800D2, TRUE); + write_client_reg(SSITX , 0x00080100, TRUE); + write_client_reg(SSITX , 0x00000128, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800D3, TRUE); + write_client_reg(SSITX , 0x00080100, TRUE); + write_client_reg(SSITX , 0x00000128, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800D4, TRUE); + write_client_reg(SSITX , 0x00080126, TRUE); + write_client_reg(SSITX , 0x000001A4, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800D5, TRUE); + write_client_reg(SSITX , 0x00000120, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800EF, TRUE); + write_client_reg(SSITX , 0x00080132, TRUE); + write_client_reg(SSITX , 0x00000100, TRUE); + mddi_wait(1); + + write_client_reg(BITMAP0 , 0x032001E0, TRUE); + write_client_reg(BITMAP1 , 0x032001E0, TRUE); + write_client_reg(BITMAP2 , 0x014000F0, TRUE); + write_client_reg(BITMAP3 , 0x014000F0, TRUE); + write_client_reg(BITMAP4 , 0x014000F0, TRUE); + write_client_reg(CLKENB , 0x0000A1EB, TRUE); + write_client_reg(PORT_ENB , 0x00000001, TRUE); + write_client_reg(PORT , 0x00000004, TRUE); + write_client_reg(PXL , 0x00000002, TRUE); + write_client_reg(MPLFBUF , 0x00000000, TRUE); + write_client_reg(HCYCLE , 0x000000FD, TRUE); + write_client_reg(HSW , 0x00000003, TRUE); + write_client_reg(HDE_START , 0x00000007, TRUE); + write_client_reg(HDE_SIZE , 0x000000EF, TRUE); + write_client_reg(VCYCLE , 0x00000325, TRUE); + write_client_reg(VSW , 0x00000001, TRUE); + write_client_reg(VDE_START , 0x00000003, TRUE); + write_client_reg(VDE_SIZE , 0x0000031F, TRUE); + write_client_reg(START , 0x00000001, TRUE); + mddi_wait(32); + write_client_reg(SSITX , 0x000800BC, TRUE); + write_client_reg(SSITX , 0x00000180, TRUE); + write_client_reg(SSITX , 0x0008003B, TRUE); + write_client_reg(SSITX , 0x00000100, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800B0, TRUE); + write_client_reg(SSITX , 0x00000116, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x000800B8, TRUE); + write_client_reg(SSITX , 0x000801FF, TRUE); + write_client_reg(SSITX , 0x000001F5, TRUE); + mddi_wait(1); + write_client_reg(SSITX , 0x00000011, TRUE); + mddi_wait(5); + write_client_reg(SSITX , 0x00000029, TRUE); + return; + } + + if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) { + write_client_reg(DPSET0, 0x4BEC0066, TRUE); + write_client_reg(DPSET1, 0x00000113, TRUE); + write_client_reg(DPSUS, 0x00000000, TRUE); + write_client_reg(DPRUN, 0x00000001, TRUE); + mddi_wait(14); + write_client_reg(SYSCKENA, 0x00000001, TRUE); + write_client_reg(CLKENB, 0x000000EF, TRUE); + write_client_reg(GPIO_BLOCK_BASE, 0x03FF0000, TRUE); + write_client_reg(GPIODIR, 0x0000024D, TRUE); + write_client_reg(SYSTEM_BLOCK2_BASE, 0x00000173, TRUE); + write_client_reg(GPIOPC, 0x03C300C0, TRUE); + write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000000, TRUE); + write_client_reg(GPIOIS, 0x00000000, TRUE); + write_client_reg(GPIOIEV, 0x00000001, TRUE); + write_client_reg(GPIOIC, 0x000003FF, TRUE); + write_client_reg(GPIO_BLOCK_BASE, 0x00060006, TRUE); + write_client_reg(GPIO_BLOCK_BASE, 0x00080008, TRUE); + write_client_reg(GPIO_BLOCK_BASE, 0x02000200, TRUE); + write_client_reg(DRAMPWR, 0x00000001, TRUE); + write_client_reg(TIMER0CTRL, 0x00000060, TRUE); + write_client_reg(PWM_BLOCK_BASE, 0x00001388, TRUE); + write_client_reg(PWM0OFF, 0x00001387, TRUE); + write_client_reg(TIMER1CTRL, 0x00000060, TRUE); + write_client_reg(TIMER1LOAD, 0x00001388, TRUE); + write_client_reg(PWM1OFF, 0x00001387, TRUE); + write_client_reg(TIMER0CTRL, 0x000000E0, TRUE); + write_client_reg(TIMER1CTRL, 0x000000E0, TRUE); + write_client_reg(PWMCR, 0x00000003, TRUE); + mddi_wait(1); + write_client_reg(SPI_BLOCK_BASE, 0x00063111, TRUE); + write_client_reg(SSITIME, 0x00000100, TRUE); + write_client_reg(SPI_BLOCK_BASE, 0x00063113, TRUE); + mddi_wait(1); + write_client_reg(SSITX, 0x00000000, TRUE); + mddi_wait(1); + write_client_reg(SSITX, 0x00000000, TRUE); + mddi_wait(1); + write_client_reg(SSITX, 0x00000000, TRUE); + mddi_wait(1); + write_client_reg(CLKENB, 0x0000A1EF, TRUE); + write_client_reg(START, 0x00000000, TRUE); + write_client_reg(WRSTB, 0x0000003F, TRUE); + write_client_reg(RDSTB, 0x00000432, TRUE); + write_client_reg(PORT_ENB, 0x00000002, TRUE); + write_client_reg(VSYNIF, 0x00000000, TRUE); + write_client_reg(ASY_DATA, 0x80000000, TRUE); + write_client_reg(ASY_DATB, 0x00000001, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(10); + write_client_reg(ASY_DATA, 0x80000000, TRUE); + write_client_reg(ASY_DATB, 0x80000000, TRUE); + write_client_reg(ASY_DATC, 0x80000000, TRUE); + write_client_reg(ASY_DATD, 0x80000000, TRUE); + write_client_reg(ASY_CMDSET, 0x00000009, TRUE); + write_client_reg(ASY_CMDSET, 0x00000008, TRUE); + write_client_reg(ASY_DATA, 0x80000007, TRUE); + write_client_reg(ASY_DATB, 0x00004005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(20); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + write_client_reg(ASY_DATB, 0x00000000, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + + write_client_reg(VSYNIF, 0x00000001, TRUE); + write_client_reg(PORT_ENB, 0x00000001, TRUE); + } else { + write_client_reg(DPSET0, 0x4BEC0066, TRUE); + write_client_reg(DPSET1, 0x00000113, TRUE); + write_client_reg(DPSUS, 0x00000000, TRUE); + write_client_reg(DPRUN, 0x00000001, TRUE); + mddi_wait(14); + write_client_reg(SYSCKENA, 0x00000001, TRUE); + write_client_reg(CLKENB, 0x000000EF, TRUE); + write_client_reg(GPIODATA, 0x03FF0000, TRUE); + write_client_reg(GPIODIR, 0x0000024D, TRUE); + write_client_reg(GPIOSEL, 0x00000173, TRUE); + write_client_reg(GPIOPC, 0x03C300C0, TRUE); + write_client_reg(WKREQ, 0x00000000, TRUE); + write_client_reg(GPIOIS, 0x00000000, TRUE); + write_client_reg(GPIOIEV, 0x00000001, TRUE); + write_client_reg(GPIOIC, 0x000003FF, TRUE); + write_client_reg(GPIODATA, 0x00060006, TRUE); + write_client_reg(GPIODATA, 0x00080008, TRUE); + write_client_reg(GPIODATA, 0x02000200, TRUE); + + if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA) { + mddi_wait(400); + write_client_reg(DRAMPWR, 0x00000001, TRUE); + + write_client_reg(CNT_DIS, 0x00000002, TRUE); + write_client_reg(BITMAP0, 0x01E00320, TRUE); + write_client_reg(PORT_ENB, 0x00000001, TRUE); + write_client_reg(PORT, 0x00000004, TRUE); + write_client_reg(PXL, 0x0000003A, TRUE); + write_client_reg(MPLFBUF, 0x00000000, TRUE); + write_client_reg(HCYCLE, 0x00000253, TRUE); + write_client_reg(HSW, 0x00000003, TRUE); + write_client_reg(HDE_START, 0x00000017, TRUE); + write_client_reg(HDE_SIZE, 0x0000018F, TRUE); + write_client_reg(VCYCLE, 0x000001FF, TRUE); + write_client_reg(VSW, 0x00000001, TRUE); + write_client_reg(VDE_START, 0x00000003, TRUE); + write_client_reg(VDE_SIZE, 0x000001DF, TRUE); + write_client_reg(START, 0x00000001, TRUE); + mddi_wait(1); + write_client_reg(TIMER0CTRL, 0x00000060, TRUE); + write_client_reg(TIMER0LOAD, 0x00001388, TRUE); + write_client_reg(TIMER1CTRL, 0x00000060, TRUE); + write_client_reg(TIMER1LOAD, 0x00001388, TRUE); + write_client_reg(PWM1OFF, 0x00000087, TRUE); + } else { + write_client_reg(DRAMPWR, 0x00000001, TRUE); + write_client_reg(TIMER0CTRL, 0x00000060, TRUE); + write_client_reg(TIMER0LOAD, 0x00001388, TRUE); + write_client_reg(TIMER1CTRL, 0x00000060, TRUE); + write_client_reg(TIMER1LOAD, 0x00001388, TRUE); + write_client_reg(PWM1OFF, 0x00001387, TRUE); + } + + write_client_reg(TIMER0CTRL, 0x000000E0, TRUE); + write_client_reg(TIMER1CTRL, 0x000000E0, TRUE); + write_client_reg(PWMCR, 0x00000003, TRUE); + mddi_wait(1); + write_client_reg(SSICTL, 0x00000799, TRUE); + write_client_reg(SSITIME, 0x00000100, TRUE); + write_client_reg(SSICTL, 0x0000079b, TRUE); + write_client_reg(SSITX, 0x00000000, TRUE); + mddi_wait(1); + write_client_reg(SSITX, 0x00000000, TRUE); + mddi_wait(1); + write_client_reg(SSITX, 0x00000000, TRUE); + mddi_wait(1); + write_client_reg(SSITX, 0x000800BA, TRUE); + write_client_reg(SSITX, 0x00000111, TRUE); + write_client_reg(SSITX, 0x00080036, TRUE); + write_client_reg(SSITX, 0x00000100, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800BB, TRUE); + write_client_reg(SSITX, 0x00000100, TRUE); + write_client_reg(SSITX, 0x0008003A, TRUE); + write_client_reg(SSITX, 0x00000160, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800BF, TRUE); + write_client_reg(SSITX, 0x00000100, TRUE); + write_client_reg(SSITX, 0x000800B1, TRUE); + write_client_reg(SSITX, 0x0000015D, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800B2, TRUE); + write_client_reg(SSITX, 0x00000133, TRUE); + write_client_reg(SSITX, 0x000800B3, TRUE); + write_client_reg(SSITX, 0x00000122, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800B4, TRUE); + write_client_reg(SSITX, 0x00000102, TRUE); + write_client_reg(SSITX, 0x000800B5, TRUE); + write_client_reg(SSITX, 0x0000011F, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800B6, TRUE); + write_client_reg(SSITX, 0x00000128, TRUE); + write_client_reg(SSITX, 0x000800B7, TRUE); + write_client_reg(SSITX, 0x00000103, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800B9, TRUE); + write_client_reg(SSITX, 0x00000120, TRUE); + write_client_reg(SSITX, 0x000800BD, TRUE); + write_client_reg(SSITX, 0x00000102, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800BE, TRUE); + write_client_reg(SSITX, 0x00000100, TRUE); + write_client_reg(SSITX, 0x000800C0, TRUE); + write_client_reg(SSITX, 0x00000111, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800C1, TRUE); + write_client_reg(SSITX, 0x00000111, TRUE); + write_client_reg(SSITX, 0x000800C2, TRUE); + write_client_reg(SSITX, 0x00000111, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800C3, TRUE); + write_client_reg(SSITX, 0x0008010A, TRUE); + write_client_reg(SSITX, 0x0000010A, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800C4, TRUE); + write_client_reg(SSITX, 0x00080160, TRUE); + write_client_reg(SSITX, 0x00000160, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800C5, TRUE); + write_client_reg(SSITX, 0x00080160, TRUE); + write_client_reg(SSITX, 0x00000160, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800C6, TRUE); + write_client_reg(SSITX, 0x00080160, TRUE); + write_client_reg(SSITX, 0x00000160, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800C7, TRUE); + write_client_reg(SSITX, 0x00080133, TRUE); + write_client_reg(SSITX, 0x00000143, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800C8, TRUE); + write_client_reg(SSITX, 0x00000144, TRUE); + write_client_reg(SSITX, 0x000800C9, TRUE); + write_client_reg(SSITX, 0x00000133, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800CA, TRUE); + write_client_reg(SSITX, 0x00000100, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800EC, TRUE); + write_client_reg(SSITX, 0x00080102, TRUE); + write_client_reg(SSITX, 0x00000118, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800CF, TRUE); + write_client_reg(SSITX, 0x00000101, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800D0, TRUE); + write_client_reg(SSITX, 0x00080110, TRUE); + write_client_reg(SSITX, 0x00000104, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800D1, TRUE); + write_client_reg(SSITX, 0x00000101, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800D2, TRUE); + write_client_reg(SSITX, 0x00080100, TRUE); + write_client_reg(SSITX, 0x0000013A, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800D3, TRUE); + write_client_reg(SSITX, 0x00080100, TRUE); + write_client_reg(SSITX, 0x0000013A, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800D4, TRUE); + write_client_reg(SSITX, 0x00080124, TRUE); + write_client_reg(SSITX, 0x0000016E, TRUE); + mddi_wait(1); + write_client_reg(SSITX, 0x000800D5, TRUE); + write_client_reg(SSITX, 0x00000124, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800ED, TRUE); + write_client_reg(SSITX, 0x00080101, TRUE); + write_client_reg(SSITX, 0x0000010A, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800D6, TRUE); + write_client_reg(SSITX, 0x00000101, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800D7, TRUE); + write_client_reg(SSITX, 0x00080110, TRUE); + write_client_reg(SSITX, 0x0000010A, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800D8, TRUE); + write_client_reg(SSITX, 0x00000101, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800D9, TRUE); + write_client_reg(SSITX, 0x00080100, TRUE); + write_client_reg(SSITX, 0x00000114, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800DE, TRUE); + write_client_reg(SSITX, 0x00080100, TRUE); + write_client_reg(SSITX, 0x00000114, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800DF, TRUE); + write_client_reg(SSITX, 0x00080112, TRUE); + write_client_reg(SSITX, 0x0000013F, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800E0, TRUE); + write_client_reg(SSITX, 0x0000010B, TRUE); + write_client_reg(SSITX, 0x000800E2, TRUE); + write_client_reg(SSITX, 0x00000101, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800E3, TRUE); + write_client_reg(SSITX, 0x00000136, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800E4, TRUE); + write_client_reg(SSITX, 0x00080100, TRUE); + write_client_reg(SSITX, 0x00000103, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800E5, TRUE); + write_client_reg(SSITX, 0x00080102, TRUE); + write_client_reg(SSITX, 0x00000104, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800E6, TRUE); + write_client_reg(SSITX, 0x00000103, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800E7, TRUE); + write_client_reg(SSITX, 0x00080104, TRUE); + write_client_reg(SSITX, 0x0000010A, TRUE); + mddi_wait(2); + write_client_reg(SSITX, 0x000800E8, TRUE); + write_client_reg(SSITX, 0x00000104, TRUE); + write_client_reg(CLKENB, 0x000001EF, TRUE); + write_client_reg(START, 0x00000000, TRUE); + write_client_reg(WRSTB, 0x0000003F, TRUE); + write_client_reg(RDSTB, 0x00000432, TRUE); + write_client_reg(PORT_ENB, 0x00000002, TRUE); + write_client_reg(VSYNIF, 0x00000000, TRUE); + write_client_reg(ASY_DATA, 0x80000000, TRUE); + write_client_reg(ASY_DATB, 0x00000001, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(10); + write_client_reg(ASY_DATA, 0x80000000, TRUE); + write_client_reg(ASY_DATB, 0x80000000, TRUE); + write_client_reg(ASY_DATC, 0x80000000, TRUE); + write_client_reg(ASY_DATD, 0x80000000, TRUE); + write_client_reg(ASY_CMDSET, 0x00000009, TRUE); + write_client_reg(ASY_CMDSET, 0x00000008, TRUE); + write_client_reg(ASY_DATA, 0x80000007, TRUE); + write_client_reg(ASY_DATB, 0x00004005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(20); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + write_client_reg(ASY_DATB, 0x00000000, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + write_client_reg(VSYNIF, 0x00000001, TRUE); + write_client_reg(PORT_ENB, 0x00000001, TRUE); + } + + mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_STANDBY, + TOSHIBA_STATE_PRIM_SEC_READY); +} + +static void toshiba_prim_start(struct msm_fb_data_type *mfd) +{ + if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) + return; + + if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) { + write_client_reg(BITMAP1, 0x01E000F0, TRUE); + write_client_reg(BITMAP2, 0x01E000F0, TRUE); + write_client_reg(BITMAP3, 0x01E000F0, TRUE); + write_client_reg(BITMAP4, 0x00DC00B0, TRUE); + write_client_reg(CLKENB, 0x000001EF, TRUE); + write_client_reg(PORT_ENB, 0x00000001, TRUE); + write_client_reg(PORT, 0x00000016, TRUE); + write_client_reg(PXL, 0x00000002, TRUE); + write_client_reg(MPLFBUF, 0x00000000, TRUE); + write_client_reg(HCYCLE, 0x00000185, TRUE); + write_client_reg(HSW, 0x00000018, TRUE); + write_client_reg(HDE_START, 0x0000004A, TRUE); + write_client_reg(HDE_SIZE, 0x000000EF, TRUE); + write_client_reg(VCYCLE, 0x0000028E, TRUE); + write_client_reg(VSW, 0x00000004, TRUE); + write_client_reg(VDE_START, 0x00000009, TRUE); + write_client_reg(VDE_SIZE, 0x0000027F, TRUE); + write_client_reg(START, 0x00000001, TRUE); + write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000002, TRUE); + } else{ + + write_client_reg(VSYNIF, 0x00000001, TRUE); + write_client_reg(PORT_ENB, 0x00000001, TRUE); + write_client_reg(BITMAP1, 0x01E000F0, TRUE); + write_client_reg(BITMAP2, 0x01E000F0, TRUE); + write_client_reg(BITMAP3, 0x01E000F0, TRUE); + write_client_reg(BITMAP4, 0x00DC00B0, TRUE); + write_client_reg(CLKENB, 0x000001EF, TRUE); + write_client_reg(PORT_ENB, 0x00000001, TRUE); + write_client_reg(PORT, 0x00000004, TRUE); + write_client_reg(PXL, 0x00000002, TRUE); + write_client_reg(MPLFBUF, 0x00000000, TRUE); + + if (mddi_toshiba_61Hz_refresh) { + write_client_reg(HCYCLE, 0x000000FC, TRUE); + mddi_toshiba_rows_per_second = 39526; + mddi_toshiba_rows_per_refresh = 646; + mddi_toshiba_usecs_per_refresh = 16344; + } else { + write_client_reg(HCYCLE, 0x0000010b, TRUE); + mddi_toshiba_rows_per_second = 37313; + mddi_toshiba_rows_per_refresh = 646; + mddi_toshiba_usecs_per_refresh = 17313; + } + + write_client_reg(HSW, 0x00000003, TRUE); + write_client_reg(HDE_START, 0x00000007, TRUE); + write_client_reg(HDE_SIZE, 0x000000EF, TRUE); + write_client_reg(VCYCLE, 0x00000285, TRUE); + write_client_reg(VSW, 0x00000001, TRUE); + write_client_reg(VDE_START, 0x00000003, TRUE); + write_client_reg(VDE_SIZE, 0x0000027F, TRUE); + write_client_reg(START, 0x00000001, TRUE); + mddi_wait(10); + write_client_reg(SSITX, 0x000800BC, TRUE); + write_client_reg(SSITX, 0x00000180, TRUE); + write_client_reg(SSITX, 0x0008003B, TRUE); + write_client_reg(SSITX, 0x00000100, TRUE); + mddi_wait(1); + write_client_reg(SSITX, 0x000800B0, TRUE); + write_client_reg(SSITX, 0x00000116, TRUE); + mddi_wait(1); + write_client_reg(SSITX, 0x000800B8, TRUE); + write_client_reg(SSITX, 0x000801FF, TRUE); + write_client_reg(SSITX, 0x000001F5, TRUE); + mddi_wait(1); + write_client_reg(SSITX, 0x00000011, TRUE); + write_client_reg(SSITX, 0x00000029, TRUE); + write_client_reg(WKREQ, 0x00000000, TRUE); + write_client_reg(WAKEUP, 0x00000000, TRUE); + write_client_reg(INTMSK, 0x00000001, TRUE); + } + + mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY, + TOSHIBA_STATE_PRIM_NORMAL_MODE); +} + +static void toshiba_sec_start(struct msm_fb_data_type *mfd) +{ + if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) + return; + + write_client_reg(VSYNIF, 0x00000000, TRUE); + write_client_reg(PORT_ENB, 0x00000002, TRUE); + write_client_reg(CLKENB, 0x000011EF, TRUE); + write_client_reg(BITMAP0, 0x028001E0, TRUE); + write_client_reg(BITMAP1, 0x00000000, TRUE); + write_client_reg(BITMAP2, 0x00000000, TRUE); + write_client_reg(BITMAP3, 0x00000000, TRUE); + write_client_reg(BITMAP4, 0x00DC00B0, TRUE); + write_client_reg(PORT, 0x00000000, TRUE); + write_client_reg(PXL, 0x00000000, TRUE); + write_client_reg(MPLFBUF, 0x00000004, TRUE); + write_client_reg(HCYCLE, 0x0000006B, TRUE); + write_client_reg(HSW, 0x00000003, TRUE); + write_client_reg(HDE_START, 0x00000007, TRUE); + write_client_reg(HDE_SIZE, 0x00000057, TRUE); + write_client_reg(VCYCLE, 0x000000E6, TRUE); + write_client_reg(VSW, 0x00000001, TRUE); + write_client_reg(VDE_START, 0x00000003, TRUE); + write_client_reg(VDE_SIZE, 0x000000DB, TRUE); + write_client_reg(ASY_DATA, 0x80000001, TRUE); + write_client_reg(ASY_DATB, 0x0000011B, TRUE); + write_client_reg(ASY_DATC, 0x80000002, TRUE); + write_client_reg(ASY_DATD, 0x00000700, TRUE); + write_client_reg(ASY_DATE, 0x80000003, TRUE); + write_client_reg(ASY_DATF, 0x00000230, TRUE); + write_client_reg(ASY_DATG, 0x80000008, TRUE); + write_client_reg(ASY_DATH, 0x00000402, TRUE); + write_client_reg(ASY_CMDSET, 0x00000001, TRUE); + write_client_reg(ASY_CMDSET, 0x00000000, TRUE); + write_client_reg(ASY_DATA, 0x80000009, TRUE); + write_client_reg(ASY_DATB, 0x00000000, TRUE); + write_client_reg(ASY_DATC, 0x8000000B, TRUE); + write_client_reg(ASY_DATD, 0x00000000, TRUE); + write_client_reg(ASY_DATE, 0x8000000C, TRUE); + write_client_reg(ASY_DATF, 0x00000000, TRUE); + write_client_reg(ASY_DATG, 0x8000000D, TRUE); + write_client_reg(ASY_DATH, 0x00000409, TRUE); + write_client_reg(ASY_CMDSET, 0x00000001, TRUE); + write_client_reg(ASY_CMDSET, 0x00000000, TRUE); + write_client_reg(ASY_DATA, 0x8000000E, TRUE); + write_client_reg(ASY_DATB, 0x00000409, TRUE); + write_client_reg(ASY_DATC, 0x80000030, TRUE); + write_client_reg(ASY_DATD, 0x00000000, TRUE); + write_client_reg(ASY_DATE, 0x80000031, TRUE); + write_client_reg(ASY_DATF, 0x00000100, TRUE); + write_client_reg(ASY_DATG, 0x80000032, TRUE); + write_client_reg(ASY_DATH, 0x00000104, TRUE); + write_client_reg(ASY_CMDSET, 0x00000001, TRUE); + write_client_reg(ASY_CMDSET, 0x00000000, TRUE); + write_client_reg(ASY_DATA, 0x80000033, TRUE); + write_client_reg(ASY_DATB, 0x00000400, TRUE); + write_client_reg(ASY_DATC, 0x80000034, TRUE); + write_client_reg(ASY_DATD, 0x00000306, TRUE); + write_client_reg(ASY_DATE, 0x80000035, TRUE); + write_client_reg(ASY_DATF, 0x00000706, TRUE); + write_client_reg(ASY_DATG, 0x80000036, TRUE); + write_client_reg(ASY_DATH, 0x00000707, TRUE); + write_client_reg(ASY_CMDSET, 0x00000001, TRUE); + write_client_reg(ASY_CMDSET, 0x00000000, TRUE); + write_client_reg(ASY_DATA, 0x80000037, TRUE); + write_client_reg(ASY_DATB, 0x00000004, TRUE); + write_client_reg(ASY_DATC, 0x80000038, TRUE); + write_client_reg(ASY_DATD, 0x00000000, TRUE); + write_client_reg(ASY_DATE, 0x80000039, TRUE); + write_client_reg(ASY_DATF, 0x00000000, TRUE); + write_client_reg(ASY_DATG, 0x8000003A, TRUE); + write_client_reg(ASY_DATH, 0x00000001, TRUE); + write_client_reg(ASY_CMDSET, 0x00000001, TRUE); + write_client_reg(ASY_CMDSET, 0x00000000, TRUE); + write_client_reg(ASY_DATA, 0x80000044, TRUE); + write_client_reg(ASY_DATB, 0x0000AF00, TRUE); + write_client_reg(ASY_DATC, 0x80000045, TRUE); + write_client_reg(ASY_DATD, 0x0000DB00, TRUE); + write_client_reg(ASY_DATE, 0x08000042, TRUE); + write_client_reg(ASY_DATF, 0x0000DB00, TRUE); + write_client_reg(ASY_DATG, 0x80000021, TRUE); + write_client_reg(ASY_DATH, 0x00000000, TRUE); + write_client_reg(ASY_CMDSET, 0x00000001, TRUE); + write_client_reg(ASY_CMDSET, 0x00000000, TRUE); + write_client_reg(PXL, 0x0000000C, TRUE); + write_client_reg(VSYNIF, 0x00000001, TRUE); + write_client_reg(ASY_DATA, 0x80000022, TRUE); + write_client_reg(ASY_CMDSET, 0x00000003, TRUE); + write_client_reg(START, 0x00000001, TRUE); + mddi_wait(60); + write_client_reg(PXL, 0x00000000, TRUE); + write_client_reg(VSYNIF, 0x00000000, TRUE); + write_client_reg(START, 0x00000000, TRUE); + write_client_reg(ASY_CMDSET, 0x00000000, TRUE); + write_client_reg(ASY_DATA, 0x80000050, TRUE); + write_client_reg(ASY_DATB, 0x00000000, TRUE); + write_client_reg(ASY_DATC, 0x80000051, TRUE); + write_client_reg(ASY_DATD, 0x00000E00, TRUE); + write_client_reg(ASY_DATE, 0x80000052, TRUE); + write_client_reg(ASY_DATF, 0x00000D01, TRUE); + write_client_reg(ASY_DATG, 0x80000053, TRUE); + write_client_reg(ASY_DATH, 0x00000000, TRUE); + write_client_reg(ASY_CMDSET, 0x00000001, TRUE); + write_client_reg(ASY_CMDSET, 0x00000000, TRUE); + write_client_reg(ASY_DATA, 0x80000058, TRUE); + write_client_reg(ASY_DATB, 0x00000000, TRUE); + write_client_reg(ASY_DATC, 0x8000005A, TRUE); + write_client_reg(ASY_DATD, 0x00000E01, TRUE); + write_client_reg(ASY_CMDSET, 0x00000009, TRUE); + write_client_reg(ASY_CMDSET, 0x00000008, TRUE); + write_client_reg(ASY_DATA, 0x80000011, TRUE); + write_client_reg(ASY_DATB, 0x00000812, TRUE); + write_client_reg(ASY_DATC, 0x80000012, TRUE); + write_client_reg(ASY_DATD, 0x00000003, TRUE); + write_client_reg(ASY_DATE, 0x80000013, TRUE); + write_client_reg(ASY_DATF, 0x00000909, TRUE); + write_client_reg(ASY_DATG, 0x80000010, TRUE); + write_client_reg(ASY_DATH, 0x00000040, TRUE); + write_client_reg(ASY_CMDSET, 0x00000001, TRUE); + write_client_reg(ASY_CMDSET, 0x00000000, TRUE); + mddi_wait(40); + write_client_reg(ASY_DATA, 0x80000010, TRUE); + write_client_reg(ASY_DATB, 0x00000340, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(60); + write_client_reg(ASY_DATA, 0x80000010, TRUE); + write_client_reg(ASY_DATB, 0x00003340, TRUE); + write_client_reg(ASY_DATC, 0x80000007, TRUE); + write_client_reg(ASY_DATD, 0x00004007, TRUE); + write_client_reg(ASY_CMDSET, 0x00000009, TRUE); + write_client_reg(ASY_CMDSET, 0x00000008, TRUE); + mddi_wait(1); + write_client_reg(ASY_DATA, 0x80000007, TRUE); + write_client_reg(ASY_DATB, 0x00004017, TRUE); + write_client_reg(ASY_DATC, 0x8000005B, TRUE); + write_client_reg(ASY_DATD, 0x00000000, TRUE); + write_client_reg(ASY_DATE, 0x80000059, TRUE); + write_client_reg(ASY_DATF, 0x00000011, TRUE); + write_client_reg(ASY_CMDSET, 0x0000000D, TRUE); + write_client_reg(ASY_CMDSET, 0x0000000C, TRUE); + mddi_wait(20); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + /* LTPS I/F control */ + write_client_reg(ASY_DATB, 0x00000019, TRUE); + /* Direct cmd transfer enable */ + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + /* Direct cmd transfer disable */ + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(20); + /* Index setting of SUB LCDD */ + write_client_reg(ASY_DATA, 0x80000059, TRUE); + /* LTPS I/F control */ + write_client_reg(ASY_DATB, 0x00000079, TRUE); + /* Direct cmd transfer enable */ + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + /* Direct cmd transfer disable */ + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(20); + /* Index setting of SUB LCDD */ + write_client_reg(ASY_DATA, 0x80000059, TRUE); + /* LTPS I/F control */ + write_client_reg(ASY_DATB, 0x000003FD, TRUE); + /* Direct cmd transfer enable */ + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + /* Direct cmd transfer disable */ + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(20); + mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY, + TOSHIBA_STATE_SEC_NORMAL_MODE); +} + +static void toshiba_prim_lcd_off(struct msm_fb_data_type *mfd) +{ + if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) { + gordon_disp_off(); + } else{ + + /* Main panel power off (Deep standby in) */ + write_client_reg(SSITX, 0x000800BC, TRUE); + write_client_reg(SSITX, 0x00000100, TRUE); + write_client_reg(SSITX, 0x00000028, TRUE); + mddi_wait(1); + write_client_reg(SSITX, 0x000800B8, TRUE); + write_client_reg(SSITX, 0x00000180, TRUE); + write_client_reg(SSITX, 0x00000102, TRUE); + write_client_reg(SSITX, 0x00000010, TRUE); + } + write_client_reg(PORT, 0x00000003, TRUE); + write_client_reg(REGENB, 0x00000001, TRUE); + mddi_wait(1); + write_client_reg(PXL, 0x00000000, TRUE); + write_client_reg(START, 0x00000000, TRUE); + write_client_reg(REGENB, 0x00000001, TRUE); + mddi_wait(3); + if (TM_GET_PID(mfd->panel.id) != LCD_SHARP_2P4_VGA) { + write_client_reg(SSITX, 0x000800B0, TRUE); + write_client_reg(SSITX, 0x00000100, TRUE); + } + mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_NORMAL_MODE, + TOSHIBA_STATE_PRIM_SEC_STANDBY); +} + +static void toshiba_sec_lcd_off(struct msm_fb_data_type *mfd) +{ + if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) + return; + + write_client_reg(VSYNIF, 0x00000000, TRUE); + write_client_reg(PORT_ENB, 0x00000002, TRUE); + write_client_reg(ASY_DATA, 0x80000007, TRUE); + write_client_reg(ASY_DATB, 0x00004016, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(2); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + write_client_reg(ASY_DATB, 0x00000019, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(2); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + write_client_reg(ASY_DATB, 0x0000000B, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(2); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + write_client_reg(ASY_DATB, 0x00000002, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(4); + write_client_reg(ASY_DATA, 0x80000010, TRUE); + write_client_reg(ASY_DATB, 0x00000300, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(4); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + write_client_reg(ASY_DATB, 0x00000000, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(2); + write_client_reg(ASY_DATA, 0x80000007, TRUE); + write_client_reg(ASY_DATB, 0x00004004, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(2); + write_client_reg(PORT, 0x00000000, TRUE); + write_client_reg(PXL, 0x00000000, TRUE); + write_client_reg(START, 0x00000000, TRUE); + write_client_reg(VSYNIF, 0x00000001, TRUE); + write_client_reg(PORT_ENB, 0x00000001, TRUE); + write_client_reg(REGENB, 0x00000001, TRUE); + mddi_toshiba_state_transition(TOSHIBA_STATE_SEC_NORMAL_MODE, + TOSHIBA_STATE_PRIM_SEC_STANDBY); +} + +static void toshiba_sec_cont_update_start(struct msm_fb_data_type *mfd) +{ + + if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) + return; + + write_client_reg(VSYNIF, 0x00000000, TRUE); + write_client_reg(PORT_ENB, 0x00000002, TRUE); + write_client_reg(INTMASK, 0x00000001, TRUE); + write_client_reg(TTBUSSEL, 0x0000000B, TRUE); + write_client_reg(MONI, 0x00000008, TRUE); + write_client_reg(CLKENB, 0x000000EF, TRUE); + write_client_reg(CLKENB, 0x000010EF, TRUE); + write_client_reg(CLKENB, 0x000011EF, TRUE); + write_client_reg(BITMAP4, 0x00DC00B0, TRUE); + write_client_reg(HCYCLE, 0x0000006B, TRUE); + write_client_reg(HSW, 0x00000003, TRUE); + write_client_reg(HDE_START, 0x00000002, TRUE); + write_client_reg(HDE_SIZE, 0x00000057, TRUE); + write_client_reg(VCYCLE, 0x000000E6, TRUE); + write_client_reg(VSW, 0x00000001, TRUE); + write_client_reg(VDE_START, 0x00000003, TRUE); + write_client_reg(VDE_SIZE, 0x000000DB, TRUE); + write_client_reg(WRSTB, 0x00000015, TRUE); + write_client_reg(MPLFBUF, 0x00000004, TRUE); + write_client_reg(ASY_DATA, 0x80000021, TRUE); + write_client_reg(ASY_DATB, 0x00000000, TRUE); + write_client_reg(ASY_DATC, 0x80000022, TRUE); + write_client_reg(ASY_CMDSET, 0x00000007, TRUE); + write_client_reg(PXL, 0x00000089, TRUE); + write_client_reg(VSYNIF, 0x00000001, TRUE); + mddi_wait(2); +} + +static void toshiba_sec_cont_update_stop(struct msm_fb_data_type *mfd) +{ + if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) + return; + + write_client_reg(PXL, 0x00000000, TRUE); + write_client_reg(VSYNIF, 0x00000000, TRUE); + write_client_reg(START, 0x00000000, TRUE); + write_client_reg(ASY_CMDSET, 0x00000000, TRUE); + mddi_wait(3); + write_client_reg(SRST, 0x00000002, TRUE); + mddi_wait(3); + write_client_reg(SRST, 0x00000003, TRUE); +} + +static void toshiba_sec_backlight_on(struct msm_fb_data_type *mfd) +{ + if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) + return; + + write_client_reg(TIMER0CTRL, 0x00000060, TRUE); + write_client_reg(TIMER0LOAD, 0x00001388, TRUE); + write_client_reg(PWM0OFF, 0x00000001, TRUE); + write_client_reg(TIMER1CTRL, 0x00000060, TRUE); + write_client_reg(TIMER1LOAD, 0x00001388, TRUE); + write_client_reg(PWM1OFF, 0x00001387, TRUE); + write_client_reg(TIMER0CTRL, 0x000000E0, TRUE); + write_client_reg(TIMER1CTRL, 0x000000E0, TRUE); + write_client_reg(PWMCR, 0x00000003, TRUE); +} + +static void toshiba_sec_sleep_in(struct msm_fb_data_type *mfd) +{ + if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) + return; + + write_client_reg(VSYNIF, 0x00000000, TRUE); + write_client_reg(PORT_ENB, 0x00000002, TRUE); + write_client_reg(ASY_DATA, 0x80000007, TRUE); + write_client_reg(ASY_DATB, 0x00004016, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(2); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + write_client_reg(ASY_DATB, 0x00000019, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(2); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + write_client_reg(ASY_DATB, 0x0000000B, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(2); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + write_client_reg(ASY_DATB, 0x00000002, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(4); + write_client_reg(ASY_DATA, 0x80000010, TRUE); + write_client_reg(ASY_DATB, 0x00000300, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(4); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + write_client_reg(ASY_DATB, 0x00000000, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(2); + write_client_reg(ASY_DATA, 0x80000007, TRUE); + write_client_reg(ASY_DATB, 0x00004004, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(2); + write_client_reg(PORT, 0x00000000, TRUE); + write_client_reg(PXL, 0x00000000, TRUE); + write_client_reg(START, 0x00000000, TRUE); + write_client_reg(REGENB, 0x00000001, TRUE); + /* Sleep in sequence */ + write_client_reg(ASY_DATA, 0x80000010, TRUE); + write_client_reg(ASY_DATB, 0x00000302, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); +} + +static void toshiba_sec_sleep_out(struct msm_fb_data_type *mfd) +{ + if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) + return; + + write_client_reg(VSYNIF, 0x00000000, TRUE); + write_client_reg(PORT_ENB, 0x00000002, TRUE); + write_client_reg(ASY_DATA, 0x80000010, TRUE); + write_client_reg(ASY_DATB, 0x00000300, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + /* Display ON sequence */ + write_client_reg(ASY_DATA, 0x80000011, TRUE); + write_client_reg(ASY_DATB, 0x00000812, TRUE); + write_client_reg(ASY_DATC, 0x80000012, TRUE); + write_client_reg(ASY_DATD, 0x00000003, TRUE); + write_client_reg(ASY_DATE, 0x80000013, TRUE); + write_client_reg(ASY_DATF, 0x00000909, TRUE); + write_client_reg(ASY_DATG, 0x80000010, TRUE); + write_client_reg(ASY_DATH, 0x00000040, TRUE); + write_client_reg(ASY_CMDSET, 0x00000001, TRUE); + write_client_reg(ASY_CMDSET, 0x00000000, TRUE); + mddi_wait(4); + write_client_reg(ASY_DATA, 0x80000010, TRUE); + write_client_reg(ASY_DATB, 0x00000340, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(6); + write_client_reg(ASY_DATA, 0x80000010, TRUE); + write_client_reg(ASY_DATB, 0x00003340, TRUE); + write_client_reg(ASY_DATC, 0x80000007, TRUE); + write_client_reg(ASY_DATD, 0x00004007, TRUE); + write_client_reg(ASY_CMDSET, 0x00000009, TRUE); + write_client_reg(ASY_CMDSET, 0x00000008, TRUE); + mddi_wait(1); + write_client_reg(ASY_DATA, 0x80000007, TRUE); + write_client_reg(ASY_DATB, 0x00004017, TRUE); + write_client_reg(ASY_DATC, 0x8000005B, TRUE); + write_client_reg(ASY_DATD, 0x00000000, TRUE); + write_client_reg(ASY_DATE, 0x80000059, TRUE); + write_client_reg(ASY_DATF, 0x00000011, TRUE); + write_client_reg(ASY_CMDSET, 0x0000000D, TRUE); + write_client_reg(ASY_CMDSET, 0x0000000C, TRUE); + mddi_wait(2); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + write_client_reg(ASY_DATB, 0x00000019, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(2); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + write_client_reg(ASY_DATB, 0x00000079, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(2); + write_client_reg(ASY_DATA, 0x80000059, TRUE); + write_client_reg(ASY_DATB, 0x000003FD, TRUE); + write_client_reg(ASY_CMDSET, 0x00000005, TRUE); + write_client_reg(ASY_CMDSET, 0x00000004, TRUE); + mddi_wait(2); +} + +static void mddi_toshiba_lcd_set_backlight(struct msm_fb_data_type *mfd) +{ + int32 level; + int ret = -EPERM; + int max = mfd->panel_info.bl_max; + int min = mfd->panel_info.bl_min; + + if (mddi_toshiba_pdata && mddi_toshiba_pdata->pmic_backlight) { + ret = mddi_toshiba_pdata->pmic_backlight(mfd->bl_level); + if (!ret) + return; + } + + if (ret && mddi_toshiba_pdata && mddi_toshiba_pdata->backlight_level) { + level = mddi_toshiba_pdata->backlight_level(mfd->bl_level, + max, min); + + if (level < 0) + return; + + if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) + write_client_reg(TIMER0LOAD, 0x00001388, TRUE); + } else { + if (!max) + level = 0; + else + level = (mfd->bl_level * 4999) / max; + } + + write_client_reg(PWM0OFF, level, TRUE); +} + +static void mddi_toshiba_vsync_set_handler(msm_fb_vsync_handler_type handler, /* ISR to be executed */ + void *arg) +{ + boolean error = FALSE; + unsigned long flags; + + /* Disable interrupts */ + spin_lock_irqsave(&mddi_host_spin_lock, flags); + /* INTLOCK(); */ + + if (mddi_toshiba_vsync_handler != NULL) { + error = TRUE; + } else { + /* Register the handler for this particular GROUP interrupt source */ + mddi_toshiba_vsync_handler = handler; + mddi_toshiba_vsync_handler_arg = arg; + } + + /* Restore interrupts */ + spin_unlock_irqrestore(&mddi_host_spin_lock, flags); + /* MDDI_INTFREE(); */ + if (error) { + MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n"); + } else { + /* Enable the vsync wakeup */ + mddi_queue_register_write(INTMSK, 0x0000, FALSE, 0); + + mddi_toshiba_vsync_attempts = 1; + mddi_vsync_detect_enabled = TRUE; + } +} /* mddi_toshiba_vsync_set_handler */ + +static void mddi_toshiba_lcd_vsync_detected(boolean detected) +{ + /* static timetick_type start_time = 0; */ + static struct timeval start_time; + static boolean first_time = TRUE; + /* uint32 mdp_cnt_val = 0; */ + /* timetick_type elapsed_us; */ + struct timeval now; + uint32 elapsed_us; + uint32 num_vsyncs; + + if ((detected) || (mddi_toshiba_vsync_attempts > 5)) { + if ((detected) && (mddi_toshiba_monitor_refresh_value)) { + /* if (start_time != 0) */ + if (!first_time) { + jiffies_to_timeval(jiffies, &now); + elapsed_us = + (now.tv_sec - start_time.tv_sec) * 1000000 + + now.tv_usec - start_time.tv_usec; + /* + * LCD is configured for a refresh every usecs, + * so to determine the number of vsyncs that + * have occurred since the last measurement + * add half that to the time difference and + * divide by the refresh rate. + */ + num_vsyncs = (elapsed_us + + (mddi_toshiba_usecs_per_refresh >> + 1)) / + mddi_toshiba_usecs_per_refresh; + /* + * LCD is configured for * hsyncs (rows) per + * refresh cycle. Calculate new rows_per_second + * value based upon these new measurements. + * MDP can update with this new value. + */ + mddi_toshiba_rows_per_second = + (mddi_toshiba_rows_per_refresh * 1000 * + num_vsyncs) / (elapsed_us / 1000); + } + /* start_time = timetick_get(); */ + first_time = FALSE; + jiffies_to_timeval(jiffies, &start_time); + if (mddi_toshiba_report_refresh_measurements) { + (void)mddi_queue_register_read_int(VPOS, + &mddi_toshiba_curr_vpos); + /* mdp_cnt_val = MDP_LINE_COUNT; */ + } + } + /* if detected = TRUE, client initiated wakeup was detected */ + if (mddi_toshiba_vsync_handler != NULL) { + (*mddi_toshiba_vsync_handler) + (mddi_toshiba_vsync_handler_arg); + mddi_toshiba_vsync_handler = NULL; + } + mddi_vsync_detect_enabled = FALSE; + mddi_toshiba_vsync_attempts = 0; + /* need to disable the interrupt wakeup */ + if (!mddi_queue_register_write_int(INTMSK, 0x0001)) + MDDI_MSG_ERR("Vsync interrupt disable failed!\n"); + if (!detected) { + /* give up after 5 failed attempts but show error */ + MDDI_MSG_NOTICE("Vsync detection failed!\n"); + } else if ((mddi_toshiba_monitor_refresh_value) && + (mddi_toshiba_report_refresh_measurements)) { + MDDI_MSG_NOTICE(" Last Line Counter=%d!\n", + mddi_toshiba_curr_vpos); + /* MDDI_MSG_NOTICE(" MDP Line Counter=%d!\n",mdp_cnt_val); */ + MDDI_MSG_NOTICE(" Lines Per Second=%d!\n", + mddi_toshiba_rows_per_second); + } + /* clear the interrupt */ + if (!mddi_queue_register_write_int(INTFLG, 0x0001)) + MDDI_MSG_ERR("Vsync interrupt clear failed!\n"); + } else { + /* if detected = FALSE, we woke up from hibernation, but did not + * detect client initiated wakeup. + */ + mddi_toshiba_vsync_attempts++; + } +} + +static void mddi_toshiba_prim_init(struct msm_fb_data_type *mfd) +{ + + switch (toshiba_state) { + case TOSHIBA_STATE_PRIM_SEC_READY: + break; + case TOSHIBA_STATE_OFF: + toshiba_state = TOSHIBA_STATE_PRIM_SEC_STANDBY; + toshiba_common_initial_setup(mfd); + break; + case TOSHIBA_STATE_PRIM_SEC_STANDBY: + toshiba_common_initial_setup(mfd); + break; + case TOSHIBA_STATE_SEC_NORMAL_MODE: + toshiba_sec_cont_update_stop(mfd); + toshiba_sec_sleep_in(mfd); + toshiba_sec_sleep_out(mfd); + toshiba_sec_lcd_off(mfd); + toshiba_common_initial_setup(mfd); + break; + default: + MDDI_MSG_ERR("mddi_toshiba_prim_init from state %d\n", + toshiba_state); + } + + toshiba_prim_start(mfd); + if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) + gordon_disp_init(); + mddi_host_write_pix_attr_reg(0x00C3); +} + +static void mddi_toshiba_sec_init(struct msm_fb_data_type *mfd) +{ + + switch (toshiba_state) { + case TOSHIBA_STATE_PRIM_SEC_READY: + break; + case TOSHIBA_STATE_PRIM_SEC_STANDBY: + toshiba_common_initial_setup(mfd); + break; + case TOSHIBA_STATE_PRIM_NORMAL_MODE: + toshiba_prim_lcd_off(mfd); + toshiba_common_initial_setup(mfd); + break; + default: + MDDI_MSG_ERR("mddi_toshiba_sec_init from state %d\n", + toshiba_state); + } + + toshiba_sec_start(mfd); + toshiba_sec_backlight_on(mfd); + toshiba_sec_cont_update_start(mfd); + mddi_host_write_pix_attr_reg(0x0400); +} + +static void mddi_toshiba_lcd_powerdown(struct msm_fb_data_type *mfd) +{ + switch (toshiba_state) { + case TOSHIBA_STATE_PRIM_SEC_READY: + mddi_toshiba_prim_init(mfd); + mddi_toshiba_lcd_powerdown(mfd); + return; + case TOSHIBA_STATE_PRIM_SEC_STANDBY: + break; + case TOSHIBA_STATE_PRIM_NORMAL_MODE: + toshiba_prim_lcd_off(mfd); + break; + case TOSHIBA_STATE_SEC_NORMAL_MODE: + toshiba_sec_cont_update_stop(mfd); + toshiba_sec_sleep_in(mfd); + toshiba_sec_sleep_out(mfd); + toshiba_sec_lcd_off(mfd); + break; + default: + MDDI_MSG_ERR("mddi_toshiba_lcd_powerdown from state %d\n", + toshiba_state); + } +} + +static int mddi_sharpgordon_firsttime = 1; + +static int mddi_toshiba_lcd_on(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd; + mfd = platform_get_drvdata(pdev); + if (!mfd) + return -ENODEV; + if (mfd->key != MFD_KEY) + return -EINVAL; + + if (TM_GET_DID(mfd->panel.id) == TOSHIBA_VGA_PRIM) + mddi_toshiba_prim_init(mfd); + else + mddi_toshiba_sec_init(mfd); + if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) { + if (mddi_sharpgordon_firsttime) { + mddi_sharpgordon_firsttime = 0; + write_client_reg(REGENB, 0x00000001, TRUE); + } + } + return 0; +} + +static int mddi_toshiba_lcd_off(struct platform_device *pdev) +{ + mddi_toshiba_lcd_powerdown(platform_get_drvdata(pdev)); + return 0; +} + +static int __init mddi_toshiba_lcd_probe(struct platform_device *pdev) +{ + if (pdev->id == 0) { + mddi_toshiba_pdata = pdev->dev.platform_data; + return 0; + } + + msm_fb_add_device(pdev); + + return 0; +} + +static struct platform_driver this_driver = { + .probe = mddi_toshiba_lcd_probe, + .driver = { + .name = "mddi_toshiba", + }, +}; + +static struct msm_fb_panel_data toshiba_panel_data = { + .on = mddi_toshiba_lcd_on, + .off = mddi_toshiba_lcd_off, +}; + +static int ch_used[3]; + +int mddi_toshiba_device_register(struct msm_panel_info *pinfo, + u32 channel, u32 panel) +{ + struct platform_device *pdev = NULL; + int ret; + + if ((channel >= 3) || ch_used[channel]) + return -ENODEV; + + if ((channel != TOSHIBA_VGA_PRIM) && + mddi_toshiba_pdata && mddi_toshiba_pdata->panel_num) + if (mddi_toshiba_pdata->panel_num() < 2) + return -ENODEV; + + ch_used[channel] = TRUE; + + pdev = platform_device_alloc("mddi_toshiba", (panel << 8)|channel); + if (!pdev) + return -ENOMEM; + + if (channel == TOSHIBA_VGA_PRIM) { + toshiba_panel_data.set_backlight = + mddi_toshiba_lcd_set_backlight; + + if (pinfo->lcd.vsync_enable) { + toshiba_panel_data.set_vsync_notifier = + mddi_toshiba_vsync_set_handler; + mddi_lcd.vsync_detected = + mddi_toshiba_lcd_vsync_detected; + } + } else { + toshiba_panel_data.set_backlight = NULL; + toshiba_panel_data.set_vsync_notifier = NULL; + } + + toshiba_panel_data.panel_info = *pinfo; + + ret = platform_device_add_data(pdev, &toshiba_panel_data, + sizeof(toshiba_panel_data)); + if (ret) { + printk(KERN_ERR + "%s: platform_device_add_data failed!\n", __func__); + goto err_device_put; + } + + ret = platform_device_add(pdev); + if (ret) { + printk(KERN_ERR + "%s: platform_device_register failed!\n", __func__); + goto err_device_put; + } + + return 0; + +err_device_put: + platform_device_put(pdev); + return ret; +} + +static int __init mddi_toshiba_lcd_init(void) +{ + return platform_driver_register(&this_driver); +} + +module_init(mddi_toshiba_lcd_init); diff --git a/drivers/staging/msm/mddi_toshiba.h b/drivers/staging/msm/mddi_toshiba.h new file mode 100644 index 000000000000..2d22b9a2c413 --- /dev/null +++ b/drivers/staging/msm/mddi_toshiba.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MDDI_TOSHIBA_H +#define MDDI_TOSHIBA_H + +#define TOSHIBA_VGA_PRIM 1 +#define TOSHIBA_VGA_SECD 2 + +#define LCD_TOSHIBA_2P4_VGA 0 +#define LCD_TOSHIBA_2P4_WVGA 1 +#define LCD_TOSHIBA_2P4_WVGA_PT 2 +#define LCD_SHARP_2P4_VGA 3 + +#define GPIO_BLOCK_BASE 0x150000 +#define SYSTEM_BLOCK2_BASE 0x170000 + +#define GPIODIR (GPIO_BLOCK_BASE|0x04) +#define GPIOSEL (SYSTEM_BLOCK2_BASE|0x00) +#define GPIOPC (GPIO_BLOCK_BASE|0x28) +#define GPIODATA (GPIO_BLOCK_BASE|0x00) + +#define write_client_reg(__X, __Y, __Z) {\ + mddi_queue_register_write(__X, __Y, TRUE, 0);\ +} + +#endif /* MDDI_TOSHIBA_H */ diff --git a/drivers/staging/msm/mddi_toshiba_vga.c b/drivers/staging/msm/mddi_toshiba_vga.c new file mode 100644 index 000000000000..7e61d3a5b8f1 --- /dev/null +++ b/drivers/staging/msm/mddi_toshiba_vga.c @@ -0,0 +1,136 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" +#include "mddihost.h" +#include "mddihosti.h" +#include "mddi_toshiba.h" + +static uint32 read_client_reg(uint32 addr) +{ + uint32 val; + mddi_queue_register_read(addr, &val, TRUE, 0); + return val; +} + +static uint32 toshiba_lcd_gpio_read(void) +{ + uint32 val; + + write_client_reg(GPIODIR, 0x0000000C, TRUE); + write_client_reg(GPIOSEL, 0x00000000, TRUE); + write_client_reg(GPIOSEL, 0x00000000, TRUE); + write_client_reg(GPIOPC, 0x03CF00C0, TRUE); + val = read_client_reg(GPIODATA) & 0x2C0; + + return val; +} + +static u32 mddi_toshiba_panel_detect(void) +{ + mddi_host_type host_idx = MDDI_HOST_PRIM; + uint32 lcd_gpio; + u32 mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA; + + /* Toshiba display requires larger drive_lo value */ + mddi_host_reg_out(DRIVE_LO, 0x0050); + + lcd_gpio = toshiba_lcd_gpio_read(); + switch (lcd_gpio) { + case 0x0080: + mddi_toshiba_lcd = LCD_SHARP_2P4_VGA; + break; + + case 0x00C0: + default: + mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA; + break; + } + + return mddi_toshiba_lcd; +} + +static int __init mddi_toshiba_vga_init(void) +{ + int ret; + struct msm_panel_info pinfo; + u32 panel; + +#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT + u32 id; + + ret = msm_fb_detect_client("mddi_toshiba_vga"); + if (ret == -ENODEV) + return 0; + + if (ret) { + id = mddi_get_client_id(); + if ((id >> 16) != 0xD263) + return 0; + } +#endif + + panel = mddi_toshiba_panel_detect(); + + pinfo.xres = 480; + pinfo.yres = 640; + pinfo.type = MDDI_PANEL; + pinfo.pdest = DISPLAY_1; + pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR; + pinfo.wait_cycle = 0; + pinfo.bpp = 18; + pinfo.lcd.vsync_enable = TRUE; + pinfo.lcd.refx100 = 6118; + pinfo.lcd.v_back_porch = 6; + pinfo.lcd.v_front_porch = 0; + pinfo.lcd.v_pulse_width = 0; + pinfo.lcd.hw_vsync_mode = FALSE; + pinfo.lcd.vsync_notifier_period = (1 * HZ); + pinfo.bl_max = 99; + pinfo.bl_min = 1; + pinfo.clk_rate = 122880000; + pinfo.clk_min = 120000000; + pinfo.clk_max = 200000000; + pinfo.fb_num = 2; + + ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM, panel); + if (ret) { + printk(KERN_ERR "%s: failed to register device!\n", __func__); + return ret; + } + + pinfo.xres = 176; + pinfo.yres = 220; + pinfo.type = MDDI_PANEL; + pinfo.pdest = DISPLAY_2; + pinfo.mddi.vdopkt = 0x400; + pinfo.wait_cycle = 0; + pinfo.bpp = 18; + pinfo.clk_rate = 122880000; + pinfo.clk_min = 120000000; + pinfo.clk_max = 200000000; + pinfo.fb_num = 2; + + ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_SECD, panel); + if (ret) + printk(KERN_WARNING + "%s: failed to register device!\n", __func__); + + return ret; +} + +module_init(mddi_toshiba_vga_init); diff --git a/drivers/staging/msm/mddi_toshiba_wvga.c b/drivers/staging/msm/mddi_toshiba_wvga.c new file mode 100644 index 000000000000..557b0f08faf8 --- /dev/null +++ b/drivers/staging/msm/mddi_toshiba_wvga.c @@ -0,0 +1,63 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" +#include "mddihost.h" +#include "mddi_toshiba.h" + +static int __init mddi_toshiba_wvga_init(void) +{ + int ret; + struct msm_panel_info pinfo; + +#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT + if (msm_fb_detect_client("mddi_toshiba_wvga")) + return 0; +#endif + + pinfo.xres = 800; + pinfo.yres = 480; + pinfo.pdest = DISPLAY_2; + pinfo.type = MDDI_PANEL; + pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR; + pinfo.wait_cycle = 0; + pinfo.bpp = 18; + pinfo.lcd.vsync_enable = TRUE; + pinfo.lcd.refx100 = 6118; + pinfo.lcd.v_back_porch = 6; + pinfo.lcd.v_front_porch = 0; + pinfo.lcd.v_pulse_width = 0; + pinfo.lcd.hw_vsync_mode = FALSE; + pinfo.lcd.vsync_notifier_period = (1 * HZ); + pinfo.bl_max = 4; + pinfo.bl_min = 1; + pinfo.clk_rate = 192000000; + pinfo.clk_min = 190000000; + pinfo.clk_max = 200000000; + pinfo.fb_num = 2; + + ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM, + LCD_TOSHIBA_2P4_WVGA); + if (ret) { + printk(KERN_ERR "%s: failed to register device!\n", __func__); + return ret; + } + + return ret; +} + +module_init(mddi_toshiba_wvga_init); diff --git a/drivers/staging/msm/mddi_toshiba_wvga_pt.c b/drivers/staging/msm/mddi_toshiba_wvga_pt.c new file mode 100644 index 000000000000..fc7d4e0d294f --- /dev/null +++ b/drivers/staging/msm/mddi_toshiba_wvga_pt.c @@ -0,0 +1,64 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "msm_fb.h" +#include "mddihost.h" +#include "mddihosti.h" +#include "mddi_toshiba.h" + +static int __init mddi_toshiba_wvga_pt_init(void) +{ + int ret; + struct msm_panel_info pinfo; +#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT + uint id; + + ret = msm_fb_detect_client("mddi_toshiba_wvga_pt"); + if (ret == -ENODEV) + return 0; + + if (ret) { + id = mddi_get_client_id(); + if (id != 0xd2638722) + return 0; + } +#endif + + pinfo.xres = 480; + pinfo.yres = 800; + pinfo.type = MDDI_PANEL; + pinfo.pdest = DISPLAY_1; + pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR; + pinfo.wait_cycle = 0; + pinfo.bpp = 18; + pinfo.lcd.vsync_enable = FALSE; + pinfo.bl_max = 15; + pinfo.bl_min = 1; + pinfo.clk_rate = 192000000; + pinfo.clk_min = 190000000; + pinfo.clk_max = 200000000; + pinfo.fb_num = 2; + + ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM, + LCD_TOSHIBA_2P4_WVGA_PT); + if (ret) + printk(KERN_ERR "%s: failed to register device!\n", __func__); + + return ret; +} + +module_init(mddi_toshiba_wvga_pt_init); diff --git a/drivers/staging/msm/mddihost.c b/drivers/staging/msm/mddihost.c new file mode 100644 index 000000000000..c6c1ee4eda05 --- /dev/null +++ b/drivers/staging/msm/mddihost.c @@ -0,0 +1,377 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/mm.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> + +#include "msm_fb.h" +#include "mddihost.h" +#include "mddihosti.h" + +#include <linux/clk.h> +#include <mach/clk.h> + +struct semaphore mddi_host_mutex; + +struct clk *mddi_io_clk; +static boolean mddi_host_powered = FALSE; +static boolean mddi_host_initialized = FALSE; +extern uint32 *mddi_reg_read_value_ptr; + +mddi_lcd_func_type mddi_lcd; + +extern mddi_client_capability_type mddi_client_capability_pkt; + +#ifdef FEATURE_MDDI_HITACHI +extern void mddi_hitachi_window_adjust(uint16 x1, + uint16 x2, uint16 y1, uint16 y2); +#endif + +extern void mddi_toshiba_lcd_init(void); + +#ifdef FEATURE_MDDI_S6D0142 +extern void mddi_s6d0142_lcd_init(void); +extern void mddi_s6d0142_window_adjust(uint16 x1, + uint16 x2, + uint16 y1, + uint16 y2, + mddi_llist_done_cb_type done_cb); +#endif + +void mddi_init(void) +{ + if (mddi_host_initialized) + return; + + mddi_host_initialized = TRUE; + + init_MUTEX(&mddi_host_mutex); + + if (!mddi_host_powered) { + down(&mddi_host_mutex); + mddi_host_init(MDDI_HOST_PRIM); + mddi_host_powered = TRUE; + up(&mddi_host_mutex); + mdelay(10); + } +} + +int mddi_host_register_read(uint32 reg_addr, + uint32 *reg_value_ptr, boolean wait, mddi_host_type host) { + mddi_linked_list_type *curr_llist_ptr; + mddi_register_access_packet_type *regacc_pkt_ptr; + uint16 curr_llist_idx; + int ret = 0; + + if (in_interrupt()) + MDDI_MSG_CRIT("Called from ISR context\n"); + + if (!mddi_host_powered) { + MDDI_MSG_ERR("MDDI powered down!\n"); + mddi_init(); + } + + down(&mddi_host_mutex); + + mddi_reg_read_value_ptr = reg_value_ptr; + curr_llist_idx = mddi_get_reg_read_llist_item(host, TRUE); + if (curr_llist_idx == UNASSIGNED_INDEX) { + up(&mddi_host_mutex); + + /* need to change this to some sort of wait */ + MDDI_MSG_ERR("Attempting to queue up more than 1 reg read\n"); + return -EINVAL; + } + + curr_llist_ptr = &llist_extern[host][curr_llist_idx]; + curr_llist_ptr->link_controller_flags = 0x11; + curr_llist_ptr->packet_header_count = 14; + curr_llist_ptr->packet_data_count = 0; + + curr_llist_ptr->next_packet_pointer = NULL; + curr_llist_ptr->packet_data_pointer = NULL; + curr_llist_ptr->reserved = 0; + + regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt; + + regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count; + regacc_pkt_ptr->packet_type = 146; /* register access packet */ + regacc_pkt_ptr->bClient_ID = 0; + regacc_pkt_ptr->read_write_info = 0x8001; + regacc_pkt_ptr->register_address = reg_addr; + + /* now adjust pointers */ + mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait, + NULL, host); + /* need to check if we can write the pointer or not */ + + up(&mddi_host_mutex); + + if (wait) { + int wait_ret; + + mddi_linked_list_notify_type *llist_notify_ptr; + llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx]; + wait_ret = wait_for_completion_timeout( + &(llist_notify_ptr->done_comp), 5 * HZ); + + if (wait_ret <= 0) + ret = -EBUSY; + + if (wait_ret < 0) + printk(KERN_ERR "%s: failed to wait for completion!\n", + __func__); + else if (!wait_ret) + printk(KERN_ERR "%s: Timed out waiting!\n", __func__); + } + + MDDI_MSG_DEBUG("Reg Read value=0x%x\n", *reg_value_ptr); + + return ret; +} /* mddi_host_register_read */ + +int mddi_host_register_write(uint32 reg_addr, + uint32 reg_val, enum mddi_data_packet_size_type packet_size, + boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host) { + mddi_linked_list_type *curr_llist_ptr; + mddi_linked_list_type *curr_llist_dma_ptr; + mddi_register_access_packet_type *regacc_pkt_ptr; + uint16 curr_llist_idx; + int ret = 0; + + if (in_interrupt()) + MDDI_MSG_CRIT("Called from ISR context\n"); + + if (!mddi_host_powered) { + MDDI_MSG_ERR("MDDI powered down!\n"); + mddi_init(); + } + + down(&mddi_host_mutex); + + curr_llist_idx = mddi_get_next_free_llist_item(host, TRUE); + curr_llist_ptr = &llist_extern[host][curr_llist_idx]; + curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx]; + + curr_llist_ptr->link_controller_flags = 1; + curr_llist_ptr->packet_header_count = 14; + curr_llist_ptr->packet_data_count = 4; + + curr_llist_ptr->next_packet_pointer = NULL; + curr_llist_ptr->reserved = 0; + + regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt; + + regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count + + (uint16)packet_size; + regacc_pkt_ptr->packet_type = 146; /* register access packet */ + regacc_pkt_ptr->bClient_ID = 0; + regacc_pkt_ptr->read_write_info = 0x0001; + regacc_pkt_ptr->register_address = reg_addr; + regacc_pkt_ptr->register_data_list = reg_val; + + MDDI_MSG_DEBUG("Reg Access write reg=0x%x, value=0x%x\n", + regacc_pkt_ptr->register_address, + regacc_pkt_ptr->register_data_list); + + regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt; + curr_llist_ptr->packet_data_pointer = + (void *)(®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); +} diff --git a/drivers/staging/msm/mddihost.h b/drivers/staging/msm/mddihost.h new file mode 100644 index 000000000000..20b817841c4a --- /dev/null +++ b/drivers/staging/msm/mddihost.h @@ -0,0 +1,225 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MDDIHOST_H +#define MDDIHOST_H + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include "linux/proc_fs.h" +#include <linux/types.h> +#include <linux/dma-mapping.h> +#include <linux/clk.h> + +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/types.h> +#include <linux/dma-mapping.h> + +#include "msm_fb_panel.h" + +#undef FEATURE_MDDI_MC4 +#undef FEATURE_MDDI_S6D0142 +#undef FEATURE_MDDI_HITACHI +#define FEATURE_MDDI_SHARP +#define FEATURE_MDDI_TOSHIBA +#undef FEATURE_MDDI_E751 +#define FEATURE_MDDI_CORONA +#define FEATURE_MDDI_PRISM + +#define T_MSM7500 + +typedef enum { + format_16bpp, + format_18bpp, + format_24bpp +} mddi_video_format; + +typedef enum { + MDDI_LCD_NONE = 0, + MDDI_LCD_MC4, + MDDI_LCD_S6D0142, + MDDI_LCD_SHARP, + MDDI_LCD_E751, + MDDI_LCD_CORONA, + MDDI_LCD_HITACHI, + MDDI_LCD_TOSHIBA, + MDDI_LCD_PRISM, + MDDI_LCD_TP2, + MDDI_NUM_LCD_TYPES, + MDDI_LCD_DEFAULT = MDDI_LCD_TOSHIBA +} mddi_lcd_type; + +typedef enum { + MDDI_HOST_PRIM = 0, + MDDI_HOST_EXT, + MDDI_NUM_HOST_CORES +} mddi_host_type; + +typedef enum { + MDDI_DRIVER_RESET, /* host core registers have not been written. */ + MDDI_DRIVER_DISABLED, /* registers written, interrupts disabled. */ + MDDI_DRIVER_ENABLED /* registers written, interrupts enabled. */ +} mddi_host_driver_state_type; + +typedef enum { + MDDI_GPIO_INT_0 = 0, + MDDI_GPIO_INT_1, + MDDI_GPIO_INT_2, + MDDI_GPIO_INT_3, + MDDI_GPIO_INT_4, + MDDI_GPIO_INT_5, + MDDI_GPIO_INT_6, + MDDI_GPIO_INT_7, + MDDI_GPIO_INT_8, + MDDI_GPIO_INT_9, + MDDI_GPIO_INT_10, + MDDI_GPIO_INT_11, + MDDI_GPIO_INT_12, + MDDI_GPIO_INT_13, + MDDI_GPIO_INT_14, + MDDI_GPIO_INT_15, + MDDI_GPIO_NUM_INTS +} mddi_gpio_int_type; + +enum mddi_data_packet_size_type { + MDDI_DATA_PACKET_4_BYTES = 4, + MDDI_DATA_PACKET_8_BYTES = 8, + MDDI_DATA_PACKET_12_BYTES = 12, + MDDI_DATA_PACKET_16_BYTES = 16, + MDDI_DATA_PACKET_24_BYTES = 24 +}; + +typedef struct { + uint32 addr; + uint32 value; +} mddi_reg_write_type; + +boolean mddi_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg); + +typedef void (*mddi_llist_done_cb_type) (void); + +typedef void (*mddi_rev_handler_type) (void *); + +boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type); + +#define MDDI_DEFAULT_PRIM_PIX_ATTR 0xC3 +#define MDDI_DEFAULT_SECD_PIX_ATTR 0xC0 + +typedef int gpio_int_polarity_type; +typedef int gpio_int_handler_type; + +typedef struct { + void (*vsync_detected) (boolean); +} mddi_lcd_func_type; + +extern mddi_lcd_func_type mddi_lcd; +void mddi_init(void); + +void mddi_powerdown(void); + +void mddi_host_start_ext_display(void); +void mddi_host_stop_ext_display(void); + +extern spinlock_t mddi_host_spin_lock; +#ifdef T_MSM7500 +void mddi_reset(void); +#ifdef FEATURE_DUAL_PROC_MODEM_DISPLAY +void mddi_host_switch_proc_control(boolean on); +#endif +#endif +void mddi_host_exit_power_collapse(void); + +void mddi_queue_splash_screen + (void *buf_ptr, + boolean clear_area, + int16 src_width, + int16 src_starting_row, + int16 src_starting_column, + int16 num_of_rows, + int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column); + +void mddi_queue_image + (void *buf_ptr, + uint8 stereo_video, + boolean clear_area, + int16 src_width, + int16 src_starting_row, + int16 src_starting_column, + int16 num_of_rows, + int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column); + +int mddi_host_register_read + (uint32 reg_addr, + uint32 *reg_value_ptr, boolean wait, mddi_host_type host_idx); +int mddi_host_register_write + (uint32 reg_addr, uint32 reg_val, + enum mddi_data_packet_size_type packet_size, + boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host); +boolean mddi_host_register_write_int + (uint32 reg_addr, + uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host); +boolean mddi_host_register_read_int + (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host_idx); +void mddi_queue_register_write_static + (uint32 reg_addr, + uint32 reg_val, boolean wait, mddi_llist_done_cb_type done_cb); +void mddi_queue_static_window_adjust + (const mddi_reg_write_type *reg_write, + uint16 num_writes, mddi_llist_done_cb_type done_cb); + +#define mddi_queue_register_read(reg, val_ptr, wait, sig) \ + mddi_host_register_read(reg, val_ptr, wait, MDDI_HOST_PRIM) +#define mddi_queue_register_write(reg, val, wait, sig) \ + mddi_host_register_write(reg, val, MDDI_DATA_PACKET_4_BYTES,\ + wait, NULL, MDDI_HOST_PRIM) +#define mddi_queue_register_write_extn(reg, val, pkt_size, wait, sig) \ + mddi_host_register_write(reg, val, pkt_size, \ + wait, NULL, MDDI_HOST_PRIM) +#define mddi_queue_register_write_int(reg, val) \ + mddi_host_register_write_int(reg, val, NULL, MDDI_HOST_PRIM) +#define mddi_queue_register_read_int(reg, val_ptr) \ + mddi_host_register_read_int(reg, val_ptr, MDDI_HOST_PRIM) +#define mddi_queue_register_writes(reg_ptr, val, wait, sig) \ + mddi_host_register_writes(reg_ptr, val, wait, sig, MDDI_HOST_PRIM) + +void mddi_wait(uint16 time_ms); +void mddi_assign_max_pkt_dimensions(uint16 image_cols, + uint16 image_rows, + uint16 bpp, + uint16 *max_cols, uint16 * max_rows); +uint16 mddi_assign_pkt_height(uint16 pkt_width, uint16 pkt_height, uint16 bpp); +void mddi_queue_reverse_encapsulation(boolean wait); +void mddi_disable(int lock); +#endif /* MDDIHOST_H */ diff --git a/drivers/staging/msm/mddihost_e.c b/drivers/staging/msm/mddihost_e.c new file mode 100644 index 000000000000..7de5eda71ce3 --- /dev/null +++ b/drivers/staging/msm/mddihost_e.c @@ -0,0 +1,63 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/mm.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> + +#include "msm_fb.h" +#include "mddihost.h" +#include "mddihosti.h" + +#include <linux/clk.h> +#include <mach/clk.h> + +extern struct semaphore mddi_host_mutex; +static boolean mddi_host_ext_powered = FALSE; + +void mddi_host_start_ext_display(void) +{ + down(&mddi_host_mutex); + + if (!mddi_host_ext_powered) { + mddi_host_init(MDDI_HOST_EXT); + + mddi_host_ext_powered = TRUE; + } + + up(&mddi_host_mutex); +} + +void mddi_host_stop_ext_display(void) +{ + down(&mddi_host_mutex); + + if (mddi_host_ext_powered) { + mddi_host_powerdown(MDDI_HOST_EXT); + + mddi_host_ext_powered = FALSE; + } + + up(&mddi_host_mutex); +} diff --git a/drivers/staging/msm/mddihosti.c b/drivers/staging/msm/mddihosti.c new file mode 100644 index 000000000000..f9d6e91e8d5d --- /dev/null +++ b/drivers/staging/msm/mddihosti.c @@ -0,0 +1,2239 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/mm.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> + +#include "msm_fb_panel.h" +#include "mddihost.h" +#include "mddihosti.h" + +#define FEATURE_MDDI_UNDERRUN_RECOVERY +#ifndef FEATURE_MDDI_DISABLE_REVERSE +static void mddi_read_rev_packet(byte *data_ptr); +#endif + +struct timer_list mddi_host_timer; + +#define MDDI_DEFAULT_TIMER_LENGTH 5000 /* 5 seconds */ +uint32 mddi_rtd_frequency = 60000; /* send RTD every 60 seconds */ +uint32 mddi_client_status_frequency = 60000; /* get status pkt every 60 secs */ + +boolean mddi_vsync_detect_enabled = FALSE; +mddi_gpio_info_type mddi_gpio; + +uint32 mddi_host_core_version; +boolean mddi_debug_log_statistics = FALSE; +/* #define FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION */ +/* default to TRUE in case MDP does not vote */ +static boolean mddi_host_mdp_active_flag = TRUE; +static uint32 mddi_log_stats_counter; +uint32 mddi_log_stats_frequency = 4000; + +#define MDDI_DEFAULT_REV_PKT_SIZE 0x20 + +#ifndef FEATURE_MDDI_DISABLE_REVERSE +static boolean mddi_rev_ptr_workaround = TRUE; +static uint32 mddi_reg_read_retry; +static uint32 mddi_reg_read_retry_max = 20; +static boolean mddi_enable_reg_read_retry = TRUE; +static boolean mddi_enable_reg_read_retry_once = FALSE; + +#define MDDI_MAX_REV_PKT_SIZE 0x60 + +#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE 0x60 + +#define MDDI_VIDEO_REV_PKT_SIZE 0x40 +#define MDDI_REV_BUFFER_SIZE MDDI_MAX_REV_PKT_SIZE +static byte rev_packet_data[MDDI_MAX_REV_PKT_SIZE]; +#endif /* FEATURE_MDDI_DISABLE_REVERSE */ +/* leave these variables so graphics will compile */ + +#define MDDI_MAX_REV_DATA_SIZE 128 +/*lint -d__align(x) */ +boolean mddi_debug_clear_rev_data = TRUE; + +uint32 *mddi_reg_read_value_ptr; + +mddi_client_capability_type mddi_client_capability_pkt; +static boolean mddi_client_capability_request = FALSE; + +#ifndef FEATURE_MDDI_DISABLE_REVERSE + +#define MAX_MDDI_REV_HANDLERS 2 +#define INVALID_PKT_TYPE 0xFFFF + +typedef struct { + mddi_rev_handler_type handler; /* ISR to be executed */ + uint16 pkt_type; +} mddi_rev_pkt_handler_type; +static mddi_rev_pkt_handler_type mddi_rev_pkt_handler[MAX_MDDI_REV_HANDLERS] = + { {NULL, INVALID_PKT_TYPE}, {NULL, INVALID_PKT_TYPE} }; + +static boolean mddi_rev_encap_user_request = FALSE; +static mddi_linked_list_notify_type mddi_rev_user; + +spinlock_t mddi_host_spin_lock; +extern uint32 mdp_in_processing; +#endif + +typedef enum { + MDDI_REV_IDLE +#ifndef FEATURE_MDDI_DISABLE_REVERSE + , MDDI_REV_REG_READ_ISSUED, + MDDI_REV_REG_READ_SENT, + MDDI_REV_ENCAP_ISSUED, + MDDI_REV_STATUS_REQ_ISSUED, + MDDI_REV_CLIENT_CAP_ISSUED +#endif +} mddi_rev_link_state_type; + +typedef enum { + MDDI_LINK_DISABLED, + MDDI_LINK_HIBERNATING, + MDDI_LINK_ACTIVATING, + MDDI_LINK_ACTIVE +} mddi_host_link_state_type; + +typedef struct { + uint32 count; + uint32 in_count; + uint32 disp_req_count; + uint32 state_change_count; + uint32 ll_done_count; + uint32 rev_avail_count; + uint32 error_count; + uint32 rev_encap_count; + uint32 llist_ptr_write_1; + uint32 llist_ptr_write_2; +} mddi_host_int_type; + +typedef struct { + uint32 fwd_crc_count; + uint32 rev_crc_count; + uint32 pri_underflow; + uint32 sec_underflow; + uint32 rev_overflow; + uint32 pri_overwrite; + uint32 sec_overwrite; + uint32 rev_overwrite; + uint32 dma_failure; + uint32 rtd_failure; + uint32 reg_read_failure; +#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY + uint32 pri_underrun_detected; +#endif +} mddi_host_stat_type; + +typedef struct { + uint32 rtd_cnt; + uint32 rev_enc_cnt; + uint32 vid_cnt; + uint32 reg_acc_cnt; + uint32 cli_stat_cnt; + uint32 cli_cap_cnt; + uint32 reg_read_cnt; + uint32 link_active_cnt; + uint32 link_hibernate_cnt; + uint32 vsync_response_cnt; + uint32 fwd_crc_cnt; + uint32 rev_crc_cnt; +} mddi_log_params_struct_type; + +typedef struct { + uint32 rtd_value; + uint32 rtd_counter; + uint32 client_status_cnt; + boolean rev_ptr_written; + uint8 *rev_ptr_start; + uint8 *rev_ptr_curr; + uint32 mddi_rev_ptr_write_val; + dma_addr_t rev_data_dma_addr; + uint16 rev_pkt_size; + mddi_rev_link_state_type rev_state; + mddi_host_link_state_type link_state; + mddi_host_driver_state_type driver_state; + boolean disable_hibernation; + uint32 saved_int_reg; + uint32 saved_int_en; + mddi_linked_list_type *llist_ptr; + dma_addr_t llist_dma_addr; + mddi_linked_list_type *llist_dma_ptr; + uint32 *rev_data_buf; + struct completion mddi_llist_avail_comp; + boolean mddi_waiting_for_llist_avail; + mddi_host_int_type int_type; + mddi_host_stat_type stats; + mddi_log_params_struct_type log_parms; + mddi_llist_info_type llist_info; + mddi_linked_list_notify_type llist_notify[MDDI_MAX_NUM_LLIST_ITEMS]; +} mddi_host_cntl_type; + +static mddi_host_type mddi_curr_host = MDDI_HOST_PRIM; +static mddi_host_cntl_type mhctl[MDDI_NUM_HOST_CORES]; +mddi_linked_list_type *llist_extern[MDDI_NUM_HOST_CORES]; +mddi_linked_list_type *llist_dma_extern[MDDI_NUM_HOST_CORES]; +mddi_linked_list_notify_type *llist_extern_notify[MDDI_NUM_HOST_CORES]; +static mddi_log_params_struct_type prev_parms[MDDI_NUM_HOST_CORES]; + +extern uint32 mdp_total_vdopkts; + +static boolean mddi_host_io_clock_on = FALSE; +static boolean mddi_host_hclk_on = FALSE; + +int int_mddi_pri_flag = FALSE; +int int_mddi_ext_flag = FALSE; + +static void mddi_report_errors(uint32 int_reg) +{ + mddi_host_type host_idx = mddi_curr_host; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + if (int_reg & MDDI_INT_PRI_UNDERFLOW) { + pmhctl->stats.pri_underflow++; + MDDI_MSG_ERR("!!! MDDI Primary Underflow !!!\n"); + } + if (int_reg & MDDI_INT_SEC_UNDERFLOW) { + pmhctl->stats.sec_underflow++; + MDDI_MSG_ERR("!!! MDDI Secondary Underflow !!!\n"); + } +#ifndef FEATURE_MDDI_DISABLE_REVERSE + if (int_reg & MDDI_INT_REV_OVERFLOW) { + pmhctl->stats.rev_overflow++; + MDDI_MSG_ERR("!!! MDDI Reverse Overflow !!!\n"); + pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; + mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val); + + } + if (int_reg & MDDI_INT_CRC_ERROR) + MDDI_MSG_ERR("!!! MDDI Reverse CRC Error !!!\n"); +#endif + if (int_reg & MDDI_INT_PRI_OVERWRITE) { + pmhctl->stats.pri_overwrite++; + MDDI_MSG_ERR("!!! MDDI Primary Overwrite !!!\n"); + } + if (int_reg & MDDI_INT_SEC_OVERWRITE) { + pmhctl->stats.sec_overwrite++; + MDDI_MSG_ERR("!!! MDDI Secondary Overwrite !!!\n"); + } +#ifndef FEATURE_MDDI_DISABLE_REVERSE + if (int_reg & MDDI_INT_REV_OVERWRITE) { + pmhctl->stats.rev_overwrite++; + /* This will show up normally and is not a problem */ + MDDI_MSG_DEBUG("MDDI Reverse Overwrite!\n"); + } + if (int_reg & MDDI_INT_RTD_FAILURE) { + mddi_host_reg_outm(INTEN, MDDI_INT_RTD_FAILURE, 0); + pmhctl->stats.rtd_failure++; + MDDI_MSG_ERR("!!! MDDI RTD Failure !!!\n"); + } +#endif + if (int_reg & MDDI_INT_DMA_FAILURE) { + pmhctl->stats.dma_failure++; + MDDI_MSG_ERR("!!! MDDI DMA Abort !!!\n"); + } +} + +static void mddi_host_enable_io_clock(void) +{ + if (!MDDI_HOST_IS_IO_CLOCK_ON) + MDDI_HOST_ENABLE_IO_CLOCK; +} + +static void mddi_host_enable_hclk(void) +{ + + if (!MDDI_HOST_IS_HCLK_ON) + MDDI_HOST_ENABLE_HCLK; +} + +static void mddi_host_disable_io_clock(void) +{ +#ifndef FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE + if (MDDI_HOST_IS_IO_CLOCK_ON) + MDDI_HOST_DISABLE_IO_CLOCK; +#endif +} + +static void mddi_host_disable_hclk(void) +{ +#ifndef FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE + if (MDDI_HOST_IS_HCLK_ON) + MDDI_HOST_DISABLE_HCLK; +#endif +} + +static void mddi_vote_to_sleep(mddi_host_type host_idx, boolean sleep) +{ + uint16 vote_mask; + + if (host_idx == MDDI_HOST_PRIM) + vote_mask = 0x01; + else + vote_mask = 0x02; +} + +static void mddi_report_state_change(uint32 int_reg) +{ + mddi_host_type host_idx = mddi_curr_host; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + if ((pmhctl->saved_int_reg & MDDI_INT_IN_HIBERNATION) && + (pmhctl->saved_int_reg & MDDI_INT_LINK_ACTIVE)) { + /* recover from condition where the io_clock was turned off by the + clock driver during a transition to hibernation. The io_clock + disable is to prevent MDP/MDDI underruns when changing ARM + clock speeds. In the process of halting the ARM, the hclk + divider needs to be set to 1. When it is set to 1, there is + a small time (usecs) when hclk is off or slow, and this can + cause an underrun. To prevent the underrun, clock driver turns + off the MDDI io_clock before making the change. */ + mddi_host_reg_out(CMD, MDDI_CMD_POWERUP); + } + + if (int_reg & MDDI_INT_LINK_ACTIVE) { + pmhctl->link_state = MDDI_LINK_ACTIVE; + pmhctl->log_parms.link_active_cnt++; + pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL); + MDDI_MSG_DEBUG("!!! MDDI Active RTD:0x%x!!!\n", + pmhctl->rtd_value); + /* now interrupt on hibernation */ + mddi_host_reg_outm(INTEN, + (MDDI_INT_IN_HIBERNATION | + MDDI_INT_LINK_ACTIVE), + MDDI_INT_IN_HIBERNATION); + +#ifdef DEBUG_MDDIHOSTI + /* if gpio interrupt is enabled, start polling at fastest + * registered rate + */ + if (mddi_gpio.polling_enabled) { + timer_reg(&mddi_gpio_poll_timer, + mddi_gpio_poll_timer_cb, 0, mddi_gpio.polling_interval, 0); + } +#endif +#ifndef FEATURE_MDDI_DISABLE_REVERSE + if (mddi_rev_ptr_workaround) { + /* HW CR: need to reset reverse register stuff */ + pmhctl->rev_ptr_written = FALSE; + pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; + } +#endif + /* vote on sleep */ + mddi_vote_to_sleep(host_idx, FALSE); + + if (host_idx == MDDI_HOST_PRIM) { + if (mddi_vsync_detect_enabled) { + /* + * Indicate to client specific code that vsync + * was enabled, but we did not detect a client + * intiated wakeup. The client specific + * handler can either reassert vsync detection, + * or treat this as a valid vsync. + */ + mddi_client_lcd_vsync_detected(FALSE); + pmhctl->log_parms.vsync_response_cnt++; + } + } + } + if (int_reg & MDDI_INT_IN_HIBERNATION) { + pmhctl->link_state = MDDI_LINK_HIBERNATING; + pmhctl->log_parms.link_hibernate_cnt++; + MDDI_MSG_DEBUG("!!! MDDI Hibernating !!!\n"); + /* now interrupt on link_active */ +#ifdef FEATURE_MDDI_DISABLE_REVERSE + mddi_host_reg_outm(INTEN, + (MDDI_INT_MDDI_IN | + MDDI_INT_IN_HIBERNATION | + MDDI_INT_LINK_ACTIVE), + MDDI_INT_LINK_ACTIVE); +#else + mddi_host_reg_outm(INTEN, + (MDDI_INT_MDDI_IN | + MDDI_INT_IN_HIBERNATION | + MDDI_INT_LINK_ACTIVE), + (MDDI_INT_MDDI_IN | MDDI_INT_LINK_ACTIVE)); + + pmhctl->rtd_counter = mddi_rtd_frequency; + + if (pmhctl->rev_state != MDDI_REV_IDLE) { + /* a rev_encap will not wake up the link, so we do that here */ + pmhctl->link_state = MDDI_LINK_ACTIVATING; + mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); + } +#endif + + if (pmhctl->disable_hibernation) { + mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE); + mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); + pmhctl->link_state = MDDI_LINK_ACTIVATING; + } +#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY + if ((pmhctl->llist_info.transmitting_start_idx != + UNASSIGNED_INDEX) + && + ((pmhctl-> + saved_int_reg & (MDDI_INT_PRI_LINK_LIST_DONE | + MDDI_INT_PRI_PTR_READ)) == + MDDI_INT_PRI_PTR_READ)) { + mddi_linked_list_type *llist_dma; + llist_dma = pmhctl->llist_dma_ptr; + /* + * All indications are that we have not received a + * linked list done interrupt, due to an underrun + * condition. Recovery attempt is to send again. + */ + dma_coherent_pre_ops(); + /* Write to primary pointer register again */ + mddi_host_reg_out(PRI_PTR, + &llist_dma[pmhctl->llist_info. + transmitting_start_idx]); + pmhctl->stats.pri_underrun_detected++; + } +#endif + + /* vote on sleep */ + if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { + mddi_vote_to_sleep(host_idx, TRUE); + } + +#ifdef DEBUG_MDDIHOSTI + /* need to stop polling timer */ + if (mddi_gpio.polling_enabled) { + (void) timer_clr(&mddi_gpio_poll_timer, T_NONE); + } +#endif + } +} + +void mddi_host_timer_service(unsigned long data) +{ +#ifndef FEATURE_MDDI_DISABLE_REVERSE + unsigned long flags; +#endif + mddi_host_type host_idx; + mddi_host_cntl_type *pmhctl; + + unsigned long time_ms = MDDI_DEFAULT_TIMER_LENGTH; + init_timer(&mddi_host_timer); + mddi_host_timer.function = mddi_host_timer_service; + mddi_host_timer.data = 0; + + mddi_host_timer.expires = jiffies + ((time_ms * HZ) / 1000); + add_timer(&mddi_host_timer); + + for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES; + host_idx++) { + pmhctl = &(mhctl[host_idx]); + mddi_log_stats_counter += (uint32) time_ms; +#ifndef FEATURE_MDDI_DISABLE_REVERSE + pmhctl->rtd_counter += (uint32) time_ms; + pmhctl->client_status_cnt += (uint32) time_ms; + + if (host_idx == MDDI_HOST_PRIM) { + if (pmhctl->client_status_cnt >= + mddi_client_status_frequency) { + if ((pmhctl->link_state == + MDDI_LINK_HIBERNATING) + && (pmhctl->client_status_cnt > + mddi_client_status_frequency)) { + /* + * special case where we are hibernating + * and mddi_host_isr is not firing, so + * kick the link so that the status can + * be retrieved + */ + + /* need to wake up link before issuing + * rev encap command + */ + MDDI_MSG_INFO("wake up link!\n"); + spin_lock_irqsave(&mddi_host_spin_lock, + flags); + mddi_host_enable_hclk(); + mddi_host_enable_io_clock(); + pmhctl->link_state = + MDDI_LINK_ACTIVATING; + mddi_host_reg_out(CMD, + MDDI_CMD_LINK_ACTIVE); + spin_unlock_irqrestore + (&mddi_host_spin_lock, flags); + } else + if ((pmhctl->link_state == MDDI_LINK_ACTIVE) + && pmhctl->disable_hibernation) { + /* + * special case where we have disabled + * hibernation and mddi_host_isr + * is not firing, so enable interrupt + * for no pkts pending, which will + * generate an interrupt + */ + MDDI_MSG_INFO("kick isr!\n"); + spin_lock_irqsave(&mddi_host_spin_lock, + flags); + mddi_host_enable_hclk(); + mddi_host_reg_outm(INTEN, + MDDI_INT_NO_CMD_PKTS_PEND, + MDDI_INT_NO_CMD_PKTS_PEND); + spin_unlock_irqrestore + (&mddi_host_spin_lock, flags); + } + } + } +#endif /* #ifndef FEATURE_MDDI_DISABLE_REVERSE */ + } + + /* Check if logging is turned on */ + for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES; + host_idx++) { + mddi_log_params_struct_type *prev_ptr = &(prev_parms[host_idx]); + pmhctl = &(mhctl[host_idx]); + + if (mddi_debug_log_statistics) { + + /* get video pkt count from MDP, since MDDI sw cannot know this */ + pmhctl->log_parms.vid_cnt = mdp_total_vdopkts; + + if (mddi_log_stats_counter >= mddi_log_stats_frequency) { + /* mddi_log_stats_counter = 0; */ + if (mddi_debug_log_statistics) { + MDDI_MSG_NOTICE + ("MDDI Statistics since last report:\n"); + MDDI_MSG_NOTICE(" Packets sent:\n"); + MDDI_MSG_NOTICE + (" %d RTD packet(s)\n", + pmhctl->log_parms.rtd_cnt - + prev_ptr->rtd_cnt); + if (prev_ptr->rtd_cnt != + pmhctl->log_parms.rtd_cnt) { + unsigned long flags; + spin_lock_irqsave + (&mddi_host_spin_lock, + flags); + mddi_host_enable_hclk(); + pmhctl->rtd_value = + mddi_host_reg_in(RTD_VAL); + spin_unlock_irqrestore + (&mddi_host_spin_lock, + flags); + MDDI_MSG_NOTICE + (" RTD value=%d\n", + pmhctl->rtd_value); + } + MDDI_MSG_NOTICE + (" %d VIDEO packets\n", + pmhctl->log_parms.vid_cnt - + prev_ptr->vid_cnt); + MDDI_MSG_NOTICE + (" %d Register Access packets\n", + pmhctl->log_parms.reg_acc_cnt - + prev_ptr->reg_acc_cnt); + MDDI_MSG_NOTICE + (" %d Reverse Encapsulation packet(s)\n", + pmhctl->log_parms.rev_enc_cnt - + prev_ptr->rev_enc_cnt); + if (prev_ptr->rev_enc_cnt != + pmhctl->log_parms.rev_enc_cnt) { + /* report # of reverse CRC errors */ + MDDI_MSG_NOTICE + (" %d reverse CRC errors detected\n", + pmhctl->log_parms. + rev_crc_cnt - + prev_ptr->rev_crc_cnt); + } + MDDI_MSG_NOTICE + (" Packets received:\n"); + MDDI_MSG_NOTICE + (" %d Client Status packets", + pmhctl->log_parms.cli_stat_cnt - + prev_ptr->cli_stat_cnt); + if (prev_ptr->cli_stat_cnt != + pmhctl->log_parms.cli_stat_cnt) { + MDDI_MSG_NOTICE + (" %d forward CRC errors reported\n", + pmhctl->log_parms. + fwd_crc_cnt - + prev_ptr->fwd_crc_cnt); + } + MDDI_MSG_NOTICE + (" %d Register Access Read packets\n", + pmhctl->log_parms.reg_read_cnt - + prev_ptr->reg_read_cnt); + + if (pmhctl->link_state == + MDDI_LINK_ACTIVE) { + MDDI_MSG_NOTICE + (" Current Link Status: Active\n"); + } else + if ((pmhctl->link_state == + MDDI_LINK_HIBERNATING) + || (pmhctl->link_state == + MDDI_LINK_ACTIVATING)) { + MDDI_MSG_NOTICE + (" Current Link Status: Hibernation\n"); + } else { + MDDI_MSG_NOTICE + (" Current Link Status: Inactive\n"); + } + MDDI_MSG_NOTICE + (" Active state entered %d times\n", + pmhctl->log_parms.link_active_cnt - + prev_ptr->link_active_cnt); + MDDI_MSG_NOTICE + (" Hibernation state entered %d times\n", + pmhctl->log_parms. + link_hibernate_cnt - + prev_ptr->link_hibernate_cnt); + } + } + prev_parms[host_idx] = pmhctl->log_parms; + } + } + if (mddi_log_stats_counter >= mddi_log_stats_frequency) + mddi_log_stats_counter = 0; + + return; +} /* mddi_host_timer_cb */ + +static void mddi_process_link_list_done(void) +{ + mddi_host_type host_idx = mddi_curr_host; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + /* normal forward linked list packet(s) were sent */ + if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) { + MDDI_MSG_ERR("**** getting LL done, but no list ****\n"); + } else { + uint16 idx; + +#ifndef FEATURE_MDDI_DISABLE_REVERSE + if (pmhctl->rev_state == MDDI_REV_REG_READ_ISSUED) { + /* special case where a register read packet was sent */ + pmhctl->rev_state = MDDI_REV_REG_READ_SENT; + if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) { + MDDI_MSG_ERR + ("**** getting LL done, but no list ****\n"); + } + } +#endif + for (idx = pmhctl->llist_info.transmitting_start_idx;;) { + uint16 next_idx = pmhctl->llist_notify[idx].next_idx; + /* with reg read we don't release the waiting tcb until after + * the reverse encapsulation has completed. + */ + if (idx != pmhctl->llist_info.reg_read_idx) { + /* notify task that may be waiting on this completion */ + if (pmhctl->llist_notify[idx].waiting) { + complete(& + (pmhctl->llist_notify[idx]. + done_comp)); + } + if (pmhctl->llist_notify[idx].done_cb != NULL) { + (*(pmhctl->llist_notify[idx].done_cb)) + (); + } + + pmhctl->llist_notify[idx].in_use = FALSE; + pmhctl->llist_notify[idx].waiting = FALSE; + pmhctl->llist_notify[idx].done_cb = NULL; + if (idx < MDDI_NUM_DYNAMIC_LLIST_ITEMS) { + /* static LLIST items are configured only once */ + pmhctl->llist_notify[idx].next_idx = + UNASSIGNED_INDEX; + } + /* + * currently, all linked list packets are + * register access, so we can increment the + * counter for that packet type here. + */ + pmhctl->log_parms.reg_acc_cnt++; + } + if (idx == pmhctl->llist_info.transmitting_end_idx) + break; + idx = next_idx; + if (idx == UNASSIGNED_INDEX) + MDDI_MSG_CRIT("MDDI linked list corruption!\n"); + } + + pmhctl->llist_info.transmitting_start_idx = UNASSIGNED_INDEX; + pmhctl->llist_info.transmitting_end_idx = UNASSIGNED_INDEX; + + if (pmhctl->mddi_waiting_for_llist_avail) { + if (! + (pmhctl-> + llist_notify[pmhctl->llist_info.next_free_idx]. + in_use)) { + pmhctl->mddi_waiting_for_llist_avail = FALSE; + complete(&(pmhctl->mddi_llist_avail_comp)); + } + } + } + + /* Turn off MDDI_INT_PRI_LINK_LIST_DONE interrupt */ + mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, 0); + +} + +static void mddi_queue_forward_linked_list(void) +{ + uint16 first_pkt_index; + mddi_linked_list_type *llist_dma; + mddi_host_type host_idx = mddi_curr_host; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + llist_dma = pmhctl->llist_dma_ptr; + + first_pkt_index = UNASSIGNED_INDEX; + + if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) { +#ifndef FEATURE_MDDI_DISABLE_REVERSE + if (pmhctl->llist_info.reg_read_waiting) { + if (pmhctl->rev_state == MDDI_REV_IDLE) { + /* + * we have a register read to send and + * can send it now + */ + pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED; + mddi_reg_read_retry = 0; + first_pkt_index = + pmhctl->llist_info.waiting_start_idx; + pmhctl->llist_info.reg_read_waiting = FALSE; + } + } else +#endif + { + /* + * not register read to worry about, go ahead and write + * anything that may be on the waiting list. + */ + first_pkt_index = pmhctl->llist_info.waiting_start_idx; + } + } + + if (first_pkt_index != UNASSIGNED_INDEX) { + pmhctl->llist_info.transmitting_start_idx = + pmhctl->llist_info.waiting_start_idx; + pmhctl->llist_info.transmitting_end_idx = + pmhctl->llist_info.waiting_end_idx; + pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX; + pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX; + + /* write to the primary pointer register */ + MDDI_MSG_DEBUG("MDDI writing primary ptr with idx=%d\n", + first_pkt_index); + + pmhctl->int_type.llist_ptr_write_2++; + + dma_coherent_pre_ops(); + mddi_host_reg_out(PRI_PTR, &llist_dma[first_pkt_index]); + + /* enable interrupt when complete */ + mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, + MDDI_INT_PRI_LINK_LIST_DONE); + + } + +} + +#ifndef FEATURE_MDDI_DISABLE_REVERSE +static void mddi_read_rev_packet(byte *data_ptr) +{ + uint16 i, length; + mddi_host_type host_idx = mddi_curr_host; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + uint8 *rev_ptr_overflow = + (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE); + + /* first determine the length and handle invalid lengths */ + length = *pmhctl->rev_ptr_curr++; + if (pmhctl->rev_ptr_curr >= rev_ptr_overflow) + pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; + length |= ((*pmhctl->rev_ptr_curr++) << 8); + if (pmhctl->rev_ptr_curr >= rev_ptr_overflow) + pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; + if (length > (pmhctl->rev_pkt_size - 2)) { + MDDI_MSG_ERR("Invalid rev pkt length %d\n", length); + /* rev_pkt_size should always be <= rev_ptr_size so limit to packet size */ + length = pmhctl->rev_pkt_size - 2; + } + + /* If the data pointer is NULL, just increment the pmhctl->rev_ptr_curr. + * Loop around if necessary. Don't bother reading the data. + */ + if (data_ptr == NULL) { + pmhctl->rev_ptr_curr += length; + if (pmhctl->rev_ptr_curr >= rev_ptr_overflow) + pmhctl->rev_ptr_curr -= MDDI_REV_BUFFER_SIZE; + return; + } + + data_ptr[0] = length & 0x0ff; + data_ptr[1] = length >> 8; + data_ptr += 2; + /* copy the data to data_ptr byte-at-a-time */ + for (i = 0; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow); + i++) + *data_ptr++ = *pmhctl->rev_ptr_curr++; + if (pmhctl->rev_ptr_curr >= rev_ptr_overflow) + pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; + for (; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow); i++) + *data_ptr++ = *pmhctl->rev_ptr_curr++; +} + +static void mddi_process_rev_packets(void) +{ + uint32 rev_packet_count; + word i; + uint32 crc_errors; + boolean mddi_reg_read_successful = FALSE; + mddi_host_type host_idx = mddi_curr_host; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + pmhctl->log_parms.rev_enc_cnt++; + if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) && + (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED) && + (pmhctl->rev_state != MDDI_REV_CLIENT_CAP_ISSUED)) { + MDDI_MSG_ERR("Wrong state %d for reverse int\n", + pmhctl->rev_state); + } + /* Turn off MDDI_INT_REV_AVAIL interrupt */ + mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL, 0); + + /* Clear rev data avail int */ + mddi_host_reg_out(INT, MDDI_INT_REV_DATA_AVAIL); + + /* Get Number of packets */ + rev_packet_count = mddi_host_reg_in(REV_PKT_CNT); + +#ifndef T_MSM7500 + /* Clear out rev packet counter */ + mddi_host_reg_out(REV_PKT_CNT, 0x0000); +#endif + +#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) + if ((pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) && + (rev_packet_count > 0) && + (mddi_host_core_version == 0x28 || + mddi_host_core_version == 0x30)) { + + uint32 int_reg; + uint32 max_count = 0; + + mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val); + int_reg = mddi_host_reg_in(INT); + while ((int_reg & 0x100000) == 0) { + udelay(3); + int_reg = mddi_host_reg_in(INT); + if (++max_count > 100) + break; + } + } +#endif + + /* Get CRC error count */ + crc_errors = mddi_host_reg_in(REV_CRC_ERR); + if (crc_errors != 0) { + pmhctl->log_parms.rev_crc_cnt += crc_errors; + pmhctl->stats.rev_crc_count += crc_errors; + MDDI_MSG_ERR("!!! MDDI %d Reverse CRC Error(s) !!!\n", + crc_errors); +#ifndef T_MSM7500 + /* Clear CRC error count */ + mddi_host_reg_out(REV_CRC_ERR, 0x0000); +#endif + /* also issue an RTD to attempt recovery */ + pmhctl->rtd_counter = mddi_rtd_frequency; + } + + pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL); + + MDDI_MSG_DEBUG("MDDI rev pkt cnt=%d, ptr=0x%x, RTD:0x%x\n", + rev_packet_count, + pmhctl->rev_ptr_curr - pmhctl->rev_ptr_start, + pmhctl->rtd_value); + + if (rev_packet_count >= 1) { + mddi_invalidate_cache_lines((uint32 *) pmhctl->rev_ptr_start, + MDDI_REV_BUFFER_SIZE); + } + /* order the reads */ + dma_coherent_post_ops(); + for (i = 0; i < rev_packet_count; i++) { + mddi_rev_packet_type *rev_pkt_ptr; + + mddi_read_rev_packet(rev_packet_data); + + rev_pkt_ptr = (mddi_rev_packet_type *) rev_packet_data; + + if (rev_pkt_ptr->packet_length > pmhctl->rev_pkt_size) { + MDDI_MSG_ERR("!!!invalid packet size: %d\n", + rev_pkt_ptr->packet_length); + } + + MDDI_MSG_DEBUG("MDDI rev pkt 0x%x size 0x%x\n", + rev_pkt_ptr->packet_type, + rev_pkt_ptr->packet_length); + + /* Do whatever you want to do with the data based on the packet type */ + switch (rev_pkt_ptr->packet_type) { + case 66: /* Client Capability */ + { + mddi_client_capability_type + *client_capability_pkt_ptr; + + client_capability_pkt_ptr = + (mddi_client_capability_type *) + rev_packet_data; + MDDI_MSG_NOTICE + ("Client Capability: Week=%d, Year=%d\n", + client_capability_pkt_ptr-> + Week_of_Manufacture, + client_capability_pkt_ptr-> + Year_of_Manufacture); + memcpy((void *)&mddi_client_capability_pkt, + (void *)rev_packet_data, + sizeof(mddi_client_capability_type)); + pmhctl->log_parms.cli_cap_cnt++; + } + break; + + case 70: /* Display Status */ + { + mddi_client_status_type *client_status_pkt_ptr; + + client_status_pkt_ptr = + (mddi_client_status_type *) rev_packet_data; + if ((client_status_pkt_ptr->crc_error_count != + 0) + || (client_status_pkt_ptr-> + reverse_link_request != 0)) { + MDDI_MSG_ERR + ("Client Status: RevReq=%d, CrcErr=%d\n", + client_status_pkt_ptr-> + reverse_link_request, + client_status_pkt_ptr-> + crc_error_count); + } else { + MDDI_MSG_DEBUG + ("Client Status: RevReq=%d, CrcErr=%d\n", + client_status_pkt_ptr-> + reverse_link_request, + client_status_pkt_ptr-> + crc_error_count); + } + pmhctl->log_parms.fwd_crc_cnt += + client_status_pkt_ptr->crc_error_count; + pmhctl->stats.fwd_crc_count += + client_status_pkt_ptr->crc_error_count; + pmhctl->log_parms.cli_stat_cnt++; + } + break; + + case 146: /* register access packet */ + { + mddi_register_access_packet_type + * regacc_pkt_ptr; + + regacc_pkt_ptr = + (mddi_register_access_packet_type *) + rev_packet_data; + + MDDI_MSG_DEBUG + ("Reg Acc parse reg=0x%x, value=0x%x\n", + regacc_pkt_ptr->register_address, + regacc_pkt_ptr->register_data_list); + + /* Copy register value to location passed in */ + if (mddi_reg_read_value_ptr) { +#if defined(T_MSM6280) && !defined(T_MSM7200) + /* only least significant 16 bits are valid with 6280 */ + *mddi_reg_read_value_ptr = + regacc_pkt_ptr-> + register_data_list & 0x0000ffff; +#else + *mddi_reg_read_value_ptr = + regacc_pkt_ptr->register_data_list; +#endif + mddi_reg_read_successful = TRUE; + mddi_reg_read_value_ptr = NULL; + } + +#ifdef DEBUG_MDDIHOSTI + if ((mddi_gpio.polling_enabled) && + (regacc_pkt_ptr->register_address == + mddi_gpio.polling_reg)) { + /* + * ToDo: need to call Linux GPIO call + * here... + */ + mddi_client_lcd_gpio_poll( + regacc_pkt_ptr->register_data_list); + } +#endif + pmhctl->log_parms.reg_read_cnt++; + } + break; + + default: /* any other packet */ + { + uint16 hdlr; + + for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; + hdlr++) { + if (mddi_rev_pkt_handler[hdlr]. + pkt_type == + rev_pkt_ptr->packet_type) { + (* + (mddi_rev_pkt_handler[hdlr]. + handler)) (rev_pkt_ptr); + /* pmhctl->rev_state = MDDI_REV_IDLE; */ + break; + } + } + if (hdlr >= MAX_MDDI_REV_HANDLERS) + MDDI_MSG_ERR("MDDI unknown rev pkt\n"); + } + break; + } + } + if ((pmhctl->rev_ptr_curr + pmhctl->rev_pkt_size) >= + (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE)) { + pmhctl->rev_ptr_written = FALSE; + } + + if (pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) { + pmhctl->rev_state = MDDI_REV_IDLE; + if (mddi_rev_user.waiting) { + mddi_rev_user.waiting = FALSE; + complete(&(mddi_rev_user.done_comp)); + } else if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) { + MDDI_MSG_ERR + ("Reverse Encap state, but no reg read in progress\n"); + } else { + if ((!mddi_reg_read_successful) && + (mddi_reg_read_retry < mddi_reg_read_retry_max) && + (mddi_enable_reg_read_retry)) { + /* + * There is a race condition that can happen + * where the reverse encapsulation message is + * sent out by the MDDI host before the register + * read packet is sent. As a work-around for + * that problem we issue the reverse + * encapsulation one more time before giving up. + */ + if (mddi_enable_reg_read_retry_once) + mddi_reg_read_retry = + mddi_reg_read_retry_max; + pmhctl->rev_state = MDDI_REV_REG_READ_SENT; + pmhctl->stats.reg_read_failure++; + } else { + uint16 reg_read_idx = + pmhctl->llist_info.reg_read_idx; + + mddi_reg_read_retry = 0; + if (pmhctl->llist_notify[reg_read_idx].waiting) { + complete(& + (pmhctl-> + llist_notify[reg_read_idx]. + done_comp)); + } + pmhctl->llist_info.reg_read_idx = + UNASSIGNED_INDEX; + if (pmhctl->llist_notify[reg_read_idx]. + done_cb != NULL) { + (* + (pmhctl->llist_notify[reg_read_idx]. + done_cb)) (); + } + pmhctl->llist_notify[reg_read_idx].next_idx = + UNASSIGNED_INDEX; + pmhctl->llist_notify[reg_read_idx].in_use = + FALSE; + pmhctl->llist_notify[reg_read_idx].waiting = + FALSE; + pmhctl->llist_notify[reg_read_idx].done_cb = + NULL; + if (!mddi_reg_read_successful) + pmhctl->stats.reg_read_failure++; + } + } + } else if (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) { +#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) + if (mddi_host_core_version == 0x28 || + mddi_host_core_version == 0x30) { + mddi_host_reg_out(FIFO_ALLOC, 0x00); + pmhctl->rev_ptr_written = TRUE; + mddi_host_reg_out(REV_PTR, + pmhctl->mddi_rev_ptr_write_val); + pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; + mddi_host_reg_out(CMD, 0xC00); + } +#endif + + if (mddi_rev_user.waiting) { + mddi_rev_user.waiting = FALSE; + complete(&(mddi_rev_user.done_comp)); + } + pmhctl->rev_state = MDDI_REV_IDLE; + } else { + pmhctl->rev_state = MDDI_REV_IDLE; + } + + /* pmhctl->rev_state = MDDI_REV_IDLE; */ + + /* Re-enable interrupt */ + mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL, + MDDI_INT_REV_DATA_AVAIL); + +} + +static void mddi_issue_reverse_encapsulation(void) +{ + mddi_host_type host_idx = mddi_curr_host; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + /* Only issue a reverse encapsulation packet if: + * 1) another reverse is not in progress (MDDI_REV_IDLE). + * 2) a register read has been sent (MDDI_REV_REG_READ_SENT). + * 3) forward is not in progress, because of a hw bug in client that + * causes forward crc errors on packet immediately after rev encap. + */ + if (((pmhctl->rev_state == MDDI_REV_IDLE) || + (pmhctl->rev_state == MDDI_REV_REG_READ_SENT)) && + (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) && + (!mdp_in_processing)) { + uint32 mddi_command = MDDI_CMD_SEND_REV_ENCAP; + + if ((pmhctl->rev_state == MDDI_REV_REG_READ_SENT) || + (mddi_rev_encap_user_request == TRUE)) { + mddi_host_enable_io_clock(); + if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { + /* need to wake up link before issuing rev encap command */ + MDDI_MSG_DEBUG("wake up link!\n"); + pmhctl->link_state = MDDI_LINK_ACTIVATING; + mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); + } else { + if (pmhctl->rtd_counter >= mddi_rtd_frequency) { + MDDI_MSG_DEBUG + ("mddi sending RTD command!\n"); + mddi_host_reg_out(CMD, + MDDI_CMD_SEND_RTD); + pmhctl->rtd_counter = 0; + pmhctl->log_parms.rtd_cnt++; + } + if (pmhctl->rev_state != MDDI_REV_REG_READ_SENT) { + /* this is generic reverse request by user, so + * reset the waiting flag. */ + mddi_rev_encap_user_request = FALSE; + } + /* link is active so send reverse encap to get register read results */ + pmhctl->rev_state = MDDI_REV_ENCAP_ISSUED; + mddi_command = MDDI_CMD_SEND_REV_ENCAP; + MDDI_MSG_DEBUG("sending rev encap!\n"); + } + } else + if ((pmhctl->client_status_cnt >= + mddi_client_status_frequency) + || mddi_client_capability_request) { + mddi_host_enable_io_clock(); + if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { + /* only wake up the link if it client status is overdue */ + if ((pmhctl->client_status_cnt >= + (mddi_client_status_frequency * 2)) + || mddi_client_capability_request) { + /* need to wake up link before issuing rev encap command */ + MDDI_MSG_DEBUG("wake up link!\n"); + pmhctl->link_state = + MDDI_LINK_ACTIVATING; + mddi_host_reg_out(CMD, + MDDI_CMD_LINK_ACTIVE); + } + } else { + if (pmhctl->rtd_counter >= mddi_rtd_frequency) { + MDDI_MSG_DEBUG + ("mddi sending RTD command!\n"); + mddi_host_reg_out(CMD, + MDDI_CMD_SEND_RTD); + pmhctl->rtd_counter = 0; + pmhctl->log_parms.rtd_cnt++; + } + /* periodically get client status */ + MDDI_MSG_DEBUG + ("mddi sending rev enc! (get status)\n"); + if (mddi_client_capability_request) { + pmhctl->rev_state = + MDDI_REV_CLIENT_CAP_ISSUED; + mddi_command = MDDI_CMD_GET_CLIENT_CAP; + mddi_client_capability_request = FALSE; + } else { + pmhctl->rev_state = + MDDI_REV_STATUS_REQ_ISSUED; + pmhctl->client_status_cnt = 0; + mddi_command = + MDDI_CMD_GET_CLIENT_STATUS; + } + } + } + if ((pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) || + (pmhctl->rev_state == MDDI_REV_STATUS_REQ_ISSUED) || + (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED)) { + pmhctl->int_type.rev_encap_count++; +#if defined(T_MSM6280) && !defined(T_MSM7200) + mddi_rev_pointer_written = TRUE; + mddi_host_reg_out(REV_PTR, mddi_rev_ptr_write_val); + mddi_rev_ptr_curr = mddi_rev_ptr_start; + /* force new rev ptr command */ + mddi_host_reg_out(CMD, 0xC00); +#else + if (!pmhctl->rev_ptr_written) { + MDDI_MSG_DEBUG("writing reverse pointer!\n"); + pmhctl->rev_ptr_written = TRUE; +#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) + if ((pmhctl->rev_state == + MDDI_REV_CLIENT_CAP_ISSUED) && + (mddi_host_core_version == 0x28 || + mddi_host_core_version == 0x30)) { + pmhctl->rev_ptr_written = FALSE; + mddi_host_reg_out(FIFO_ALLOC, 0x02); + } else + mddi_host_reg_out(REV_PTR, + pmhctl-> + mddi_rev_ptr_write_val); +#else + mddi_host_reg_out(REV_PTR, + pmhctl-> + mddi_rev_ptr_write_val); +#endif + } +#endif + if (mddi_debug_clear_rev_data) { + uint16 i; + for (i = 0; i < MDDI_MAX_REV_DATA_SIZE / 4; i++) + pmhctl->rev_data_buf[i] = 0xdddddddd; + /* clean cache */ + mddi_flush_cache_lines(pmhctl->rev_data_buf, + MDDI_MAX_REV_DATA_SIZE); + } + + /* send reverse encapsulation to get needed data */ + mddi_host_reg_out(CMD, mddi_command); + } + } + +} + +static void mddi_process_client_initiated_wakeup(void) +{ + mddi_host_type host_idx = mddi_curr_host; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + /* Disable MDDI_INT Interrupt, we detect client initiated wakeup one + * time for each entry into hibernation */ + mddi_host_reg_outm(INTEN, MDDI_INT_MDDI_IN, 0); + + if (host_idx == MDDI_HOST_PRIM) { + if (mddi_vsync_detect_enabled) { + mddi_host_enable_io_clock(); +#ifndef MDDI_HOST_DISP_LISTEN + /* issue command to bring up link */ + /* need to do this to clear the vsync condition */ + if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { + pmhctl->link_state = MDDI_LINK_ACTIVATING; + mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); + } +#endif + /* + * Indicate to client specific code that vsync was + * enabled, and we did not detect a client initiated + * wakeup. The client specific handler can clear the + * condition if necessary to prevent subsequent + * client initiated wakeups. + */ + mddi_client_lcd_vsync_detected(TRUE); + pmhctl->log_parms.vsync_response_cnt++; + MDDI_MSG_NOTICE("MDDI_INT_IN condition\n"); + + } + } + + if (mddi_gpio.polling_enabled) { + mddi_host_enable_io_clock(); + /* check interrupt status now */ + (void)mddi_queue_register_read_int(mddi_gpio.polling_reg, + &mddi_gpio.polling_val); + } +} +#endif /* FEATURE_MDDI_DISABLE_REVERSE */ + +static void mddi_host_isr(void) +{ + uint32 int_reg, int_en; +#ifndef FEATURE_MDDI_DISABLE_REVERSE + uint32 status_reg; +#endif + mddi_host_type host_idx = mddi_curr_host; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + if (!MDDI_HOST_IS_HCLK_ON) { + MDDI_HOST_ENABLE_HCLK; + MDDI_MSG_DEBUG("HCLK disabled, but isr is firing\n"); + } + int_reg = mddi_host_reg_in(INT); + int_en = mddi_host_reg_in(INTEN); + pmhctl->saved_int_reg = int_reg; + pmhctl->saved_int_en = int_en; + int_reg = int_reg & int_en; + pmhctl->int_type.count++; + + +#ifndef FEATURE_MDDI_DISABLE_REVERSE + status_reg = mddi_host_reg_in(STAT); + + if ((int_reg & MDDI_INT_MDDI_IN) || + ((int_en & MDDI_INT_MDDI_IN) && + ((int_reg == 0) || (status_reg & MDDI_STAT_CLIENT_WAKEUP_REQ)))) { + /* + * The MDDI_IN condition will clear itself, and so it is + * possible that MDDI_IN was the reason for the isr firing, + * even though the interrupt register does not have the + * MDDI_IN bit set. To check if this was the case we need to + * look at the status register bit that signifies a client + * initiated wakeup. If the status register bit is set, as well + * as the MDDI_IN interrupt enabled, then we treat this as a + * client initiated wakeup. + */ + if (int_reg & MDDI_INT_MDDI_IN) + pmhctl->int_type.in_count++; + mddi_process_client_initiated_wakeup(); + } +#endif + + if (int_reg & MDDI_INT_LINK_STATE_CHANGES) { + pmhctl->int_type.state_change_count++; + mddi_report_state_change(int_reg); + } + + if (int_reg & MDDI_INT_PRI_LINK_LIST_DONE) { + pmhctl->int_type.ll_done_count++; + mddi_process_link_list_done(); + } +#ifndef FEATURE_MDDI_DISABLE_REVERSE + if (int_reg & MDDI_INT_REV_DATA_AVAIL) { + pmhctl->int_type.rev_avail_count++; + mddi_process_rev_packets(); + } +#endif + + if (int_reg & MDDI_INT_ERROR_CONDITIONS) { + pmhctl->int_type.error_count++; + mddi_report_errors(int_reg); + + mddi_host_reg_out(INT, int_reg & MDDI_INT_ERROR_CONDITIONS); + } +#ifndef FEATURE_MDDI_DISABLE_REVERSE + mddi_issue_reverse_encapsulation(); + + if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) && + (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED)) +#endif + /* don't want simultaneous reverse and forward with Eagle */ + mddi_queue_forward_linked_list(); + + if (int_reg & MDDI_INT_NO_CMD_PKTS_PEND) { + /* this interrupt is used to kick the isr when hibernation is disabled */ + mddi_host_reg_outm(INTEN, MDDI_INT_NO_CMD_PKTS_PEND, 0); + } + + if ((!mddi_host_mdp_active_flag) && + (!mddi_vsync_detect_enabled) && + (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) && + (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) && + (pmhctl->rev_state == MDDI_REV_IDLE)) { + if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { + mddi_host_disable_io_clock(); + mddi_host_disable_hclk(); + } +#ifdef FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION + else if ((pmhctl->link_state == MDDI_LINK_ACTIVE) && + (!pmhctl->disable_hibernation)) { + mddi_host_reg_out(CMD, MDDI_CMD_POWERDOWN); + } +#endif + } +} + +static void mddi_host_isr_primary(void) +{ + mddi_curr_host = MDDI_HOST_PRIM; + mddi_host_isr(); +} + +irqreturn_t mddi_pmdh_isr_proxy(int irq, void *ptr) +{ + mddi_host_isr_primary(); + return IRQ_HANDLED; +} + +static void mddi_host_isr_external(void) +{ + mddi_curr_host = MDDI_HOST_EXT; + mddi_host_isr(); + mddi_curr_host = MDDI_HOST_PRIM; +} + +irqreturn_t mddi_emdh_isr_proxy(int irq, void *ptr) +{ + mddi_host_isr_external(); + return IRQ_HANDLED; +} + +static void mddi_host_initialize_registers(mddi_host_type host_idx) +{ + uint32 pad_reg_val; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + if (pmhctl->driver_state == MDDI_DRIVER_ENABLED) + return; + + /* turn on HCLK to MDDI host core */ + mddi_host_enable_hclk(); + + /* MDDI Reset command */ + mddi_host_reg_out(CMD, MDDI_CMD_RESET); + + /* Version register (= 0x01) */ + mddi_host_reg_out(VERSION, 0x0001); + + /* Bytes per subframe register */ + mddi_host_reg_out(BPS, MDDI_HOST_BYTES_PER_SUBFRAME); + + /* Subframes per media frames register (= 0x03) */ + mddi_host_reg_out(SPM, 0x0003); + + /* Turn Around 1 register (= 0x05) */ + mddi_host_reg_out(TA1_LEN, 0x0005); + + /* Turn Around 2 register (= 0x0C) */ + mddi_host_reg_out(TA2_LEN, MDDI_HOST_TA2_LEN); + + /* Drive hi register (= 0x96) */ + mddi_host_reg_out(DRIVE_HI, 0x0096); + + /* Drive lo register (= 0x32) */ + mddi_host_reg_out(DRIVE_LO, 0x0032); + + /* Display wakeup count register (= 0x3c) */ + mddi_host_reg_out(DISP_WAKE, 0x003c); + + /* Reverse Rate Divisor register (= 0x2) */ + mddi_host_reg_out(REV_RATE_DIV, MDDI_HOST_REV_RATE_DIV); + +#ifndef FEATURE_MDDI_DISABLE_REVERSE + /* Reverse Pointer Size */ + mddi_host_reg_out(REV_SIZE, MDDI_REV_BUFFER_SIZE); + + /* Rev Encap Size */ + mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size); +#endif + + /* Periodic Rev Encap */ + /* don't send periodically */ + mddi_host_reg_out(CMD, MDDI_CMD_PERIODIC_REV_ENCAP); + + pad_reg_val = mddi_host_reg_in(PAD_CTL); + if (pad_reg_val == 0) { + /* If we are turning on band gap, need to wait 5us before turning + * on the rest of the PAD */ + mddi_host_reg_out(PAD_CTL, 0x08000); + udelay(5); + } +#ifdef T_MSM7200 + /* Recommendation from PAD hw team */ + mddi_host_reg_out(PAD_CTL, 0xa850a); +#else + /* Recommendation from PAD hw team */ + mddi_host_reg_out(PAD_CTL, 0xa850f); +#endif + +#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) + mddi_host_reg_out(PAD_IO_CTL, 0x00320000); + mddi_host_reg_out(PAD_CAL, 0x00220020); +#endif + + mddi_host_core_version = mddi_host_reg_inm(CORE_VER, 0xffff); + +#ifndef FEATURE_MDDI_DISABLE_REVERSE + if (mddi_host_core_version >= 8) + mddi_rev_ptr_workaround = FALSE; + pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; +#endif + + if ((mddi_host_core_version > 8) && (mddi_host_core_version < 0x19)) + mddi_host_reg_out(TEST, 0x2); + + /* Need an even number for counts */ + mddi_host_reg_out(DRIVER_START_CNT, 0x60006); + +#ifndef T_MSM7500 + /* Setup defaults for MDP related register */ + mddi_host_reg_out(MDP_VID_FMT_DES, 0x5666); + mddi_host_reg_out(MDP_VID_PIX_ATTR, 0x00C3); + mddi_host_reg_out(MDP_VID_CLIENTID, 0); +#endif + + /* automatically hibernate after 1 empty subframe */ + if (pmhctl->disable_hibernation) + mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE); + else + mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1); + + /* Bring up link if display (client) requests it */ +#ifdef MDDI_HOST_DISP_LISTEN + mddi_host_reg_out(CMD, MDDI_CMD_DISP_LISTEN); +#else + mddi_host_reg_out(CMD, MDDI_CMD_DISP_IGNORE); +#endif + +} + +void mddi_host_configure_interrupts(mddi_host_type host_idx, boolean enable) +{ + unsigned long flags; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + spin_lock_irqsave(&mddi_host_spin_lock, flags); + + /* turn on HCLK to MDDI host core if it has been disabled */ + mddi_host_enable_hclk(); + /* Clear MDDI Interrupt enable reg */ + mddi_host_reg_out(INTEN, 0); + + spin_unlock_irqrestore(&mddi_host_spin_lock, flags); + + if (enable) { + pmhctl->driver_state = MDDI_DRIVER_ENABLED; + + if (host_idx == MDDI_HOST_PRIM) { + if (request_irq + (INT_MDDI_PRI, mddi_pmdh_isr_proxy, IRQF_DISABLED, + "PMDH", 0) != 0) + printk(KERN_ERR + "a mddi: unable to request_irq\n"); + else + int_mddi_pri_flag = TRUE; + } else { + if (request_irq + (INT_MDDI_EXT, mddi_emdh_isr_proxy, IRQF_DISABLED, + "EMDH", 0) != 0) + printk(KERN_ERR + "b mddi: unable to request_irq\n"); + else + int_mddi_ext_flag = TRUE; + } + + /* Set MDDI Interrupt enable reg -- Enable Reverse data avail */ +#ifdef FEATURE_MDDI_DISABLE_REVERSE + mddi_host_reg_out(INTEN, + MDDI_INT_ERROR_CONDITIONS | + MDDI_INT_LINK_STATE_CHANGES); +#else + /* Reverse Pointer register */ + pmhctl->rev_ptr_written = FALSE; + + mddi_host_reg_out(INTEN, + MDDI_INT_REV_DATA_AVAIL | + MDDI_INT_ERROR_CONDITIONS | + MDDI_INT_LINK_STATE_CHANGES); + pmhctl->rtd_counter = mddi_rtd_frequency; + pmhctl->client_status_cnt = 0; +#endif + } else { + if (pmhctl->driver_state == MDDI_DRIVER_ENABLED) + pmhctl->driver_state = MDDI_DRIVER_DISABLED; + } + +} + +static void mddi_host_powerup(mddi_host_type host_idx) +{ + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + if (pmhctl->link_state != MDDI_LINK_DISABLED) + return; + + /* enable IO_CLK and hclk to MDDI host core */ + mddi_host_enable_io_clock(); + + mddi_host_initialize_registers(host_idx); + mddi_host_configure_interrupts(host_idx, TRUE); + + pmhctl->link_state = MDDI_LINK_ACTIVATING; + + /* Link activate command */ + mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); + +#ifdef CLKRGM_MDDI_IO_CLOCK_IN_MHZ + MDDI_MSG_NOTICE("MDDI Host: Activating Link %d Mbps\n", + CLKRGM_MDDI_IO_CLOCK_IN_MHZ * 2); +#else + MDDI_MSG_NOTICE("MDDI Host: Activating Link\n"); +#endif + + /* Initialize the timer */ + if (host_idx == MDDI_HOST_PRIM) + mddi_host_timer_service(0); +} + +void mddi_host_init(mddi_host_type host_idx) +/* Write out the MDDI configuration registers */ +{ + static boolean initialized = FALSE; + mddi_host_cntl_type *pmhctl; + + if (host_idx >= MDDI_NUM_HOST_CORES) { + MDDI_MSG_ERR("Invalid host core index\n"); + return; + } + + if (!initialized) { + uint16 idx; + mddi_host_type host; + for (host = MDDI_HOST_PRIM; host < MDDI_NUM_HOST_CORES; host++) { + pmhctl = &(mhctl[host]); + initialized = TRUE; + + pmhctl->llist_ptr = + dma_alloc_coherent(NULL, MDDI_LLIST_POOL_SIZE, + &(pmhctl->llist_dma_addr), + GFP_KERNEL); + pmhctl->llist_dma_ptr = + (mddi_linked_list_type *) (void *)pmhctl-> + llist_dma_addr; +#ifdef FEATURE_MDDI_DISABLE_REVERSE + pmhctl->rev_data_buf = NULL; + if (pmhctl->llist_ptr == NULL) +#else + mddi_rev_user.waiting = FALSE; + init_completion(&(mddi_rev_user.done_comp)); + pmhctl->rev_data_buf = + dma_alloc_coherent(NULL, MDDI_MAX_REV_DATA_SIZE, + &(pmhctl->rev_data_dma_addr), + GFP_KERNEL); + if ((pmhctl->llist_ptr == NULL) + || (pmhctl->rev_data_buf == NULL)) +#endif + { + MDDI_MSG_CRIT + ("unable to alloc non-cached memory\n"); + } + llist_extern[host] = pmhctl->llist_ptr; + llist_dma_extern[host] = pmhctl->llist_dma_ptr; + llist_extern_notify[host] = pmhctl->llist_notify; + + for (idx = 0; idx < UNASSIGNED_INDEX; idx++) { + init_completion(& + (pmhctl->llist_notify[idx]. + done_comp)); + } + init_completion(&(pmhctl->mddi_llist_avail_comp)); + spin_lock_init(&mddi_host_spin_lock); + pmhctl->mddi_waiting_for_llist_avail = FALSE; + pmhctl->mddi_rev_ptr_write_val = + (uint32) (void *)(pmhctl->rev_data_dma_addr); + pmhctl->rev_ptr_start = (void *)pmhctl->rev_data_buf; + + pmhctl->rev_pkt_size = MDDI_DEFAULT_REV_PKT_SIZE; + pmhctl->rev_state = MDDI_REV_IDLE; +#ifdef IMAGE_MODEM_PROC + /* assume hibernation state is last state from APPS proc, so that + * we don't reinitialize the host core */ + pmhctl->link_state = MDDI_LINK_HIBERNATING; +#else + pmhctl->link_state = MDDI_LINK_DISABLED; +#endif + pmhctl->driver_state = MDDI_DRIVER_DISABLED; + pmhctl->disable_hibernation = FALSE; + + /* initialize llist variables */ + pmhctl->llist_info.transmitting_start_idx = + UNASSIGNED_INDEX; + pmhctl->llist_info.transmitting_end_idx = + UNASSIGNED_INDEX; + pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX; + pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX; + pmhctl->llist_info.reg_read_idx = UNASSIGNED_INDEX; + pmhctl->llist_info.next_free_idx = + MDDI_FIRST_DYNAMIC_LLIST_IDX; + pmhctl->llist_info.reg_read_waiting = FALSE; + + mddi_vsync_detect_enabled = FALSE; + mddi_gpio.polling_enabled = FALSE; + + pmhctl->int_type.count = 0; + pmhctl->int_type.in_count = 0; + pmhctl->int_type.disp_req_count = 0; + pmhctl->int_type.state_change_count = 0; + pmhctl->int_type.ll_done_count = 0; + pmhctl->int_type.rev_avail_count = 0; + pmhctl->int_type.error_count = 0; + pmhctl->int_type.rev_encap_count = 0; + pmhctl->int_type.llist_ptr_write_1 = 0; + pmhctl->int_type.llist_ptr_write_2 = 0; + + pmhctl->stats.fwd_crc_count = 0; + pmhctl->stats.rev_crc_count = 0; + pmhctl->stats.pri_underflow = 0; + pmhctl->stats.sec_underflow = 0; + pmhctl->stats.rev_overflow = 0; + pmhctl->stats.pri_overwrite = 0; + pmhctl->stats.sec_overwrite = 0; + pmhctl->stats.rev_overwrite = 0; + pmhctl->stats.dma_failure = 0; + pmhctl->stats.rtd_failure = 0; + pmhctl->stats.reg_read_failure = 0; +#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY + pmhctl->stats.pri_underrun_detected = 0; +#endif + + pmhctl->log_parms.rtd_cnt = 0; + pmhctl->log_parms.rev_enc_cnt = 0; + pmhctl->log_parms.vid_cnt = 0; + pmhctl->log_parms.reg_acc_cnt = 0; + pmhctl->log_parms.cli_stat_cnt = 0; + pmhctl->log_parms.cli_cap_cnt = 0; + pmhctl->log_parms.reg_read_cnt = 0; + pmhctl->log_parms.link_active_cnt = 0; + pmhctl->log_parms.link_hibernate_cnt = 0; + pmhctl->log_parms.fwd_crc_cnt = 0; + pmhctl->log_parms.rev_crc_cnt = 0; + pmhctl->log_parms.vsync_response_cnt = 0; + + prev_parms[host_idx] = pmhctl->log_parms; + mddi_client_capability_pkt.packet_length = 0; + } + +#ifndef T_MSM7500 + /* tell clock driver we are user of this PLL */ + MDDI_HOST_ENABLE_IO_CLOCK; +#endif + } + + mddi_host_powerup(host_idx); + pmhctl = &(mhctl[host_idx]); +} + +#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT +static uint32 mddi_client_id; + +uint32 mddi_get_client_id(void) +{ + +#ifndef FEATURE_MDDI_DISABLE_REVERSE + mddi_host_type host_idx = MDDI_HOST_PRIM; + static boolean client_detection_try = FALSE; + mddi_host_cntl_type *pmhctl; + unsigned long flags; + uint16 saved_rev_pkt_size; + + if (!client_detection_try) { + /* Toshiba display requires larger drive_lo value */ + mddi_host_reg_out(DRIVE_LO, 0x0050); + + pmhctl = &(mhctl[MDDI_HOST_PRIM]); + + saved_rev_pkt_size = pmhctl->rev_pkt_size; + + /* Increase Rev Encap Size */ + pmhctl->rev_pkt_size = MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE; + mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size); + + /* disable hibernation temporarily */ + if (!pmhctl->disable_hibernation) + mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE); + + mddi_rev_user.waiting = TRUE; + INIT_COMPLETION(mddi_rev_user.done_comp); + + spin_lock_irqsave(&mddi_host_spin_lock, flags); + + /* turn on clock(s), if they have been disabled */ + mddi_host_enable_hclk(); + mddi_host_enable_io_clock(); + + mddi_client_capability_request = TRUE; + + if (pmhctl->rev_state == MDDI_REV_IDLE) { + /* attempt to send the reverse encapsulation now */ + mddi_issue_reverse_encapsulation(); + } + spin_unlock_irqrestore(&mddi_host_spin_lock, flags); + + wait_for_completion_killable(&(mddi_rev_user.done_comp)); + + /* Set Rev Encap Size back to its original value */ + pmhctl->rev_pkt_size = saved_rev_pkt_size; + mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size); + + /* reenable auto-hibernate */ + if (!pmhctl->disable_hibernation) + mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1); + + mddi_host_reg_out(DRIVE_LO, 0x0032); + client_detection_try = TRUE; + + mddi_client_id = (mddi_client_capability_pkt.Mfr_Name<<16) | + mddi_client_capability_pkt.Product_Code; + + if (!mddi_client_id) + mddi_disable(1); + } + +#if 0 + switch (mddi_client_capability_pkt.Mfr_Name) { + case 0x4474: + if ((mddi_client_capability_pkt.Product_Code != 0x8960) && + (target == DISPLAY_1)) { + ret = PRISM_WVGA; + } + break; + + case 0xD263: + if (target == DISPLAY_1) + ret = TOSHIBA_VGA_PRIM; + else if (target == DISPLAY_2) + ret = TOSHIBA_QCIF_SECD; + break; + + case 0: + if (mddi_client_capability_pkt.Product_Code == 0x8835) { + if (target == DISPLAY_1) + ret = SHARP_QVGA_PRIM; + else if (target == DISPLAY_2) + ret = SHARP_128x128_SECD; + } + break; + + default: + break; + } + + if ((!client_detection_try) && (ret != TOSHIBA_VGA_PRIM) + && (ret != TOSHIBA_QCIF_SECD)) { + /* Not a Toshiba display, so change drive_lo back to default value */ + mddi_host_reg_out(DRIVE_LO, 0x0032); + } +#endif + +#endif + + return mddi_client_id; +} +#endif + +void mddi_host_powerdown(mddi_host_type host_idx) +{ + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + if (host_idx >= MDDI_NUM_HOST_CORES) { + MDDI_MSG_ERR("Invalid host core index\n"); + return; + } + + if (pmhctl->driver_state == MDDI_DRIVER_RESET) { + return; + } + + if (host_idx == MDDI_HOST_PRIM) { + /* disable timer */ + del_timer(&mddi_host_timer); + } + + mddi_host_configure_interrupts(host_idx, FALSE); + + /* turn on HCLK to MDDI host core if it has been disabled */ + mddi_host_enable_hclk(); + + /* MDDI Reset command */ + mddi_host_reg_out(CMD, MDDI_CMD_RESET); + + /* Pad Control Register */ + mddi_host_reg_out(PAD_CTL, 0x0); + + /* disable IO_CLK and hclk to MDDI host core */ + mddi_host_disable_io_clock(); + mddi_host_disable_hclk(); + + pmhctl->link_state = MDDI_LINK_DISABLED; + pmhctl->driver_state = MDDI_DRIVER_RESET; + + MDDI_MSG_NOTICE("MDDI Host: Disabling Link\n"); + +} + +uint16 mddi_get_next_free_llist_item(mddi_host_type host_idx, boolean wait) +{ + unsigned long flags; + uint16 ret_idx; + boolean forced_wait = FALSE; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + ret_idx = pmhctl->llist_info.next_free_idx; + + pmhctl->llist_info.next_free_idx++; + if (pmhctl->llist_info.next_free_idx >= MDDI_NUM_DYNAMIC_LLIST_ITEMS) + pmhctl->llist_info.next_free_idx = MDDI_FIRST_DYNAMIC_LLIST_IDX; + spin_lock_irqsave(&mddi_host_spin_lock, flags); + if (pmhctl->llist_notify[ret_idx].in_use) { + if (!wait) { + pmhctl->llist_info.next_free_idx = ret_idx; + ret_idx = UNASSIGNED_INDEX; + } else { + forced_wait = TRUE; + INIT_COMPLETION(pmhctl->mddi_llist_avail_comp); + } + } + spin_unlock_irqrestore(&mddi_host_spin_lock, flags); + + if (forced_wait) { + wait_for_completion_killable(& + (pmhctl-> + mddi_llist_avail_comp)); + MDDI_MSG_ERR("task waiting on mddi llist item\n"); + } + + if (ret_idx != UNASSIGNED_INDEX) { + pmhctl->llist_notify[ret_idx].waiting = FALSE; + pmhctl->llist_notify[ret_idx].done_cb = NULL; + pmhctl->llist_notify[ret_idx].in_use = TRUE; + pmhctl->llist_notify[ret_idx].next_idx = UNASSIGNED_INDEX; + } + + return ret_idx; +} + +uint16 mddi_get_reg_read_llist_item(mddi_host_type host_idx, boolean wait) +{ +#ifdef FEATURE_MDDI_DISABLE_REVERSE + MDDI_MSG_CRIT("No reverse link available\n"); + (void)wait; + return FALSE; +#else + unsigned long flags; + uint16 ret_idx; + boolean error = FALSE; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + spin_lock_irqsave(&mddi_host_spin_lock, flags); + if (pmhctl->llist_info.reg_read_idx != UNASSIGNED_INDEX) { + /* need to block here or is this an error condition? */ + error = TRUE; + ret_idx = UNASSIGNED_INDEX; + } + spin_unlock_irqrestore(&mddi_host_spin_lock, flags); + + if (!error) { + ret_idx = pmhctl->llist_info.reg_read_idx = + mddi_get_next_free_llist_item(host_idx, wait); + /* clear the reg_read_waiting flag */ + pmhctl->llist_info.reg_read_waiting = FALSE; + } + + if (error) + MDDI_MSG_ERR("***** Reg read still in progress! ****\n"); + return ret_idx; +#endif + +} + +void mddi_queue_forward_packets(uint16 first_llist_idx, + uint16 last_llist_idx, + boolean wait, + mddi_llist_done_cb_type llist_done_cb, + mddi_host_type host_idx) +{ + unsigned long flags; + mddi_linked_list_type *llist; + mddi_linked_list_type *llist_dma; + mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); + + if ((first_llist_idx >= UNASSIGNED_INDEX) || + (last_llist_idx >= UNASSIGNED_INDEX)) { + MDDI_MSG_ERR("MDDI queueing invalid linked list\n"); + return; + } + + if (pmhctl->link_state == MDDI_LINK_DISABLED) + MDDI_MSG_CRIT("MDDI host powered down!\n"); + + llist = pmhctl->llist_ptr; + llist_dma = pmhctl->llist_dma_ptr; + + /* clean cache so MDDI host can read data */ + memory_barrier(); + + pmhctl->llist_notify[last_llist_idx].waiting = wait; + if (wait) + INIT_COMPLETION(pmhctl->llist_notify[last_llist_idx].done_comp); + pmhctl->llist_notify[last_llist_idx].done_cb = llist_done_cb; + + spin_lock_irqsave(&mddi_host_spin_lock, flags); + + if ((pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) && + (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) && + (pmhctl->rev_state == MDDI_REV_IDLE)) { + /* no packets are currently transmitting */ +#ifndef FEATURE_MDDI_DISABLE_REVERSE + if (first_llist_idx == pmhctl->llist_info.reg_read_idx) { + /* This is the special case where the packet is a register read. */ + pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED; + mddi_reg_read_retry = 0; + /* mddi_rev_reg_read_attempt = 1; */ + } +#endif + /* assign transmitting index values */ + pmhctl->llist_info.transmitting_start_idx = first_llist_idx; + pmhctl->llist_info.transmitting_end_idx = last_llist_idx; + + /* turn on clock(s), if they have been disabled */ + mddi_host_enable_hclk(); + mddi_host_enable_io_clock(); + pmhctl->int_type.llist_ptr_write_1++; + /* Write to primary pointer register */ + dma_coherent_pre_ops(); + mddi_host_reg_out(PRI_PTR, &llist_dma[first_llist_idx]); + + /* enable interrupt when complete */ + mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, + MDDI_INT_PRI_LINK_LIST_DONE); + + } else if (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) { +#ifndef FEATURE_MDDI_DISABLE_REVERSE + if (first_llist_idx == pmhctl->llist_info.reg_read_idx) { + /* + * we have a register read to send but need to wait + * for current reverse activity to end or there are + * packets currently transmitting + */ + /* mddi_rev_reg_read_attempt = 0; */ + pmhctl->llist_info.reg_read_waiting = TRUE; + } +#endif + + /* assign waiting index values */ + pmhctl->llist_info.waiting_start_idx = first_llist_idx; + pmhctl->llist_info.waiting_end_idx = last_llist_idx; + } else { + uint16 prev_end_idx = pmhctl->llist_info.waiting_end_idx; +#ifndef FEATURE_MDDI_DISABLE_REVERSE + if (first_llist_idx == pmhctl->llist_info.reg_read_idx) { + /* + * we have a register read to send but need to wait + * for current reverse activity to end or there are + * packets currently transmitting + */ + /* mddi_rev_reg_read_attempt = 0; */ + pmhctl->llist_info.reg_read_waiting = TRUE; + } +#endif + + llist = pmhctl->llist_ptr; + + /* clear end flag in previous last packet */ + llist[prev_end_idx].link_controller_flags = 0; + pmhctl->llist_notify[prev_end_idx].next_idx = first_llist_idx; + + /* set the next_packet_pointer of the previous last packet */ + llist[prev_end_idx].next_packet_pointer = + (void *)(&llist_dma[first_llist_idx]); + + /* clean cache so MDDI host can read data */ + memory_barrier(); + + /* assign new waiting last index value */ + pmhctl->llist_info.waiting_end_idx = last_llist_idx; + } + + spin_unlock_irqrestore(&mddi_host_spin_lock, flags); + +} + +void mddi_host_write_pix_attr_reg(uint32 value) +{ + (void)value; +} + +void mddi_queue_reverse_encapsulation(boolean wait) +{ +#ifdef FEATURE_MDDI_DISABLE_REVERSE + MDDI_MSG_CRIT("No reverse link available\n"); + (void)wait; +#else + unsigned long flags; + boolean error = FALSE; + mddi_host_type host_idx = MDDI_HOST_PRIM; + mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]); + + spin_lock_irqsave(&mddi_host_spin_lock, flags); + + /* turn on clock(s), if they have been disabled */ + mddi_host_enable_hclk(); + mddi_host_enable_io_clock(); + + if (wait) { + if (!mddi_rev_user.waiting) { + mddi_rev_user.waiting = TRUE; + INIT_COMPLETION(mddi_rev_user.done_comp); + } else + error = TRUE; + } + mddi_rev_encap_user_request = TRUE; + + if (pmhctl->rev_state == MDDI_REV_IDLE) { + /* attempt to send the reverse encapsulation now */ + mddi_host_type orig_host_idx = mddi_curr_host; + mddi_curr_host = host_idx; + mddi_issue_reverse_encapsulation(); + mddi_curr_host = orig_host_idx; + } + spin_unlock_irqrestore(&mddi_host_spin_lock, flags); + + if (error) { + MDDI_MSG_ERR("Reverse Encap request already in progress\n"); + } else if (wait) + wait_for_completion_killable(&(mddi_rev_user.done_comp)); +#endif +} + +/* ISR to be executed */ +boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type) +{ +#ifdef FEATURE_MDDI_DISABLE_REVERSE + MDDI_MSG_CRIT("No reverse link available\n"); + (void)handler; + (void)pkt_type; + return (FALSE); +#else + unsigned long flags; + uint16 hdlr; + boolean handler_set = FALSE; + boolean overwrite = FALSE; + mddi_host_type host_idx = MDDI_HOST_PRIM; + mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]); + + /* Disable interrupts */ + spin_lock_irqsave(&mddi_host_spin_lock, flags); + + for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) { + if (mddi_rev_pkt_handler[hdlr].pkt_type == pkt_type) { + mddi_rev_pkt_handler[hdlr].handler = handler; + if (handler == NULL) { + /* clearing handler from table */ + mddi_rev_pkt_handler[hdlr].pkt_type = + INVALID_PKT_TYPE; + handler_set = TRUE; + if (pkt_type == 0x10) { /* video stream packet */ + /* ensure HCLK on to MDDI host core before register write */ + mddi_host_enable_hclk(); + /* No longer getting video, so reset rev encap size to default */ + pmhctl->rev_pkt_size = + MDDI_DEFAULT_REV_PKT_SIZE; + mddi_host_reg_out(REV_ENCAP_SZ, + pmhctl->rev_pkt_size); + } + } else { + /* already a handler for this packet */ + overwrite = TRUE; + } + break; + } + } + if ((hdlr >= MAX_MDDI_REV_HANDLERS) && (handler != NULL)) { + /* assigning new handler */ + for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) { + if (mddi_rev_pkt_handler[hdlr].pkt_type == + INVALID_PKT_TYPE) { + if ((pkt_type == 0x10) && /* video stream packet */ + (pmhctl->rev_pkt_size < + MDDI_VIDEO_REV_PKT_SIZE)) { + /* ensure HCLK on to MDDI host core before register write */ + mddi_host_enable_hclk(); + /* Increase Rev Encap Size */ + pmhctl->rev_pkt_size = + MDDI_VIDEO_REV_PKT_SIZE; + mddi_host_reg_out(REV_ENCAP_SZ, + pmhctl->rev_pkt_size); + } + mddi_rev_pkt_handler[hdlr].handler = handler; + mddi_rev_pkt_handler[hdlr].pkt_type = pkt_type; + handler_set = TRUE; + break; + } + } + } + + /* Restore interrupts */ + spin_unlock_irqrestore(&mddi_host_spin_lock, flags); + + if (overwrite) + MDDI_MSG_ERR("Overwriting previous rev packet handler\n"); + + return handler_set; + +#endif +} /* mddi_set_rev_handler */ + +void mddi_host_disable_hibernation(boolean disable) +{ + mddi_host_type host_idx = MDDI_HOST_PRIM; + mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]); + + if (disable) { + pmhctl->disable_hibernation = TRUE; + /* hibernation will be turned off by isr next time it is entered */ + } else { + if (pmhctl->disable_hibernation) { + unsigned long flags; + spin_lock_irqsave(&mddi_host_spin_lock, flags); + if (!MDDI_HOST_IS_HCLK_ON) + MDDI_HOST_ENABLE_HCLK; + mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1); + spin_unlock_irqrestore(&mddi_host_spin_lock, flags); + pmhctl->disable_hibernation = FALSE; + } + } +} + +void mddi_mhctl_remove(mddi_host_type host_idx) +{ + mddi_host_cntl_type *pmhctl; + + pmhctl = &(mhctl[host_idx]); + + dma_free_coherent(NULL, MDDI_LLIST_POOL_SIZE, (void *)pmhctl->llist_ptr, + pmhctl->llist_dma_addr); + + dma_free_coherent(NULL, MDDI_MAX_REV_DATA_SIZE, + (void *)pmhctl->rev_data_buf, + pmhctl->rev_data_dma_addr); +} diff --git a/drivers/staging/msm/mddihosti.h b/drivers/staging/msm/mddihosti.h new file mode 100644 index 000000000000..7b26a4253896 --- /dev/null +++ b/drivers/staging/msm/mddihosti.h @@ -0,0 +1,547 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MDDIHOSTI_H +#define MDDIHOSTI_H + +#include "msm_fb.h" +#include "mddihost.h" +#include <linux/clk.h> + +/* Register offsets in MDDI, applies to both msm_pmdh_base and + * (u32)msm_emdh_base. */ +#define MDDI_CMD 0x0000 +#define MDDI_VERSION 0x0004 +#define MDDI_PRI_PTR 0x0008 +#define MDDI_BPS 0x0010 +#define MDDI_SPM 0x0014 +#define MDDI_INT 0x0018 +#define MDDI_INTEN 0x001c +#define MDDI_REV_PTR 0x0020 +#define MDDI_REV_SIZE 0x0024 +#define MDDI_STAT 0x0028 +#define MDDI_REV_RATE_DIV 0x002c +#define MDDI_REV_CRC_ERR 0x0030 +#define MDDI_TA1_LEN 0x0034 +#define MDDI_TA2_LEN 0x0038 +#define MDDI_TEST 0x0040 +#define MDDI_REV_PKT_CNT 0x0044 +#define MDDI_DRIVE_HI 0x0048 +#define MDDI_DRIVE_LO 0x004c +#define MDDI_DISP_WAKE 0x0050 +#define MDDI_REV_ENCAP_SZ 0x0054 +#define MDDI_RTD_VAL 0x0058 +#define MDDI_PAD_CTL 0x0068 +#define MDDI_DRIVER_START_CNT 0x006c +#define MDDI_CORE_VER 0x008c +#define MDDI_FIFO_ALLOC 0x0090 +#define MDDI_PAD_IO_CTL 0x00a0 +#define MDDI_PAD_CAL 0x00a4 + +extern u32 mddi_msg_level; + +/* No longer need to write to clear these registers */ +#define xxxx_mddi_host_reg_outm(reg, mask, val) \ +do { \ + if (host_idx == MDDI_HOST_PRIM) \ + mddi_host_reg_outm_pmdh(reg, mask, val); \ + else \ + mddi_host_reg_outm_emdh(reg, mask, val); \ +} while (0) + +#define mddi_host_reg_outm(reg, mask, val) \ +do { \ + unsigned long __addr; \ + if (host_idx == MDDI_HOST_PRIM) \ + __addr = (u32)msm_pmdh_base + MDDI_##reg; \ + else \ + __addr = (u32)msm_emdh_base + MDDI_##reg; \ + writel((readl(__addr) & ~(mask)) | ((val) & (mask)), __addr); \ +} while (0) + +#define xxxx_mddi_host_reg_out(reg, val) \ +do { \ + if (host_idx == MDDI_HOST_PRIM) \ + mddi_host_reg_out_pmdh(reg, val); \ + else \ + mddi_host_reg_out_emdh(reg, val); \ + } while (0) + +#define mddi_host_reg_out(reg, val) \ +do { \ + if (host_idx == MDDI_HOST_PRIM) \ + writel(val, (u32)msm_pmdh_base + MDDI_##reg); \ + else \ + writel(val, (u32)msm_emdh_base + MDDI_##reg); \ +} while (0) + +#define xxxx_mddi_host_reg_in(reg) \ + ((host_idx) ? \ + mddi_host_reg_in_emdh(reg) : mddi_host_reg_in_pmdh(reg)); + +#define mddi_host_reg_in(reg) \ +((host_idx) ? \ + readl((u32)msm_emdh_base + MDDI_##reg) : \ + readl((u32)msm_pmdh_base + MDDI_##reg)) \ + +#define xxxx_mddi_host_reg_inm(reg, mask) \ + ((host_idx) ? \ + mddi_host_reg_inm_emdh(reg, mask) : \ + mddi_host_reg_inm_pmdh(reg, mask);) + +#define mddi_host_reg_inm(reg, mask) \ +((host_idx) ? \ + readl((u32)msm_emdh_base + MDDI_##reg) & (mask) : \ + readl((u32)msm_pmdh_base + MDDI_##reg) & (mask)) \ + +/* Using non-cacheable pmem, so do nothing */ +#define mddi_invalidate_cache_lines(addr_start, num_bytes) +/* + * Using non-cacheable pmem, so do nothing with cache + * but, ensure write goes out to memory + */ +#define mddi_flush_cache_lines(addr_start, num_bytes) \ + (void) addr_start; \ + (void) num_bytes; \ + memory_barrier() + +/* Since this translates to Remote Procedure Calls to check on clock status +* just use a local variable to keep track of io_clock */ +#define MDDI_HOST_IS_IO_CLOCK_ON mddi_host_io_clock_on +#define MDDI_HOST_ENABLE_IO_CLOCK +#define MDDI_HOST_DISABLE_IO_CLOCK +#define MDDI_HOST_IS_HCLK_ON mddi_host_hclk_on +#define MDDI_HOST_ENABLE_HCLK +#define MDDI_HOST_DISABLE_HCLK +#define FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE +#define FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE + +#define TRAMP_MDDI_HOST_ISR TRAMP_MDDI_PRI_ISR +#define TRAMP_MDDI_HOST_EXT_ISR TRAMP_MDDI_EXT_ISR +#define MDP_LINE_COUNT_BMSK 0x3ff +#define MDP_SYNC_STATUS 0x000c +#define MDP_LINE_COUNT \ +(readl(msm_mdp_base + MDP_SYNC_STATUS) & MDP_LINE_COUNT_BMSK) + +/* MDP sends 256 pixel packets, so lower value hibernates more without +* significantly increasing latency of waiting for next subframe */ +#define MDDI_HOST_BYTES_PER_SUBFRAME 0x3C00 + +#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) +#define MDDI_HOST_TA2_LEN 0x001a +#define MDDI_HOST_REV_RATE_DIV 0x0004 +#else +#define MDDI_HOST_TA2_LEN 0x000c +#define MDDI_HOST_REV_RATE_DIV 0x0002 +#endif + +#define MDDI_MSG_EMERG(msg, ...) \ + if (mddi_msg_level > 0) \ + printk(KERN_EMERG msg, ## __VA_ARGS__); +#define MDDI_MSG_ALERT(msg, ...) \ + if (mddi_msg_level > 1) \ + printk(KERN_ALERT msg, ## __VA_ARGS__); +#define MDDI_MSG_CRIT(msg, ...) \ + if (mddi_msg_level > 2) \ + printk(KERN_CRIT msg, ## __VA_ARGS__); +#define MDDI_MSG_ERR(msg, ...) \ + if (mddi_msg_level > 3) \ + printk(KERN_ERR msg, ## __VA_ARGS__); +#define MDDI_MSG_WARNING(msg, ...) \ + if (mddi_msg_level > 4) \ + printk(KERN_WARNING msg, ## __VA_ARGS__); +#define MDDI_MSG_NOTICE(msg, ...) \ + if (mddi_msg_level > 5) \ + printk(KERN_NOTICE msg, ## __VA_ARGS__); +#define MDDI_MSG_INFO(msg, ...) \ + if (mddi_msg_level > 6) \ + printk(KERN_INFO msg, ## __VA_ARGS__); +#define MDDI_MSG_DEBUG(msg, ...) \ + if (mddi_msg_level > 7) \ + printk(KERN_DEBUG msg, ## __VA_ARGS__); + +#define GCC_PACKED __attribute__((packed)) +typedef struct GCC_PACKED { + uint16 packet_length; + /* total # of bytes in the packet not including + the packet_length field. */ + + uint16 packet_type; + /* A Packet Type of 70 identifies the packet as + a Client status Packet. */ + + uint16 bClient_ID; + /* This field is reserved for future use and shall + be set to zero. */ + +} mddi_rev_packet_type; + +typedef struct GCC_PACKED { + uint16 packet_length; + /* total # of bytes in the packet not including + the packet_length field. */ + + uint16 packet_type; + /* A Packet Type of 70 identifies the packet as + a Client status Packet. */ + + uint16 bClient_ID; + /* This field is reserved for future use and shall + be set to zero. */ + + uint16 reverse_link_request; + /* 16 bit unsigned integer with number of bytes client + needs in the * reverse encapsulation message + to transmit data. */ + + uint8 crc_error_count; + uint8 capability_change; + uint16 graphics_busy_flags; + + uint16 parameter_CRC; + /* 16-bit CRC of all the bytes in the packet + including Packet Length. */ + +} mddi_client_status_type; + +typedef struct GCC_PACKED { + uint16 packet_length; + /* total # of bytes in the packet not including + the packet_length field. */ + + uint16 packet_type; + /* A Packet Type of 66 identifies the packet as + a Client Capability Packet. */ + + uint16 bClient_ID; + /* This field is reserved for future use and + shall be set to zero. */ + + uint16 Protocol_Version; + uint16 Minimum_Protocol_Version; + uint16 Data_Rate_Capability; + uint8 Interface_Type_Capability; + uint8 Number_of_Alt_Displays; + uint16 PostCal_Data_Rate; + uint16 Bitmap_Width; + uint16 Bitmap_Height; + uint16 Display_Window_Width; + uint16 Display_Window_Height; + uint32 Color_Map_Size; + uint16 Color_Map_RGB_Width; + uint16 RGB_Capability; + uint8 Monochrome_Capability; + uint8 Reserved_1; + uint16 Y_Cb_Cr_Capability; + uint16 Bayer_Capability; + uint16 Alpha_Cursor_Image_Planes; + uint32 Client_Feature_Capability_Indicators; + uint8 Maximum_Video_Frame_Rate_Capability; + uint8 Minimum_Video_Frame_Rate_Capability; + uint16 Minimum_Sub_frame_Rate; + uint16 Audio_Buffer_Depth; + uint16 Audio_Channel_Capability; + uint16 Audio_Sample_Rate_Capability; + uint8 Audio_Sample_Resolution; + uint8 Mic_Audio_Sample_Resolution; + uint16 Mic_Sample_Rate_Capability; + uint8 Keyboard_Data_Format; + uint8 pointing_device_data_format; + uint16 content_protection_type; + uint16 Mfr_Name; + uint16 Product_Code; + uint16 Reserved_3; + uint32 Serial_Number; + uint8 Week_of_Manufacture; + uint8 Year_of_Manufacture; + + uint16 parameter_CRC; + /* 16-bit CRC of all the bytes in the packet including Packet Length. */ + +} mddi_client_capability_type; + +typedef struct GCC_PACKED { + uint16 packet_length; + /* total # of bytes in the packet not including the packet_length field. */ + + uint16 packet_type; + /* A Packet Type of 16 identifies the packet as a Video Stream Packet. */ + + uint16 bClient_ID; + /* This field is reserved for future use and shall be set to zero. */ + + uint16 video_data_format_descriptor; + /* format of each pixel in the Pixel Data in the present stream in the + * present packet. + * If bits [15:13] = 000 monochrome + * If bits [15:13] = 001 color pixels (palette). + * If bits [15:13] = 010 color pixels in raw RGB + * If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format + * If bits [15:13] = 100 Bayer pixels + */ + + uint16 pixel_data_attributes; + /* interpreted as follows: + * Bits [1:0] = 11 pixel data is displayed to both eyes + * Bits [1:0] = 10 pixel data is routed to the left eye only. + * Bits [1:0] = 01 pixel data is routed to the right eye only. + * Bits [1:0] = 00 pixel data is routed to the alternate display. + * Bit 2 is 0 Pixel Data is in the standard progressive format. + * Bit 2 is 1 Pixel Data is in interlace format. + * Bit 3 is 0 Pixel Data is in the standard progressive format. + * Bit 3 is 1 Pixel Data is in alternate pixel format. + * Bit 4 is 0 Pixel Data is to or from the display frame buffer. + * Bit 4 is 1 Pixel Data is to or from the camera. + * Bit 5 is 0 pixel data contains the next consecutive row of pixels. + * Bit 5 is 1 X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge, + * X Start, and Y Start parameters are not defined and + * shall be ignored by the client. + * Bits [7:6] = 01 Pixel data is written to the offline image buffer. + * Bits [7:6] = 00 Pixel data is written to the buffer to refresh display. + * Bits [7:6] = 11 Pixel data is written to all image buffers. + * Bits [7:6] = 10 Invalid. Reserved for future use. + * Bits 8 through 11 alternate display number. + * Bits 12 through 14 are reserved for future use and shall be set to zero. + * Bit 15 is 1 the row of pixels is the last row of pixels in a frame. + */ + + uint16 x_left_edge; + uint16 y_top_edge; + /* X,Y coordinate of the top left edge of the screen window */ + + uint16 x_right_edge; + uint16 y_bottom_edge; + /* X,Y coordinate of the bottom right edge of the window being updated. */ + + uint16 x_start; + uint16 y_start; + /* (X Start, Y Start) is the first pixel in the Pixel Data field below. */ + + uint16 pixel_count; + /* number of pixels in the Pixel Data field below. */ + + uint16 parameter_CRC; + /* 16-bit CRC of all bytes from the Packet Length to the Pixel Count. */ + + uint16 reserved; + /* 16-bit variable to make structure align on 4 byte boundary */ + +} mddi_video_stream_packet_type; + +typedef struct GCC_PACKED { + uint16 packet_length; + /* total # of bytes in the packet not including the packet_length field. */ + + uint16 packet_type; + /* A Packet Type of 146 identifies the packet as a Register Access Packet. */ + + uint16 bClient_ID; + /* This field is reserved for future use and shall be set to zero. */ + + uint16 read_write_info; + /* Bits 13:0 a 14-bit unsigned integer that specifies the number of + * 32-bit Register Data List items to be transferred in the + * Register Data List field. + * Bits[15:14] = 00 Write to register(s); + * Bits[15:14] = 10 Read from register(s); + * Bits[15:14] = 11 Response to a Read. + * Bits[15:14] = 01 this value is reserved for future use. */ + + uint32 register_address; + /* the register address that is to be written to or read from. */ + + uint16 parameter_CRC; + /* 16-bit CRC of all bytes from the Packet Length to the Register Address. */ + + uint32 register_data_list; + /* list of 4-byte register data values for/from client registers */ + +} mddi_register_access_packet_type; + +typedef union GCC_PACKED { + mddi_video_stream_packet_type video_pkt; + mddi_register_access_packet_type register_pkt; + /* add 48 byte pad to ensure 64 byte llist struct, that can be + * manipulated easily with cache */ + uint32 alignment_pad[12]; /* 48 bytes */ +} mddi_packet_header_type; + +typedef struct GCC_PACKED mddi_host_llist_struct { + uint16 link_controller_flags; + uint16 packet_header_count; + uint16 packet_data_count; + void *packet_data_pointer; + struct mddi_host_llist_struct *next_packet_pointer; + uint16 reserved; + mddi_packet_header_type packet_header; +} mddi_linked_list_type; + +typedef struct { + struct completion done_comp; + mddi_llist_done_cb_type done_cb; + uint16 next_idx; + boolean waiting; + boolean in_use; +} mddi_linked_list_notify_type; + +#define MDDI_LLIST_POOL_SIZE 0x1000 +#define MDDI_MAX_NUM_LLIST_ITEMS (MDDI_LLIST_POOL_SIZE / \ + sizeof(mddi_linked_list_type)) +#define UNASSIGNED_INDEX MDDI_MAX_NUM_LLIST_ITEMS +#define MDDI_FIRST_DYNAMIC_LLIST_IDX 0 + +/* Static llist items can be used for applications that frequently send + * the same set of packets using the linked list interface. */ +/* Here we configure for 6 static linked list items: + * The 1st is used for a the adaptive backlight setting. + * and the remaining 5 are used for sending window adjustments for + * MDDI clients that need windowing info sent separate from video + * packets. */ +#define MDDI_NUM_STATIC_ABL_ITEMS 1 +#define MDDI_NUM_STATIC_WINDOW_ITEMS 5 +#define MDDI_NUM_STATIC_LLIST_ITEMS (MDDI_NUM_STATIC_ABL_ITEMS + \ + MDDI_NUM_STATIC_WINDOW_ITEMS) +#define MDDI_NUM_DYNAMIC_LLIST_ITEMS (MDDI_MAX_NUM_LLIST_ITEMS - \ + MDDI_NUM_STATIC_LLIST_ITEMS) + +#define MDDI_FIRST_STATIC_LLIST_IDX MDDI_NUM_DYNAMIC_LLIST_ITEMS +#define MDDI_FIRST_STATIC_ABL_IDX MDDI_FIRST_STATIC_LLIST_IDX +#define MDDI_FIRST_STATIC_WINDOW_IDX (MDDI_FIRST_STATIC_LLIST_IDX + \ + MDDI_NUM_STATIC_ABL_ITEMS) + +/* GPIO registers */ +#define VSYNC_WAKEUP_REG 0x80 +#define GPIO_REG 0x81 +#define GPIO_OUTPUT_REG 0x82 +#define GPIO_INTERRUPT_REG 0x83 +#define GPIO_INTERRUPT_ENABLE_REG 0x84 +#define GPIO_POLARITY_REG 0x85 + +/* Interrupt Bits */ +#define MDDI_INT_PRI_PTR_READ 0x0001 +#define MDDI_INT_SEC_PTR_READ 0x0002 +#define MDDI_INT_REV_DATA_AVAIL 0x0004 +#define MDDI_INT_DISP_REQ 0x0008 +#define MDDI_INT_PRI_UNDERFLOW 0x0010 +#define MDDI_INT_SEC_UNDERFLOW 0x0020 +#define MDDI_INT_REV_OVERFLOW 0x0040 +#define MDDI_INT_CRC_ERROR 0x0080 +#define MDDI_INT_MDDI_IN 0x0100 +#define MDDI_INT_PRI_OVERWRITE 0x0200 +#define MDDI_INT_SEC_OVERWRITE 0x0400 +#define MDDI_INT_REV_OVERWRITE 0x0800 +#define MDDI_INT_DMA_FAILURE 0x1000 +#define MDDI_INT_LINK_ACTIVE 0x2000 +#define MDDI_INT_IN_HIBERNATION 0x4000 +#define MDDI_INT_PRI_LINK_LIST_DONE 0x8000 +#define MDDI_INT_SEC_LINK_LIST_DONE 0x10000 +#define MDDI_INT_NO_CMD_PKTS_PEND 0x20000 +#define MDDI_INT_RTD_FAILURE 0x40000 + +#define MDDI_INT_ERROR_CONDITIONS ( \ + MDDI_INT_PRI_UNDERFLOW | MDDI_INT_SEC_UNDERFLOW | \ + MDDI_INT_REV_OVERFLOW | MDDI_INT_CRC_ERROR | \ + MDDI_INT_PRI_OVERWRITE | MDDI_INT_SEC_OVERWRITE | \ + MDDI_INT_RTD_FAILURE | \ + MDDI_INT_REV_OVERWRITE | MDDI_INT_DMA_FAILURE) + +#define MDDI_INT_LINK_STATE_CHANGES ( \ + MDDI_INT_LINK_ACTIVE | MDDI_INT_IN_HIBERNATION) + +/* Status Bits */ +#define MDDI_STAT_LINK_ACTIVE 0x0001 +#define MDDI_STAT_NEW_REV_PTR 0x0002 +#define MDDI_STAT_NEW_PRI_PTR 0x0004 +#define MDDI_STAT_NEW_SEC_PTR 0x0008 +#define MDDI_STAT_IN_HIBERNATION 0x0010 +#define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020 +#define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040 +#define MDDI_STAT_PENDING_TIMING_PKT 0x0080 +#define MDDI_STAT_PENDING_REV_ENCAP 0x0100 +#define MDDI_STAT_PENDING_POWERDOWN 0x0200 +#define MDDI_STAT_RTD_MEAS_FAIL 0x0800 +#define MDDI_STAT_CLIENT_WAKEUP_REQ 0x1000 + +/* Command Bits */ +#define MDDI_CMD_POWERDOWN 0x0100 +#define MDDI_CMD_POWERUP 0x0200 +#define MDDI_CMD_HIBERNATE 0x0300 +#define MDDI_CMD_RESET 0x0400 +#define MDDI_CMD_DISP_IGNORE 0x0501 +#define MDDI_CMD_DISP_LISTEN 0x0500 +#define MDDI_CMD_SEND_REV_ENCAP 0x0600 +#define MDDI_CMD_GET_CLIENT_CAP 0x0601 +#define MDDI_CMD_GET_CLIENT_STATUS 0x0602 +#define MDDI_CMD_SEND_RTD 0x0700 +#define MDDI_CMD_LINK_ACTIVE 0x0900 +#define MDDI_CMD_PERIODIC_REV_ENCAP 0x0A00 + +extern void mddi_host_init(mddi_host_type host); +extern void mddi_host_powerdown(mddi_host_type host); +extern uint16 mddi_get_next_free_llist_item(mddi_host_type host, boolean wait); +extern uint16 mddi_get_reg_read_llist_item(mddi_host_type host, boolean wait); +extern void mddi_queue_forward_packets(uint16 first_llist_idx, + uint16 last_llist_idx, + boolean wait, + mddi_llist_done_cb_type llist_done_cb, + mddi_host_type host); + +extern void mddi_host_write_pix_attr_reg(uint32 value); +extern void mddi_client_lcd_gpio_poll(uint32 poll_reg_val); +extern void mddi_client_lcd_vsync_detected(boolean detected); +extern void mddi_host_disable_hibernation(boolean disable); + +extern mddi_linked_list_type *llist_extern[]; +extern mddi_linked_list_type *llist_dma_extern[]; +extern mddi_linked_list_notify_type *llist_extern_notify[]; +extern struct timer_list mddi_host_timer; + +typedef struct { + uint16 transmitting_start_idx; + uint16 transmitting_end_idx; + uint16 waiting_start_idx; + uint16 waiting_end_idx; + uint16 reg_read_idx; + uint16 next_free_idx; + boolean reg_read_waiting; +} mddi_llist_info_type; + +extern mddi_llist_info_type mddi_llist; + +#define MDDI_GPIO_DEFAULT_POLLING_INTERVAL 200 +typedef struct { + uint32 polling_reg; + uint32 polling_val; + uint32 polling_interval; + boolean polling_enabled; +} mddi_gpio_info_type; + +uint32 mddi_get_client_id(void); +void mddi_mhctl_remove(mddi_host_type host_idx); +void mddi_host_timer_service(unsigned long data); +#endif /* MDDIHOSTI_H */ diff --git a/drivers/staging/msm/mdp.c b/drivers/staging/msm/mdp.c new file mode 100644 index 000000000000..36053afdebe2 --- /dev/null +++ b/drivers/staging/msm/mdp.c @@ -0,0 +1,1113 @@ +/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/hrtimer.h> +#include <linux/clk.h> +#include <mach/hardware.h> +#include <linux/io.h> +#include <linux/debugfs.h> +#include <linux/delay.h> +#include <linux/mutex.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/uaccess.h> + +#include "mdp.h" +#include "msm_fb.h" +#ifdef CONFIG_FB_MSM_MDP40 +#include "mdp4.h" +#endif + +static struct clk *mdp_clk; +static struct clk *mdp_pclk; + +struct completion mdp_ppp_comp; +struct semaphore mdp_ppp_mutex; +struct semaphore mdp_pipe_ctrl_mutex; + +unsigned long mdp_timer_duration = (HZ); /* 1 sec */ +/* unsigned long mdp_mdp_timer_duration=0; */ + +boolean mdp_ppp_waiting = FALSE; +uint32 mdp_tv_underflow_cnt; +uint32 mdp_lcdc_underflow_cnt; + +boolean mdp_current_clk_on = FALSE; +boolean mdp_is_in_isr = FALSE; + +/* + * legacy mdp_in_processing is only for DMA2-MDDI + * this applies to DMA2 block only + */ +uint32 mdp_in_processing = FALSE; + +#ifdef CONFIG_FB_MSM_MDP40 +uint32 mdp_intr_mask = MDP4_ANY_INTR_MASK; +#else +uint32 mdp_intr_mask = MDP_ANY_INTR_MASK; +#endif + +MDP_BLOCK_TYPE mdp_debug[MDP_MAX_BLOCK]; + +int32 mdp_block_power_cnt[MDP_MAX_BLOCK]; + +spinlock_t mdp_spin_lock; +struct workqueue_struct *mdp_dma_wq; /*mdp dma wq */ +struct workqueue_struct *mdp_vsync_wq; /*mdp vsync wq */ + +static struct workqueue_struct *mdp_pipe_ctrl_wq; /* mdp mdp pipe ctrl wq */ +static struct delayed_work mdp_pipe_ctrl_worker; + +#ifdef CONFIG_FB_MSM_MDP40 +struct mdp_dma_data dma2_data; +struct mdp_dma_data dma_s_data; +struct mdp_dma_data dma_e_data; +#else +static struct mdp_dma_data dma2_data; +static struct mdp_dma_data dma_s_data; +static struct mdp_dma_data dma_e_data; +#endif +static struct mdp_dma_data dma3_data; + +extern ktime_t mdp_dma2_last_update_time; + +extern uint32 mdp_dma2_update_time_in_usec; +extern int mdp_lcd_rd_cnt_offset_slow; +extern int mdp_lcd_rd_cnt_offset_fast; +extern int mdp_usec_diff_threshold; + +#ifdef CONFIG_FB_MSM_LCDC +extern int mdp_lcdc_pclk_clk_rate; +extern int mdp_lcdc_pad_pclk_clk_rate; +extern int first_pixel_start_x; +extern int first_pixel_start_y; +#endif + +#ifdef MSM_FB_ENABLE_DBGFS +struct dentry *mdp_dir; +#endif + +#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND) +static int mdp_suspend(struct platform_device *pdev, pm_message_t state); +#else +#define mdp_suspend NULL +#endif + +struct timeval mdp_dma2_timeval; +struct timeval mdp_ppp_timeval; + +#ifdef CONFIG_HAS_EARLYSUSPEND +static struct early_suspend early_suspend; +#endif + +#ifndef CONFIG_FB_MSM_MDP22 +DEFINE_MUTEX(mdp_lut_push_sem); +static int mdp_lut_i; +static int mdp_lut_hw_update(struct fb_cmap *cmap) +{ + int i; + u16 *c[3]; + u16 r, g, b; + + c[0] = cmap->green; + c[1] = cmap->blue; + c[2] = cmap->red; + + for (i = 0; i < cmap->len; i++) { + if (copy_from_user(&r, cmap->red++, sizeof(r)) || + copy_from_user(&g, cmap->green++, sizeof(g)) || + copy_from_user(&b, cmap->blue++, sizeof(b))) + return -EFAULT; + +#ifdef CONFIG_FB_MSM_MDP40 + MDP_OUTP(MDP_BASE + 0x94800 + +#else + MDP_OUTP(MDP_BASE + 0x93800 + +#endif + (0x400*mdp_lut_i) + cmap->start*4 + i*4, + ((g & 0xff) | + ((b & 0xff) << 8) | + ((r & 0xff) << 16))); + } + + return 0; +} + +static int mdp_lut_push; +static int mdp_lut_push_i; +static int mdp_lut_update_nonlcdc(struct fb_info *info, struct fb_cmap *cmap) +{ + int ret; + + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + ret = mdp_lut_hw_update(cmap); + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + + if (ret) + return ret; + + mutex_lock(&mdp_lut_push_sem); + mdp_lut_push = 1; + mdp_lut_push_i = mdp_lut_i; + mutex_unlock(&mdp_lut_push_sem); + + mdp_lut_i = (mdp_lut_i + 1)%2; + + return 0; +} + +static int mdp_lut_update_lcdc(struct fb_info *info, struct fb_cmap *cmap) +{ + int ret; + + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + ret = mdp_lut_hw_update(cmap); + + if (ret) { + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + return ret; + } + + MDP_OUTP(MDP_BASE + 0x90070, (mdp_lut_i << 10) | 0x17); + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + mdp_lut_i = (mdp_lut_i + 1)%2; + + return 0; +} + +#define MDP_HIST_MAX_BIN 32 +static __u32 mdp_hist_r[MDP_HIST_MAX_BIN]; +static __u32 mdp_hist_g[MDP_HIST_MAX_BIN]; +static __u32 mdp_hist_b[MDP_HIST_MAX_BIN]; + +#ifdef CONFIG_FB_MSM_MDP40 +struct mdp_histogram mdp_hist; +struct completion mdp_hist_comp; +#else +static struct mdp_histogram mdp_hist; +static struct completion mdp_hist_comp; +#endif + +static int mdp_do_histogram(struct fb_info *info, struct mdp_histogram *hist) +{ + int ret = 0; + + if (!hist->frame_cnt || (hist->bin_cnt == 0) || + (hist->bin_cnt > MDP_HIST_MAX_BIN)) + return -EINVAL; + + INIT_COMPLETION(mdp_hist_comp); + + mdp_hist.bin_cnt = hist->bin_cnt; + mdp_hist.r = (hist->r) ? mdp_hist_r : 0; + mdp_hist.g = (hist->g) ? mdp_hist_g : 0; + mdp_hist.b = (hist->b) ? mdp_hist_b : 0; + +#ifdef CONFIG_FB_MSM_MDP40 + MDP_OUTP(MDP_BASE + 0x95004, hist->frame_cnt); + MDP_OUTP(MDP_BASE + 0x95000, 1); +#else + MDP_OUTP(MDP_BASE + 0x94004, hist->frame_cnt); + MDP_OUTP(MDP_BASE + 0x94000, 1); +#endif + wait_for_completion_killable(&mdp_hist_comp); + + if (hist->r) { + ret = copy_to_user(hist->r, mdp_hist.r, hist->bin_cnt*4); + if (ret) + goto hist_err; + } + if (hist->g) { + ret = copy_to_user(hist->g, mdp_hist.g, hist->bin_cnt*4); + if (ret) + goto hist_err; + } + if (hist->b) { + ret = copy_to_user(hist->b, mdp_hist.b, hist->bin_cnt*4); + if (ret) + goto hist_err; + } + return 0; + +hist_err: + printk(KERN_ERR "%s: invalid hist buffer\n", __func__); + return ret; +} +#endif + +/* Returns < 0 on error, 0 on timeout, or > 0 on successful wait */ + +int mdp_ppp_pipe_wait(void) +{ + int ret = 1; + + /* wait 5 seconds for the operation to complete before declaring + the MDP hung */ + + if (mdp_ppp_waiting == TRUE) { + ret = wait_for_completion_interruptible_timeout(&mdp_ppp_comp, + 5 * HZ); + + if (!ret) + printk(KERN_ERR "%s: Timed out waiting for the MDP.\n", + __func__); + } + + return ret; +} + +static DEFINE_SPINLOCK(mdp_lock); +static int mdp_irq_mask; +static int mdp_irq_enabled; + +void mdp_enable_irq(uint32 term) +{ + unsigned long irq_flags; + + spin_lock_irqsave(&mdp_lock, irq_flags); + if (mdp_irq_mask & term) { + printk(KERN_ERR "MDP IRQ term-0x%x is already set\n", term); + } else { + mdp_irq_mask |= term; + if (mdp_irq_mask && !mdp_irq_enabled) { + mdp_irq_enabled = 1; + enable_irq(INT_MDP); + } + } + spin_unlock_irqrestore(&mdp_lock, irq_flags); +} + +void mdp_disable_irq(uint32 term) +{ + unsigned long irq_flags; + + spin_lock_irqsave(&mdp_lock, irq_flags); + if (!(mdp_irq_mask & term)) { + printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term); + } else { + mdp_irq_mask &= ~term; + if (!mdp_irq_mask && mdp_irq_enabled) { + mdp_irq_enabled = 0; + disable_irq(INT_MDP); + } + } + spin_unlock_irqrestore(&mdp_lock, irq_flags); +} + +void mdp_disable_irq_nolock(uint32 term) +{ + + if (!(mdp_irq_mask & term)) { + printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term); + } else { + mdp_irq_mask &= ~term; + if (!mdp_irq_mask && mdp_irq_enabled) { + mdp_irq_enabled = 0; + disable_irq(INT_MDP); + } + } +} + +void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd) +{ + + dmb(); /* memory barrier */ + + /* kick off PPP engine */ + if (term == MDP_PPP_TERM) { + if (mdp_debug[MDP_PPP_BLOCK]) + jiffies_to_timeval(jiffies, &mdp_ppp_timeval); + + /* let's turn on PPP block */ + mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + + mdp_enable_irq(term); + INIT_COMPLETION(mdp_ppp_comp); + mdp_ppp_waiting = TRUE; + outpdw(MDP_BASE + 0x30, 0x1000); + wait_for_completion_killable(&mdp_ppp_comp); + mdp_disable_irq(term); + + if (mdp_debug[MDP_PPP_BLOCK]) { + struct timeval now; + + jiffies_to_timeval(jiffies, &now); + mdp_ppp_timeval.tv_usec = + now.tv_usec - mdp_ppp_timeval.tv_usec; + MSM_FB_INFO("MDP-PPP: %d\n", + (int)mdp_ppp_timeval.tv_usec); + } + } else if (term == MDP_DMA2_TERM) { + if (mdp_debug[MDP_DMA2_BLOCK]) { + MSM_FB_INFO("MDP-DMA2: %d\n", + (int)mdp_dma2_timeval.tv_usec); + jiffies_to_timeval(jiffies, &mdp_dma2_timeval); + } + /* DMA update timestamp */ + mdp_dma2_last_update_time = ktime_get_real(); + /* let's turn on DMA2 block */ +#if 0 + mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE); +#endif +#ifdef CONFIG_FB_MSM_MDP22 + outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x0044, 0x0);/* start DMA */ +#else + if (mdp_lut_push) { + mutex_lock(&mdp_lut_push_sem); + mdp_lut_push = 0; + MDP_OUTP(MDP_BASE + 0x90070, + (mdp_lut_push_i << 10) | 0x17); + mutex_unlock(&mdp_lut_push_sem); + } +#ifdef CONFIG_FB_MSM_MDP40 + outpdw(MDP_BASE + 0x000c, 0x0); /* start DMA */ +#else + outpdw(MDP_BASE + 0x0044, 0x0); /* start DMA */ +#endif +#endif +#ifdef CONFIG_FB_MSM_MDP40 + } else if (term == MDP_DMA_S_TERM) { + mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + outpdw(MDP_BASE + 0x0010, 0x0); /* start DMA */ + } else if (term == MDP_DMA_E_TERM) { + mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + outpdw(MDP_BASE + 0x0014, 0x0); /* start DMA */ + } else if (term == MDP_OVERLAY0_TERM) { + mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + outpdw(MDP_BASE + 0x0004, 0); + } else if (term == MDP_OVERLAY1_TERM) { + mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + outpdw(MDP_BASE + 0x0008, 0); + } +#else + } else if (term == MDP_DMA_S_TERM) { + mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + outpdw(MDP_BASE + 0x0048, 0x0); /* start DMA */ + } +#endif +} + +static void mdp_pipe_ctrl_workqueue_handler(struct work_struct *work) +{ + mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); +} + +void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state, + boolean isr) +{ + boolean mdp_all_blocks_off = TRUE; + int i; + unsigned long flag; + + spin_lock_irqsave(&mdp_spin_lock, flag); + if (MDP_BLOCK_POWER_ON == state) { + mdp_block_power_cnt[block]++; + + if (MDP_DMA2_BLOCK == block) + mdp_in_processing = TRUE; + } else { + mdp_block_power_cnt[block]--; + + if (mdp_block_power_cnt[block] < 0) { + /* + * Master has to serve a request to power off MDP always + * It also has a timer to power off. So, in case of + * timer expires first and DMA2 finishes later, + * master has to power off two times + * There shouldn't be multiple power-off request for + * other blocks + */ + if (block != MDP_MASTER_BLOCK) { + MSM_FB_INFO("mdp_block_power_cnt[block=%d] \ + multiple power-off request\n", block); + } + mdp_block_power_cnt[block] = 0; + } + + if (MDP_DMA2_BLOCK == block) + mdp_in_processing = FALSE; + } + spin_unlock_irqrestore(&mdp_spin_lock, flag); + + /* + * If it's in isr, we send our request to workqueue. + * Otherwise, processing happens in the current context + */ + if (isr) { + /* checking all blocks power state */ + for (i = 0; i < MDP_MAX_BLOCK; i++) { + if (mdp_block_power_cnt[i] > 0) + mdp_all_blocks_off = FALSE; + } + + if ((mdp_all_blocks_off) && (mdp_current_clk_on)) { + /* send workqueue to turn off mdp power */ + queue_delayed_work(mdp_pipe_ctrl_wq, + &mdp_pipe_ctrl_worker, + mdp_timer_duration); + } + } else { + down(&mdp_pipe_ctrl_mutex); + /* checking all blocks power state */ + for (i = 0; i < MDP_MAX_BLOCK; i++) { + if (mdp_block_power_cnt[i] > 0) + mdp_all_blocks_off = FALSE; + } + + /* + * find out whether a delayable work item is currently + * pending + */ + + if (delayed_work_pending(&mdp_pipe_ctrl_worker)) { + /* + * try to cancel the current work if it fails to + * stop (which means del_timer can't delete it + * from the list, it's about to expire and run), + * we have to let it run. queue_delayed_work won't + * accept the next job which is same as + * queue_delayed_work(mdp_timer_duration = 0) + */ + cancel_delayed_work(&mdp_pipe_ctrl_worker); + } + + if ((mdp_all_blocks_off) && (mdp_current_clk_on)) { + if (block == MDP_MASTER_BLOCK) { + mdp_current_clk_on = FALSE; + /* turn off MDP clks */ + if (mdp_clk != NULL) { + clk_disable(mdp_clk); + MSM_FB_DEBUG("MDP CLK OFF\n"); + } + if (mdp_pclk != NULL) { + clk_disable(mdp_pclk); + MSM_FB_DEBUG("MDP PCLK OFF\n"); + } + } else { + /* send workqueue to turn off mdp power */ + queue_delayed_work(mdp_pipe_ctrl_wq, + &mdp_pipe_ctrl_worker, + mdp_timer_duration); + } + } else if ((!mdp_all_blocks_off) && (!mdp_current_clk_on)) { + mdp_current_clk_on = TRUE; + /* turn on MDP clks */ + if (mdp_clk != NULL) { + clk_enable(mdp_clk); + MSM_FB_DEBUG("MDP CLK ON\n"); + } + if (mdp_pclk != NULL) { + clk_enable(mdp_pclk); + MSM_FB_DEBUG("MDP PCLK ON\n"); + } + } + up(&mdp_pipe_ctrl_mutex); + } +} + +#ifndef CONFIG_FB_MSM_MDP40 +irqreturn_t mdp_isr(int irq, void *ptr) +{ + uint32 mdp_interrupt = 0; + struct mdp_dma_data *dma; + + mdp_is_in_isr = TRUE; + do { + mdp_interrupt = inp32(MDP_INTR_STATUS); + outp32(MDP_INTR_CLEAR, mdp_interrupt); + + mdp_interrupt &= mdp_intr_mask; + + if (mdp_interrupt & TV_ENC_UNDERRUN) { + mdp_interrupt &= ~(TV_ENC_UNDERRUN); + mdp_tv_underflow_cnt++; + } + + if (!mdp_interrupt) + break; + + /* DMA3 TV-Out Start */ + if (mdp_interrupt & TV_OUT_DMA3_START) { + /* let's disable TV out interrupt */ + mdp_intr_mask &= ~TV_OUT_DMA3_START; + outp32(MDP_INTR_ENABLE, mdp_intr_mask); + + dma = &dma3_data; + if (dma->waiting) { + dma->waiting = FALSE; + complete(&dma->comp); + } + } +#ifndef CONFIG_FB_MSM_MDP22 + if (mdp_interrupt & MDP_HIST_DONE) { + outp32(MDP_BASE + 0x94018, 0x3); + outp32(MDP_INTR_CLEAR, MDP_HIST_DONE); + if (mdp_hist.r) + memcpy(mdp_hist.r, MDP_BASE + 0x94100, + mdp_hist.bin_cnt*4); + if (mdp_hist.g) + memcpy(mdp_hist.g, MDP_BASE + 0x94200, + mdp_hist.bin_cnt*4); + if (mdp_hist.b) + memcpy(mdp_hist.b, MDP_BASE + 0x94300, + mdp_hist.bin_cnt*4); + complete(&mdp_hist_comp); + } + + /* LCDC UnderFlow */ + if (mdp_interrupt & LCDC_UNDERFLOW) { + mdp_lcdc_underflow_cnt++; + } + /* LCDC Frame Start */ + if (mdp_interrupt & LCDC_FRAME_START) { + /* let's disable LCDC interrupt */ + mdp_intr_mask &= ~LCDC_FRAME_START; + outp32(MDP_INTR_ENABLE, mdp_intr_mask); + + dma = &dma2_data; + if (dma->waiting) { + dma->waiting = FALSE; + complete(&dma->comp); + } + } + + /* DMA2 LCD-Out Complete */ + if (mdp_interrupt & MDP_DMA_S_DONE) { + dma = &dma_s_data; + dma->busy = FALSE; + mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF, + TRUE); + complete(&dma->comp); + } +#endif + + /* DMA2 LCD-Out Complete */ + if (mdp_interrupt & MDP_DMA_P_DONE) { + struct timeval now; + ktime_t now_k; + + now_k = ktime_get_real(); + mdp_dma2_last_update_time.tv.sec = + now_k.tv.sec - mdp_dma2_last_update_time.tv.sec; + mdp_dma2_last_update_time.tv.nsec = + now_k.tv.nsec - mdp_dma2_last_update_time.tv.nsec; + + if (mdp_debug[MDP_DMA2_BLOCK]) { + jiffies_to_timeval(jiffies, &now); + mdp_dma2_timeval.tv_usec = + now.tv_usec - mdp_dma2_timeval.tv_usec; + } + + dma = &dma2_data; + dma->busy = FALSE; + mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, + TRUE); + complete(&dma->comp); + } + /* PPP Complete */ + if (mdp_interrupt & MDP_PPP_DONE) { +#ifdef CONFIG_MDP_PPP_ASYNC_OP + mdp_ppp_djob_done(); +#else + mdp_pipe_ctrl(MDP_PPP_BLOCK, + MDP_BLOCK_POWER_OFF, TRUE); + if (mdp_ppp_waiting) { + mdp_ppp_waiting = FALSE; + complete(&mdp_ppp_comp); + } +#endif + } + } while (1); + + mdp_is_in_isr = FALSE; + + return IRQ_HANDLED; +} +#endif + +static void mdp_drv_init(void) +{ + int i; + + for (i = 0; i < MDP_MAX_BLOCK; i++) { + mdp_debug[i] = 0; + } + + /* initialize spin lock and workqueue */ + spin_lock_init(&mdp_spin_lock); + mdp_dma_wq = create_singlethread_workqueue("mdp_dma_wq"); + mdp_vsync_wq = create_singlethread_workqueue("mdp_vsync_wq"); + mdp_pipe_ctrl_wq = create_singlethread_workqueue("mdp_pipe_ctrl_wq"); + INIT_DELAYED_WORK(&mdp_pipe_ctrl_worker, + mdp_pipe_ctrl_workqueue_handler); +#ifdef CONFIG_MDP_PPP_ASYNC_OP + mdp_ppp_dq_init(); +#endif + + /* initialize semaphore */ + init_completion(&mdp_ppp_comp); + init_MUTEX(&mdp_ppp_mutex); + init_MUTEX(&mdp_pipe_ctrl_mutex); + + dma2_data.busy = FALSE; + dma2_data.waiting = FALSE; + init_completion(&dma2_data.comp); + init_MUTEX(&dma2_data.mutex); + mutex_init(&dma2_data.ov_mutex); + + dma3_data.busy = FALSE; + dma3_data.waiting = FALSE; + init_completion(&dma3_data.comp); + init_MUTEX(&dma3_data.mutex); + + dma_s_data.busy = FALSE; + dma_s_data.waiting = FALSE; + init_completion(&dma_s_data.comp); + init_MUTEX(&dma_s_data.mutex); + + dma_e_data.busy = FALSE; + dma_e_data.waiting = FALSE; + init_completion(&dma_e_data.comp); + +#ifndef CONFIG_FB_MSM_MDP22 + init_completion(&mdp_hist_comp); +#endif + + /* initializing mdp power block counter to 0 */ + for (i = 0; i < MDP_MAX_BLOCK; i++) { + mdp_block_power_cnt[i] = 0; + } + +#ifdef MSM_FB_ENABLE_DBGFS + { + struct dentry *root; + char sub_name[] = "mdp"; + + root = msm_fb_get_debugfs_root(); + if (root != NULL) { + mdp_dir = debugfs_create_dir(sub_name, root); + + if (mdp_dir) { + msm_fb_debugfs_file_create(mdp_dir, + "dma2_update_time_in_usec", + (u32 *) &mdp_dma2_update_time_in_usec); + msm_fb_debugfs_file_create(mdp_dir, + "vs_rdcnt_slow", + (u32 *) &mdp_lcd_rd_cnt_offset_slow); + msm_fb_debugfs_file_create(mdp_dir, + "vs_rdcnt_fast", + (u32 *) &mdp_lcd_rd_cnt_offset_fast); + msm_fb_debugfs_file_create(mdp_dir, + "mdp_usec_diff_threshold", + (u32 *) &mdp_usec_diff_threshold); + msm_fb_debugfs_file_create(mdp_dir, + "mdp_current_clk_on", + (u32 *) &mdp_current_clk_on); +#ifdef CONFIG_FB_MSM_LCDC + msm_fb_debugfs_file_create(mdp_dir, + "lcdc_start_x", + (u32 *) &first_pixel_start_x); + msm_fb_debugfs_file_create(mdp_dir, + "lcdc_start_y", + (u32 *) &first_pixel_start_y); + msm_fb_debugfs_file_create(mdp_dir, + "mdp_lcdc_pclk_clk_rate", + (u32 *) &mdp_lcdc_pclk_clk_rate); + msm_fb_debugfs_file_create(mdp_dir, + "mdp_lcdc_pad_pclk_clk_rate", + (u32 *) &mdp_lcdc_pad_pclk_clk_rate); +#endif + } + } + } +#endif +} + +static int mdp_probe(struct platform_device *pdev); +static int mdp_remove(struct platform_device *pdev); + +static struct platform_driver mdp_driver = { + .probe = mdp_probe, + .remove = mdp_remove, +#ifndef CONFIG_HAS_EARLYSUSPEND + .suspend = mdp_suspend, + .resume = NULL, +#endif + .shutdown = NULL, + .driver = { + /* + * Driver name must match the device name added in + * platform.c. + */ + .name = "mdp", + }, +}; + +static int mdp_off(struct platform_device *pdev) +{ + int ret = 0; + +#ifdef MDP_HW_VSYNC + struct msm_fb_data_type *mfd = platform_get_drvdata(pdev); +#endif + + ret = panel_next_off(pdev); + +#ifdef MDP_HW_VSYNC + mdp_hw_vsync_clk_disable(mfd); +#endif + + return ret; +} + +static int mdp_on(struct platform_device *pdev) +{ +#ifdef MDP_HW_VSYNC + struct msm_fb_data_type *mfd = platform_get_drvdata(pdev); +#endif + + int ret = 0; + +#ifdef MDP_HW_VSYNC + mdp_hw_vsync_clk_enable(mfd); +#endif + + ret = panel_next_on(pdev); + + return ret; +} + +static int mdp_irq_clk_setup(void) +{ + int ret; + +#ifdef CONFIG_FB_MSM_MDP40 + ret = request_irq(INT_MDP, mdp4_isr, IRQF_DISABLED, "MDP", 0); +#else + ret = request_irq(INT_MDP, mdp_isr, IRQF_DISABLED, "MDP", 0); +#endif + if (ret) { + printk(KERN_ERR "mdp request_irq() failed!\n"); + return ret; + } + disable_irq(INT_MDP); + + mdp_clk = clk_get(NULL, "mdp_clk"); + + if (IS_ERR(mdp_clk)) { + ret = PTR_ERR(mdp_clk); + printk(KERN_ERR "can't get mdp_clk error:%d!\n", ret); + free_irq(INT_MDP, 0); + return ret; + } + + mdp_pclk = clk_get(NULL, "mdp_pclk"); + if (IS_ERR(mdp_pclk)) + mdp_pclk = NULL; + + +#ifdef CONFIG_FB_MSM_MDP40 + /* + * mdp_clk should greater than mdp_pclk always + */ + clk_set_rate(mdp_clk, 122880000); /* 122.88 Mhz */ + printk(KERN_INFO "mdp_clk: mdp_clk=%d mdp_pclk=%d\n", + (int)clk_get_rate(mdp_clk), (int)clk_get_rate(mdp_pclk)); +#endif + + return 0; +} + +static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; +static int pdev_list_cnt; +static int mdp_resource_initialized; +static struct msm_panel_common_pdata *mdp_pdata; + +static int mdp_probe(struct platform_device *pdev) +{ + struct platform_device *msm_fb_dev = NULL; + struct msm_fb_data_type *mfd; + struct msm_fb_panel_data *pdata = NULL; + int rc; + resource_size_t size ; +#ifdef CONFIG_FB_MSM_MDP40 + int intf, if_no; +#else + unsigned long flag; +#endif + + if ((pdev->id == 0) && (pdev->num_resources > 0)) { + mdp_pdata = pdev->dev.platform_data; + + size = resource_size(&pdev->resource[0]); + msm_mdp_base = ioremap(pdev->resource[0].start, size); + + MSM_FB_INFO("MDP HW Base phy_Address = 0x%x virt = 0x%x\n", + (int)pdev->resource[0].start, (int)msm_mdp_base); + + if (unlikely(!msm_mdp_base)) + return -ENOMEM; + + printk("irq clk setup\n"); + rc = mdp_irq_clk_setup(); + printk("irq clk setup done\n"); + if (rc) + return rc; + + /* initializing mdp hw */ +#ifdef CONFIG_FB_MSM_MDP40 + mdp4_hw_init(); +#else + mdp_hw_init(); +#endif + + mdp_resource_initialized = 1; + return 0; + } + + if (!mdp_resource_initialized) + return -EPERM; + + mfd = platform_get_drvdata(pdev); + + if (!mfd) + return -ENODEV; + + if (mfd->key != MFD_KEY) + return -EINVAL; + + if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) + return -ENOMEM; + + msm_fb_dev = platform_device_alloc("msm_fb", pdev->id); + if (!msm_fb_dev) + return -ENOMEM; + + /* link to the latest pdev */ + mfd->pdev = msm_fb_dev; + + /* add panel data */ + if (platform_device_add_data + (msm_fb_dev, pdev->dev.platform_data, + sizeof(struct msm_fb_panel_data))) { + printk(KERN_ERR "mdp_probe: platform_device_add_data failed!\n"); + rc = -ENOMEM; + goto mdp_probe_err; + } + /* data chain */ + pdata = msm_fb_dev->dev.platform_data; + pdata->on = mdp_on; + pdata->off = mdp_off; + pdata->next = pdev; + + switch (mfd->panel.type) { + case EXT_MDDI_PANEL: + case MDDI_PANEL: + case EBI2_PANEL: + INIT_WORK(&mfd->dma_update_worker, + mdp_lcd_update_workqueue_handler); + INIT_WORK(&mfd->vsync_resync_worker, + mdp_vsync_resync_workqueue_handler); + mfd->hw_refresh = FALSE; + + if (mfd->panel.type == EXT_MDDI_PANEL) { + /* 15 fps -> 66 msec */ + mfd->refresh_timer_duration = (66 * HZ / 1000); + } else { + /* 24 fps -> 42 msec */ + mfd->refresh_timer_duration = (42 * HZ / 1000); + } + +#ifdef CONFIG_FB_MSM_MDP22 + mfd->dma_fnc = mdp_dma2_update; + mfd->dma = &dma2_data; +#else + if (mfd->panel_info.pdest == DISPLAY_1) { +#ifdef CONFIG_FB_MSM_OVERLAY + mfd->dma_fnc = mdp4_mddi_overlay; +#else + mfd->dma_fnc = mdp_dma2_update; +#endif + mfd->dma = &dma2_data; + mfd->lut_update = mdp_lut_update_nonlcdc; + mfd->do_histogram = mdp_do_histogram; + } else { + mfd->dma_fnc = mdp_dma_s_update; + mfd->dma = &dma_s_data; + } +#endif + if (mdp_pdata) + mfd->vsync_gpio = mdp_pdata->gpio; + else + mfd->vsync_gpio = -1; + +#ifdef CONFIG_FB_MSM_MDP40 + if (mfd->panel.type == EBI2_PANEL) + intf = EBI2_INTF; + else + intf = MDDI_INTF; + + if (mfd->panel_info.pdest == DISPLAY_1) + if_no = PRIMARY_INTF_SEL; + else + if_no = SECONDARY_INTF_SEL; + + mdp4_display_intf_sel(if_no, intf); +#endif + mdp_config_vsync(mfd); + break; + + case HDMI_PANEL: + case LCDC_PANEL: + pdata->on = mdp_lcdc_on; + pdata->off = mdp_lcdc_off; + mfd->hw_refresh = TRUE; + mfd->cursor_update = mdp_hw_cursor_update; +#ifndef CONFIG_FB_MSM_MDP22 + mfd->lut_update = mdp_lut_update_lcdc; + mfd->do_histogram = mdp_do_histogram; +#endif +#ifdef CONFIG_FB_MSM_OVERLAY + mfd->dma_fnc = mdp4_lcdc_overlay; +#else + mfd->dma_fnc = mdp_lcdc_update; +#endif + +#ifdef CONFIG_FB_MSM_MDP40 + if (mfd->panel.type == HDMI_PANEL) { + mfd->dma = &dma_e_data; + mdp4_display_intf_sel(EXTERNAL_INTF_SEL, LCDC_RGB_INTF); + } else { + mfd->dma = &dma2_data; + mdp4_display_intf_sel(PRIMARY_INTF_SEL, LCDC_RGB_INTF); + } +#else + mfd->dma = &dma2_data; + spin_lock_irqsave(&mdp_spin_lock, flag); + mdp_intr_mask &= ~MDP_DMA_P_DONE; + outp32(MDP_INTR_ENABLE, mdp_intr_mask); + spin_unlock_irqrestore(&mdp_spin_lock, flag); +#endif + break; + + case TV_PANEL: + pdata->on = mdp_dma3_on; + pdata->off = mdp_dma3_off; + mfd->hw_refresh = TRUE; + mfd->dma_fnc = mdp_dma3_update; + mfd->dma = &dma3_data; + break; + + default: + printk(KERN_ERR "mdp_probe: unknown device type!\n"); + rc = -ENODEV; + goto mdp_probe_err; + } + + /* set driver data */ + platform_set_drvdata(msm_fb_dev, mfd); + + rc = platform_device_add(msm_fb_dev); + if (rc) { + goto mdp_probe_err; + } + + pdev_list[pdev_list_cnt++] = pdev; + return 0; + + mdp_probe_err: + platform_device_put(msm_fb_dev); + return rc; +} + +static void mdp_suspend_sub(void) +{ + /* cancel pipe ctrl worker */ + cancel_delayed_work(&mdp_pipe_ctrl_worker); + + /* for workder can't be cancelled... */ + flush_workqueue(mdp_pipe_ctrl_wq); + + /* let's wait for PPP completion */ + while (mdp_block_power_cnt[MDP_PPP_BLOCK] > 0) ; + + /* try to power down */ + mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); +} + +#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND) +static int mdp_suspend(struct platform_device *pdev, pm_message_t state) +{ + mdp_suspend_sub(); + return 0; +} +#endif + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void mdp_early_suspend(struct early_suspend *h) +{ + mdp_suspend_sub(); +} +#endif + +static int mdp_remove(struct platform_device *pdev) +{ + iounmap(msm_mdp_base); + return 0; +} + +static int mdp_register_driver(void) +{ +#ifdef CONFIG_HAS_EARLYSUSPEND + early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1; + early_suspend.suspend = mdp_early_suspend; + register_early_suspend(&early_suspend); +#endif + + return platform_driver_register(&mdp_driver); +} + +static int __init mdp_driver_init(void) +{ + int ret; + + mdp_drv_init(); + + ret = mdp_register_driver(); + if (ret) { + printk(KERN_ERR "mdp_register_driver() failed!\n"); + return ret; + } + +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_FB_MSM_MDP40) + mdp4_debugfs_init(); +#endif + + return 0; + +} + +module_init(mdp_driver_init); diff --git a/drivers/staging/msm/mdp.h b/drivers/staging/msm/mdp.h new file mode 100644 index 000000000000..0a5d6ac386ac --- /dev/null +++ b/drivers/staging/msm/mdp.h @@ -0,0 +1,695 @@ +/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MDP_H +#define MDP_H + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/fb.h> +#include <linux/hrtimer.h> +#include "msm_mdp.h" + +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> + +#include "msm_fb_panel.h" + +#ifdef CONFIG_MDP_PPP_ASYNC_OP +#include "mdp_ppp_dq.h" +#endif + +#ifdef BIT +#undef BIT +#endif + +#define BIT(x) (1<<(x)) + +#define MDPOP_NOP 0 +#define MDPOP_LR BIT(0) /* left to right flip */ +#define MDPOP_UD BIT(1) /* up and down flip */ +#define MDPOP_ROT90 BIT(2) /* rotate image to 90 degree */ +#define MDPOP_ROT180 (MDPOP_UD|MDPOP_LR) +#define MDPOP_ROT270 (MDPOP_ROT90|MDPOP_UD|MDPOP_LR) +#define MDPOP_ASCALE BIT(7) +#define MDPOP_ALPHAB BIT(8) /* enable alpha blending */ +#define MDPOP_TRANSP BIT(9) /* enable transparency */ +#define MDPOP_DITHER BIT(10) /* enable dither */ +#define MDPOP_SHARPENING BIT(11) /* enable sharpening */ +#define MDPOP_BLUR BIT(12) /* enable blur */ +#define MDPOP_FG_PM_ALPHA BIT(13) + +struct mdp_table_entry { + uint32_t reg; + uint32_t val; +}; + +extern struct mdp_ccs mdp_ccs_yuv2rgb ; +extern struct mdp_ccs mdp_ccs_rgb2yuv ; + +/* + * MDP Image Structure + */ +typedef struct mdpImg_ { + uint32 imgType; /* Image type */ + uint32 *bmy_addr; /* bitmap or y addr */ + uint32 *cbcr_addr; /* cbcr addr */ + uint32 width; /* image width */ + uint32 mdpOp; /* image opertion (rotation,flip up/down, alpha/tp) */ + uint32 tpVal; /* transparency color */ + uint32 alpha; /* alpha percentage 0%(0x0) ~ 100%(0x100) */ + int sp_value; /* sharpening strength */ +} MDPIMG; + +#ifdef CONFIG_MDP_PPP_ASYNC_OP +#define MDP_OUTP(addr, data) mdp_ppp_outdw((uint32_t)(addr), \ + (uint32_t)(data)) +#else +#define MDP_OUTP(addr, data) outpdw((addr), (data)) +#endif + +#define MDP_KTIME2USEC(kt) (kt.tv.sec*1000000 + kt.tv.nsec/1000) + +#define MDP_BASE msm_mdp_base + +typedef enum { + MDP_BC_SCALE_POINT2_POINT4, + MDP_BC_SCALE_POINT4_POINT6, + MDP_BC_SCALE_POINT6_POINT8, + MDP_BC_SCALE_POINT8_1, + MDP_BC_SCALE_UP, + MDP_PR_SCALE_POINT2_POINT4, + MDP_PR_SCALE_POINT4_POINT6, + MDP_PR_SCALE_POINT6_POINT8, + MDP_PR_SCALE_POINT8_1, + MDP_PR_SCALE_UP, + MDP_SCALE_BLUR, + MDP_INIT_SCALE +} MDP_SCALE_MODE; + +typedef enum { + MDP_BLOCK_POWER_OFF, + MDP_BLOCK_POWER_ON +} MDP_BLOCK_POWER_STATE; + +typedef enum { + MDP_MASTER_BLOCK, + MDP_CMD_BLOCK, + MDP_PPP_BLOCK, + MDP_DMA2_BLOCK, + MDP_DMA3_BLOCK, + MDP_DMA_S_BLOCK, + MDP_DMA_E_BLOCK, + MDP_OVERLAY0_BLOCK, + MDP_OVERLAY1_BLOCK, + MDP_MAX_BLOCK +} MDP_BLOCK_TYPE; + +/* Let's keep Q Factor power of 2 for optimization */ +#define MDP_SCALE_Q_FACTOR 512 + +#ifdef CONFIG_FB_MSM_MDP31 +#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8) +#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8) +#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8) +#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8) +#else +#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4) +#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4) +#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4) +#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4) +#endif + +/* SHIM Q Factor */ +#define PHI_Q_FACTOR 29 +#define PQF_PLUS_5 (PHI_Q_FACTOR + 5) /* due to 32 phases */ +#define PQF_PLUS_4 (PHI_Q_FACTOR + 4) +#define PQF_PLUS_2 (PHI_Q_FACTOR + 2) /* to get 4.0 */ +#define PQF_MINUS_2 (PHI_Q_FACTOR - 2) /* to get 0.25 */ +#define PQF_PLUS_5_PLUS_2 (PQF_PLUS_5 + 2) +#define PQF_PLUS_5_MINUS_2 (PQF_PLUS_5 - 2) + +#define MDP_CONVTP(tpVal) (((tpVal&0xF800)<<8)|((tpVal&0x7E0)<<5)|((tpVal&0x1F)<<3)) + +#define MDPOP_ROTATION (MDPOP_ROT90|MDPOP_LR|MDPOP_UD) +#define MDP_CHKBIT(val, bit) ((bit) == ((val) & (bit))) + +/* overlay interface API defines */ +typedef enum { + MORE_IBUF, + FINAL_IBUF, + COMPLETE_IBUF +} MDP_IBUF_STATE; + +struct mdp_dirty_region { + __u32 xoffset; /* source origin in the x-axis */ + __u32 yoffset; /* source origin in the y-axis */ + __u32 width; /* number of pixels in the x-axis */ + __u32 height; /* number of pixels in the y-axis */ +}; + +/* + * MDP extended data types + */ +typedef struct mdp_roi_s { + uint32 x; + uint32 y; + uint32 width; + uint32 height; + int32 lcd_x; + int32 lcd_y; + uint32 dst_width; + uint32 dst_height; +} MDP_ROI; + +typedef struct mdp_ibuf_s { + uint8 *buf; + uint32 bpp; + uint32 ibuf_type; + uint32 ibuf_width; + uint32 ibuf_height; + + MDP_ROI roi; + MDPIMG mdpImg; + + int32 dma_x; + int32 dma_y; + uint32 dma_w; + uint32 dma_h; + + uint32 vsync_enable; + uint32 visible_swapped; +} MDPIBUF; + +struct mdp_dma_data { + boolean busy; + boolean waiting; + struct mutex ov_mutex; + struct semaphore mutex; + struct completion comp; +}; + +#define MDP_CMD_DEBUG_ACCESS_BASE (MDP_BASE+0x10000) + +#define MDP_DMA2_TERM 0x1 +#define MDP_DMA3_TERM 0x2 +#define MDP_PPP_TERM 0x4 +#define MDP_DMA_S_TERM 0x8 +#ifdef CONFIG_FB_MSM_MDP40 +#define MDP_DMA_E_TERM 0x10 +#define MDP_OVERLAY0_TERM 0x20 +#define MDP_OVERLAY1_TERM 0x40 +#endif + +#define ACTIVE_START_X_EN BIT(31) +#define ACTIVE_START_Y_EN BIT(31) +#define ACTIVE_HIGH 0 +#define ACTIVE_LOW 1 +#define MDP_DMA_S_DONE BIT(2) +#define LCDC_FRAME_START BIT(15) +#define LCDC_UNDERFLOW BIT(16) + +#ifdef CONFIG_FB_MSM_MDP22 +#define MDP_DMA_P_DONE BIT(2) +#else +#define MDP_DMA_P_DONE BIT(14) +#endif + +#define MDP_PPP_DONE BIT(0) +#define TV_OUT_DMA3_DONE BIT(6) +#define TV_ENC_UNDERRUN BIT(7) +#define TV_OUT_DMA3_START BIT(13) +#define MDP_HIST_DONE BIT(20) + +#ifdef CONFIG_FB_MSM_MDP22 +#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \ + MDP_DMA_P_DONE| \ + TV_ENC_UNDERRUN) +#else +#define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \ + MDP_DMA_P_DONE| \ + MDP_DMA_S_DONE| \ + LCDC_UNDERFLOW| \ + MDP_HIST_DONE| \ + TV_ENC_UNDERRUN) +#endif + +#define MDP_TOP_LUMA 16 +#define MDP_TOP_CHROMA 0 +#define MDP_BOTTOM_LUMA 19 +#define MDP_BOTTOM_CHROMA 3 +#define MDP_LEFT_LUMA 22 +#define MDP_LEFT_CHROMA 6 +#define MDP_RIGHT_LUMA 25 +#define MDP_RIGHT_CHROMA 9 + +#define CLR_G 0x0 +#define CLR_B 0x1 +#define CLR_R 0x2 +#define CLR_ALPHA 0x3 + +#define CLR_Y CLR_G +#define CLR_CB CLR_B +#define CLR_CR CLR_R + +/* from lsb to msb */ +#define MDP_GET_PACK_PATTERN(a,x,y,z,bit) (((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z)) + +/* + * 0x0000 0x0004 0x0008 MDP sync config + */ +#ifdef CONFIG_FB_MSM_MDP22 +#define MDP_SYNCFG_HGT_LOC 22 +#define MDP_SYNCFG_VSYNC_EXT_EN BIT(21) +#define MDP_SYNCFG_VSYNC_INT_EN BIT(20) +#else +#define MDP_SYNCFG_HGT_LOC 21 +#define MDP_SYNCFG_VSYNC_EXT_EN BIT(20) +#define MDP_SYNCFG_VSYNC_INT_EN BIT(19) +#define MDP_HW_VSYNC +#endif + +/* + * 0x0018 MDP VSYNC THREASH + */ +#define MDP_PRIM_BELOW_LOC 0 +#define MDP_PRIM_ABOVE_LOC 8 + +/* + * MDP_PRIMARY_VSYNC_OUT_CTRL + * 0x0080,84,88 internal vsync pulse config + */ +#define VSYNC_PULSE_EN BIT(31) +#define VSYNC_PULSE_INV BIT(30) + +/* + * 0x008c MDP VSYNC CONTROL + */ +#define DISP0_VSYNC_MAP_VSYNC0 0 +#define DISP0_VSYNC_MAP_VSYNC1 BIT(0) +#define DISP0_VSYNC_MAP_VSYNC2 BIT(0)|BIT(1) + +#define DISP1_VSYNC_MAP_VSYNC0 0 +#define DISP1_VSYNC_MAP_VSYNC1 BIT(2) +#define DISP1_VSYNC_MAP_VSYNC2 BIT(2)|BIT(3) + +#define PRIMARY_LCD_SYNC_EN BIT(4) +#define PRIMARY_LCD_SYNC_DISABLE 0 + +#define SECONDARY_LCD_SYNC_EN BIT(5) +#define SECONDARY_LCD_SYNC_DISABLE 0 + +#define EXTERNAL_LCD_SYNC_EN BIT(6) +#define EXTERNAL_LCD_SYNC_DISABLE 0 + +/* + * 0x101f0 MDP VSYNC Threshold + */ +#define VSYNC_THRESHOLD_ABOVE_LOC 0 +#define VSYNC_THRESHOLD_BELOW_LOC 16 +#define VSYNC_ANTI_TEAR_EN BIT(31) + +/* + * 0x10004 command config + */ +#define MDP_CMD_DBGBUS_EN BIT(0) + +/* + * 0x10124 or 0x101d4PPP source config + */ +#define PPP_SRC_C0G_8BITS (BIT(1)|BIT(0)) +#define PPP_SRC_C1B_8BITS (BIT(3)|BIT(2)) +#define PPP_SRC_C2R_8BITS (BIT(5)|BIT(4)) +#define PPP_SRC_C3A_8BITS (BIT(7)|BIT(6)) + +#define PPP_SRC_C0G_6BITS BIT(1) +#define PPP_SRC_C1B_6BITS BIT(3) +#define PPP_SRC_C2R_6BITS BIT(5) + +#define PPP_SRC_C0G_5BITS BIT(0) +#define PPP_SRC_C1B_5BITS BIT(2) +#define PPP_SRC_C2R_5BITS BIT(4) + +#define PPP_SRC_C3_ALPHA_EN BIT(8) + +#define PPP_SRC_BPP_INTERLVD_1BYTES 0 +#define PPP_SRC_BPP_INTERLVD_2BYTES BIT(9) +#define PPP_SRC_BPP_INTERLVD_3BYTES BIT(10) +#define PPP_SRC_BPP_INTERLVD_4BYTES (BIT(10)|BIT(9)) + +#define PPP_SRC_BPP_ROI_ODD_X BIT(11) +#define PPP_SRC_BPP_ROI_ODD_Y BIT(12) +#define PPP_SRC_INTERLVD_2COMPONENTS BIT(13) +#define PPP_SRC_INTERLVD_3COMPONENTS BIT(14) +#define PPP_SRC_INTERLVD_4COMPONENTS (BIT(14)|BIT(13)) + +/* + * RGB666 unpack format + * TIGHT means R6+G6+B6 together + * LOOSE means R6+2 +G6+2+ B6+2 (with MSB) + * or 2+R6 +2+G6 +2+B6 (with LSB) + */ +#define PPP_SRC_UNPACK_TIGHT BIT(17) +#define PPP_SRC_UNPACK_LOOSE 0 +#define PPP_SRC_UNPACK_ALIGN_LSB 0 +#define PPP_SRC_UNPACK_ALIGN_MSB BIT(18) + +#define PPP_SRC_FETCH_PLANES_INTERLVD 0 +#define PPP_SRC_FETCH_PLANES_PSEUDOPLNR BIT(20) + +#define PPP_SRC_WMV9_MODE BIT(21) /* window media version 9 */ + +/* + * 0x10138 PPP operation config + */ +#define PPP_OP_SCALE_X_ON BIT(0) +#define PPP_OP_SCALE_Y_ON BIT(1) + +#define PPP_OP_CONVERT_RGB2YCBCR 0 +#define PPP_OP_CONVERT_YCBCR2RGB BIT(2) +#define PPP_OP_CONVERT_ON BIT(3) + +#define PPP_OP_CONVERT_MATRIX_PRIMARY 0 +#define PPP_OP_CONVERT_MATRIX_SECONDARY BIT(4) + +#define PPP_OP_LUT_C0_ON BIT(5) +#define PPP_OP_LUT_C1_ON BIT(6) +#define PPP_OP_LUT_C2_ON BIT(7) + +/* rotate or blend enable */ +#define PPP_OP_ROT_ON BIT(8) + +#define PPP_OP_ROT_90 BIT(9) +#define PPP_OP_FLIP_LR BIT(10) +#define PPP_OP_FLIP_UD BIT(11) + +#define PPP_OP_BLEND_ON BIT(12) + +#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0 +#define PPP_OP_BLEND_DSTPIXEL_ALPHA BIT(13) +#define PPP_OP_BLEND_CONSTANT_ALPHA BIT(14) +#define PPP_OP_BLEND_SRCPIXEL_TRANSP (BIT(13)|BIT(14)) + +#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0 +#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE BIT(15) + +#define PPP_OP_DITHER_EN BIT(16) + +#define PPP_OP_COLOR_SPACE_RGB 0 +#define PPP_OP_COLOR_SPACE_YCBCR BIT(17) + +#define PPP_OP_SRC_CHROMA_RGB 0 +#define PPP_OP_SRC_CHROMA_H2V1 BIT(18) +#define PPP_OP_SRC_CHROMA_H1V2 BIT(19) +#define PPP_OP_SRC_CHROMA_420 (BIT(18)|BIT(19)) +#define PPP_OP_SRC_CHROMA_COSITE 0 +#define PPP_OP_SRC_CHROMA_OFFSITE BIT(20) + +#define PPP_OP_DST_CHROMA_RGB 0 +#define PPP_OP_DST_CHROMA_H2V1 BIT(21) +#define PPP_OP_DST_CHROMA_H1V2 BIT(22) +#define PPP_OP_DST_CHROMA_420 (BIT(21)|BIT(22)) +#define PPP_OP_DST_CHROMA_COSITE 0 +#define PPP_OP_DST_CHROMA_OFFSITE BIT(23) + +#define PPP_BLEND_CALPHA_TRNASP BIT(24) + +#define PPP_OP_BG_CHROMA_RGB 0 +#define PPP_OP_BG_CHROMA_H2V1 BIT(25) +#define PPP_OP_BG_CHROMA_H1V2 BIT(26) +#define PPP_OP_BG_CHROMA_420 BIT(25)|BIT(26) +#define PPP_OP_BG_CHROMA_SITE_COSITE 0 +#define PPP_OP_BG_CHROMA_SITE_OFFSITE BIT(27) +#define PPP_OP_DEINT_EN BIT(29) + +#define PPP_BLEND_BG_USE_ALPHA_SEL (1 << 0) +#define PPP_BLEND_BG_ALPHA_REVERSE (1 << 3) +#define PPP_BLEND_BG_SRCPIXEL_ALPHA (0 << 1) +#define PPP_BLEND_BG_DSTPIXEL_ALPHA (1 << 1) +#define PPP_BLEND_BG_CONSTANT_ALPHA (2 << 1) +#define PPP_BLEND_BG_CONST_ALPHA_VAL(x) ((x) << 24) + +#define PPP_OP_DST_RGB 0 +#define PPP_OP_DST_YCBCR BIT(30) +/* + * 0x10150 PPP destination config + */ +#define PPP_DST_C0G_8BIT (BIT(0)|BIT(1)) +#define PPP_DST_C1B_8BIT (BIT(3)|BIT(2)) +#define PPP_DST_C2R_8BIT (BIT(5)|BIT(4)) +#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6)) + +#define PPP_DST_C0G_6BIT BIT(1) +#define PPP_DST_C1B_6BIT BIT(3) +#define PPP_DST_C2R_6BIT BIT(5) + +#define PPP_DST_C0G_5BIT BIT(0) +#define PPP_DST_C1B_5BIT BIT(2) +#define PPP_DST_C2R_5BIT BIT(4) + +#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6)) +#define PPP_DST_C3ALPHA_EN BIT(8) + +#define PPP_DST_PACKET_CNT_INTERLVD_2ELEM BIT(9) +#define PPP_DST_PACKET_CNT_INTERLVD_3ELEM BIT(10) +#define PPP_DST_PACKET_CNT_INTERLVD_4ELEM (BIT(10)|BIT(9)) +#define PPP_DST_PACKET_CNT_INTERLVD_6ELEM (BIT(11)|BIT(9)) + +#define PPP_DST_PACK_LOOSE 0 +#define PPP_DST_PACK_TIGHT BIT(13) +#define PPP_DST_PACK_ALIGN_LSB 0 +#define PPP_DST_PACK_ALIGN_MSB BIT(14) + +#define PPP_DST_OUT_SEL_AXI 0 +#define PPP_DST_OUT_SEL_MDDI BIT(15) + +#define PPP_DST_BPP_2BYTES BIT(16) +#define PPP_DST_BPP_3BYTES BIT(17) +#define PPP_DST_BPP_4BYTES (BIT(17)|BIT(16)) + +#define PPP_DST_PLANE_INTERLVD 0 +#define PPP_DST_PLANE_PLANAR BIT(18) +#define PPP_DST_PLANE_PSEUDOPLN BIT(19) + +#define PPP_DST_TO_TV BIT(20) + +#define PPP_DST_MDDI_PRIMARY 0 +#define PPP_DST_MDDI_SECONDARY BIT(21) +#define PPP_DST_MDDI_EXTERNAL BIT(22) + +/* + * 0x10180 DMA config + */ +#define DMA_DSTC0G_8BITS (BIT(1)|BIT(0)) +#define DMA_DSTC1B_8BITS (BIT(3)|BIT(2)) +#define DMA_DSTC2R_8BITS (BIT(5)|BIT(4)) + +#define DMA_DSTC0G_6BITS BIT(1) +#define DMA_DSTC1B_6BITS BIT(3) +#define DMA_DSTC2R_6BITS BIT(5) + +#define DMA_DSTC0G_5BITS BIT(0) +#define DMA_DSTC1B_5BITS BIT(2) +#define DMA_DSTC2R_5BITS BIT(4) + +#define DMA_PACK_TIGHT BIT(6) +#define DMA_PACK_LOOSE 0 +#define DMA_PACK_ALIGN_LSB 0 +/* + * use DMA_PACK_ALIGN_MSB if the upper 6 bits from 8 bits output + * from LCDC block maps into 6 pins out to the panel + */ +#define DMA_PACK_ALIGN_MSB BIT(7) +#define DMA_PACK_PATTERN_RGB \ + (MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8) +#define DMA_PACK_PATTERN_BGR \ + (MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 2)<<8) +#define DMA_OUT_SEL_AHB 0 +#define DMA_OUT_SEL_LCDC BIT(20) +#define DMA_IBUF_FORMAT_RGB888 0 +#define DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888 BIT(26) + +#ifdef CONFIG_FB_MSM_MDP22 +#define DMA_OUT_SEL_MDDI BIT(14) +#define DMA_AHBM_LCD_SEL_PRIMARY 0 +#define DMA_AHBM_LCD_SEL_SECONDARY BIT(15) +#define DMA_IBUF_C3ALPHA_EN BIT(16) +#define DMA_DITHER_EN BIT(17) +#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0 +#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY BIT(18) +#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL BIT(19) +#define DMA_IBUF_FORMAT_RGB565 BIT(20) +#define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0 +#define DMA_IBUF_NONCONTIGUOUS BIT(21) +#else +#define DMA_OUT_SEL_MDDI BIT(19) +#define DMA_AHBM_LCD_SEL_PRIMARY 0 +#define DMA_AHBM_LCD_SEL_SECONDARY 0 +#define DMA_IBUF_C3ALPHA_EN 0 +#define DMA_DITHER_EN BIT(24) +#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0 +#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY 0 +#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL 0 +#define DMA_IBUF_FORMAT_RGB565 BIT(25) +#define DMA_IBUF_NONCONTIGUOUS 0 +#endif + +/* + * MDDI Register + */ +#define MDDI_VDO_PACKET_DESC 0x5666 + +#ifdef CONFIG_FB_MSM_MDP40 +#define MDP_INTR_ENABLE (msm_mdp_base + 0x0050) +#define MDP_INTR_STATUS (msm_mdp_base + 0x0054) +#define MDP_INTR_CLEAR (msm_mdp_base + 0x0058) +#define MDP_EBI2_LCD0 (msm_mdp_base + 0x0060) +#define MDP_EBI2_LCD1 (msm_mdp_base + 0x0064) +#define MDP_EBI2_PORTMAP_MODE (msm_mdp_base + 0x0070) + +#define MDP_DMA_P_HIST_INTR_STATUS (msm_mdp_base + 0x95014) +#define MDP_DMA_P_HIST_INTR_CLEAR (msm_mdp_base + 0x95018) +#define MDP_DMA_P_HIST_INTR_ENABLE (msm_mdp_base + 0x9501C) +#else +#define MDP_INTR_ENABLE (msm_mdp_base + 0x0020) +#define MDP_INTR_STATUS (msm_mdp_base + 0x0024) +#define MDP_INTR_CLEAR (msm_mdp_base + 0x0028) +#define MDP_EBI2_LCD0 (msm_mdp_base + 0x003c) +#define MDP_EBI2_LCD1 (msm_mdp_base + 0x0040) +#define MDP_EBI2_PORTMAP_MODE (msm_mdp_base + 0x005c) +#endif + +#define MDP_FULL_BYPASS_WORD43 (msm_mdp_base + 0x101ac) + +#define MDP_CSC_PFMVn(n) (msm_mdp_base + 0x40400 + 4 * (n)) +#define MDP_CSC_PRMVn(n) (msm_mdp_base + 0x40440 + 4 * (n)) +#define MDP_CSC_PRE_BV1n(n) (msm_mdp_base + 0x40500 + 4 * (n)) +#define MDP_CSC_PRE_BV2n(n) (msm_mdp_base + 0x40540 + 4 * (n)) +#define MDP_CSC_POST_BV1n(n) (msm_mdp_base + 0x40580 + 4 * (n)) +#define MDP_CSC_POST_BV2n(n) (msm_mdp_base + 0x405c0 + 4 * (n)) + +#ifdef CONFIG_FB_MSM_MDP31 +#define MDP_CSC_PRE_LV1n(n) (msm_mdp_base + 0x40600 + 4 * (n)) +#define MDP_CSC_PRE_LV2n(n) (msm_mdp_base + 0x40640 + 4 * (n)) +#define MDP_CSC_POST_LV1n(n) (msm_mdp_base + 0x40680 + 4 * (n)) +#define MDP_CSC_POST_LV2n(n) (msm_mdp_base + 0x406c0 + 4 * (n)) +#define MDP_PPP_SCALE_COEFF_LSBn(n) (msm_mdp_base + 0x50400 + 8 * (n)) +#define MDP_PPP_SCALE_COEFF_MSBn(n) (msm_mdp_base + 0x50404 + 8 * (n)) + +#define SCALE_D0_SET 0 +#define SCALE_D1_SET BIT(0) +#define SCALE_D2_SET BIT(1) +#define SCALE_U1_SET (BIT(0)|BIT(1)) + +#else +#define MDP_CSC_PRE_LV1n(n) (msm_mdp_base + 0x40580 + 4 * (n)) +#endif + +#define MDP_CURSOR_WIDTH 64 +#define MDP_CURSOR_HEIGHT 64 +#define MDP_CURSOR_SIZE (MDP_CURSOR_WIDTH*MDP_CURSOR_WIDTH*4) + +#define MDP_DMA_P_LUT_C0_EN BIT(0) +#define MDP_DMA_P_LUT_C1_EN BIT(1) +#define MDP_DMA_P_LUT_C2_EN BIT(2) +#define MDP_DMA_P_LUT_POST BIT(4) + +void mdp_hw_init(void); +int mdp_ppp_pipe_wait(void); +void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd); +void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state, + boolean isr); +void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty, + boolean sync); +void mdp_dma_pan_update(struct fb_info *info); +void mdp_refresh_screen(unsigned long data); +int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req, + struct file **pp_src, struct file **pp_dest); +void mdp_lcd_update_workqueue_handler(struct work_struct *work); +void mdp_vsync_resync_workqueue_handler(struct work_struct *work); +void mdp_dma2_update(struct msm_fb_data_type *mfd); +void mdp_config_vsync(struct msm_fb_data_type *); +uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd); +enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht); +void mdp_set_scale(MDPIBUF *iBuf, + uint32 dst_roi_width, + uint32 dst_roi_height, + boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr); +void mdp_init_scale_table(void); +void mdp_adjust_start_addr(uint8 **src0, + uint8 **src1, + int v_slice, + int h_slice, + int x, + int y, + uint32 width, + uint32 height, int bpp, MDPIBUF *iBuf, int layer); +void mdp_set_blend_attr(MDPIBUF *iBuf, + uint32 *alpha, + uint32 *tpVal, + uint32 perPixelAlpha, uint32 *pppop_reg_ptr); + +int mdp_dma3_on(struct platform_device *pdev); +int mdp_dma3_off(struct platform_device *pdev); +void mdp_dma3_update(struct msm_fb_data_type *mfd); + +int mdp_lcdc_on(struct platform_device *pdev); +int mdp_lcdc_off(struct platform_device *pdev); +void mdp_lcdc_update(struct msm_fb_data_type *mfd); +int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor); +void mdp_enable_irq(uint32 term); +void mdp_disable_irq(uint32 term); +void mdp_disable_irq_nolock(uint32 term); +uint32_t mdp_get_bytes_per_pixel(uint32_t format); + +#ifdef MDP_HW_VSYNC +void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd); +void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd); +#endif + +void mdp_dma_s_update(struct msm_fb_data_type *mfd); + +/* Added to support flipping */ +void mdp_set_offset_info(struct fb_info *info, uint32 address, uint32 interval); + +int get_gem_img(struct mdp_img *img, unsigned long *start, + unsigned long *len); +int get_img(struct mdp_img *img, struct fb_info *info, + unsigned long *start, unsigned long *len, + struct file **pp_file); + + +/*int get_img(struct msmfb_data *img, struct fb_info *info, + unsigned long *start, unsigned long *len, struct file **pp_file);*/ +#endif /* MDP_H */ diff --git a/drivers/staging/msm/mdp4.h b/drivers/staging/msm/mdp4.h new file mode 100644 index 000000000000..26ec8f12cf64 --- /dev/null +++ b/drivers/staging/msm/mdp4.h @@ -0,0 +1,352 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MDP4_H +#define MDP4_H + +extern struct mdp_dma_data dma2_data; +extern struct mdp_dma_data dma_s_data; +extern struct mdp_dma_data dma_e_data; +extern struct mdp_histogram mdp_hist; +extern struct completion mdp_hist_comp; +extern boolean mdp_is_in_isr; +extern uint32 mdp_intr_mask; +extern spinlock_t mdp_spin_lock; + + +#define MDP4_NONBLOCKING /* enable non blocking ioctl */ + +#define MDP4_OVERLAYPROC0_BASE 0x10000 +#define MDP4_OVERLAYPROC1_BASE 0x18000 + +#define MDP4_VIDEO_BASE 0x20000 +#define MDP4_VIDEO_OFF 0x10000 + +#define MDP4_RGB_BASE 0x40000 +#define MDP4_RGB_OFF 0x10000 + +enum { /* display */ + PRIMARY_INTF_SEL, + SECONDARY_INTF_SEL, + EXTERNAL_INTF_SEL +}; + +enum { + LCDC_RGB_INTF, + DTV_INTF = LCDC_RGB_INTF, + MDDI_LCDC_INTF, + MDDI_INTF, + EBI2_INTF +}; + +enum { + MDDI_PRIMARY_SET, + MDDI_SECONDARY_SET, + MDDI_EXTERNAL_SET +}; + +enum { + EBI2_LCD0, + EBI2_LCD1 +}; + +enum { + OVERLAY_MODE_NONE, + OVERLAY_MODE_BLT +}; + +enum { + OVERLAY_REFRESH_ON_DEMAND, + OVERLAY_REFRESH_VSYNC, + OVERLAY_REFRESH_VSYNC_HALF, + OVERLAY_REFRESH_VSYNC_QUARTER +}; + +enum { + OVERLAY_FRAMEBUF, + OVERLAY_DIRECTOUT +}; + +/* system interrupts */ +#define INTR_OVERLAY0_DONE BIT(0) +#define INTR_OVERLAY1_DONE BIT(1) +#define INTR_DMA_S_DONE BIT(2) +#define INTR_DMA_E_DONE BIT(3) +#define INTR_DMA_P_DONE BIT(4) +#define INTR_VG1_HISTOGRAM BIT(5) +#define INTR_VG2_HISTOGRAM BIT(6) +#define INTR_PRIMARY_VSYNC BIT(7) +#define INTR_PRIMARY_INTF_UDERRUN BIT(8) +#define INTR_EXTERNAL_VSYNC BIT(9) +#define INTR_EXTERNAL_INTF_UDERRUN BIT(10) +#define INTR_DMA_P_HISTOGRAM BIT(17) + +/* histogram interrupts */ +#define INTR_HIST_DONE BIT(0) +#define INTR_HIST_RESET_SEQ_DONE BIT(1) + + +#ifdef CONFIG_FB_MSM_OVERLAY +#define MDP4_ANY_INTR_MASK (INTR_OVERLAY0_DONE) +#else +#define MDP4_ANY_INTR_MASK (INTR_DMA_P_DONE) +#endif + +enum { + OVERLAY_PIPE_RGB1, + OVERLAY_PIPE_RGB2, +}; + +enum { + OVERLAY_PIPE_VG1, /* video/graphic */ + OVERLAY_PIPE_VG2 +}; + +enum { + OVERLAY_TYPE_RGB, + OVERLAY_TYPE_VG /* video/graphic */ +}; + +enum { + MDP4_MIXER0, + MDP4_MIXER1 +}; + +#define MDP4_MAX_MIXER 2 + +enum { + OVERLAY_PLANE_INTERLEAVED, + OVERLAY_PLANE_PLANAR, + OVERLAY_PLANE_PSEUDO_PLANAR +}; + +enum { + MDP4_MIXER_STAGE_UNUNSED, /* pipe not used */ + MDP4_MIXER_STAGE_BASE, + MDP4_MIXER_STAGE0, /* zorder 0 */ + MDP4_MIXER_STAGE1, /* zorder 1 */ + MDP4_MIXER_STAGE2 /* zorder 2 */ +}; + +#define MDP4_MAX_STAGE 4 + +enum { + MDP4_FRAME_FORMAT_LINEAR, + MDP4_FRAME_FORMAT_ARGB_TILE, + MDP4_FRAME_FORMAT_VIDEO_SUPERTILE +}; + +enum { + MDP4_CHROMA_RGB, + MDP4_CHROMA_H2V1, + MDP4_CHROMA_H1V2, + MDP4_CHROMA_420 +}; + +#define MDP4_BLEND_BG_TRANSP_EN BIT(9) +#define MDP4_BLEND_FG_TRANSP_EN BIT(8) +#define MDP4_BLEND_BG_MOD_ALPHA BIT(7) +#define MDP4_BLEND_BG_INV_ALPHA BIT(6) +#define MDP4_BLEND_BG_ALPHA_FG_CONST (0 << 4) +#define MDP4_BLEND_BG_ALPHA_BG_CONST (1 << 4) +#define MDP4_BLEND_BG_ALPHA_FG_PIXEL (2 << 4) +#define MDP4_BLEND_BG_ALPHA_BG_PIXEL (3 << 4) +#define MDP4_BLEND_FG_MOD_ALPHA BIT(3) +#define MDP4_BLEND_FG_INV_ALPHA BIT(2) +#define MDP4_BLEND_FG_ALPHA_FG_CONST (0 << 0) +#define MDP4_BLEND_FG_ALPHA_BG_CONST (1 << 0) +#define MDP4_BLEND_FG_ALPHA_FG_PIXEL (2 << 0) +#define MDP4_BLEND_FG_ALPHA_BG_PIXEL (3 << 0) + +#define MDP4_FORMAT_SOLID_FILL BIT(22) +#define MDP4_FORMAT_UNPACK_ALIGN_MSB BIT(18) +#define MDP4_FORMAT_UNPACK_TIGHT BIT(17) +#define MDP4_FORMAT_90_ROTATED BIT(12) +#define MDP4_FORMAT_ALPHA_ENABLE BIT(8) + +#define MDP4_OP_DEINT_ODD_REF BIT(19) +#define MDP4_OP_IGC_LUT_EN BIT(16) +#define MDP4_OP_DITHER_EN BIT(15) +#define MDP4_OP_FLIP_UD BIT(14) +#define MDP4_OP_FLIP_LR BIT(13) +#define MDP4_OP_CSC_EN BIT(11) +#define MDP4_OP_SRC_DATA_YCBCR BIT(9) +#define MDP4_OP_SCALEY_FIR (0 << 4) +#define MDP4_OP_SCALEY_MN_PHASE (1 << 4) +#define MDP4_OP_SCALEY_PIXEL_RPT (2 << 4) +#define MDP4_OP_SCALEX_FIR (0 << 2) +#define MDP4_OP_SCALEX_MN_PHASE (1 << 2) +#define MDP4_OP_SCALEX_PIXEL_RPT (2 << 2) +#define MDP4_OP_SCALEY_EN BIT(1) +#define MDP4_OP_SCALEX_EN BIT(0) + +#define MDP4_PIPE_PER_MIXER 2 + +#define MDP4_MAX_PLANE 4 + +#define MDP4_MAX_VIDEO_PIPE 2 +#define MDP4_MAX_RGB_PIPE 2 +#define MDP4_MAX_OVERLAY_PIPE 16 + + +struct mdp4_overlay_pipe { + uint32 pipe_type; /* rgb, video/graphic */ + uint32 pipe_num; + uint32 pipe_ndx; + uint32 mixer_num; /* which mixer used */ + uint32 mixer_stage; /* which stage of mixer used */ + uint32 src_format; + uint32 src_width; /* source img width */ + uint32 src_height; /* source img height */ + uint32 src_w; /* roi */ + uint32 src_h; /* roi */ + uint32 src_x; /* roi */ + uint32 src_y; /* roi */ + uint32 dst_w; /* roi */ + uint32 dst_h; /* roi */ + uint32 dst_x; /* roi */ + uint32 dst_y; /* roi */ + uint32 op_mode; + uint32 transp; + uint32 blend_op; + uint32 phasex_step; + uint32 phasey_step; + uint32 alpha; + uint32 is_fg; /* control alpha & color key */ + uint32 srcp0_addr; /* interleave, luma */ + uint32 srcp0_ystride; + uint32 srcp1_addr; /* pseudoplanar, chroma plane */ + uint32 srcp1_ystride; + uint32 srcp2_addr; /* planar color 2*/ + uint32 srcp2_ystride; + uint32 srcp3_addr; /* alpha/color 3 */ + uint32 srcp3_ystride; + uint32 fetch_plane; + uint32 frame_format; /* video */ + uint32 chroma_site; /* video */ + uint32 chroma_sample; /* video */ + uint32 solid_fill; + uint32 vc1_reduce; /* video */ + uint32 fatch_planes; /* video */ + uint32 unpack_align_msb;/* 0 to LSB, 1 to MSB */ + uint32 unpack_tight;/* 0 for loose, 1 for tight */ + uint32 unpack_count;/* 0 = 1 component, 1 = 2 component ... */ + uint32 rotated_90; /* has been rotated 90 degree */ + uint32 bpp; /* byte per pixel */ + uint32 alpha_enable;/* source has alpha */ + /* + * number of bits for source component, + * 0 = 1 bit, 1 = 2 bits, 2 = 6 bits, 3 = 8 bits + */ + uint32 a_bit; /* component 3, alpha */ + uint32 r_bit; /* component 2, R_Cr */ + uint32 b_bit; /* component 1, B_Cb */ + uint32 g_bit; /* component 0, G_lumz */ + /* + * unpack pattern + * A = C3, R = C2, B = C1, G = C0 + */ + uint32 element3; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */ + uint32 element2; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */ + uint32 element1; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */ + uint32 element0; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */ + struct completion comp; + struct mdp_overlay req_data; +}; + +void mdp4_sw_reset(unsigned long bits); +void mdp4_display_intf_sel(int output, unsigned long intf); +void mdp4_overlay_cfg(int layer, int blt_mode, int refresh, int direct_out); +void mdp4_ebi2_lcd_setup(int lcd, unsigned long base, int ystride); +void mdp4_mddi_setup(int which, unsigned long id); +unsigned long mdp4_display_status(void); +void mdp4_enable_clk_irq(void); +void mdp4_disable_clk_irq(void); +void mdp4_dma_p_update(struct msm_fb_data_type *mfd); +void mdp4_dma_s_update(struct msm_fb_data_type *mfd); +void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state, + boolean isr); +void mdp4_pipe_kickoff(uint32 pipe, struct msm_fb_data_type *mfd); +int mdp4_lcdc_on(struct platform_device *pdev); +int mdp4_lcdc_off(struct platform_device *pdev); +void mdp4_lcdc_update(struct msm_fb_data_type *mfd); +void mdp4_intr_clear_set(ulong clear, ulong set); +void mdp4_dma_p_cfg(void); +void mdp4_hw_init(void); +void mdp4_isr_read(int); +void mdp4_clear_lcdc(void); +void mdp4_mixer_blend_init(int mixer_num); +void mdp4_vg_qseed_init(int vg_num); +void mdp4_vg_csc_mv_setup(int vp_num); +void mdp4_vg_csc_pre_bv_setup(int vp_num); +void mdp4_vg_csc_post_bv_setup(int vp_num); +void mdp4_vg_csc_pre_lv_setup(int vp_num); +void mdp4_vg_csc_post_lv_setup(int vp_num); +irqreturn_t mdp4_isr(int irq, void *ptr); +void mdp4_overlay_format_to_pipe(uint32 format, struct mdp4_overlay_pipe *pipe); +uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe); +uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe); +uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe); +void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd); +void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe); +void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all); +void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe); +void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe); +void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe); +int mdp4_mixer_stage_can_run(struct mdp4_overlay_pipe *pipe); +void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe); +void mdp4_mddi_overlay(struct msm_fb_data_type *mfd); +int mdp4_overlay_format2type(uint32 format); +int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe); +int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req); +int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req); +int mdp4_overlay_unset(struct fb_info *info, int ndx); +int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req, + struct file **pp_src_file); +struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void); +void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe); +void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc); +void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe); +int mdp4_overlay_active(int mixer); +void mdp4_overlay0_done_lcdc(void); +void mdp4_overlay0_done_mddi(void); +void mdp4_mddi_overlay_restore(void); +void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd, + struct mdp4_overlay_pipe *pipe); +void mdp4_rgb_igc_lut_setup(int num); +void mdp4_vg_igc_lut_setup(int num); +void mdp4_mixer_gc_lut_setup(int mixer_num); + +#ifdef CONFIG_DEBUG_FS +int mdp4_debugfs_init(void); +#endif + +int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req, + struct file **pp_src_file, struct file **pp_dst_file); + +#endif /* MDP_H */ diff --git a/drivers/staging/msm/mdp4_debugfs.c b/drivers/staging/msm/mdp4_debugfs.c new file mode 100644 index 000000000000..844d46775ecd --- /dev/null +++ b/drivers/staging/msm/mdp4_debugfs.c @@ -0,0 +1,181 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/hrtimer.h> +#include <linux/clk.h> +#include <mach/hardware.h> +#include <linux/io.h> +#include <linux/debugfs.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/uaccess.h> + +#include "mdp.h" +#include "msm_fb.h" +#include "mdp4.h" + + +#define MDP4_DEBUG_BUF 128 + + +static char mdp4_debug_buf[MDP4_DEBUG_BUF]; +static ulong mdp4_debug_offset; +static ulong mdp4_base_addr; + +static int mdp4_offset_set(void *data, u64 val) +{ + mdp4_debug_offset = (int)val; + return 0; +} + +static int mdp4_offset_get(void *data, u64 *val) +{ + *val = (u64)mdp4_debug_offset; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE( + mdp4_offset_fops, + mdp4_offset_get, + mdp4_offset_set, + "%llx\n"); + + +static int mdp4_debugfs_open(struct inode *inode, struct file *file) +{ + /* non-seekable */ + file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); + return 0; +} + +static int mdp4_debugfs_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static ssize_t mdp4_debugfs_write( + struct file *file, + const char __user *buff, + size_t count, + loff_t *ppos) +{ + int cnt; + unsigned int data; + + printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n", + __func__, (int)mdp4_debug_offset, (int)count, (int)*ppos); + + if (count > sizeof(mdp4_debug_buf)) + return -EFAULT; + + if (copy_from_user(mdp4_debug_buf, buff, count)) + return -EFAULT; + + + mdp4_debug_buf[count] = 0; /* end of string */ + + cnt = sscanf(mdp4_debug_buf, "%x", &data); + if (cnt < 1) { + printk(KERN_ERR "%s: sscanf failed cnt=%d" , __func__, cnt); + return -EINVAL; + } + + writel(&data, mdp4_base_addr + mdp4_debug_offset); + + return 0; +} + +static ssize_t mdp4_debugfs_read( + struct file *file, + char __user *buff, + size_t count, + loff_t *ppos) +{ + int len = 0; + unsigned int data; + + printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n", + __func__, (int)mdp4_debug_offset, (int)count, (int)*ppos); + + if (*ppos) + return 0; /* the end */ + + data = readl(mdp4_base_addr + mdp4_debug_offset); + + len = snprintf(mdp4_debug_buf, 4, "%x\n", data); + + if (len > 0) { + if (len > count) + len = count; + if (copy_to_user(buff, mdp4_debug_buf, len)) + return -EFAULT; + } + + printk(KERN_INFO "%s: len=%d\n", __func__, len); + + if (len < 0) + return 0; + + *ppos += len; /* increase offset */ + + return len; +} + +static const struct file_operations mdp4_debugfs_fops = { + .open = mdp4_debugfs_open, + .release = mdp4_debugfs_release, + .read = mdp4_debugfs_read, + .write = mdp4_debugfs_write, +}; + +int mdp4_debugfs_init(void) +{ + struct dentry *dent = debugfs_create_dir("mdp4", NULL); + + if (IS_ERR(dent)) { + printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n", + __FILE__, __LINE__, PTR_ERR(dent)); + return -1; + } + + if (debugfs_create_file("offset", 0644, dent, 0, &mdp4_offset_fops) + == NULL) { + printk(KERN_ERR "%s(%d): debugfs_create_file: offset fail\n", + __FILE__, __LINE__); + return -1; + } + + if (debugfs_create_file("regs", 0644, dent, 0, &mdp4_debugfs_fops) + == NULL) { + printk(KERN_ERR "%s(%d): debugfs_create_file: regs fail\n", + __FILE__, __LINE__); + return -1; + } + + mdp4_debug_offset = 0; + mdp4_base_addr = (ulong) msm_mdp_base; /* defined at msm_fb_def.h */ + + return 0; +} diff --git a/drivers/staging/msm/mdp4_overlay.c b/drivers/staging/msm/mdp4_overlay.c new file mode 100644 index 000000000000..304bb8297635 --- /dev/null +++ b/drivers/staging/msm/mdp4_overlay.c @@ -0,0 +1,1259 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/hrtimer.h> +#include <linux/clk.h> +#include <mach/hardware.h> +#include <linux/io.h> +#include <linux/debugfs.h> +#include <linux/fb.h> +#include <msm_mdp.h> +#include <linux/file.h> +#include "android_pmem.h" +#include <linux/major.h> +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/uaccess.h> +#include <linux/mutex.h> + +#include "mdp.h" +#include "msm_fb.h" +#include "mdp4.h" + + +struct mdp4_overlay_ctrl { + struct mdp4_overlay_pipe plist[MDP4_MAX_OVERLAY_PIPE]; + struct mdp4_overlay_pipe *stage[MDP4_MAX_MIXER][MDP4_MAX_STAGE]; +} mdp4_overlay_db; + +static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db; + + +void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc) +{ + uint32 dma2_cfg_reg; + + dma2_cfg_reg = DMA_DITHER_EN; + + if (mfd->fb_imgType == MDP_BGR_565) + dma2_cfg_reg |= DMA_PACK_PATTERN_BGR; + else + dma2_cfg_reg |= DMA_PACK_PATTERN_RGB; + + + if (mfd->panel_info.bpp == 18) { + dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */ + DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS; + } else if (mfd->panel_info.bpp == 16) { + dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */ + DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS; + } else { + dma2_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */ + DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS; + } + + if (lcdc) + dma2_cfg_reg |= DMA_PACK_ALIGN_MSB; + + /* dma2 config register */ + MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg); + +} + +void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe) +{ + + /* dma_p source */ + MDP_OUTP(MDP_BASE + 0x90004, + (pipe->src_height << 16 | pipe->src_width)); + MDP_OUTP(MDP_BASE + 0x90008, pipe->srcp0_addr); + MDP_OUTP(MDP_BASE + 0x9000c, pipe->srcp0_ystride); + + /* dma_p dest */ + MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x)); +} + +#define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000 +#define MDP4_VG_PHASE_STEP_SHIFT 29 + +static int mdp4_leading_0(uint32 num) +{ + uint32 bit = 0x80000000; + int i; + + for (i = 0; i < 32; i++) { + if (bit & num) + return i; + bit >>= 1; + } + + return i; +} + +static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst) +{ + uint32 val; + int n; + + n = mdp4_leading_0(src); + if (n > f_num) + n = f_num; + val = src << n; /* maximum to reduce lose of resolution */ + val /= dst; + if (n < f_num) { + n = f_num - n; + val <<= n; + } + + return val; +} + +static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe) +{ + + pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT; + pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT; + + if (pipe->dst_h && pipe->src_h != pipe->dst_h) { + if (pipe->dst_h >= pipe->src_h * 8) /* too much */ + return; + pipe->op_mode |= MDP4_OP_SCALEY_EN; + + if (pipe->pipe_type == OVERLAY_TYPE_VG) { + if (pipe->dst_h <= (pipe->src_h / 4)) + pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE; + else + pipe->op_mode |= MDP4_OP_SCALEY_FIR; + } + + pipe->phasey_step = mdp4_scale_phase_step(29, + pipe->src_h, pipe->dst_h); + } + + if (pipe->dst_w && pipe->src_w != pipe->dst_w) { + if (pipe->dst_w >= pipe->src_w * 8) /* too much */ + return; + pipe->op_mode |= MDP4_OP_SCALEX_EN; + + if (pipe->pipe_type == OVERLAY_TYPE_VG) { + if (pipe->dst_w <= (pipe->src_w / 4)) + pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE; + else + pipe->op_mode |= MDP4_OP_SCALEY_FIR; + } + + pipe->phasex_step = mdp4_scale_phase_step(29, + pipe->src_w, pipe->dst_w); + } +} + +void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe) +{ + char *rgb_base; + uint32 src_size, src_xy, dst_size, dst_xy; + uint32 format, pattern; + + rgb_base = MDP_BASE + MDP4_RGB_BASE; + rgb_base += (MDP4_RGB_OFF * pipe->pipe_num); + + src_size = ((pipe->src_h << 16) | pipe->src_w); + src_xy = ((pipe->src_y << 16) | pipe->src_x); + dst_size = ((pipe->dst_h << 16) | pipe->dst_w); + dst_xy = ((pipe->dst_y << 16) | pipe->dst_x); + + format = mdp4_overlay_format(pipe); + pattern = mdp4_overlay_unpack_pattern(pipe); + + pipe->op_mode |= MDP4_OP_IGC_LUT_EN; + + mdp4_scale_setup(pipe); + + outpdw(rgb_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */ + outpdw(rgb_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */ + outpdw(rgb_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */ + outpdw(rgb_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */ + + outpdw(rgb_base + 0x0010, pipe->srcp0_addr); + outpdw(rgb_base + 0x0040, pipe->srcp0_ystride); + + outpdw(rgb_base + 0x0050, format);/* MDP_RGB_SRC_FORMAT */ + outpdw(rgb_base + 0x0054, pattern);/* MDP_RGB_SRC_UNPACK_PATTERN */ + outpdw(rgb_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */ + outpdw(rgb_base + 0x005c, pipe->phasex_step); + outpdw(rgb_base + 0x0060, pipe->phasey_step); + + /* 16 bytes-burst x 3 req <= 48 bytes */ + outpdw(rgb_base + 0x1004, 0xc2); /* MDP_RGB_FETCH_CFG */ +} + +void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe) +{ + char *vg_base; + uint32 frame_size, src_size, src_xy, dst_size, dst_xy; + uint32 format, pattern; + + vg_base = MDP_BASE + MDP4_VIDEO_BASE; + vg_base += (MDP4_VIDEO_OFF * pipe->pipe_num); + + frame_size = ((pipe->src_height << 16) | pipe->src_width); + src_size = ((pipe->src_h << 16) | pipe->src_w); + src_xy = ((pipe->src_y << 16) | pipe->src_x); + dst_size = ((pipe->dst_h << 16) | pipe->dst_w); + dst_xy = ((pipe->dst_y << 16) | pipe->dst_x); + + format = mdp4_overlay_format(pipe); + pattern = mdp4_overlay_unpack_pattern(pipe); + + pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR | + MDP4_OP_IGC_LUT_EN); + + mdp4_scale_setup(pipe); + + outpdw(vg_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */ + outpdw(vg_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */ + outpdw(vg_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */ + outpdw(vg_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */ + outpdw(vg_base + 0x0048, frame_size); /* TILE frame size */ + + /* luma component plane */ + outpdw(vg_base + 0x0010, pipe->srcp0_addr); + + /* chroma component plane */ + outpdw(vg_base + 0x0014, pipe->srcp1_addr); + + outpdw(vg_base + 0x0040, + pipe->srcp1_ystride << 16 | pipe->srcp0_ystride); + + outpdw(vg_base + 0x0050, format); /* MDP_RGB_SRC_FORMAT */ + outpdw(vg_base + 0x0054, pattern); /* MDP_RGB_SRC_UNPACK_PATTERN */ + outpdw(vg_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */ + outpdw(vg_base + 0x005c, pipe->phasex_step); + outpdw(vg_base + 0x0060, pipe->phasey_step); + + if (pipe->op_mode & MDP4_OP_DITHER_EN) { + outpdw(vg_base + 0x0068, + pipe->r_bit << 4 | pipe->b_bit << 2 | pipe->g_bit); + } + + /* 16 bytes-burst x 3 req <= 48 bytes */ + outpdw(vg_base + 0x1004, 0xc2); /* MDP_VG_FETCH_CFG */ +} + +int mdp4_overlay_format2type(uint32 format) +{ + switch (format) { + case MDP_RGB_565: + case MDP_RGB_888: + case MDP_BGR_565: + case MDP_ARGB_8888: + case MDP_RGBA_8888: + case MDP_BGRA_8888: + return OVERLAY_TYPE_RGB; + case MDP_YCRYCB_H2V1: + case MDP_Y_CRCB_H2V1: + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V2: + case MDP_Y_CBCR_H2V2: + case MDP_Y_CBCR_H2V2_TILE: + case MDP_Y_CRCB_H2V2_TILE: + return OVERLAY_TYPE_VG; + default: + return -ERANGE; + } + +} + +#define C3_ALPHA 3 /* alpha */ +#define C2_R_Cr 2 /* R/Cr */ +#define C1_B_Cb 1 /* B/Cb */ +#define C0_G_Y 0 /* G/luma */ + +int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe) +{ + switch (pipe->src_format) { + case MDP_RGB_565: + pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; + pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; + pipe->a_bit = 0; + pipe->r_bit = 1; /* R, 5 bits */ + pipe->b_bit = 1; /* B, 5 bits */ + pipe->g_bit = 2; /* G, 6 bits */ + pipe->alpha_enable = 0; + pipe->unpack_tight = 1; + pipe->unpack_align_msb = 0; + pipe->unpack_count = 2; + pipe->element2 = C2_R_Cr; /* R */ + pipe->element1 = C0_G_Y; /* G */ + pipe->element0 = C1_B_Cb; /* B */ + pipe->bpp = 2; /* 2 bpp */ + break; + case MDP_RGB_888: + pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; + pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; + pipe->a_bit = 0; + pipe->r_bit = 3; /* R, 8 bits */ + pipe->b_bit = 3; /* B, 8 bits */ + pipe->g_bit = 3; /* G, 8 bits */ + pipe->alpha_enable = 0; + pipe->unpack_tight = 1; + pipe->unpack_align_msb = 0; + pipe->unpack_count = 2; + pipe->element2 = C2_R_Cr; /* R */ + pipe->element1 = C0_G_Y; /* G */ + pipe->element0 = C1_B_Cb; /* B */ + pipe->bpp = 3; /* 3 bpp */ + break; + case MDP_BGR_565: + pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; + pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; + pipe->a_bit = 0; + pipe->r_bit = 1; /* R, 5 bits */ + pipe->b_bit = 1; /* B, 5 bits */ + pipe->g_bit = 2; /* G, 6 bits */ + pipe->alpha_enable = 0; + pipe->unpack_tight = 1; + pipe->unpack_align_msb = 0; + pipe->unpack_count = 2; + pipe->element2 = C1_B_Cb; /* B */ + pipe->element1 = C0_G_Y; /* G */ + pipe->element0 = C2_R_Cr; /* R */ + pipe->bpp = 2; /* 2 bpp */ + break; + case MDP_ARGB_8888: + pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; + pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; + pipe->a_bit = 3; /* alpha, 4 bits */ + pipe->r_bit = 3; /* R, 8 bits */ + pipe->b_bit = 3; /* B, 8 bits */ + pipe->g_bit = 3; /* G, 8 bits */ + pipe->alpha_enable = 1; + pipe->unpack_tight = 1; + pipe->unpack_align_msb = 0; + pipe->unpack_count = 3; + pipe->element3 = C3_ALPHA; /* alpha */ + pipe->element2 = C2_R_Cr; /* R */ + pipe->element1 = C0_G_Y; /* G */ + pipe->element0 = C1_B_Cb; /* B */ + pipe->bpp = 4; /* 4 bpp */ + break; + case MDP_RGBA_8888: + pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; + pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; + pipe->a_bit = 3; /* alpha, 4 bits */ + pipe->r_bit = 3; /* R, 8 bits */ + pipe->b_bit = 3; /* B, 8 bits */ + pipe->g_bit = 3; /* G, 8 bits */ + pipe->alpha_enable = 1; + pipe->unpack_tight = 1; + pipe->unpack_align_msb = 0; + pipe->unpack_count = 3; + pipe->element3 = C2_R_Cr; /* R */ + pipe->element2 = C0_G_Y; /* G */ + pipe->element1 = C1_B_Cb; /* B */ + pipe->element0 = C3_ALPHA; /* alpha */ + pipe->bpp = 4; /* 4 bpp */ + break; + case MDP_BGRA_8888: + pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; + pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; + pipe->a_bit = 3; /* alpha, 4 bits */ + pipe->r_bit = 3; /* R, 8 bits */ + pipe->b_bit = 3; /* B, 8 bits */ + pipe->g_bit = 3; /* G, 8 bits */ + pipe->alpha_enable = 1; + pipe->unpack_tight = 1; + pipe->unpack_align_msb = 0; + pipe->unpack_count = 3; + pipe->element3 = C1_B_Cb; /* B */ + pipe->element2 = C0_G_Y; /* G */ + pipe->element1 = C2_R_Cr; /* R */ + pipe->element0 = C3_ALPHA; /* alpha */ + pipe->bpp = 4; /* 4 bpp */ + break; + case MDP_YCRYCB_H2V1: + pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; + pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; + pipe->a_bit = 0; /* alpha, 4 bits */ + pipe->r_bit = 3; /* R, 8 bits */ + pipe->b_bit = 3; /* B, 8 bits */ + pipe->g_bit = 3; /* G, 8 bits */ + pipe->alpha_enable = 0; + pipe->unpack_tight = 1; + pipe->unpack_align_msb = 0; + pipe->unpack_count = 3; + pipe->element3 = C0_G_Y; /* G */ + pipe->element2 = C2_R_Cr; /* R */ + pipe->element1 = C0_G_Y; /* G */ + pipe->element0 = C1_B_Cb; /* B */ + pipe->bpp = 2; /* 2 bpp */ + pipe->chroma_sample = MDP4_CHROMA_H2V1; + break; + case MDP_Y_CRCB_H2V1: + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V2: + case MDP_Y_CBCR_H2V2: + pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; + pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR; + pipe->a_bit = 0; + pipe->r_bit = 3; /* R, 8 bits */ + pipe->b_bit = 3; /* B, 8 bits */ + pipe->g_bit = 3; /* G, 8 bits */ + pipe->alpha_enable = 0; + pipe->unpack_tight = 1; + pipe->unpack_align_msb = 0; + pipe->unpack_count = 1; /* 2 */ + pipe->element3 = C0_G_Y; /* not used */ + pipe->element2 = C0_G_Y; /* not used */ + if (pipe->src_format == MDP_Y_CRCB_H2V1) { + pipe->element1 = C2_R_Cr; /* R */ + pipe->element0 = C1_B_Cb; /* B */ + pipe->chroma_sample = MDP4_CHROMA_H2V1; + } else if (pipe->src_format == MDP_Y_CBCR_H2V1) { + pipe->element1 = C1_B_Cb; /* B */ + pipe->element0 = C2_R_Cr; /* R */ + pipe->chroma_sample = MDP4_CHROMA_H2V1; + } else if (pipe->src_format == MDP_Y_CRCB_H2V2) { + pipe->element1 = C2_R_Cr; /* R */ + pipe->element0 = C1_B_Cb; /* B */ + pipe->chroma_sample = MDP4_CHROMA_420; + } else if (pipe->src_format == MDP_Y_CBCR_H2V2) { + pipe->element1 = C1_B_Cb; /* B */ + pipe->element0 = C2_R_Cr; /* R */ + pipe->chroma_sample = MDP4_CHROMA_420; + } + pipe->bpp = 2; /* 2 bpp */ + break; + case MDP_Y_CBCR_H2V2_TILE: + case MDP_Y_CRCB_H2V2_TILE: + pipe->frame_format = MDP4_FRAME_FORMAT_VIDEO_SUPERTILE; + pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR; + pipe->a_bit = 0; + pipe->r_bit = 3; /* R, 8 bits */ + pipe->b_bit = 3; /* B, 8 bits */ + pipe->g_bit = 3; /* G, 8 bits */ + pipe->alpha_enable = 0; + pipe->unpack_tight = 1; + pipe->unpack_align_msb = 0; + pipe->unpack_count = 1; /* 2 */ + pipe->element3 = C0_G_Y; /* not used */ + pipe->element2 = C0_G_Y; /* not used */ + if (pipe->src_format == MDP_Y_CRCB_H2V2_TILE) { + pipe->element1 = C2_R_Cr; /* R */ + pipe->element0 = C1_B_Cb; /* B */ + pipe->chroma_sample = MDP4_CHROMA_420; + } else if (pipe->src_format == MDP_Y_CBCR_H2V2_TILE) { + pipe->element1 = C1_B_Cb; /* B */ + pipe->element0 = C2_R_Cr; /* R */ + pipe->chroma_sample = MDP4_CHROMA_420; + } + pipe->bpp = 2; /* 2 bpp */ + break; + default: + /* not likely */ + return -ERANGE; + } + + return 0; +} + +/* + * color_key_convert: output with 12 bits color key + */ +static uint32 color_key_convert(int start, int num, uint32 color) +{ + + uint32 data; + + data = (color >> start) & ((1 << num) - 1); + + if (num == 5) + data = (data << 7) + (data << 2) + (data >> 3); + else if (num == 6) + data = (data << 6) + data; + else /* 8 bits */ + data = (data << 4) + (data >> 4); + + return data; + +} + +void transp_color_key(int format, uint32 transp, + uint32 *c0, uint32 *c1, uint32 *c2) +{ + int b_start, g_start, r_start; + int b_num, g_num, r_num; + + switch (format) { + case MDP_RGB_565: + b_start = 0; + g_start = 5; + r_start = 11; + r_num = 5; + g_num = 6; + b_num = 5; + break; + case MDP_RGB_888: + case MDP_XRGB_8888: + case MDP_ARGB_8888: + b_start = 0; + g_start = 8; + r_start = 16; + r_num = 8; + g_num = 8; + b_num = 8; + break; + case MDP_BGR_565: + b_start = 11; + g_start = 5; + r_start = 0; + r_num = 5; + g_num = 6; + b_num = 5; + break; + case MDP_Y_CBCR_H2V2: + case MDP_Y_CBCR_H2V1: + b_start = 8; + g_start = 16; + r_start = 0; + r_num = 8; + g_num = 8; + b_num = 8; + break; + case MDP_Y_CRCB_H2V2: + case MDP_Y_CRCB_H2V1: + b_start = 0; + g_start = 16; + r_start = 8; + r_num = 8; + g_num = 8; + b_num = 8; + break; + default: + b_start = 0; + g_start = 8; + r_start = 16; + r_num = 8; + g_num = 8; + b_num = 8; + break; + } + + *c0 = color_key_convert(g_start, g_num, transp); + *c1 = color_key_convert(b_start, b_num, transp); + *c2 = color_key_convert(r_start, r_num, transp); +} + +uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe) +{ + uint32 format; + + format = 0; + + if (pipe->solid_fill) + format |= MDP4_FORMAT_SOLID_FILL; + + if (pipe->unpack_align_msb) + format |= MDP4_FORMAT_UNPACK_ALIGN_MSB; + + if (pipe->unpack_tight) + format |= MDP4_FORMAT_UNPACK_TIGHT; + + if (pipe->alpha_enable) + format |= MDP4_FORMAT_ALPHA_ENABLE; + + format |= (pipe->unpack_count << 13); + format |= ((pipe->bpp - 1) << 9); + format |= (pipe->a_bit << 6); + format |= (pipe->r_bit << 4); + format |= (pipe->b_bit << 2); + format |= pipe->g_bit; + + format |= (pipe->frame_format << 29); + + if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) { + /* video/graphic */ + format |= (pipe->fetch_plane << 19); + format |= (pipe->chroma_site << 28); + format |= (pipe->chroma_sample << 26); + } + + return format; +} + +uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe) +{ + return (pipe->element3 << 24) | (pipe->element2 << 16) | + (pipe->element1 << 8) | pipe->element0; +} + +void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe) +{ + uint32 data; + char *overlay_base; + + if (pipe->mixer_num == MDP4_MIXER1) + overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */ + else + overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */ + + /* MDP_OVERLAYPROC_CFG */ + outpdw(overlay_base + 0x0004, 0x01); /* directout */ + data = pipe->src_height; + data <<= 16; + data |= pipe->src_width; + outpdw(overlay_base + 0x0008, data); /* ROI, height + width */ + outpdw(overlay_base + 0x000c, pipe->srcp0_addr); + outpdw(overlay_base + 0x0010, pipe->srcp0_ystride); + outpdw(overlay_base + 0x0014, 0x4); /* GC_LUT_EN, 888 */ +} + +int mdp4_overlay_active(int mixer) +{ + uint32 data, mask, i; + int p1, p2; + + data = inpdw(MDP_BASE + 0x10100); + p1 = 0; + p2 = 0; + for (i = 0; i < 8; i++) { + mask = data & 0x0f; + if (mask) { + if (mask <= 4) + p1++; + else + p2++; + } + data >>= 4; + } + + if (mixer) + return p2; + else + return p1; +} + +void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe) +{ + uint32 data, mask, snum, stage, mixer; + + stage = pipe->mixer_stage; + mixer = pipe->mixer_num; + + /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */ + data = inpdw(MDP_BASE + 0x10100); + + if (mixer == MDP4_MIXER1) + stage += 8; + + if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */ + snum = 0; + snum += (4 * pipe->pipe_num); + } else { + snum = 8; + snum += (4 * pipe->pipe_num); /* RGB1 and RGB2 */ + } + + mask = 0x0f; + mask <<= snum; + stage <<= snum; + data &= ~mask; /* clear old bits */ + + data |= stage; + + outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */ + + data = inpdw(MDP_BASE + 0x10100); + + ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe; /* keep it */ +} + +void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe) +{ + uint32 data, mask, snum, stage, mixer; + + stage = pipe->mixer_stage; + mixer = pipe->mixer_num; + + if (pipe != ctrl->stage[mixer][stage]) /* not runing */ + return; + + /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */ + data = inpdw(MDP_BASE + 0x10100); + + if (mixer == MDP4_MIXER1) + stage += 8; + + if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */ + snum = 0; + snum += (4 * pipe->pipe_num); + } else { + snum = 8; + snum += (4 * pipe->pipe_num); /* RGB1 and RGB2 */ + } + + mask = 0x0f; + mask <<= snum; + data &= ~mask; /* clear old bits */ + + outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */ + + data = inpdw(MDP_BASE + 0x10100); + + ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL; /* clear it */ +} + +void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe) +{ + unsigned char *overlay_base; + uint32 c0, c1, c2, blend_op; + int off; + + if (pipe->mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */ + overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */ + else + overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */ + + /* stage 0 to stage 2 */ + off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0); + + blend_op = 0; + if (pipe->alpha_enable) /* ARGB */ + blend_op = MDP4_BLEND_FG_ALPHA_FG_PIXEL | + MDP4_BLEND_BG_ALPHA_FG_PIXEL; + else + blend_op = (MDP4_BLEND_BG_ALPHA_BG_CONST | + MDP4_BLEND_FG_ALPHA_FG_CONST); + + + if (pipe->alpha_enable == 0) { /* not ARGB */ + if (pipe->is_fg) { + outpdw(overlay_base + off + 0x108, pipe->alpha); + outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha); + } else { + outpdw(overlay_base + off + 0x108, 0xff - pipe->alpha); + outpdw(overlay_base + off + 0x10c, pipe->alpha); + } + } + + if (pipe->transp != MDP_TRANSP_NOP) { + transp_color_key(pipe->src_format, pipe->transp, &c0, &c1, &c2); + if (pipe->is_fg) { + blend_op |= MDP4_BLEND_FG_TRANSP_EN; /* Fg blocked */ + /* lower limit */ + if (c0 > 0x10) + c0 -= 0x10; + if (c1 > 0x10) + c1 -= 0x10; + if (c2 > 0x10) + c2 -= 0x10; + outpdw(overlay_base + off + 0x110, + (c1 << 16 | c0));/* low */ + outpdw(overlay_base + off + 0x114, c2);/* low */ + /* upper limit */ + if ((c0 + 0x20) < 0x0fff) + c0 += 0x20; + else + c0 = 0x0fff; + if ((c1 + 0x20) < 0x0fff) + c1 += 0x20; + else + c1 = 0x0fff; + if ((c2 + 0x20) < 0x0fff) + c2 += 0x20; + else + c2 = 0x0fff; + outpdw(overlay_base + off + 0x118, + (c1 << 16 | c0));/* high */ + outpdw(overlay_base + off + 0x11c, c2);/* high */ + } else { + blend_op |= MDP4_BLEND_BG_TRANSP_EN; /* bg blocked */ + /* lower limit */ + if (c0 > 0x10) + c0 -= 0x10; + if (c1 > 0x10) + c1 -= 0x10; + if (c2 > 0x10) + c2 -= 0x10; + outpdw(overlay_base + 0x180, + (c1 << 16 | c0));/* low */ + outpdw(overlay_base + 0x184, c2);/* low */ + /* upper limit */ + if ((c0 + 0x20) < 0x0fff) + c0 += 0x20; + else + c0 = 0x0fff; + if ((c1 + 0x20) < 0x0fff) + c1 += 0x20; + else + c1 = 0x0fff; + if ((c2 + 0x20) < 0x0fff) + c2 += 0x20; + else + c2 = 0x0fff; + outpdw(overlay_base + 0x188, + (c1 << 16 | c0));/* high */ + outpdw(overlay_base + 0x18c, c2);/* high */ + } + } + outpdw(overlay_base + off + 0x104, blend_op); +} + +void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all) +{ + uint32 bits = 0; + + if (pipe->mixer_num == MDP4_MIXER1) + bits |= 0x02; + else + bits |= 0x01; + + if (all) { + if (pipe->pipe_type == OVERLAY_TYPE_RGB) { + if (pipe->pipe_num == OVERLAY_PIPE_RGB2) + bits |= 0x20; + else + bits |= 0x10; + } else { + if (pipe->pipe_num == OVERLAY_PIPE_VG2) + bits |= 0x08; + else + bits |= 0x04; + } + } + + outpdw(MDP_BASE + 0x18000, bits); /* MDP_OVERLAY_REG_FLUSH */ + + while (inpdw(MDP_BASE + 0x18000) & bits) /* self clear when complete */ + ; +} + +struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx) +{ + struct mdp4_overlay_pipe *pipe; + + if (ndx == 0 || ndx >= MDP4_MAX_OVERLAY_PIPE) + return NULL; + + pipe = &ctrl->plist[ndx - 1]; /* ndx start from 1 */ + + if (pipe->pipe_ndx == 0) + return NULL; + + return pipe; +} + +struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void) +{ + int i; + struct mdp4_overlay_pipe *pipe; + + pipe = &ctrl->plist[0]; + for (i = 0; i < MDP4_MAX_OVERLAY_PIPE; i++) { + if (pipe->pipe_ndx == 0) { + pipe->pipe_ndx = i + 1; /* start from 1 */ + init_completion(&pipe->comp); + printk(KERN_INFO "mdp4_overlay_pipe_alloc: pipe=%x ndx=%d\n", + (int)pipe, pipe->pipe_ndx); + return pipe; + } + pipe++; + } + + return NULL; +} + + +void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe) +{ + printk(KERN_INFO "mdp4_overlay_pipe_free: pipe=%x ndx=%d\n", + (int)pipe, pipe->pipe_ndx); + memset(pipe, 0, sizeof(*pipe)); +} + +static int get_pipe_num(int ptype, int stage) +{ + if (ptype == OVERLAY_TYPE_RGB) { + if (stage == MDP4_MIXER_STAGE_BASE) + return OVERLAY_PIPE_RGB1; + else + return OVERLAY_PIPE_RGB2; + } else { + if (stage == MDP4_MIXER_STAGE0) + return OVERLAY_PIPE_VG1; + else + return OVERLAY_PIPE_VG2; + } +} + +int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer) +{ + struct mdp4_overlay_pipe *pipe; + + pipe = ctrl->stage[mixer][z_order]; + + if (pipe == NULL) + return 0; + + if (pipe->pipe_ndx == id) /* same req, recycle */ + return 0; + + return -EPERM; +} + +static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer, + struct mdp4_overlay_pipe **ppipe) +{ + struct mdp4_overlay_pipe *pipe; + int ret, ptype; + + if (mixer >= MDP4_MAX_MIXER) { + printk(KERN_ERR "mpd_overlay_req2pipe: mixer out of range!\n"); + return -ERANGE; + } + + if (req->z_order < 0 || req->z_order > 2) { + printk(KERN_ERR "mpd_overlay_req2pipe: z_order=%d out of range!\n", + req->z_order); + return -ERANGE; + } + + if (req->src_rect.h == 0 || req->src_rect.w == 0) { + printk(KERN_ERR "mpd_overlay_req2pipe: src img of zero size!\n"); + return -EINVAL; + } + + ret = mdp4_overlay_req_check(req->id, req->z_order, mixer); + if (ret < 0) + return ret; + + ptype = mdp4_overlay_format2type(req->src.format); + if (ptype < 0) + return ptype; + + if (req->id == MSMFB_NEW_REQUEST) /* new request */ + pipe = mdp4_overlay_pipe_alloc(); + else + pipe = mdp4_overlay_ndx2pipe(req->id); + + if (pipe == NULL) + return -ENOMEM; + + pipe->src_format = req->src.format; + ret = mdp4_overlay_format2pipe(pipe); + + if (ret < 0) + return ret; + + /* + * base layer == 1, reserved for frame buffer + * zorder 0 == stage 0 == 2 + * zorder 1 == stage 1 == 3 + * zorder 2 == stage 2 == 4 + */ + if (req->id == MSMFB_NEW_REQUEST) { /* new request */ + pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0; + pipe->pipe_type = ptype; + pipe->pipe_num = get_pipe_num(ptype, pipe->mixer_stage); + printk(KERN_INFO "mpd4_overlay_req2pipe: zorder=%d pipe_num=%d\n", + req->z_order, pipe->pipe_num); + } + + pipe->src_width = req->src.width & 0x07ff; /* source img width */ + pipe->src_height = req->src.height & 0x07ff; /* source img height */ + pipe->src_h = req->src_rect.h & 0x07ff; + pipe->src_w = req->src_rect.w & 0x07ff; + pipe->src_y = req->src_rect.y & 0x07ff; + pipe->src_x = req->src_rect.x & 0x07ff; + pipe->dst_h = req->dst_rect.h & 0x07ff; + pipe->dst_w = req->dst_rect.w & 0x07ff; + pipe->dst_y = req->dst_rect.y & 0x07ff; + pipe->dst_x = req->dst_rect.x & 0x07ff; + + if (req->flags & MDP_FLIP_LR) + pipe->op_mode |= MDP4_OP_FLIP_LR; + + if (req->flags & MDP_FLIP_UD) + pipe->op_mode |= MDP4_OP_FLIP_UD; + + if (req->flags & MDP_DITHER) + pipe->op_mode |= MDP4_OP_DITHER_EN; + + if (req->flags & MDP_DEINTERLACE) + pipe->op_mode |= MDP4_OP_DEINT_ODD_REF; + + pipe->is_fg = req->is_fg;/* control alpha and color key */ + + pipe->alpha = req->alpha & 0x0ff; + + pipe->transp = req->transp_mask; + + *ppipe = pipe; + + return 0; +} + +int get_img(struct msmfb_data *img, struct fb_info *info, + unsigned long *start, unsigned long *len, struct file **pp_file) +{ + int put_needed, ret = 0; + struct file *file; +#ifdef CONFIG_ANDROID_PMEM + unsigned long vstart; +#endif + +#ifdef CONFIG_ANDROID_PMEM + if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file)) + return 0; +#endif + file = fget_light(img->memory_id, &put_needed); + if (file == NULL) + return -1; + + if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) { + *start = info->fix.smem_start; + *len = info->fix.smem_len; + *pp_file = file; + } else { + ret = -1; + fput_light(file, put_needed); + } + return ret; +} +int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req) +{ + struct mdp4_overlay_pipe *pipe; + + pipe = mdp4_overlay_ndx2pipe(req->id); + if (pipe == NULL) + return -ENODEV; + + *req = pipe->req_data; + + return 0; +} + +int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + int ret, mixer; + struct mdp4_overlay_pipe *pipe; + int lcdc; + + if (mfd == NULL) + return -ENODEV; + + if (req->src.format == MDP_FB_FORMAT) + req->src.format = mfd->fb_imgType; + + if (mutex_lock_interruptible(&mfd->dma->ov_mutex)) + return -EINTR; + + mixer = info->node; /* minor number of char device */ + + ret = mdp4_overlay_req2pipe(req, mixer, &pipe); + if (ret < 0) { + mutex_unlock(&mfd->dma->ov_mutex); + return ret; + } + + lcdc = inpdw(MDP_BASE + 0xc0000); + + if (lcdc == 0) { /* mddi */ + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + } + + /* return id back to user */ + req->id = pipe->pipe_ndx; /* pipe_ndx start from 1 */ + pipe->req_data = *req; /* keep original req */ + + mutex_unlock(&mfd->dma->ov_mutex); + + return 0; +} + +int mdp4_overlay_unset(struct fb_info *info, int ndx) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + struct mdp4_overlay_pipe *pipe; + int lcdc; + + if (mfd == NULL) + return -ENODEV; + + if (mutex_lock_interruptible(&mfd->dma->ov_mutex)) + return -EINTR; + + pipe = mdp4_overlay_ndx2pipe(ndx); + + if (pipe == NULL) { + mutex_unlock(&mfd->dma->ov_mutex); + return -ENODEV; + } + + lcdc = inpdw(MDP_BASE + 0xc0000); + + mdp4_mixer_stage_down(pipe); + + if (lcdc == 0) { /* mddi */ + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + } + + if (lcdc) /* LCDC mode */ + mdp4_overlay_reg_flush(pipe, 0); + + mdp4_overlay_pipe_free(pipe); + + if (lcdc == 0) { /* mddi */ + mdp4_mddi_overlay_restore(); + } + + mutex_unlock(&mfd->dma->ov_mutex); + + return 0; +} + +struct tile_desc { + uint32 width; /* tile's width */ + uint32 height; /* tile's height */ + uint32 row_tile_w; /* tiles per row's width */ + uint32 row_tile_h; /* tiles per row's height */ +}; + +void tile_samsung(struct tile_desc *tp) +{ + /* + * each row of samsung tile consists of two tiles in height + * and two tiles in width which means width should align to + * 64 x 2 bytes and height should align to 32 x 2 bytes. + * video decoder generate two tiles in width and one tile + * in height which ends up height align to 32 X 1 bytes. + */ + tp->width = 64; /* 64 bytes */ + tp->row_tile_w = 2; /* 2 tiles per row's width */ + tp->height = 32; /* 32 bytes */ + tp->row_tile_h = 1; /* 1 tiles per row's height */ +} + +uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp) +{ + uint32 tile_w, tile_h; + uint32 row_num_w, row_num_h; + + + tile_w = tp->width * tp->row_tile_w; + tile_h = tp->height * tp->row_tile_h; + + row_num_w = (pipe->src_width + tile_w - 1) / tile_w; + row_num_h = (pipe->src_height + tile_h - 1) / tile_h; + + return row_num_w * row_num_h * tile_w * tile_h; +} + +int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req, + struct file **pp_src_file) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + struct msmfb_data *img; + struct mdp4_overlay_pipe *pipe; + ulong start, addr; + ulong len = 0; + struct file *p_src_file = 0; + int lcdc; + + if (mfd == NULL) + return -ENODEV; + + pipe = mdp4_overlay_ndx2pipe(req->id); + if (pipe == NULL) + return -ENODEV; + + if (mutex_lock_interruptible(&mfd->dma->ov_mutex)) + return -EINTR; + + img = &req->data; + get_img(img, info, &start, &len, &p_src_file); + if (len == 0) { + mutex_unlock(&mfd->dma->ov_mutex); + printk(KERN_ERR "mdp_overlay_play: could not retrieve" + " image from memory\n"); + return -1; + } + *pp_src_file = p_src_file; + + addr = start + img->offset; + pipe->srcp0_addr = addr; + pipe->srcp0_ystride = pipe->src_width * pipe->bpp; + + if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) { + if (pipe->frame_format == MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) { + struct tile_desc tile; + + tile_samsung(&tile); + pipe->srcp1_addr = addr + tile_mem_size(pipe, &tile); + } else + pipe->srcp1_addr = addr + + pipe->src_width * pipe->src_height; + + pipe->srcp0_ystride = pipe->src_width; + pipe->srcp1_ystride = pipe->src_width; + } + + lcdc = inpdw(MDP_BASE + 0xc0000); + lcdc &= 0x01; /* LCDC mode */ + + if (pipe->pipe_type == OVERLAY_TYPE_VG) + mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */ + else + mdp4_overlay_rgb_setup(pipe); /* rgb pipe */ + + mdp4_mixer_blend_setup(pipe); + mdp4_mixer_stage_up(pipe); + + if (lcdc) { /* LCDC mode */ + mdp4_overlay_reg_flush(pipe, 1); + } + + if (lcdc) { /* LCDC mode */ + if (pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) { /* done */ + mutex_unlock(&mfd->dma->ov_mutex); + return 0; + } + } + + if (lcdc == 0) { /* MDDI mode */ +#ifdef MDP4_NONBLOCKING + if (mfd->panel_power_on) +#else + if (!mfd->dma->busy && mfd->panel_power_on) +#endif + mdp4_mddi_overlay_kickoff(mfd, pipe); + } + + mutex_unlock(&mfd->dma->ov_mutex); + + return 0; +} diff --git a/drivers/staging/msm/mdp4_overlay_lcdc.c b/drivers/staging/msm/mdp4_overlay_lcdc.c new file mode 100644 index 000000000000..a6ab8ec83f55 --- /dev/null +++ b/drivers/staging/msm/mdp4_overlay_lcdc.c @@ -0,0 +1,313 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/hrtimer.h> +#include <linux/delay.h> +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/spinlock.h> + +#include <linux/fb.h> + +#include "mdp.h" +#include "msm_fb.h" +#include "mdp4.h" + +#ifdef CONFIG_FB_MSM_MDP40 +#define LCDC_BASE 0xC0000 +#else +#define LCDC_BASE 0xE0000 +#endif + +int first_pixel_start_x; +int first_pixel_start_y; + +static struct mdp4_overlay_pipe *lcdc_pipe; + +int mdp_lcdc_on(struct platform_device *pdev) +{ + int lcdc_width; + int lcdc_height; + int lcdc_bpp; + int lcdc_border_clr; + int lcdc_underflow_clr; + int lcdc_hsync_skew; + + int hsync_period; + int hsync_ctrl; + int vsync_period; + int display_hctl; + int display_v_start; + int display_v_end; + int active_hctl; + int active_h_start; + int active_h_end; + int active_v_start; + int active_v_end; + int ctrl_polarity; + int h_back_porch; + int h_front_porch; + int v_back_porch; + int v_front_porch; + int hsync_pulse_width; + int vsync_pulse_width; + int hsync_polarity; + int vsync_polarity; + int data_en_polarity; + int hsync_start_x; + int hsync_end_x; + uint8 *buf; + int bpp, ptype; + uint32 format; + struct fb_info *fbi; + struct fb_var_screeninfo *var; + struct msm_fb_data_type *mfd; + struct mdp4_overlay_pipe *pipe; + int ret; + + mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); + + if (!mfd) + return -ENODEV; + + if (mfd->key != MFD_KEY) + return -EINVAL; + + fbi = mfd->fbi; + var = &fbi->var; + + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + + bpp = fbi->var.bits_per_pixel / 8; + buf = (uint8 *) fbi->fix.smem_start; + buf += fbi->var.xoffset * bpp + + fbi->var.yoffset * fbi->fix.line_length; + + if (bpp == 2) + format = MDP_RGB_565; + else if (bpp == 3) + format = MDP_RGB_888; + else + format = MDP_ARGB_8888; + + + if (lcdc_pipe == NULL) { + ptype = mdp4_overlay_format2type(format); + pipe = mdp4_overlay_pipe_alloc(); + pipe->pipe_type = ptype; + /* use RGB1 pipe */ + pipe->pipe_num = OVERLAY_PIPE_RGB1; + pipe->mixer_stage = MDP4_MIXER_STAGE_BASE; + pipe->mixer_num = MDP4_MIXER0; + pipe->src_format = format; + mdp4_overlay_format2pipe(pipe); + + lcdc_pipe = pipe; /* keep it */ + } else { + pipe = lcdc_pipe; + } + + pipe->src_height = fbi->var.yres; + pipe->src_width = fbi->var.xres; + pipe->src_h = fbi->var.yres; + pipe->src_w = fbi->var.xres; + pipe->src_y = 0; + pipe->src_x = 0; + pipe->srcp0_addr = (uint32) buf; + pipe->srcp0_ystride = fbi->fix.line_length; + + mdp4_overlay_dmap_xy(pipe); + mdp4_overlay_dmap_cfg(mfd, 1); + + mdp4_overlay_rgb_setup(pipe); + + mdp4_mixer_stage_up(pipe); + + mdp4_overlayproc_cfg(pipe); + + /* + * LCDC timing setting + */ + h_back_porch = var->left_margin; + h_front_porch = var->right_margin; + v_back_porch = var->upper_margin; + v_front_porch = var->lower_margin; + hsync_pulse_width = var->hsync_len; + vsync_pulse_width = var->vsync_len; + lcdc_border_clr = mfd->panel_info.lcdc.border_clr; + lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr; + lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew; + + lcdc_width = mfd->panel_info.xres; + lcdc_height = mfd->panel_info.yres; + lcdc_bpp = mfd->panel_info.bpp; + + hsync_period = + hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch; + hsync_ctrl = (hsync_period << 16) | hsync_pulse_width; + hsync_start_x = hsync_pulse_width + h_back_porch; + hsync_end_x = hsync_period - h_front_porch - 1; + display_hctl = (hsync_end_x << 16) | hsync_start_x; + + vsync_period = + (vsync_pulse_width + v_back_porch + lcdc_height + + v_front_porch) * hsync_period; + display_v_start = + (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew; + display_v_end = + vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1; + + if (lcdc_width != var->xres) { + active_h_start = hsync_start_x + first_pixel_start_x; + active_h_end = active_h_start + var->xres - 1; + active_hctl = + ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start; + } else { + active_hctl = 0; + } + + if (lcdc_height != var->yres) { + active_v_start = + display_v_start + first_pixel_start_y * hsync_period; + active_v_end = active_v_start + (var->yres) * hsync_period - 1; + active_v_start |= ACTIVE_START_Y_EN; + } else { + active_v_start = 0; + active_v_end = 0; + } + + +#ifdef CONFIG_FB_MSM_MDP40 + hsync_polarity = 1; + vsync_polarity = 1; + lcdc_underflow_clr |= 0x80000000; /* enable recovery */ +#else + hsync_polarity = 0; + vsync_polarity = 0; +#endif + data_en_polarity = 0; + + ctrl_polarity = + (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity); + + MDP_OUTP(MDP_BASE + LCDC_BASE + 0x4, hsync_ctrl); + MDP_OUTP(MDP_BASE + LCDC_BASE + 0x8, vsync_period); + MDP_OUTP(MDP_BASE + LCDC_BASE + 0xc, vsync_pulse_width * hsync_period); + MDP_OUTP(MDP_BASE + LCDC_BASE + 0x10, display_hctl); + MDP_OUTP(MDP_BASE + LCDC_BASE + 0x14, display_v_start); + MDP_OUTP(MDP_BASE + LCDC_BASE + 0x18, display_v_end); + MDP_OUTP(MDP_BASE + LCDC_BASE + 0x28, lcdc_border_clr); + MDP_OUTP(MDP_BASE + LCDC_BASE + 0x2c, lcdc_underflow_clr); + MDP_OUTP(MDP_BASE + LCDC_BASE + 0x30, lcdc_hsync_skew); + MDP_OUTP(MDP_BASE + LCDC_BASE + 0x38, ctrl_polarity); + MDP_OUTP(MDP_BASE + LCDC_BASE + 0x1c, active_hctl); + MDP_OUTP(MDP_BASE + LCDC_BASE + 0x20, active_v_start); + MDP_OUTP(MDP_BASE + LCDC_BASE + 0x24, active_v_end); + + ret = panel_next_on(pdev); + if (ret == 0) { + /* enable LCDC block */ + MDP_OUTP(MDP_BASE + LCDC_BASE, 1); + mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + } + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + + return ret; +} + +int mdp_lcdc_off(struct platform_device *pdev) +{ + int ret = 0; + struct mdp4_overlay_pipe *pipe; + + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + MDP_OUTP(MDP_BASE + LCDC_BASE, 0); + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + + ret = panel_next_off(pdev); + + /* delay to make sure the last frame finishes */ + mdelay(100); + + /* dis-engage rgb0 from mixer */ + pipe = lcdc_pipe; + mdp4_mixer_stage_down(pipe); + + return ret; +} + +/* + * mdp4_overlay0_done_lcdc: called from isr + */ +void mdp4_overlay0_done_lcdc() +{ + complete(&lcdc_pipe->comp); +} + +void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd) +{ + struct fb_info *fbi = mfd->fbi; + uint8 *buf; + int bpp; + unsigned long flag; + struct mdp4_overlay_pipe *pipe; + + if (!mfd->panel_power_on) + return; + + /* no need to power on cmd block since it's lcdc mode */ + bpp = fbi->var.bits_per_pixel / 8; + buf = (uint8 *) fbi->fix.smem_start; + buf += fbi->var.xoffset * bpp + + fbi->var.yoffset * fbi->fix.line_length; + + mutex_lock(&mfd->dma->ov_mutex); + + pipe = lcdc_pipe; + pipe->srcp0_addr = (uint32) buf; + mdp4_overlay_rgb_setup(pipe); + mdp4_overlay_reg_flush(pipe, 1); /* rgb1 and mixer0 */ + + /* enable irq */ + spin_lock_irqsave(&mdp_spin_lock, flag); + mdp_enable_irq(MDP_OVERLAY0_TERM); + INIT_COMPLETION(lcdc_pipe->comp); + mfd->dma->waiting = TRUE; + outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE); + mdp_intr_mask |= INTR_OVERLAY0_DONE; + outp32(MDP_INTR_ENABLE, mdp_intr_mask); + spin_unlock_irqrestore(&mdp_spin_lock, flag); + wait_for_completion_killable(&lcdc_pipe->comp); + mdp_disable_irq(MDP_OVERLAY0_TERM); + + mutex_unlock(&mfd->dma->ov_mutex); +} diff --git a/drivers/staging/msm/mdp4_overlay_mddi.c b/drivers/staging/msm/mdp4_overlay_mddi.c new file mode 100644 index 000000000000..be1b2874185b --- /dev/null +++ b/drivers/staging/msm/mdp4_overlay_mddi.c @@ -0,0 +1,254 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/hrtimer.h> +#include <linux/delay.h> +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/spinlock.h> + +#include <linux/fb.h> + +#include "mdp.h" +#include "msm_fb.h" +#include "mdp4.h" + +static struct mdp4_overlay_pipe *mddi_pipe; +static struct mdp4_overlay_pipe *pending_pipe; +static struct msm_fb_data_type *mddi_mfd; + +#define WHOLESCREEN + +void mdp4_overlay_update_lcd(struct msm_fb_data_type *mfd) +{ + MDPIBUF *iBuf = &mfd->ibuf; + uint8 *src; + int bpp, ptype; + uint32 format; + uint32 mddi_ld_param; + uint16 mddi_vdo_packet_reg; + struct mdp4_overlay_pipe *pipe; + + if (mfd->key != MFD_KEY) + return; + + mddi_mfd = mfd; /* keep it */ + + bpp = iBuf->bpp; + + if (bpp == 2) + format = MDP_RGB_565; + else if (bpp == 3) + format = MDP_RGB_888; + else + format = MDP_ARGB_8888; + + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + + if (mddi_pipe == NULL) { + ptype = mdp4_overlay_format2type(format); + pipe = mdp4_overlay_pipe_alloc(); + pipe->pipe_type = ptype; + /* use RGB1 pipe */ + pipe->pipe_num = OVERLAY_PIPE_RGB1; + pipe->mixer_num = MDP4_MIXER0; + pipe->src_format = format; + mdp4_overlay_format2pipe(pipe); + + mddi_pipe = pipe; /* keep it */ + + mddi_ld_param = 0; + mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt; + + if (mfd->panel_info.type == MDDI_PANEL) { + if (mfd->panel_info.pdest == DISPLAY_1) + mddi_ld_param = 0; + else + mddi_ld_param = 1; + } else { + mddi_ld_param = 2; + } + + MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param); + MDP_OUTP(MDP_BASE + 0x00094, + (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg); + } else { + pipe = mddi_pipe; + } + + + src = (uint8 *) iBuf->buf; + +#ifdef WHOLESCREEN + { + struct fb_info *fbi; + + fbi = mfd->fbi; + pipe->src_height = fbi->var.yres; + pipe->src_width = fbi->var.xres; + pipe->src_h = fbi->var.yres; + pipe->src_w = fbi->var.xres; + pipe->src_y = 0; + pipe->src_x = 0; + pipe->dst_h = fbi->var.yres; + pipe->dst_w = fbi->var.xres; + pipe->dst_y = 0; + pipe->dst_x = 0; + pipe->srcp0_addr = (uint32)src; + pipe->srcp0_ystride = fbi->var.xres_virtual * bpp; + } + +#else + if (mdp4_overlay_active(MDP4_MIXER0)) { + struct fb_info *fbi; + + fbi = mfd->fbi; + pipe->src_height = fbi->var.yres; + pipe->src_width = fbi->var.xres; + pipe->src_h = fbi->var.yres; + pipe->src_w = fbi->var.xres; + pipe->src_y = 0; + pipe->src_x = 0; + pipe->dst_h = fbi->var.yres; + pipe->dst_w = fbi->var.xres; + pipe->dst_y = 0; + pipe->dst_x = 0; + pipe->srcp0_addr = (uint32) src; + pipe->srcp0_ystride = fbi->var.xres_virtual * bpp; + } else { + /* starting input address */ + src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * bpp; + + pipe->src_height = iBuf->dma_h; + pipe->src_width = iBuf->dma_w; + pipe->src_h = iBuf->dma_h; + pipe->src_w = iBuf->dma_w; + pipe->src_y = 0; + pipe->src_x = 0; + pipe->dst_h = iBuf->dma_h; + pipe->dst_w = iBuf->dma_w; + pipe->dst_y = iBuf->dma_y; + pipe->dst_x = iBuf->dma_x; + pipe->srcp0_addr = (uint32) src; + pipe->srcp0_ystride = iBuf->ibuf_width * bpp; + } +#endif + + pipe->mixer_stage = MDP4_MIXER_STAGE_BASE; + + mdp4_overlay_rgb_setup(pipe); + + mdp4_mixer_stage_up(pipe); + + mdp4_overlayproc_cfg(pipe); + + mdp4_overlay_dmap_xy(pipe); + + mdp4_overlay_dmap_cfg(mfd, 0); + + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + +} + +/* + * mdp4_overlay0_done_mddi: called from isr + */ +void mdp4_overlay0_done_mddi() +{ + if (pending_pipe) + complete(&pending_pipe->comp); +} + +void mdp4_mddi_overlay_restore(void) +{ + /* mutex holded by caller */ + mdp4_overlay_update_lcd(mddi_mfd); + mdp4_mddi_overlay_kickoff(mddi_mfd, mddi_pipe); +} + +void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd, + struct mdp4_overlay_pipe *pipe) +{ +#ifdef MDP4_NONBLOCKING + unsigned long flag; + + spin_lock_irqsave(&mdp_spin_lock, flag); + if (mfd->dma->busy == TRUE) { + INIT_COMPLETION(pipe->comp); + pending_pipe = pipe; + } + spin_unlock_irqrestore(&mdp_spin_lock, flag); + + if (pending_pipe != NULL) { + /* wait until DMA finishes the current job */ + wait_for_completion_killable(&pipe->comp); + pending_pipe = NULL; + } + down(&mfd->sem); + mdp_enable_irq(MDP_OVERLAY0_TERM); + mfd->dma->busy = TRUE; + /* start OVERLAY pipe */ + mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd); + up(&mfd->sem); +#else + down(&mfd->sem); + mdp_enable_irq(MDP_OVERLAY0_TERM); + mfd->dma->busy = TRUE; + INIT_COMPLETION(pipe->comp); + pending_pipe = pipe; + + /* start OVERLAY pipe */ + mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd); + up(&mfd->sem); + + /* wait until DMA finishes the current job */ + wait_for_completion_killable(&pipe->comp); + mdp_disable_irq(MDP_OVERLAY0_TERM); +#endif + +} + +void mdp4_mddi_overlay(struct msm_fb_data_type *mfd) +{ + mutex_lock(&mfd->dma->ov_mutex); + + if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) { + mdp4_overlay_update_lcd(mfd); + + mdp4_mddi_overlay_kickoff(mfd, mddi_pipe); + + /* signal if pan function is waiting for the update completion */ + if (mfd->pan_waiting) { + mfd->pan_waiting = FALSE; + complete(&mfd->pan_comp); + } + } + + mutex_unlock(&mfd->dma->ov_mutex); +} diff --git a/drivers/staging/msm/mdp4_util.c b/drivers/staging/msm/mdp4_util.c new file mode 100644 index 000000000000..fd97f5205992 --- /dev/null +++ b/drivers/staging/msm/mdp4_util.c @@ -0,0 +1,1686 @@ + +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/hrtimer.h> +#include <linux/clk.h> +#include <mach/hardware.h> +#include <linux/io.h> +#include <linux/debugfs.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/uaccess.h> + +#include "mdp.h" +#include "msm_fb.h" +#include "mdp4.h" + +void mdp4_sw_reset(ulong bits) +{ + bits &= 0x1f; /* 5 bits */ + outpdw(MDP_BASE + 0x001c, bits); /* MDP_SW_RESET */ + + while (inpdw(MDP_BASE + 0x001c) & bits) /* self clear when complete */ + ; + MSM_FB_INFO("mdp4_sw_reset: 0x%x\n", (int)bits); +} + +void mdp4_overlay_cfg(int overlayer, int blt_mode, int refresh, int direct_out) +{ + ulong bits = 0; + + if (blt_mode) + bits |= (1 << 3); + refresh &= 0x03; /* 2 bites */ + bits |= (refresh << 1); + direct_out &= 0x01; + bits |= direct_out; + + if (overlayer == MDP4_MIXER0) + outpdw(MDP_BASE + 0x10004, bits); /* MDP_OVERLAY0_CFG */ + else + outpdw(MDP_BASE + 0x18004, bits); /* MDP_OVERLAY1_CFG */ + + MSM_FB_INFO("mdp4_overlay_cfg: 0x%x\n", (int)inpdw(MDP_BASE + 0x10004)); +} + +void mdp4_display_intf_sel(int output, ulong intf) +{ + ulong bits, mask; + + bits = inpdw(MDP_BASE + 0x0038); /* MDP_DISP_INTF_SEL */ + + mask = 0x03; /* 2 bits */ + intf &= 0x03; /* 2 bits */ + + switch (output) { + case EXTERNAL_INTF_SEL: + intf <<= 4; + mask <<= 4; + break; + case SECONDARY_INTF_SEL: + intf &= 0x02; /* only MDDI and EBI2 support */ + intf <<= 2; + mask <<= 2; + break; + default: + break; + } + + + bits &= ~mask; + bits |= intf; + + outpdw(MDP_BASE + 0x0038, bits); /* MDP_DISP_INTF_SEL */ + + MSM_FB_INFO("mdp4_display_intf_sel: 0x%x\n", (int)inpdw(MDP_BASE + 0x0038)); +} + +unsigned long mdp4_display_status(void) +{ + return inpdw(MDP_BASE + 0x0018) & 0x3ff; /* MDP_DISPLAY_STATUS */ +} + +void mdp4_ebi2_lcd_setup(int lcd, ulong base, int ystride) +{ + /* always use memory map */ + ystride &= 0x01fff; /* 13 bits */ + if (lcd == EBI2_LCD0) { + outpdw(MDP_BASE + 0x0060, base);/* MDP_EBI2_LCD0 */ + outpdw(MDP_BASE + 0x0068, ystride);/* MDP_EBI2_LCD0_YSTRIDE */ + } else { + outpdw(MDP_BASE + 0x0064, base);/* MDP_EBI2_LCD1 */ + outpdw(MDP_BASE + 0x006c, ystride);/* MDP_EBI2_LCD1_YSTRIDE */ + } +} + +void mdp4_mddi_setup(int mddi, unsigned long id) +{ + ulong bits; + + if (mddi == MDDI_EXTERNAL_SET) + bits = 0x02; + else if (mddi == MDDI_SECONDARY_SET) + bits = 0x01; + else + bits = 0; /* PRIMARY_SET */ + + id <<= 16; + + bits |= id; + + outpdw(MDP_BASE + 0x0090, bits); /* MDP_MDDI_PARAM_WR_SEL */ +} + +int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req, + struct file **pp_src_file, struct file **pp_dst_file) +{ + + /* not implemented yet */ + return -1; +} + +void mdp4_hw_init(void) +{ + ulong bits; + + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + +#ifdef MDP4_ERROR + /* + * Issue software reset on DMA_P will casue DMA_P dma engine stall + * on LCDC mode. However DMA_P does not stall at MDDI mode. + * This need further investigation. + */ + mdp4_sw_reset(0x17); +#endif + + mdp4_clear_lcdc(); + + mdp4_mixer_blend_init(0); + mdp4_mixer_blend_init(1); + mdp4_vg_qseed_init(0); + mdp4_vg_qseed_init(1); + mdp4_vg_csc_mv_setup(0); + mdp4_vg_csc_mv_setup(1); + mdp4_vg_csc_pre_bv_setup(0); + mdp4_vg_csc_pre_bv_setup(1); + mdp4_vg_csc_post_bv_setup(0); + mdp4_vg_csc_post_bv_setup(1); + mdp4_vg_csc_pre_lv_setup(0); + mdp4_vg_csc_pre_lv_setup(1); + mdp4_vg_csc_post_lv_setup(0); + mdp4_vg_csc_post_lv_setup(1); + + mdp4_mixer_gc_lut_setup(0); + mdp4_mixer_gc_lut_setup(1); + + mdp4_vg_igc_lut_setup(0); + mdp4_vg_igc_lut_setup(1); + + mdp4_rgb_igc_lut_setup(0); + mdp4_rgb_igc_lut_setup(1); + + outp32(MDP_EBI2_PORTMAP_MODE, 0x3); + + /* system interrupts */ + + bits = mdp_intr_mask; + outpdw(MDP_BASE + 0x0050, bits);/* enable specififed interrupts */ + + /* histogram */ + MDP_OUTP(MDP_BASE + 0x95010, 1); /* auto clear HIST */ + + /* enable histogram interrupts */ + outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE); + + /* For the max read pending cmd config below, if the MDP clock */ + /* is less than the AXI clock, then we must use 3 pending */ + /* pending requests. Otherwise, we should use 8 pending requests. */ + /* In the future we should do this detection automatically. */ + + /* max read pending cmd config */ + outpdw(MDP_BASE + 0x004c, 0x02222); /* 3 pending requests */ + + /* dma_p fetch config */ + outpdw(MDP_BASE + 0x91004, 0x27); /* burst size of 8 */ + +#ifndef CONFIG_FB_MSM_OVERLAY + /* both REFRESH_MODE and DIRECT_OUT are ignored at BLT mode */ + mdp4_overlay_cfg(MDP4_MIXER0, OVERLAY_MODE_BLT, 0, 0); + mdp4_overlay_cfg(MDP4_MIXER1, OVERLAY_MODE_BLT, 0, 0); +#endif + + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); +} + + +void mdp4_clear_lcdc(void) +{ + uint32 bits; + + bits = inpdw(MDP_BASE + 0xc0000); + if (bits & 0x01) /* enabled already */ + return; + + outpdw(MDP_BASE + 0xc0004, 0); /* vsync ctrl out */ + outpdw(MDP_BASE + 0xc0008, 0); /* vsync period */ + outpdw(MDP_BASE + 0xc000c, 0); /* vsync pusle width */ + outpdw(MDP_BASE + 0xc0010, 0); /* lcdc display HCTL */ + outpdw(MDP_BASE + 0xc0014, 0); /* lcdc display v start */ + outpdw(MDP_BASE + 0xc0018, 0); /* lcdc display v end */ + outpdw(MDP_BASE + 0xc001c, 0); /* lcdc active hctl */ + outpdw(MDP_BASE + 0xc0020, 0); /* lcdc active v start */ + outpdw(MDP_BASE + 0xc0024, 0); /* lcdc active v end */ + outpdw(MDP_BASE + 0xc0028, 0); /* lcdc board color */ + outpdw(MDP_BASE + 0xc002c, 0); /* lcdc underflow ctrl */ + outpdw(MDP_BASE + 0xc0030, 0); /* lcdc hsync skew */ + outpdw(MDP_BASE + 0xc0034, 0); /* lcdc test ctl */ + outpdw(MDP_BASE + 0xc0038, 0); /* lcdc ctl polarity */ +} + +static struct mdp_dma_data overlay1_data; +static int intr_dma_p; +static int intr_dma_s; +static int intr_dma_e; +static int intr_overlay0; +static int intr_overlay1; + +irqreturn_t mdp4_isr(int irq, void *ptr) +{ + uint32 isr, mask, lcdc; + struct mdp_dma_data *dma; + + mdp_is_in_isr = TRUE; + + while (1) { + isr = inpdw(MDP_INTR_STATUS); + if (isr == 0) + break; + + mask = inpdw(MDP_INTR_ENABLE); + outpdw(MDP_INTR_CLEAR, isr); + + isr &= mask; + + if (unlikely(isr == 0)) + break; + + if (isr & INTR_DMA_P_DONE) { + intr_dma_p++; + lcdc = inpdw(MDP_BASE + 0xc0000); + dma = &dma2_data; + if (lcdc & 0x01) { /* LCDC enable */ + /* disable LCDC interrupt */ + mdp_intr_mask &= ~INTR_DMA_P_DONE; + outp32(MDP_INTR_ENABLE, mdp_intr_mask); + dma->waiting = FALSE; + } else { + dma->busy = FALSE; + mdp_pipe_ctrl(MDP_DMA2_BLOCK, + MDP_BLOCK_POWER_OFF, TRUE); + } + complete(&dma->comp); + } + if (isr & INTR_DMA_S_DONE) { + intr_dma_s++; + dma = &dma_s_data; + dma->busy = FALSE; + mdp_pipe_ctrl(MDP_DMA_S_BLOCK, + MDP_BLOCK_POWER_OFF, TRUE); + complete(&dma->comp); + } + if (isr & INTR_DMA_E_DONE) { + intr_dma_e++; + dma = &dma_e_data; + mdp_intr_mask &= ~INTR_DMA_E_DONE; + outp32(MDP_INTR_ENABLE, mdp_intr_mask); + dma->busy = FALSE; + + if (dma->waiting) { + dma->waiting = FALSE; + complete(&dma->comp); + } + } + if (isr & INTR_OVERLAY0_DONE) { + intr_overlay0++; + lcdc = inpdw(MDP_BASE + 0xc0000); + dma = &dma2_data; + if (lcdc & 0x01) { /* LCDC enable */ + /* disable LCDC interrupt */ + mdp_intr_mask &= ~INTR_OVERLAY0_DONE; + outp32(MDP_INTR_ENABLE, mdp_intr_mask); + dma->waiting = FALSE; + mdp4_overlay0_done_lcdc(); + } else { /* MDDI */ + dma->busy = FALSE; +#ifdef MDP4_NONBLOCKING + mdp_disable_irq_nolock(MDP_OVERLAY0_TERM); +#endif + mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, + MDP_BLOCK_POWER_OFF, TRUE); + mdp4_overlay0_done_mddi(); + } + } + if (isr & INTR_OVERLAY1_DONE) { + intr_overlay1++; + dma = &overlay1_data; + dma->busy = FALSE; + mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, + MDP_BLOCK_POWER_OFF, TRUE); + complete(&dma->comp); + } + if (isr & INTR_DMA_P_HISTOGRAM) { + isr = inpdw(MDP_DMA_P_HIST_INTR_STATUS); + mask = inpdw(MDP_DMA_P_HIST_INTR_ENABLE); + outpdw(MDP_DMA_P_HIST_INTR_CLEAR, isr); + isr &= mask; + if (isr & INTR_HIST_DONE) { + if (mdp_hist.r) + memcpy(mdp_hist.r, MDP_BASE + 0x95100, + mdp_hist.bin_cnt*4); + if (mdp_hist.g) + memcpy(mdp_hist.g, MDP_BASE + 0x95200, + mdp_hist.bin_cnt*4); + if (mdp_hist.b) + memcpy(mdp_hist.b, MDP_BASE + 0x95300, + mdp_hist.bin_cnt*4); + complete(&mdp_hist_comp); + } + } + } + + mdp_is_in_isr = FALSE; + + return IRQ_HANDLED; +} + + +/* + * QSEED tables + */ + +static uint32 vg_qseed_table0[] = { + 0x5556aaff, 0x00000000, 0x00000000, 0x00000000 +}; + +static uint32 vg_qseed_table1[] = { + 0x76543210, 0xfedcba98 +}; + +static uint32 vg_qseed_table2[] = { + 0x02000000, 0x00000000, 0x02060ff2, 0x00000008, + 0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021, + 0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042, + 0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068, + 0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095, + 0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6, + 0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa, + 0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d, + 0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f, + 0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f, + 0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7, + 0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc, + 0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5, + 0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203, + 0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a, + 0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206, + 0x02000000, 0x00000000, 0x02040ff2, 0x0000000a, + 0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029, + 0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050, + 0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c, + 0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae, + 0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2, + 0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117, + 0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148, + 0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177, + 0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2, + 0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4, + 0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2, + 0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6, + 0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203, + 0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208, + 0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205, + 0x02000000, 0x00000000, 0x02020ff2, 0x0000000c, + 0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030, + 0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d, + 0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e, + 0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4, + 0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9, + 0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e, + 0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d, + 0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188, + 0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae, + 0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc, + 0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7, + 0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8, + 0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202, + 0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206, + 0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204, + 0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f, + 0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e, + 0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075, + 0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad, + 0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7, + 0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e, + 0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150, + 0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b, + 0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1, + 0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0, + 0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8, + 0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed, + 0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa, + 0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202, + 0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205, + 0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203, + 0x02000000, 0x00000000, 0x02050ff5, 0x00000006, + 0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a, + 0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034, + 0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054, + 0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079, + 0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3, + 0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1, + 0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101, + 0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132, + 0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163, + 0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f, + 0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba, + 0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc, + 0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3, + 0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201, + 0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204, + 0x02000000, 0x00000000, 0x02030ff5, 0x00000008, + 0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020, + 0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040, + 0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065, + 0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f, + 0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd, + 0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee, + 0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d, + 0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d, + 0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b, + 0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2, + 0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6, + 0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3, + 0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6, + 0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202, + 0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203, + 0x02000000, 0x00000000, 0x02020ff5, 0x00000009, + 0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026, + 0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b, + 0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074, + 0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3, + 0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3, + 0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105, + 0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135, + 0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162, + 0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c, + 0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af, + 0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0, + 0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7, + 0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7, + 0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200, + 0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203, + 0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c, + 0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032, + 0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f, + 0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090, + 0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4, + 0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8, + 0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129, + 0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156, + 0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e, + 0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3, + 0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0, + 0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db, + 0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed, + 0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa, + 0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201, + 0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202, + 0x02000000, 0x00000000, 0x02040ff7, 0x00000005, + 0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016, + 0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c, + 0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046, + 0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066, + 0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b, + 0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4, + 0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0, + 0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f, + 0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140, + 0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f, + 0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e, + 0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6, + 0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5, + 0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa, + 0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202, + 0x02000000, 0x00000000, 0x02030ff7, 0x00000006, + 0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b, + 0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035, + 0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055, + 0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079, + 0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2, + 0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf, + 0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc, + 0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b, + 0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a, + 0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185, + 0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae, + 0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1, + 0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea, + 0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb, + 0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202, + 0x02000000, 0x00000000, 0x02010ff7, 0x00000008, + 0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020, + 0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f, + 0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062, + 0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b, + 0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7, + 0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6, + 0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114, + 0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141, + 0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d, + 0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196, + 0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb, + 0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8, + 0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed, + 0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb, + 0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201, + 0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a, + 0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a, + 0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051, + 0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b, + 0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa, + 0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da, + 0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a, + 0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138, + 0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162, + 0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b, + 0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab, + 0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9, + 0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1, + 0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2, + 0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd, + 0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201, + 0x02000000, 0x00000000, 0x02030ff9, 0x00000004, + 0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010, + 0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020, + 0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034, + 0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d, + 0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a, + 0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c, + 0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2, + 0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd, + 0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c, + 0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b, + 0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170, + 0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0, + 0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8, + 0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea, + 0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe, + 0x02000000, 0x00000000, 0x02020ff9, 0x00000005, + 0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014, + 0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028, + 0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040, + 0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d, + 0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f, + 0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4, + 0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd, + 0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9, + 0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128, + 0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155, + 0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185, + 0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0, + 0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3, + 0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef, + 0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff, + 0x02000000, 0x00000000, 0x02010ff9, 0x00000006, + 0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018, + 0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f, + 0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b, + 0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c, + 0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091, + 0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9, + 0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4, + 0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110, + 0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f, + 0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a, + 0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195, + 0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb, + 0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9, + 0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1, + 0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff, + 0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008, + 0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020, + 0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e, + 0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060, + 0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087, + 0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1, + 0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd, + 0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109, + 0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135, + 0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160, + 0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187, + 0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac, + 0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb, + 0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3, + 0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5, + 0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff, + 0x02000000, 0x00000000, 0x02060ff2, 0x00000008, + 0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021, + 0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042, + 0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068, + 0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095, + 0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6, + 0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa, + 0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d, + 0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f, + 0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f, + 0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7, + 0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc, + 0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5, + 0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203, + 0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a, + 0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206, + 0x02000000, 0x00000000, 0x02040ff2, 0x0000000a, + 0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029, + 0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050, + 0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c, + 0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae, + 0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2, + 0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117, + 0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148, + 0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177, + 0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2, + 0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4, + 0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2, + 0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6, + 0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203, + 0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208, + 0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205, + 0x02000000, 0x00000000, 0x02020ff2, 0x0000000c, + 0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030, + 0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d, + 0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e, + 0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4, + 0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9, + 0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e, + 0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d, + 0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188, + 0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae, + 0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc, + 0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7, + 0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8, + 0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202, + 0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206, + 0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204, + 0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f, + 0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e, + 0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075, + 0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad, + 0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7, + 0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e, + 0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150, + 0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b, + 0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1, + 0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0, + 0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8, + 0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed, + 0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa, + 0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202, + 0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205, + 0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203, + 0x02000000, 0x00000000, 0x02050ff5, 0x00000006, + 0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a, + 0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034, + 0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054, + 0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079, + 0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3, + 0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1, + 0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101, + 0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132, + 0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163, + 0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f, + 0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba, + 0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc, + 0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3, + 0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201, + 0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204, + 0x02000000, 0x00000000, 0x02030ff5, 0x00000008, + 0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020, + 0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040, + 0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065, + 0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f, + 0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd, + 0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee, + 0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d, + 0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d, + 0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b, + 0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2, + 0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6, + 0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3, + 0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6, + 0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202, + 0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203, + 0x02000000, 0x00000000, 0x02020ff5, 0x00000009, + 0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026, + 0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b, + 0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074, + 0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3, + 0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3, + 0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105, + 0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135, + 0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162, + 0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c, + 0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af, + 0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0, + 0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7, + 0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7, + 0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200, + 0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203, + 0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c, + 0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032, + 0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f, + 0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090, + 0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4, + 0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8, + 0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129, + 0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156, + 0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e, + 0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3, + 0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0, + 0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db, + 0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed, + 0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa, + 0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201, + 0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202, + 0x02000000, 0x00000000, 0x02040ff7, 0x00000005, + 0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016, + 0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c, + 0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046, + 0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066, + 0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b, + 0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4, + 0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0, + 0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f, + 0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140, + 0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f, + 0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e, + 0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6, + 0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5, + 0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa, + 0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202, + 0x02000000, 0x00000000, 0x02030ff7, 0x00000006, + 0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b, + 0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035, + 0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055, + 0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079, + 0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2, + 0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf, + 0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc, + 0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b, + 0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a, + 0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185, + 0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae, + 0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1, + 0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea, + 0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb, + 0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202, + 0x02000000, 0x00000000, 0x02010ff7, 0x00000008, + 0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020, + 0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f, + 0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062, + 0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b, + 0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7, + 0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6, + 0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114, + 0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141, + 0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d, + 0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196, + 0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb, + 0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8, + 0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed, + 0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb, + 0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201, + 0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a, + 0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a, + 0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051, + 0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b, + 0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa, + 0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da, + 0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a, + 0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138, + 0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162, + 0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b, + 0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab, + 0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9, + 0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1, + 0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2, + 0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd, + 0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201, + 0x02000000, 0x00000000, 0x02030ff9, 0x00000004, + 0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010, + 0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020, + 0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034, + 0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d, + 0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a, + 0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c, + 0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2, + 0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd, + 0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c, + 0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b, + 0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170, + 0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0, + 0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8, + 0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea, + 0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe, + 0x02000000, 0x00000000, 0x02020ff9, 0x00000005, + 0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014, + 0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028, + 0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040, + 0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d, + 0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f, + 0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4, + 0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd, + 0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9, + 0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128, + 0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155, + 0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185, + 0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0, + 0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3, + 0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef, + 0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff, + 0x02000000, 0x00000000, 0x02010ff9, 0x00000006, + 0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018, + 0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f, + 0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b, + 0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c, + 0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091, + 0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9, + 0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4, + 0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110, + 0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f, + 0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a, + 0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195, + 0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb, + 0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9, + 0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1, + 0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff, + 0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008, + 0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020, + 0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e, + 0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060, + 0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087, + 0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1, + 0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd, + 0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109, + 0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135, + 0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160, + 0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187, + 0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac, + 0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb, + 0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3, + 0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5, + 0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff +}; + + +#define MDP4_QSEED_TABLE0_OFF 0x8100 +#define MDP4_QSEED_TABLE1_OFF 0x8200 +#define MDP4_QSEED_TABLE2_OFF 0x9000 + +void mdp4_vg_qseed_init(int vp_num) +{ + uint32 *off; + int i, voff; + + voff = MDP4_VIDEO_OFF * vp_num; + off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + + MDP4_QSEED_TABLE0_OFF); + for (i = 0; i < (sizeof(vg_qseed_table0) / sizeof(uint32)); i++) { + outpdw(off, vg_qseed_table0[i]); + off++; + } + + off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + + MDP4_QSEED_TABLE1_OFF); + for (i = 0; i < (sizeof(vg_qseed_table1) / sizeof(uint32)); i++) { + outpdw(off, vg_qseed_table1[i]); + off++; + } + + off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + + MDP4_QSEED_TABLE2_OFF); + for (i = 0; i < (sizeof(vg_qseed_table2) / sizeof(uint32)); i++) { + outpdw(off, vg_qseed_table2[i]); + off++; + } + +} + +void mdp4_mixer_blend_init(mixer_num) +{ + unsigned char *overlay_base; + int off; + + if (mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */ + overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */ + else + overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */ + + /* stage 0 to stage 2 */ + off = 0; + outpdw(overlay_base + off + 0x104, 0x010); + outpdw(overlay_base + off + 0x108, 0xff);/* FG */ + outpdw(overlay_base + off + 0x10c, 0x00);/* BG */ + + off += 0x20; + outpdw(overlay_base + off + 0x104, 0x010); + outpdw(overlay_base + off + 0x108, 0xff);/* FG */ + outpdw(overlay_base + off + 0x10c, 0x00);/* BG */ + + off += 0x20; + outpdw(overlay_base + off + 0x104, 0x010); + outpdw(overlay_base + off + 0x108, 0xff);/* FG */ + outpdw(overlay_base + off + 0x10c, 0x00);/* BG */ +} + + +static uint32 csc_matrix_tab[9] = { + 0x0254, 0x0000, 0x0331, + 0x0254, 0xff37, 0xfe60, + 0x0254, 0x0409, 0x0000 +}; + +static uint32 csc_pre_bv_tab[3] = {0xfff0, 0xff80, 0xff80 }; +static uint32 csc_post_bv_tab[3] = {0, 0, 0 }; + +static uint32 csc_pre_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff }; +static uint32 csc_post_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff }; + +#define MDP4_CSC_MV_OFF 0x4400 +#define MDP4_CSC_PRE_BV_OFF 0x4500 +#define MDP4_CSC_POST_BV_OFF 0x4580 +#define MDP4_CSC_PRE_LV_OFF 0x4600 +#define MDP4_CSC_POST_LV_OFF 0x4680 + +void mdp4_vg_csc_mv_setup(int vp_num) +{ + uint32 *off; + int i, voff; + + voff = MDP4_VIDEO_OFF * vp_num; + off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + + MDP4_CSC_MV_OFF); + for (i = 0; i < 9; i++) { + outpdw(off, csc_matrix_tab[i]); + off++; + } +} + +void mdp4_vg_csc_pre_bv_setup(int vp_num) +{ + uint32 *off; + int i, voff; + + voff = MDP4_VIDEO_OFF * vp_num; + off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + + MDP4_CSC_PRE_BV_OFF); + for (i = 0; i < 3; i++) { + outpdw(off, csc_pre_bv_tab[i]); + off++; + } +} + +void mdp4_vg_csc_post_bv_setup(int vp_num) +{ + uint32 *off; + int i, voff; + + voff = MDP4_VIDEO_OFF * vp_num; + off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + + MDP4_CSC_POST_BV_OFF); + for (i = 0; i < 3; i++) { + outpdw(off, csc_post_bv_tab[i]); + off++; + } +} + +void mdp4_vg_csc_pre_lv_setup(int vp_num) +{ + uint32 *off; + int i, voff; + + voff = MDP4_VIDEO_OFF * vp_num; + off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + + MDP4_CSC_PRE_LV_OFF); + + for (i = 0; i < 6; i++) { + outpdw(off, csc_pre_lv_tab[i]); + off++; + } +} + +void mdp4_vg_csc_post_lv_setup(int vp_num) +{ + uint32 *off; + int i, voff; + + voff = MDP4_VIDEO_OFF * vp_num; + off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + + MDP4_CSC_POST_LV_OFF); + + for (i = 0; i < 6; i++) { + outpdw(off, csc_post_lv_tab[i]); + off++; + } +} + +char gc_lut[] = { + 0x0, 0x1, 0x2, 0x2, 0x3, 0x4, 0x5, 0x6, + 0x6, 0x7, 0x8, 0x9, 0xA, 0xA, 0xB, 0xC, + 0xD, 0xD, 0xE, 0xF, 0xF, 0x10, 0x10, 0x11, + 0x12, 0x12, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, + 0x16, 0x16, 0x17, 0x17, 0x17, 0x18, 0x18, 0x19, + 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C, + 0x1C, 0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, + 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, + 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, + 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, + 0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28, + 0x28, 0x29, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A, + 0x2A, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2C, 0x2C, + 0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E, + 0x2E, 0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x2F, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x32, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x35, 0x35, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39, + 0x39, 0x39, 0x39, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, + 0x3A, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3C, + 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D, + 0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, + 0x3E, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42, + 0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43, 0x43, + 0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, + 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, + 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48, + 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, + 0x49, 0x49, 0x49, 0x49, 0x49, 0x4A, 0x4A, 0x4A, + 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B, 0x4B, + 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4C, 0x4C, 0x4C, + 0x4C, 0x4C, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4D, + 0x4D, 0x4D, 0x4D, 0x4D, 0x4E, 0x4E, 0x4E, 0x4E, + 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4F, 0x4F, 0x4F, + 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x50, 0x50, 0x50, + 0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52, + 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x53, 0x53, + 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, + 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, + 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, + 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5A, 0x5A, + 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, + 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, + 0x5B, 0x5B, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, + 0x5C, 0x5C, 0x5C, 0x5C, 0x5D, 0x5D, 0x5D, 0x5D, + 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5E, 0x5E, + 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, + 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, + 0x5F, 0x5F, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, + 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x62, + 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, + 0x62, 0x62, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x64, 0x64, 0x64, + 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, + 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, + 0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x67, + 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, + 0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, + 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, + 0x69, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, + 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6B, 0x6B, 0x6B, + 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, + 0x6B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, + 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, + 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, + 0x6D, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, + 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6F, 0x6F, 0x6F, + 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, + 0x6F, 0x6F, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, + 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71, + 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, + 0x71, 0x71, 0x71, 0x72, 0x72, 0x72, 0x72, 0x72, + 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, + 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, + 0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, + 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, + 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, + 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, + 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, + 0x76, 0x76, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x78, 0x78, + 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, + 0x78, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, + 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x7A, 0x7A, + 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, + 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7B, + 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, + 0x7B, 0x7B, 0x7B, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, + 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, + 0x7C, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, + 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, + 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, + 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, + 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, + 0x83, 0x83, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, + 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, + 0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, + 0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, + 0x87, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, + 0x89, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, + 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, + 0x8A, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, + 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, + 0x8B, 0x8B, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, + 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, + 0x8C, 0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, + 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, + 0x8D, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8E, 0x8E, + 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, + 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, 0x8F, 0x8F, + 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, + 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, + 0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, + 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, + 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, + 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, + 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, + 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, + 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, + 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0x9B, 0x9B, + 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, + 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, + 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, + 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, + 0x9C, 0x9C, 0x9C, 0x9C, 0x9D, 0x9D, 0x9D, 0x9D, + 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, + 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9E, + 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, + 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, + 0x9E, 0x9E, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, + 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, + 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0xA0, 0xA0, + 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, + 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, + 0xA0, 0xA0, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, + 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, + 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA2, 0xA2, + 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, + 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, + 0xA2, 0xA2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, + 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, + 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA4, 0xA4, + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, + 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, + 0xA4, 0xA4, 0xA4, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, + 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, + 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, + 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, + 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, + 0xA6, 0xA6, 0xA6, 0xA6, 0xA7, 0xA7, 0xA7, 0xA7, + 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, + 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, + 0xA7, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, + 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, + 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA9, + 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, + 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, + 0xA9, 0xA9, 0xA9, 0xA9, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, + 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, + 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAC, + 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, + 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, + 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAD, 0xAD, 0xAD, + 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, + 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, + 0xAD, 0xAD, 0xAD, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, + 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, + 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, + 0xAE, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, + 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, + 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xB0, + 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, + 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, + 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB1, 0xB1, + 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, + 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, + 0xB1, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2, 0xB2, 0xB2, + 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, + 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, + 0xB2, 0xB2, 0xB2, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, + 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, + 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, + 0xB3, 0xB3, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, + 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, + 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, + 0xB4, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, + 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, + 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, + 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, + 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, + 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, + 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, + 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, + 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB8, + 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, + 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, + 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB9, + 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, + 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, + 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xBA, + 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, + 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, + 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, + 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, + 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, + 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, + 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, + 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, + 0xBD, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, + 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, + 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, + 0xBE, 0xBE, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, + 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, + 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, + 0xBF, 0xBF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC1, 0xC1, 0xC1, 0xC1, + 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, + 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, + 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC2, 0xC2, 0xC2, + 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, + 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, + 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC3, 0xC3, + 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, + 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, + 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, + 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, + 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, + 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, + 0xC4, 0xC4, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, + 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, + 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, + 0xC5, 0xC5, 0xC5, 0xC5, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, + 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, 0xC7, + 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, + 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, + 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, + 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, + 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, + 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, + 0xC8, 0xC8, 0xC8, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, + 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, + 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, + 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xCA, 0xCA, + 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, + 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, + 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, + 0xCA, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, + 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, + 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, + 0xCB, 0xCB, 0xCB, 0xCB, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, + 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, + 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, + 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, + 0xCD, 0xCD, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, + 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, + 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, + 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCF, 0xCF, + 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, + 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, + 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, + 0xCF, 0xCF, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, + 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD1, 0xD1, 0xD1, + 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, + 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, + 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, + 0xD1, 0xD1, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, + 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, + 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, + 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD3, 0xD3, + 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, + 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, + 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, + 0xD3, 0xD3, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, + 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, + 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, + 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD5, + 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, + 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, + 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, + 0xD5, 0xD5, 0xD5, 0xD5, 0xD6, 0xD6, 0xD6, 0xD6, + 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, + 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, + 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, + 0xD6, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, + 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, + 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, + 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD8, 0xD8, + 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, + 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, + 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, + 0xD8, 0xD8, 0xD8, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, + 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, + 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, + 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, + 0xD9, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, + 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, + 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, + 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDB, 0xDB, + 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, + 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, + 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, + 0xDB, 0xDB, 0xDB, 0xDB, 0xDC, 0xDC, 0xDC, 0xDC, + 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, + 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, + 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, + 0xDC, 0xDC, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, + 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, + 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, + 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDF, + 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, + 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, + 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, + 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xE0, 0xE0, + 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, + 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, + 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, + 0xE0, 0xE0, 0xE0, 0xE0, 0xE1, 0xE1, 0xE1, 0xE1, + 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, + 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, + 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, + 0xE1, 0xE1, 0xE1, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, + 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, + 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, + 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, + 0xE2, 0xE2, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, + 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, + 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, + 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, + 0xE3, 0xE3, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, + 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, + 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, + 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, + 0xE4, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, + 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, + 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, + 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, + 0xE5, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, + 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, + 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, + 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, + 0xE6, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, + 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, + 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, + 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, + 0xE7, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, + 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, + 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, + 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, + 0xE8, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, + 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, + 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, + 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, + 0xE9, 0xE9, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, + 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, + 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, + 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, + 0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, + 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, + 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, + 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, + 0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, + 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, + 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, + 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, + 0xEC, 0xEC, 0xEC, 0xEC, 0xED, 0xED, 0xED, 0xED, + 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, + 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, + 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, + 0xED, 0xED, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF, + 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, + 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, + 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, + 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, + 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, + 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, + 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, + 0xF1, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF2, 0xF2, + 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, + 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, + 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, + 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF3, 0xF3, + 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, + 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, + 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, + 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, + 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, + 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, + 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, + 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, + 0xF4, 0xF4, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, + 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, + 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, + 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, + 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6, + 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, + 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, + 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, + 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, + 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, + 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, + 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, + 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, + 0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, + 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, + 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, + 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, + 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9, + 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, + 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, + 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, + 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, + 0xF9, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, + 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, + 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, + 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, + 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB, + 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, + 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, + 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, + 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, + 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, + 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, + 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, + 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, + 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, + 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +void mdp4_mixer_gc_lut_setup(int mixer_num) +{ + unsigned char *base; + uint32 data; + char val; + int i, off; + + if (mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */ + base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */ + else + base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */ + + base += 0x4000; /* GC_LUT offset */ + + off = 0; + for (i = 0; i < 4096; i++) { + val = gc_lut[i]; + data = (val << 16 | val << 8 | val); /* R, B, and G are same */ + outpdw(base + off, data); + off += 4; + } +} + +uint32 igc_video_lut[] = { /* non linear */ + 0x0, 0x1, 0x2, 0x4, 0x5, 0x6, 0x7, 0x9, + 0xA, 0xB, 0xC, 0xE, 0xF, 0x10, 0x12, 0x14, + 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23, + 0x25, 0x28, 0x2A, 0x2D, 0x30, 0x32, 0x35, 0x38, + 0x3B, 0x3E, 0x42, 0x45, 0x48, 0x4C, 0x4F, 0x53, + 0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x70, 0x74, + 0x79, 0x7E, 0x83, 0x88, 0x8D, 0x92, 0x97, 0x9C, + 0xA2, 0xA8, 0xAD, 0xB3, 0xB9, 0xBF, 0xC5, 0xCC, + 0xD2, 0xD8, 0xDF, 0xE6, 0xED, 0xF4, 0xFB, 0x102, + 0x109, 0x111, 0x118, 0x120, 0x128, 0x130, 0x138, 0x140, + 0x149, 0x151, 0x15A, 0x162, 0x16B, 0x174, 0x17D, 0x186, + 0x190, 0x199, 0x1A3, 0x1AC, 0x1B6, 0x1C0, 0x1CA, 0x1D5, + 0x1DF, 0x1EA, 0x1F4, 0x1FF, 0x20A, 0x215, 0x220, 0x22B, + 0x237, 0x242, 0x24E, 0x25A, 0x266, 0x272, 0x27F, 0x28B, + 0x298, 0x2A4, 0x2B1, 0x2BE, 0x2CB, 0x2D8, 0x2E6, 0x2F3, + 0x301, 0x30F, 0x31D, 0x32B, 0x339, 0x348, 0x356, 0x365, + 0x374, 0x383, 0x392, 0x3A1, 0x3B1, 0x3C0, 0x3D0, 0x3E0, + 0x3F0, 0x400, 0x411, 0x421, 0x432, 0x443, 0x454, 0x465, + 0x476, 0x487, 0x499, 0x4AB, 0x4BD, 0x4CF, 0x4E1, 0x4F3, + 0x506, 0x518, 0x52B, 0x53E, 0x551, 0x565, 0x578, 0x58C, + 0x5A0, 0x5B3, 0x5C8, 0x5DC, 0x5F0, 0x605, 0x61A, 0x62E, + 0x643, 0x659, 0x66E, 0x684, 0x699, 0x6AF, 0x6C5, 0x6DB, + 0x6F2, 0x708, 0x71F, 0x736, 0x74D, 0x764, 0x77C, 0x793, + 0x7AB, 0x7C3, 0x7DB, 0x7F3, 0x80B, 0x824, 0x83D, 0x855, + 0x86F, 0x888, 0x8A1, 0x8BB, 0x8D4, 0x8EE, 0x908, 0x923, + 0x93D, 0x958, 0x973, 0x98E, 0x9A9, 0x9C4, 0x9DF, 0x9FB, + 0xA17, 0xA33, 0xA4F, 0xA6C, 0xA88, 0xAA5, 0xAC2, 0xADF, + 0xAFC, 0xB19, 0xB37, 0xB55, 0xB73, 0xB91, 0xBAF, 0xBCE, + 0xBEC, 0xC0B, 0xC2A, 0xC4A, 0xC69, 0xC89, 0xCA8, 0xCC8, + 0xCE8, 0xD09, 0xD29, 0xD4A, 0xD6B, 0xD8C, 0xDAD, 0xDCF, + 0xDF0, 0xE12, 0xE34, 0xE56, 0xE79, 0xE9B, 0xEBE, 0xEE1, + 0xF04, 0xF27, 0xF4B, 0xF6E, 0xF92, 0xFB6, 0xFDB, 0xFFF, +}; + +void mdp4_vg_igc_lut_setup(int vp_num) +{ + unsigned char *base; + int i, voff, off; + uint32 data, val; + + voff = MDP4_VIDEO_OFF * vp_num; + base = MDP_BASE + MDP4_VIDEO_BASE + voff + 0x5000; + + off = 0; + for (i = 0; i < 256; i++) { + val = igc_video_lut[i]; + data = (val << 16 | val); /* color 0 and 1 */ + outpdw(base + off, data); + outpdw(base + off + 0x800, val); /* color 2 */ + off += 4; + } +} + +uint32 igc_rgb_lut[] = { /* linear */ + 0x0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, + 0x101, 0x111, 0x121, 0x131, 0x141, 0x151, 0x161, 0x171, + 0x181, 0x191, 0x1A2, 0x1B2, 0x1C2, 0x1D2, 0x1E2, 0x1F2, + 0x202, 0x212, 0x222, 0x232, 0x242, 0x252, 0x262, 0x272, + 0x282, 0x292, 0x2A2, 0x2B3, 0x2C3, 0x2D3, 0x2E3, 0x2F3, + 0x303, 0x313, 0x323, 0x333, 0x343, 0x353, 0x363, 0x373, + 0x383, 0x393, 0x3A3, 0x3B3, 0x3C4, 0x3D4, 0x3E4, 0x3F4, + 0x404, 0x414, 0x424, 0x434, 0x444, 0x454, 0x464, 0x474, + 0x484, 0x494, 0x4A4, 0x4B4, 0x4C4, 0x4D5, 0x4E5, 0x4F5, + 0x505, 0x515, 0x525, 0x535, 0x545, 0x555, 0x565, 0x575, + 0x585, 0x595, 0x5A5, 0x5B5, 0x5C5, 0x5D5, 0x5E6, 0x5F6, + 0x606, 0x616, 0x626, 0x636, 0x646, 0x656, 0x666, 0x676, + 0x686, 0x696, 0x6A6, 0x6B6, 0x6C6, 0x6D6, 0x6E6, 0x6F7, + 0x707, 0x717, 0x727, 0x737, 0x747, 0x757, 0x767, 0x777, + 0x787, 0x797, 0x7A7, 0x7B7, 0x7C7, 0x7D7, 0x7E7, 0x7F7, + 0x808, 0x818, 0x828, 0x838, 0x848, 0x858, 0x868, 0x878, + 0x888, 0x898, 0x8A8, 0x8B8, 0x8C8, 0x8D8, 0x8E8, 0x8F8, + 0x908, 0x919, 0x929, 0x939, 0x949, 0x959, 0x969, 0x979, + 0x989, 0x999, 0x9A9, 0x9B9, 0x9C9, 0x9D9, 0x9E9, 0x9F9, + 0xA09, 0xA19, 0xA2A, 0xA3A, 0xA4A, 0xA5A, 0xA6A, 0xA7A, + 0xA8A, 0xA9A, 0xAAA, 0xABA, 0xACA, 0xADA, 0xAEA, 0xAFA, + 0xB0A, 0xB1A, 0xB2A, 0xB3B, 0xB4B, 0xB5B, 0xB6B, 0xB7B, + 0xB8B, 0xB9B, 0xBAB, 0xBBB, 0xBCB, 0xBDB, 0xBEB, 0xBFB, + 0xC0B, 0xC1B, 0xC2B, 0xC3B, 0xC4C, 0xC5C, 0xC6C, 0xC7C, + 0xC8C, 0xC9C, 0xCAC, 0xCBC, 0xCCC, 0xCDC, 0xCEC, 0xCFC, + 0xD0C, 0xD1C, 0xD2C, 0xD3C, 0xD4C, 0xD5D, 0xD6D, 0xD7D, + 0xD8D, 0xD9D, 0xDAD, 0xDBD, 0xDCD, 0xDDD, 0xDED, 0xDFD, + 0xE0D, 0xE1D, 0xE2D, 0xE3D, 0xE4D, 0xE5D, 0xE6E, 0xE7E, + 0xE8E, 0xE9E, 0xEAE, 0xEBE, 0xECE, 0xEDE, 0xEEE, 0xEFE, + 0xF0E, 0xF1E, 0xF2E, 0xF3E, 0xF4E, 0xF5E, 0xF6E, 0xF7F, + 0xF8F, 0xF9F, 0xFAF, 0xFBF, 0xFCF, 0xFDF, 0xFEF, 0xFFF, +}; + +void mdp4_rgb_igc_lut_setup(int num) +{ + unsigned char *base; + int i, voff, off; + uint32 data, val; + + voff = MDP4_RGB_OFF * num; + base = MDP_BASE + MDP4_RGB_BASE + voff + 0x5000; + + off = 0; + for (i = 0; i < 256; i++) { + val = igc_rgb_lut[i]; + data = (val << 16 | val); /* color 0 and 1 */ + outpdw(base + off, data); + outpdw(base + off + 0x800, val); /* color 2 */ + off += 4; + } +} diff --git a/drivers/staging/msm/mdp_cursor.c b/drivers/staging/msm/mdp_cursor.c new file mode 100644 index 000000000000..7d28f30d9313 --- /dev/null +++ b/drivers/staging/msm/mdp_cursor.c @@ -0,0 +1,104 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/hrtimer.h> + +#include <mach/hardware.h> +#include <asm/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/spinlock.h> + +#include <linux/fb.h> + +#include "mdp.h" +#include "msm_fb.h" + +static int cursor_enabled; + +int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + struct fb_image *img = &cursor->image; + int calpha_en, transp_en; + int alpha; + int ret = 0; + + if ((img->width > MDP_CURSOR_WIDTH) || + (img->height > MDP_CURSOR_HEIGHT) || + (img->depth != 32)) + return -EINVAL; + + if (cursor->set & FB_CUR_SETPOS) + MDP_OUTP(MDP_BASE + 0x9004c, (img->dy << 16) | img->dx); + + if (cursor->set & FB_CUR_SETIMAGE) { + ret = copy_from_user(mfd->cursor_buf, img->data, + img->width*img->height*4); + if (ret) + return ret; + + if (img->bg_color == 0xffffffff) + transp_en = 0; + else + transp_en = 1; + + alpha = (img->fg_color & 0xff000000) >> 24; + + if (alpha) + calpha_en = 0x2; /* xrgb */ + else + calpha_en = 0x1; /* argb */ + + MDP_OUTP(MDP_BASE + 0x90044, (img->height << 16) | img->width); + MDP_OUTP(MDP_BASE + 0x90048, mfd->cursor_buf_phys); + /* order the writes the cursor_buf before updating the + * hardware */ +// dma_coherent_pre_ops(); + MDP_OUTP(MDP_BASE + 0x90060, + (transp_en << 3) | (calpha_en << 1) | + (inp32(MDP_BASE + 0x90060) & 0x1)); +#ifdef CONFIG_FB_MSM_MDP40 + MDP_OUTP(MDP_BASE + 0x90064, (alpha << 24)); + MDP_OUTP(MDP_BASE + 0x90068, (0xffffff & img->bg_color)); + MDP_OUTP(MDP_BASE + 0x9006C, (0xffffff & img->bg_color)); +#else + MDP_OUTP(MDP_BASE + 0x90064, + (alpha << 24) | (0xffffff & img->bg_color)); + MDP_OUTP(MDP_BASE + 0x90068, 0); +#endif + } + + if ((cursor->enable) && (!cursor_enabled)) { + cursor_enabled = 1; + MDP_OUTP(MDP_BASE + 0x90060, inp32(MDP_BASE + 0x90060) | 0x1); + } else if ((!cursor->enable) && (cursor_enabled)) { + cursor_enabled = 0; + MDP_OUTP(MDP_BASE + 0x90060, + inp32(MDP_BASE + 0x90060) & (~0x1)); + } + + return 0; +} diff --git a/drivers/staging/msm/mdp_dma.c b/drivers/staging/msm/mdp_dma.c new file mode 100644 index 000000000000..639918b143b4 --- /dev/null +++ b/drivers/staging/msm/mdp_dma.c @@ -0,0 +1,561 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/hrtimer.h> + +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/spinlock.h> + +#include <linux/fb.h> + +#include "mdp.h" +#include "msm_fb.h" +#include "mddihost.h" + +static uint32 mdp_last_dma2_update_width; +static uint32 mdp_last_dma2_update_height; +static uint32 mdp_curr_dma2_update_width; +static uint32 mdp_curr_dma2_update_height; + +ktime_t mdp_dma2_last_update_time = { 0 }; + +int mdp_lcd_rd_cnt_offset_slow = 20; +int mdp_lcd_rd_cnt_offset_fast = 20; +int mdp_vsync_usec_wait_line_too_short = 5; +uint32 mdp_dma2_update_time_in_usec; +uint32 mdp_total_vdopkts; + +extern u32 msm_fb_debug_enabled; +extern struct workqueue_struct *mdp_dma_wq; + +int vsync_start_y_adjust = 4; + +static void mdp_dma2_update_lcd(struct msm_fb_data_type *mfd) +{ + MDPIBUF *iBuf = &mfd->ibuf; + int mddi_dest = FALSE; + uint32 outBpp = iBuf->bpp; + uint32 dma2_cfg_reg; + uint8 *src; + uint32 mddi_ld_param; + uint16 mddi_vdo_packet_reg; + struct msm_fb_panel_data *pdata = + (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; + uint32 ystride = mfd->fbi->fix.line_length; + + dma2_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB | + DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS; + +#ifdef CONFIG_FB_MSM_MDP30 + /* + * Software workaround: On 7x25/7x27, the MDP will not + * respond if dma_w is 1 pixel. Set the update width to + * 2 pixels and adjust the x offset if needed. + */ + if (iBuf->dma_w == 1) { + iBuf->dma_w = 2; + if (iBuf->dma_x == (iBuf->ibuf_width - 2)) + iBuf->dma_x--; + } +#endif + + if (mfd->fb_imgType == MDP_BGR_565) + dma2_cfg_reg |= DMA_PACK_PATTERN_BGR; + else + dma2_cfg_reg |= DMA_PACK_PATTERN_RGB; + + if (outBpp == 4) + dma2_cfg_reg |= DMA_IBUF_C3ALPHA_EN; + + if (outBpp == 2) + dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565; + + mddi_ld_param = 0; + mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt; + + if ((mfd->panel_info.type == MDDI_PANEL) || + (mfd->panel_info.type == EXT_MDDI_PANEL)) { + dma2_cfg_reg |= DMA_OUT_SEL_MDDI; + mddi_dest = TRUE; + + if (mfd->panel_info.type == MDDI_PANEL) { + mdp_total_vdopkts++; + if (mfd->panel_info.pdest == DISPLAY_1) { + dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY; + mddi_ld_param = 0; +#ifdef MDDI_HOST_WINDOW_WORKAROUND + mddi_window_adjust(mfd, iBuf->dma_x, + iBuf->dma_w - 1, iBuf->dma_y, + iBuf->dma_h - 1); +#endif + } else { + dma2_cfg_reg |= + DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY; + mddi_ld_param = 1; +#ifdef MDDI_HOST_WINDOW_WORKAROUND + mddi_window_adjust(mfd, iBuf->dma_x, + iBuf->dma_w - 1, iBuf->dma_y, + iBuf->dma_h - 1); +#endif + } + } else { + dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL; + mddi_ld_param = 2; + } + } else { + if (mfd->panel_info.pdest == DISPLAY_1) { + dma2_cfg_reg |= DMA_AHBM_LCD_SEL_PRIMARY; + outp32(MDP_EBI2_LCD0, mfd->data_port_phys); + } else { + dma2_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY; + outp32(MDP_EBI2_LCD1, mfd->data_port_phys); + } + } + + dma2_cfg_reg |= DMA_DITHER_EN; + + src = (uint8 *) iBuf->buf; + /* starting input address */ + src += iBuf->dma_x * outBpp + iBuf->dma_y * ystride; + + mdp_curr_dma2_update_width = iBuf->dma_w; + mdp_curr_dma2_update_height = iBuf->dma_h; + + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + +#ifdef CONFIG_FB_MSM_MDP22 + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0184, + (iBuf->dma_h << 16 | iBuf->dma_w)); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0188, src); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x018C, ystride); +#else + MDP_OUTP(MDP_BASE + 0x90004, (iBuf->dma_h << 16 | iBuf->dma_w)); + MDP_OUTP(MDP_BASE + 0x90008, src); + MDP_OUTP(MDP_BASE + 0x9000c, ystride); +#endif + + if (mfd->panel_info.bpp == 18) { + dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */ + DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS; + } else { + dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */ + DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS; + } + + if (mddi_dest) { +#ifdef CONFIG_FB_MSM_MDP22 + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0194, + (iBuf->dma_y << 16) | iBuf->dma_x); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0, mddi_ld_param); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4, + (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg); +#else + MDP_OUTP(MDP_BASE + 0x90010, (iBuf->dma_y << 16) | iBuf->dma_x); + MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param); + MDP_OUTP(MDP_BASE + 0x00094, + (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg); +#endif + } else { + /* setting EBI2 LCDC write window */ + pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w, + iBuf->dma_h); + } + + /* dma2 config register */ +#ifdef MDP_HW_VSYNC + MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg); + + if ((mfd->use_mdp_vsync) && + (mfd->ibuf.vsync_enable) && (mfd->panel_info.lcd.vsync_enable)) { + uint32 start_y; + + if (vsync_start_y_adjust <= iBuf->dma_y) + start_y = iBuf->dma_y - vsync_start_y_adjust; + else + start_y = + (mfd->total_lcd_lines - 1) - (vsync_start_y_adjust - + iBuf->dma_y); + + /* + * MDP VSYNC clock must be On by now so, we don't have to + * re-enable it + */ + MDP_OUTP(MDP_BASE + 0x210, start_y); + MDP_OUTP(MDP_BASE + 0x20c, 1); /* enable prim vsync */ + } else { + MDP_OUTP(MDP_BASE + 0x20c, 0); /* disable prim vsync */ + } +#else +#ifdef CONFIG_FB_MSM_MDP22 + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0180, dma2_cfg_reg); +#else + MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg); +#endif +#endif /* MDP_HW_VSYNC */ + + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); +} + +static ktime_t vt = { 0 }; +int mdp_usec_diff_threshold = 100; +int mdp_expected_usec_wait; + +enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht) +{ + struct msm_fb_data_type *mfd = NULL; + + mfd = container_of(ht, struct msm_fb_data_type, dma_hrtimer); + + mdp_pipe_kickoff(MDP_DMA2_TERM, mfd); + + if (msm_fb_debug_enabled) { + ktime_t t; + int usec_diff; + int actual_wait; + + t = ktime_get_real(); + + actual_wait = + (t.tv.sec - vt.tv.sec) * 1000000 + (t.tv.nsec - + vt.tv.nsec) / 1000; + usec_diff = actual_wait - mdp_expected_usec_wait; + + if ((mdp_usec_diff_threshold < usec_diff) || (usec_diff < 0)) + MSM_FB_DEBUG + ("HRT Diff = %d usec Exp=%d usec Act=%d usec\n", + usec_diff, mdp_expected_usec_wait, actual_wait); + } + + return HRTIMER_NORESTART; +} + +static void mdp_dma_schedule(struct msm_fb_data_type *mfd, uint32 term) +{ + /* + * dma2 configure VSYNC block + * vsync supported on Primary LCD only for now + */ + int32 mdp_lcd_rd_cnt; + uint32 usec_wait_time; + uint32 start_y; + + /* + * ToDo: if we can move HRT timer callback to workqueue, we can + * move DMA2 power on under mdp_pipe_kickoff(). + * This will save a power for hrt time wait. + * However if the latency for context switch (hrt irq -> workqueue) + * is too big, we will miss the vsync timing. + */ + if (term == MDP_DMA2_TERM) + mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + + mdp_dma2_update_time_in_usec = + MDP_KTIME2USEC(mdp_dma2_last_update_time); + + if ((!mfd->ibuf.vsync_enable) || (!mfd->panel_info.lcd.vsync_enable) + || (mfd->use_mdp_vsync)) { + mdp_pipe_kickoff(term, mfd); + return; + } + /* SW vsync logic starts here */ + + /* get current rd counter */ + mdp_lcd_rd_cnt = mdp_get_lcd_line_counter(mfd); + if (mdp_dma2_update_time_in_usec != 0) { + uint32 num, den; + + /* + * roi width boundary calculation to know the size of pixel + * width that MDP can send faster or slower than LCD read + * pointer + */ + + num = mdp_last_dma2_update_width * mdp_last_dma2_update_height; + den = + (((mfd->panel_info.lcd.refx100 * mfd->total_lcd_lines) / + 1000) * (mdp_dma2_update_time_in_usec / 100)) / 1000; + + if (den == 0) + mfd->vsync_width_boundary[mdp_last_dma2_update_width] = + mfd->panel_info.xres + 1; + else + mfd->vsync_width_boundary[mdp_last_dma2_update_width] = + (int)(num / den); + } + + if (mfd->vsync_width_boundary[mdp_last_dma2_update_width] > + mdp_curr_dma2_update_width) { + /* MDP wrp is faster than LCD rdp */ + mdp_lcd_rd_cnt += mdp_lcd_rd_cnt_offset_fast; + } else { + /* MDP wrp is slower than LCD rdp */ + mdp_lcd_rd_cnt -= mdp_lcd_rd_cnt_offset_slow; + } + + if (mdp_lcd_rd_cnt < 0) + mdp_lcd_rd_cnt = mfd->total_lcd_lines + mdp_lcd_rd_cnt; + else if (mdp_lcd_rd_cnt > mfd->total_lcd_lines) + mdp_lcd_rd_cnt = mdp_lcd_rd_cnt - mfd->total_lcd_lines - 1; + + /* get wrt pointer position */ + start_y = mfd->ibuf.dma_y; + + /* measure line difference between start_y and rd counter */ + if (start_y > mdp_lcd_rd_cnt) { + /* + * *100 for lcd_ref_hzx100 was already multiplied by 100 + * *1000000 is for usec conversion + */ + + if ((start_y - mdp_lcd_rd_cnt) <= + mdp_vsync_usec_wait_line_too_short) + usec_wait_time = 0; + else + usec_wait_time = + ((start_y - + mdp_lcd_rd_cnt) * 1000000) / + ((mfd->total_lcd_lines * + mfd->panel_info.lcd.refx100) / 100); + } else { + if ((start_y + (mfd->total_lcd_lines - mdp_lcd_rd_cnt)) <= + mdp_vsync_usec_wait_line_too_short) + usec_wait_time = 0; + else + usec_wait_time = + ((start_y + + (mfd->total_lcd_lines - + mdp_lcd_rd_cnt)) * 1000000) / + ((mfd->total_lcd_lines * + mfd->panel_info.lcd.refx100) / 100); + } + + mdp_last_dma2_update_width = mdp_curr_dma2_update_width; + mdp_last_dma2_update_height = mdp_curr_dma2_update_height; + + if (usec_wait_time == 0) { + mdp_pipe_kickoff(term, mfd); + } else { + ktime_t wait_time; + + wait_time.tv.sec = 0; + wait_time.tv.nsec = usec_wait_time * 1000; + + if (msm_fb_debug_enabled) { + vt = ktime_get_real(); + mdp_expected_usec_wait = usec_wait_time; + } + hrtimer_start(&mfd->dma_hrtimer, wait_time, HRTIMER_MODE_REL); + } +} + +#ifdef MDDI_HOST_WINDOW_WORKAROUND +void mdp_dma2_update(struct msm_fb_data_type *mfd) +{ + MDPIBUF *iBuf; + uint32 upper_height; + + if (mfd->panel.type == EXT_MDDI_PANEL) { + mdp_dma2_update_sub(mfd); + return; + } + + iBuf = &mfd->ibuf; + + upper_height = + (uint32) mddi_assign_pkt_height((uint16) iBuf->dma_w, + (uint16) iBuf->dma_h, 18); + + if (upper_height >= iBuf->dma_h) { + mdp_dma2_update_sub(mfd); + } else { + MDPIBUF lower_height; + + /* sending the upper region first */ + lower_height = iBuf->dma_h - upper_height; + iBuf->dma_h = upper_height; + mdp_dma2_update_sub(mfd); + + /* sending the lower region second */ + iBuf->dma_h = lower_height; + iBuf->dma_y += lower_height; + iBuf->vsync_enable = FALSE; + mdp_dma2_update_sub(mfd); + } +} + +void mdp_dma2_update_sub(struct msm_fb_data_type *mfd) +#else +void mdp_dma2_update(struct msm_fb_data_type *mfd) +#endif +{ + down(&mfd->dma->mutex); + if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) { + down(&mfd->sem); + mfd->ibuf_flushed = TRUE; + mdp_dma2_update_lcd(mfd); + + mdp_enable_irq(MDP_DMA2_TERM); + mfd->dma->busy = TRUE; + INIT_COMPLETION(mfd->dma->comp); + + /* schedule DMA to start */ + mdp_dma_schedule(mfd, MDP_DMA2_TERM); + up(&mfd->sem); + + /* wait until DMA finishes the current job */ + wait_for_completion_killable(&mfd->dma->comp); + mdp_disable_irq(MDP_DMA2_TERM); + + /* signal if pan function is waiting for the update completion */ + if (mfd->pan_waiting) { + mfd->pan_waiting = FALSE; + complete(&mfd->pan_comp); + } + } + up(&mfd->dma->mutex); +} + +void mdp_lcd_update_workqueue_handler(struct work_struct *work) +{ + struct msm_fb_data_type *mfd = NULL; + + mfd = container_of(work, struct msm_fb_data_type, dma_update_worker); + if (mfd) + mfd->dma_fnc(mfd); +} + +void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty, + boolean sync) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + MDPIBUF *iBuf; + int bpp = info->var.bits_per_pixel / 8; + + down(&mfd->sem); + iBuf = &mfd->ibuf; + iBuf->buf = (uint8 *) info->fix.smem_start; + iBuf->buf += info->var.xoffset * bpp + + info->var.yoffset * info->fix.line_length; + + iBuf->ibuf_width = info->var.xres_virtual; + iBuf->bpp = bpp; + + iBuf->vsync_enable = sync; + + if (dirty) { + /* + * ToDo: dirty region check inside var.xoffset+xres + * <-> var.yoffset+yres + */ + iBuf->dma_x = dirty->xoffset % info->var.xres; + iBuf->dma_y = dirty->yoffset % info->var.yres; + iBuf->dma_w = dirty->width; + iBuf->dma_h = dirty->height; + } else { + iBuf->dma_x = 0; + iBuf->dma_y = 0; + iBuf->dma_w = info->var.xres; + iBuf->dma_h = info->var.yres; + } + mfd->ibuf_flushed = FALSE; + up(&mfd->sem); +} + +void mdp_set_offset_info(struct fb_info *info, uint32 addr, uint32 sync) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + MDPIBUF *iBuf; + + int bpp = info->var.bits_per_pixel / 8; + + down(&mfd->sem); + iBuf = &mfd->ibuf; + iBuf->ibuf_width = info->var.xres_virtual; + iBuf->bpp = bpp; + iBuf->vsync_enable = sync; + iBuf->dma_x = 0; + iBuf->dma_y = 0; + iBuf->dma_w = info->var.xres; + iBuf->dma_h = info->var.yres; + iBuf->buf = (uint8 *) addr; + + mfd->ibuf_flushed = FALSE; + up(&mfd->sem); +} + +void mdp_dma_pan_update(struct fb_info *info) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + MDPIBUF *iBuf; + + iBuf = &mfd->ibuf; + + if (mfd->sw_currently_refreshing) { + /* we need to wait for the pending update */ + mfd->pan_waiting = TRUE; + if (!mfd->ibuf_flushed) { + wait_for_completion_killable(&mfd->pan_comp); + } + /* waiting for this update to complete */ + mfd->pan_waiting = TRUE; + wait_for_completion_killable(&mfd->pan_comp); + } else + mfd->dma_fnc(mfd); +} + +void mdp_refresh_screen(unsigned long data) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data; + + if ((mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) { + init_timer(&mfd->refresh_timer); + mfd->refresh_timer.function = mdp_refresh_screen; + mfd->refresh_timer.data = data; + + if (mfd->dma->busy) + /* come back in 1 msec */ + mfd->refresh_timer.expires = jiffies + (HZ / 1000); + else + mfd->refresh_timer.expires = + jiffies + mfd->refresh_timer_duration; + + add_timer(&mfd->refresh_timer); + + if (!mfd->dma->busy) { + if (!queue_work(mdp_dma_wq, &mfd->dma_update_worker)) { + MSM_FB_DEBUG("mdp_dma: can't queue_work! -> \ + MDP/MDDI/LCD clock speed needs to be increased\n"); + } + } + } else { + if (!mfd->hw_refresh) + complete(&mfd->refresher_comp); + } +} diff --git a/drivers/staging/msm/mdp_dma_lcdc.c b/drivers/staging/msm/mdp_dma_lcdc.c new file mode 100644 index 000000000000..b57fa1a0ceb0 --- /dev/null +++ b/drivers/staging/msm/mdp_dma_lcdc.c @@ -0,0 +1,379 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/hrtimer.h> +#include <linux/delay.h> +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/spinlock.h> + +#include <linux/fb.h> + +#include "mdp.h" +#include "msm_fb.h" +#include "mdp4.h" + +#ifdef CONFIG_FB_MSM_MDP40 +#define LCDC_BASE 0xC0000 +#define DTV_BASE 0xD0000 +#define DMA_E_BASE 0xB0000 +#else +#define LCDC_BASE 0xE0000 +#endif + +#define DMA_P_BASE 0x90000 + +extern spinlock_t mdp_spin_lock; +#ifndef CONFIG_FB_MSM_MDP40 +extern uint32 mdp_intr_mask; +#endif + +int first_pixel_start_x; +int first_pixel_start_y; + +int mdp_lcdc_on(struct platform_device *pdev) +{ + int lcdc_width; + int lcdc_height; + int lcdc_bpp; + int lcdc_border_clr; + int lcdc_underflow_clr; + int lcdc_hsync_skew; + + int hsync_period; + int hsync_ctrl; + int vsync_period; + int display_hctl; + int display_v_start; + int display_v_end; + int active_hctl; + int active_h_start; + int active_h_end; + int active_v_start; + int active_v_end; + int ctrl_polarity; + int h_back_porch; + int h_front_porch; + int v_back_porch; + int v_front_porch; + int hsync_pulse_width; + int vsync_pulse_width; + int hsync_polarity; + int vsync_polarity; + int data_en_polarity; + int hsync_start_x; + int hsync_end_x; + uint8 *buf; + int bpp; + uint32 dma2_cfg_reg; + struct fb_info *fbi; + struct fb_var_screeninfo *var; + struct msm_fb_data_type *mfd; + uint32 dma_base; + uint32 timer_base = LCDC_BASE; + uint32 block = MDP_DMA2_BLOCK; + int ret; + + mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); + + if (!mfd) + return -ENODEV; + + if (mfd->key != MFD_KEY) + return -EINVAL; + + fbi = mfd->fbi; + var = &fbi->var; + + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + + bpp = fbi->var.bits_per_pixel / 8; + buf = (uint8 *) fbi->fix.smem_start; + buf += fbi->var.xoffset * bpp + fbi->var.yoffset * fbi->fix.line_length; + + dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_DITHER_EN | DMA_OUT_SEL_LCDC; + + if (mfd->fb_imgType == MDP_BGR_565) + dma2_cfg_reg |= DMA_PACK_PATTERN_BGR; + else + dma2_cfg_reg |= DMA_PACK_PATTERN_RGB; + + if (bpp == 2) + dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565; + else if (bpp == 3) + dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB888; + else + dma2_cfg_reg |= DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888; + + switch (mfd->panel_info.bpp) { + case 24: + dma2_cfg_reg |= DMA_DSTC0G_8BITS | + DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS; + break; + + case 18: + dma2_cfg_reg |= DMA_DSTC0G_6BITS | + DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS; + break; + + case 16: + dma2_cfg_reg |= DMA_DSTC0G_6BITS | + DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS; + break; + + default: + printk(KERN_ERR "mdp lcdc can't support format %d bpp!\n", + mfd->panel_info.bpp); + return -ENODEV; + } + + /* DMA register config */ + + dma_base = DMA_P_BASE; + +#ifdef CONFIG_FB_MSM_MDP40 + if (mfd->panel.type == HDMI_PANEL) + dma_base = DMA_E_BASE; +#endif + + /* starting address */ + MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf); + /* active window width and height */ + MDP_OUTP(MDP_BASE + dma_base + 0x4, ((fbi->var.yres) << 16) | + (fbi->var.xres)); + /* buffer ystride */ + MDP_OUTP(MDP_BASE + dma_base + 0xc, fbi->fix.line_length); + /* x/y coordinate = always 0 for lcdc */ + MDP_OUTP(MDP_BASE + dma_base + 0x10, 0); + /* dma config */ + MDP_OUTP(MDP_BASE + dma_base, dma2_cfg_reg); + + /* + * LCDC timing setting + */ + h_back_porch = var->left_margin; + h_front_porch = var->right_margin; + v_back_porch = var->upper_margin; + v_front_porch = var->lower_margin; + hsync_pulse_width = var->hsync_len; + vsync_pulse_width = var->vsync_len; + lcdc_border_clr = mfd->panel_info.lcdc.border_clr; + lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr; + lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew; + + lcdc_width = mfd->panel_info.xres; + lcdc_height = mfd->panel_info.yres; + lcdc_bpp = mfd->panel_info.bpp; + + hsync_period = + hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch; + hsync_ctrl = (hsync_period << 16) | hsync_pulse_width; + hsync_start_x = hsync_pulse_width + h_back_porch; + hsync_end_x = hsync_period - h_front_porch - 1; + display_hctl = (hsync_end_x << 16) | hsync_start_x; + + vsync_period = + (vsync_pulse_width + v_back_porch + lcdc_height + + v_front_porch) * hsync_period; + display_v_start = + (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew; + display_v_end = + vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1; + + if (lcdc_width != var->xres) { + active_h_start = hsync_start_x + first_pixel_start_x; + active_h_end = active_h_start + var->xres - 1; + active_hctl = + ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start; + } else { + active_hctl = 0; + } + + if (lcdc_height != var->yres) { + active_v_start = + display_v_start + first_pixel_start_y * hsync_period; + active_v_end = active_v_start + (var->yres) * hsync_period - 1; + active_v_start |= ACTIVE_START_Y_EN; + } else { + active_v_start = 0; + active_v_end = 0; + } + + +#ifdef CONFIG_FB_MSM_MDP40 + if (mfd->panel.type == HDMI_PANEL) { + block = MDP_DMA_E_BLOCK; + timer_base = DTV_BASE; + hsync_polarity = 0; + vsync_polarity = 0; + } else { + hsync_polarity = 1; + vsync_polarity = 1; + } + + lcdc_underflow_clr |= 0x80000000; /* enable recovery */ +#else + hsync_polarity = 0; + vsync_polarity = 0; +#endif + data_en_polarity = 0; + + ctrl_polarity = + (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity); + + MDP_OUTP(MDP_BASE + timer_base + 0x4, hsync_ctrl); + MDP_OUTP(MDP_BASE + timer_base + 0x8, vsync_period); + MDP_OUTP(MDP_BASE + timer_base + 0xc, vsync_pulse_width * hsync_period); + if (timer_base == LCDC_BASE) { + MDP_OUTP(MDP_BASE + timer_base + 0x10, display_hctl); + MDP_OUTP(MDP_BASE + timer_base + 0x14, display_v_start); + MDP_OUTP(MDP_BASE + timer_base + 0x18, display_v_end); + MDP_OUTP(MDP_BASE + timer_base + 0x28, lcdc_border_clr); + MDP_OUTP(MDP_BASE + timer_base + 0x2c, lcdc_underflow_clr); + MDP_OUTP(MDP_BASE + timer_base + 0x30, lcdc_hsync_skew); + MDP_OUTP(MDP_BASE + timer_base + 0x38, ctrl_polarity); + MDP_OUTP(MDP_BASE + timer_base + 0x1c, active_hctl); + MDP_OUTP(MDP_BASE + timer_base + 0x20, active_v_start); + MDP_OUTP(MDP_BASE + timer_base + 0x24, active_v_end); + } else { + MDP_OUTP(MDP_BASE + timer_base + 0x18, display_hctl); + MDP_OUTP(MDP_BASE + timer_base + 0x1c, display_v_start); + MDP_OUTP(MDP_BASE + timer_base + 0x20, display_v_end); + MDP_OUTP(MDP_BASE + timer_base + 0x40, lcdc_border_clr); + MDP_OUTP(MDP_BASE + timer_base + 0x44, lcdc_underflow_clr); + MDP_OUTP(MDP_BASE + timer_base + 0x48, lcdc_hsync_skew); + MDP_OUTP(MDP_BASE + timer_base + 0x50, ctrl_polarity); + MDP_OUTP(MDP_BASE + timer_base + 0x2c, active_hctl); + MDP_OUTP(MDP_BASE + timer_base + 0x30, active_v_start); + MDP_OUTP(MDP_BASE + timer_base + 0x38, active_v_end); + } + + ret = panel_next_on(pdev); + if (ret == 0) { + /* enable LCDC block */ + MDP_OUTP(MDP_BASE + timer_base, 1); + mdp_pipe_ctrl(block, MDP_BLOCK_POWER_ON, FALSE); + } + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + + return ret; +} + +int mdp_lcdc_off(struct platform_device *pdev) +{ + int ret = 0; + struct msm_fb_data_type *mfd; + uint32 timer_base = LCDC_BASE; + uint32 block = MDP_DMA2_BLOCK; + + mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); + +#ifdef CONFIG_FB_MSM_MDP40 + if (mfd->panel.type == HDMI_PANEL) { + block = MDP_DMA_E_BLOCK; + timer_base = DTV_BASE; + } +#endif + + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + MDP_OUTP(MDP_BASE + timer_base, 0); + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + mdp_pipe_ctrl(block, MDP_BLOCK_POWER_OFF, FALSE); + + ret = panel_next_off(pdev); + + /* delay to make sure the last frame finishes */ + mdelay(100); + + return ret; +} + +void mdp_lcdc_update(struct msm_fb_data_type *mfd) +{ + struct fb_info *fbi = mfd->fbi; + uint8 *buf; + int bpp; + unsigned long flag; + uint32 dma_base; + int irq_block = MDP_DMA2_TERM; +#ifdef CONFIG_FB_MSM_MDP40 + int intr = INTR_DMA_P_DONE; +#endif + + if (!mfd->panel_power_on) + return; + + /* no need to power on cmd block since it's lcdc mode */ + + if (!mfd->ibuf.visible_swapped) { + bpp = fbi->var.bits_per_pixel / 8; + buf = (uint8 *) fbi->fix.smem_start; + buf += fbi->var.xoffset * bpp + + fbi->var.yoffset * fbi->fix.line_length; + } else { + /* we've done something to update the pointer. */ + bpp = mfd->ibuf.bpp; + buf = mfd->ibuf.buf; + } + + dma_base = DMA_P_BASE; + +#ifdef CONFIG_FB_MSM_MDP40 + if (mfd->panel.type == HDMI_PANEL) { + intr = INTR_DMA_E_DONE; + irq_block = MDP_DMA_E_TERM; + dma_base = DMA_E_BASE; + } +#endif + + /* starting address */ + MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf); + + /* enable LCDC irq */ + spin_lock_irqsave(&mdp_spin_lock, flag); + mdp_enable_irq(irq_block); + INIT_COMPLETION(mfd->dma->comp); + mfd->dma->waiting = TRUE; +#ifdef CONFIG_FB_MSM_MDP40 + outp32(MDP_INTR_CLEAR, intr); + mdp_intr_mask |= intr; + outp32(MDP_INTR_ENABLE, mdp_intr_mask); +#else + outp32(MDP_INTR_CLEAR, LCDC_FRAME_START); + mdp_intr_mask |= LCDC_FRAME_START; + outp32(MDP_INTR_ENABLE, mdp_intr_mask); +#endif + spin_unlock_irqrestore(&mdp_spin_lock, flag); + + if (mfd->ibuf.vsync_enable) + wait_for_completion_killable(&mfd->dma->comp); + mdp_disable_irq(irq_block); +} diff --git a/drivers/staging/msm/mdp_dma_s.c b/drivers/staging/msm/mdp_dma_s.c new file mode 100644 index 000000000000..0c34a1010f17 --- /dev/null +++ b/drivers/staging/msm/mdp_dma_s.c @@ -0,0 +1,139 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/hrtimer.h> + +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/spinlock.h> + +#include <linux/fb.h> + +#include "mdp.h" +#include "msm_fb.h" + +static void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd) +{ + MDPIBUF *iBuf = &mfd->ibuf; + int mddi_dest = FALSE; + uint32 outBpp = iBuf->bpp; + uint32 dma_s_cfg_reg; + uint8 *src; + struct msm_fb_panel_data *pdata = + (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; + + dma_s_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB | + DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS; + + if (mfd->fb_imgType == MDP_BGR_565) + dma_s_cfg_reg |= DMA_PACK_PATTERN_BGR; + else + dma_s_cfg_reg |= DMA_PACK_PATTERN_RGB; + + if (outBpp == 4) + dma_s_cfg_reg |= DMA_IBUF_C3ALPHA_EN; + + if (outBpp == 2) + dma_s_cfg_reg |= DMA_IBUF_FORMAT_RGB565; + + if (mfd->panel_info.pdest != DISPLAY_2) { + printk(KERN_ERR "error: non-secondary type through dma_s!\n"); + return; + } + + if (mfd->panel_info.type == MDDI_PANEL) { + dma_s_cfg_reg |= DMA_OUT_SEL_MDDI; + mddi_dest = TRUE; + } else { + dma_s_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY; + outp32(MDP_EBI2_LCD1, mfd->data_port_phys); + } + + dma_s_cfg_reg |= DMA_DITHER_EN; + + src = (uint8 *) iBuf->buf; + /* starting input address */ + src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * outBpp; + + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + /* PIXELSIZE */ + MDP_OUTP(MDP_BASE + 0xa0004, (iBuf->dma_h << 16 | iBuf->dma_w)); + MDP_OUTP(MDP_BASE + 0xa0008, src); /* ibuf address */ + MDP_OUTP(MDP_BASE + 0xa000c, iBuf->ibuf_width * outBpp);/* ystride */ + + if (mfd->panel_info.bpp == 18) { + dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */ + DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS; + } else { + dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */ + DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS; + } + + if (mddi_dest) { + MDP_OUTP(MDP_BASE + 0xa0010, (iBuf->dma_y << 16) | iBuf->dma_x); + MDP_OUTP(MDP_BASE + 0x00090, 1); + MDP_OUTP(MDP_BASE + 0x00094, + (MDDI_VDO_PACKET_DESC << 16) | + mfd->panel_info.mddi.vdopkt); + } else { + /* setting LCDC write window */ + pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w, + iBuf->dma_h); + } + + MDP_OUTP(MDP_BASE + 0xa0000, dma_s_cfg_reg); + + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd); +} + +void mdp_dma_s_update(struct msm_fb_data_type *mfd) +{ + down(&mfd->dma->mutex); + if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) { + down(&mfd->sem); + mdp_enable_irq(MDP_DMA_S_TERM); + mfd->dma->busy = TRUE; + INIT_COMPLETION(mfd->dma->comp); + mfd->ibuf_flushed = TRUE; + mdp_dma_s_update_lcd(mfd); + up(&mfd->sem); + + /* wait until DMA finishes the current job */ + wait_for_completion_killable(&mfd->dma->comp); + mdp_disable_irq(MDP_DMA_S_TERM); + + /* signal if pan function is waiting for the update completion */ + if (mfd->pan_waiting) { + mfd->pan_waiting = FALSE; + complete(&mfd->pan_comp); + } + } + up(&mfd->dma->mutex); +} diff --git a/drivers/staging/msm/mdp_dma_tv.c b/drivers/staging/msm/mdp_dma_tv.c new file mode 100644 index 000000000000..70989fb32c1d --- /dev/null +++ b/drivers/staging/msm/mdp_dma_tv.c @@ -0,0 +1,142 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/hrtimer.h> +#include <linux/delay.h> + +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/spinlock.h> + +#include <linux/fb.h> + +#include "mdp.h" +#include "msm_fb.h" + +extern spinlock_t mdp_spin_lock; +extern uint32 mdp_intr_mask; + +int mdp_dma3_on(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd; + struct fb_info *fbi; + uint8 *buf; + int bpp; + int ret = 0; + + mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); + + if (!mfd) + return -ENODEV; + + if (mfd->key != MFD_KEY) + return -EINVAL; + + fbi = mfd->fbi; + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + + bpp = fbi->var.bits_per_pixel / 8; + buf = (uint8 *) fbi->fix.smem_start; + buf += fbi->var.xoffset * bpp + + fbi->var.yoffset * fbi->fix.line_length; + + /* starting address[31..8] of Video frame buffer is CS0 */ + MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3); + + mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + + MDP_OUTP(MDP_BASE + 0xC0004, 0x4c60674); /* flicker filter enabled */ + MDP_OUTP(MDP_BASE + 0xC0010, 0x20); /* sobel treshold */ + + MDP_OUTP(MDP_BASE + 0xC0018, 0xeb0010); /* Y Max, Y min */ + MDP_OUTP(MDP_BASE + 0xC001C, 0xf00010); /* Cb Max, Cb min */ + MDP_OUTP(MDP_BASE + 0xC0020, 0xf00010); /* Cb Max, Cb min */ + + MDP_OUTP(MDP_BASE + 0xC000C, 0x67686970); /* add a few chars for CC */ + MDP_OUTP(MDP_BASE + 0xC0000, 0x1); /* MDP tv out enable */ + + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + + ret = panel_next_on(pdev); + + return ret; +} + +int mdp_dma3_off(struct platform_device *pdev) +{ + int ret = 0; + + ret = panel_next_off(pdev); + if (ret) + return ret; + + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + MDP_OUTP(MDP_BASE + 0xC0000, 0x0); + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + + mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + + /* delay to make sure the last frame finishes */ + mdelay(100); + + return ret; +} + +void mdp_dma3_update(struct msm_fb_data_type *mfd) +{ + struct fb_info *fbi = mfd->fbi; + uint8 *buf; + int bpp; + unsigned long flag; + + if (!mfd->panel_power_on) + return; + + /* no need to power on cmd block since dma3 is running */ + bpp = fbi->var.bits_per_pixel / 8; + buf = (uint8 *) fbi->fix.smem_start; + buf += fbi->var.xoffset * bpp + + fbi->var.yoffset * fbi->fix.line_length; + MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3); + + spin_lock_irqsave(&mdp_spin_lock, flag); + mdp_enable_irq(MDP_DMA3_TERM); + INIT_COMPLETION(mfd->dma->comp); + mfd->dma->waiting = TRUE; + + outp32(MDP_INTR_CLEAR, TV_OUT_DMA3_START); + mdp_intr_mask |= TV_OUT_DMA3_START; + outp32(MDP_INTR_ENABLE, mdp_intr_mask); + spin_unlock_irqrestore(&mdp_spin_lock, flag); + + wait_for_completion_killable(&mfd->dma->comp); + mdp_disable_irq(MDP_DMA3_TERM); +} diff --git a/drivers/staging/msm/mdp_hw_init.c b/drivers/staging/msm/mdp_hw_init.c new file mode 100644 index 000000000000..807362ac592c --- /dev/null +++ b/drivers/staging/msm/mdp_hw_init.c @@ -0,0 +1,720 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "mdp.h" + +/* mdp primary csc limit vector */ +uint32 mdp_plv[] = { 0x10, 0xeb, 0x10, 0xf0 }; + +/* Color Coefficient matrix for YUV -> RGB */ +struct mdp_ccs mdp_ccs_yuv2rgb = { + MDP_CCS_YUV2RGB, + { + 0x254, + 0x000, + 0x331, + 0x254, + 0xff38, + 0xfe61, + 0x254, + 0x409, + 0x000, + }, + { +#ifdef CONFIG_FB_MSM_MDP31 + 0x1f0, + 0x180, + 0x180 +#else + 0x10, + 0x80, + 0x80 +#endif + } +}; + +/* Color Coefficient matrix for RGB -> YUV */ +struct mdp_ccs mdp_ccs_rgb2yuv = { + MDP_CCS_RGB2YUV, + { + 0x83, + 0x102, + 0x32, + 0xffb5, + 0xff6c, + 0xe1, + 0xe1, + 0xff45, + 0xffdc, + }, +#ifdef CONFIG_FB_MSM_MDP31 + { + 0x10, + 0x80, + 0x80 + } +#endif +}; + +static void mdp_load_lut_param(void) +{ + outpdw(MDP_BASE + 0x40800, 0x0); + outpdw(MDP_BASE + 0x40804, 0x151515); + outpdw(MDP_BASE + 0x40808, 0x1d1d1d); + outpdw(MDP_BASE + 0x4080c, 0x232323); + outpdw(MDP_BASE + 0x40810, 0x272727); + outpdw(MDP_BASE + 0x40814, 0x2b2b2b); + outpdw(MDP_BASE + 0x40818, 0x2f2f2f); + outpdw(MDP_BASE + 0x4081c, 0x333333); + outpdw(MDP_BASE + 0x40820, 0x363636); + outpdw(MDP_BASE + 0x40824, 0x393939); + outpdw(MDP_BASE + 0x40828, 0x3b3b3b); + outpdw(MDP_BASE + 0x4082c, 0x3e3e3e); + outpdw(MDP_BASE + 0x40830, 0x404040); + outpdw(MDP_BASE + 0x40834, 0x434343); + outpdw(MDP_BASE + 0x40838, 0x454545); + outpdw(MDP_BASE + 0x4083c, 0x474747); + outpdw(MDP_BASE + 0x40840, 0x494949); + outpdw(MDP_BASE + 0x40844, 0x4b4b4b); + outpdw(MDP_BASE + 0x40848, 0x4d4d4d); + outpdw(MDP_BASE + 0x4084c, 0x4f4f4f); + outpdw(MDP_BASE + 0x40850, 0x515151); + outpdw(MDP_BASE + 0x40854, 0x535353); + outpdw(MDP_BASE + 0x40858, 0x555555); + outpdw(MDP_BASE + 0x4085c, 0x565656); + outpdw(MDP_BASE + 0x40860, 0x585858); + outpdw(MDP_BASE + 0x40864, 0x5a5a5a); + outpdw(MDP_BASE + 0x40868, 0x5b5b5b); + outpdw(MDP_BASE + 0x4086c, 0x5d5d5d); + outpdw(MDP_BASE + 0x40870, 0x5e5e5e); + outpdw(MDP_BASE + 0x40874, 0x606060); + outpdw(MDP_BASE + 0x40878, 0x616161); + outpdw(MDP_BASE + 0x4087c, 0x636363); + outpdw(MDP_BASE + 0x40880, 0x646464); + outpdw(MDP_BASE + 0x40884, 0x666666); + outpdw(MDP_BASE + 0x40888, 0x676767); + outpdw(MDP_BASE + 0x4088c, 0x686868); + outpdw(MDP_BASE + 0x40890, 0x6a6a6a); + outpdw(MDP_BASE + 0x40894, 0x6b6b6b); + outpdw(MDP_BASE + 0x40898, 0x6c6c6c); + outpdw(MDP_BASE + 0x4089c, 0x6e6e6e); + outpdw(MDP_BASE + 0x408a0, 0x6f6f6f); + outpdw(MDP_BASE + 0x408a4, 0x707070); + outpdw(MDP_BASE + 0x408a8, 0x717171); + outpdw(MDP_BASE + 0x408ac, 0x727272); + outpdw(MDP_BASE + 0x408b0, 0x747474); + outpdw(MDP_BASE + 0x408b4, 0x757575); + outpdw(MDP_BASE + 0x408b8, 0x767676); + outpdw(MDP_BASE + 0x408bc, 0x777777); + outpdw(MDP_BASE + 0x408c0, 0x787878); + outpdw(MDP_BASE + 0x408c4, 0x797979); + outpdw(MDP_BASE + 0x408c8, 0x7a7a7a); + outpdw(MDP_BASE + 0x408cc, 0x7c7c7c); + outpdw(MDP_BASE + 0x408d0, 0x7d7d7d); + outpdw(MDP_BASE + 0x408d4, 0x7e7e7e); + outpdw(MDP_BASE + 0x408d8, 0x7f7f7f); + outpdw(MDP_BASE + 0x408dc, 0x808080); + outpdw(MDP_BASE + 0x408e0, 0x818181); + outpdw(MDP_BASE + 0x408e4, 0x828282); + outpdw(MDP_BASE + 0x408e8, 0x838383); + outpdw(MDP_BASE + 0x408ec, 0x848484); + outpdw(MDP_BASE + 0x408f0, 0x858585); + outpdw(MDP_BASE + 0x408f4, 0x868686); + outpdw(MDP_BASE + 0x408f8, 0x878787); + outpdw(MDP_BASE + 0x408fc, 0x888888); + outpdw(MDP_BASE + 0x40900, 0x898989); + outpdw(MDP_BASE + 0x40904, 0x8a8a8a); + outpdw(MDP_BASE + 0x40908, 0x8b8b8b); + outpdw(MDP_BASE + 0x4090c, 0x8c8c8c); + outpdw(MDP_BASE + 0x40910, 0x8d8d8d); + outpdw(MDP_BASE + 0x40914, 0x8e8e8e); + outpdw(MDP_BASE + 0x40918, 0x8f8f8f); + outpdw(MDP_BASE + 0x4091c, 0x8f8f8f); + outpdw(MDP_BASE + 0x40920, 0x909090); + outpdw(MDP_BASE + 0x40924, 0x919191); + outpdw(MDP_BASE + 0x40928, 0x929292); + outpdw(MDP_BASE + 0x4092c, 0x939393); + outpdw(MDP_BASE + 0x40930, 0x949494); + outpdw(MDP_BASE + 0x40934, 0x959595); + outpdw(MDP_BASE + 0x40938, 0x969696); + outpdw(MDP_BASE + 0x4093c, 0x969696); + outpdw(MDP_BASE + 0x40940, 0x979797); + outpdw(MDP_BASE + 0x40944, 0x989898); + outpdw(MDP_BASE + 0x40948, 0x999999); + outpdw(MDP_BASE + 0x4094c, 0x9a9a9a); + outpdw(MDP_BASE + 0x40950, 0x9b9b9b); + outpdw(MDP_BASE + 0x40954, 0x9c9c9c); + outpdw(MDP_BASE + 0x40958, 0x9c9c9c); + outpdw(MDP_BASE + 0x4095c, 0x9d9d9d); + outpdw(MDP_BASE + 0x40960, 0x9e9e9e); + outpdw(MDP_BASE + 0x40964, 0x9f9f9f); + outpdw(MDP_BASE + 0x40968, 0xa0a0a0); + outpdw(MDP_BASE + 0x4096c, 0xa0a0a0); + outpdw(MDP_BASE + 0x40970, 0xa1a1a1); + outpdw(MDP_BASE + 0x40974, 0xa2a2a2); + outpdw(MDP_BASE + 0x40978, 0xa3a3a3); + outpdw(MDP_BASE + 0x4097c, 0xa4a4a4); + outpdw(MDP_BASE + 0x40980, 0xa4a4a4); + outpdw(MDP_BASE + 0x40984, 0xa5a5a5); + outpdw(MDP_BASE + 0x40988, 0xa6a6a6); + outpdw(MDP_BASE + 0x4098c, 0xa7a7a7); + outpdw(MDP_BASE + 0x40990, 0xa7a7a7); + outpdw(MDP_BASE + 0x40994, 0xa8a8a8); + outpdw(MDP_BASE + 0x40998, 0xa9a9a9); + outpdw(MDP_BASE + 0x4099c, 0xaaaaaa); + outpdw(MDP_BASE + 0x409a0, 0xaaaaaa); + outpdw(MDP_BASE + 0x409a4, 0xababab); + outpdw(MDP_BASE + 0x409a8, 0xacacac); + outpdw(MDP_BASE + 0x409ac, 0xadadad); + outpdw(MDP_BASE + 0x409b0, 0xadadad); + outpdw(MDP_BASE + 0x409b4, 0xaeaeae); + outpdw(MDP_BASE + 0x409b8, 0xafafaf); + outpdw(MDP_BASE + 0x409bc, 0xafafaf); + outpdw(MDP_BASE + 0x409c0, 0xb0b0b0); + outpdw(MDP_BASE + 0x409c4, 0xb1b1b1); + outpdw(MDP_BASE + 0x409c8, 0xb2b2b2); + outpdw(MDP_BASE + 0x409cc, 0xb2b2b2); + outpdw(MDP_BASE + 0x409d0, 0xb3b3b3); + outpdw(MDP_BASE + 0x409d4, 0xb4b4b4); + outpdw(MDP_BASE + 0x409d8, 0xb4b4b4); + outpdw(MDP_BASE + 0x409dc, 0xb5b5b5); + outpdw(MDP_BASE + 0x409e0, 0xb6b6b6); + outpdw(MDP_BASE + 0x409e4, 0xb6b6b6); + outpdw(MDP_BASE + 0x409e8, 0xb7b7b7); + outpdw(MDP_BASE + 0x409ec, 0xb8b8b8); + outpdw(MDP_BASE + 0x409f0, 0xb8b8b8); + outpdw(MDP_BASE + 0x409f4, 0xb9b9b9); + outpdw(MDP_BASE + 0x409f8, 0xbababa); + outpdw(MDP_BASE + 0x409fc, 0xbababa); + outpdw(MDP_BASE + 0x40a00, 0xbbbbbb); + outpdw(MDP_BASE + 0x40a04, 0xbcbcbc); + outpdw(MDP_BASE + 0x40a08, 0xbcbcbc); + outpdw(MDP_BASE + 0x40a0c, 0xbdbdbd); + outpdw(MDP_BASE + 0x40a10, 0xbebebe); + outpdw(MDP_BASE + 0x40a14, 0xbebebe); + outpdw(MDP_BASE + 0x40a18, 0xbfbfbf); + outpdw(MDP_BASE + 0x40a1c, 0xc0c0c0); + outpdw(MDP_BASE + 0x40a20, 0xc0c0c0); + outpdw(MDP_BASE + 0x40a24, 0xc1c1c1); + outpdw(MDP_BASE + 0x40a28, 0xc1c1c1); + outpdw(MDP_BASE + 0x40a2c, 0xc2c2c2); + outpdw(MDP_BASE + 0x40a30, 0xc3c3c3); + outpdw(MDP_BASE + 0x40a34, 0xc3c3c3); + outpdw(MDP_BASE + 0x40a38, 0xc4c4c4); + outpdw(MDP_BASE + 0x40a3c, 0xc5c5c5); + outpdw(MDP_BASE + 0x40a40, 0xc5c5c5); + outpdw(MDP_BASE + 0x40a44, 0xc6c6c6); + outpdw(MDP_BASE + 0x40a48, 0xc6c6c6); + outpdw(MDP_BASE + 0x40a4c, 0xc7c7c7); + outpdw(MDP_BASE + 0x40a50, 0xc8c8c8); + outpdw(MDP_BASE + 0x40a54, 0xc8c8c8); + outpdw(MDP_BASE + 0x40a58, 0xc9c9c9); + outpdw(MDP_BASE + 0x40a5c, 0xc9c9c9); + outpdw(MDP_BASE + 0x40a60, 0xcacaca); + outpdw(MDP_BASE + 0x40a64, 0xcbcbcb); + outpdw(MDP_BASE + 0x40a68, 0xcbcbcb); + outpdw(MDP_BASE + 0x40a6c, 0xcccccc); + outpdw(MDP_BASE + 0x40a70, 0xcccccc); + outpdw(MDP_BASE + 0x40a74, 0xcdcdcd); + outpdw(MDP_BASE + 0x40a78, 0xcecece); + outpdw(MDP_BASE + 0x40a7c, 0xcecece); + outpdw(MDP_BASE + 0x40a80, 0xcfcfcf); + outpdw(MDP_BASE + 0x40a84, 0xcfcfcf); + outpdw(MDP_BASE + 0x40a88, 0xd0d0d0); + outpdw(MDP_BASE + 0x40a8c, 0xd0d0d0); + outpdw(MDP_BASE + 0x40a90, 0xd1d1d1); + outpdw(MDP_BASE + 0x40a94, 0xd2d2d2); + outpdw(MDP_BASE + 0x40a98, 0xd2d2d2); + outpdw(MDP_BASE + 0x40a9c, 0xd3d3d3); + outpdw(MDP_BASE + 0x40aa0, 0xd3d3d3); + outpdw(MDP_BASE + 0x40aa4, 0xd4d4d4); + outpdw(MDP_BASE + 0x40aa8, 0xd4d4d4); + outpdw(MDP_BASE + 0x40aac, 0xd5d5d5); + outpdw(MDP_BASE + 0x40ab0, 0xd6d6d6); + outpdw(MDP_BASE + 0x40ab4, 0xd6d6d6); + outpdw(MDP_BASE + 0x40ab8, 0xd7d7d7); + outpdw(MDP_BASE + 0x40abc, 0xd7d7d7); + outpdw(MDP_BASE + 0x40ac0, 0xd8d8d8); + outpdw(MDP_BASE + 0x40ac4, 0xd8d8d8); + outpdw(MDP_BASE + 0x40ac8, 0xd9d9d9); + outpdw(MDP_BASE + 0x40acc, 0xd9d9d9); + outpdw(MDP_BASE + 0x40ad0, 0xdadada); + outpdw(MDP_BASE + 0x40ad4, 0xdbdbdb); + outpdw(MDP_BASE + 0x40ad8, 0xdbdbdb); + outpdw(MDP_BASE + 0x40adc, 0xdcdcdc); + outpdw(MDP_BASE + 0x40ae0, 0xdcdcdc); + outpdw(MDP_BASE + 0x40ae4, 0xdddddd); + outpdw(MDP_BASE + 0x40ae8, 0xdddddd); + outpdw(MDP_BASE + 0x40aec, 0xdedede); + outpdw(MDP_BASE + 0x40af0, 0xdedede); + outpdw(MDP_BASE + 0x40af4, 0xdfdfdf); + outpdw(MDP_BASE + 0x40af8, 0xdfdfdf); + outpdw(MDP_BASE + 0x40afc, 0xe0e0e0); + outpdw(MDP_BASE + 0x40b00, 0xe0e0e0); + outpdw(MDP_BASE + 0x40b04, 0xe1e1e1); + outpdw(MDP_BASE + 0x40b08, 0xe1e1e1); + outpdw(MDP_BASE + 0x40b0c, 0xe2e2e2); + outpdw(MDP_BASE + 0x40b10, 0xe3e3e3); + outpdw(MDP_BASE + 0x40b14, 0xe3e3e3); + outpdw(MDP_BASE + 0x40b18, 0xe4e4e4); + outpdw(MDP_BASE + 0x40b1c, 0xe4e4e4); + outpdw(MDP_BASE + 0x40b20, 0xe5e5e5); + outpdw(MDP_BASE + 0x40b24, 0xe5e5e5); + outpdw(MDP_BASE + 0x40b28, 0xe6e6e6); + outpdw(MDP_BASE + 0x40b2c, 0xe6e6e6); + outpdw(MDP_BASE + 0x40b30, 0xe7e7e7); + outpdw(MDP_BASE + 0x40b34, 0xe7e7e7); + outpdw(MDP_BASE + 0x40b38, 0xe8e8e8); + outpdw(MDP_BASE + 0x40b3c, 0xe8e8e8); + outpdw(MDP_BASE + 0x40b40, 0xe9e9e9); + outpdw(MDP_BASE + 0x40b44, 0xe9e9e9); + outpdw(MDP_BASE + 0x40b48, 0xeaeaea); + outpdw(MDP_BASE + 0x40b4c, 0xeaeaea); + outpdw(MDP_BASE + 0x40b50, 0xebebeb); + outpdw(MDP_BASE + 0x40b54, 0xebebeb); + outpdw(MDP_BASE + 0x40b58, 0xececec); + outpdw(MDP_BASE + 0x40b5c, 0xececec); + outpdw(MDP_BASE + 0x40b60, 0xededed); + outpdw(MDP_BASE + 0x40b64, 0xededed); + outpdw(MDP_BASE + 0x40b68, 0xeeeeee); + outpdw(MDP_BASE + 0x40b6c, 0xeeeeee); + outpdw(MDP_BASE + 0x40b70, 0xefefef); + outpdw(MDP_BASE + 0x40b74, 0xefefef); + outpdw(MDP_BASE + 0x40b78, 0xf0f0f0); + outpdw(MDP_BASE + 0x40b7c, 0xf0f0f0); + outpdw(MDP_BASE + 0x40b80, 0xf1f1f1); + outpdw(MDP_BASE + 0x40b84, 0xf1f1f1); + outpdw(MDP_BASE + 0x40b88, 0xf2f2f2); + outpdw(MDP_BASE + 0x40b8c, 0xf2f2f2); + outpdw(MDP_BASE + 0x40b90, 0xf2f2f2); + outpdw(MDP_BASE + 0x40b94, 0xf3f3f3); + outpdw(MDP_BASE + 0x40b98, 0xf3f3f3); + outpdw(MDP_BASE + 0x40b9c, 0xf4f4f4); + outpdw(MDP_BASE + 0x40ba0, 0xf4f4f4); + outpdw(MDP_BASE + 0x40ba4, 0xf5f5f5); + outpdw(MDP_BASE + 0x40ba8, 0xf5f5f5); + outpdw(MDP_BASE + 0x40bac, 0xf6f6f6); + outpdw(MDP_BASE + 0x40bb0, 0xf6f6f6); + outpdw(MDP_BASE + 0x40bb4, 0xf7f7f7); + outpdw(MDP_BASE + 0x40bb8, 0xf7f7f7); + outpdw(MDP_BASE + 0x40bbc, 0xf8f8f8); + outpdw(MDP_BASE + 0x40bc0, 0xf8f8f8); + outpdw(MDP_BASE + 0x40bc4, 0xf9f9f9); + outpdw(MDP_BASE + 0x40bc8, 0xf9f9f9); + outpdw(MDP_BASE + 0x40bcc, 0xfafafa); + outpdw(MDP_BASE + 0x40bd0, 0xfafafa); + outpdw(MDP_BASE + 0x40bd4, 0xfafafa); + outpdw(MDP_BASE + 0x40bd8, 0xfbfbfb); + outpdw(MDP_BASE + 0x40bdc, 0xfbfbfb); + outpdw(MDP_BASE + 0x40be0, 0xfcfcfc); + outpdw(MDP_BASE + 0x40be4, 0xfcfcfc); + outpdw(MDP_BASE + 0x40be8, 0xfdfdfd); + outpdw(MDP_BASE + 0x40bec, 0xfdfdfd); + outpdw(MDP_BASE + 0x40bf0, 0xfefefe); + outpdw(MDP_BASE + 0x40bf4, 0xfefefe); + outpdw(MDP_BASE + 0x40bf8, 0xffffff); + outpdw(MDP_BASE + 0x40bfc, 0xffffff); + outpdw(MDP_BASE + 0x40c00, 0x0); + outpdw(MDP_BASE + 0x40c04, 0x0); + outpdw(MDP_BASE + 0x40c08, 0x0); + outpdw(MDP_BASE + 0x40c0c, 0x0); + outpdw(MDP_BASE + 0x40c10, 0x0); + outpdw(MDP_BASE + 0x40c14, 0x0); + outpdw(MDP_BASE + 0x40c18, 0x0); + outpdw(MDP_BASE + 0x40c1c, 0x0); + outpdw(MDP_BASE + 0x40c20, 0x0); + outpdw(MDP_BASE + 0x40c24, 0x0); + outpdw(MDP_BASE + 0x40c28, 0x0); + outpdw(MDP_BASE + 0x40c2c, 0x0); + outpdw(MDP_BASE + 0x40c30, 0x0); + outpdw(MDP_BASE + 0x40c34, 0x0); + outpdw(MDP_BASE + 0x40c38, 0x0); + outpdw(MDP_BASE + 0x40c3c, 0x0); + outpdw(MDP_BASE + 0x40c40, 0x10101); + outpdw(MDP_BASE + 0x40c44, 0x10101); + outpdw(MDP_BASE + 0x40c48, 0x10101); + outpdw(MDP_BASE + 0x40c4c, 0x10101); + outpdw(MDP_BASE + 0x40c50, 0x10101); + outpdw(MDP_BASE + 0x40c54, 0x10101); + outpdw(MDP_BASE + 0x40c58, 0x10101); + outpdw(MDP_BASE + 0x40c5c, 0x10101); + outpdw(MDP_BASE + 0x40c60, 0x10101); + outpdw(MDP_BASE + 0x40c64, 0x10101); + outpdw(MDP_BASE + 0x40c68, 0x20202); + outpdw(MDP_BASE + 0x40c6c, 0x20202); + outpdw(MDP_BASE + 0x40c70, 0x20202); + outpdw(MDP_BASE + 0x40c74, 0x20202); + outpdw(MDP_BASE + 0x40c78, 0x20202); + outpdw(MDP_BASE + 0x40c7c, 0x20202); + outpdw(MDP_BASE + 0x40c80, 0x30303); + outpdw(MDP_BASE + 0x40c84, 0x30303); + outpdw(MDP_BASE + 0x40c88, 0x30303); + outpdw(MDP_BASE + 0x40c8c, 0x30303); + outpdw(MDP_BASE + 0x40c90, 0x30303); + outpdw(MDP_BASE + 0x40c94, 0x40404); + outpdw(MDP_BASE + 0x40c98, 0x40404); + outpdw(MDP_BASE + 0x40c9c, 0x40404); + outpdw(MDP_BASE + 0x40ca0, 0x40404); + outpdw(MDP_BASE + 0x40ca4, 0x40404); + outpdw(MDP_BASE + 0x40ca8, 0x50505); + outpdw(MDP_BASE + 0x40cac, 0x50505); + outpdw(MDP_BASE + 0x40cb0, 0x50505); + outpdw(MDP_BASE + 0x40cb4, 0x50505); + outpdw(MDP_BASE + 0x40cb8, 0x60606); + outpdw(MDP_BASE + 0x40cbc, 0x60606); + outpdw(MDP_BASE + 0x40cc0, 0x60606); + outpdw(MDP_BASE + 0x40cc4, 0x70707); + outpdw(MDP_BASE + 0x40cc8, 0x70707); + outpdw(MDP_BASE + 0x40ccc, 0x70707); + outpdw(MDP_BASE + 0x40cd0, 0x70707); + outpdw(MDP_BASE + 0x40cd4, 0x80808); + outpdw(MDP_BASE + 0x40cd8, 0x80808); + outpdw(MDP_BASE + 0x40cdc, 0x80808); + outpdw(MDP_BASE + 0x40ce0, 0x90909); + outpdw(MDP_BASE + 0x40ce4, 0x90909); + outpdw(MDP_BASE + 0x40ce8, 0xa0a0a); + outpdw(MDP_BASE + 0x40cec, 0xa0a0a); + outpdw(MDP_BASE + 0x40cf0, 0xa0a0a); + outpdw(MDP_BASE + 0x40cf4, 0xb0b0b); + outpdw(MDP_BASE + 0x40cf8, 0xb0b0b); + outpdw(MDP_BASE + 0x40cfc, 0xb0b0b); + outpdw(MDP_BASE + 0x40d00, 0xc0c0c); + outpdw(MDP_BASE + 0x40d04, 0xc0c0c); + outpdw(MDP_BASE + 0x40d08, 0xd0d0d); + outpdw(MDP_BASE + 0x40d0c, 0xd0d0d); + outpdw(MDP_BASE + 0x40d10, 0xe0e0e); + outpdw(MDP_BASE + 0x40d14, 0xe0e0e); + outpdw(MDP_BASE + 0x40d18, 0xe0e0e); + outpdw(MDP_BASE + 0x40d1c, 0xf0f0f); + outpdw(MDP_BASE + 0x40d20, 0xf0f0f); + outpdw(MDP_BASE + 0x40d24, 0x101010); + outpdw(MDP_BASE + 0x40d28, 0x101010); + outpdw(MDP_BASE + 0x40d2c, 0x111111); + outpdw(MDP_BASE + 0x40d30, 0x111111); + outpdw(MDP_BASE + 0x40d34, 0x121212); + outpdw(MDP_BASE + 0x40d38, 0x121212); + outpdw(MDP_BASE + 0x40d3c, 0x131313); + outpdw(MDP_BASE + 0x40d40, 0x131313); + outpdw(MDP_BASE + 0x40d44, 0x141414); + outpdw(MDP_BASE + 0x40d48, 0x151515); + outpdw(MDP_BASE + 0x40d4c, 0x151515); + outpdw(MDP_BASE + 0x40d50, 0x161616); + outpdw(MDP_BASE + 0x40d54, 0x161616); + outpdw(MDP_BASE + 0x40d58, 0x171717); + outpdw(MDP_BASE + 0x40d5c, 0x171717); + outpdw(MDP_BASE + 0x40d60, 0x181818); + outpdw(MDP_BASE + 0x40d64, 0x191919); + outpdw(MDP_BASE + 0x40d68, 0x191919); + outpdw(MDP_BASE + 0x40d6c, 0x1a1a1a); + outpdw(MDP_BASE + 0x40d70, 0x1b1b1b); + outpdw(MDP_BASE + 0x40d74, 0x1b1b1b); + outpdw(MDP_BASE + 0x40d78, 0x1c1c1c); + outpdw(MDP_BASE + 0x40d7c, 0x1c1c1c); + outpdw(MDP_BASE + 0x40d80, 0x1d1d1d); + outpdw(MDP_BASE + 0x40d84, 0x1e1e1e); + outpdw(MDP_BASE + 0x40d88, 0x1f1f1f); + outpdw(MDP_BASE + 0x40d8c, 0x1f1f1f); + outpdw(MDP_BASE + 0x40d90, 0x202020); + outpdw(MDP_BASE + 0x40d94, 0x212121); + outpdw(MDP_BASE + 0x40d98, 0x212121); + outpdw(MDP_BASE + 0x40d9c, 0x222222); + outpdw(MDP_BASE + 0x40da0, 0x232323); + outpdw(MDP_BASE + 0x40da4, 0x242424); + outpdw(MDP_BASE + 0x40da8, 0x242424); + outpdw(MDP_BASE + 0x40dac, 0x252525); + outpdw(MDP_BASE + 0x40db0, 0x262626); + outpdw(MDP_BASE + 0x40db4, 0x272727); + outpdw(MDP_BASE + 0x40db8, 0x272727); + outpdw(MDP_BASE + 0x40dbc, 0x282828); + outpdw(MDP_BASE + 0x40dc0, 0x292929); + outpdw(MDP_BASE + 0x40dc4, 0x2a2a2a); + outpdw(MDP_BASE + 0x40dc8, 0x2b2b2b); + outpdw(MDP_BASE + 0x40dcc, 0x2c2c2c); + outpdw(MDP_BASE + 0x40dd0, 0x2c2c2c); + outpdw(MDP_BASE + 0x40dd4, 0x2d2d2d); + outpdw(MDP_BASE + 0x40dd8, 0x2e2e2e); + outpdw(MDP_BASE + 0x40ddc, 0x2f2f2f); + outpdw(MDP_BASE + 0x40de0, 0x303030); + outpdw(MDP_BASE + 0x40de4, 0x313131); + outpdw(MDP_BASE + 0x40de8, 0x323232); + outpdw(MDP_BASE + 0x40dec, 0x333333); + outpdw(MDP_BASE + 0x40df0, 0x333333); + outpdw(MDP_BASE + 0x40df4, 0x343434); + outpdw(MDP_BASE + 0x40df8, 0x353535); + outpdw(MDP_BASE + 0x40dfc, 0x363636); + outpdw(MDP_BASE + 0x40e00, 0x373737); + outpdw(MDP_BASE + 0x40e04, 0x383838); + outpdw(MDP_BASE + 0x40e08, 0x393939); + outpdw(MDP_BASE + 0x40e0c, 0x3a3a3a); + outpdw(MDP_BASE + 0x40e10, 0x3b3b3b); + outpdw(MDP_BASE + 0x40e14, 0x3c3c3c); + outpdw(MDP_BASE + 0x40e18, 0x3d3d3d); + outpdw(MDP_BASE + 0x40e1c, 0x3e3e3e); + outpdw(MDP_BASE + 0x40e20, 0x3f3f3f); + outpdw(MDP_BASE + 0x40e24, 0x404040); + outpdw(MDP_BASE + 0x40e28, 0x414141); + outpdw(MDP_BASE + 0x40e2c, 0x424242); + outpdw(MDP_BASE + 0x40e30, 0x434343); + outpdw(MDP_BASE + 0x40e34, 0x444444); + outpdw(MDP_BASE + 0x40e38, 0x464646); + outpdw(MDP_BASE + 0x40e3c, 0x474747); + outpdw(MDP_BASE + 0x40e40, 0x484848); + outpdw(MDP_BASE + 0x40e44, 0x494949); + outpdw(MDP_BASE + 0x40e48, 0x4a4a4a); + outpdw(MDP_BASE + 0x40e4c, 0x4b4b4b); + outpdw(MDP_BASE + 0x40e50, 0x4c4c4c); + outpdw(MDP_BASE + 0x40e54, 0x4d4d4d); + outpdw(MDP_BASE + 0x40e58, 0x4f4f4f); + outpdw(MDP_BASE + 0x40e5c, 0x505050); + outpdw(MDP_BASE + 0x40e60, 0x515151); + outpdw(MDP_BASE + 0x40e64, 0x525252); + outpdw(MDP_BASE + 0x40e68, 0x535353); + outpdw(MDP_BASE + 0x40e6c, 0x545454); + outpdw(MDP_BASE + 0x40e70, 0x565656); + outpdw(MDP_BASE + 0x40e74, 0x575757); + outpdw(MDP_BASE + 0x40e78, 0x585858); + outpdw(MDP_BASE + 0x40e7c, 0x595959); + outpdw(MDP_BASE + 0x40e80, 0x5b5b5b); + outpdw(MDP_BASE + 0x40e84, 0x5c5c5c); + outpdw(MDP_BASE + 0x40e88, 0x5d5d5d); + outpdw(MDP_BASE + 0x40e8c, 0x5e5e5e); + outpdw(MDP_BASE + 0x40e90, 0x606060); + outpdw(MDP_BASE + 0x40e94, 0x616161); + outpdw(MDP_BASE + 0x40e98, 0x626262); + outpdw(MDP_BASE + 0x40e9c, 0x646464); + outpdw(MDP_BASE + 0x40ea0, 0x656565); + outpdw(MDP_BASE + 0x40ea4, 0x666666); + outpdw(MDP_BASE + 0x40ea8, 0x686868); + outpdw(MDP_BASE + 0x40eac, 0x696969); + outpdw(MDP_BASE + 0x40eb0, 0x6a6a6a); + outpdw(MDP_BASE + 0x40eb4, 0x6c6c6c); + outpdw(MDP_BASE + 0x40eb8, 0x6d6d6d); + outpdw(MDP_BASE + 0x40ebc, 0x6f6f6f); + outpdw(MDP_BASE + 0x40ec0, 0x707070); + outpdw(MDP_BASE + 0x40ec4, 0x717171); + outpdw(MDP_BASE + 0x40ec8, 0x737373); + outpdw(MDP_BASE + 0x40ecc, 0x747474); + outpdw(MDP_BASE + 0x40ed0, 0x767676); + outpdw(MDP_BASE + 0x40ed4, 0x777777); + outpdw(MDP_BASE + 0x40ed8, 0x797979); + outpdw(MDP_BASE + 0x40edc, 0x7a7a7a); + outpdw(MDP_BASE + 0x40ee0, 0x7c7c7c); + outpdw(MDP_BASE + 0x40ee4, 0x7d7d7d); + outpdw(MDP_BASE + 0x40ee8, 0x7f7f7f); + outpdw(MDP_BASE + 0x40eec, 0x808080); + outpdw(MDP_BASE + 0x40ef0, 0x828282); + outpdw(MDP_BASE + 0x40ef4, 0x838383); + outpdw(MDP_BASE + 0x40ef8, 0x858585); + outpdw(MDP_BASE + 0x40efc, 0x868686); + outpdw(MDP_BASE + 0x40f00, 0x888888); + outpdw(MDP_BASE + 0x40f04, 0x898989); + outpdw(MDP_BASE + 0x40f08, 0x8b8b8b); + outpdw(MDP_BASE + 0x40f0c, 0x8d8d8d); + outpdw(MDP_BASE + 0x40f10, 0x8e8e8e); + outpdw(MDP_BASE + 0x40f14, 0x909090); + outpdw(MDP_BASE + 0x40f18, 0x919191); + outpdw(MDP_BASE + 0x40f1c, 0x939393); + outpdw(MDP_BASE + 0x40f20, 0x959595); + outpdw(MDP_BASE + 0x40f24, 0x969696); + outpdw(MDP_BASE + 0x40f28, 0x989898); + outpdw(MDP_BASE + 0x40f2c, 0x9a9a9a); + outpdw(MDP_BASE + 0x40f30, 0x9b9b9b); + outpdw(MDP_BASE + 0x40f34, 0x9d9d9d); + outpdw(MDP_BASE + 0x40f38, 0x9f9f9f); + outpdw(MDP_BASE + 0x40f3c, 0xa1a1a1); + outpdw(MDP_BASE + 0x40f40, 0xa2a2a2); + outpdw(MDP_BASE + 0x40f44, 0xa4a4a4); + outpdw(MDP_BASE + 0x40f48, 0xa6a6a6); + outpdw(MDP_BASE + 0x40f4c, 0xa7a7a7); + outpdw(MDP_BASE + 0x40f50, 0xa9a9a9); + outpdw(MDP_BASE + 0x40f54, 0xababab); + outpdw(MDP_BASE + 0x40f58, 0xadadad); + outpdw(MDP_BASE + 0x40f5c, 0xafafaf); + outpdw(MDP_BASE + 0x40f60, 0xb0b0b0); + outpdw(MDP_BASE + 0x40f64, 0xb2b2b2); + outpdw(MDP_BASE + 0x40f68, 0xb4b4b4); + outpdw(MDP_BASE + 0x40f6c, 0xb6b6b6); + outpdw(MDP_BASE + 0x40f70, 0xb8b8b8); + outpdw(MDP_BASE + 0x40f74, 0xbababa); + outpdw(MDP_BASE + 0x40f78, 0xbbbbbb); + outpdw(MDP_BASE + 0x40f7c, 0xbdbdbd); + outpdw(MDP_BASE + 0x40f80, 0xbfbfbf); + outpdw(MDP_BASE + 0x40f84, 0xc1c1c1); + outpdw(MDP_BASE + 0x40f88, 0xc3c3c3); + outpdw(MDP_BASE + 0x40f8c, 0xc5c5c5); + outpdw(MDP_BASE + 0x40f90, 0xc7c7c7); + outpdw(MDP_BASE + 0x40f94, 0xc9c9c9); + outpdw(MDP_BASE + 0x40f98, 0xcbcbcb); + outpdw(MDP_BASE + 0x40f9c, 0xcdcdcd); + outpdw(MDP_BASE + 0x40fa0, 0xcfcfcf); + outpdw(MDP_BASE + 0x40fa4, 0xd1d1d1); + outpdw(MDP_BASE + 0x40fa8, 0xd3d3d3); + outpdw(MDP_BASE + 0x40fac, 0xd5d5d5); + outpdw(MDP_BASE + 0x40fb0, 0xd7d7d7); + outpdw(MDP_BASE + 0x40fb4, 0xd9d9d9); + outpdw(MDP_BASE + 0x40fb8, 0xdbdbdb); + outpdw(MDP_BASE + 0x40fbc, 0xdddddd); + outpdw(MDP_BASE + 0x40fc0, 0xdfdfdf); + outpdw(MDP_BASE + 0x40fc4, 0xe1e1e1); + outpdw(MDP_BASE + 0x40fc8, 0xe3e3e3); + outpdw(MDP_BASE + 0x40fcc, 0xe5e5e5); + outpdw(MDP_BASE + 0x40fd0, 0xe7e7e7); + outpdw(MDP_BASE + 0x40fd4, 0xe9e9e9); + outpdw(MDP_BASE + 0x40fd8, 0xebebeb); + outpdw(MDP_BASE + 0x40fdc, 0xeeeeee); + outpdw(MDP_BASE + 0x40fe0, 0xf0f0f0); + outpdw(MDP_BASE + 0x40fe4, 0xf2f2f2); + outpdw(MDP_BASE + 0x40fe8, 0xf4f4f4); + outpdw(MDP_BASE + 0x40fec, 0xf6f6f6); + outpdw(MDP_BASE + 0x40ff0, 0xf8f8f8); + outpdw(MDP_BASE + 0x40ff4, 0xfbfbfb); + outpdw(MDP_BASE + 0x40ff8, 0xfdfdfd); + outpdw(MDP_BASE + 0x40ffc, 0xffffff); +} + +#define IRQ_EN_1__MDP_IRQ___M 0x00000800 + +void mdp_hw_init(void) +{ + int i; + + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + + /* debug interface write access */ + outpdw(MDP_BASE + 0x60, 1); + + outp32(MDP_INTR_ENABLE, MDP_ANY_INTR_MASK); + outp32(MDP_EBI2_PORTMAP_MODE, 0x3); + outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8, 0x0); + outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc, 0x0); + outpdw(MDP_BASE + 0x60, 0x1); + mdp_load_lut_param(); + + /* + * clear up unused fg/main registers + */ + /* comp.plane 2&3 ystride */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0120, 0x0); + /* unpacked pattern */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x012c, 0x0); + /* unpacked pattern */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0130, 0x0); + /* unpacked pattern */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0134, 0x0); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0158, 0x0); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x15c, 0x0); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0160, 0x0); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0170, 0x0); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0174, 0x0); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x017c, 0x0); + + /* comp.plane 2 */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0114, 0x0); + /* comp.plane 3 */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0118, 0x0); + + /* clear up unused bg registers */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8, 0); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0, 0); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc, 0); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0, 0); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4, 0); + +#ifndef CONFIG_FB_MSM_MDP22 + MDP_OUTP(MDP_BASE + 0xE0000, 0); + MDP_OUTP(MDP_BASE + 0x100, 0xffffffff); + MDP_OUTP(MDP_BASE + 0x90070, 0); + MDP_OUTP(MDP_BASE + 0x94010, 1); + MDP_OUTP(MDP_BASE + 0x9401c, 2); +#endif + + /* + * limit vector + * pre gets applied before color matrix conversion + * post is after ccs + */ + writel(mdp_plv[0], MDP_CSC_PRE_LV1n(0)); + writel(mdp_plv[1], MDP_CSC_PRE_LV1n(1)); + writel(mdp_plv[2], MDP_CSC_PRE_LV1n(2)); + writel(mdp_plv[3], MDP_CSC_PRE_LV1n(3)); + +#ifdef CONFIG_FB_MSM_MDP31 + writel(mdp_plv[2], MDP_CSC_PRE_LV1n(4)); + writel(mdp_plv[3], MDP_CSC_PRE_LV1n(5)); + + writel(0, MDP_CSC_POST_LV1n(0)); + writel(0xff, MDP_CSC_POST_LV1n(1)); + writel(0, MDP_CSC_POST_LV1n(2)); + writel(0xff, MDP_CSC_POST_LV1n(3)); + writel(0, MDP_CSC_POST_LV1n(4)); + writel(0xff, MDP_CSC_POST_LV1n(5)); + + writel(0, MDP_CSC_PRE_LV2n(0)); + writel(0xff, MDP_CSC_PRE_LV2n(1)); + writel(0, MDP_CSC_PRE_LV2n(2)); + writel(0xff, MDP_CSC_PRE_LV2n(3)); + writel(0, MDP_CSC_PRE_LV2n(4)); + writel(0xff, MDP_CSC_PRE_LV2n(5)); + + writel(mdp_plv[0], MDP_CSC_POST_LV2n(0)); + writel(mdp_plv[1], MDP_CSC_POST_LV2n(1)); + writel(mdp_plv[2], MDP_CSC_POST_LV2n(2)); + writel(mdp_plv[3], MDP_CSC_POST_LV2n(3)); + writel(mdp_plv[2], MDP_CSC_POST_LV2n(4)); + writel(mdp_plv[3], MDP_CSC_POST_LV2n(5)); +#endif + + /* primary forward matrix */ + for (i = 0; i < MDP_CCS_SIZE; i++) + writel(mdp_ccs_rgb2yuv.ccs[i], MDP_CSC_PFMVn(i)); + +#ifdef CONFIG_FB_MSM_MDP31 + for (i = 0; i < MDP_BV_SIZE; i++) + writel(mdp_ccs_rgb2yuv.bv[i], MDP_CSC_POST_BV2n(i)); + + writel(0, MDP_CSC_PRE_BV2n(0)); + writel(0, MDP_CSC_PRE_BV2n(1)); + writel(0, MDP_CSC_PRE_BV2n(2)); +#endif + /* primary reverse matrix */ + for (i = 0; i < MDP_CCS_SIZE; i++) + writel(mdp_ccs_yuv2rgb.ccs[i], MDP_CSC_PRMVn(i)); + + for (i = 0; i < MDP_BV_SIZE; i++) + writel(mdp_ccs_yuv2rgb.bv[i], MDP_CSC_PRE_BV1n(i)); + +#ifdef CONFIG_FB_MSM_MDP31 + writel(0, MDP_CSC_POST_BV1n(0)); + writel(0, MDP_CSC_POST_BV1n(1)); + writel(0, MDP_CSC_POST_BV1n(2)); + + outpdw(MDP_BASE + 0x30010, 0x03e0); + outpdw(MDP_BASE + 0x30014, 0x0360); + outpdw(MDP_BASE + 0x30018, 0x0120); + outpdw(MDP_BASE + 0x3001c, 0x0140); +#endif + mdp_init_scale_table(); + +#ifndef CONFIG_FB_MSM_MDP31 + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0104, + ((16 << 6) << 16) | (16) << 6); +#endif + + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); +}
\ No newline at end of file diff --git a/drivers/staging/msm/mdp_ppp.c b/drivers/staging/msm/mdp_ppp.c new file mode 100644 index 000000000000..c35a6aebca14 --- /dev/null +++ b/drivers/staging/msm/mdp_ppp.c @@ -0,0 +1,1502 @@ +/* drivers/video/msm/src/drv/mdp/mdp_ppp.c + * + * Copyright (C) 2007 Google Incorporated + * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/fb.h> +#include <msm_mdp.h> +#include <linux/file.h> +#include <linux/major.h> + +#include "linux/proc_fs.h" + +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> + +#include "mdp.h" +#include "msm_fb.h" + +#define MDP_IS_IMGTYPE_BAD(x) (((x) >= MDP_IMGTYPE_LIMIT) && \ + (((x) < MDP_IMGTYPE2_START) || \ + ((x) >= MDP_IMGTYPE_LIMIT2))) + +static uint32_t bytes_per_pixel[] = { + [MDP_RGB_565] = 2, + [MDP_RGB_888] = 3, + [MDP_XRGB_8888] = 4, + [MDP_ARGB_8888] = 4, + [MDP_RGBA_8888] = 4, + [MDP_BGRA_8888] = 4, + [MDP_Y_CBCR_H2V1] = 1, + [MDP_Y_CBCR_H2V2] = 1, + [MDP_Y_CRCB_H2V1] = 1, + [MDP_Y_CRCB_H2V2] = 1, + [MDP_YCRYCB_H2V1] = 2, + [MDP_BGR_565] = 2 +}; + +extern uint32 mdp_plv[]; +extern struct semaphore mdp_ppp_mutex; + +uint32_t mdp_get_bytes_per_pixel(uint32_t format) +{ + uint32_t bpp = 0; + if (format < ARRAY_SIZE(bytes_per_pixel)) + bpp = bytes_per_pixel[format]; + + BUG_ON(!bpp); + return bpp; +} + +static uint32 mdp_conv_matx_rgb2yuv(uint32 input_pixel, + uint16 *matrix_and_bias_vector, + uint32 *clamp_vector, + uint32 *look_up_table) +{ + uint8 input_C2, input_C0, input_C1; + uint32 output; + int32 comp_C2, comp_C1, comp_C0, temp; + int32 temp1, temp2, temp3; + int32 matrix[9]; + int32 bias_vector[3]; + int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit; + int32 i; + uint32 _is_lookup_table_enabled; + + input_C2 = (input_pixel >> 16) & 0xFF; + input_C1 = (input_pixel >> 8) & 0xFF; + input_C0 = (input_pixel >> 0) & 0xFF; + + comp_C0 = input_C0; + comp_C1 = input_C1; + comp_C2 = input_C2; + + for (i = 0; i < 9; i++) + matrix[i] = + ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20; + + bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF); + bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF); + bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF); + + Y_low_limit = (int32) clamp_vector[0]; + Y_high_limit = (int32) clamp_vector[1]; + C_low_limit = (int32) clamp_vector[2]; + C_high_limit = (int32) clamp_vector[3]; + + if (look_up_table == 0) /* check for NULL point */ + _is_lookup_table_enabled = 0; + else + _is_lookup_table_enabled = 1; + + if (_is_lookup_table_enabled == 1) { + comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF; + comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF; + comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF; + } + /* + * Color Conversion + * reorder input colors + */ + temp = comp_C2; + comp_C2 = comp_C1; + comp_C1 = comp_C0; + comp_C0 = temp; + + /* matrix multiplication */ + temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2]; + temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5]; + temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8]; + + comp_C0 = temp1 + 0x100; + comp_C1 = temp2 + 0x100; + comp_C2 = temp3 + 0x100; + + /* take interger part */ + comp_C0 >>= 9; + comp_C1 >>= 9; + comp_C2 >>= 9; + + /* post bias (+) */ + comp_C0 += bias_vector[0]; + comp_C1 += bias_vector[1]; + comp_C2 += bias_vector[2]; + + /* limit pixel to 8-bit */ + if (comp_C0 < 0) + comp_C0 = 0; + + if (comp_C0 > 255) + comp_C0 = 255; + + if (comp_C1 < 0) + comp_C1 = 0; + + if (comp_C1 > 255) + comp_C1 = 255; + + if (comp_C2 < 0) + comp_C2 = 0; + + if (comp_C2 > 255) + comp_C2 = 255; + + /* clamp */ + if (comp_C0 < Y_low_limit) + comp_C0 = Y_low_limit; + + if (comp_C0 > Y_high_limit) + comp_C0 = Y_high_limit; + + if (comp_C1 < C_low_limit) + comp_C1 = C_low_limit; + + if (comp_C1 > C_high_limit) + comp_C1 = C_high_limit; + + if (comp_C2 < C_low_limit) + comp_C2 = C_low_limit; + + if (comp_C2 > C_high_limit) + comp_C2 = C_high_limit; + + output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0; + return output; +} + +uint32 mdp_conv_matx_yuv2rgb(uint32 input_pixel, + uint16 *matrix_and_bias_vector, + uint32 *clamp_vector, uint32 *look_up_table) +{ + uint8 input_C2, input_C0, input_C1; + uint32 output; + int32 comp_C2, comp_C1, comp_C0, temp; + int32 temp1, temp2, temp3; + int32 matrix[9]; + int32 bias_vector[3]; + int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit; + int32 i; + uint32 _is_lookup_table_enabled; + + input_C2 = (input_pixel >> 16) & 0xFF; + input_C1 = (input_pixel >> 8) & 0xFF; + input_C0 = (input_pixel >> 0) & 0xFF; + + comp_C0 = input_C0; + comp_C1 = input_C1; + comp_C2 = input_C2; + + for (i = 0; i < 9; i++) + matrix[i] = + ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20; + + bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF); + bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF); + bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF); + + Y_low_limit = (int32) clamp_vector[0]; + Y_high_limit = (int32) clamp_vector[1]; + C_low_limit = (int32) clamp_vector[2]; + C_high_limit = (int32) clamp_vector[3]; + + if (look_up_table == 0) /* check for NULL point */ + _is_lookup_table_enabled = 0; + else + _is_lookup_table_enabled = 1; + + /* clamp */ + if (comp_C0 < Y_low_limit) + comp_C0 = Y_low_limit; + + if (comp_C0 > Y_high_limit) + comp_C0 = Y_high_limit; + + if (comp_C1 < C_low_limit) + comp_C1 = C_low_limit; + + if (comp_C1 > C_high_limit) + comp_C1 = C_high_limit; + + if (comp_C2 < C_low_limit) + comp_C2 = C_low_limit; + + if (comp_C2 > C_high_limit) + comp_C2 = C_high_limit; + + /* + * Color Conversion + * pre bias (-) + */ + comp_C0 -= bias_vector[0]; + comp_C1 -= bias_vector[1]; + comp_C2 -= bias_vector[2]; + + /* matrix multiplication */ + temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2]; + temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5]; + temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8]; + + comp_C0 = temp1 + 0x100; + comp_C1 = temp2 + 0x100; + comp_C2 = temp3 + 0x100; + + /* take interger part */ + comp_C0 >>= 9; + comp_C1 >>= 9; + comp_C2 >>= 9; + + /* reorder output colors */ + temp = comp_C0; + comp_C0 = comp_C1; + comp_C1 = comp_C2; + comp_C2 = temp; + + /* limit pixel to 8-bit */ + if (comp_C0 < 0) + comp_C0 = 0; + + if (comp_C0 > 255) + comp_C0 = 255; + + if (comp_C1 < 0) + comp_C1 = 0; + + if (comp_C1 > 255) + comp_C1 = 255; + + if (comp_C2 < 0) + comp_C2 = 0; + + if (comp_C2 > 255) + comp_C2 = 255; + + /* Look-up table */ + if (_is_lookup_table_enabled == 1) { + comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF; + comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF; + comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF; + } + + output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0; + return output; +} + +static uint32 mdp_calc_tpval(MDPIMG *mdpImg) +{ + uint32 tpVal; + uint8 plane_tp; + + tpVal = 0; + if ((mdpImg->imgType == MDP_RGB_565) + || (mdpImg->imgType == MDP_BGR_565)) { + /* + * transparent color conversion into 24 bpp + * + * C2R_8BIT + * left shift the entire bit and or it with the upper most bits + */ + plane_tp = (uint8) ((mdpImg->tpVal & 0xF800) >> 11); + tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16; + + /* C1B_8BIT */ + plane_tp = (uint8) (mdpImg->tpVal & 0x1F); + tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8; + + /* C0G_8BIT */ + plane_tp = (uint8) ((mdpImg->tpVal & 0x7E0) >> 5); + tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4)); + } else { + /* 24bit RGB to RBG conversion */ + + tpVal = (mdpImg->tpVal & 0xFF00) >> 8; + tpVal |= (mdpImg->tpVal & 0xFF) << 8; + tpVal |= (mdpImg->tpVal & 0xFF0000); + } + + return tpVal; +} + +static uint8 *mdp_get_chroma_addr(MDPIBUF *iBuf) +{ + uint8 *dest1; + + dest1 = NULL; + switch (iBuf->ibuf_type) { + case MDP_Y_CBCR_H2V2: + case MDP_Y_CRCB_H2V2: + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V1: + dest1 = (uint8 *) iBuf->buf; + dest1 += iBuf->ibuf_width * iBuf->ibuf_height * iBuf->bpp; + break; + + default: + break; + } + + return dest1; +} + +static void mdp_ppp_setbg(MDPIBUF *iBuf) +{ + uint8 *bg0_addr; + uint8 *bg1_addr; + uint32 bg0_ystride, bg1_ystride; + uint32 ppp_src_cfg_reg, unpack_pattern; + int v_slice, h_slice; + + v_slice = h_slice = 1; + bg0_addr = (uint8 *) iBuf->buf; + bg1_addr = mdp_get_chroma_addr(iBuf); + + bg0_ystride = iBuf->ibuf_width * iBuf->bpp; + bg1_ystride = iBuf->ibuf_width * iBuf->bpp; + + switch (iBuf->ibuf_type) { + case MDP_BGR_565: + case MDP_RGB_565: + /* 888 = 3bytes + * RGB = 3Components + * RGB interleaved + */ + ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS | + PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES | + PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | + PPP_SRC_UNPACK_ALIGN_LSB | + PPP_SRC_FETCH_PLANES_INTERLVD; + + if (iBuf->ibuf_type == MDP_RGB_565) + unpack_pattern = + MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); + else + unpack_pattern = + MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8); + break; + + case MDP_RGB_888: + /* + * 888 = 3bytes + * RGB = 3Components + * RGB interleaved + */ + ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | + PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES | + PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | + PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_INTERLVD; + + unpack_pattern = + MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); + break; + + case MDP_BGRA_8888: + case MDP_RGBA_8888: + case MDP_ARGB_8888: + case MDP_XRGB_8888: + /* + * 8888 = 4bytes + * ARGB = 4Components + * ARGB interleaved + */ + ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | + PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | PPP_SRC_C3_ALPHA_EN | + PPP_SRC_BPP_INTERLVD_4BYTES | PPP_SRC_INTERLVD_4COMPONENTS | + PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB | + PPP_SRC_FETCH_PLANES_INTERLVD; + + if (iBuf->ibuf_type == MDP_BGRA_8888) + unpack_pattern = + MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, + 8); + else if (iBuf->ibuf_type == MDP_RGBA_8888) + unpack_pattern = + MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, + 8); + else + unpack_pattern = + MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, + 8); + break; + + case MDP_Y_CBCR_H2V2: + case MDP_Y_CRCB_H2V2: + ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | + PPP_SRC_C0G_8BITS | + PPP_SRC_C1B_8BITS | + PPP_SRC_C3A_8BITS | + PPP_SRC_BPP_INTERLVD_2BYTES | + PPP_SRC_INTERLVD_2COMPONENTS | + PPP_SRC_UNPACK_TIGHT | + PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; + + if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1) + unpack_pattern = + MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); + else + unpack_pattern = + MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); + v_slice = h_slice = 2; + break; + + case MDP_YCRYCB_H2V1: + ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | + PPP_SRC_C0G_8BITS | + PPP_SRC_C1B_8BITS | + PPP_SRC_C3A_8BITS | + PPP_SRC_BPP_INTERLVD_2BYTES | + PPP_SRC_INTERLVD_4COMPONENTS | + PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB; + + unpack_pattern = + MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8); + h_slice = 2; + break; + + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V1: + ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | + PPP_SRC_C0G_8BITS | + PPP_SRC_C1B_8BITS | + PPP_SRC_C3A_8BITS | + PPP_SRC_BPP_INTERLVD_2BYTES | + PPP_SRC_INTERLVD_2COMPONENTS | + PPP_SRC_UNPACK_TIGHT | + PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; + + if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1) + unpack_pattern = + MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); + else + unpack_pattern = + MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); + h_slice = 2; + break; + + default: + return; + } + + /* starting input address adjustment */ + mdp_adjust_start_addr(&bg0_addr, &bg1_addr, v_slice, h_slice, + iBuf->roi.lcd_x, iBuf->roi.lcd_y, + iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp, + iBuf, 1); + + /* + * 0x01c0: background plane 0 addr + * 0x01c4: background plane 1 addr + * 0x01c8: background plane 2 addr + * 0x01cc: bg y stride for plane 0 and 1 + * 0x01d0: bg y stride for plane 2 + * 0x01d4: bg src PPP config + * 0x01d8: unpack pattern + */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c0, bg0_addr); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c4, bg1_addr); + + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01cc, + (bg1_ystride << 16) | bg0_ystride); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d4, ppp_src_cfg_reg); + + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d8, unpack_pattern); +} + +#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \ + (img == MDP_Y_CBCR_H2V2) | \ + (img == MDP_Y_CRCB_H2V1) | \ + (img == MDP_Y_CBCR_H2V1)) + +#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp) + +#define Y_TO_CRCB_RATIO(format) \ + ((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ? 2 :\ + (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ? 1 : 1) + +static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp, + uint32_t *len0, uint32_t *len1) +{ + *len0 = IMG_LEN(rect->h, img->width, rect->w, bpp); + if (IS_PSEUDOPLNR(img->format)) + *len1 = *len0/Y_TO_CRCB_RATIO(img->format); + else + *len1 = 0; +} + +static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp, + struct file *p_src_file, struct file *p_dst_file) +{ +#ifdef CONFIG_ANDROID_PMEM + uint32_t src0_len, src1_len, dst0_len, dst1_len; + + /* flush src images to memory before dma to mdp */ + get_len(&req->src, &req->src_rect, src_bpp, + &src0_len, &src1_len); + + flush_pmem_file(p_src_file, + req->src.offset, src0_len); + + if (IS_PSEUDOPLNR(req->src.format)) + flush_pmem_file(p_src_file, + req->src.offset + src0_len, src1_len); + + get_len(&req->dst, &req->dst_rect, dst_bpp, &dst0_len, &dst1_len); + flush_pmem_file(p_dst_file, req->dst.offset, dst0_len); + + if (IS_PSEUDOPLNR(req->dst.format)) + flush_pmem_file(p_dst_file, + req->dst.offset + dst0_len, dst1_len); +#endif +} + +static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf, +struct mdp_blit_req *req, struct file *p_src_file, struct file *p_dst_file) +{ + uint8 *src0, *src1; + uint8 *dest0, *dest1; + uint16 inpBpp; + uint32 dest0_ystride; + uint32 src_width; + uint32 src_height; + uint32 src0_ystride; + uint32 dst_roi_width; + uint32 dst_roi_height; + uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg; + uint32 alpha, tpVal; + uint32 packPattern; + uint32 dst_packPattern; + boolean inputRGB, outputRGB, pseudoplanr_output; + int sv_slice, sh_slice; + int dv_slice, dh_slice; + boolean perPixelAlpha = FALSE; + boolean ppp_lookUp_enable = FALSE; + + sv_slice = sh_slice = dv_slice = dh_slice = 1; + alpha = tpVal = 0; + src_width = iBuf->mdpImg.width; + src_height = iBuf->roi.y + iBuf->roi.height; + src1 = NULL; + dest1 = NULL; + + inputRGB = outputRGB = TRUE; + pseudoplanr_output = FALSE; + ppp_operation_reg = 0; + ppp_dst_cfg_reg = 0; + ppp_src_cfg_reg = 0; + + /* Wait for the pipe to clear */ + do { } while (mdp_ppp_pipe_wait() <= 0); + + /* + * destination config + */ + switch (iBuf->ibuf_type) { + case MDP_RGB_888: + dst_packPattern = + MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); + ppp_dst_cfg_reg = + PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | PPP_DST_C2R_8BIT | + PPP_DST_PACKET_CNT_INTERLVD_3ELEM | PPP_DST_PACK_TIGHT | + PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI | + PPP_DST_BPP_3BYTES | PPP_DST_PLANE_INTERLVD; + break; + + case MDP_XRGB_8888: + case MDP_ARGB_8888: + case MDP_RGBA_8888: + if (iBuf->ibuf_type == MDP_BGRA_8888) + dst_packPattern = + MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, + 8); + else if (iBuf->ibuf_type == MDP_RGBA_8888) + dst_packPattern = + MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, + 8); + else + dst_packPattern = + MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, + 8); + + ppp_dst_cfg_reg = PPP_DST_C0G_8BIT | + PPP_DST_C1B_8BIT | + PPP_DST_C2R_8BIT | + PPP_DST_C3A_8BIT | + PPP_DST_C3ALPHA_EN | + PPP_DST_PACKET_CNT_INTERLVD_4ELEM | + PPP_DST_PACK_TIGHT | + PPP_DST_PACK_ALIGN_LSB | + PPP_DST_OUT_SEL_AXI | + PPP_DST_BPP_4BYTES | PPP_DST_PLANE_INTERLVD; + break; + + case MDP_Y_CBCR_H2V2: + case MDP_Y_CRCB_H2V2: + if (iBuf->ibuf_type == MDP_Y_CBCR_H2V2) + dst_packPattern = + MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); + else + dst_packPattern = + MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); + + ppp_dst_cfg_reg = PPP_DST_C2R_8BIT | + PPP_DST_C0G_8BIT | + PPP_DST_C1B_8BIT | + PPP_DST_C3A_8BIT | + PPP_DST_PACKET_CNT_INTERLVD_2ELEM | + PPP_DST_PACK_TIGHT | + PPP_DST_PACK_ALIGN_LSB | + PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES; + + ppp_operation_reg |= PPP_OP_DST_CHROMA_420; + outputRGB = FALSE; + pseudoplanr_output = TRUE; + /* + * vertically (y direction) and horizontally (x direction) + * sample reduction by 2 + */ + + /* + * H2V2(YUV420) Cosite + * + * Y Y Y Y + * CbCr CbCr + * Y Y Y Y + * Y Y Y Y + * CbCr CbCr + * Y Y Y Y + */ + dv_slice = dh_slice = 2; + + /* (x,y) and (width,height) must be even numbern */ + iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; + iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; + iBuf->roi.x = (iBuf->roi.x / 2) * 2; + iBuf->roi.width = (iBuf->roi.width / 2) * 2; + + iBuf->roi.lcd_y = (iBuf->roi.lcd_y / 2) * 2; + iBuf->roi.dst_height = (iBuf->roi.dst_height / 2) * 2; + iBuf->roi.y = (iBuf->roi.y / 2) * 2; + iBuf->roi.height = (iBuf->roi.height / 2) * 2; + break; + + case MDP_YCRYCB_H2V1: + dst_packPattern = + MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8); + ppp_dst_cfg_reg = + PPP_DST_C2R_8BIT | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | + PPP_DST_C3A_8BIT | PPP_DST_PACKET_CNT_INTERLVD_4ELEM | + PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB | + PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES | + PPP_DST_PLANE_INTERLVD; + + ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1; + outputRGB = FALSE; + /* + * horizontally (x direction) sample reduction by 2 + * + * H2V1(YUV422) Cosite + * + * YCbCr Y YCbCr Y + * YCbCr Y YCbCr Y + * YCbCr Y YCbCr Y + * YCbCr Y YCbCr Y + */ + dh_slice = 2; + + /* + * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the + * preloaded gamma setting of 2.2 when the content is + * non-linear ppp_lookUp_enable = TRUE; + */ + + /* x and width must be even number */ + iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; + iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; + iBuf->roi.x = (iBuf->roi.x / 2) * 2; + iBuf->roi.width = (iBuf->roi.width / 2) * 2; + break; + + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V1: + if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1) + dst_packPattern = + MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); + else + dst_packPattern = + MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); + + ppp_dst_cfg_reg = PPP_DST_C2R_8BIT | + PPP_DST_C0G_8BIT | + PPP_DST_C1B_8BIT | + PPP_DST_C3A_8BIT | + PPP_DST_PACKET_CNT_INTERLVD_2ELEM | + PPP_DST_PACK_TIGHT | + PPP_DST_PACK_ALIGN_LSB | + PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES; + + ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1; + outputRGB = FALSE; + pseudoplanr_output = TRUE; + /* horizontally (x direction) sample reduction by 2 */ + dh_slice = 2; + + /* x and width must be even number */ + iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; + iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; + iBuf->roi.x = (iBuf->roi.x / 2) * 2; + iBuf->roi.width = (iBuf->roi.width / 2) * 2; + break; + + case MDP_BGR_565: + case MDP_RGB_565: + default: + if (iBuf->ibuf_type == MDP_RGB_565) + dst_packPattern = + MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); + else + dst_packPattern = + MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8); + + ppp_dst_cfg_reg = PPP_DST_C0G_6BIT | + PPP_DST_C1B_5BIT | + PPP_DST_C2R_5BIT | + PPP_DST_PACKET_CNT_INTERLVD_3ELEM | + PPP_DST_PACK_TIGHT | + PPP_DST_PACK_ALIGN_LSB | + PPP_DST_OUT_SEL_AXI | + PPP_DST_BPP_2BYTES | PPP_DST_PLANE_INTERLVD; + break; + } + + /* source config */ + switch (iBuf->mdpImg.imgType) { + case MDP_RGB_888: + inpBpp = 3; + /* + * 565 = 2bytes + * RGB = 3Components + * RGB interleaved + */ + ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | + PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES | + PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | + PPP_SRC_UNPACK_ALIGN_LSB | + PPP_SRC_FETCH_PLANES_INTERLVD; + + packPattern = MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); + + ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB | + PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB; + break; + + case MDP_BGRA_8888: + case MDP_RGBA_8888: + case MDP_ARGB_8888: + perPixelAlpha = TRUE; + case MDP_XRGB_8888: + inpBpp = 4; + /* + * 8888 = 4bytes + * ARGB = 4Components + * ARGB interleaved + */ + ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | + PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | + PPP_SRC_C3_ALPHA_EN | PPP_SRC_BPP_INTERLVD_4BYTES | + PPP_SRC_INTERLVD_4COMPONENTS | PPP_SRC_UNPACK_TIGHT | + PPP_SRC_UNPACK_ALIGN_LSB | + PPP_SRC_FETCH_PLANES_INTERLVD; + + if (iBuf->mdpImg.imgType == MDP_BGRA_8888) + packPattern = + MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, + 8); + else if (iBuf->mdpImg.imgType == MDP_RGBA_8888) + packPattern = + MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, + 8); + else + packPattern = + MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, + 8); + + ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB | + PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB; + break; + + case MDP_Y_CBCR_H2V2: + case MDP_Y_CRCB_H2V2: + inpBpp = 1; + src1 = (uint8 *) iBuf->mdpImg.cbcr_addr; + + /* + * CbCr = 2bytes + * CbCr = 2Components + * Y+CbCr + */ + ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | + PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES | + PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT | + PPP_SRC_UNPACK_ALIGN_LSB | + PPP_SRC_FETCH_PLANES_PSEUDOPLNR; + + if (iBuf->mdpImg.imgType == MDP_Y_CRCB_H2V2) + packPattern = + MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); + else + packPattern = + MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); + + ppp_operation_reg |= PPP_OP_COLOR_SPACE_YCBCR | + PPP_OP_SRC_CHROMA_420 | + PPP_OP_SRC_CHROMA_COSITE | + PPP_OP_DST_CHROMA_RGB | PPP_OP_DST_CHROMA_COSITE; + + inputRGB = FALSE; + sh_slice = sv_slice = 2; + break; + + case MDP_YCRYCB_H2V1: + inpBpp = 2; + ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | + PPP_SRC_C0G_8BITS | + PPP_SRC_C1B_8BITS | + PPP_SRC_C3A_8BITS | + PPP_SRC_BPP_INTERLVD_2BYTES | + PPP_SRC_INTERLVD_4COMPONENTS | + PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB; + + packPattern = + MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8); + + ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 | + PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE; + + /* + * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the + * preloaded inverse gamma setting of 2.2 since they're + * symetric when the content is non-linear + * ppp_lookUp_enable = TRUE; + */ + + /* x and width must be even number */ + iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; + iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; + iBuf->roi.x = (iBuf->roi.x / 2) * 2; + iBuf->roi.width = (iBuf->roi.width / 2) * 2; + + inputRGB = FALSE; + sh_slice = 2; + break; + + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V1: + inpBpp = 1; + src1 = (uint8 *) iBuf->mdpImg.cbcr_addr; + + ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | + PPP_SRC_C0G_8BITS | + PPP_SRC_C1B_8BITS | + PPP_SRC_C3A_8BITS | + PPP_SRC_BPP_INTERLVD_2BYTES | + PPP_SRC_INTERLVD_2COMPONENTS | + PPP_SRC_UNPACK_TIGHT | + PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; + + if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V1) + packPattern = + MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); + else + packPattern = + MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); + + ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 | + PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE; + inputRGB = FALSE; + sh_slice = 2; + break; + + case MDP_BGR_565: + case MDP_RGB_565: + default: + inpBpp = 2; + /* + * 565 = 2bytes + * RGB = 3Components + * RGB interleaved + */ + ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS | + PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES | + PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | + PPP_SRC_UNPACK_ALIGN_LSB | + PPP_SRC_FETCH_PLANES_INTERLVD; + + if (iBuf->mdpImg.imgType == MDP_RGB_565) + packPattern = + MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); + else + packPattern = + MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8); + + ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB | + PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB; + break; + + } + + if (pseudoplanr_output) + ppp_dst_cfg_reg |= PPP_DST_PLANE_PSEUDOPLN; + + /* YCbCr to RGB color conversion flag */ + if ((!inputRGB) && (outputRGB)) { + ppp_operation_reg |= PPP_OP_CONVERT_YCBCR2RGB | + PPP_OP_CONVERT_ON; + + /* + * primary/secondary is sort of misleading term...but + * in mdp2.2/3.0 we only use primary matrix (forward/rev) + * in mdp3.1 we use set1(prim) and set2(secd) + */ +#ifdef CONFIG_FB_MSM_MDP31 + ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_SECONDARY | + PPP_OP_DST_RGB; + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0); +#endif + + if (ppp_lookUp_enable) { + ppp_operation_reg |= PPP_OP_LUT_C0_ON | + PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON; + } + } + /* RGB to YCbCr color conversion flag */ + if ((inputRGB) && (!outputRGB)) { + ppp_operation_reg |= PPP_OP_CONVERT_RGB2YCBCR | + PPP_OP_CONVERT_ON; + +#ifdef CONFIG_FB_MSM_MDP31 + ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_PRIMARY | + PPP_OP_DST_YCBCR; + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0x1e); +#endif + + if (ppp_lookUp_enable) { + ppp_operation_reg |= PPP_OP_LUT_C0_ON | + PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON; + } + } + /* YCbCr to YCbCr color conversion flag */ + if ((!inputRGB) && (!outputRGB)) { + if ((ppp_lookUp_enable) && + (iBuf->mdpImg.imgType != iBuf->ibuf_type)) { + ppp_operation_reg |= PPP_OP_LUT_C0_ON; + } + } + + ppp_src_cfg_reg |= (iBuf->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0; + ppp_src_cfg_reg |= (iBuf->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0; + + if (req->flags & MDP_DEINTERLACE) + ppp_operation_reg |= PPP_OP_DEINT_EN; + + /* Dither at DMA side only since iBuf format is RGB888 */ + if (iBuf->mdpImg.mdpOp & MDPOP_DITHER) + ppp_operation_reg |= PPP_OP_DITHER_EN; + + if (iBuf->mdpImg.mdpOp & MDPOP_ROTATION) { + ppp_operation_reg |= PPP_OP_ROT_ON; + + if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) { + ppp_operation_reg |= PPP_OP_ROT_90; + } + if (iBuf->mdpImg.mdpOp & MDPOP_LR) { + ppp_operation_reg |= PPP_OP_FLIP_LR; + } + if (iBuf->mdpImg.mdpOp & MDPOP_UD) { + ppp_operation_reg |= PPP_OP_FLIP_UD; + } + } + + src0_ystride = src_width * inpBpp; + dest0_ystride = iBuf->ibuf_width * iBuf->bpp; + + /* no need to care about rotation since it's the real-XY. */ + dst_roi_width = iBuf->roi.dst_width; + dst_roi_height = iBuf->roi.dst_height; + + src0 = (uint8 *) iBuf->mdpImg.bmy_addr; + dest0 = (uint8 *) iBuf->buf; + + /* Jumping from Y-Plane to Chroma Plane */ + dest1 = mdp_get_chroma_addr(iBuf); + + /* first pixel addr calculation */ + mdp_adjust_start_addr(&src0, &src1, sv_slice, sh_slice, iBuf->roi.x, + iBuf->roi.y, src_width, src_height, inpBpp, iBuf, + 0); + mdp_adjust_start_addr(&dest0, &dest1, dv_slice, dh_slice, + iBuf->roi.lcd_x, iBuf->roi.lcd_y, + iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp, + iBuf, 2); + + /* set scale operation */ + mdp_set_scale(iBuf, dst_roi_width, dst_roi_height, + inputRGB, outputRGB, &ppp_operation_reg); + + /* + * setting background source for blending + */ + mdp_set_blend_attr(iBuf, &alpha, &tpVal, perPixelAlpha, + &ppp_operation_reg); + + if (ppp_operation_reg & PPP_OP_BLEND_ON) { + mdp_ppp_setbg(iBuf); + + if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) { + ppp_operation_reg |= PPP_OP_BG_CHROMA_H2V1; + + if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) { + tpVal = mdp_conv_matx_rgb2yuv(tpVal, + (uint16 *) & + mdp_ccs_rgb2yuv, + &mdp_plv[0], NULL); + } + } + } + + /* + * 0x0004: enable dbg bus + * 0x0100: "don't care" Edge Condit until scaling is on + * 0x0104: xrc tile x&y size u7.6 format = 7bit.6bit + * 0x0108: src pixel size + * 0x010c: component plane 0 starting address + * 0x011c: component plane 0 ystride + * 0x0124: PPP source config register + * 0x0128: unpacked pattern from lsb to msb (eg. RGB->BGR) + */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0108, (iBuf->roi.height << 16 | + iBuf->roi.width)); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c, + (src0_ystride << 16 | src0_ystride)); + + /* setup for rgb 565 */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0128, packPattern); + /* + * 0x0138: PPP destination operation register + * 0x014c: constant_alpha|transparent_color + * 0x0150: PPP destination config register + * 0x0154: PPP packing pattern + */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0138, ppp_operation_reg); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x014c, alpha << 24 | tpVal); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0150, ppp_dst_cfg_reg); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0154, dst_packPattern); + + /* + * 0x0164: ROI height and width + * 0x0168: Component Plane 0 starting addr + * 0x016c: Component Plane 1 starting addr + * 0x0178: Component Plane 1/0 y stride + */ + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0164, + (dst_roi_height << 16 | dst_roi_width)); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0168, dest0); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x016c, dest1); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0178, + (dest0_ystride << 16 | dest0_ystride)); + + flush_imgs(req, inpBpp, iBuf->bpp, p_src_file, p_dst_file); +#ifdef CONFIG_MDP_PPP_ASYNC_OP + mdp_ppp_process_curr_djob(); +#else + mdp_pipe_kickoff(MDP_PPP_TERM, mfd); +#endif +} + +static int mdp_ppp_verify_req(struct mdp_blit_req *req) +{ + u32 src_width, src_height, dst_width, dst_height; + + if (req == NULL) + return -1; + + if (MDP_IS_IMGTYPE_BAD(req->src.format) || + MDP_IS_IMGTYPE_BAD(req->dst.format)) + return -1; + + if ((req->src.width == 0) || (req->src.height == 0) || + (req->src_rect.w == 0) || (req->src_rect.h == 0) || + (req->dst.width == 0) || (req->dst.height == 0) || + (req->dst_rect.w == 0) || (req->dst_rect.h == 0)) + + return -1; + + if (((req->src_rect.x + req->src_rect.w) > req->src.width) || + ((req->src_rect.y + req->src_rect.h) > req->src.height)) + return -1; + + if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) || + ((req->dst_rect.y + req->dst_rect.h) > req->dst.height)) + return -1; + + /* + * scaling range check + */ + src_width = req->src_rect.w; + src_height = req->src_rect.h; + + if (req->flags & MDP_ROT_90) { + dst_width = req->dst_rect.h; + dst_height = req->dst_rect.w; + } else { + dst_width = req->dst_rect.w; + dst_height = req->dst_rect.h; + } + + switch (req->dst.format) { + case MDP_Y_CRCB_H2V2: + case MDP_Y_CBCR_H2V2: + src_width = (src_width / 2) * 2; + src_height = (src_height / 2) * 2; + dst_width = (src_width / 2) * 2; + dst_height = (src_height / 2) * 2; + break; + + case MDP_Y_CRCB_H2V1: + case MDP_Y_CBCR_H2V1: + case MDP_YCRYCB_H2V1: + src_width = (src_width / 2) * 2; + dst_width = (src_width / 2) * 2; + break; + + default: + break; + } + + if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width > + MDP_MAX_X_SCALE_FACTOR) + || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width < + MDP_MIN_X_SCALE_FACTOR)) + return -1; + + if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height > + MDP_MAX_Y_SCALE_FACTOR) + || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height < + MDP_MIN_Y_SCALE_FACTOR)) + return -1; + + return 0; +} + +/** + * get_gem_img() - retrieve drm obj's start address and size + * @img: contains drm file descriptor and gem handle + * @start: repository of starting address of drm obj allocated memory + * @len: repository of size of drm obj alloacted memory + * + **/ +int get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len) +{ + panic("waaaaaaaah"); + //return kgsl_gem_obj_addr(img->memory_id, (int)img->priv, start, len); +} + +int get_img(struct mdp_img *img, struct fb_info *info, unsigned long *start, + unsigned long *len, struct file **pp_file) +{ + int put_needed, ret = 0; + struct file *file; + unsigned long vstart; +#ifdef CONFIG_ANDROID_PMEM + if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file)) + return 0; +#endif + file = fget_light(img->memory_id, &put_needed); + if (file == NULL) + return -1; + + if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) { + *start = info->fix.smem_start; + *len = info->fix.smem_len; + *pp_file = file; + } else { + ret = -1; + fput_light(file, put_needed); + } + return ret; +} + +int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req, + struct file **pp_src_file, struct file **pp_dst_file) +{ + unsigned long src_start, dst_start; + unsigned long src_len = 0; + unsigned long dst_len = 0; + MDPIBUF iBuf; + u32 dst_width, dst_height; + struct file *p_src_file = 0 , *p_dst_file = 0; + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + + if (req->dst.format == MDP_FB_FORMAT) + req->dst.format = mfd->fb_imgType; + if (req->src.format == MDP_FB_FORMAT) + req->src.format = mfd->fb_imgType; + + if (req->flags & MDP_BLIT_SRC_GEM) { + if (get_gem_img(&req->src, &src_start, &src_len) < 0) + return -1; + } else { + get_img(&req->src, info, &src_start, &src_len, &p_src_file); + } + if (src_len == 0) { + printk(KERN_ERR "mdp_ppp: could not retrieve image from " + "memory\n"); + return -1; + } + + if (req->flags & MDP_BLIT_DST_GEM) { + if (get_gem_img(&req->dst, &dst_start, &dst_len) < 0) + return -1; + } else { + get_img(&req->dst, info, &dst_start, &dst_len, &p_dst_file); + } + if (dst_len == 0) { + printk(KERN_ERR "mdp_ppp: could not retrieve image from " + "memory\n"); + return -1; + } + *pp_src_file = p_src_file; + *pp_dst_file = p_dst_file; + if (mdp_ppp_verify_req(req)) { + printk(KERN_ERR "mdp_ppp: invalid image!\n"); + return -1; + } + + iBuf.ibuf_width = req->dst.width; + iBuf.ibuf_height = req->dst.height; + iBuf.bpp = bytes_per_pixel[req->dst.format]; + + iBuf.ibuf_type = req->dst.format; + iBuf.buf = (uint8 *) dst_start; + iBuf.buf += req->dst.offset; + + iBuf.roi.lcd_x = req->dst_rect.x; + iBuf.roi.lcd_y = req->dst_rect.y; + iBuf.roi.dst_width = req->dst_rect.w; + iBuf.roi.dst_height = req->dst_rect.h; + + iBuf.roi.x = req->src_rect.x; + iBuf.roi.width = req->src_rect.w; + iBuf.roi.y = req->src_rect.y; + iBuf.roi.height = req->src_rect.h; + + iBuf.mdpImg.width = req->src.width; + iBuf.mdpImg.imgType = req->src.format; + + iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset); + iBuf.mdpImg.cbcr_addr = + (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr + + req->src.width * req->src.height); + + iBuf.mdpImg.mdpOp = MDPOP_NOP; + + /* blending check */ + if (req->transp_mask != MDP_TRANSP_NOP) { + iBuf.mdpImg.mdpOp |= MDPOP_TRANSP; + iBuf.mdpImg.tpVal = req->transp_mask; + iBuf.mdpImg.tpVal = mdp_calc_tpval(&iBuf.mdpImg); + } + + req->alpha &= 0xff; + if (req->alpha < MDP_ALPHA_NOP) { + iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB; + iBuf.mdpImg.alpha = req->alpha; + } + + /* rotation check */ + if (req->flags & MDP_FLIP_LR) + iBuf.mdpImg.mdpOp |= MDPOP_LR; + if (req->flags & MDP_FLIP_UD) + iBuf.mdpImg.mdpOp |= MDPOP_UD; + if (req->flags & MDP_ROT_90) + iBuf.mdpImg.mdpOp |= MDPOP_ROT90; + if (req->flags & MDP_DITHER) + iBuf.mdpImg.mdpOp |= MDPOP_DITHER; + + if (req->flags & MDP_BLEND_FG_PREMULT) { +#ifdef CONFIG_FB_MSM_MDP31 + iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA; +#else + return -EINVAL; +#endif + } + + if (req->flags & MDP_DEINTERLACE) { +#ifdef CONFIG_FB_MSM_MDP31 + if ((req->src.format != MDP_Y_CBCR_H2V2) && + (req->src.format != MDP_Y_CRCB_H2V2)) +#endif + return -EINVAL; + } + + /* scale check */ + if (req->flags & MDP_ROT_90) { + dst_width = req->dst_rect.h; + dst_height = req->dst_rect.w; + } else { + dst_width = req->dst_rect.w; + dst_height = req->dst_rect.h; + } + + if ((iBuf.roi.width != dst_width) || (iBuf.roi.height != dst_height)) + iBuf.mdpImg.mdpOp |= MDPOP_ASCALE; + + if (req->flags & MDP_BLUR) { +#ifdef CONFIG_FB_MSM_MDP31 + if (req->flags & MDP_SHARPENING) + printk(KERN_WARNING + "mdp: MDP_SHARPENING is set with MDP_BLUR!\n"); + req->flags |= MDP_SHARPENING; + req->sharpening_strength = -127; +#else + iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_BLUR; + +#endif + } + + if (req->flags & MDP_SHARPENING) { +#ifdef CONFIG_FB_MSM_MDP31 + if ((req->sharpening_strength > 127) || + (req->sharpening_strength < -127)) { + printk(KERN_ERR + "%s: sharpening strength out of range\n", + __func__); + return -EINVAL; + } + + iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING; + iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff; +#else + return -EINVAL; +#endif + } + + down(&mdp_ppp_mutex); + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + +#ifdef CONFIG_FB_MSM_MDP31 + mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); +#else + /* bg tile fetching HW workaround */ + if (((iBuf.mdpImg.mdpOp & (MDPOP_TRANSP | MDPOP_ALPHAB)) || + (req->src.format == MDP_ARGB_8888) || + (req->src.format == MDP_BGRA_8888) || + (req->src.format == MDP_RGBA_8888)) && + (iBuf.mdpImg.mdpOp & MDPOP_ROT90) && (req->dst_rect.w <= 16)) { + int dst_h, src_w, i; + + src_w = req->src_rect.w; + dst_h = iBuf.roi.dst_height; + + for (i = 0; i < (req->dst_rect.h / 16); i++) { + /* this tile size */ + iBuf.roi.dst_height = 16; + iBuf.roi.width = + (16 * req->src_rect.w) / req->dst_rect.h; + + /* if it's out of scale range... */ + if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / + iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) + iBuf.roi.width = + (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / + MDP_MAX_X_SCALE_FACTOR; + else if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / + iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) + iBuf.roi.width = + (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / + MDP_MIN_X_SCALE_FACTOR; + + mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); + + /* next tile location */ + iBuf.roi.lcd_y += 16; + iBuf.roi.x += iBuf.roi.width; + + /* this is for a remainder update */ + dst_h -= 16; + src_w -= iBuf.roi.width; + } + + if ((dst_h < 0) || (src_w < 0)) + printk + ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n", + __LINE__); + + /* remainder update */ + if ((dst_h > 0) && (src_w > 0)) { + u32 tmp_v; + + iBuf.roi.dst_height = dst_h; + iBuf.roi.width = src_w; + + if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / + iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) { + tmp_v = + (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / + MDP_MAX_X_SCALE_FACTOR + + (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) % + MDP_MAX_X_SCALE_FACTOR ? 1 : 0; + + /* move x location as roi width gets bigger */ + iBuf.roi.x -= tmp_v - iBuf.roi.width; + iBuf.roi.width = tmp_v; + } else + if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / + iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) { + tmp_v = + (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / + MDP_MIN_X_SCALE_FACTOR + + (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) % + MDP_MIN_X_SCALE_FACTOR ? 1 : 0; + + /* + * we don't move x location for continuity of + * source image + */ + iBuf.roi.width = tmp_v; + } + + mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); + } + } else { + mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); + } +#endif + + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + up(&mdp_ppp_mutex); + + return 0; +} diff --git a/drivers/staging/msm/mdp_ppp_dq.c b/drivers/staging/msm/mdp_ppp_dq.c new file mode 100644 index 000000000000..3dc1c0cc61f9 --- /dev/null +++ b/drivers/staging/msm/mdp_ppp_dq.c @@ -0,0 +1,347 @@ +/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "mdp.h" + +static boolean mdp_ppp_intr_flag = FALSE; +static boolean mdp_ppp_busy_flag = FALSE; + +/* Queue to keep track of the completed jobs for cleaning */ +static LIST_HEAD(mdp_ppp_djob_clnrq); +static DEFINE_SPINLOCK(mdp_ppp_djob_clnrq_lock); + +/* Worker to cleanup Display Jobs */ +static struct workqueue_struct *mdp_ppp_djob_clnr; + +/* Display Queue (DQ) for MDP PPP Block */ +static LIST_HEAD(mdp_ppp_dq); +static DEFINE_SPINLOCK(mdp_ppp_dq_lock); + +/* Current Display Job for MDP PPP */ +static struct mdp_ppp_djob *curr_djob; + +/* Track ret code for the last opeartion */ +static int mdp_ppp_ret_code; + +inline int mdp_ppp_get_ret_code(void) +{ + return mdp_ppp_ret_code; +} + +/* Push <Reg, Val> pair into DQ (if available) to later + * program the MDP PPP Block */ +inline void mdp_ppp_outdw(uint32_t addr, uint32_t data) +{ + if (curr_djob) { + + /* get the last node of the list. */ + struct mdp_ppp_roi_cmd_set *node = + list_entry(curr_djob->roi_cmd_list.prev, + struct mdp_ppp_roi_cmd_set, node); + + /* If a node is already full, create a new one and add it to + * the list (roi_cmd_list). + */ + if (node->ncmds == MDP_PPP_ROI_NODE_SIZE) { + node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set), + GFP_KERNEL); + if (!node) { + printk(KERN_ERR + "MDP_PPP: not enough memory.\n"); + mdp_ppp_ret_code = -EINVAL; + return; + } + + /* no ROI commands initially */ + node->ncmds = 0; + + /* add one node to roi_cmd_list. */ + list_add_tail(&node->node, &curr_djob->roi_cmd_list); + } + + /* register ROI commands */ + node->cmd[node->ncmds].reg = addr; + node->cmd[node->ncmds].val = data; + node->ncmds++; + } else + /* program MDP PPP block now */ + outpdw((addr), (data)); +} + +/* Initialize DQ */ +inline void mdp_ppp_dq_init(void) +{ + mdp_ppp_djob_clnr = create_singlethread_workqueue("MDPDJobClnrThrd"); +} + +/* Release resources of a job (DJob). */ +static void mdp_ppp_del_djob(struct mdp_ppp_djob *job) +{ + struct mdp_ppp_roi_cmd_set *node, *tmp; + + /* release mem */ + mdp_ppp_put_img(job->p_src_file, job->p_dst_file); + + /* release roi_cmd_list */ + list_for_each_entry_safe(node, tmp, &job->roi_cmd_list, node) { + list_del(&node->node); + kfree(node); + } + + /* release job struct */ + kfree(job); +} + +/* Worker thread to reclaim resources once a display job is done */ +static void mdp_ppp_djob_cleaner(struct work_struct *work) +{ + struct mdp_ppp_djob *job; + + MDP_PPP_DEBUG_MSG("mdp ppp display job cleaner started \n"); + + /* cleanup display job */ + job = container_of(work, struct mdp_ppp_djob, cleaner.work); + if (likely(work && job)) + mdp_ppp_del_djob(job); +} + +/* Create a new Display Job (DJob) */ +inline struct mdp_ppp_djob *mdp_ppp_new_djob(void) +{ + struct mdp_ppp_djob *job; + struct mdp_ppp_roi_cmd_set *node; + + /* create a new djob */ + job = kmalloc(sizeof(struct mdp_ppp_djob), GFP_KERNEL); + if (!job) + return NULL; + + /* add the first node to curr_djob->roi_cmd_list */ + node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set), GFP_KERNEL); + if (!node) { + kfree(job); + return NULL; + } + + /* make this current djob container to keep track of the curr djob not + * used in the async path i.e. no sync needed + * + * Should not contain any references from the past djob + */ + BUG_ON(curr_djob); + curr_djob = job; + INIT_LIST_HEAD(&curr_djob->roi_cmd_list); + + /* no ROI commands initially */ + node->ncmds = 0; + INIT_LIST_HEAD(&node->node); + list_add_tail(&node->node, &curr_djob->roi_cmd_list); + + /* register this djob with the djob cleaner + * initializes 'work' data struct + */ + INIT_DELAYED_WORK(&curr_djob->cleaner, mdp_ppp_djob_cleaner); + INIT_LIST_HEAD(&curr_djob->entry); + + curr_djob->p_src_file = 0; + curr_djob->p_dst_file = 0; + + return job; +} + +/* Undo the effect of mdp_ppp_new_djob() */ +inline void mdp_ppp_clear_curr_djob(void) +{ + if (likely(curr_djob)) { + mdp_ppp_del_djob(curr_djob); + curr_djob = NULL; + } +} + +/* Cleanup dirty djobs */ +static void mdp_ppp_flush_dirty_djobs(void *cond) +{ + unsigned long flags; + struct mdp_ppp_djob *job; + + /* Flush the jobs from the djob clnr queue */ + while (cond && test_bit(0, (unsigned long *)cond)) { + + /* Until we are done with the cleanup queue */ + spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags); + if (list_empty(&mdp_ppp_djob_clnrq)) { + spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags); + break; + } + + MDP_PPP_DEBUG_MSG("flushing djobs ... loop \n"); + + /* Retrieve the job that needs to be cleaned */ + job = list_entry(mdp_ppp_djob_clnrq.next, + struct mdp_ppp_djob, entry); + list_del_init(&job->entry); + spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags); + + /* Keep mem state coherent */ + msm_fb_ensure_mem_coherency_after_dma(job->info, &job->req, 1); + + /* Schedule jobs for cleanup + * A seperate worker thread does this */ + queue_delayed_work(mdp_ppp_djob_clnr, &job->cleaner, + mdp_timer_duration); + } +} + +/* If MDP PPP engine is busy, wait until it is available again */ +void mdp_ppp_wait(void) +{ + unsigned long flags; + int cond = 1; + + /* keep flushing dirty djobs as long as MDP PPP engine is busy */ + mdp_ppp_flush_dirty_djobs(&mdp_ppp_busy_flag); + + /* block if MDP PPP engine is still busy */ + spin_lock_irqsave(&mdp_ppp_dq_lock, flags); + if (test_bit(0, (unsigned long *)&mdp_ppp_busy_flag)) { + + /* prepare for the wakeup event */ + test_and_set_bit(0, (unsigned long *)&mdp_ppp_waiting); + INIT_COMPLETION(mdp_ppp_comp); + spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); + + /* block uninterruptibly until available */ + MDP_PPP_DEBUG_MSG("waiting for mdp... \n"); + wait_for_completion_killable(&mdp_ppp_comp); + + /* if MDP PPP engine is still free, + * disable INT_MDP if enabled + */ + spin_lock_irqsave(&mdp_ppp_dq_lock, flags); + if (!test_bit(0, (unsigned long *)&mdp_ppp_busy_flag) && + test_and_clear_bit(0, (unsigned long *)&mdp_ppp_intr_flag)) + mdp_disable_irq(MDP_PPP_TERM); + } + spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); + + /* flush remaining dirty djobs, if any */ + mdp_ppp_flush_dirty_djobs(&cond); +} + +/* Program MDP PPP block to process this ROI */ +static void mdp_ppp_process_roi(struct list_head *roi_cmd_list) +{ + + /* program PPP engine with registered ROI commands */ + struct mdp_ppp_roi_cmd_set *node; + list_for_each_entry(node, roi_cmd_list, node) { + int i = 0; + for (; i < node->ncmds; i++) { + MDP_PPP_DEBUG_MSG("%d: reg: 0x%x val: 0x%x \n", + i, node->cmd[i].reg, node->cmd[i].val); + outpdw(node->cmd[i].reg, node->cmd[i].val); + } + } + + /* kickoff MDP PPP engine */ + MDP_PPP_DEBUG_MSG("kicking off mdp \n"); + outpdw(MDP_BASE + 0x30, 0x1000); +} + +/* Submit this display job to MDP PPP engine */ +static void mdp_ppp_dispatch_djob(struct mdp_ppp_djob *job) +{ + /* enable INT_MDP if disabled */ + if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_intr_flag)) + mdp_enable_irq(MDP_PPP_TERM); + + /* turn on PPP and CMD blocks */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + + /* process this ROI */ + mdp_ppp_process_roi(&job->roi_cmd_list); +} + +/* Enqueue this display job to be cleaned up later in "mdp_ppp_djob_done" */ +static inline void mdp_ppp_enqueue_djob(struct mdp_ppp_djob *job) +{ + unsigned long flags; + + spin_lock_irqsave(&mdp_ppp_dq_lock, flags); + list_add_tail(&job->entry, &mdp_ppp_dq); + spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); +} + +/* First enqueue display job for cleanup and dispatch immediately + * if MDP PPP engine is free */ +void mdp_ppp_process_curr_djob(void) +{ + /* enqueue djob */ + mdp_ppp_enqueue_djob(curr_djob); + + /* dispatch now if MDP PPP engine is free */ + if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_busy_flag)) + mdp_ppp_dispatch_djob(curr_djob); + + /* done with the current djob */ + curr_djob = NULL; +} + +/* Called from mdp_isr - cleanup finished job and start with next + * if available else set MDP PPP engine free */ +void mdp_ppp_djob_done(void) +{ + struct mdp_ppp_djob *curr, *next; + unsigned long flags; + + /* dequeue current */ + spin_lock_irqsave(&mdp_ppp_dq_lock, flags); + curr = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob, entry); + list_del_init(&curr->entry); + spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); + + /* cleanup current - enqueue in the djob clnr queue */ + spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags); + list_add_tail(&curr->entry, &mdp_ppp_djob_clnrq); + spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags); + + /* grab next pending */ + spin_lock_irqsave(&mdp_ppp_dq_lock, flags); + if (!list_empty(&mdp_ppp_dq)) { + next = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob, + entry); + spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); + + /* process next in the queue */ + mdp_ppp_process_roi(&next->roi_cmd_list); + } else { + /* no pending display job */ + spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); + + /* turn off PPP and CMD blocks - "in_isr" is TRUE */ + mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE); + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE); + + /* notify if waiting */ + if (test_and_clear_bit(0, (unsigned long *)&mdp_ppp_waiting)) + complete(&mdp_ppp_comp); + + /* set free */ + test_and_clear_bit(0, (unsigned long *)&mdp_ppp_busy_flag); + } +} diff --git a/drivers/staging/msm/mdp_ppp_dq.h b/drivers/staging/msm/mdp_ppp_dq.h new file mode 100644 index 000000000000..03e4e9a5f234 --- /dev/null +++ b/drivers/staging/msm/mdp_ppp_dq.h @@ -0,0 +1,86 @@ +/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MDP_PPP_DQ_H +#define MDP_PPP_DQ_H + +#include "msm_fb_def.h" + +#define MDP_PPP_DEBUG_MSG MSM_FB_DEBUG + +/* The maximum number of <Reg,Val> pairs in an mdp_ppp_roi_cmd_set structure (a + * node) + */ +#define MDP_PPP_ROI_NODE_SIZE 32 + +/* ROI config command (<Reg,Val> pair) for MDP PPP block */ +struct mdp_ppp_roi_cmd { + uint32_t reg; + uint32_t val; +}; + +/* ROI config commands for MDP PPP block are stored in a list of + * mdp_ppp_roi_cmd_set structures (nodes). + */ +struct mdp_ppp_roi_cmd_set { + struct list_head node; + uint32_t ncmds; /* number of commands in this set (node). */ + struct mdp_ppp_roi_cmd cmd[MDP_PPP_ROI_NODE_SIZE]; +}; + +/* MDP PPP Display Job (DJob) */ +struct mdp_ppp_djob { + struct list_head entry; + /* One ROI per MDP PPP DJob */ + struct list_head roi_cmd_list; + struct mdp_blit_req req; + struct fb_info *info; + struct delayed_work cleaner; + struct file *p_src_file, *p_dst_file; +}; + +extern struct completion mdp_ppp_comp; +extern boolean mdp_ppp_waiting; +extern unsigned long mdp_timer_duration; + +unsigned int mdp_ppp_async_op_get(void); +void mdp_ppp_async_op_set(unsigned int flag); +void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info, + struct mdp_blit_req *req_list, int req_list_count); +void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file); +void mdp_ppp_dq_init(void); +void mdp_ppp_outdw(uint32_t addr, uint32_t data); +struct mdp_ppp_djob *mdp_ppp_new_djob(void); +void mdp_ppp_clear_curr_djob(void); +void mdp_ppp_process_curr_djob(void); +int mdp_ppp_get_ret_code(void); +void mdp_ppp_djob_done(void); +void mdp_ppp_wait(void); + +#endif /* MDP_PPP_DQ_H */ diff --git a/drivers/staging/msm/mdp_ppp_v20.c b/drivers/staging/msm/mdp_ppp_v20.c new file mode 100644 index 000000000000..b5b7271921e0 --- /dev/null +++ b/drivers/staging/msm/mdp_ppp_v20.c @@ -0,0 +1,2486 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/fb.h> +#include "linux/proc_fs.h" + +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <asm/div64.h> + +#include "mdp.h" +#include "msm_fb.h" + +static MDP_SCALE_MODE mdp_curr_up_scale_xy; +static MDP_SCALE_MODE mdp_curr_down_scale_x; +static MDP_SCALE_MODE mdp_curr_down_scale_y; + +static long long mdp_do_div(long long num, long long den) +{ + do_div(num, den); + return num; +} + +struct mdp_table_entry mdp_gaussian_blur_table[] = { + /* max variance */ + { 0x5fffc, 0x20000080 }, + { 0x50280, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50284, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50288, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5028c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50290, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50294, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50298, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5029c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502a0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502a4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502a8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502ac, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502b0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502b4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502b8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502bc, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502c0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502c4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502c8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502cc, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502d0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502d4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502d8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502dc, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502e0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502e4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502e8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502ec, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502f0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502f4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502f8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502fc, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50300, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50304, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50308, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5030c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50310, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50314, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50318, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5031c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50320, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50324, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50328, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5032c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50330, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50334, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50338, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5033c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50340, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50344, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50348, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5034c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50350, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50354, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50358, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5035c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50360, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50364, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50368, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5036c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50370, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50374, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50378, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5037c, 0x20000080 }, +}; + +static void load_scale_table( + struct mdp_table_entry *table, int len) +{ + int i; + for (i = 0; i < len; i++) + MDP_OUTP(MDP_BASE + table[i].reg, table[i].val); +} + +static void mdp_load_pr_upscale_table(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50204, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50208, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5020c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50210, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50214, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50218, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5021c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50220, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50224, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50228, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5022c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50230, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50234, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50238, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5023c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50240, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50244, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50248, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5024c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50250, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50254, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50258, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5025c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50260, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50264, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50268, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5026c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50270, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50274, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50278, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5027c, 0x0); +} + +static void mdp_load_pr_downscale_table_x_point2TOpoint4(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502c0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502c4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502c8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502cc, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502d0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502d4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502d8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502dc, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502e0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502e4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502e8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502ec, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502f0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502f4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502f8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502fc, 0x0); +} + +static void mdp_load_pr_downscale_table_y_point2TOpoint4(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50340, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50344, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50348, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5034c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50350, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50354, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50358, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5035c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50360, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50364, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50368, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5036c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50370, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50374, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50378, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5037c, 0x0); +} + +static void mdp_load_pr_downscale_table_x_point4TOpoint6(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502c0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502c4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502c8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502cc, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502d0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502d4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502d8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502dc, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502e0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502e4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502e8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502ec, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502f0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502f4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502f8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502fc, 0x0); +} + +static void mdp_load_pr_downscale_table_y_point4TOpoint6(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50340, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50344, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50348, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5034c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50350, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50354, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50358, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5035c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50360, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50364, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50368, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5036c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50370, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50374, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50378, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5037c, 0x0); +} + +static void mdp_load_pr_downscale_table_x_point6TOpoint8(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502c0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502c4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502c8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502cc, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502d0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502d4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502d8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502dc, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502e0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502e4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502e8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502ec, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502f0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502f4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502f8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502fc, 0x0); +} + +static void mdp_load_pr_downscale_table_y_point6TOpoint8(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50340, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50344, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50348, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5034c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50350, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50354, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50358, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5035c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50360, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50364, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50368, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5036c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50370, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50374, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50378, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5037c, 0x0); +} + +static void mdp_load_pr_downscale_table_x_point8TO1(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502c0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502c4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502c8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502cc, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502d0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502d4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502d8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502dc, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502e0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502e4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502e8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502ec, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502f0, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502f4, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502f8, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x502fc, 0x0); +} + +static void mdp_load_pr_downscale_table_y_point8TO1(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50340, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50344, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50348, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5034c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50350, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50354, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50358, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5035c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50360, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50364, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50368, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5036c, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50370, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50374, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x50378, 0x0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); + MDP_OUTP(MDP_BASE + 0x5037c, 0x0); +} + +static void mdp_load_bc_upscale_table(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d); + MDP_OUTP(MDP_BASE + 0x50204, 0x7ec003f9); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c); + MDP_OUTP(MDP_BASE + 0x50208, 0x7d4003f3); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b); + MDP_OUTP(MDP_BASE + 0x5020c, 0x7b8003ed); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c); + MDP_OUTP(MDP_BASE + 0x50210, 0x794003e8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d); + MDP_OUTP(MDP_BASE + 0x50214, 0x76c003e4); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f); + MDP_OUTP(MDP_BASE + 0x50218, 0x73c003e0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071); + MDP_OUTP(MDP_BASE + 0x5021c, 0x708003de); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085); + MDP_OUTP(MDP_BASE + 0x50220, 0x6d0003db); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098); + MDP_OUTP(MDP_BASE + 0x50224, 0x698003d9); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac); + MDP_OUTP(MDP_BASE + 0x50228, 0x654003d8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1); + MDP_OUTP(MDP_BASE + 0x5022c, 0x610003d7); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5); + MDP_OUTP(MDP_BASE + 0x50230, 0x5c8003d7); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9); + MDP_OUTP(MDP_BASE + 0x50234, 0x580003d7); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd); + MDP_OUTP(MDP_BASE + 0x50238, 0x534003d8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112); + MDP_OUTP(MDP_BASE + 0x5023c, 0x4e8003d8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126); + MDP_OUTP(MDP_BASE + 0x50240, 0x494003da); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a); + MDP_OUTP(MDP_BASE + 0x50244, 0x448003db); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d); + MDP_OUTP(MDP_BASE + 0x50248, 0x3f4003dd); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160); + MDP_OUTP(MDP_BASE + 0x5024c, 0x3a4003df); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172); + MDP_OUTP(MDP_BASE + 0x50250, 0x354003e1); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184); + MDP_OUTP(MDP_BASE + 0x50254, 0x304003e3); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195); + MDP_OUTP(MDP_BASE + 0x50258, 0x2b0003e6); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6); + MDP_OUTP(MDP_BASE + 0x5025c, 0x260003e8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4); + MDP_OUTP(MDP_BASE + 0x50260, 0x214003eb); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2); + MDP_OUTP(MDP_BASE + 0x50264, 0x1c4003ee); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf); + MDP_OUTP(MDP_BASE + 0x50268, 0x17c003f1); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db); + MDP_OUTP(MDP_BASE + 0x5026c, 0x134003f3); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5); + MDP_OUTP(MDP_BASE + 0x50270, 0xf0003f6); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee); + MDP_OUTP(MDP_BASE + 0x50274, 0xac003f9); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5); + MDP_OUTP(MDP_BASE + 0x50278, 0x70003fb); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb); + MDP_OUTP(MDP_BASE + 0x5027c, 0x34003fe); +} + +static void mdp_load_bc_downscale_table_x_point2TOpoint4(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084); + MDP_OUTP(MDP_BASE + 0x50280, 0x23400083); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084); + MDP_OUTP(MDP_BASE + 0x50284, 0x23000083); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084); + MDP_OUTP(MDP_BASE + 0x50288, 0x23000082); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085); + MDP_OUTP(MDP_BASE + 0x5028c, 0x23000081); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085); + MDP_OUTP(MDP_BASE + 0x50290, 0x23000080); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086); + MDP_OUTP(MDP_BASE + 0x50294, 0x22c0007f); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086); + MDP_OUTP(MDP_BASE + 0x50298, 0x2280007f); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086); + MDP_OUTP(MDP_BASE + 0x5029c, 0x2280007e); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086); + MDP_OUTP(MDP_BASE + 0x502a0, 0x2280007d); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086); + MDP_OUTP(MDP_BASE + 0x502a4, 0x2240007d); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087); + MDP_OUTP(MDP_BASE + 0x502a8, 0x2240007c); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087); + MDP_OUTP(MDP_BASE + 0x502ac, 0x2240007b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087); + MDP_OUTP(MDP_BASE + 0x502b0, 0x2200007b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088); + MDP_OUTP(MDP_BASE + 0x502b4, 0x22400079); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088); + MDP_OUTP(MDP_BASE + 0x502b8, 0x22400078); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088); + MDP_OUTP(MDP_BASE + 0x502bc, 0x22400077); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089); + MDP_OUTP(MDP_BASE + 0x502c0, 0x22000077); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089); + MDP_OUTP(MDP_BASE + 0x502c4, 0x22000076); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089); + MDP_OUTP(MDP_BASE + 0x502c8, 0x22000075); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088); + MDP_OUTP(MDP_BASE + 0x502cc, 0x21c00075); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089); + MDP_OUTP(MDP_BASE + 0x502d0, 0x21c00074); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089); + MDP_OUTP(MDP_BASE + 0x502d4, 0x21c00073); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089); + MDP_OUTP(MDP_BASE + 0x502d8, 0x21800073); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a); + MDP_OUTP(MDP_BASE + 0x502dc, 0x21800072); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a); + MDP_OUTP(MDP_BASE + 0x502e0, 0x21800071); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a); + MDP_OUTP(MDP_BASE + 0x502e4, 0x21800070); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b); + MDP_OUTP(MDP_BASE + 0x502e8, 0x2180006f); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c); + MDP_OUTP(MDP_BASE + 0x502ec, 0x2140006e); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c); + MDP_OUTP(MDP_BASE + 0x502f0, 0x2140006d); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c); + MDP_OUTP(MDP_BASE + 0x502f4, 0x2100006d); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c); + MDP_OUTP(MDP_BASE + 0x502f8, 0x2100006c); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d); + MDP_OUTP(MDP_BASE + 0x502fc, 0x2100006b); +} + +static void mdp_load_bc_downscale_table_y_point2TOpoint4(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084); + MDP_OUTP(MDP_BASE + 0x50300, 0x23400083); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084); + MDP_OUTP(MDP_BASE + 0x50304, 0x23000083); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084); + MDP_OUTP(MDP_BASE + 0x50308, 0x23000082); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085); + MDP_OUTP(MDP_BASE + 0x5030c, 0x23000081); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085); + MDP_OUTP(MDP_BASE + 0x50310, 0x23000080); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086); + MDP_OUTP(MDP_BASE + 0x50314, 0x22c0007f); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086); + MDP_OUTP(MDP_BASE + 0x50318, 0x2280007f); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086); + MDP_OUTP(MDP_BASE + 0x5031c, 0x2280007e); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086); + MDP_OUTP(MDP_BASE + 0x50320, 0x2280007d); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086); + MDP_OUTP(MDP_BASE + 0x50324, 0x2240007d); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087); + MDP_OUTP(MDP_BASE + 0x50328, 0x2240007c); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087); + MDP_OUTP(MDP_BASE + 0x5032c, 0x2240007b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087); + MDP_OUTP(MDP_BASE + 0x50330, 0x2200007b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088); + MDP_OUTP(MDP_BASE + 0x50334, 0x22400079); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088); + MDP_OUTP(MDP_BASE + 0x50338, 0x22400078); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088); + MDP_OUTP(MDP_BASE + 0x5033c, 0x22400077); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089); + MDP_OUTP(MDP_BASE + 0x50340, 0x22000077); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089); + MDP_OUTP(MDP_BASE + 0x50344, 0x22000076); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089); + MDP_OUTP(MDP_BASE + 0x50348, 0x22000075); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088); + MDP_OUTP(MDP_BASE + 0x5034c, 0x21c00075); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089); + MDP_OUTP(MDP_BASE + 0x50350, 0x21c00074); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089); + MDP_OUTP(MDP_BASE + 0x50354, 0x21c00073); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089); + MDP_OUTP(MDP_BASE + 0x50358, 0x21800073); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a); + MDP_OUTP(MDP_BASE + 0x5035c, 0x21800072); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a); + MDP_OUTP(MDP_BASE + 0x50360, 0x21800071); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a); + MDP_OUTP(MDP_BASE + 0x50364, 0x21800070); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b); + MDP_OUTP(MDP_BASE + 0x50368, 0x2180006f); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c); + MDP_OUTP(MDP_BASE + 0x5036c, 0x2140006e); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c); + MDP_OUTP(MDP_BASE + 0x50370, 0x2140006d); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c); + MDP_OUTP(MDP_BASE + 0x50374, 0x2100006d); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c); + MDP_OUTP(MDP_BASE + 0x50378, 0x2100006c); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d); + MDP_OUTP(MDP_BASE + 0x5037c, 0x2100006b); +} + +static void mdp_load_bc_downscale_table_x_point4TOpoint6(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c); + MDP_OUTP(MDP_BASE + 0x50280, 0x33800088); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e); + MDP_OUTP(MDP_BASE + 0x50284, 0x33400084); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092); + MDP_OUTP(MDP_BASE + 0x50288, 0x33000080); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094); + MDP_OUTP(MDP_BASE + 0x5028c, 0x3300007b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098); + MDP_OUTP(MDP_BASE + 0x50290, 0x32400077); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b); + MDP_OUTP(MDP_BASE + 0x50294, 0x32000073); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d); + MDP_OUTP(MDP_BASE + 0x50298, 0x31c0006f); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0); + MDP_OUTP(MDP_BASE + 0x5029c, 0x3140006b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2); + MDP_OUTP(MDP_BASE + 0x502a0, 0x31000067); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5); + MDP_OUTP(MDP_BASE + 0x502a4, 0x30800062); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8); + MDP_OUTP(MDP_BASE + 0x502a8, 0x2fc0005f); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa); + MDP_OUTP(MDP_BASE + 0x502ac, 0x2fc0005b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad); + MDP_OUTP(MDP_BASE + 0x502b0, 0x2f400057); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0); + MDP_OUTP(MDP_BASE + 0x502b4, 0x2e400054); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2); + MDP_OUTP(MDP_BASE + 0x502b8, 0x2e000050); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4); + MDP_OUTP(MDP_BASE + 0x502bc, 0x2d80004c); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6); + MDP_OUTP(MDP_BASE + 0x502c0, 0x2d000049); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8); + MDP_OUTP(MDP_BASE + 0x502c4, 0x2c800045); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9); + MDP_OUTP(MDP_BASE + 0x502c8, 0x2c000042); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd); + MDP_OUTP(MDP_BASE + 0x502cc, 0x2b40003e); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf); + MDP_OUTP(MDP_BASE + 0x502d0, 0x2a80003b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf); + MDP_OUTP(MDP_BASE + 0x502d4, 0x2a000039); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2); + MDP_OUTP(MDP_BASE + 0x502d8, 0x29400036); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4); + MDP_OUTP(MDP_BASE + 0x502dc, 0x28800032); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5); + MDP_OUTP(MDP_BASE + 0x502e0, 0x2800002f); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7); + MDP_OUTP(MDP_BASE + 0x502e4, 0x2740002c); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8); + MDP_OUTP(MDP_BASE + 0x502e8, 0x26c00029); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9); + MDP_OUTP(MDP_BASE + 0x502ec, 0x26000027); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc); + MDP_OUTP(MDP_BASE + 0x502f0, 0x25000024); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc); + MDP_OUTP(MDP_BASE + 0x502f4, 0x24800021); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd); + MDP_OUTP(MDP_BASE + 0x502f8, 0x23800020); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce); + MDP_OUTP(MDP_BASE + 0x502fc, 0x2300001d); +} + +static void mdp_load_bc_downscale_table_y_point4TOpoint6(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c); + MDP_OUTP(MDP_BASE + 0x50300, 0x33800088); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e); + MDP_OUTP(MDP_BASE + 0x50304, 0x33400084); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092); + MDP_OUTP(MDP_BASE + 0x50308, 0x33000080); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094); + MDP_OUTP(MDP_BASE + 0x5030c, 0x3300007b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098); + MDP_OUTP(MDP_BASE + 0x50310, 0x32400077); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b); + MDP_OUTP(MDP_BASE + 0x50314, 0x32000073); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d); + MDP_OUTP(MDP_BASE + 0x50318, 0x31c0006f); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0); + MDP_OUTP(MDP_BASE + 0x5031c, 0x3140006b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2); + MDP_OUTP(MDP_BASE + 0x50320, 0x31000067); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5); + MDP_OUTP(MDP_BASE + 0x50324, 0x30800062); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8); + MDP_OUTP(MDP_BASE + 0x50328, 0x2fc0005f); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa); + MDP_OUTP(MDP_BASE + 0x5032c, 0x2fc0005b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad); + MDP_OUTP(MDP_BASE + 0x50330, 0x2f400057); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0); + MDP_OUTP(MDP_BASE + 0x50334, 0x2e400054); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2); + MDP_OUTP(MDP_BASE + 0x50338, 0x2e000050); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4); + MDP_OUTP(MDP_BASE + 0x5033c, 0x2d80004c); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6); + MDP_OUTP(MDP_BASE + 0x50340, 0x2d000049); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8); + MDP_OUTP(MDP_BASE + 0x50344, 0x2c800045); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9); + MDP_OUTP(MDP_BASE + 0x50348, 0x2c000042); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd); + MDP_OUTP(MDP_BASE + 0x5034c, 0x2b40003e); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf); + MDP_OUTP(MDP_BASE + 0x50350, 0x2a80003b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf); + MDP_OUTP(MDP_BASE + 0x50354, 0x2a000039); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2); + MDP_OUTP(MDP_BASE + 0x50358, 0x29400036); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4); + MDP_OUTP(MDP_BASE + 0x5035c, 0x28800032); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5); + MDP_OUTP(MDP_BASE + 0x50360, 0x2800002f); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7); + MDP_OUTP(MDP_BASE + 0x50364, 0x2740002c); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8); + MDP_OUTP(MDP_BASE + 0x50368, 0x26c00029); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9); + MDP_OUTP(MDP_BASE + 0x5036c, 0x26000027); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc); + MDP_OUTP(MDP_BASE + 0x50370, 0x25000024); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc); + MDP_OUTP(MDP_BASE + 0x50374, 0x24800021); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd); + MDP_OUTP(MDP_BASE + 0x50378, 0x23800020); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce); + MDP_OUTP(MDP_BASE + 0x5037c, 0x2300001d); +} + +static void mdp_load_bc_downscale_table_x_point6TOpoint8(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070); + MDP_OUTP(MDP_BASE + 0x50280, 0x4bc00068); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078); + MDP_OUTP(MDP_BASE + 0x50284, 0x4bc00060); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080); + MDP_OUTP(MDP_BASE + 0x50288, 0x4b800059); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089); + MDP_OUTP(MDP_BASE + 0x5028c, 0x4b000052); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091); + MDP_OUTP(MDP_BASE + 0x50290, 0x4a80004b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a); + MDP_OUTP(MDP_BASE + 0x50294, 0x4a000044); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3); + MDP_OUTP(MDP_BASE + 0x50298, 0x4940003d); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac); + MDP_OUTP(MDP_BASE + 0x5029c, 0x48400037); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4); + MDP_OUTP(MDP_BASE + 0x502a0, 0x47800031); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd); + MDP_OUTP(MDP_BASE + 0x502a4, 0x4640002b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5); + MDP_OUTP(MDP_BASE + 0x502a8, 0x45000026); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce); + MDP_OUTP(MDP_BASE + 0x502ac, 0x43800021); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6); + MDP_OUTP(MDP_BASE + 0x502b0, 0x4240001c); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df); + MDP_OUTP(MDP_BASE + 0x502b4, 0x40800018); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6); + MDP_OUTP(MDP_BASE + 0x502b8, 0x3f000014); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee); + MDP_OUTP(MDP_BASE + 0x502bc, 0x3d400010); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5); + MDP_OUTP(MDP_BASE + 0x502c0, 0x3b80000c); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc); + MDP_OUTP(MDP_BASE + 0x502c4, 0x39800009); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102); + MDP_OUTP(MDP_BASE + 0x502c8, 0x37c00006); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109); + MDP_OUTP(MDP_BASE + 0x502cc, 0x35800004); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e); + MDP_OUTP(MDP_BASE + 0x502d0, 0x33800002); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114); + MDP_OUTP(MDP_BASE + 0x502d4, 0x31400000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119); + MDP_OUTP(MDP_BASE + 0x502d8, 0x2f4003fe); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e); + MDP_OUTP(MDP_BASE + 0x502dc, 0x2d0003fc); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121); + MDP_OUTP(MDP_BASE + 0x502e0, 0x2b0003fb); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125); + MDP_OUTP(MDP_BASE + 0x502e4, 0x28c003fa); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128); + MDP_OUTP(MDP_BASE + 0x502e8, 0x268003f9); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a); + MDP_OUTP(MDP_BASE + 0x502ec, 0x244003f9); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c); + MDP_OUTP(MDP_BASE + 0x502f0, 0x224003f8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e); + MDP_OUTP(MDP_BASE + 0x502f4, 0x200003f8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f); + MDP_OUTP(MDP_BASE + 0x502f8, 0x1e0003f8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f); + MDP_OUTP(MDP_BASE + 0x502fc, 0x1c0003f8); +} + +static void mdp_load_bc_downscale_table_y_point6TOpoint8(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070); + MDP_OUTP(MDP_BASE + 0x50300, 0x4bc00068); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078); + MDP_OUTP(MDP_BASE + 0x50304, 0x4bc00060); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080); + MDP_OUTP(MDP_BASE + 0x50308, 0x4b800059); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089); + MDP_OUTP(MDP_BASE + 0x5030c, 0x4b000052); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091); + MDP_OUTP(MDP_BASE + 0x50310, 0x4a80004b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a); + MDP_OUTP(MDP_BASE + 0x50314, 0x4a000044); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3); + MDP_OUTP(MDP_BASE + 0x50318, 0x4940003d); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac); + MDP_OUTP(MDP_BASE + 0x5031c, 0x48400037); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4); + MDP_OUTP(MDP_BASE + 0x50320, 0x47800031); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd); + MDP_OUTP(MDP_BASE + 0x50324, 0x4640002b); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5); + MDP_OUTP(MDP_BASE + 0x50328, 0x45000026); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce); + MDP_OUTP(MDP_BASE + 0x5032c, 0x43800021); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6); + MDP_OUTP(MDP_BASE + 0x50330, 0x4240001c); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df); + MDP_OUTP(MDP_BASE + 0x50334, 0x40800018); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6); + MDP_OUTP(MDP_BASE + 0x50338, 0x3f000014); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee); + MDP_OUTP(MDP_BASE + 0x5033c, 0x3d400010); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5); + MDP_OUTP(MDP_BASE + 0x50340, 0x3b80000c); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc); + MDP_OUTP(MDP_BASE + 0x50344, 0x39800009); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102); + MDP_OUTP(MDP_BASE + 0x50348, 0x37c00006); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109); + MDP_OUTP(MDP_BASE + 0x5034c, 0x35800004); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e); + MDP_OUTP(MDP_BASE + 0x50350, 0x33800002); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114); + MDP_OUTP(MDP_BASE + 0x50354, 0x31400000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119); + MDP_OUTP(MDP_BASE + 0x50358, 0x2f4003fe); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e); + MDP_OUTP(MDP_BASE + 0x5035c, 0x2d0003fc); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121); + MDP_OUTP(MDP_BASE + 0x50360, 0x2b0003fb); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125); + MDP_OUTP(MDP_BASE + 0x50364, 0x28c003fa); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128); + MDP_OUTP(MDP_BASE + 0x50368, 0x268003f9); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a); + MDP_OUTP(MDP_BASE + 0x5036c, 0x244003f9); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c); + MDP_OUTP(MDP_BASE + 0x50370, 0x224003f8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e); + MDP_OUTP(MDP_BASE + 0x50374, 0x200003f8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f); + MDP_OUTP(MDP_BASE + 0x50378, 0x1e0003f8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f); + MDP_OUTP(MDP_BASE + 0x5037c, 0x1c0003f8); +} + +static void mdp_load_bc_downscale_table_x_point8TO1(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d); + MDP_OUTP(MDP_BASE + 0x50284, 0x7ec003f9); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c); + MDP_OUTP(MDP_BASE + 0x50288, 0x7d4003f3); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b); + MDP_OUTP(MDP_BASE + 0x5028c, 0x7b8003ed); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c); + MDP_OUTP(MDP_BASE + 0x50290, 0x794003e8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d); + MDP_OUTP(MDP_BASE + 0x50294, 0x76c003e4); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f); + MDP_OUTP(MDP_BASE + 0x50298, 0x73c003e0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071); + MDP_OUTP(MDP_BASE + 0x5029c, 0x708003de); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085); + MDP_OUTP(MDP_BASE + 0x502a0, 0x6d0003db); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098); + MDP_OUTP(MDP_BASE + 0x502a4, 0x698003d9); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac); + MDP_OUTP(MDP_BASE + 0x502a8, 0x654003d8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1); + MDP_OUTP(MDP_BASE + 0x502ac, 0x610003d7); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5); + MDP_OUTP(MDP_BASE + 0x502b0, 0x5c8003d7); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9); + MDP_OUTP(MDP_BASE + 0x502b4, 0x580003d7); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd); + MDP_OUTP(MDP_BASE + 0x502b8, 0x534003d8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112); + MDP_OUTP(MDP_BASE + 0x502bc, 0x4e8003d8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126); + MDP_OUTP(MDP_BASE + 0x502c0, 0x494003da); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a); + MDP_OUTP(MDP_BASE + 0x502c4, 0x448003db); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d); + MDP_OUTP(MDP_BASE + 0x502c8, 0x3f4003dd); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160); + MDP_OUTP(MDP_BASE + 0x502cc, 0x3a4003df); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172); + MDP_OUTP(MDP_BASE + 0x502d0, 0x354003e1); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184); + MDP_OUTP(MDP_BASE + 0x502d4, 0x304003e3); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195); + MDP_OUTP(MDP_BASE + 0x502d8, 0x2b0003e6); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6); + MDP_OUTP(MDP_BASE + 0x502dc, 0x260003e8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4); + MDP_OUTP(MDP_BASE + 0x502e0, 0x214003eb); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2); + MDP_OUTP(MDP_BASE + 0x502e4, 0x1c4003ee); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf); + MDP_OUTP(MDP_BASE + 0x502e8, 0x17c003f1); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db); + MDP_OUTP(MDP_BASE + 0x502ec, 0x134003f3); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5); + MDP_OUTP(MDP_BASE + 0x502f0, 0xf0003f6); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee); + MDP_OUTP(MDP_BASE + 0x502f4, 0xac003f9); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5); + MDP_OUTP(MDP_BASE + 0x502f8, 0x70003fb); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb); + MDP_OUTP(MDP_BASE + 0x502fc, 0x34003fe); +} + +static void mdp_load_bc_downscale_table_y_point8TO1(void) +{ + MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); + MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d); + MDP_OUTP(MDP_BASE + 0x50304, 0x7ec003f9); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c); + MDP_OUTP(MDP_BASE + 0x50308, 0x7d4003f3); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b); + MDP_OUTP(MDP_BASE + 0x5030c, 0x7b8003ed); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c); + MDP_OUTP(MDP_BASE + 0x50310, 0x794003e8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d); + MDP_OUTP(MDP_BASE + 0x50314, 0x76c003e4); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f); + MDP_OUTP(MDP_BASE + 0x50318, 0x73c003e0); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071); + MDP_OUTP(MDP_BASE + 0x5031c, 0x708003de); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085); + MDP_OUTP(MDP_BASE + 0x50320, 0x6d0003db); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098); + MDP_OUTP(MDP_BASE + 0x50324, 0x698003d9); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac); + MDP_OUTP(MDP_BASE + 0x50328, 0x654003d8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1); + MDP_OUTP(MDP_BASE + 0x5032c, 0x610003d7); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5); + MDP_OUTP(MDP_BASE + 0x50330, 0x5c8003d7); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9); + MDP_OUTP(MDP_BASE + 0x50334, 0x580003d7); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd); + MDP_OUTP(MDP_BASE + 0x50338, 0x534003d8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112); + MDP_OUTP(MDP_BASE + 0x5033c, 0x4e8003d8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126); + MDP_OUTP(MDP_BASE + 0x50340, 0x494003da); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a); + MDP_OUTP(MDP_BASE + 0x50344, 0x448003db); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d); + MDP_OUTP(MDP_BASE + 0x50348, 0x3f4003dd); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160); + MDP_OUTP(MDP_BASE + 0x5034c, 0x3a4003df); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172); + MDP_OUTP(MDP_BASE + 0x50350, 0x354003e1); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184); + MDP_OUTP(MDP_BASE + 0x50354, 0x304003e3); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195); + MDP_OUTP(MDP_BASE + 0x50358, 0x2b0003e6); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6); + MDP_OUTP(MDP_BASE + 0x5035c, 0x260003e8); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4); + MDP_OUTP(MDP_BASE + 0x50360, 0x214003eb); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2); + MDP_OUTP(MDP_BASE + 0x50364, 0x1c4003ee); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf); + MDP_OUTP(MDP_BASE + 0x50368, 0x17c003f1); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db); + MDP_OUTP(MDP_BASE + 0x5036c, 0x134003f3); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5); + MDP_OUTP(MDP_BASE + 0x50370, 0xf0003f6); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee); + MDP_OUTP(MDP_BASE + 0x50374, 0xac003f9); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5); + MDP_OUTP(MDP_BASE + 0x50378, 0x70003fb); + MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb); + MDP_OUTP(MDP_BASE + 0x5037c, 0x34003fe); +} + +static int mdp_get_edge_cond(MDPIBUF *iBuf, uint32 *dup, uint32 *dup2) +{ + uint32 reg; + uint32 dst_roi_width; /* Dimensions of DST ROI. */ + uint32 dst_roi_height; /* Used to calculate scaling ratios. */ + + /* + * positions of the luma pixel(relative to the image ) required for + * scaling the ROI + */ + int32 luma_interp_point_left = 0; /* left-most luma pixel needed */ + int32 luma_interp_point_right = 0; /* right-most luma pixel needed */ + int32 luma_interp_point_top = 0; /* top-most luma pixel needed */ + int32 luma_interp_point_bottom = 0; /* bottom-most luma pixel needed */ + + /* + * positions of the chroma pixel(relative to the image ) required for + * interpolating a chroma value at all required luma positions + */ + /* left-most chroma pixel needed */ + int32 chroma_interp_point_left = 0; + /* right-most chroma pixel needed */ + int32 chroma_interp_point_right = 0; + /* top-most chroma pixel needed */ + int32 chroma_interp_point_top = 0; + /* bottom-most chroma pixel needed */ + int32 chroma_interp_point_bottom = 0; + + /* + * a rectangular region within the chroma plane of the "image". + * Chroma pixels falling inside of this rectangle belongs to the ROI + */ + int32 chroma_bound_left = 0; + int32 chroma_bound_right = 0; + int32 chroma_bound_top = 0; + int32 chroma_bound_bottom = 0; + + /* + * number of chroma pixels to replicate on the left, right, + * top and bottom edge of the ROI. + */ + int32 chroma_repeat_left = 0; + int32 chroma_repeat_right = 0; + int32 chroma_repeat_top = 0; + int32 chroma_repeat_bottom = 0; + + /* + * number of luma pixels to replicate on the left, right, + * top and bottom edge of the ROI. + */ + int32 luma_repeat_left = 0; + int32 luma_repeat_right = 0; + int32 luma_repeat_top = 0; + int32 luma_repeat_bottom = 0; + + boolean chroma_edge_enable; + + uint32 _is_scale_enabled = 0; + uint32 _is_yuv_offsite_vertical = 0; + + /* fg edge duplicate */ + reg = 0x0; + + if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) { /* if scaling enabled */ + + _is_scale_enabled = 1; + + /* + * if rotation mode involves a 90 deg rotation, flip + * dst_roi_width with dst_roi_height. + * Scaling ratios is based on source ROI dimensions, and + * dst ROI dimensions before rotation. + */ + if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) { + dst_roi_width = iBuf->roi.dst_height; + dst_roi_height = iBuf->roi.dst_width; + } else { + dst_roi_width = iBuf->roi.dst_width; + dst_roi_height = iBuf->roi.dst_height; + } + + /* + * Find out the luma pixels needed for scaling in the + * x direction (LEFT and RIGHT). Locations of pixels are + * relative to the ROI. Upper-left corner of ROI corresponds + * to coordinates (0,0). Also set the number of luma pixel + * to repeat. + */ + if (iBuf->roi.width > 3 * dst_roi_width) { + /* scale factor < 1/3 */ + luma_interp_point_left = 0; + luma_interp_point_right = (iBuf->roi.width - 1); + luma_repeat_left = 0; + luma_repeat_right = 0; + } else if (iBuf->roi.width == 3 * dst_roi_width) { + /* scale factor == 1/3 */ + luma_interp_point_left = 0; + luma_interp_point_right = (iBuf->roi.width - 1) + 1; + luma_repeat_left = 0; + luma_repeat_right = 1; + } else if ((iBuf->roi.width > dst_roi_width) && + (iBuf->roi.width < 3 * dst_roi_width)) { + /* 1/3 < scale factor < 1 */ + luma_interp_point_left = -1; + luma_interp_point_right = (iBuf->roi.width - 1) + 1; + luma_repeat_left = 1; + luma_repeat_right = 1; + } + + else if (iBuf->roi.width == dst_roi_width) { + /* scale factor == 1 */ + luma_interp_point_left = -1; + luma_interp_point_right = (iBuf->roi.width - 1) + 2; + luma_repeat_left = 1; + luma_repeat_right = 2; + } else { /* (iBuf->roi.width < dst_roi_width) */ + /* scale factor > 1 */ + luma_interp_point_left = -2; + luma_interp_point_right = (iBuf->roi.width - 1) + 2; + luma_repeat_left = 2; + luma_repeat_right = 2; + } + + /* + * Find out the number of pixels needed for scaling in the + * y direction (TOP and BOTTOM). Locations of pixels are + * relative to the ROI. Upper-left corner of ROI corresponds + * to coordinates (0,0). Also set the number of luma pixel + * to repeat. + */ + if (iBuf->roi.height > 3 * dst_roi_height) { + /* scale factor < 1/3 */ + luma_interp_point_top = 0; + luma_interp_point_bottom = (iBuf->roi.height - 1); + luma_repeat_top = 0; + luma_repeat_bottom = 0; + } else if (iBuf->roi.height == 3 * dst_roi_height) { + /* scale factor == 1/3 */ + luma_interp_point_top = 0; + luma_interp_point_bottom = (iBuf->roi.height - 1) + 1; + luma_repeat_top = 0; + luma_repeat_bottom = 1; + } else if ((iBuf->roi.height > dst_roi_height) && + (iBuf->roi.height < 3 * dst_roi_height)) { + /* 1/3 < scale factor < 1 */ + luma_interp_point_top = -1; + luma_interp_point_bottom = (iBuf->roi.height - 1) + 1; + luma_repeat_top = 1; + luma_repeat_bottom = 1; + } else if (iBuf->roi.height == dst_roi_height) { + /* scale factor == 1 */ + luma_interp_point_top = -1; + luma_interp_point_bottom = (iBuf->roi.height - 1) + 2; + luma_repeat_top = 1; + luma_repeat_bottom = 2; + } else { /* (iBuf->roi.height < dst_roi_height) */ + /* scale factor > 1 */ + luma_interp_point_top = -2; + luma_interp_point_bottom = (iBuf->roi.height - 1) + 2; + luma_repeat_top = 2; + luma_repeat_bottom = 2; + } + } /* if (iBuf->scale.scale_flag) */ + else { /* scaling disabled */ + /* + * Since no scaling needed, Tile Fetch does not require any + * more luma pixel than what the ROI contains. + */ + luma_interp_point_left = (int32) 0; + luma_interp_point_right = (int32) (iBuf->roi.width - 1); + luma_interp_point_top = (int32) 0; + luma_interp_point_bottom = (int32) (iBuf->roi.height - 1); + + luma_repeat_left = 0; + luma_repeat_right = 0; + luma_repeat_top = 0; + luma_repeat_bottom = 0; + } + + /* After adding the ROI offsets, we have locations of + * luma_interp_points relative to the image. + */ + luma_interp_point_left += (int32) (iBuf->roi.x); + luma_interp_point_right += (int32) (iBuf->roi.x); + luma_interp_point_top += (int32) (iBuf->roi.y); + luma_interp_point_bottom += (int32) (iBuf->roi.y); + + /* + * After adding the ROI offsets, we have locations of + * chroma_interp_points relative to the image. + */ + chroma_interp_point_left = luma_interp_point_left; + chroma_interp_point_right = luma_interp_point_right; + chroma_interp_point_top = luma_interp_point_top; + chroma_interp_point_bottom = luma_interp_point_bottom; + + chroma_edge_enable = TRUE; + /* find out which chroma pixels are needed for chroma upsampling. */ + switch (iBuf->mdpImg.imgType) { + /* + * cosite in horizontal axis + * fully sampled in vertical axis + */ + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V1: + case MDP_YCRYCB_H2V1: + /* floor( luma_interp_point_left / 2 ); */ + chroma_interp_point_left = luma_interp_point_left >> 1; + /* floor( ( luma_interp_point_right + 1 ) / 2 ); */ + chroma_interp_point_right = (luma_interp_point_right + 1) >> 1; + + chroma_interp_point_top = luma_interp_point_top; + chroma_interp_point_bottom = luma_interp_point_bottom; + break; + + /* + * cosite in horizontal axis + * offsite in vertical axis + */ + case MDP_Y_CBCR_H2V2: + case MDP_Y_CRCB_H2V2: + /* floor( luma_interp_point_left / 2) */ + chroma_interp_point_left = luma_interp_point_left >> 1; + + /* floor( ( luma_interp_point_right + 1 )/ 2 ) */ + chroma_interp_point_right = (luma_interp_point_right + 1) >> 1; + + /* floor( (luma_interp_point_top - 1 ) / 2 ) */ + chroma_interp_point_top = (luma_interp_point_top - 1) >> 1; + + /* floor( ( luma_interp_point_bottom + 1 ) / 2 ) */ + chroma_interp_point_bottom = + (luma_interp_point_bottom + 1) >> 1; + + _is_yuv_offsite_vertical = 1; + break; + + default: + chroma_edge_enable = FALSE; + chroma_interp_point_left = luma_interp_point_left; + chroma_interp_point_right = luma_interp_point_right; + chroma_interp_point_top = luma_interp_point_top; + chroma_interp_point_bottom = luma_interp_point_bottom; + + break; + } + + /* only if the image type is in YUV domain, we calculate chroma edge */ + if (chroma_edge_enable) { + /* Defines which chroma pixels belongs to the roi */ + switch (iBuf->mdpImg.imgType) { + /* + * Cosite in horizontal direction, and fully sampled + * in vertical direction. + */ + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V1: + case MDP_YCRYCB_H2V1: + /* + * width of chroma ROI is 1/2 of size of luma ROI + * height of chroma ROI same as size of luma ROI + */ + chroma_bound_left = iBuf->roi.x / 2; + + /* there are half as many chroma pixel as luma pixels */ + chroma_bound_right = + (iBuf->roi.width + iBuf->roi.x - 1) / 2; + chroma_bound_top = iBuf->roi.y; + chroma_bound_bottom = + (iBuf->roi.height + iBuf->roi.y - 1); + break; + + case MDP_Y_CBCR_H2V2: + case MDP_Y_CRCB_H2V2: + /* + * cosite in horizontal dir, and offsite in vertical dir + * width of chroma ROI is 1/2 of size of luma ROI + * height of chroma ROI is 1/2 of size of luma ROI + */ + + chroma_bound_left = iBuf->roi.x / 2; + chroma_bound_right = + (iBuf->roi.width + iBuf->roi.x - 1) / 2; + chroma_bound_top = iBuf->roi.y / 2; + chroma_bound_bottom = + (iBuf->roi.height + iBuf->roi.y - 1) / 2; + break; + + default: + /* + * If no valid chroma sub-sampling format specified, + * assume 4:4:4 ( i.e. fully sampled). Set ROI + * boundaries for chroma same as ROI boundaries for + * luma. + */ + chroma_bound_left = iBuf->roi.x; + chroma_bound_right = iBuf->roi.width + iBuf->roi.x - 1; + chroma_bound_top = iBuf->roi.y; + chroma_bound_bottom = + (iBuf->roi.height + iBuf->roi.y - 1); + break; + } + + /* + * Knowing which chroma pixels are needed, and which chroma + * pixels belong to the ROI (i.e. available for fetching ), + * calculate how many chroma pixels Tile Fetch needs to + * duplicate. If any required chroma pixels falls outside + * of the ROI, Tile Fetch must obtain them by replicating + * pixels. + */ + if (chroma_bound_left > chroma_interp_point_left) + chroma_repeat_left = + chroma_bound_left - chroma_interp_point_left; + else + chroma_repeat_left = 0; + + if (chroma_interp_point_right > chroma_bound_right) + chroma_repeat_right = + chroma_interp_point_right - chroma_bound_right; + else + chroma_repeat_right = 0; + + if (chroma_bound_top > chroma_interp_point_top) + chroma_repeat_top = + chroma_bound_top - chroma_interp_point_top; + else + chroma_repeat_top = 0; + + if (chroma_interp_point_bottom > chroma_bound_bottom) + chroma_repeat_bottom = + chroma_interp_point_bottom - chroma_bound_bottom; + else + chroma_repeat_bottom = 0; + + if (_is_scale_enabled && (iBuf->roi.height == 1) + && _is_yuv_offsite_vertical) { + chroma_repeat_bottom = 3; + chroma_repeat_top = 0; + } + } + /* make sure chroma repeats are non-negative */ + if ((chroma_repeat_left < 0) || (chroma_repeat_right < 0) || + (chroma_repeat_top < 0) || (chroma_repeat_bottom < 0)) + return -1; + + /* make sure chroma repeats are no larger than 3 pixels */ + if ((chroma_repeat_left > 3) || (chroma_repeat_right > 3) || + (chroma_repeat_top > 3) || (chroma_repeat_bottom > 3)) + return -1; + + /* make sure luma repeats are non-negative */ + if ((luma_repeat_left < 0) || (luma_repeat_right < 0) || + (luma_repeat_top < 0) || (luma_repeat_bottom < 0)) + return -1; + + /* make sure luma repeats are no larger than 3 pixels */ + if ((luma_repeat_left > 3) || (luma_repeat_right > 3) || + (luma_repeat_top > 3) || (luma_repeat_bottom > 3)) + return -1; + + /* write chroma_repeat_left to register */ + reg |= (chroma_repeat_left & 3) << MDP_LEFT_CHROMA; + + /* write chroma_repeat_right to register */ + reg |= (chroma_repeat_right & 3) << MDP_RIGHT_CHROMA; + + /* write chroma_repeat_top to register */ + reg |= (chroma_repeat_top & 3) << MDP_TOP_CHROMA; + + /* write chroma_repeat_bottom to register */ + reg |= (chroma_repeat_bottom & 3) << MDP_BOTTOM_CHROMA; + + /* write luma_repeat_left to register */ + reg |= (luma_repeat_left & 3) << MDP_LEFT_LUMA; + + /* write luma_repeat_right to register */ + reg |= (luma_repeat_right & 3) << MDP_RIGHT_LUMA; + + /* write luma_repeat_top to register */ + reg |= (luma_repeat_top & 3) << MDP_TOP_LUMA; + + /* write luma_repeat_bottom to register */ + reg |= (luma_repeat_bottom & 3) << MDP_BOTTOM_LUMA; + + /* done with reg */ + *dup = reg; + + /* bg edge duplicate */ + reg = 0x0; + + switch (iBuf->ibuf_type) { + case MDP_Y_CBCR_H2V2: + case MDP_Y_CRCB_H2V2: + /* + * Edge condition for MDP_Y_CRCB/CBCR_H2V2 cosite only. + * For 420 cosite, 1 chroma replicated on all sides except + * left, so reg 101b8 should be 0x0209. For 420 offsite, + * 1 chroma replicated all sides. + */ + if (iBuf->roi.lcd_y == 0) { + reg |= BIT(MDP_TOP_CHROMA); + } + + if ((iBuf->roi.lcd_y + iBuf->roi.dst_height) == + iBuf->ibuf_height) { + reg |= BIT(MDP_BOTTOM_CHROMA); + } + + if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) == + iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) { + reg |= BIT(MDP_RIGHT_CHROMA); + } + + break; + + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V1: + case MDP_YCRYCB_H2V1: + if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) == + iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) { + reg |= BIT(MDP_RIGHT_CHROMA); + } + break; + default: + break; + } + + *dup2 = reg; + + return 0; +} + +#define ADJUST_IP /* for 1/3 scale factor fix */ + +static int mdp_calc_scale_params( +/* ROI origin coordinate for the dimension */ + uint32 org, +/* src ROI dimension */ + uint32 dim_in, +/* scaled ROI dimension*/ + uint32 dim_out, +/* is this ROI width dimension? */ + boolean is_W, +/* initial phase location address */ + int32 *phase_init_ptr, +/* phase increment location address */ + uint32 *phase_step_ptr, +/* ROI start over-fetch location address */ + uint32 *num_repl_beg_ptr, +/* ROI end over-fetch location address */ + uint32 *num_repl_end_ptr) +{ + boolean rpa_on = FALSE; + int init_phase = 0; + uint32 beg_of = 0; + uint32 end_of = 0; + uint64 numer = 0; + uint64 denom = 0; + /*uint64 inverter = 1; */ + int64 point5 = 1; + int64 one = 1; + int64 k1, k2, k3, k4; /* linear equation coefficients */ + uint64 int_mask; + uint64 fract_mask; + uint64 Os; + int64 Osprime; + int64 Od; + int64 Odprime; + int64 Oreq; + uint64 Es; + uint64 Ed; + uint64 Ereq; +#ifdef ADJUST_IP + int64 IP64; + int64 delta; +#endif + uint32 mult; + + /* + * The phase accumulator should really be rational for all cases in a + * general purpose polyphase scaler for a tiled architecture with + * non-zero * origin capability because there is no way to represent + * certain scale factors in fixed point regardless of precision. + * The error incurred in attempting to use fixed point is most + * eggregious for SF where 1/SF is an integral multiple of 1/3. + * + * However, since the MDP2 has already been committed to HW, we + * only use the rational phase accumulator (RPA) when 1/SF is an + * integral multiple of 1/3. This will help minimize regressions in + * matching the HW to the C-Sim. + */ + /* + * Set the RPA flag for this dimension. + * + * In order for 1/SF (dim_in/dim_out) to be an integral multiple of + * 1/3, dim_out must be an integral multiple of 3. + */ + if (!(dim_out % 3)) { + mult = dim_out / 3; + rpa_on = (!(dim_in % mult)); + } + + numer = dim_out; + denom = dim_in; + + /* + * convert to U30.34 before division + * + * The K vectors carry 4 extra bits of precision + * and are rounded. + * + * We initially go 5 bits over then round by adding + * 1 and right shifting by 1 + * so final result is U31.33 + */ + numer <<= PQF_PLUS_5; + + /* now calculate the scale factor (aka k3) */ + k3 = ((mdp_do_div(numer, denom) + 1) >> 1); + + /* check scale factor for legal range [0.25 - 4.0] */ + if (((k3 >> 4) < (1LL << PQF_MINUS_2)) || + ((k3 >> 4) > (1LL << PQF_PLUS_2))) { + return -1; + } + + /* calculate inverse scale factor (aka k1) for phase init */ + numer = dim_in; + denom = dim_out; + numer <<= PQF_PLUS_5; + k1 = ((mdp_do_div(numer, denom) + 1) >> 1); + + /* + * calculate initial phase and ROI overfetch + */ + /* convert point5 & one to S39.24 (will always be positive) */ + point5 <<= (PQF_PLUS_4 - 1); + one <<= PQF_PLUS_4; + k2 = ((k1 - one) >> 1); + init_phase = (int)(k2 >> 4); + k4 = ((k3 - one) >> 1); + if (k3 == one) { + /* the simple case; SF = 1.0 */ + beg_of = 1; + end_of = 2; + } else { + /* calculate the masks */ + fract_mask = one - 1; + int_mask = ~fract_mask; + + if (!rpa_on) { + /* + * FIXED POINT IMPLEMENTATION + */ + if (!org) { + /* A fairly simple case; ROI origin = 0 */ + if (k1 < one) { + /* upscaling */ + beg_of = end_of = 2; + } + /* 0.33 <= SF < 1.0 */ + else if (k1 < (3LL << PQF_PLUS_4)) + beg_of = end_of = 1; + /* 0.33 == SF */ + else if (k1 == (3LL << PQF_PLUS_4)) { + beg_of = 0; + end_of = 1; + } + /* 0.25 <= SF < 0.33 */ + else + beg_of = end_of = 0; + } else { + /* + * The complicated case; ROI origin != 0 + * init_phase needs to be adjusted + * OF is also position dependent + */ + + /* map (org - .5) into destination space */ + Os = ((uint64) org << 1) - 1; + Od = ((k3 * Os) >> 1) + k4; + + /* take the ceiling */ + Odprime = (Od & int_mask); + if (Odprime != Od) + Odprime += one; + + /* now map that back to source space */ + Osprime = (k1 * (Odprime >> PQF_PLUS_4)) + k2; + + /* then floor & decrement to calculate the required + starting coordinate */ + Oreq = (Osprime & int_mask) - one; + + /* calculate end coord in destination space then map to + source space */ + Ed = Odprime + + ((uint64) dim_out << PQF_PLUS_4) - one; + Es = (k1 * (Ed >> PQF_PLUS_4)) + k2; + + /* now floor & increment by 2 to calculate the required + ending coordinate */ + Ereq = (Es & int_mask) + (one << 1); + + /* calculate initial phase */ +#ifdef ADJUST_IP + + IP64 = Osprime - Oreq; + delta = ((int64) (org) << PQF_PLUS_4) - Oreq; + IP64 -= delta; + + /* limit to valid range before the left shift */ + delta = (IP64 & (1LL << 63)) ? 4 : -4; + delta <<= PQF_PLUS_4; + while (abs((int)(IP64 >> PQF_PLUS_4)) > 4) + IP64 += delta; + + /* right shift to account for extra bits of precision */ + init_phase = (int)(IP64 >> 4); + +#else /* ADJUST_IP */ + + /* just calculate the real initial phase */ + init_phase = (int)((Osprime - Oreq) >> 4); + +#endif /* ADJUST_IP */ + + /* calculate the overfetch */ + beg_of = org - (uint32) (Oreq >> PQF_PLUS_4); + end_of = + (uint32) (Ereq >> PQF_PLUS_4) - (org + + dim_in - + 1); + } + } else { + /* + * RPA IMPLEMENTATION + * + * init_phase needs to be calculated in all RPA_on cases + * because it's a numerator, not a fixed point value. + */ + + /* map (org - .5) into destination space */ + Os = ((uint64) org << PQF_PLUS_4) - point5; + Od = mdp_do_div((dim_out * (Os + point5)), + dim_in) - point5; + + /* take the ceiling */ + Odprime = (Od & int_mask); + if (Odprime != Od) + Odprime += one; + + /* now map that back to source space */ + Osprime = + mdp_do_div((dim_in * (Odprime + point5)), + dim_out) - point5; + + /* then floor & decrement to calculate the required + starting coordinate */ + Oreq = (Osprime & int_mask) - one; + + /* calculate end coord in destination space then map to + source space */ + Ed = Odprime + ((uint64) dim_out << PQF_PLUS_4) - one; + Es = mdp_do_div((dim_in * (Ed + point5)), + dim_out) - point5; + + /* now floor & increment by 2 to calculate the required + ending coordinate */ + Ereq = (Es & int_mask) + (one << 1); + + /* calculate initial phase */ + +#ifdef ADJUST_IP + + IP64 = Osprime - Oreq; + delta = ((int64) (org) << PQF_PLUS_4) - Oreq; + IP64 -= delta; + + /* limit to valid range before the left shift */ + delta = (IP64 & (1LL << 63)) ? 4 : -4; + delta <<= PQF_PLUS_4; + while (abs((int)(IP64 >> PQF_PLUS_4)) > 4) + IP64 += delta; + + /* right shift to account for extra bits of precision */ + init_phase = (int)(IP64 >> 4); + +#else /* ADJUST_IP */ + + /* just calculate the real initial phase */ + init_phase = (int)((Osprime - Oreq) >> 4); + +#endif /* ADJUST_IP */ + + /* calculate the overfetch */ + beg_of = org - (uint32) (Oreq >> PQF_PLUS_4); + end_of = + (uint32) (Ereq >> PQF_PLUS_4) - (org + dim_in - 1); + } + } + + /* return the scale parameters */ + *phase_init_ptr = init_phase; + *phase_step_ptr = (uint32) (k1 >> 4); + *num_repl_beg_ptr = beg_of; + *num_repl_end_ptr = end_of; + + return 0; +} + +static uint8 *mdp_adjust_rot_addr(MDPIBUF *iBuf, uint8 *addr, uint32 uv) +{ + uint32 dest_ystride = iBuf->ibuf_width * iBuf->bpp; + uint32 h_slice = 1; + + if (uv && ((iBuf->ibuf_type == MDP_Y_CBCR_H2V2) || + (iBuf->ibuf_type == MDP_Y_CRCB_H2V2))) + h_slice = 2; + + if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_ROT90) ^ + MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_LR)) { + addr = + addr + (iBuf->roi.dst_width - + MIN(16, iBuf->roi.dst_width)) * iBuf->bpp; + } + if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_UD)) { + addr = + addr + ((iBuf->roi.dst_height - + MIN(16, iBuf->roi.dst_height))/h_slice) * dest_ystride; + } + + return addr; +} + +void mdp_set_scale(MDPIBUF *iBuf, + uint32 dst_roi_width, + uint32 dst_roi_height, + boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr) +{ + uint32 dst_roi_width_scale; + uint32 dst_roi_height_scale; + boolean use_pr; + uint32 phasex_step = 0; + uint32 phasey_step = 0; + int32 phasex_init = 0; + int32 phasey_init = 0; + uint32 lines_dup = 0; + uint32 lines_dup_bg = 0; + uint32 dummy; + uint32 mdp_blur = 0; + + if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) { + if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) { + dst_roi_width_scale = dst_roi_height; + dst_roi_height_scale = dst_roi_width; + } else { + dst_roi_width_scale = dst_roi_width; + dst_roi_height_scale = dst_roi_height; + } + + mdp_blur = iBuf->mdpImg.mdpOp & MDPOP_BLUR; + + if ((dst_roi_width_scale != iBuf->roi.width) || + (dst_roi_height_scale != iBuf->roi.height) || + mdp_blur) { + *pppop_reg_ptr |= + (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON); + + /* let's use SHIM logic to calculate the partial ROI scaling */ +#if 0 + phasex_step = + (uint32) mdp_do_div(0x20000000 * iBuf->roi.width, + dst_roi_width_scale); + phasey_step = + (uint32) mdp_do_div(0x20000000 * iBuf->roi.height, + dst_roi_height_scale); + +/* + phasex_step= ((long long) iBuf->roi.width * 0x20000000)/dst_roi_width_scale; + phasey_step= ((long long)iBuf->roi.height * 0x20000000)/dst_roi_height_scale; +*/ + + phasex_init = + (((long long)phasex_step - 0x20000000) >> 1); + phasey_init = + (((long long)phasey_step - 0x20000000) >> 1); + +#else + mdp_calc_scale_params(iBuf->roi.x, iBuf->roi.width, + dst_roi_width_scale, 1, + &phasex_init, &phasex_step, + &dummy, &dummy); + mdp_calc_scale_params(iBuf->roi.y, iBuf->roi.height, + dst_roi_height_scale, 0, + &phasey_init, &phasey_step, + &dummy, &dummy); +#endif + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c, + phasex_init); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140, + phasey_init); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144, + phasex_step); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148, + phasey_step); + + use_pr = (inputRGB) && (outputRGB); + + if ((dst_roi_width_scale > iBuf->roi.width) || + (dst_roi_height_scale > iBuf->roi.height)) { + if ((use_pr) + && (mdp_curr_up_scale_xy != + MDP_PR_SCALE_UP)) { + mdp_load_pr_upscale_table(); + mdp_curr_up_scale_xy = MDP_PR_SCALE_UP; + } else if ((!use_pr) + && (mdp_curr_up_scale_xy != + MDP_BC_SCALE_UP)) { + mdp_load_bc_upscale_table(); + mdp_curr_up_scale_xy = MDP_BC_SCALE_UP; + } + } + + if (mdp_blur) { + load_scale_table(mdp_gaussian_blur_table, + ARRAY_SIZE(mdp_gaussian_blur_table)); + mdp_curr_down_scale_x = MDP_SCALE_BLUR; + mdp_curr_down_scale_y = MDP_SCALE_BLUR; + } + + /* 0.2 < x <= 1 scaling factor */ + if ((dst_roi_width_scale <= iBuf->roi.width) && + !mdp_blur) { + if (((dst_roi_width_scale * 10) / + iBuf->roi.width) > 8) { + if ((use_pr) + && (mdp_curr_down_scale_x != + MDP_PR_SCALE_POINT8_1)) { + mdp_load_pr_downscale_table_x_point8TO1 + (); + mdp_curr_down_scale_x = + MDP_PR_SCALE_POINT8_1; + } else if ((!use_pr) + && (mdp_curr_down_scale_x != + MDP_BC_SCALE_POINT8_1)) { + mdp_load_bc_downscale_table_x_point8TO1 + (); + mdp_curr_down_scale_x = + MDP_BC_SCALE_POINT8_1; + } + } else + if (((dst_roi_width_scale * 10) / + iBuf->roi.width) > 6) { + if ((use_pr) + && (mdp_curr_down_scale_x != + MDP_PR_SCALE_POINT6_POINT8)) { + mdp_load_pr_downscale_table_x_point6TOpoint8 + (); + mdp_curr_down_scale_x = + MDP_PR_SCALE_POINT6_POINT8; + } else if ((!use_pr) + && (mdp_curr_down_scale_x != + MDP_BC_SCALE_POINT6_POINT8)) + { + mdp_load_bc_downscale_table_x_point6TOpoint8 + (); + mdp_curr_down_scale_x = + MDP_BC_SCALE_POINT6_POINT8; + } + } else + if (((dst_roi_width_scale * 10) / + iBuf->roi.width) > 4) { + if ((use_pr) + && (mdp_curr_down_scale_x != + MDP_PR_SCALE_POINT4_POINT6)) { + mdp_load_pr_downscale_table_x_point4TOpoint6 + (); + mdp_curr_down_scale_x = + MDP_PR_SCALE_POINT4_POINT6; + } else if ((!use_pr) + && (mdp_curr_down_scale_x != + MDP_BC_SCALE_POINT4_POINT6)) + { + mdp_load_bc_downscale_table_x_point4TOpoint6 + (); + mdp_curr_down_scale_x = + MDP_BC_SCALE_POINT4_POINT6; + } + } else { + if ((use_pr) + && (mdp_curr_down_scale_x != + MDP_PR_SCALE_POINT2_POINT4)) { + mdp_load_pr_downscale_table_x_point2TOpoint4 + (); + mdp_curr_down_scale_x = + MDP_PR_SCALE_POINT2_POINT4; + } else if ((!use_pr) + && (mdp_curr_down_scale_x != + MDP_BC_SCALE_POINT2_POINT4)) + { + mdp_load_bc_downscale_table_x_point2TOpoint4 + (); + mdp_curr_down_scale_x = + MDP_BC_SCALE_POINT2_POINT4; + } + } + } + /* 0.2 < y <= 1 scaling factor */ + if ((dst_roi_height_scale <= iBuf->roi.height) && + !mdp_blur) { + if (((dst_roi_height_scale * 10) / + iBuf->roi.height) > 8) { + if ((use_pr) + && (mdp_curr_down_scale_y != + MDP_PR_SCALE_POINT8_1)) { + mdp_load_pr_downscale_table_y_point8TO1 + (); + mdp_curr_down_scale_y = + MDP_PR_SCALE_POINT8_1; + } else if ((!use_pr) + && (mdp_curr_down_scale_y != + MDP_BC_SCALE_POINT8_1)) { + mdp_load_bc_downscale_table_y_point8TO1 + (); + mdp_curr_down_scale_y = + MDP_BC_SCALE_POINT8_1; + } + } else + if (((dst_roi_height_scale * 10) / + iBuf->roi.height) > 6) { + if ((use_pr) + && (mdp_curr_down_scale_y != + MDP_PR_SCALE_POINT6_POINT8)) { + mdp_load_pr_downscale_table_y_point6TOpoint8 + (); + mdp_curr_down_scale_y = + MDP_PR_SCALE_POINT6_POINT8; + } else if ((!use_pr) + && (mdp_curr_down_scale_y != + MDP_BC_SCALE_POINT6_POINT8)) + { + mdp_load_bc_downscale_table_y_point6TOpoint8 + (); + mdp_curr_down_scale_y = + MDP_BC_SCALE_POINT6_POINT8; + } + } else + if (((dst_roi_height_scale * 10) / + iBuf->roi.height) > 4) { + if ((use_pr) + && (mdp_curr_down_scale_y != + MDP_PR_SCALE_POINT4_POINT6)) { + mdp_load_pr_downscale_table_y_point4TOpoint6 + (); + mdp_curr_down_scale_y = + MDP_PR_SCALE_POINT4_POINT6; + } else if ((!use_pr) + && (mdp_curr_down_scale_y != + MDP_BC_SCALE_POINT4_POINT6)) + { + mdp_load_bc_downscale_table_y_point4TOpoint6 + (); + mdp_curr_down_scale_y = + MDP_BC_SCALE_POINT4_POINT6; + } + } else { + if ((use_pr) + && (mdp_curr_down_scale_y != + MDP_PR_SCALE_POINT2_POINT4)) { + mdp_load_pr_downscale_table_y_point2TOpoint4 + (); + mdp_curr_down_scale_y = + MDP_PR_SCALE_POINT2_POINT4; + } else if ((!use_pr) + && (mdp_curr_down_scale_y != + MDP_BC_SCALE_POINT2_POINT4)) + { + mdp_load_bc_downscale_table_y_point2TOpoint4 + (); + mdp_curr_down_scale_y = + MDP_BC_SCALE_POINT2_POINT4; + } + } + } + } else { + iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE); + } + } + /* setting edge condition here after scaling check */ + if (mdp_get_edge_cond(iBuf, &lines_dup, &lines_dup_bg)) + printk(KERN_ERR "msm_fb: mdp_get_edge_cond() error!\n"); + + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01b8, lines_dup); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01bc, lines_dup_bg); +} + +void mdp_init_scale_table(void) +{ + mdp_curr_up_scale_xy = MDP_INIT_SCALE; + mdp_curr_down_scale_x = MDP_INIT_SCALE; + mdp_curr_down_scale_y = MDP_INIT_SCALE; +} + +void mdp_adjust_start_addr(uint8 **src0, + uint8 **src1, + int v_slice, + int h_slice, + int x, + int y, + uint32 width, + uint32 height, int bpp, MDPIBUF *iBuf, int layer) +{ + *src0 += (x + y * width) * bpp; + + /* if it's dest/bg buffer, we need to adjust it for rotation */ + if (layer != 0) + *src0 = mdp_adjust_rot_addr(iBuf, *src0, 0); + + if (*src1) { + /* + * MDP_Y_CBCR_H2V2/MDP_Y_CRCB_H2V2 cosite for now + * we need to shift x direction same as y dir for offsite + */ + *src1 += + ((x / h_slice) * h_slice + + ((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp; + + /* if it's dest/bg buffer, we need to adjust it for rotation */ + if (layer != 0) + *src1 = mdp_adjust_rot_addr(iBuf, *src1, 1); + } +} + +void mdp_set_blend_attr(MDPIBUF *iBuf, + uint32 *alpha, + uint32 *tpVal, + uint32 perPixelAlpha, uint32 *pppop_reg_ptr) +{ + if (perPixelAlpha) { + *pppop_reg_ptr |= PPP_OP_ROT_ON | + PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA; + } else { + if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) + && (iBuf->mdpImg.alpha == 0xff)) { + iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB); + } + + if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) + && (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) { + *pppop_reg_ptr |= + PPP_OP_ROT_ON | PPP_OP_BLEND_ON | + PPP_OP_BLEND_CONSTANT_ALPHA | + PPP_OP_BLEND_ALPHA_BLEND_NORMAL | + PPP_BLEND_CALPHA_TRNASP; + + *alpha = iBuf->mdpImg.alpha; + *tpVal = iBuf->mdpImg.tpVal; + } else { + if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) { + *pppop_reg_ptr |= PPP_OP_ROT_ON | + PPP_OP_BLEND_ON | + PPP_OP_BLEND_SRCPIXEL_TRANSP; + *tpVal = iBuf->mdpImg.tpVal; + } else if (iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) { + *pppop_reg_ptr |= PPP_OP_ROT_ON | + PPP_OP_BLEND_ON | + PPP_OP_BLEND_ALPHA_BLEND_NORMAL | + PPP_OP_BLEND_CONSTANT_ALPHA; + *alpha = iBuf->mdpImg.alpha; + } + } + } +} diff --git a/drivers/staging/msm/mdp_ppp_v31.c b/drivers/staging/msm/mdp_ppp_v31.c new file mode 100644 index 000000000000..76495dbe4e64 --- /dev/null +++ b/drivers/staging/msm/mdp_ppp_v31.c @@ -0,0 +1,828 @@ +/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/fb.h> +#include "linux/proc_fs.h" + +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <asm/div64.h> + +#include "mdp.h" +#include "msm_fb.h" + +#define MDP_SCALE_COEFF_NUM 32 +#define MDP_SCALE_0P2_TO_0P4_INDEX 0 +#define MDP_SCALE_0P4_TO_0P6_INDEX 32 +#define MDP_SCALE_0P6_TO_0P8_INDEX 64 +#define MDP_SCALE_0P8_TO_8P0_INDEX 96 +#define MDP_SCALE_COEFF_MASK 0x3ff + +#define MDP_SCALE_PR 0 +#define MDP_SCALE_FIR 1 + +static uint32 mdp_scale_0p8_to_8p0_mode; +static uint32 mdp_scale_0p6_to_0p8_mode; +static uint32 mdp_scale_0p4_to_0p6_mode; +static uint32 mdp_scale_0p2_to_0p4_mode; + +/* -------- All scaling range, "pixel repeat" -------- */ +static int16 mdp_scale_pixel_repeat_C0[MDP_SCALE_COEFF_NUM] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static int16 mdp_scale_pixel_repeat_C1[MDP_SCALE_COEFF_NUM] = { + 511, 511, 511, 511, 511, 511, 511, 511, + 511, 511, 511, 511, 511, 511, 511, 511, + 511, 511, 511, 511, 511, 511, 511, 511, + 511, 511, 511, 511, 511, 511, 511, 511 +}; + +static int16 mdp_scale_pixel_repeat_C2[MDP_SCALE_COEFF_NUM] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static int16 mdp_scale_pixel_repeat_C3[MDP_SCALE_COEFF_NUM] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* --------------------------- FIR ------------------------------------- */ +/* -------- Downscale, ranging from 0.8x to 8.0x of original size -------- */ + +static int16 mdp_scale_0p8_to_8p0_C0[MDP_SCALE_COEFF_NUM] = { + 0, -7, -13, -19, -24, -28, -32, -34, -37, -39, + -40, -41, -41, -41, -40, -40, -38, -37, -35, -33, + -31, -29, -26, -24, -21, -18, -15, -13, -10, -7, + -5, -2 +}; + +static int16 mdp_scale_0p8_to_8p0_C1[MDP_SCALE_COEFF_NUM] = { + 511, 507, 501, 494, 485, 475, 463, 450, 436, 422, + 405, 388, 370, 352, 333, 314, 293, 274, 253, 233, + 213, 193, 172, 152, 133, 113, 95, 77, 60, 43, + 28, 13 +}; + +static int16 mdp_scale_0p8_to_8p0_C2[MDP_SCALE_COEFF_NUM] = { + 0, 13, 28, 43, 60, 77, 95, 113, 133, 152, + 172, 193, 213, 233, 253, 274, 294, 314, 333, 352, + 370, 388, 405, 422, 436, 450, 463, 475, 485, 494, + 501, 507, +}; + +static int16 mdp_scale_0p8_to_8p0_C3[MDP_SCALE_COEFF_NUM] = { + 0, -2, -5, -7, -10, -13, -15, -18, -21, -24, + -26, -29, -31, -33, -35, -37, -38, -40, -40, -41, + -41, -41, -40, -39, -37, -34, -32, -28, -24, -19, + -13, -7 +}; + +/* -------- Downscale, ranging from 0.6x to 0.8x of original size -------- */ + +static int16 mdp_scale_0p6_to_0p8_C0[MDP_SCALE_COEFF_NUM] = { + 104, 96, 89, 82, 75, 68, 61, 55, 49, 43, + 38, 33, 28, 24, 20, 16, 12, 9, 6, 4, + 2, 0, -2, -4, -5, -6, -7, -7, -8, -8, + -8, -8 +}; + +static int16 mdp_scale_0p6_to_0p8_C1[MDP_SCALE_COEFF_NUM] = { + 303, 303, 302, 300, 298, 296, 293, 289, 286, 281, + 276, 270, 265, 258, 252, 245, 238, 230, 223, 214, + 206, 197, 189, 180, 172, 163, 154, 145, 137, 128, + 120, 112 +}; + +static int16 mdp_scale_0p6_to_0p8_C2[MDP_SCALE_COEFF_NUM] = { + 112, 120, 128, 137, 145, 154, 163, 172, 180, 189, + 197, 206, 214, 223, 230, 238, 245, 252, 258, 265, + 270, 276, 281, 286, 289, 293, 296, 298, 300, 302, + 303, 303 +}; + +static int16 mdp_scale_0p6_to_0p8_C3[MDP_SCALE_COEFF_NUM] = { + -8, -8, -8, -8, -7, -7, -6, -5, -4, -2, + 0, 2, 4, 6, 9, 12, 16, 20, 24, 28, + 33, 38, 43, 49, 55, 61, 68, 75, 82, 89, + 96, 104 +}; + +/* -------- Downscale, ranging from 0.4x to 0.6x of original size -------- */ + +static int16 mdp_scale_0p4_to_0p6_C0[MDP_SCALE_COEFF_NUM] = { + 136, 132, 128, 123, 119, 115, 111, 107, 103, 98, + 95, 91, 87, 84, 80, 76, 73, 69, 66, 62, + 59, 57, 54, 50, 47, 44, 41, 39, 36, 33, + 32, 29 +}; + +static int16 mdp_scale_0p4_to_0p6_C1[MDP_SCALE_COEFF_NUM] = { + 206, 205, 204, 204, 201, 200, 199, 197, 196, 194, + 191, 191, 189, 185, 184, 182, 180, 178, 176, 173, + 170, 168, 165, 162, 160, 157, 155, 152, 148, 146, + 142, 140 +}; + +static int16 mdp_scale_0p4_to_0p6_C2[MDP_SCALE_COEFF_NUM] = { + 140, 142, 146, 148, 152, 155, 157, 160, 162, 165, + 168, 170, 173, 176, 178, 180, 182, 184, 185, 189, + 191, 191, 194, 196, 197, 199, 200, 201, 204, 204, + 205, 206 +}; + +static int16 mdp_scale_0p4_to_0p6_C3[MDP_SCALE_COEFF_NUM] = { + 29, 32, 33, 36, 39, 41, 44, 47, 50, 54, + 57, 59, 62, 66, 69, 73, 76, 80, 84, 87, + 91, 95, 98, 103, 107, 111, 115, 119, 123, 128, + 132, 136 +}; + +/* -------- Downscale, ranging from 0.2x to 0.4x of original size -------- */ + +static int16 mdp_scale_0p2_to_0p4_C0[MDP_SCALE_COEFF_NUM] = { + 131, 131, 130, 129, 128, 127, 127, 126, 125, 125, + 124, 123, 123, 121, 120, 119, 119, 118, 117, 117, + 116, 115, 115, 114, 113, 112, 111, 110, 109, 109, + 108, 107 +}; + +static int16 mdp_scale_0p2_to_0p4_C1[MDP_SCALE_COEFF_NUM] = { + 141, 140, 140, 140, 140, 139, 138, 138, 138, 137, + 137, 137, 136, 137, 137, 137, 136, 136, 136, 135, + 135, 135, 134, 134, 134, 134, 134, 133, 133, 132, + 132, 132 +}; + +static int16 mdp_scale_0p2_to_0p4_C2[MDP_SCALE_COEFF_NUM] = { + 132, 132, 132, 133, 133, 134, 134, 134, 134, 134, + 135, 135, 135, 136, 136, 136, 137, 137, 137, 136, + 137, 137, 137, 138, 138, 138, 139, 140, 140, 140, + 140, 141 +}; + +static int16 mdp_scale_0p2_to_0p4_C3[MDP_SCALE_COEFF_NUM] = { + 107, 108, 109, 109, 110, 111, 112, 113, 114, 115, + 115, 116, 117, 117, 118, 119, 119, 120, 121, 123, + 123, 124, 125, 125, 126, 127, 127, 128, 129, 130, + 131, 131 +}; + +static void mdp_update_scale_table(int index, int16 *c0, int16 *c1, + int16 *c2, int16 *c3) +{ + int i, val; + + for (i = 0; i < MDP_SCALE_COEFF_NUM; i++) { + val = + ((MDP_SCALE_COEFF_MASK & c1[i]) << 16) | + (MDP_SCALE_COEFF_MASK & c0[i]); + MDP_OUTP(MDP_PPP_SCALE_COEFF_LSBn(index), val); + val = + ((MDP_SCALE_COEFF_MASK & c3[i]) << 16) | + (MDP_SCALE_COEFF_MASK & c2[i]); + MDP_OUTP(MDP_PPP_SCALE_COEFF_MSBn(index), val); + index++; + } +} + +void mdp_init_scale_table(void) +{ + mdp_scale_0p2_to_0p4_mode = MDP_SCALE_FIR; + mdp_update_scale_table(MDP_SCALE_0P2_TO_0P4_INDEX, + mdp_scale_0p2_to_0p4_C0, + mdp_scale_0p2_to_0p4_C1, + mdp_scale_0p2_to_0p4_C2, + mdp_scale_0p2_to_0p4_C3); + + mdp_scale_0p4_to_0p6_mode = MDP_SCALE_FIR; + mdp_update_scale_table(MDP_SCALE_0P4_TO_0P6_INDEX, + mdp_scale_0p4_to_0p6_C0, + mdp_scale_0p4_to_0p6_C1, + mdp_scale_0p4_to_0p6_C2, + mdp_scale_0p4_to_0p6_C3); + + mdp_scale_0p6_to_0p8_mode = MDP_SCALE_FIR; + mdp_update_scale_table(MDP_SCALE_0P6_TO_0P8_INDEX, + mdp_scale_0p6_to_0p8_C0, + mdp_scale_0p6_to_0p8_C1, + mdp_scale_0p6_to_0p8_C2, + mdp_scale_0p6_to_0p8_C3); + + mdp_scale_0p8_to_8p0_mode = MDP_SCALE_FIR; + mdp_update_scale_table(MDP_SCALE_0P8_TO_8P0_INDEX, + mdp_scale_0p8_to_8p0_C0, + mdp_scale_0p8_to_8p0_C1, + mdp_scale_0p8_to_8p0_C2, + mdp_scale_0p8_to_8p0_C3); +} + +static long long mdp_do_div(long long num, long long den) +{ + do_div(num, den); + return num; +} + +#define SCALER_PHASE_BITS 29 +#define HAL_MDP_PHASE_STEP_2P50 0x50000000 +#define HAL_MDP_PHASE_STEP_1P66 0x35555555 +#define HAL_MDP_PHASE_STEP_1P25 0x28000000 + +struct phase_val { + int phase_init_x; + int phase_init_y; + int phase_step_x; + int phase_step_y; +}; + +static void mdp_calc_scaleInitPhase_3p1(uint32 in_w, + uint32 in_h, + uint32 out_w, + uint32 out_h, + boolean is_rotate, + boolean is_pp_x, + boolean is_pp_y, struct phase_val *pval) +{ + uint64 dst_ROI_width; + uint64 dst_ROI_height; + uint64 src_ROI_width; + uint64 src_ROI_height; + + /* + * phase_step_x, phase_step_y, phase_init_x and phase_init_y + * are represented in fixed-point, unsigned 3.29 format + */ + uint32 phase_step_x = 0; + uint32 phase_step_y = 0; + uint32 phase_init_x = 0; + uint32 phase_init_y = 0; + uint32 yscale_filter_sel, xscale_filter_sel; + uint32 scale_unit_sel_x, scale_unit_sel_y; + + uint64 numerator, denominator; + uint64 temp_dim; + + src_ROI_width = in_w; + src_ROI_height = in_h; + dst_ROI_width = out_w; + dst_ROI_height = out_h; + + /* if there is a 90 degree rotation */ + if (is_rotate) { + /* decide whether to use FIR or M/N for scaling */ + + /* if down-scaling by a factor smaller than 1/4 */ + if (src_ROI_width > (4 * dst_ROI_height)) + scale_unit_sel_x = 1; /* use M/N scalar */ + else + scale_unit_sel_x = 0; /* use FIR scalar */ + + /* if down-scaling by a factor smaller than 1/4 */ + if (src_ROI_height > (4 * dst_ROI_width)) + scale_unit_sel_y = 1; /* use M/N scalar */ + else + scale_unit_sel_y = 0; /* use FIR scalar */ + } else { + /* decide whether to use FIR or M/N for scaling */ + + if (src_ROI_width > (4 * dst_ROI_width)) + scale_unit_sel_x = 1; /* use M/N scalar */ + else + scale_unit_sel_x = 0; /* use FIR scalar */ + + if (src_ROI_height > (4 * dst_ROI_height)) + scale_unit_sel_y = 1; /* use M/N scalar */ + else + scale_unit_sel_y = 0; /* use FIR scalar */ + + } + + /* if there is a 90 degree rotation */ + if (is_rotate) { + /* swap the width and height of dst ROI */ + temp_dim = dst_ROI_width; + dst_ROI_width = dst_ROI_height; + dst_ROI_height = temp_dim; + } + + /* calculate phase step for the x direction */ + + /* if destination is only 1 pixel wide, the value of phase_step_x + is unimportant. Assigning phase_step_x to src ROI width + as an arbitrary value. */ + if (dst_ROI_width == 1) + phase_step_x = (uint32) ((src_ROI_width) << SCALER_PHASE_BITS); + + /* if using FIR scalar */ + else if (scale_unit_sel_x == 0) { + + /* Calculate the quotient ( src_ROI_width - 1 ) / ( dst_ROI_width - 1) + with u3.29 precision. Quotient is rounded up to the larger + 29th decimal point. */ + numerator = (src_ROI_width - 1) << SCALER_PHASE_BITS; + denominator = (dst_ROI_width - 1); /* never equals to 0 because of the "( dst_ROI_width == 1 ) case" */ + phase_step_x = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* divide and round up to the larger 29th decimal point. */ + + } + + /* if M/N scalar */ + else if (scale_unit_sel_x == 1) { + /* Calculate the quotient ( src_ROI_width ) / ( dst_ROI_width) + with u3.29 precision. Quotient is rounded down to the + smaller 29th decimal point. */ + numerator = (src_ROI_width) << SCALER_PHASE_BITS; + denominator = (dst_ROI_width); + phase_step_x = (uint32) mdp_do_div(numerator, denominator); + } + /* calculate phase step for the y direction */ + + /* if destination is only 1 pixel wide, the value of + phase_step_x is unimportant. Assigning phase_step_x + to src ROI width as an arbitrary value. */ + if (dst_ROI_height == 1) + phase_step_y = (uint32) ((src_ROI_height) << SCALER_PHASE_BITS); + + /* if FIR scalar */ + else if (scale_unit_sel_y == 0) { + /* Calculate the quotient ( src_ROI_height - 1 ) / ( dst_ROI_height - 1) + with u3.29 precision. Quotient is rounded up to the larger + 29th decimal point. */ + numerator = (src_ROI_height - 1) << SCALER_PHASE_BITS; + denominator = (dst_ROI_height - 1); /* never equals to 0 because of the "( dst_ROI_height == 1 )" case */ + phase_step_y = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* Quotient is rounded up to the larger 29th decimal point. */ + + } + + /* if M/N scalar */ + else if (scale_unit_sel_y == 1) { + /* Calculate the quotient ( src_ROI_height ) / ( dst_ROI_height) + with u3.29 precision. Quotient is rounded down to the smaller + 29th decimal point. */ + numerator = (src_ROI_height) << SCALER_PHASE_BITS; + denominator = (dst_ROI_height); + phase_step_y = (uint32) mdp_do_div(numerator, denominator); + } + + /* decide which set of FIR coefficients to use */ + if (phase_step_x > HAL_MDP_PHASE_STEP_2P50) + xscale_filter_sel = 0; + else if (phase_step_x > HAL_MDP_PHASE_STEP_1P66) + xscale_filter_sel = 1; + else if (phase_step_x > HAL_MDP_PHASE_STEP_1P25) + xscale_filter_sel = 2; + else + xscale_filter_sel = 3; + + if (phase_step_y > HAL_MDP_PHASE_STEP_2P50) + yscale_filter_sel = 0; + else if (phase_step_y > HAL_MDP_PHASE_STEP_1P66) + yscale_filter_sel = 1; + else if (phase_step_y > HAL_MDP_PHASE_STEP_1P25) + yscale_filter_sel = 2; + else + yscale_filter_sel = 3; + + /* calculate phase init for the x direction */ + + /* if using FIR scalar */ + if (scale_unit_sel_x == 0) { + if (dst_ROI_width == 1) + phase_init_x = + (uint32) ((src_ROI_width - 1) << SCALER_PHASE_BITS); + else + phase_init_x = 0; + + } + /* M over N scalar */ + else if (scale_unit_sel_x == 1) + phase_init_x = 0; + + /* calculate phase init for the y direction + if using FIR scalar */ + if (scale_unit_sel_y == 0) { + if (dst_ROI_height == 1) + phase_init_y = + (uint32) ((src_ROI_height - + 1) << SCALER_PHASE_BITS); + else + phase_init_y = 0; + + } + /* M over N scalar */ + else if (scale_unit_sel_y == 1) + phase_init_y = 0; + + /* write registers */ + pval->phase_step_x = (uint32) phase_step_x; + pval->phase_step_y = (uint32) phase_step_y; + pval->phase_init_x = (uint32) phase_init_x; + pval->phase_init_y = (uint32) phase_init_y; + + return; +} + +void mdp_set_scale(MDPIBUF *iBuf, + uint32 dst_roi_width, + uint32 dst_roi_height, + boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr) +{ + uint32 dst_roi_width_scale; + uint32 dst_roi_height_scale; + struct phase_val pval; + boolean use_pr; + uint32 ppp_scale_config = 0; + + if (!inputRGB) + ppp_scale_config |= BIT(6); + + if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) { + if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) { + dst_roi_width_scale = dst_roi_height; + dst_roi_height_scale = dst_roi_width; + } else { + dst_roi_width_scale = dst_roi_width; + dst_roi_height_scale = dst_roi_height; + } + + if ((dst_roi_width_scale != iBuf->roi.width) || + (dst_roi_height_scale != iBuf->roi.height) || + (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) { + *pppop_reg_ptr |= + (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON); + + mdp_calc_scaleInitPhase_3p1(iBuf->roi.width, + iBuf->roi.height, + dst_roi_width, + dst_roi_height, + iBuf->mdpImg. + mdpOp & MDPOP_ROT90, 1, 1, + &pval); + + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c, + pval.phase_init_x); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140, + pval.phase_init_y); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144, + pval.phase_step_x); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148, + pval.phase_step_y); + + use_pr = (inputRGB) && (outputRGB); + + /* x-direction */ + if ((dst_roi_width_scale == iBuf->roi.width) && + !(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) { + *pppop_reg_ptr &= ~PPP_OP_SCALE_X_ON; + } else + if (((dst_roi_width_scale * 10) / iBuf->roi.width) > + 8) { + if ((use_pr) + && (mdp_scale_0p8_to_8p0_mode != + MDP_SCALE_PR)) { + mdp_scale_0p8_to_8p0_mode = + MDP_SCALE_PR; + mdp_update_scale_table + (MDP_SCALE_0P8_TO_8P0_INDEX, + mdp_scale_pixel_repeat_C0, + mdp_scale_pixel_repeat_C1, + mdp_scale_pixel_repeat_C2, + mdp_scale_pixel_repeat_C3); + } else if ((!use_pr) + && (mdp_scale_0p8_to_8p0_mode != + MDP_SCALE_FIR)) { + mdp_scale_0p8_to_8p0_mode = + MDP_SCALE_FIR; + mdp_update_scale_table + (MDP_SCALE_0P8_TO_8P0_INDEX, + mdp_scale_0p8_to_8p0_C0, + mdp_scale_0p8_to_8p0_C1, + mdp_scale_0p8_to_8p0_C2, + mdp_scale_0p8_to_8p0_C3); + } + ppp_scale_config |= (SCALE_U1_SET << 2); + } else + if (((dst_roi_width_scale * 10) / iBuf->roi.width) > + 6) { + if ((use_pr) + && (mdp_scale_0p6_to_0p8_mode != + MDP_SCALE_PR)) { + mdp_scale_0p6_to_0p8_mode = + MDP_SCALE_PR; + mdp_update_scale_table + (MDP_SCALE_0P6_TO_0P8_INDEX, + mdp_scale_pixel_repeat_C0, + mdp_scale_pixel_repeat_C1, + mdp_scale_pixel_repeat_C2, + mdp_scale_pixel_repeat_C3); + } else if ((!use_pr) + && (mdp_scale_0p6_to_0p8_mode != + MDP_SCALE_FIR)) { + mdp_scale_0p6_to_0p8_mode = + MDP_SCALE_FIR; + mdp_update_scale_table + (MDP_SCALE_0P6_TO_0P8_INDEX, + mdp_scale_0p6_to_0p8_C0, + mdp_scale_0p6_to_0p8_C1, + mdp_scale_0p6_to_0p8_C2, + mdp_scale_0p6_to_0p8_C3); + } + ppp_scale_config |= (SCALE_D2_SET << 2); + } else + if (((dst_roi_width_scale * 10) / iBuf->roi.width) > + 4) { + if ((use_pr) + && (mdp_scale_0p4_to_0p6_mode != + MDP_SCALE_PR)) { + mdp_scale_0p4_to_0p6_mode = + MDP_SCALE_PR; + mdp_update_scale_table + (MDP_SCALE_0P4_TO_0P6_INDEX, + mdp_scale_pixel_repeat_C0, + mdp_scale_pixel_repeat_C1, + mdp_scale_pixel_repeat_C2, + mdp_scale_pixel_repeat_C3); + } else if ((!use_pr) + && (mdp_scale_0p4_to_0p6_mode != + MDP_SCALE_FIR)) { + mdp_scale_0p4_to_0p6_mode = + MDP_SCALE_FIR; + mdp_update_scale_table + (MDP_SCALE_0P4_TO_0P6_INDEX, + mdp_scale_0p4_to_0p6_C0, + mdp_scale_0p4_to_0p6_C1, + mdp_scale_0p4_to_0p6_C2, + mdp_scale_0p4_to_0p6_C3); + } + ppp_scale_config |= (SCALE_D1_SET << 2); + } else + if (((dst_roi_width_scale * 4) / iBuf->roi.width) >= + 1) { + if ((use_pr) + && (mdp_scale_0p2_to_0p4_mode != + MDP_SCALE_PR)) { + mdp_scale_0p2_to_0p4_mode = + MDP_SCALE_PR; + mdp_update_scale_table + (MDP_SCALE_0P2_TO_0P4_INDEX, + mdp_scale_pixel_repeat_C0, + mdp_scale_pixel_repeat_C1, + mdp_scale_pixel_repeat_C2, + mdp_scale_pixel_repeat_C3); + } else if ((!use_pr) + && (mdp_scale_0p2_to_0p4_mode != + MDP_SCALE_FIR)) { + mdp_scale_0p2_to_0p4_mode = + MDP_SCALE_FIR; + mdp_update_scale_table + (MDP_SCALE_0P2_TO_0P4_INDEX, + mdp_scale_0p2_to_0p4_C0, + mdp_scale_0p2_to_0p4_C1, + mdp_scale_0p2_to_0p4_C2, + mdp_scale_0p2_to_0p4_C3); + } + ppp_scale_config |= (SCALE_D0_SET << 2); + } else + ppp_scale_config |= BIT(0); + + /* y-direction */ + if ((dst_roi_height_scale == iBuf->roi.height) && + !(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) { + *pppop_reg_ptr &= ~PPP_OP_SCALE_Y_ON; + } else if (((dst_roi_height_scale * 10) / + iBuf->roi.height) > 8) { + if ((use_pr) + && (mdp_scale_0p8_to_8p0_mode != + MDP_SCALE_PR)) { + mdp_scale_0p8_to_8p0_mode = + MDP_SCALE_PR; + mdp_update_scale_table + (MDP_SCALE_0P8_TO_8P0_INDEX, + mdp_scale_pixel_repeat_C0, + mdp_scale_pixel_repeat_C1, + mdp_scale_pixel_repeat_C2, + mdp_scale_pixel_repeat_C3); + } else if ((!use_pr) + && (mdp_scale_0p8_to_8p0_mode != + MDP_SCALE_FIR)) { + mdp_scale_0p8_to_8p0_mode = + MDP_SCALE_FIR; + mdp_update_scale_table + (MDP_SCALE_0P8_TO_8P0_INDEX, + mdp_scale_0p8_to_8p0_C0, + mdp_scale_0p8_to_8p0_C1, + mdp_scale_0p8_to_8p0_C2, + mdp_scale_0p8_to_8p0_C3); + } + ppp_scale_config |= (SCALE_U1_SET << 4); + } else + if (((dst_roi_height_scale * 10) / + iBuf->roi.height) > 6) { + if ((use_pr) + && (mdp_scale_0p6_to_0p8_mode != + MDP_SCALE_PR)) { + mdp_scale_0p6_to_0p8_mode = + MDP_SCALE_PR; + mdp_update_scale_table + (MDP_SCALE_0P6_TO_0P8_INDEX, + mdp_scale_pixel_repeat_C0, + mdp_scale_pixel_repeat_C1, + mdp_scale_pixel_repeat_C2, + mdp_scale_pixel_repeat_C3); + } else if ((!use_pr) + && (mdp_scale_0p6_to_0p8_mode != + MDP_SCALE_FIR)) { + mdp_scale_0p6_to_0p8_mode = + MDP_SCALE_FIR; + mdp_update_scale_table + (MDP_SCALE_0P6_TO_0P8_INDEX, + mdp_scale_0p6_to_0p8_C0, + mdp_scale_0p6_to_0p8_C1, + mdp_scale_0p6_to_0p8_C2, + mdp_scale_0p6_to_0p8_C3); + } + ppp_scale_config |= (SCALE_D2_SET << 4); + } else + if (((dst_roi_height_scale * 10) / + iBuf->roi.height) > 4) { + if ((use_pr) + && (mdp_scale_0p4_to_0p6_mode != + MDP_SCALE_PR)) { + mdp_scale_0p4_to_0p6_mode = + MDP_SCALE_PR; + mdp_update_scale_table + (MDP_SCALE_0P4_TO_0P6_INDEX, + mdp_scale_pixel_repeat_C0, + mdp_scale_pixel_repeat_C1, + mdp_scale_pixel_repeat_C2, + mdp_scale_pixel_repeat_C3); + } else if ((!use_pr) + && (mdp_scale_0p4_to_0p6_mode != + MDP_SCALE_FIR)) { + mdp_scale_0p4_to_0p6_mode = + MDP_SCALE_FIR; + mdp_update_scale_table + (MDP_SCALE_0P4_TO_0P6_INDEX, + mdp_scale_0p4_to_0p6_C0, + mdp_scale_0p4_to_0p6_C1, + mdp_scale_0p4_to_0p6_C2, + mdp_scale_0p4_to_0p6_C3); + } + ppp_scale_config |= (SCALE_D1_SET << 4); + } else + if (((dst_roi_height_scale * 4) / + iBuf->roi.height) >= 1) { + if ((use_pr) + && (mdp_scale_0p2_to_0p4_mode != + MDP_SCALE_PR)) { + mdp_scale_0p2_to_0p4_mode = + MDP_SCALE_PR; + mdp_update_scale_table + (MDP_SCALE_0P2_TO_0P4_INDEX, + mdp_scale_pixel_repeat_C0, + mdp_scale_pixel_repeat_C1, + mdp_scale_pixel_repeat_C2, + mdp_scale_pixel_repeat_C3); + } else if ((!use_pr) + && (mdp_scale_0p2_to_0p4_mode != + MDP_SCALE_FIR)) { + mdp_scale_0p2_to_0p4_mode = + MDP_SCALE_FIR; + mdp_update_scale_table + (MDP_SCALE_0P2_TO_0P4_INDEX, + mdp_scale_0p2_to_0p4_C0, + mdp_scale_0p2_to_0p4_C1, + mdp_scale_0p2_to_0p4_C2, + mdp_scale_0p2_to_0p4_C3); + } + ppp_scale_config |= (SCALE_D0_SET << 4); + } else + ppp_scale_config |= BIT(1); + + if (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING) { + ppp_scale_config |= BIT(7); + MDP_OUTP(MDP_BASE + 0x50020, + iBuf->mdpImg.sp_value); + } + + MDP_OUTP(MDP_BASE + 0x10230, ppp_scale_config); + } else { + iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE); + } + } +} + +void mdp_adjust_start_addr(uint8 **src0, + uint8 **src1, + int v_slice, + int h_slice, + int x, + int y, + uint32 width, + uint32 height, int bpp, MDPIBUF *iBuf, int layer) +{ + switch (layer) { + case 0: + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0200, (y << 16) | (x)); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0208, + (height << 16) | (width)); + break; + + case 1: + /* MDP 3.1 HW bug workaround */ + if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) { + *src0 += (x + y * width) * bpp; + x = y = 0; + width = iBuf->roi.dst_width; + height = iBuf->roi.dst_height; + } + + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0204, (y << 16) | (x)); + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x020c, + (height << 16) | (width)); + break; + + case 2: + MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x019c, (y << 16) | (x)); + break; + } +} + +void mdp_set_blend_attr(MDPIBUF *iBuf, + uint32 *alpha, + uint32 *tpVal, + uint32 perPixelAlpha, uint32 *pppop_reg_ptr) +{ + int bg_alpha; + + *alpha = iBuf->mdpImg.alpha; + *tpVal = iBuf->mdpImg.tpVal; + + if (iBuf->mdpImg.mdpOp & MDPOP_FG_PM_ALPHA) { + *pppop_reg_ptr |= PPP_OP_ROT_ON | + PPP_OP_BLEND_ON | PPP_OP_BLEND_CONSTANT_ALPHA; + + bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL | + PPP_BLEND_BG_ALPHA_REVERSE; + + if (perPixelAlpha) + bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA; + else + bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA; + + outpdw(MDP_BASE + 0x70010, bg_alpha); + + if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) + *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP; + } else if (perPixelAlpha) { + *pppop_reg_ptr |= PPP_OP_ROT_ON | + PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA; + } else { + if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) + && (iBuf->mdpImg.alpha == 0xff)) { + iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB); + } + + if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) + || (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) { + *pppop_reg_ptr |= + PPP_OP_ROT_ON | PPP_OP_BLEND_ON | + PPP_OP_BLEND_CONSTANT_ALPHA | + PPP_OP_BLEND_ALPHA_BLEND_NORMAL; + } + + if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) + *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP; + } +} diff --git a/drivers/staging/msm/mdp_vsync.c b/drivers/staging/msm/mdp_vsync.c new file mode 100644 index 000000000000..bbd456044356 --- /dev/null +++ b/drivers/staging/msm/mdp_vsync.c @@ -0,0 +1,389 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/hrtimer.h> +#include <linux/vmalloc.h> +#include <linux/clk.h> + +#include <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/semaphore.h> +#include <linux/uaccess.h> +#include <mach/gpio.h> + +#include "mdp.h" +#include "msm_fb.h" +#include "mddihost.h" + +#ifdef CONFIG_FB_MSM_MDP40 +#define MDP_SYNC_CFG_0 0x100 +#define MDP_SYNC_STATUS_0 0x10c +#define MDP_PRIM_VSYNC_OUT_CTRL 0x118 +#define MDP_PRIM_VSYNC_INIT_VAL 0x128 +#else +#define MDP_SYNC_CFG_0 0x300 +#define MDP_SYNC_STATUS_0 0x30c +#define MDP_PRIM_VSYNC_OUT_CTRL 0x318 +#define MDP_PRIM_VSYNC_INIT_VAL 0x328 +#endif + +extern mddi_lcd_type mddi_lcd_idx; +extern spinlock_t mdp_spin_lock; +extern struct workqueue_struct *mdp_vsync_wq; +extern int lcdc_mode; +extern int vsync_mode; + +#ifdef MDP_HW_VSYNC +int vsync_above_th = 4; +int vsync_start_th = 1; +int vsync_load_cnt; + +struct clk *mdp_vsync_clk; + +void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd) +{ + if (mfd->use_mdp_vsync) + clk_enable(mdp_vsync_clk); +} + +void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd) +{ + if (mfd->use_mdp_vsync) + clk_disable(mdp_vsync_clk); +} +#endif + +static void mdp_set_vsync(unsigned long data) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data; + struct msm_fb_panel_data *pdata = NULL; + + pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; + + if ((pdata) && (pdata->set_vsync_notifier == NULL)) + return; + + init_timer(&mfd->vsync_resync_timer); + mfd->vsync_resync_timer.function = mdp_set_vsync; + mfd->vsync_resync_timer.data = data; + mfd->vsync_resync_timer.expires = + jiffies + mfd->panel_info.lcd.vsync_notifier_period; + add_timer(&mfd->vsync_resync_timer); + + if ((mfd->panel_info.lcd.vsync_enable) && (mfd->panel_power_on) + && (!mfd->vsync_handler_pending)) { + mfd->vsync_handler_pending = TRUE; + if (!queue_work(mdp_vsync_wq, &mfd->vsync_resync_worker)) { + MSM_FB_INFO + ("mdp_set_vsync: can't queue_work! -> needs to increase vsync_resync_timer_duration\n"); + } + } else { + MSM_FB_DEBUG + ("mdp_set_vsync failed! EN:%d PWR:%d PENDING:%d\n", + mfd->panel_info.lcd.vsync_enable, mfd->panel_power_on, + mfd->vsync_handler_pending); + } +} + +static void mdp_vsync_handler(void *data) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data; + + if (mfd->use_mdp_vsync) { +#ifdef MDP_HW_VSYNC + if (mfd->panel_power_on) + MDP_OUTP(MDP_BASE + MDP_SYNC_STATUS_0, vsync_load_cnt); + + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE); +#endif + } else { + mfd->last_vsync_timetick = ktime_get_real(); + } + + mfd->vsync_handler_pending = FALSE; +} + +irqreturn_t mdp_hw_vsync_handler_proxy(int irq, void *data) +{ + /* + * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt + * but getting inaccurate timing in mdp_vsync_handler() + * disable_irq(MDP_HW_VSYNC_IRQ); + */ + mdp_vsync_handler(data); + + return IRQ_HANDLED; +} + +#ifdef MDP_HW_VSYNC +static void mdp_set_sync_cfg_0(struct msm_fb_data_type *mfd, int vsync_cnt) +{ + unsigned long cfg; + + cfg = mfd->total_lcd_lines - 1; + cfg <<= MDP_SYNCFG_HGT_LOC; + if (mfd->panel_info.lcd.hw_vsync_mode) + cfg |= MDP_SYNCFG_VSYNC_EXT_EN; + cfg |= (MDP_SYNCFG_VSYNC_INT_EN | vsync_cnt); + + MDP_OUTP(MDP_BASE + MDP_SYNC_CFG_0, cfg); +} +#endif + +void mdp_config_vsync(struct msm_fb_data_type *mfd) +{ + + /* vsync on primary lcd only for now */ + if ((mfd->dest != DISPLAY_LCD) || (mfd->panel_info.pdest != DISPLAY_1) + || (!vsync_mode)) { + goto err_handle; + } + + if (mfd->panel_info.lcd.vsync_enable) { + mfd->total_porch_lines = mfd->panel_info.lcd.v_back_porch + + mfd->panel_info.lcd.v_front_porch + + mfd->panel_info.lcd.v_pulse_width; + mfd->total_lcd_lines = + mfd->panel_info.yres + mfd->total_porch_lines; + mfd->lcd_ref_usec_time = + 100000000 / mfd->panel_info.lcd.refx100; + mfd->vsync_handler_pending = FALSE; + mfd->last_vsync_timetick.tv.sec = 0; + mfd->last_vsync_timetick.tv.nsec = 0; + +#ifdef MDP_HW_VSYNC + if (mdp_vsync_clk == NULL) + mdp_vsync_clk = clk_get(NULL, "mdp_vsync_clk"); + + if (IS_ERR(mdp_vsync_clk)) { + printk(KERN_ERR "error: can't get mdp_vsync_clk!\n"); + mfd->use_mdp_vsync = 0; + } else + mfd->use_mdp_vsync = 1; + + if (mfd->use_mdp_vsync) { + uint32 vsync_cnt_cfg, vsync_cnt_cfg_dem; + uint32 mdp_vsync_clk_speed_hz; + + mdp_vsync_clk_speed_hz = clk_get_rate(mdp_vsync_clk); + + if (mdp_vsync_clk_speed_hz == 0) { + mfd->use_mdp_vsync = 0; + } else { + /* + * Do this calculation in 2 steps for + * rounding uint32 properly. + */ + vsync_cnt_cfg_dem = + (mfd->panel_info.lcd.refx100 * + mfd->total_lcd_lines) / 100; + vsync_cnt_cfg = + (mdp_vsync_clk_speed_hz) / + vsync_cnt_cfg_dem; + + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, + FALSE); + mdp_hw_vsync_clk_enable(mfd); + + mdp_set_sync_cfg_0(mfd, vsync_cnt_cfg); + + /* + * load the last line + 1 to be in the + * safety zone + */ + vsync_load_cnt = mfd->panel_info.yres; + + /* line counter init value at the next pulse */ + MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_INIT_VAL, + vsync_load_cnt); + + /* + * external vsync source pulse width and + * polarity flip + */ + MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_OUT_CTRL, + BIT(30) | BIT(0)); + + + /* threshold */ + MDP_OUTP(MDP_BASE + 0x200, + (vsync_above_th << 16) | + (vsync_start_th)); + + mdp_hw_vsync_clk_disable(mfd); + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, + MDP_BLOCK_POWER_OFF, FALSE); + } + } +#else + mfd->use_mdp_vsync = 0; + hrtimer_init(&mfd->dma_hrtimer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + mfd->dma_hrtimer.function = mdp_dma2_vsync_hrtimer_handler; + mfd->vsync_width_boundary = vmalloc(mfd->panel_info.xres * 4); +#endif + + mfd->channel_irq = 0; + if (mfd->panel_info.lcd.hw_vsync_mode) { + u32 vsync_gpio = mfd->vsync_gpio; + u32 ret; + + if (vsync_gpio == -1) { + MSM_FB_INFO("vsync_gpio not defined!\n"); + goto err_handle; + } + + ret = gpio_tlmm_config(GPIO_CFG + (vsync_gpio, + (mfd->use_mdp_vsync) ? 1 : 0, + GPIO_INPUT, + GPIO_PULL_DOWN, + GPIO_2MA), + GPIO_ENABLE); + if (ret) + goto err_handle; + + if (!mfd->use_mdp_vsync) { + mfd->channel_irq = MSM_GPIO_TO_INT(vsync_gpio); + if (request_irq + (mfd->channel_irq, + &mdp_hw_vsync_handler_proxy, + IRQF_TRIGGER_FALLING, "VSYNC_GPIO", + (void *)mfd)) { + MSM_FB_INFO + ("irq=%d failed! vsync_gpio=%d\n", + mfd->channel_irq, + vsync_gpio); + goto err_handle; + } + } + } + + mdp_set_vsync((unsigned long)mfd); + } + + return; + +err_handle: + if (mfd->vsync_width_boundary) + vfree(mfd->vsync_width_boundary); + mfd->panel_info.lcd.vsync_enable = FALSE; + printk(KERN_ERR "%s: failed!\n", __func__); +} + +void mdp_vsync_resync_workqueue_handler(struct work_struct *work) +{ + struct msm_fb_data_type *mfd = NULL; + int vsync_fnc_enabled = FALSE; + struct msm_fb_panel_data *pdata = NULL; + + mfd = container_of(work, struct msm_fb_data_type, vsync_resync_worker); + + if (mfd) { + if (mfd->panel_power_on) { + pdata = + (struct msm_fb_panel_data *)mfd->pdev->dev. + platform_data; + + /* + * we need to turn on MDP power if it uses MDP vsync + * HW block in SW mode + */ + if ((!mfd->panel_info.lcd.hw_vsync_mode) && + (mfd->use_mdp_vsync) && + (pdata) && (pdata->set_vsync_notifier != NULL)) { + /* + * enable pwr here since we can't enable it in + * vsync callback in isr mode + */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, + FALSE); + } + + if (pdata->set_vsync_notifier != NULL) { + vsync_fnc_enabled = TRUE; + pdata->set_vsync_notifier(mdp_vsync_handler, + (void *)mfd); + } + } + } + + if ((mfd) && (!vsync_fnc_enabled)) + mfd->vsync_handler_pending = FALSE; +} + +boolean mdp_hw_vsync_set_handler(msm_fb_vsync_handler_type handler, void *data) +{ + /* + * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt + * but getting inaccurate timing in mdp_vsync_handler() + * enable_irq(MDP_HW_VSYNC_IRQ); + */ + + return TRUE; +} + +uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd) +{ + uint32 elapsed_usec_time; + uint32 lcd_line; + ktime_t last_vsync_timetick_local; + ktime_t curr_time; + unsigned long flag; + + if ((!mfd->panel_info.lcd.vsync_enable) || (!vsync_mode)) + return 0; + + spin_lock_irqsave(&mdp_spin_lock, flag); + last_vsync_timetick_local = mfd->last_vsync_timetick; + spin_unlock_irqrestore(&mdp_spin_lock, flag); + + curr_time = ktime_get_real(); + elapsed_usec_time = + ((curr_time.tv.sec - last_vsync_timetick_local.tv.sec) * 1000000) + + ((curr_time.tv.nsec - last_vsync_timetick_local.tv.nsec) / 1000); + + elapsed_usec_time = elapsed_usec_time % mfd->lcd_ref_usec_time; + + /* lcd line calculation referencing to line counter = 0 */ + lcd_line = + (elapsed_usec_time * mfd->total_lcd_lines) / mfd->lcd_ref_usec_time; + + /* lcd line adjusment referencing to the actual line counter at vsync */ + lcd_line = + (mfd->total_lcd_lines - mfd->panel_info.lcd.v_back_porch + + lcd_line) % (mfd->total_lcd_lines + 1); + + if (lcd_line > mfd->total_lcd_lines) { + MSM_FB_INFO + ("mdp_get_lcd_line_counter: mdp_lcd_rd_cnt >= mfd->total_lcd_lines error!\n"); + } + + return lcd_line; +} diff --git a/drivers/staging/msm/memory.c b/drivers/staging/msm/memory.c new file mode 100644 index 000000000000..cc80fdf17d61 --- /dev/null +++ b/drivers/staging/msm/memory.c @@ -0,0 +1,214 @@ +/* arch/arm/mach-msm/memory.c + * + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/mm.h> +#include <linux/mm_types.h> +#include <linux/bootmem.h> +#include <linux/module.h> +#include <asm/pgtable.h> +#include <asm/io.h> +#include <asm/mach/map.h> +#include "memory_ll.h" +#include <asm/cacheflush.h> +#if defined(CONFIG_MSM_NPA_REMOTE) +#include "npa_remote.h" +#include <linux/completion.h> +#include <linux/err.h> +#endif + +int arch_io_remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, + unsigned long pfn, unsigned long size, pgprot_t prot) +{ + unsigned long pfn_addr = pfn << PAGE_SHIFT; +/* + if ((pfn_addr >= 0x88000000) && (pfn_addr < 0xD0000000)) { + prot = pgprot_device(prot); + printk("remapping device %lx\n", prot); + } +*/ + panic("Memory remap PFN stuff not done\n"); + return remap_pfn_range(vma, addr, pfn, size, prot); +} + +void *zero_page_strongly_ordered; + +static void map_zero_page_strongly_ordered(void) +{ + if (zero_page_strongly_ordered) + return; +/* + zero_page_strongly_ordered = + ioremap_strongly_ordered(page_to_pfn(empty_zero_page) + << PAGE_SHIFT, PAGE_SIZE); +*/ + panic("Strongly ordered memory functions not implemented\n"); +} + +void write_to_strongly_ordered_memory(void) +{ + map_zero_page_strongly_ordered(); + *(int *)zero_page_strongly_ordered = 0; +} +EXPORT_SYMBOL(write_to_strongly_ordered_memory); + +void flush_axi_bus_buffer(void) +{ + __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \ + : : "r" (0) : "memory"); + write_to_strongly_ordered_memory(); +} + +#define CACHE_LINE_SIZE 32 + +/* These cache related routines make the assumption that the associated + * physical memory is contiguous. They will operate on all (L1 + * and L2 if present) caches. + */ +void clean_and_invalidate_caches(unsigned long vstart, + unsigned long length, unsigned long pstart) +{ + unsigned long vaddr; + + for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE) + asm ("mcr p15, 0, %0, c7, c14, 1" : : "r" (vaddr)); +#ifdef CONFIG_OUTER_CACHE + outer_flush_range(pstart, pstart + length); +#endif + asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); + asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0)); + + flush_axi_bus_buffer(); +} + +void clean_caches(unsigned long vstart, + unsigned long length, unsigned long pstart) +{ + unsigned long vaddr; + + for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE) + asm ("mcr p15, 0, %0, c7, c10, 1" : : "r" (vaddr)); +#ifdef CONFIG_OUTER_CACHE + outer_clean_range(pstart, pstart + length); +#endif + asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); + asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0)); + + flush_axi_bus_buffer(); +} + +void invalidate_caches(unsigned long vstart, + unsigned long length, unsigned long pstart) +{ + unsigned long vaddr; + + for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE) + asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (vaddr)); +#ifdef CONFIG_OUTER_CACHE + outer_inv_range(pstart, pstart + length); +#endif + asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); + asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0)); + + flush_axi_bus_buffer(); +} + +void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment) +{ + void *unused_addr = NULL; + unsigned long addr, tmp_size, unused_size; + + /* Allocate maximum size needed, see where it ends up. + * Then free it -- in this path there are no other allocators + * so we can depend on getting the same address back + * when we allocate a smaller piece that is aligned + * at the end (if necessary) and the piece we really want, + * then free the unused first piece. + */ + + tmp_size = size + alignment - PAGE_SIZE; + addr = (unsigned long)alloc_bootmem(tmp_size); + free_bootmem(__pa(addr), tmp_size); + + unused_size = alignment - (addr % alignment); + if (unused_size) + unused_addr = alloc_bootmem(unused_size); + + addr = (unsigned long)alloc_bootmem(size); + if (unused_size) + free_bootmem(__pa(unused_addr), unused_size); + + return (void *)addr; +} + +#if defined(CONFIG_MSM_NPA_REMOTE) +struct npa_client *npa_memory_client; +#endif + +static int change_memory_power_state(unsigned long start_pfn, + unsigned long nr_pages, int state) +{ +#if defined(CONFIG_MSM_NPA_REMOTE) + static atomic_t node_created_flag = ATOMIC_INIT(1); +#else + unsigned long start; + unsigned long size; + unsigned long virtual; +#endif + int rc = 0; + +#if defined(CONFIG_MSM_NPA_REMOTE) + if (atomic_dec_and_test(&node_created_flag)) { + /* Create NPA 'required' client. */ + npa_memory_client = npa_create_sync_client(NPA_MEMORY_NODE_NAME, + "memory node", NPA_CLIENT_REQUIRED); + if (IS_ERR(npa_memory_client)) { + rc = PTR_ERR(npa_memory_client); + return rc; + } + } + + rc = npa_issue_required_request(npa_memory_client, state); +#else + if (state == MEMORY_DEEP_POWERDOWN) { + /* simulate turning off memory by writing bit pattern into it */ + start = start_pfn << PAGE_SHIFT; + size = nr_pages << PAGE_SHIFT; + virtual = __phys_to_virt(start); + memset((void *)virtual, 0x27, size); + } +#endif + return rc; +} + +int platform_physical_remove_pages(unsigned long start_pfn, + unsigned long nr_pages) +{ + return change_memory_power_state(start_pfn, nr_pages, + MEMORY_DEEP_POWERDOWN); +} + +int platform_physical_add_pages(unsigned long start_pfn, + unsigned long nr_pages) +{ + return change_memory_power_state(start_pfn, nr_pages, MEMORY_ACTIVE); +} + +int platform_physical_low_power_pages(unsigned long start_pfn, + unsigned long nr_pages) +{ + return change_memory_power_state(start_pfn, nr_pages, + MEMORY_SELF_REFRESH); +} diff --git a/drivers/staging/msm/memory_ll.h b/drivers/staging/msm/memory_ll.h new file mode 100644 index 000000000000..18a239a89a78 --- /dev/null +++ b/drivers/staging/msm/memory_ll.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef __ASM_ARCH_MEMORY_LL_H +#define __ASM_ARCH_MEMORY_LL_H + +#define MAX_PHYSMEM_BITS 32 +#define SECTION_SIZE_BITS 25 + +#define HAS_ARCH_IO_REMAP_PFN_RANGE + +#ifndef __ASSEMBLY__ +void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment); +void clean_and_invalidate_caches(unsigned long, unsigned long, unsigned long); +void clean_caches(unsigned long, unsigned long, unsigned long); +void invalidate_caches(unsigned long, unsigned long, unsigned long); +int platform_physical_remove_pages(unsigned long, unsigned long); +int platform_physical_add_pages(unsigned long, unsigned long); +int platform_physical_low_power_pages(unsigned long, unsigned long); + +#ifdef CONFIG_ARCH_MSM_ARM11 +void write_to_strongly_ordered_memory(void); + +#include <asm/mach-types.h> + +#define arch_barrier_extra() do \ + { if (machine_is_msm7x27_surf() || machine_is_msm7x27_ffa()) \ + write_to_strongly_ordered_memory(); \ + } while (0) +#endif + +#ifdef CONFIG_CACHE_L2X0 +extern void l2x0_cache_sync(void); +#define finish_arch_switch(prev) do { l2x0_cache_sync(); } while (0) +#endif + +#endif + +#ifdef CONFIG_ARCH_MSM_SCORPION +#define arch_has_speculative_dfetch() 1 +#endif + +#endif + +/* these correspond to values known by the modem */ +#define MEMORY_DEEP_POWERDOWN 0 +#define MEMORY_SELF_REFRESH 1 +#define MEMORY_ACTIVE 2 + +#define NPA_MEMORY_NODE_NAME "/mem/ebi1/cs1" diff --git a/drivers/staging/msm/msm_fb.c b/drivers/staging/msm/msm_fb.c new file mode 100644 index 000000000000..af5620e4eee1 --- /dev/null +++ b/drivers/staging/msm/msm_fb.c @@ -0,0 +1,2354 @@ +/* + * + * Core MSM framebuffer driver. + * + * Copyright (C) 2007 Google Incorporated + * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/mm.h> +#include <linux/fb.h> +#include "msm_mdp.h" +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> +#include <mach/board.h> +#include <linux/uaccess.h> + +#include <linux/workqueue.h> +#include <linux/string.h> +#include <linux/version.h> +#include <linux/proc_fs.h> +#include <linux/vmalloc.h> +#include <linux/debugfs.h> +#include <linux/console.h> +#include <linux/leds.h> +#include <asm/dma-mapping.h> + + +#define MSM_FB_C +#include "msm_fb.h" +#include "mddihosti.h" +#include "tvenc.h" +#include "mdp.h" +#include "mdp4.h" + +#ifdef CONFIG_FB_MSM_LOGO +#define INIT_IMAGE_FILE "/logo.rle" +extern int load_565rle_image(char *filename); +#endif + + +#define pgprot_noncached(prot) \ + __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED) +#define pgprot_writecombine(prot) \ + __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE) +#define pgprot_device(prot) \ + __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_DEV_NONSHARED) +#define pgprot_writethroughcache(prot) \ + __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITETHROUGH) +#define pgprot_writebackcache(prot) \ + __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEBACK) +#define pgprot_writebackwacache(prot) \ + __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEALLOC) + +static unsigned char *fbram; +static unsigned char *fbram_phys; +static int fbram_size; + +static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; +static int pdev_list_cnt; + +int vsync_mode = 1; + +#define MAX_FBI_LIST 32 +static struct fb_info *fbi_list[MAX_FBI_LIST]; +static int fbi_list_index; + +static struct msm_fb_data_type *mfd_list[MAX_FBI_LIST]; +static int mfd_list_index; + +static u32 msm_fb_pseudo_palette[16] = { + 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff +}; + +u32 msm_fb_debug_enabled; +/* Setting msm_fb_msg_level to 8 prints out ALL messages */ +u32 msm_fb_msg_level = 7; + +/* Setting mddi_msg_level to 8 prints out ALL messages */ +u32 mddi_msg_level = 5; + +extern int32 mdp_block_power_cnt[MDP_MAX_BLOCK]; +extern unsigned long mdp_timer_duration; + +static int msm_fb_register(struct msm_fb_data_type *mfd); +static int msm_fb_open(struct fb_info *info, int user); +static int msm_fb_release(struct fb_info *info, int user); +static int msm_fb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info); +static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd); +int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd); +static int msm_fb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info); +static int msm_fb_set_par(struct fb_info *info); +static int msm_fb_blank_sub(int blank_mode, struct fb_info *info, + boolean op_enable); +static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd); +static int msm_fb_resume_sub(struct msm_fb_data_type *mfd); +static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg); +static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma); + +#ifdef MSM_FB_ENABLE_DBGFS + +#define MSM_FB_MAX_DBGFS 1024 +#define MAX_BACKLIGHT_BRIGHTNESS 255 + +int msm_fb_debugfs_file_index; +struct dentry *msm_fb_debugfs_root; +struct dentry *msm_fb_debugfs_file[MSM_FB_MAX_DBGFS]; + +struct dentry *msm_fb_get_debugfs_root(void) +{ + if (msm_fb_debugfs_root == NULL) + msm_fb_debugfs_root = debugfs_create_dir("msm_fb", NULL); + + return msm_fb_debugfs_root; +} + +void msm_fb_debugfs_file_create(struct dentry *root, const char *name, + u32 *var) +{ + if (msm_fb_debugfs_file_index >= MSM_FB_MAX_DBGFS) + return; + + msm_fb_debugfs_file[msm_fb_debugfs_file_index++] = + debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var); +} +#endif + +int msm_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + + if (!mfd->cursor_update) + return -ENODEV; + + return mfd->cursor_update(info, cursor); +} + +static int msm_fb_resource_initialized; + +#ifndef CONFIG_FB_BACKLIGHT +static int lcd_backlight_registered; + +static void msm_fb_set_bl_brightness(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent); + int bl_lvl; + + if (value > MAX_BACKLIGHT_BRIGHTNESS) + value = MAX_BACKLIGHT_BRIGHTNESS; + + /* This maps android backlight level 0 to 255 into + driver backlight level 0 to bl_max with rounding */ + bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS) + /(2 * MAX_BACKLIGHT_BRIGHTNESS); + + if (!bl_lvl && value) + bl_lvl = 1; + + msm_fb_set_backlight(mfd, bl_lvl, 1); +} + +static struct led_classdev backlight_led = { + .name = "lcd-backlight", + .brightness = MAX_BACKLIGHT_BRIGHTNESS, + .brightness_set = msm_fb_set_bl_brightness, +}; +#endif + +static struct msm_fb_platform_data *msm_fb_pdata; + +int msm_fb_detect_client(const char *name) +{ + int ret = -EPERM; +#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT + u32 id; +#endif + + if (msm_fb_pdata && msm_fb_pdata->detect_client) { + ret = msm_fb_pdata->detect_client(name); + + /* if it's non mddi panel, we need to pre-scan + mddi client to see if we can disable mddi host */ + +#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT + if (!ret && msm_fb_pdata->mddi_prescan) + id = mddi_get_client_id(); +#endif + } + + return ret; +} + +static int msm_fb_probe(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd; + int rc; + + MSM_FB_DEBUG("msm_fb_probe\n"); + + if ((pdev->id == 0) && (pdev->num_resources > 0)) { + msm_fb_pdata = pdev->dev.platform_data; + fbram_size = + pdev->resource[0].end - pdev->resource[0].start + 1; + fbram_phys = (char *)pdev->resource[0].start; + fbram = ioremap((unsigned long)fbram_phys, fbram_size); + + if (!fbram) { + printk(KERN_ERR "fbram ioremap failed!\n"); + return -ENOMEM; + } + MSM_FB_INFO("msm_fb_probe: phy_Addr = 0x%x virt = 0x%x\n", + (int)fbram_phys, (int)fbram); + + msm_fb_resource_initialized = 1; + return 0; + } + + if (!msm_fb_resource_initialized) + return -EPERM; + + mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); + + if (!mfd) + return -ENODEV; + + if (mfd->key != MFD_KEY) + return -EINVAL; + + if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) + return -ENOMEM; + + mfd->panel_info.frame_count = 0; + mfd->bl_level = mfd->panel_info.bl_max; + + if (mfd->panel_info.type == LCDC_PANEL) + mfd->allow_set_offset = + msm_fb_pdata->allow_set_offset != NULL ? + msm_fb_pdata->allow_set_offset() : 0; + else + mfd->allow_set_offset = 0; + + rc = msm_fb_register(mfd); + if (rc) + return rc; + +#ifdef CONFIG_FB_BACKLIGHT + msm_fb_config_backlight(mfd); +#else + /* android supports only one lcd-backlight/lcd for now */ + if (!lcd_backlight_registered) { + if (led_classdev_register(&pdev->dev, &backlight_led)) + printk(KERN_ERR "led_classdev_register failed\n"); + else + lcd_backlight_registered = 1; + } +#endif + + pdev_list[pdev_list_cnt++] = pdev; + return 0; +} + +static int msm_fb_remove(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd; + + MSM_FB_DEBUG("msm_fb_remove\n"); + + mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); + + if (!mfd) + return -ENODEV; + + if (mfd->key != MFD_KEY) + return -EINVAL; + + if (msm_fb_suspend_sub(mfd)) + printk(KERN_ERR "msm_fb_remove: can't stop the device %d\n", mfd->index); + + if (mfd->channel_irq != 0) + free_irq(mfd->channel_irq, (void *)mfd); + + if (mfd->vsync_width_boundary) + vfree(mfd->vsync_width_boundary); + + if (mfd->vsync_resync_timer.function) + del_timer(&mfd->vsync_resync_timer); + + if (mfd->refresh_timer.function) + del_timer(&mfd->refresh_timer); + + if (mfd->dma_hrtimer.function) + hrtimer_cancel(&mfd->dma_hrtimer); + + /* remove /dev/fb* */ + unregister_framebuffer(mfd->fbi); + +#ifdef CONFIG_FB_BACKLIGHT + /* remove /sys/class/backlight */ + backlight_device_unregister(mfd->fbi->bl_dev); +#else + if (lcd_backlight_registered) { + lcd_backlight_registered = 0; + led_classdev_unregister(&backlight_led); + } +#endif + +#ifdef MSM_FB_ENABLE_DBGFS + if (mfd->sub_dir) + debugfs_remove(mfd->sub_dir); +#endif + + return 0; +} + +#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND) +static int msm_fb_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct msm_fb_data_type *mfd; + int ret = 0; + + MSM_FB_DEBUG("msm_fb_suspend\n"); + + mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); + + if ((!mfd) || (mfd->key != MFD_KEY)) + return 0; + + acquire_console_sem(); + fb_set_suspend(mfd->fbi, 1); + + ret = msm_fb_suspend_sub(mfd); + if (ret != 0) { + printk(KERN_ERR "msm_fb: failed to suspend! %d\n", ret); + fb_set_suspend(mfd->fbi, 0); + } else { + pdev->dev.power.power_state = state; + } + + release_console_sem(); + return ret; +} +#else +#define msm_fb_suspend NULL +#endif + +static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd) +{ + int ret = 0; + + if ((!mfd) || (mfd->key != MFD_KEY)) + return 0; + + /* + * suspend this channel + */ + mfd->suspend.sw_refreshing_enable = mfd->sw_refreshing_enable; + mfd->suspend.op_enable = mfd->op_enable; + mfd->suspend.panel_power_on = mfd->panel_power_on; + + if (mfd->op_enable) { + ret = + msm_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi, + mfd->suspend.op_enable); + if (ret) { + MSM_FB_INFO + ("msm_fb_suspend: can't turn off display!\n"); + return ret; + } + mfd->op_enable = FALSE; + } + /* + * try to power down + */ + mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + + /* + * detach display channel irq if there's any + * or wait until vsync-resync completes + */ + if ((mfd->dest == DISPLAY_LCD)) { + if (mfd->panel_info.lcd.vsync_enable) { + if (mfd->panel_info.lcd.hw_vsync_mode) { + if (mfd->channel_irq != 0) + disable_irq(mfd->channel_irq); + } else { + volatile boolean vh_pending; + do { + vh_pending = mfd->vsync_handler_pending; + } while (vh_pending); + } + } + } + + return 0; +} + +#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND) +static int msm_fb_resume(struct platform_device *pdev) +{ + /* This resume function is called when interrupt is enabled. + */ + int ret = 0; + struct msm_fb_data_type *mfd; + + MSM_FB_DEBUG("msm_fb_resume\n"); + + mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); + + if ((!mfd) || (mfd->key != MFD_KEY)) + return 0; + + acquire_console_sem(); + ret = msm_fb_resume_sub(mfd); + pdev->dev.power.power_state = PMSG_ON; + fb_set_suspend(mfd->fbi, 1); + release_console_sem(); + + return ret; +} +#else +#define msm_fb_resume NULL +#endif + +static int msm_fb_resume_sub(struct msm_fb_data_type *mfd) +{ + int ret = 0; + + if ((!mfd) || (mfd->key != MFD_KEY)) + return 0; + + /* attach display channel irq if there's any */ + if (mfd->channel_irq != 0) + enable_irq(mfd->channel_irq); + + /* resume state var recover */ + mfd->sw_refreshing_enable = mfd->suspend.sw_refreshing_enable; + mfd->op_enable = mfd->suspend.op_enable; + + if (mfd->suspend.panel_power_on) { + ret = + msm_fb_blank_sub(FB_BLANK_UNBLANK, mfd->fbi, + mfd->op_enable); + if (ret) + MSM_FB_INFO("msm_fb_resume: can't turn on display!\n"); + } + + return ret; +} + +static struct platform_driver msm_fb_driver = { + .probe = msm_fb_probe, + .remove = msm_fb_remove, +#ifndef CONFIG_HAS_EARLYSUSPEND + .suspend = msm_fb_suspend, + .resume = msm_fb_resume, +#endif + .shutdown = NULL, + .driver = { + /* Driver name must match the device name added in platform.c. */ + .name = "msm_fb", + }, +}; + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void msmfb_early_suspend(struct early_suspend *h) +{ + struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, + early_suspend); + msm_fb_suspend_sub(mfd); +} + +static void msmfb_early_resume(struct early_suspend *h) +{ + struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, + early_suspend); + msm_fb_resume_sub(mfd); +} +#endif + +void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl, u32 save) +{ + struct msm_fb_panel_data *pdata; + + pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; + + if ((pdata) && (pdata->set_backlight)) { + down(&mfd->sem); + if ((bkl_lvl != mfd->bl_level) || (!save)) { + u32 old_lvl; + + old_lvl = mfd->bl_level; + mfd->bl_level = bkl_lvl; + pdata->set_backlight(mfd); + + if (!save) + mfd->bl_level = old_lvl; + } + up(&mfd->sem); + } +} + +static int msm_fb_blank_sub(int blank_mode, struct fb_info *info, + boolean op_enable) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + struct msm_fb_panel_data *pdata = NULL; + int ret = 0; + + if (!op_enable) + return -EPERM; + + pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; + if ((!pdata) || (!pdata->on) || (!pdata->off)) { + printk(KERN_ERR "msm_fb_blank_sub: no panel operation detected!\n"); + return -ENODEV; + } + + switch (blank_mode) { + case FB_BLANK_UNBLANK: + if (!mfd->panel_power_on) { + mdelay(100); + ret = pdata->on(mfd->pdev); + if (ret == 0) { + mfd->panel_power_on = TRUE; + + msm_fb_set_backlight(mfd, + mfd->bl_level, 0); + +/* ToDo: possible conflict with android which doesn't expect sw refresher */ +/* + if (!mfd->hw_refresh) + { + if ((ret = msm_fb_resume_sw_refresher(mfd)) != 0) + { + MSM_FB_INFO("msm_fb_blank_sub: msm_fb_resume_sw_refresher failed = %d!\n",ret); + } + } +*/ + } + } + break; + + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_NORMAL: + case FB_BLANK_POWERDOWN: + default: + if (mfd->panel_power_on) { + int curr_pwr_state; + + mfd->op_enable = FALSE; + curr_pwr_state = mfd->panel_power_on; + mfd->panel_power_on = FALSE; + + mdelay(100); + ret = pdata->off(mfd->pdev); + if (ret) + mfd->panel_power_on = curr_pwr_state; + + msm_fb_set_backlight(mfd, 0, 0); + mfd->op_enable = TRUE; + } + break; + } + + return ret; +} + +static void msm_fb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + + cfb_fillrect(info, rect); + if (!mfd->hw_refresh && (info->var.yoffset == 0) && + !mfd->sw_currently_refreshing) { + struct fb_var_screeninfo var; + + var = info->var; + var.reserved[0] = 0x54445055; + var.reserved[1] = (rect->dy << 16) | (rect->dx); + var.reserved[2] = ((rect->dy + rect->height) << 16) | + (rect->dx + rect->width); + + msm_fb_pan_display(&var, info); + } +} + +static void msm_fb_copyarea(struct fb_info *info, + const struct fb_copyarea *area) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + + cfb_copyarea(info, area); + if (!mfd->hw_refresh && (info->var.yoffset == 0) && + !mfd->sw_currently_refreshing) { + struct fb_var_screeninfo var; + + var = info->var; + var.reserved[0] = 0x54445055; + var.reserved[1] = (area->dy << 16) | (area->dx); + var.reserved[2] = ((area->dy + area->height) << 16) | + (area->dx + area->width); + + msm_fb_pan_display(&var, info); + } +} + +static void msm_fb_imageblit(struct fb_info *info, const struct fb_image *image) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + + cfb_imageblit(info, image); + if (!mfd->hw_refresh && (info->var.yoffset == 0) && + !mfd->sw_currently_refreshing) { + struct fb_var_screeninfo var; + + var = info->var; + var.reserved[0] = 0x54445055; + var.reserved[1] = (image->dy << 16) | (image->dx); + var.reserved[2] = ((image->dy + image->height) << 16) | + (image->dx + image->width); + + msm_fb_pan_display(&var, info); + } +} + +static int msm_fb_blank(int blank_mode, struct fb_info *info) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + return msm_fb_blank_sub(blank_mode, info, mfd->op_enable); +} + +static int msm_fb_set_lut(struct fb_cmap *cmap, struct fb_info *info) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + + if (!mfd->lut_update) + return -ENODEV; + + mfd->lut_update(info, cmap); + return 0; +} + +/* + * Custom Framebuffer mmap() function for MSM driver. + * Differs from standard mmap() function by allowing for customized + * page-protection. + */ +static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma) +{ + /* Get frame buffer memory range. */ + unsigned long start = info->fix.smem_start; + u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); + unsigned long off = vma->vm_pgoff << PAGE_SHIFT; + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + if (off >= len) { + /* memory mapped io */ + off -= len; + if (info->var.accel_flags) { + mutex_unlock(&info->lock); + return -EINVAL; + } + start = info->fix.mmio_start; + len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); + } + + /* Set VM flags. */ + start &= PAGE_MASK; + if ((vma->vm_end - vma->vm_start + off) > len) + return -EINVAL; + off += start; + vma->vm_pgoff = off >> PAGE_SHIFT; + /* This is an IO map - tell maydump to skip this VMA */ + vma->vm_flags |= VM_IO | VM_RESERVED; + + /* Set VM page protection */ + if (mfd->mdp_fb_page_protection == MDP_FB_PAGE_PROTECTION_WRITECOMBINE) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + else if (mfd->mdp_fb_page_protection == + MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE) + vma->vm_page_prot = pgprot_writethroughcache(vma->vm_page_prot); + else if (mfd->mdp_fb_page_protection == + MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE) + vma->vm_page_prot = pgprot_writebackcache(vma->vm_page_prot); + else if (mfd->mdp_fb_page_protection == + MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE) + vma->vm_page_prot = pgprot_writebackwacache(vma->vm_page_prot); + else + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + /* Remap the frame buffer I/O range */ + if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) + return -EAGAIN; + + return 0; +} + +static struct fb_ops msm_fb_ops = { + .owner = THIS_MODULE, + .fb_open = msm_fb_open, + .fb_release = msm_fb_release, + .fb_read = NULL, + .fb_write = NULL, + .fb_cursor = NULL, + .fb_check_var = msm_fb_check_var, /* vinfo check */ + .fb_set_par = msm_fb_set_par, /* set the video mode according to info->var */ + .fb_setcolreg = NULL, /* set color register */ + .fb_blank = msm_fb_blank, /* blank display */ + .fb_pan_display = msm_fb_pan_display, /* pan display */ + .fb_fillrect = msm_fb_fillrect, /* Draws a rectangle */ + .fb_copyarea = msm_fb_copyarea, /* Copy data from area to another */ + .fb_imageblit = msm_fb_imageblit, /* Draws a image to the display */ + .fb_rotate = NULL, + .fb_sync = NULL, /* wait for blit idle, optional */ + .fb_ioctl = msm_fb_ioctl, /* perform fb specific ioctl (optional) */ + .fb_mmap = msm_fb_mmap, +}; + +static int msm_fb_register(struct msm_fb_data_type *mfd) +{ + int ret = -ENODEV; + int bpp; + struct msm_panel_info *panel_info = &mfd->panel_info; + struct fb_info *fbi = mfd->fbi; + struct fb_fix_screeninfo *fix; + struct fb_var_screeninfo *var; + int *id; + int fbram_offset; + + /* + * fb info initialization + */ + fix = &fbi->fix; + var = &fbi->var; + + fix->type_aux = 0; /* if type == FB_TYPE_INTERLEAVED_PLANES */ + fix->visual = FB_VISUAL_TRUECOLOR; /* True Color */ + fix->ywrapstep = 0; /* No support */ + fix->mmio_start = 0; /* No MMIO Address */ + fix->mmio_len = 0; /* No MMIO Address */ + fix->accel = FB_ACCEL_NONE;/* FB_ACCEL_MSM needes to be added in fb.h */ + + var->xoffset = 0, /* Offset from virtual to visible */ + var->yoffset = 0, /* resolution */ + var->grayscale = 0, /* No graylevels */ + var->nonstd = 0, /* standard pixel format */ + var->activate = FB_ACTIVATE_VBL, /* activate it at vsync */ + var->height = -1, /* height of picture in mm */ + var->width = -1, /* width of picture in mm */ + var->accel_flags = 0, /* acceleration flags */ + var->sync = 0, /* see FB_SYNC_* */ + var->rotate = 0, /* angle we rotate counter clockwise */ + mfd->op_enable = FALSE; + + switch (mfd->fb_imgType) { + case MDP_RGB_565: + fix->type = FB_TYPE_PACKED_PIXELS; + fix->xpanstep = 1; + fix->ypanstep = 1; + var->vmode = FB_VMODE_NONINTERLACED; + var->blue.offset = 0; + var->green.offset = 5; + var->red.offset = 11; + var->blue.length = 5; + var->green.length = 6; + var->red.length = 5; + var->blue.msb_right = 0; + var->green.msb_right = 0; + var->red.msb_right = 0; + var->transp.offset = 0; + var->transp.length = 0; + bpp = 2; + break; + + case MDP_RGB_888: + fix->type = FB_TYPE_PACKED_PIXELS; + fix->xpanstep = 1; + fix->ypanstep = 1; + var->vmode = FB_VMODE_NONINTERLACED; + var->blue.offset = 0; + var->green.offset = 8; + var->red.offset = 16; + var->blue.length = 8; + var->green.length = 8; + var->red.length = 8; + var->blue.msb_right = 0; + var->green.msb_right = 0; + var->red.msb_right = 0; + var->transp.offset = 0; + var->transp.length = 0; + bpp = 3; + break; + + case MDP_ARGB_8888: + fix->type = FB_TYPE_PACKED_PIXELS; + fix->xpanstep = 1; + fix->ypanstep = 1; + var->vmode = FB_VMODE_NONINTERLACED; + var->blue.offset = 0; + var->green.offset = 8; + var->red.offset = 16; + var->blue.length = 8; + var->green.length = 8; + var->red.length = 8; + var->blue.msb_right = 0; + var->green.msb_right = 0; + var->red.msb_right = 0; + var->transp.offset = 24; + var->transp.length = 8; + bpp = 3; + break; + + case MDP_YCRYCB_H2V1: + /* ToDo: need to check TV-Out YUV422i framebuffer format */ + /* we might need to create new type define */ + fix->type = FB_TYPE_INTERLEAVED_PLANES; + fix->xpanstep = 2; + fix->ypanstep = 1; + var->vmode = FB_VMODE_NONINTERLACED; + + /* how about R/G/B offset? */ + var->blue.offset = 0; + var->green.offset = 5; + var->red.offset = 11; + var->blue.length = 5; + var->green.length = 6; + var->red.length = 5; + var->blue.msb_right = 0; + var->green.msb_right = 0; + var->red.msb_right = 0; + var->transp.offset = 0; + var->transp.length = 0; + bpp = 2; + break; + + default: + MSM_FB_ERR("msm_fb_init: fb %d unkown image type!\n", + mfd->index); + return ret; + } + + /* The adreno GPU hardware requires that the pitch be aligned to + 32 pixels for color buffers, so for the cases where the GPU + is writing directly to fb0, the framebuffer pitch + also needs to be 32 pixel aligned */ + + if (mfd->index == 0) + fix->line_length = ALIGN(panel_info->xres * bpp, 32); + else + fix->line_length = panel_info->xres * bpp; + + fix->smem_len = fix->line_length * panel_info->yres * mfd->fb_page; + + mfd->var_xres = panel_info->xres; + mfd->var_yres = panel_info->yres; + + var->pixclock = mfd->panel_info.clk_rate; + mfd->var_pixclock = var->pixclock; + + var->xres = panel_info->xres; + var->yres = panel_info->yres; + var->xres_virtual = panel_info->xres; + var->yres_virtual = panel_info->yres * mfd->fb_page; + var->bits_per_pixel = bpp * 8, /* FrameBuffer color depth */ + /* + * id field for fb app + */ + id = (int *)&mfd->panel; + +#if defined(CONFIG_FB_MSM_MDP22) + snprintf(fix->id, sizeof(fix->id), "msmfb22_%x", (__u32) *id); +#elif defined(CONFIG_FB_MSM_MDP30) + snprintf(fix->id, sizeof(fix->id), "msmfb30_%x", (__u32) *id); +#elif defined(CONFIG_FB_MSM_MDP31) + snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id); +#elif defined(CONFIG_FB_MSM_MDP40) + snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id); +#else + error CONFIG_FB_MSM_MDP undefined ! +#endif + fbi->fbops = &msm_fb_ops; + fbi->flags = FBINFO_FLAG_DEFAULT; + fbi->pseudo_palette = msm_fb_pseudo_palette; + + mfd->ref_cnt = 0; + mfd->sw_currently_refreshing = FALSE; + mfd->sw_refreshing_enable = TRUE; + mfd->panel_power_on = FALSE; + + mfd->pan_waiting = FALSE; + init_completion(&mfd->pan_comp); + init_completion(&mfd->refresher_comp); + init_MUTEX(&mfd->sem); + + fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram; + fbram += fbram_offset; + fbram_phys += fbram_offset; + fbram_size -= fbram_offset; + + if (fbram_size < fix->smem_len) { + printk(KERN_ERR "error: no more framebuffer memory!\n"); + return -ENOMEM; + } + + fbi->screen_base = fbram; + fbi->fix.smem_start = (unsigned long)fbram_phys; + + memset(fbi->screen_base, 0x0, fix->smem_len); + + mfd->op_enable = TRUE; + mfd->panel_power_on = FALSE; + + /* cursor memory allocation */ + if (mfd->cursor_update) { + mfd->cursor_buf = dma_alloc_coherent(NULL, + MDP_CURSOR_SIZE, + (dma_addr_t *) &mfd->cursor_buf_phys, + GFP_KERNEL); + if (!mfd->cursor_buf) + mfd->cursor_update = 0; + } + + if (mfd->lut_update) { + ret = fb_alloc_cmap(&fbi->cmap, 256, 0); + if (ret) + printk(KERN_ERR "%s: fb_alloc_cmap() failed!\n", + __func__); + } + + if (register_framebuffer(fbi) < 0) { + if (mfd->lut_update) + fb_dealloc_cmap(&fbi->cmap); + + if (mfd->cursor_buf) + dma_free_coherent(NULL, + MDP_CURSOR_SIZE, + mfd->cursor_buf, + (dma_addr_t) mfd->cursor_buf_phys); + + mfd->op_enable = FALSE; + return -EPERM; + } + + fbram += fix->smem_len; + fbram_phys += fix->smem_len; + fbram_size -= fix->smem_len; + + MSM_FB_INFO + ("FrameBuffer[%d] %dx%d size=%d bytes is registered successfully!\n", + mfd->index, fbi->var.xres, fbi->var.yres, fbi->fix.smem_len); + +#ifdef CONFIG_FB_MSM_LOGO + if (!load_565rle_image(INIT_IMAGE_FILE)) ; /* Flip buffer */ +#endif + ret = 0; + +#ifdef CONFIG_HAS_EARLYSUSPEND + mfd->early_suspend.suspend = msmfb_early_suspend; + mfd->early_suspend.resume = msmfb_early_resume; + mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2; + register_early_suspend(&mfd->early_suspend); +#endif + +#ifdef MSM_FB_ENABLE_DBGFS + { + struct dentry *root; + struct dentry *sub_dir; + char sub_name[2]; + + root = msm_fb_get_debugfs_root(); + if (root != NULL) { + sub_name[0] = (char)(mfd->index + 0x30); + sub_name[1] = '\0'; + sub_dir = debugfs_create_dir(sub_name, root); + } else { + sub_dir = NULL; + } + + mfd->sub_dir = sub_dir; + + if (sub_dir) { + msm_fb_debugfs_file_create(sub_dir, "op_enable", + (u32 *) &mfd->op_enable); + msm_fb_debugfs_file_create(sub_dir, "panel_power_on", + (u32 *) &mfd-> + panel_power_on); + msm_fb_debugfs_file_create(sub_dir, "ref_cnt", + (u32 *) &mfd->ref_cnt); + msm_fb_debugfs_file_create(sub_dir, "fb_imgType", + (u32 *) &mfd->fb_imgType); + msm_fb_debugfs_file_create(sub_dir, + "sw_currently_refreshing", + (u32 *) &mfd-> + sw_currently_refreshing); + msm_fb_debugfs_file_create(sub_dir, + "sw_refreshing_enable", + (u32 *) &mfd-> + sw_refreshing_enable); + + msm_fb_debugfs_file_create(sub_dir, "xres", + (u32 *) &mfd->panel_info. + xres); + msm_fb_debugfs_file_create(sub_dir, "yres", + (u32 *) &mfd->panel_info. + yres); + msm_fb_debugfs_file_create(sub_dir, "bpp", + (u32 *) &mfd->panel_info. + bpp); + msm_fb_debugfs_file_create(sub_dir, "type", + (u32 *) &mfd->panel_info. + type); + msm_fb_debugfs_file_create(sub_dir, "wait_cycle", + (u32 *) &mfd->panel_info. + wait_cycle); + msm_fb_debugfs_file_create(sub_dir, "pdest", + (u32 *) &mfd->panel_info. + pdest); + msm_fb_debugfs_file_create(sub_dir, "backbuff", + (u32 *) &mfd->panel_info. + fb_num); + msm_fb_debugfs_file_create(sub_dir, "clk_rate", + (u32 *) &mfd->panel_info. + clk_rate); + msm_fb_debugfs_file_create(sub_dir, "frame_count", + (u32 *) &mfd->panel_info. + frame_count); + + + switch (mfd->dest) { + case DISPLAY_LCD: + msm_fb_debugfs_file_create(sub_dir, + "vsync_enable", + (u32 *)&mfd->panel_info.lcd.vsync_enable); + msm_fb_debugfs_file_create(sub_dir, + "refx100", + (u32 *) &mfd->panel_info.lcd. refx100); + msm_fb_debugfs_file_create(sub_dir, + "v_back_porch", + (u32 *) &mfd->panel_info.lcd.v_back_porch); + msm_fb_debugfs_file_create(sub_dir, + "v_front_porch", + (u32 *) &mfd->panel_info.lcd.v_front_porch); + msm_fb_debugfs_file_create(sub_dir, + "v_pulse_width", + (u32 *) &mfd->panel_info.lcd.v_pulse_width); + msm_fb_debugfs_file_create(sub_dir, + "hw_vsync_mode", + (u32 *) &mfd->panel_info.lcd.hw_vsync_mode); + msm_fb_debugfs_file_create(sub_dir, + "vsync_notifier_period", (u32 *) + &mfd->panel_info.lcd.vsync_notifier_period); + break; + + case DISPLAY_LCDC: + msm_fb_debugfs_file_create(sub_dir, + "h_back_porch", + (u32 *) &mfd->panel_info.lcdc.h_back_porch); + msm_fb_debugfs_file_create(sub_dir, + "h_front_porch", + (u32 *) &mfd->panel_info.lcdc.h_front_porch); + msm_fb_debugfs_file_create(sub_dir, + "h_pulse_width", + (u32 *) &mfd->panel_info.lcdc.h_pulse_width); + msm_fb_debugfs_file_create(sub_dir, + "v_back_porch", + (u32 *) &mfd->panel_info.lcdc.v_back_porch); + msm_fb_debugfs_file_create(sub_dir, + "v_front_porch", + (u32 *) &mfd->panel_info.lcdc.v_front_porch); + msm_fb_debugfs_file_create(sub_dir, + "v_pulse_width", + (u32 *) &mfd->panel_info.lcdc.v_pulse_width); + msm_fb_debugfs_file_create(sub_dir, + "border_clr", + (u32 *) &mfd->panel_info.lcdc.border_clr); + msm_fb_debugfs_file_create(sub_dir, + "underflow_clr", + (u32 *) &mfd->panel_info.lcdc.underflow_clr); + msm_fb_debugfs_file_create(sub_dir, + "hsync_skew", + (u32 *) &mfd->panel_info.lcdc.hsync_skew); + break; + + default: + break; + } + } + } +#endif /* MSM_FB_ENABLE_DBGFS */ + + return ret; +} + +static int msm_fb_open(struct fb_info *info, int user) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + + if (!mfd->ref_cnt) { + mdp_set_dma_pan_info(info, NULL, TRUE); + + if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) { + printk(KERN_ERR "msm_fb_open: can't turn on display!\n"); + return -1; + } + } + + mfd->ref_cnt++; + return 0; +} + +static int msm_fb_release(struct fb_info *info, int user) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + int ret = 0; + + if (!mfd->ref_cnt) { + MSM_FB_INFO("msm_fb_release: try to close unopened fb %d!\n", + mfd->index); + return -EINVAL; + } + + mfd->ref_cnt--; + + if (!mfd->ref_cnt) { + if ((ret = + msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, + mfd->op_enable)) != 0) { + printk(KERN_ERR "msm_fb_release: can't turn off display!\n"); + return ret; + } + } + + return ret; +} + +DECLARE_MUTEX(msm_fb_pan_sem); + +static int msm_fb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct mdp_dirty_region dirty; + struct mdp_dirty_region *dirtyPtr = NULL; + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + + if ((!mfd->op_enable) || (!mfd->panel_power_on)) + return -EPERM; + + if (var->xoffset > (info->var.xres_virtual - info->var.xres)) + return -EINVAL; + + if (var->yoffset > (info->var.yres_virtual - info->var.yres)) + return -EINVAL; + + if (info->fix.xpanstep) + info->var.xoffset = + (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep; + + if (info->fix.ypanstep) + info->var.yoffset = + (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep; + + /* "UPDT" */ + if (var->reserved[0] == 0x54445055) { + dirty.xoffset = var->reserved[1] & 0xffff; + dirty.yoffset = (var->reserved[1] >> 16) & 0xffff; + + if ((var->reserved[2] & 0xffff) <= dirty.xoffset) + return -EINVAL; + if (((var->reserved[2] >> 16) & 0xffff) <= dirty.yoffset) + return -EINVAL; + + dirty.width = (var->reserved[2] & 0xffff) - dirty.xoffset; + dirty.height = + ((var->reserved[2] >> 16) & 0xffff) - dirty.yoffset; + info->var.yoffset = var->yoffset; + + if (dirty.xoffset < 0) + return -EINVAL; + + if (dirty.yoffset < 0) + return -EINVAL; + + if ((dirty.xoffset + dirty.width) > info->var.xres) + return -EINVAL; + + if ((dirty.yoffset + dirty.height) > info->var.yres) + return -EINVAL; + + if ((dirty.width <= 0) || (dirty.height <= 0)) + return -EINVAL; + + dirtyPtr = &dirty; + } + + /* Flip */ + /* A constant value is used to indicate that we should change the DMA + output buffer instead of just panning */ + + if (var->reserved[0] == 0x466c6970) { + unsigned long length, address; + struct file *p_src_file; + struct mdp_img imgdata; + int bpp; + + if (mfd->allow_set_offset) { + imgdata.memory_id = var->reserved[1]; + imgdata.priv = var->reserved[2]; + + /* If there is no memory ID then we want to reset back + to the original fb visibility */ + if (var->reserved[1]) { + if (var->reserved[4] == MDP_BLIT_SRC_GEM) { + panic("waaaaaaaaaaaaaah"); + if ( /*get_gem_img(&imgdata, + (unsigned long *) &address, + &length)*/ -1 < 0) { + return -1; + } + } else { + /*get_img(&imgdata, info, &address, + &length, &p_src_file);*/ + panic("waaaaaah"); + } + mfd->ibuf.visible_swapped = TRUE; + } else { + /* Flip back to the original address + adjusted for xoffset and yoffset */ + + bpp = info->var.bits_per_pixel / 8; + address = (unsigned long) info->fix.smem_start; + address += info->var.xoffset * bpp + + info->var.yoffset * info->fix.line_length; + + mfd->ibuf.visible_swapped = FALSE; + } + + mdp_set_offset_info(info, address, + (var->activate == FB_ACTIVATE_VBL)); + + mfd->dma_fnc(mfd); + return 0; + } else + return -EINVAL; + } + + down(&msm_fb_pan_sem); + mdp_set_dma_pan_info(info, dirtyPtr, + (var->activate == FB_ACTIVATE_VBL)); + mdp_dma_pan_update(info); + up(&msm_fb_pan_sem); + + ++mfd->panel_info.frame_count; + return 0; +} + +static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + + if (var->rotate != FB_ROTATE_UR) + return -EINVAL; + if (var->grayscale != info->var.grayscale) + return -EINVAL; + + switch (var->bits_per_pixel) { + case 16: + if ((var->green.offset != 5) || + !((var->blue.offset == 11) + || (var->blue.offset == 0)) || + !((var->red.offset == 11) + || (var->red.offset == 0)) || + (var->blue.length != 5) || + (var->green.length != 6) || + (var->red.length != 5) || + (var->blue.msb_right != 0) || + (var->green.msb_right != 0) || + (var->red.msb_right != 0) || + (var->transp.offset != 0) || + (var->transp.length != 0)) + return -EINVAL; + break; + + case 24: + if ((var->blue.offset != 0) || + (var->green.offset != 8) || + (var->red.offset != 16) || + (var->blue.length != 8) || + (var->green.length != 8) || + (var->red.length != 8) || + (var->blue.msb_right != 0) || + (var->green.msb_right != 0) || + (var->red.msb_right != 0) || + !(((var->transp.offset == 0) && + (var->transp.length == 0)) || + ((var->transp.offset == 24) && + (var->transp.length == 8)))) + return -EINVAL; + break; + + default: + return -EINVAL; + } + + if ((var->xres_virtual <= 0) || (var->yres_virtual <= 0)) + return -EINVAL; + + if (info->fix.smem_len < + (var->xres_virtual*var->yres_virtual*(var->bits_per_pixel/8))) + return -EINVAL; + + if ((var->xres == 0) || (var->yres == 0)) + return -EINVAL; + + if ((var->xres > mfd->panel_info.xres) || + (var->yres > mfd->panel_info.yres)) + return -EINVAL; + + if (var->xoffset > (var->xres_virtual - var->xres)) + return -EINVAL; + + if (var->yoffset > (var->yres_virtual - var->yres)) + return -EINVAL; + + return 0; +} + +static int msm_fb_set_par(struct fb_info *info) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + struct fb_var_screeninfo *var = &info->var; + int old_imgType; + int blank = 0; + + old_imgType = mfd->fb_imgType; + switch (var->bits_per_pixel) { + case 16: + if (var->red.offset == 0) + mfd->fb_imgType = MDP_BGR_565; + else + mfd->fb_imgType = MDP_RGB_565; + break; + + case 24: + if ((var->transp.offset == 0) && (var->transp.length == 0)) + mfd->fb_imgType = MDP_RGB_888; + else if ((var->transp.offset == 24) && + (var->transp.length == 8)) { + mfd->fb_imgType = MDP_ARGB_8888; + info->var.bits_per_pixel = 32; + } + break; + + default: + return -EINVAL; + } + + if ((mfd->var_pixclock != var->pixclock) || + (mfd->hw_refresh && ((mfd->fb_imgType != old_imgType) || + (mfd->var_pixclock != var->pixclock) || + (mfd->var_xres != var->xres) || + (mfd->var_yres != var->yres)))) { + mfd->var_xres = var->xres; + mfd->var_yres = var->yres; + mfd->var_pixclock = var->pixclock; + blank = 1; + } + + if (blank) { + msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable); + msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable); + } + + return 0; +} + +static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd) +{ + if (mfd->hw_refresh) + return -EPERM; + + if (mfd->sw_currently_refreshing) { + down(&mfd->sem); + mfd->sw_currently_refreshing = FALSE; + up(&mfd->sem); + + /* wait until the refresher finishes the last job */ + wait_for_completion_killable(&mfd->refresher_comp); + } + + return 0; +} + +int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd) +{ + boolean do_refresh; + + if (mfd->hw_refresh) + return -EPERM; + + down(&mfd->sem); + if ((!mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) { + do_refresh = TRUE; + mfd->sw_currently_refreshing = TRUE; + } else { + do_refresh = FALSE; + } + up(&mfd->sem); + + if (do_refresh) + mdp_refresh_screen((unsigned long)mfd); + + return 0; +} + +void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file) +{ +#ifdef CONFIG_ANDROID_PMEM + if (p_src_file) + put_pmem_file(p_src_file); + if (p_dst_file) + put_pmem_file(p_dst_file); +#endif +} + +int mdp_blit(struct fb_info *info, struct mdp_blit_req *req) +{ + int ret; + struct file *p_src_file = 0, *p_dst_file = 0; + if (unlikely(req->src_rect.h == 0 || req->src_rect.w == 0)) { + printk(KERN_ERR "mpd_ppp: src img of zero size!\n"); + return -EINVAL; + } + if (unlikely(req->dst_rect.h == 0 || req->dst_rect.w == 0)) + return 0; + + ret = mdp_ppp_blit(info, req, &p_src_file, &p_dst_file); + mdp_ppp_put_img(p_src_file, p_dst_file); + return ret; +} + +typedef void (*msm_dma_barrier_function_pointer) (void *, size_t); + +static inline void msm_fb_dma_barrier_for_rect(struct fb_info *info, + struct mdp_img *img, struct mdp_rect *rect, + msm_dma_barrier_function_pointer dma_barrier_fp + ) +{ + /* + * Compute the start and end addresses of the rectangles. + * NOTE: As currently implemented, the data between + * the end of one row and the start of the next is + * included in the address range rather than + * doing multiple calls for each row. + */ + + char * const pmem_start = info->screen_base; +/* int bytes_per_pixel = mdp_get_bytes_per_pixel(img->format); + unsigned long start = (unsigned long)pmem_start + img->offset + + (img->width * rect->y + rect->x) * bytes_per_pixel; + size_t size = ((rect->h - 1) * img->width + rect->w) * bytes_per_pixel; + (*dma_barrier_fp) ((void *) start, size); +*/ + panic("waaaaah"); +} + +static inline void msm_dma_nc_pre(void) +{ + dmb(); +} +static inline void msm_dma_wt_pre(void) +{ + dmb(); +} +static inline void msm_dma_todevice_wb_pre(void *start, size_t size) +{ + #warning this +// dma_cache_pre_ops(start, size, DMA_TO_DEVICE); +} + +static inline void msm_dma_fromdevice_wb_pre(void *start, size_t size) +{ + #warning this +// dma_cache_pre_ops(start, size, DMA_FROM_DEVICE); +} + +static inline void msm_dma_nc_post(void) +{ + dmb(); +} + +static inline void msm_dma_fromdevice_wt_post(void *start, size_t size) +{ + #warning this +// dma_cache_post_ops(start, size, DMA_FROM_DEVICE); +} + +static inline void msm_dma_todevice_wb_post(void *start, size_t size) +{ + #warning this +// dma_cache_post_ops(start, size, DMA_TO_DEVICE); +} + +static inline void msm_dma_fromdevice_wb_post(void *start, size_t size) +{ + #warning this +// dma_cache_post_ops(start, size, DMA_FROM_DEVICE); +} + +/* + * Do the write barriers required to guarantee data is committed to RAM + * (from CPU cache or internal buffers) before a DMA operation starts. + * NOTE: As currently implemented, the data between + * the end of one row and the start of the next is + * included in the address range rather than + * doing multiple calls for each row. +*/ +static void msm_fb_ensure_memory_coherency_before_dma(struct fb_info *info, + struct mdp_blit_req *req_list, + int req_list_count) +{ +#ifdef CONFIG_ARCH_QSD8X50 + int i; + + /* + * Normally, do the requested barriers for each address + * range that corresponds to a rectangle. + * + * But if at least one write barrier is requested for data + * going to or from the device but no address range is + * needed for that barrier, then do the barrier, but do it + * only once, no matter how many requests there are. + */ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + switch (mfd->mdp_fb_page_protection) { + default: + case MDP_FB_PAGE_PROTECTION_NONCACHED: + case MDP_FB_PAGE_PROTECTION_WRITECOMBINE: + /* + * The following barrier is only done at most once, + * since further calls would be redundant. + */ + for (i = 0; i < req_list_count; i++) { + if (!(req_list[i].flags + & MDP_NO_DMA_BARRIER_START)) { + msm_dma_nc_pre(); + break; + } + } + break; + + case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE: + /* + * The following barrier is only done at most once, + * since further calls would be redundant. + */ + for (i = 0; i < req_list_count; i++) { + if (!(req_list[i].flags + & MDP_NO_DMA_BARRIER_START)) { + msm_dma_wt_pre(); + break; + } + } + break; + + case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE: + case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE: + for (i = 0; i < req_list_count; i++) { + if (!(req_list[i].flags & + MDP_NO_DMA_BARRIER_START)) { + + msm_fb_dma_barrier_for_rect(info, + &(req_list[i].src), + &(req_list[i].src_rect), + msm_dma_todevice_wb_pre + ); + + msm_fb_dma_barrier_for_rect(info, + &(req_list[i].dst), + &(req_list[i].dst_rect), + msm_dma_todevice_wb_pre + ); + } + } + break; + } +#else + dmb(); +#endif +} + + +/* + * Do the write barriers required to guarantee data will be re-read from RAM by + * the CPU after a DMA operation ends. + * NOTE: As currently implemented, the data between + * the end of one row and the start of the next is + * included in the address range rather than + * doing multiple calls for each row. +*/ +static void msm_fb_ensure_memory_coherency_after_dma(struct fb_info *info, + struct mdp_blit_req *req_list, + int req_list_count) +{ +#ifdef CONFIG_ARCH_QSD8X50 + int i; + + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + switch (mfd->mdp_fb_page_protection) { + default: + case MDP_FB_PAGE_PROTECTION_NONCACHED: + case MDP_FB_PAGE_PROTECTION_WRITECOMBINE: + /* + * The following barrier is only done at most once, + * since further calls would be redundant. + */ + for (i = 0; i < req_list_count; i++) { + if (!(req_list[i].flags + & MDP_NO_DMA_BARRIER_END)) { + msm_dma_nc_post(); + break; + } + } + break; + + case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE: + for (i = 0; i < req_list_count; i++) { + if (!(req_list[i].flags & + MDP_NO_DMA_BARRIER_END)) { + + msm_fb_dma_barrier_for_rect(info, + &(req_list[i].dst), + &(req_list[i].dst_rect), + msm_dma_fromdevice_wt_post + ); + } + } + break; + case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE: + case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE: + for (i = 0; i < req_list_count; i++) { + if (!(req_list[i].flags & + MDP_NO_DMA_BARRIER_END)) { + + msm_fb_dma_barrier_for_rect(info, + &(req_list[i].dst), + &(req_list[i].dst_rect), + msm_dma_fromdevice_wb_post + ); + } + } + break; + } +#else + dmb(); +#endif +} + +#ifdef CONFIG_MDP_PPP_ASYNC_OP +void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info, + struct mdp_blit_req *req_list, int req_list_count) +{ + BUG_ON(!info); + + /* + * Ensure that CPU cache and other internal CPU state is + * updated to reflect any change in memory modified by MDP blit + * DMA. + */ + msm_fb_ensure_memory_coherency_after_dma(info, + req_list, req_list_count); +} + +static int msmfb_async_blit(struct fb_info *info, void __user *p) +{ + /* + * CAUTION: The names of the struct types intentionally *DON'T* match + * the names of the variables declared -- they appear to be swapped. + * Read the code carefully and you should see that the variable names + * make sense. + */ + const int MAX_LIST_WINDOW = 16; + struct mdp_blit_req req_list[MAX_LIST_WINDOW]; + struct mdp_blit_req_list req_list_header; + + int count, i, req_list_count; + + /* Get the count size for the total BLIT request. */ + if (copy_from_user(&req_list_header, p, sizeof(req_list_header))) + return -EFAULT; + p += sizeof(req_list_header); + count = req_list_header.count; + while (count > 0) { + /* + * Access the requests through a narrow window to decrease copy + * overhead and make larger requests accessible to the + * coherency management code. + * NOTE: The window size is intended to be larger than the + * typical request size, but not require more than 2 + * kbytes of stack storage. + */ + req_list_count = count; + if (req_list_count > MAX_LIST_WINDOW) + req_list_count = MAX_LIST_WINDOW; + if (copy_from_user(&req_list, p, + sizeof(struct mdp_blit_req)*req_list_count)) + return -EFAULT; + + /* + * Ensure that any data CPU may have previously written to + * internal state (but not yet committed to memory) is + * guaranteed to be committed to memory now. + */ + msm_fb_ensure_memory_coherency_before_dma(info, + req_list, req_list_count); + + /* + * Do the blit DMA, if required -- returning early only if + * there is a failure. + */ + for (i = 0; i < req_list_count; i++) { + if (!(req_list[i].flags & MDP_NO_BLIT)) { + int ret = 0; + struct mdp_ppp_djob *job = NULL; + + if (unlikely(req_list[i].src_rect.h == 0 || + req_list[i].src_rect.w == 0)) { + MSM_FB_ERR("mpd_ppp: " + "src img of zero size!\n"); + return -EINVAL; + } + + if (unlikely(req_list[i].dst_rect.h == 0 || + req_list[i].dst_rect.w == 0)) + continue; + + /* create a new display job */ + job = mdp_ppp_new_djob(); + if (unlikely(!job)) + return -ENOMEM; + + job->info = info; + memcpy(&job->req, &req_list[i], + sizeof(struct mdp_blit_req)); + + /* Do the actual blit. */ + ret = mdp_ppp_blit(info, &job->req, + &job->p_src_file, &job->p_dst_file); + + /* + * Note that early returns don't guarantee + * memory coherency. + */ + if (ret || mdp_ppp_get_ret_code()) { + mdp_ppp_clear_curr_djob(); + return ret; + } + } + } + + /* Go to next window of requests. */ + count -= req_list_count; + p += sizeof(struct mdp_blit_req)*req_list_count; + } + return 0; +} +#else + +/* + * NOTE: The userspace issues blit operations in a sequence, the sequence + * start with a operation marked START and ends in an operation marked + * END. It is guranteed by the userspace that all the blit operations + * between START and END are only within the regions of areas designated + * by the START and END operations and that the userspace doesnt modify + * those areas. Hence it would be enough to perform barrier/cache operations + * only on the START and END operations. + */ +static int msmfb_blit(struct fb_info *info, void __user *p) +{ + /* + * CAUTION: The names of the struct types intentionally *DON'T* match + * the names of the variables declared -- they appear to be swapped. + * Read the code carefully and you should see that the variable names + * make sense. + */ + const int MAX_LIST_WINDOW = 16; + struct mdp_blit_req req_list[MAX_LIST_WINDOW]; + struct mdp_blit_req_list req_list_header; + + int count, i, req_list_count; + + /* Get the count size for the total BLIT request. */ + if (copy_from_user(&req_list_header, p, sizeof(req_list_header))) + return -EFAULT; + p += sizeof(req_list_header); + count = req_list_header.count; + while (count > 0) { + /* + * Access the requests through a narrow window to decrease copy + * overhead and make larger requests accessible to the + * coherency management code. + * NOTE: The window size is intended to be larger than the + * typical request size, but not require more than 2 + * kbytes of stack storage. + */ + req_list_count = count; + if (req_list_count > MAX_LIST_WINDOW) + req_list_count = MAX_LIST_WINDOW; + if (copy_from_user(&req_list, p, + sizeof(struct mdp_blit_req)*req_list_count)) + return -EFAULT; + + /* + * Ensure that any data CPU may have previously written to + * internal state (but not yet committed to memory) is + * guaranteed to be committed to memory now. + */ + msm_fb_ensure_memory_coherency_before_dma(info, + req_list, req_list_count); + + /* + * Do the blit DMA, if required -- returning early only if + * there is a failure. + */ + for (i = 0; i < req_list_count; i++) { + if (!(req_list[i].flags & MDP_NO_BLIT)) { + /* Do the actual blit. */ + int ret = mdp_blit(info, &(req_list[i])); + + /* + * Note that early returns don't guarantee + * memory coherency. + */ + if (ret) + return ret; + } + } + + /* + * Ensure that CPU cache and other internal CPU state is + * updated to reflect any change in memory modified by MDP blit + * DMA. + */ + msm_fb_ensure_memory_coherency_after_dma(info, + req_list, + req_list_count); + + /* Go to next window of requests. */ + count -= req_list_count; + p += sizeof(struct mdp_blit_req)*req_list_count; + } + return 0; +} +#endif + +#ifdef CONFIG_FB_MSM_OVERLAY +static int msmfb_overlay_get(struct fb_info *info, void __user *p) +{ + struct mdp_overlay req; + int ret; + + if (copy_from_user(&req, p, sizeof(req))) + return -EFAULT; + + ret = mdp4_overlay_get(info, &req); + if (ret) { + printk(KERN_ERR "%s: ioctl failed \n", + __func__); + return ret; + } + if (copy_to_user(p, &req, sizeof(req))) { + printk(KERN_ERR "%s: copy2user failed \n", + __func__); + return -EFAULT; + } + + return 0; +} + +static int msmfb_overlay_set(struct fb_info *info, void __user *p) +{ + struct mdp_overlay req; + int ret; + + if (copy_from_user(&req, p, sizeof(req))) + return -EFAULT; + + ret = mdp4_overlay_set(info, &req); + if (ret) { + printk(KERN_ERR "%s:ioctl failed \n", + __func__); + return ret; + } + + if (copy_to_user(p, &req, sizeof(req))) { + printk(KERN_ERR "%s: copy2user failed \n", + __func__); + return -EFAULT; + } + + return 0; +} + +static int msmfb_overlay_unset(struct fb_info *info, unsigned long *argp) +{ + int ret, ndx; + + ret = copy_from_user(&ndx, argp, sizeof(ndx)); + if (ret) { + printk(KERN_ERR "%s:msmfb_overlay_unset ioctl failed \n", + __func__); + return ret; + } + + return mdp4_overlay_unset(info, ndx); +} + +static int msmfb_overlay_play(struct fb_info *info, unsigned long *argp) +{ + int ret; + struct msmfb_overlay_data req; + struct file *p_src_file = 0; + + ret = copy_from_user(&req, argp, sizeof(req)); + if (ret) { + printk(KERN_ERR "%s:msmfb_overlay_play ioctl failed \n", + __func__); + return ret; + } + + ret = mdp4_overlay_play(info, &req, &p_src_file); + + if (p_src_file) + put_pmem_file(p_src_file); + + return ret; +} + +#endif + +DECLARE_MUTEX(msm_fb_ioctl_ppp_sem); +DEFINE_MUTEX(msm_fb_ioctl_lut_sem); +DEFINE_MUTEX(msm_fb_ioctl_hist_sem); + +/* Set color conversion matrix from user space */ + +#ifndef CONFIG_FB_MSM_MDP40 +static void msmfb_set_color_conv(struct mdp_ccs *p) +{ + int i; + + if (p->direction == MDP_CCS_RGB2YUV) { + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + + /* RGB->YUV primary forward matrix */ + for (i = 0; i < MDP_CCS_SIZE; i++) + writel(p->ccs[i], MDP_CSC_PFMVn(i)); + + #ifdef CONFIG_FB_MSM_MDP31 + for (i = 0; i < MDP_BV_SIZE; i++) + writel(p->bv[i], MDP_CSC_POST_BV2n(i)); + #endif + + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + } else { + /* MDP cmd block enable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + + /* YUV->RGB primary reverse matrix */ + for (i = 0; i < MDP_CCS_SIZE; i++) + writel(p->ccs[i], MDP_CSC_PRMVn(i)); + for (i = 0; i < MDP_BV_SIZE; i++) + writel(p->bv[i], MDP_CSC_PRE_BV1n(i)); + + /* MDP cmd block disable */ + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); + } +} +#endif + + +static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + void __user *argp = (void __user *)arg; + struct fb_cursor cursor; + struct fb_cmap cmap; + struct mdp_histogram hist; +#ifndef CONFIG_FB_MSM_MDP40 + struct mdp_ccs ccs_matrix; +#endif + struct mdp_page_protection fb_page_protection; + int ret = 0; + + if (!mfd->op_enable) + return -EPERM; + + switch (cmd) { +#ifdef CONFIG_FB_MSM_OVERLAY + case MSMFB_OVERLAY_GET: + down(&msm_fb_ioctl_ppp_sem); + ret = msmfb_overlay_get(info, argp); + up(&msm_fb_ioctl_ppp_sem); + break; + case MSMFB_OVERLAY_SET: + down(&msm_fb_ioctl_ppp_sem); + ret = msmfb_overlay_set(info, argp); + up(&msm_fb_ioctl_ppp_sem); + break; + case MSMFB_OVERLAY_UNSET: + down(&msm_fb_ioctl_ppp_sem); + ret = msmfb_overlay_unset(info, argp); + up(&msm_fb_ioctl_ppp_sem); + break; + case MSMFB_OVERLAY_PLAY: + down(&msm_fb_ioctl_ppp_sem); + ret = msmfb_overlay_play(info, argp); + up(&msm_fb_ioctl_ppp_sem); + break; +#endif + case MSMFB_BLIT: + down(&msm_fb_ioctl_ppp_sem); +#ifdef CONFIG_MDP_PPP_ASYNC_OP + ret = msmfb_async_blit(info, argp); + mdp_ppp_wait(); /* Wait for all blits to be finished. */ +#else + ret = msmfb_blit(info, argp); +#endif + up(&msm_fb_ioctl_ppp_sem); + + break; + + /* Ioctl for setting ccs matrix from user space */ + case MSMFB_SET_CCS_MATRIX: +#ifndef CONFIG_FB_MSM_MDP40 + ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix)); + if (ret) { + printk(KERN_ERR + "%s:MSMFB_SET_CCS_MATRIX ioctl failed \n", + __func__); + return ret; + } + + down(&msm_fb_ioctl_ppp_sem); + if (ccs_matrix.direction == MDP_CCS_RGB2YUV) + mdp_ccs_rgb2yuv = ccs_matrix; + else + mdp_ccs_yuv2rgb = ccs_matrix; + + msmfb_set_color_conv(&ccs_matrix) ; + up(&msm_fb_ioctl_ppp_sem); +#else + ret = -EINVAL; +#endif + + break; + + /* Ioctl for getting ccs matrix to user space */ + case MSMFB_GET_CCS_MATRIX: +#ifndef CONFIG_FB_MSM_MDP40 + ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix)) ; + if (ret) { + printk(KERN_ERR + "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n", + __func__); + return ret; + } + + down(&msm_fb_ioctl_ppp_sem); + if (ccs_matrix.direction == MDP_CCS_RGB2YUV) + ccs_matrix = mdp_ccs_rgb2yuv; + else + ccs_matrix = mdp_ccs_yuv2rgb; + + ret = copy_to_user(argp, &ccs_matrix, sizeof(ccs_matrix)); + + if (ret) { + printk(KERN_ERR + "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n", + __func__); + return ret ; + } + up(&msm_fb_ioctl_ppp_sem); +#else + ret = -EINVAL; +#endif + + break; + +#ifdef CONFIG_MDP_PPP_ASYNC_OP + case MSMFB_ASYNC_BLIT: + down(&msm_fb_ioctl_ppp_sem); + ret = msmfb_async_blit(info, argp); + up(&msm_fb_ioctl_ppp_sem); + break; + + case MSMFB_BLIT_FLUSH: + down(&msm_fb_ioctl_ppp_sem); + mdp_ppp_wait(); + up(&msm_fb_ioctl_ppp_sem); + break; +#endif + + case MSMFB_GRP_DISP: +#ifdef CONFIG_FB_MSM_MDP22 + { + unsigned long grp_id; + + ret = copy_from_user(&grp_id, argp, sizeof(grp_id)); + if (ret) + return ret; + + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); + writel(grp_id, MDP_FULL_BYPASS_WORD43); + mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, + FALSE); + break; + } +#else + return -EFAULT; +#endif + case MSMFB_SUSPEND_SW_REFRESHER: + if (!mfd->panel_power_on) + return -EPERM; + + mfd->sw_refreshing_enable = FALSE; + ret = msm_fb_stop_sw_refresher(mfd); + break; + + case MSMFB_RESUME_SW_REFRESHER: + if (!mfd->panel_power_on) + return -EPERM; + + mfd->sw_refreshing_enable = TRUE; + ret = msm_fb_resume_sw_refresher(mfd); + break; + + case MSMFB_CURSOR: + ret = copy_from_user(&cursor, argp, sizeof(cursor)); + if (ret) + return ret; + + ret = msm_fb_cursor(info, &cursor); + break; + + case MSMFB_SET_LUT: + ret = copy_from_user(&cmap, argp, sizeof(cmap)); + if (ret) + return ret; + + mutex_lock(&msm_fb_ioctl_lut_sem); + ret = msm_fb_set_lut(&cmap, info); + mutex_unlock(&msm_fb_ioctl_lut_sem); + break; + + case MSMFB_HISTOGRAM: + if (!mfd->do_histogram) + return -ENODEV; + + ret = copy_from_user(&hist, argp, sizeof(hist)); + if (ret) + return ret; + + mutex_lock(&msm_fb_ioctl_hist_sem); + ret = mfd->do_histogram(info, &hist); + mutex_unlock(&msm_fb_ioctl_hist_sem); + break; + + case MSMFB_GET_PAGE_PROTECTION: + fb_page_protection.page_protection + = mfd->mdp_fb_page_protection; + ret = copy_to_user(argp, &fb_page_protection, + sizeof(fb_page_protection)); + if (ret) + return ret; + break; + + case MSMFB_SET_PAGE_PROTECTION: +#ifdef CONFIG_ARCH_QSD8X50 + ret = copy_from_user(&fb_page_protection, argp, + sizeof(fb_page_protection)); + if (ret) + return ret; + + /* Validate the proposed page protection settings. */ + switch (fb_page_protection.page_protection) { + case MDP_FB_PAGE_PROTECTION_NONCACHED: + case MDP_FB_PAGE_PROTECTION_WRITECOMBINE: + case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE: + /* Write-back cache (read allocate) */ + case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE: + /* Write-back cache (write allocate) */ + case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE: + mfd->mdp_fb_page_protection = + fb_page_protection.page_protection; + break; + default: + ret = -EINVAL; + break; + } +#else + /* + * Don't allow caching until 7k DMA cache operations are + * available. + */ + ret = -EINVAL; +#endif + break; + + default: + MSM_FB_INFO("MDP: unknown ioctl (cmd=%d) received!\n", cmd); + ret = -EINVAL; + break; + } + + return ret; +} + +static int msm_fb_register_driver(void) +{ + return platform_driver_register(&msm_fb_driver); +} + +void msm_fb_add_device(struct platform_device *pdev) +{ + struct msm_fb_panel_data *pdata; + struct platform_device *this_dev = NULL; + struct fb_info *fbi; + struct msm_fb_data_type *mfd = NULL; + u32 type, id, fb_num; + + if (!pdev) + return; + id = pdev->id; + + pdata = pdev->dev.platform_data; + if (!pdata) + return; + type = pdata->panel_info.type; + fb_num = pdata->panel_info.fb_num; + + if (fb_num <= 0) + return; + + if (fbi_list_index >= MAX_FBI_LIST) { + printk(KERN_ERR "msm_fb: no more framebuffer info list!\n"); + return; + } + /* + * alloc panel device data + */ + this_dev = msm_fb_device_alloc(pdata, type, id); + + if (!this_dev) { + printk(KERN_ERR + "%s: msm_fb_device_alloc failed!\n", __func__); + return; + } + + /* + * alloc framebuffer info + par data + */ + fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), NULL); + if (fbi == NULL) { + platform_device_put(this_dev); + printk(KERN_ERR "msm_fb: can't alloca framebuffer info data!\n"); + return; + } + + mfd = (struct msm_fb_data_type *)fbi->par; + mfd->key = MFD_KEY; + mfd->fbi = fbi; + mfd->panel.type = type; + mfd->panel.id = id; + mfd->fb_page = fb_num; + mfd->index = fbi_list_index; + mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE; + + /* link to the latest pdev */ + mfd->pdev = this_dev; + + mfd_list[mfd_list_index++] = mfd; + fbi_list[fbi_list_index++] = fbi; + + /* + * set driver data + */ + platform_set_drvdata(this_dev, mfd); + + if (platform_device_add(this_dev)) { + printk(KERN_ERR "msm_fb: platform_device_add failed!\n"); + platform_device_put(this_dev); + framebuffer_release(fbi); + fbi_list_index--; + return; + } +} +EXPORT_SYMBOL(msm_fb_add_device); + +int __init msm_fb_init(void) +{ + int rc = -ENODEV; + + if (msm_fb_register_driver()) + return rc; + +#ifdef MSM_FB_ENABLE_DBGFS + { + struct dentry *root; + + if ((root = msm_fb_get_debugfs_root()) != NULL) { + msm_fb_debugfs_file_create(root, + "msm_fb_msg_printing_level", + (u32 *) &msm_fb_msg_level); + msm_fb_debugfs_file_create(root, + "mddi_msg_printing_level", + (u32 *) &mddi_msg_level); + msm_fb_debugfs_file_create(root, "msm_fb_debug_enabled", + (u32 *) &msm_fb_debug_enabled); + } + } +#endif + + return 0; +} + +module_init(msm_fb_init); diff --git a/drivers/staging/msm/msm_fb.h b/drivers/staging/msm/msm_fb.h new file mode 100644 index 000000000000..f93913800475 --- /dev/null +++ b/drivers/staging/msm/msm_fb.h @@ -0,0 +1,174 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MSM_FB_H +#define MSM_FB_H + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include "linux/proc_fs.h" + +#include <mach/hardware.h> +#include <linux/io.h> +#include <mach/board.h> + +#include <asm/system.h> +#include <asm/mach-types.h> +#include <mach/memory.h> +#include <linux/semaphore.h> +#include <linux/spinlock.h> +#include <linux/workqueue.h> +#include <linux/hrtimer.h> + +#include <linux/fb.h> + +#ifdef CONFIG_HAS_EARLYSUSPEND +#include <linux/earlysuspend.h> +#endif + +#include "msm_fb_panel.h" +#include "mdp.h" + +#define MSM_FB_DEFAULT_PAGE_SIZE 2 +#define MFD_KEY 0x11161126 +#define MSM_FB_MAX_DEV_LIST 32 + +struct disp_info_type_suspend { + boolean op_enable; + boolean sw_refreshing_enable; + boolean panel_power_on; +}; + +struct msm_fb_data_type { + __u32 key; + __u32 index; + __u32 ref_cnt; + __u32 fb_page; + + panel_id_type panel; + struct msm_panel_info panel_info; + + DISP_TARGET dest; + struct fb_info *fbi; + + boolean op_enable; + uint32 fb_imgType; + boolean sw_currently_refreshing; + boolean sw_refreshing_enable; + boolean hw_refresh; + + MDPIBUF ibuf; + boolean ibuf_flushed; + struct timer_list refresh_timer; + struct completion refresher_comp; + + boolean pan_waiting; + struct completion pan_comp; + + /* vsync */ + boolean use_mdp_vsync; + __u32 vsync_gpio; + __u32 total_lcd_lines; + __u32 total_porch_lines; + __u32 lcd_ref_usec_time; + __u32 refresh_timer_duration; + + struct hrtimer dma_hrtimer; + + boolean panel_power_on; + struct work_struct dma_update_worker; + struct semaphore sem; + + struct timer_list vsync_resync_timer; + boolean vsync_handler_pending; + struct work_struct vsync_resync_worker; + + ktime_t last_vsync_timetick; + + __u32 *vsync_width_boundary; + + unsigned int pmem_id; + struct disp_info_type_suspend suspend; + + __u32 channel_irq; + + struct mdp_dma_data *dma; + void (*dma_fnc) (struct msm_fb_data_type *mfd); + int (*cursor_update) (struct fb_info *info, + struct fb_cursor *cursor); + int (*lut_update) (struct fb_info *info, + struct fb_cmap *cmap); + int (*do_histogram) (struct fb_info *info, + struct mdp_histogram *hist); + void *cursor_buf; + void *cursor_buf_phys; + + void *cmd_port; + void *data_port; + void *data_port_phys; + + __u32 bl_level; + + struct platform_device *pdev; + + __u32 var_xres; + __u32 var_yres; + __u32 var_pixclock; + +#ifdef MSM_FB_ENABLE_DBGFS + struct dentry *sub_dir; +#endif + +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; + struct early_suspend mddi_early_suspend; + struct early_suspend mddi_ext_early_suspend; +#endif + u32 mdp_fb_page_protection; + int allow_set_offset; +}; + +struct dentry *msm_fb_get_debugfs_root(void); +void msm_fb_debugfs_file_create(struct dentry *root, const char *name, + u32 *var); +void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl, + u32 save); + +void msm_fb_add_device(struct platform_device *pdev); + +int msm_fb_detect_client(const char *name); + +#ifdef CONFIG_FB_BACKLIGHT +void msm_fb_config_backlight(struct msm_fb_data_type *mfd); +#endif + +#endif /* MSM_FB_H */ diff --git a/drivers/staging/msm/msm_fb_bl.c b/drivers/staging/msm/msm_fb_bl.c new file mode 100644 index 000000000000..033fc9486e01 --- /dev/null +++ b/drivers/staging/msm/msm_fb_bl.c @@ -0,0 +1,79 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include <linux/string.h> +#include <linux/version.h> +#include <linux/backlight.h> + +#include "msm_fb.h" + +static int msm_fb_bl_get_brightness(struct backlight_device *pbd) +{ + return pbd->props.brightness; +} + +static int msm_fb_bl_update_status(struct backlight_device *pbd) +{ + struct msm_fb_data_type *mfd = bl_get_data(pbd); + __u32 bl_lvl; + + bl_lvl = pbd->props.brightness; + bl_lvl = mfd->fbi->bl_curve[bl_lvl]; + msm_fb_set_backlight(mfd, bl_lvl, 1); + return 0; +} + +static struct backlight_ops msm_fb_bl_ops = { + .get_brightness = msm_fb_bl_get_brightness, + .update_status = msm_fb_bl_update_status, +}; + +void msm_fb_config_backlight(struct msm_fb_data_type *mfd) +{ + struct msm_fb_panel_data *pdata; + struct backlight_device *pbd; + struct fb_info *fbi; + char name[16]; + + fbi = mfd->fbi; + pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; + + if ((pdata) && (pdata->set_backlight)) { + snprintf(name, sizeof(name), "msmfb_bl%d", mfd->index); + pbd = + backlight_device_register(name, fbi->dev, mfd, + &msm_fb_bl_ops); + if (!IS_ERR(pbd)) { + fbi->bl_dev = pbd; + fb_bl_default_curve(fbi, + 0, + mfd->panel_info.bl_min, + mfd->panel_info.bl_max); + pbd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1; + pbd->props.brightness = FB_BACKLIGHT_LEVELS - 1; + backlight_update_status(pbd); + } else { + fbi->bl_dev = NULL; + printk(KERN_ERR "msm_fb: backlight_device_register failed!\n"); + } + } +} diff --git a/drivers/staging/msm/msm_fb_def.h b/drivers/staging/msm/msm_fb_def.h new file mode 100644 index 000000000000..6de440937422 --- /dev/null +++ b/drivers/staging/msm/msm_fb_def.h @@ -0,0 +1,201 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MSM_FB_DEF_H +#define MSM_FB_DEF_H + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/mm.h> +#include <linux/fb.h> +#include "msm_mdp.h" +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> +#include <linux/uaccess.h> +#include <linux/workqueue.h> +#include <linux/string.h> +#include <linux/version.h> +#include <linux/proc_fs.h> +#include <linux/vmalloc.h> +#include <linux/debugfs.h> +#include <linux/console.h> + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include "linux/proc_fs.h" +#include <mach/hardware.h> +#include <linux/io.h> +#include <linux/fb.h> +#include <asm/system.h> +#include <asm/mach-types.h> +#include <linux/platform_device.h> + +typedef s64 int64; +typedef s32 int32; +typedef s16 int16; +typedef s8 int8; + +typedef u64 uint64; +typedef u32 uint32; +typedef u16 uint16; +typedef u8 uint8; + +typedef s32 int4; +typedef s16 int2; +typedef s8 int1; + +typedef u32 uint4; +typedef u16 uint2; +typedef u8 uint1; + +typedef u32 dword; +typedef u16 word; +typedef u8 byte; + +typedef unsigned int boolean; + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define MSM_FB_ENABLE_DBGFS +#define FEATURE_MDDI + +#define outp32(addr, val) writel(val, addr) +#define outp16(addr, val) writew(val, addr) +#define outp8(addr, val) writeb(val, addr) +#define outp(addr, val) outp32(addr, val) + +#ifndef MAX +#define MAX( x, y ) (((x) > (y)) ? (x) : (y)) +#endif + +#ifndef MIN +#define MIN( x, y ) (((x) < (y)) ? (x) : (y)) +#endif + +/*--------------------------------------------------------------------------*/ + +#define inp32(addr) readl(addr) +#define inp16(addr) readw(addr) +#define inp8(addr) readb(addr) +#define inp(addr) inp32(addr) + +#define inpw(port) readw(port) +#define outpw(port, val) writew(val, port) +#define inpdw(port) readl(port) +#define outpdw(port, val) writel(val, port) + + +#define clk_busy_wait(x) msleep_interruptible((x)/1000) + +#define memory_barrier() + +#define assert(expr) \ + if(!(expr)) { \ + printk(KERN_ERR "msm_fb: assertion failed! %s,%s,%s,line=%d\n",\ + #expr, __FILE__, __func__, __LINE__); \ + } + +#define ASSERT(x) assert(x) + +#define DISP_EBI2_LOCAL_DEFINE +#ifdef DISP_EBI2_LOCAL_DEFINE +#define LCD_PRIM_BASE_PHYS 0x98000000 +#define LCD_SECD_BASE_PHYS 0x9c000000 +#define EBI2_PRIM_LCD_RS_PIN 0x20000 +#define EBI2_SECD_LCD_RS_PIN 0x20000 + +#define EBI2_PRIM_LCD_CLR 0xC0 +#define EBI2_PRIM_LCD_SEL 0x40 + +#define EBI2_SECD_LCD_CLR 0x300 +#define EBI2_SECD_LCD_SEL 0x100 +#endif + +extern u32 msm_fb_msg_level; + +/* + * Message printing priorities: + * LEVEL 0 KERN_EMERG (highest priority) + * LEVEL 1 KERN_ALERT + * LEVEL 2 KERN_CRIT + * LEVEL 3 KERN_ERR + * LEVEL 4 KERN_WARNING + * LEVEL 5 KERN_NOTICE + * LEVEL 6 KERN_INFO + * LEVEL 7 KERN_DEBUG (Lowest priority) + */ +#define MSM_FB_EMERG(msg, ...) \ + if (msm_fb_msg_level > 0) \ + printk(KERN_EMERG msg, ## __VA_ARGS__); +#define MSM_FB_ALERT(msg, ...) \ + if (msm_fb_msg_level > 1) \ + printk(KERN_ALERT msg, ## __VA_ARGS__); +#define MSM_FB_CRIT(msg, ...) \ + if (msm_fb_msg_level > 2) \ + printk(KERN_CRIT msg, ## __VA_ARGS__); +#define MSM_FB_ERR(msg, ...) \ + if (msm_fb_msg_level > 3) \ + printk(KERN_ERR msg, ## __VA_ARGS__); +#define MSM_FB_WARNING(msg, ...) \ + if (msm_fb_msg_level > 4) \ + printk(KERN_WARNING msg, ## __VA_ARGS__); +#define MSM_FB_NOTICE(msg, ...) \ + if (msm_fb_msg_level > 5) \ + printk(KERN_NOTICE msg, ## __VA_ARGS__); +#define MSM_FB_INFO(msg, ...) \ + if (msm_fb_msg_level > 6) \ + printk(KERN_INFO msg, ## __VA_ARGS__); +#define MSM_FB_DEBUG(msg, ...) \ + if (msm_fb_msg_level > 7) \ + printk(KERN_DEBUG msg, ## __VA_ARGS__); + +#ifdef MSM_FB_C +unsigned char *msm_mdp_base; +unsigned char *msm_pmdh_base; +unsigned char *msm_emdh_base; +#else +extern unsigned char *msm_mdp_base; +extern unsigned char *msm_pmdh_base; +extern unsigned char *msm_emdh_base; +#endif + +#endif /* MSM_FB_DEF_H */ diff --git a/drivers/staging/msm/msm_fb_panel.c b/drivers/staging/msm/msm_fb_panel.c new file mode 100644 index 000000000000..b17a239a1bc7 --- /dev/null +++ b/drivers/staging/msm/msm_fb_panel.c @@ -0,0 +1,136 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/mm.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> +#include <linux/uaccess.h> +#include <linux/workqueue.h> +#include <linux/string.h> +#include <linux/version.h> +#include <linux/proc_fs.h> +#include <linux/vmalloc.h> +#include <linux/debugfs.h> + +#include "msm_fb_panel.h" + +int panel_next_on(struct platform_device *pdev) +{ + int ret = 0; + struct msm_fb_panel_data *pdata; + struct msm_fb_panel_data *next_pdata; + struct platform_device *next_pdev; + + pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data; + + if (pdata) { + next_pdev = pdata->next; + if (next_pdev) { + next_pdata = + (struct msm_fb_panel_data *)next_pdev->dev. + platform_data; + if ((next_pdata) && (next_pdata->on)) + ret = next_pdata->on(next_pdev); + } + } + + return ret; +} + +int panel_next_off(struct platform_device *pdev) +{ + int ret = 0; + struct msm_fb_panel_data *pdata; + struct msm_fb_panel_data *next_pdata; + struct platform_device *next_pdev; + + pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data; + + if (pdata) { + next_pdev = pdata->next; + if (next_pdev) { + next_pdata = + (struct msm_fb_panel_data *)next_pdev->dev. + platform_data; + if ((next_pdata) && (next_pdata->on)) + ret = next_pdata->off(next_pdev); + } + } + + return ret; +} + +struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata, + u32 type, u32 id) +{ + struct platform_device *this_dev = NULL; + char dev_name[16]; + + switch (type) { + case EBI2_PANEL: + snprintf(dev_name, sizeof(dev_name), "ebi2_lcd"); + break; + + case MDDI_PANEL: + snprintf(dev_name, sizeof(dev_name), "mddi"); + break; + + case EXT_MDDI_PANEL: + snprintf(dev_name, sizeof(dev_name), "mddi_ext"); + break; + + case TV_PANEL: + snprintf(dev_name, sizeof(dev_name), "tvenc"); + break; + + case HDMI_PANEL: + case LCDC_PANEL: + snprintf(dev_name, sizeof(dev_name), "lcdc"); + break; + + default: + return NULL; + } + + if (pdata != NULL) + pdata->next = NULL; + else + return NULL; + + this_dev = + platform_device_alloc(dev_name, ((u32) type << 16) | (u32) id); + + if (this_dev) { + if (platform_device_add_data + (this_dev, pdata, sizeof(struct msm_fb_panel_data))) { + printk + ("msm_fb_device_alloc: platform_device_add_data failed!\n"); + platform_device_put(this_dev); + return NULL; + } + } + + return this_dev; +} diff --git a/drivers/staging/msm/msm_fb_panel.h b/drivers/staging/msm/msm_fb_panel.h new file mode 100644 index 000000000000..ab458310c3a2 --- /dev/null +++ b/drivers/staging/msm/msm_fb_panel.h @@ -0,0 +1,145 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MSM_FB_PANEL_H +#define MSM_FB_PANEL_H + +#include "msm_fb_def.h" + +struct msm_fb_data_type; + +typedef void (*msm_fb_vsync_handler_type) (void *arg); + +/* panel id type */ +typedef struct panel_id_s { + uint16 id; + uint16 type; +} panel_id_type; + +/* panel type list */ +#define NO_PANEL 0xffff /* No Panel */ +#define MDDI_PANEL 1 /* MDDI */ +#define EBI2_PANEL 2 /* EBI2 */ +#define LCDC_PANEL 3 /* internal LCDC type */ +#define EXT_MDDI_PANEL 4 /* Ext.MDDI */ +#define TV_PANEL 5 /* TV */ +#define HDMI_PANEL 6 /* HDMI TV */ + +/* panel class */ +typedef enum { + DISPLAY_LCD = 0, /* lcd = ebi2/mddi */ + DISPLAY_LCDC, /* lcdc */ + DISPLAY_TV, /* TV Out */ + DISPLAY_EXT_MDDI, /* External MDDI */ +} DISP_TARGET; + +/* panel device locaiton */ +typedef enum { + DISPLAY_1 = 0, /* attached as first device */ + DISPLAY_2, /* attached on second device */ + MAX_PHYS_TARGET_NUM, +} DISP_TARGET_PHYS; + +/* panel info type */ +struct lcd_panel_info { + __u32 vsync_enable; + __u32 refx100; + __u32 v_back_porch; + __u32 v_front_porch; + __u32 v_pulse_width; + __u32 hw_vsync_mode; + __u32 vsync_notifier_period; +}; + +struct lcdc_panel_info { + __u32 h_back_porch; + __u32 h_front_porch; + __u32 h_pulse_width; + __u32 v_back_porch; + __u32 v_front_porch; + __u32 v_pulse_width; + __u32 border_clr; + __u32 underflow_clr; + __u32 hsync_skew; +}; + +struct mddi_panel_info { + __u32 vdopkt; +}; + +struct msm_panel_info { + __u32 xres; + __u32 yres; + __u32 bpp; + __u32 type; + __u32 wait_cycle; + DISP_TARGET_PHYS pdest; + __u32 bl_max; + __u32 bl_min; + __u32 fb_num; + __u32 clk_rate; + __u32 clk_min; + __u32 clk_max; + __u32 frame_count; + + union { + struct mddi_panel_info mddi; + }; + + union { + struct lcd_panel_info lcd; + struct lcdc_panel_info lcdc; + }; +}; + +struct msm_fb_panel_data { + struct msm_panel_info panel_info; + void (*set_rect) (int x, int y, int xres, int yres); + void (*set_vsync_notifier) (msm_fb_vsync_handler_type, void *arg); + void (*set_backlight) (struct msm_fb_data_type *); + + /* function entry chain */ + int (*on) (struct platform_device *pdev); + int (*off) (struct platform_device *pdev); + struct platform_device *next; +}; + +/*=========================================================================== + FUNCTIONS PROTOTYPES +============================================================================*/ +struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata, + u32 type, u32 id); +int panel_next_on(struct platform_device *pdev); +int panel_next_off(struct platform_device *pdev); + +int lcdc_device_register(struct msm_panel_info *pinfo); + +int mddi_toshiba_device_register(struct msm_panel_info *pinfo, + u32 channel, u32 panel); + +#endif /* MSM_FB_PANEL_H */ diff --git a/drivers/staging/msm/msm_mdp.h b/drivers/staging/msm/msm_mdp.h new file mode 100644 index 000000000000..2d5323f5b62d --- /dev/null +++ b/drivers/staging/msm/msm_mdp.h @@ -0,0 +1,245 @@ +/* include/linux/msm_mdp.h + * + * Copyright (C) 2007 Google Incorporated + * 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 _MSM_MDP_H_ +#define _MSM_MDP_H_ + +#include <linux/types.h> +#include <linux/fb.h> + +#define MSMFB_IOCTL_MAGIC 'm' +#define MSMFB_GRP_DISP _IOW(MSMFB_IOCTL_MAGIC, 1, unsigned int) +#define MSMFB_BLIT _IOW(MSMFB_IOCTL_MAGIC, 2, unsigned int) +#define MSMFB_SUSPEND_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 128, unsigned int) +#define MSMFB_RESUME_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 129, unsigned int) +#define MSMFB_CURSOR _IOW(MSMFB_IOCTL_MAGIC, 130, struct fb_cursor) +#define MSMFB_SET_LUT _IOW(MSMFB_IOCTL_MAGIC, 131, struct fb_cmap) +#define MSMFB_HISTOGRAM _IOWR(MSMFB_IOCTL_MAGIC, 132, struct mdp_histogram) +/* new ioctls's for set/get ccs matrix */ +#define MSMFB_GET_CCS_MATRIX _IOWR(MSMFB_IOCTL_MAGIC, 133, struct mdp_ccs) +#define MSMFB_SET_CCS_MATRIX _IOW(MSMFB_IOCTL_MAGIC, 134, struct mdp_ccs) +#define MSMFB_OVERLAY_SET _IOWR(MSMFB_IOCTL_MAGIC, 135, \ + struct mdp_overlay) +#define MSMFB_OVERLAY_UNSET _IOW(MSMFB_IOCTL_MAGIC, 136, unsigned int) +#define MSMFB_OVERLAY_PLAY _IOW(MSMFB_IOCTL_MAGIC, 137, \ + struct msmfb_overlay_data) +#define MSMFB_GET_PAGE_PROTECTION _IOR(MSMFB_IOCTL_MAGIC, 138, \ + struct mdp_page_protection) +#define MSMFB_SET_PAGE_PROTECTION _IOW(MSMFB_IOCTL_MAGIC, 139, \ + struct mdp_page_protection) +#define MSMFB_OVERLAY_GET _IOR(MSMFB_IOCTL_MAGIC, 140, \ + struct mdp_overlay) + +/* new ioctls for async MDP ops */ +#define MSMFB_ASYNC_BLIT _IOW(MSMFB_IOCTL_MAGIC, 141, unsigned int) +#define MSMFB_BLIT_FLUSH _IOR(MSMFB_IOCTL_MAGIC, 142, unsigned int) + +#define MDP_IMGTYPE2_START 0x10000 + +enum { + MDP_RGB_565, /* RGB 565 planer */ + MDP_XRGB_8888, /* RGB 888 padded */ + MDP_Y_CBCR_H2V2, /* Y and CbCr, pseudo planer w/ Cb is in MSB */ + MDP_ARGB_8888, /* ARGB 888 */ + MDP_RGB_888, /* RGB 888 planer */ + MDP_Y_CRCB_H2V2, /* Y and CrCb, pseudo planer w/ Cr is in MSB */ + MDP_YCRYCB_H2V1, /* YCrYCb interleave */ + MDP_Y_CRCB_H2V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */ + MDP_Y_CBCR_H2V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */ + MDP_RGBA_8888, /* ARGB 888 */ + MDP_BGRA_8888, /* ABGR 888 */ + MDP_Y_CRCB_H2V2_TILE, /* Y and CrCb, pseudo planer tile */ + MDP_Y_CBCR_H2V2_TILE, /* Y and CbCr, pseudo planer tile */ + MDP_IMGTYPE_LIMIT, + MDP_BGR_565 = MDP_IMGTYPE2_START, /* BGR 565 planer */ + MDP_FB_FORMAT, /* framebuffer format */ + MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */ +}; + +enum { + PMEM_IMG, + FB_IMG, +}; + +/* mdp_blit_req flag values */ +#define MDP_ROT_NOP 0 +#define MDP_FLIP_LR 0x1 +#define MDP_FLIP_UD 0x2 +#define MDP_ROT_90 0x4 +#define MDP_ROT_180 (MDP_FLIP_UD|MDP_FLIP_LR) +#define MDP_ROT_270 (MDP_ROT_90|MDP_FLIP_UD|MDP_FLIP_LR) +#define MDP_DITHER 0x8 +#define MDP_BLUR 0x10 +#define MDP_BLEND_FG_PREMULT 0x20000 + +#define MDP_DEINTERLACE 0x80000000 +#define MDP_SHARPENING 0x40000000 + +#define MDP_NO_DMA_BARRIER_START 0x20000000 +#define MDP_NO_DMA_BARRIER_END 0x10000000 +#define MDP_NO_BLIT 0x08000000 +#define MDP_BLIT_WITH_DMA_BARRIERS 0x000 +#define MDP_BLIT_WITH_NO_DMA_BARRIERS \ + (MDP_NO_DMA_BARRIER_START | MDP_NO_DMA_BARRIER_END) +#define MDP_TRANSP_NOP 0xffffffff +#define MDP_ALPHA_NOP 0xff + +#define MDP_BLIT_SRC_GEM 0x02000000 /* set for GEM, clear for PMEM */ +#define MDP_BLIT_DST_GEM 0x01000000 /* set for GEM, clear for PMEM */ + +#define MDP_FB_PAGE_PROTECTION_NONCACHED (0) +#define MDP_FB_PAGE_PROTECTION_WRITECOMBINE (1) +#define MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE (2) +#define MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE (3) +#define MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE (4) +/* Sentinel: Don't use! */ +#define MDP_FB_PAGE_PROTECTION_INVALID (5) +/* Count of the number of MDP_FB_PAGE_PROTECTION_... values. */ +#define MDP_NUM_FB_PAGE_PROTECTION_VALUES (5) + +struct mdp_rect { + uint32_t x; + uint32_t y; + uint32_t w; + uint32_t h; +}; + +struct mdp_img { + uint32_t width; + uint32_t height; + uint32_t format; + uint32_t offset; + int memory_id; /* the file descriptor */ + uint32_t priv; +}; + +/* + * {3x3} + {3} ccs matrix + */ + +#define MDP_CCS_RGB2YUV 0 +#define MDP_CCS_YUV2RGB 1 + +#define MDP_CCS_SIZE 9 +#define MDP_BV_SIZE 3 + +struct mdp_ccs { + int direction; /* MDP_CCS_RGB2YUV or YUV2RGB */ + uint16_t ccs[MDP_CCS_SIZE]; /* 3x3 color coefficients */ + uint16_t bv[MDP_BV_SIZE]; /* 1x3 bias vector */ +}; + +/* The version of the mdp_blit_req structure so that + * user applications can selectively decide which functionality + * to include + */ + +#define MDP_BLIT_REQ_VERSION 2 + +struct mdp_blit_req { + struct mdp_img src; + struct mdp_img dst; + struct mdp_rect src_rect; + struct mdp_rect dst_rect; + uint32_t alpha; + uint32_t transp_mask; + uint32_t flags; + int sharpening_strength; /* -127 <--> 127, default 64 */ +}; + +struct mdp_blit_req_list { + uint32_t count; + struct mdp_blit_req req[]; +}; + +struct msmfb_data { + uint32_t offset; + int memory_id; + int id; +}; + +#define MSMFB_NEW_REQUEST -1 + +struct msmfb_overlay_data { + uint32_t id; + struct msmfb_data data; +}; + +struct msmfb_img { + uint32_t width; + uint32_t height; + uint32_t format; +}; + +struct mdp_overlay { + struct msmfb_img src; + struct mdp_rect src_rect; + struct mdp_rect dst_rect; + uint32_t z_order; /* stage number */ + uint32_t is_fg; /* control alpha & transp */ + uint32_t alpha; + uint32_t transp_mask; + uint32_t flags; + uint32_t id; + uint32_t user_data[8]; +}; + +struct mdp_histogram { + uint32_t frame_cnt; + uint32_t bin_cnt; + uint32_t *r; + uint32_t *g; + uint32_t *b; +}; + +struct mdp_page_protection { + uint32_t page_protection; +}; + + +struct msm_panel_common_pdata { + int gpio; + int (*backlight_level)(int level, int max, int min); + int (*pmic_backlight)(int level); + int (*panel_num)(void); + void (*panel_config_gpio)(int); + int *gpio_num; +}; + +struct lcdc_platform_data { + int (*lcdc_gpio_config)(int on); + void (*lcdc_power_save)(int); +}; + +struct tvenc_platform_data { + int (*pm_vid_en)(int on); +}; + +struct mddi_platform_data { + void (*mddi_power_save)(int on); + int (*mddi_sel_clk)(u32 *clk_rate); +}; + +struct msm_fb_platform_data { + int (*detect_client)(const char *name); + int mddi_prescan; + int (*allow_set_offset)(void); +}; + +struct msm_hdmi_platform_data { + int irq; + int (*cable_detect)(int insert); +}; + +#endif /*_MSM_MDP_H_*/ diff --git a/drivers/staging/msm/staging-devices.c b/drivers/staging/msm/staging-devices.c new file mode 100644 index 000000000000..0f8ec3e26013 --- /dev/null +++ b/drivers/staging/msm/staging-devices.c @@ -0,0 +1,323 @@ +#include <linux/kernel.h> +#include <linux/irq.h> +#include <linux/gpio.h> +#include <linux/platform_device.h> +#include <linux/bootmem.h> +#include <linux/delay.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/io.h> +#include <asm/setup.h> + +#include <mach/board.h> +#include <mach/irqs.h> +#include <mach/sirc.h> +#include <mach/gpio.h> + +#include "msm_mdp.h" +#include "memory_ll.h" +//#include "android_pmem.h" +#include <mach/board.h> + +#ifdef CONFIG_MSM_SOC_REV_A +#define MSM_SMI_BASE 0xE0000000 +#else +#define MSM_SMI_BASE 0x00000000 +#endif + + +#define TOUCHPAD_SUSPEND 34 +#define TOUCHPAD_IRQ 38 + +#define MSM_PMEM_MDP_SIZE 0x1591000 + +#ifdef CONFIG_MSM_SOC_REV_A +#define SMEM_SPINLOCK_I2C "D:I2C02000021" +#else +#define SMEM_SPINLOCK_I2C "S:6" +#endif + +#define MSM_PMEM_ADSP_SIZE 0x1C00000 + +#define MSM_FB_SIZE 0x500000 +#define MSM_FB_SIZE_ST15 0x800000 +#define MSM_AUDIO_SIZE 0x80000 +#define MSM_GPU_PHYS_SIZE SZ_2M + +#ifdef CONFIG_MSM_SOC_REV_A +#define MSM_SMI_BASE 0xE0000000 +#else +#define MSM_SMI_BASE 0x00000000 +#endif + +#define MSM_SHARED_RAM_PHYS (MSM_SMI_BASE + 0x00100000) + +#define MSM_PMEM_SMI_BASE (MSM_SMI_BASE + 0x02B00000) +#define MSM_PMEM_SMI_SIZE 0x01500000 + +#define MSM_FB_BASE MSM_PMEM_SMI_BASE +#define MSM_GPU_PHYS_BASE (MSM_FB_BASE + MSM_FB_SIZE) +#define MSM_PMEM_SMIPOOL_BASE (MSM_GPU_PHYS_BASE + MSM_GPU_PHYS_SIZE) +#define MSM_PMEM_SMIPOOL_SIZE (MSM_PMEM_SMI_SIZE - MSM_FB_SIZE \ + - MSM_GPU_PHYS_SIZE) + +#if defined(CONFIG_FB_MSM_MDP40) +#define MDP_BASE 0xA3F00000 +#define PMDH_BASE 0xAD600000 +#define EMDH_BASE 0xAD700000 +#define TVENC_BASE 0xAD400000 +#else +#define MDP_BASE 0xAA200000 +#define PMDH_BASE 0xAA600000 +#define EMDH_BASE 0xAA700000 +#define TVENC_BASE 0xAA400000 +#endif + +#define PMEM_KERNEL_EBI1_SIZE (CONFIG_PMEM_KERNEL_SIZE * 1024 * 1024) + +static struct resource msm_fb_resources[] = { + { + .flags = IORESOURCE_DMA, + } +}; + +static struct resource msm_mdp_resources[] = { + { + .name = "mdp", + .start = MDP_BASE, + .end = MDP_BASE + 0x000F0000 - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device msm_mdp_device = { + .name = "mdp", + .id = 0, + .num_resources = ARRAY_SIZE(msm_mdp_resources), + .resource = msm_mdp_resources, +}; + +static struct platform_device msm_lcdc_device = { + .name = "lcdc", + .id = 0, +}; + +static int msm_fb_detect_panel(const char *name) +{ + int ret = -EPERM; + + if (machine_is_qsd8x50_ffa() || machine_is_qsd8x50a_ffa()) { + if (!strncmp(name, "mddi_toshiba_wvga_pt", 20)) + ret = 0; + else + ret = -ENODEV; + } else if ((machine_is_qsd8x50_surf() || machine_is_qsd8x50a_surf()) + && !strcmp(name, "lcdc_external")) + ret = 0; + else if (0 /*machine_is_qsd8x50_grapefruit() */) { + if (!strcmp(name, "lcdc_grapefruit_vga")) + ret = 0; + else + ret = -ENODEV; + } else if (machine_is_qsd8x50_st1()) { + if (!strcmp(name, "lcdc_st1_wxga")) + ret = 0; + else + ret = -ENODEV; + } else if (machine_is_qsd8x50a_st1_5()) { + if (!strcmp(name, "lcdc_st15") || + !strcmp(name, "hdmi_sii9022")) + ret = 0; + else + ret = -ENODEV; + } + + return ret; +} + +/* Only allow a small subset of machines to set the offset via + FB PAN_DISPLAY */ + +static int msm_fb_allow_set_offset(void) +{ + return (machine_is_qsd8x50_st1() || + machine_is_qsd8x50a_st1_5()) ? 1 : 0; +} + + +static struct msm_fb_platform_data msm_fb_pdata = { + .detect_client = msm_fb_detect_panel, + .allow_set_offset = msm_fb_allow_set_offset, +}; + +static struct platform_device msm_fb_device = { + .name = "msm_fb", + .id = 0, + .num_resources = ARRAY_SIZE(msm_fb_resources), + .resource = msm_fb_resources, + .dev = { + .platform_data = &msm_fb_pdata, + } +}; + +static void __init qsd8x50_allocate_memory_regions(void) +{ + void *addr; + unsigned long size; + if (machine_is_qsd8x50a_st1_5()) + size = MSM_FB_SIZE_ST15; + else + size = MSM_FB_SIZE; + + addr = alloc_bootmem(size); // (void *)MSM_FB_BASE; + if (!addr) + printk("Failed to allocate bootmem for framebuffer\n"); + + + msm_fb_resources[0].start = __pa(addr); + msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1; + pr_info(KERN_ERR "using %lu bytes of SMI at %lx physical for fb\n", + size, (unsigned long)addr); +} + +static int msm_fb_lcdc_gpio_config(int on) +{ +// return 0; + if (machine_is_qsd8x50_st1()) { + if (on) { + gpio_set_value(32, 1); + mdelay(100); + gpio_set_value(20, 1); + gpio_set_value(17, 1); + gpio_set_value(19, 1); + } else { + gpio_set_value(17, 0); + gpio_set_value(19, 0); + gpio_set_value(20, 0); + mdelay(100); + gpio_set_value(32, 0); + } + } else if (machine_is_qsd8x50a_st1_5()) { + if (on) { + gpio_set_value(17, 1); + gpio_set_value(19, 1); + gpio_set_value(20, 1); + gpio_set_value(22, 0); + gpio_set_value(32, 1); + gpio_set_value(155, 1); + //st15_hdmi_power(1); + gpio_set_value(22, 1); + + } else { + gpio_set_value(17, 0); + gpio_set_value(19, 0); + gpio_set_value(22, 0); + gpio_set_value(32, 0); + gpio_set_value(155, 0); + // st15_hdmi_power(0); + } + } + return 0; +} + + +static struct lcdc_platform_data lcdc_pdata = { + .lcdc_gpio_config = msm_fb_lcdc_gpio_config, +}; + +static struct msm_gpio msm_fb_st15_gpio_config_data[] = { + { GPIO_CFG(17, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en0" }, + { GPIO_CFG(19, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "dat_pwr_sv" }, + { GPIO_CFG(20, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lvds_pwr_dn" }, + { GPIO_CFG(22, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en1" }, + { GPIO_CFG(32, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en2" }, + { GPIO_CFG(103, 0, GPIO_INPUT, GPIO_NO_PULL, GPIO_2MA), "hdmi_irq" }, + { GPIO_CFG(155, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "hdmi_3v3" }, +}; + +static struct msm_panel_common_pdata mdp_pdata = { + .gpio = 98, +}; + +static struct platform_device *devices[] __initdata = { + &msm_fb_device, +}; + + +static void __init msm_register_device(struct platform_device *pdev, void *data) +{ + int ret; + + pdev->dev.platform_data = data; + + ret = platform_device_register(pdev); + if (ret) + dev_err(&pdev->dev, + "%s: platform_device_register() failed = %d\n", + __func__, ret); +} + +void __init msm_fb_register_device(char *name, void *data) +{ + if (!strncmp(name, "mdp", 3)) + msm_register_device(&msm_mdp_device, data); +/* + else if (!strncmp(name, "pmdh", 4)) + msm_register_device(&msm_mddi_device, data); + else if (!strncmp(name, "emdh", 4)) + msm_register_device(&msm_mddi_ext_device, data); + else if (!strncmp(name, "ebi2", 4)) + msm_register_device(&msm_ebi2_lcd_device, data); + else if (!strncmp(name, "tvenc", 5)) + msm_register_device(&msm_tvenc_device, data); + else */ + + if (!strncmp(name, "lcdc", 4)) + msm_register_device(&msm_lcdc_device, data); + /*else + printk(KERN_ERR "%s: unknown device! %s\n", __func__, name); +*/ +} + +static void __init msm_fb_add_devices(void) +{ + int rc; + msm_fb_register_device("mdp", &mdp_pdata); +// msm_fb_register_device("pmdh", &mddi_pdata); +// msm_fb_register_device("emdh", &mddi_pdata); +// msm_fb_register_device("tvenc", 0); + + if (machine_is_qsd8x50a_st1_5()) { +/* rc = st15_hdmi_vreg_init(); + if (rc) + return; +*/ + rc = msm_gpios_request_enable( + msm_fb_st15_gpio_config_data, + ARRAY_SIZE(msm_fb_st15_gpio_config_data)); + if (rc) { + printk(KERN_ERR "%s: unable to init lcdc gpios\n", + __func__); + return; + } + msm_fb_register_device("lcdc", &lcdc_pdata); + } else + msm_fb_register_device("lcdc", 0); +} + +int __init staging_init_pmem(void) +{ + qsd8x50_allocate_memory_regions(); + return 0; +} + +int __init staging_init_devices(void) +{ + platform_add_devices(devices, ARRAY_SIZE(devices)); + msm_fb_add_devices(); + return 0; +} + +arch_initcall(staging_init_pmem); +arch_initcall(staging_init_devices); diff --git a/drivers/staging/msm/tv_ntsc.c b/drivers/staging/msm/tv_ntsc.c new file mode 100644 index 000000000000..5eb67611661a --- /dev/null +++ b/drivers/staging/msm/tv_ntsc.c @@ -0,0 +1,163 @@ +/* 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 "msm_fb.h" +#include "tvenc.h" + +#define NTSC_TV_DIMENSION_WIDTH 720 +#define NTSC_TV_DIMENSION_HEIGHT 480 + +static int ntsc_off(struct platform_device *pdev); +static int ntsc_on(struct platform_device *pdev); + +static int ntsc_on(struct platform_device *pdev) +{ + uint32 reg = 0; + int ret = 0; + struct msm_fb_data_type *mfd; + + mfd = platform_get_drvdata(pdev); + + if (!mfd) + return -ENODEV; + + if (mfd->key != MFD_KEY) + return -EINVAL; + + TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */ + + if (mfd->panel.id == NTSC_M) { + /* Cr gain 11, Cb gain C6, y_gain 97 */ + TV_OUT(TV_GAIN, 0x0081B697); + } else { + /* Cr gain 11, Cb gain C6, y_gain 97 */ + TV_OUT(TV_GAIN, 0x008bc4a3); + reg |= TVENC_CTL_NTSCJ_MODE; + } + + TV_OUT(TV_CGMS, 0x0); + /* NTSC Timing */ + TV_OUT(TV_SYNC_1, 0x0020009e); + TV_OUT(TV_SYNC_2, 0x011306B4); + TV_OUT(TV_SYNC_3, 0x0006000C); + TV_OUT(TV_SYNC_4, 0x0028020D); + TV_OUT(TV_SYNC_5, 0x005E02FB); + TV_OUT(TV_SYNC_6, 0x0006000C); + TV_OUT(TV_SYNC_7, 0x00000012); + TV_OUT(TV_BURST_V1, 0x0013020D); + TV_OUT(TV_BURST_V2, 0x0014020C); + TV_OUT(TV_BURST_V3, 0x0013020D); + TV_OUT(TV_BURST_V4, 0x0014020C); + TV_OUT(TV_BURST_H, 0x00AE00F2); + TV_OUT(TV_SOL_REQ_ODD, 0x00280208); + TV_OUT(TV_SOL_REQ_EVEN, 0x00290209); + + reg |= TVENC_CTL_TV_MODE_NTSC_M_PAL60; + + reg |= TVENC_CTL_Y_FILTER_EN | + TVENC_CTL_CR_FILTER_EN | + TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN; +#ifdef CONFIG_FB_MSM_TVOUT_SVIDEO + reg |= TVENC_CTL_S_VIDEO_EN; +#endif + + TV_OUT(TV_LEVEL, 0x00000000); /* DC offset to 0. */ + TV_OUT(TV_OFFSET, 0x008080f0); + +#ifdef CONFIG_FB_MSM_MDP31 + TV_OUT(TV_DAC_INTF, 0x29); +#endif + TV_OUT(TV_ENC_CTL, reg); + + reg |= TVENC_CTL_ENC_EN; + TV_OUT(TV_ENC_CTL, reg); + + return ret; +} + +static int ntsc_off(struct platform_device *pdev) +{ + TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */ + return 0; +} + +static int __init ntsc_probe(struct platform_device *pdev) +{ + msm_fb_add_device(pdev); + + return 0; +} + +static struct platform_driver this_driver = { + .probe = ntsc_probe, + .driver = { + .name = "tv_ntsc", + }, +}; + +static struct msm_fb_panel_data ntsc_panel_data = { + .panel_info.xres = NTSC_TV_DIMENSION_WIDTH, + .panel_info.yres = NTSC_TV_DIMENSION_HEIGHT, + .panel_info.type = TV_PANEL, + .panel_info.pdest = DISPLAY_1, + .panel_info.wait_cycle = 0, + .panel_info.bpp = 16, + .panel_info.fb_num = 2, + .on = ntsc_on, + .off = ntsc_off, +}; + +static struct platform_device this_device = { + .name = "tv_ntsc", + .id = 0, + .dev = { + .platform_data = &ntsc_panel_data, + } +}; + +static int __init ntsc_init(void) +{ + int ret; + + ret = platform_driver_register(&this_driver); + if (!ret) { + ret = platform_device_register(&this_device); + if (ret) + platform_driver_unregister(&this_driver); + } + + return ret; +} + +module_init(ntsc_init);
\ No newline at end of file diff --git a/drivers/staging/msm/tv_pal.c b/drivers/staging/msm/tv_pal.c new file mode 100644 index 000000000000..204da514660e --- /dev/null +++ b/drivers/staging/msm/tv_pal.c @@ -0,0 +1,213 @@ +/* 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 "msm_fb.h" +#include "tvenc.h" + +#ifdef CONFIG_FB_MSM_TVOUT_PAL_M +#define PAL_TV_DIMENSION_WIDTH 720 +#define PAL_TV_DIMENSION_HEIGHT 480 +#else +#define PAL_TV_DIMENSION_WIDTH 720 +#define PAL_TV_DIMENSION_HEIGHT 576 +#endif + +static int pal_on(struct platform_device *pdev) +{ + uint32 reg = 0; + int ret = 0; + struct msm_fb_data_type *mfd; + + mfd = platform_get_drvdata(pdev); + + if (!mfd) + return -ENODEV; + + if (mfd->key != MFD_KEY) + return -EINVAL; + + TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */ + + switch (mfd->panel.id) { + case PAL_BDGHIN: + /* Cr gain 11, Cb gain C6, y_gain 97 */ + TV_OUT(TV_GAIN, 0x0088c1a0); + TV_OUT(TV_CGMS, 0x00012345); + TV_OUT(TV_TEST_MUX, 0x0); + /* PAL Timing */ + TV_OUT(TV_SYNC_1, 0x00180097); + TV_OUT(TV_SYNC_2, 0x011f06c0); + TV_OUT(TV_SYNC_3, 0x0005000a); + TV_OUT(TV_SYNC_4, 0x00320271); + TV_OUT(TV_SYNC_5, 0x005602f9); + TV_OUT(TV_SYNC_6, 0x0005000a); + TV_OUT(TV_SYNC_7, 0x0000000f); + TV_OUT(TV_BURST_V1, 0x0012026e); + TV_OUT(TV_BURST_V2, 0x0011026d); + TV_OUT(TV_BURST_V3, 0x00100270); + TV_OUT(TV_BURST_V4, 0x0013026f); + TV_OUT(TV_BURST_H, 0x00af00ea); + TV_OUT(TV_SOL_REQ_ODD, 0x0030026e); + TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f); + + reg |= TVENC_CTL_TV_MODE_PAL_BDGHIN; + break; + case PAL_M: + /* Cr gain 11, Cb gain C6, y_gain 97 */ + TV_OUT(TV_GAIN, 0x0081b697); + TV_OUT(TV_CGMS, 0x000af317); + TV_OUT(TV_TEST_MUX, 0x000001c3); + TV_OUT(TV_TEST_MODE, 0x00000002); + /* PAL Timing */ + TV_OUT(TV_SYNC_1, 0x0020009e); + TV_OUT(TV_SYNC_2, 0x011306b4); + TV_OUT(TV_SYNC_3, 0x0006000c); + TV_OUT(TV_SYNC_4, 0x0028020D); + TV_OUT(TV_SYNC_5, 0x005e02fb); + TV_OUT(TV_SYNC_6, 0x0006000c); + TV_OUT(TV_SYNC_7, 0x00000012); + TV_OUT(TV_BURST_V1, 0x0012020b); + TV_OUT(TV_BURST_V2, 0x0016020c); + TV_OUT(TV_BURST_V3, 0x00150209); + TV_OUT(TV_BURST_V4, 0x0013020c); + TV_OUT(TV_BURST_H, 0x00bf010b); + TV_OUT(TV_SOL_REQ_ODD, 0x00280208); + TV_OUT(TV_SOL_REQ_EVEN, 0x00290209); + + reg |= TVENC_CTL_TV_MODE_PAL_M; + break; + case PAL_N: + /* Cr gain 11, Cb gain C6, y_gain 97 */ + TV_OUT(TV_GAIN, 0x0081b697); + TV_OUT(TV_CGMS, 0x000af317); + TV_OUT(TV_TEST_MUX, 0x000001c3); + TV_OUT(TV_TEST_MODE, 0x00000002); + /* PAL Timing */ + TV_OUT(TV_SYNC_1, 0x00180097); + TV_OUT(TV_SYNC_2, 0x12006c0); + TV_OUT(TV_SYNC_3, 0x0005000a); + TV_OUT(TV_SYNC_4, 0x00320271); + TV_OUT(TV_SYNC_5, 0x005602f9); + TV_OUT(TV_SYNC_6, 0x0005000a); + TV_OUT(TV_SYNC_7, 0x0000000f); + TV_OUT(TV_BURST_V1, 0x0012026e); + TV_OUT(TV_BURST_V2, 0x0011026d); + TV_OUT(TV_BURST_V3, 0x00100270); + TV_OUT(TV_BURST_V4, 0x0013026f); + TV_OUT(TV_BURST_H, 0x00af00fa); + TV_OUT(TV_SOL_REQ_ODD, 0x0030026e); + TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f); + + reg |= TVENC_CTL_TV_MODE_PAL_N; + break; + + default: + return -ENODEV; + } + + reg |= TVENC_CTL_Y_FILTER_EN | + TVENC_CTL_CR_FILTER_EN | + TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN; +#ifdef CONFIG_FB_MSM_TVOUT_SVIDEO + reg |= TVENC_CTL_S_VIDEO_EN; +#endif + + TV_OUT(TV_LEVEL, 0x00000000); /* DC offset to 0. */ + TV_OUT(TV_OFFSET, 0x008080f0); + +#ifdef CONFIG_FB_MSM_MDP31 + TV_OUT(TV_DAC_INTF, 0x29); +#endif + TV_OUT(TV_ENC_CTL, reg); + + reg |= TVENC_CTL_ENC_EN; + TV_OUT(TV_ENC_CTL, reg); + + return ret; +} + +static int pal_off(struct platform_device *pdev) +{ + TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */ + return 0; +} + +static int __init pal_probe(struct platform_device *pdev) +{ + msm_fb_add_device(pdev); + + return 0; +} + +static struct platform_driver this_driver = { + .probe = pal_probe, + .driver = { + .name = "tv_pal", + }, +}; + +static struct msm_fb_panel_data pal_panel_data = { + .panel_info.xres = PAL_TV_DIMENSION_WIDTH, + .panel_info.yres = PAL_TV_DIMENSION_HEIGHT, + .panel_info.type = TV_PANEL, + .panel_info.pdest = DISPLAY_1, + .panel_info.wait_cycle = 0, + .panel_info.bpp = 16, + .panel_info.fb_num = 2, + .on = pal_on, + .off = pal_off, +}; + +static struct platform_device this_device = { + .name = "tv_pal", + .id = 0, + .dev = { + .platform_data = &pal_panel_data, + } +}; + +static int __init pal_init(void) +{ + int ret; + + ret = platform_driver_register(&this_driver); + if (!ret) { + ret = platform_device_register(&this_device); + if (ret) + platform_driver_unregister(&this_driver); + } + + return ret; +} + +module_init(pal_init); diff --git a/drivers/staging/msm/tvenc.c b/drivers/staging/msm/tvenc.c new file mode 100644 index 000000000000..f41c5ac22f25 --- /dev/null +++ b/drivers/staging/msm/tvenc.c @@ -0,0 +1,295 @@ +/* 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> + +#define TVENC_C +#include "tvenc.h" +#include "msm_fb.h" + +static int tvenc_probe(struct platform_device *pdev); +static int tvenc_remove(struct platform_device *pdev); + +static int tvenc_off(struct platform_device *pdev); +static int tvenc_on(struct platform_device *pdev); + +static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; +static int pdev_list_cnt; + +static struct clk *tvenc_clk; +static struct clk *tvdac_clk; + +static struct platform_driver tvenc_driver = { + .probe = tvenc_probe, + .remove = tvenc_remove, + .suspend = NULL, +// .suspend_late = NULL, +// .resume_early = NULL, + .resume = NULL, + .shutdown = NULL, + .driver = { + .name = "tvenc", + }, +}; + +static struct tvenc_platform_data *tvenc_pdata; + +static int tvenc_off(struct platform_device *pdev) +{ + int ret = 0; + + ret = panel_next_off(pdev); + + clk_disable(tvenc_clk); + clk_disable(tvdac_clk); + + if (tvenc_pdata && tvenc_pdata->pm_vid_en) + ret = tvenc_pdata->pm_vid_en(0); + + //pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc", + // PM_QOS_DEFAULT_VALUE); + + if (ret) + printk(KERN_ERR "%s: pm_vid_en(off) failed! %d\n", + __func__, ret); + + return ret; +} + +static int tvenc_on(struct platform_device *pdev) +{ + int ret = 0; + +// pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc", +// 128000); + if (tvenc_pdata && tvenc_pdata->pm_vid_en) + ret = tvenc_pdata->pm_vid_en(1); + + if (ret) { + printk(KERN_ERR "%s: pm_vid_en(on) failed! %d\n", + __func__, ret); + return ret; + } + + clk_enable(tvenc_clk); + clk_enable(tvdac_clk); + + ret = panel_next_on(pdev); + + return ret; +} + +void tvenc_gen_test_pattern(struct msm_fb_data_type *mfd) +{ + uint32 reg = 0, i; + + reg = readl(MSM_TV_ENC_CTL); + reg |= TVENC_CTL_TEST_PATT_EN; + + for (i = 0; i < 3; i++) { + TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */ + + switch (i) { + /* + * TV Encoder - Color Bar Test Pattern + */ + case 0: + reg |= TVENC_CTL_TPG_CLRBAR; + break; + /* + * TV Encoder - Red Frame Test Pattern + */ + case 1: + reg |= TVENC_CTL_TPG_REDCLR; + break; + /* + * TV Encoder - Modulated Ramp Test Pattern + */ + default: + reg |= TVENC_CTL_TPG_MODRAMP; + break; + } + + TV_OUT(TV_ENC_CTL, reg); + mdelay(5000); + + switch (i) { + /* + * TV Encoder - Color Bar Test Pattern + */ + case 0: + reg &= ~TVENC_CTL_TPG_CLRBAR; + break; + /* + * TV Encoder - Red Frame Test Pattern + */ + case 1: + reg &= ~TVENC_CTL_TPG_REDCLR; + break; + /* + * TV Encoder - Modulated Ramp Test Pattern + */ + default: + reg &= ~TVENC_CTL_TPG_MODRAMP; + break; + } + } +} + +static int tvenc_resource_initialized; + +static int tvenc_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; + + if (pdev->id == 0) { + tvenc_base = ioremap(pdev->resource[0].start, + pdev->resource[0].end - + pdev->resource[0].start + 1); + if (!tvenc_base) { + printk(KERN_ERR + "tvenc_base ioremap failed!\n"); + return -ENOMEM; + } + tvenc_pdata = pdev->dev.platform_data; + tvenc_resource_initialized = 1; + return 0; + } + + if (!tvenc_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 (tvenc_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_TV; + + /* + * alloc panel device data + */ + if (platform_device_add_data + (mdp_dev, pdev->dev.platform_data, + sizeof(struct msm_fb_panel_data))) { + printk(KERN_ERR "tvenc_probe: platform_device_add_data failed!\n"); + platform_device_put(mdp_dev); + return -ENOMEM; + } + /* + * data chain + */ + pdata = mdp_dev->dev.platform_data; + pdata->on = tvenc_on; + pdata->off = tvenc_off; + pdata->next = pdev; + + /* + * get/set panel specific fb info + */ + mfd->panel_info = pdata->panel_info; + mfd->fb_imgType = MDP_YCRYCB_H2V1; + + /* + * set driver data + */ + platform_set_drvdata(mdp_dev, mfd); + + /* + * register in mdp driver + */ + rc = platform_device_add(mdp_dev); + if (rc) + goto tvenc_probe_err; + + pdev_list[pdev_list_cnt++] = pdev; + return 0; + +tvenc_probe_err: + platform_device_put(mdp_dev); + return rc; +} + +static int tvenc_remove(struct platform_device *pdev) +{ +// pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc"); + return 0; +} + +static int tvenc_register_driver(void) +{ + return platform_driver_register(&tvenc_driver); +} + +static int __init tvenc_driver_init(void) +{ + tvenc_clk = clk_get(NULL, "tv_enc_clk"); + tvdac_clk = clk_get(NULL, "tv_dac_clk"); + + if (IS_ERR(tvenc_clk)) { + printk(KERN_ERR "error: can't get tvenc_clk!\n"); + return IS_ERR(tvenc_clk); + } + + if (IS_ERR(tvdac_clk)) { + printk(KERN_ERR "error: can't get tvdac_clk!\n"); + return IS_ERR(tvdac_clk); + } + +// pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc", +// PM_QOS_DEFAULT_VALUE); + return tvenc_register_driver(); +} + +module_init(tvenc_driver_init); diff --git a/drivers/staging/msm/tvenc.h b/drivers/staging/msm/tvenc.h new file mode 100644 index 000000000000..a682dbebcf7d --- /dev/null +++ b/drivers/staging/msm/tvenc.h @@ -0,0 +1,117 @@ +/* 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 TVENC_H +#define TVENC_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 <mach/hardware.h> +#include <linux/io.h> + +#include <asm/system.h> +#include <asm/mach-types.h> + +#include "msm_fb_panel.h" + +#define NTSC_M 0 /* North America, Korea */ +#define NTSC_J 1 /* Japan */ +#define PAL_BDGHIN 2 /* Non-argentina PAL-N */ +#define PAL_M 3 /* PAL-M */ +#define PAL_N 4 /* Argentina PAL-N */ + +/* 3.57954545 Mhz */ +#define TVENC_CTL_TV_MODE_NTSC_M_PAL60 0 +/* 3.57961149 Mhz */ +#define TVENC_CTL_TV_MODE_PAL_M BIT(0) +/*non-Argintina = 4.3361875 Mhz */ +#define TVENC_CTL_TV_MODE_PAL_BDGHIN BIT(1) +/*Argentina = 3.582055625 Mhz */ +#define TVENC_CTL_TV_MODE_PAL_N (BIT(1)|BIT(0)) + +#define TVENC_CTL_ENC_EN BIT(2) +#define TVENC_CTL_CC_EN BIT(3) +#define TVENC_CTL_CGMS_EN BIT(4) +#define TVENC_CTL_MACRO_EN BIT(5) +#define TVENC_CTL_Y_FILTER_W_NOTCH BIT(6) +#define TVENC_CTL_Y_FILTER_WO_NOTCH 0 +#define TVENC_CTL_Y_FILTER_EN BIT(7) +#define TVENC_CTL_CR_FILTER_EN BIT(8) +#define TVENC_CTL_CB_FILTER_EN BIT(9) +#define TVENC_CTL_SINX_FILTER_EN BIT(10) +#define TVENC_CTL_TEST_PATT_EN BIT(11) +#define TVENC_CTL_OUTPUT_INV BIT(12) +#define TVENC_CTL_PAL60_MODE BIT(13) +#define TVENC_CTL_NTSCJ_MODE BIT(14) +#define TVENC_CTL_TPG_CLRBAR 0 +#define TVENC_CTL_TPG_MODRAMP BIT(15) +#define TVENC_CTL_TPG_REDCLR BIT(16) +#define TVENC_CTL_S_VIDEO_EN BIT(19) + +#ifdef TVENC_C +void *tvenc_base; +#else +extern void *tvenc_base; +#endif + +#define TV_OUT(reg, v) writel(v, tvenc_base + MSM_##reg) + +#define MSM_TV_ENC_CTL 0x00 +#define MSM_TV_LEVEL 0x04 +#define MSM_TV_GAIN 0x08 +#define MSM_TV_OFFSET 0x0c +#define MSM_TV_CGMS 0x10 +#define MSM_TV_SYNC_1 0x14 +#define MSM_TV_SYNC_2 0x18 +#define MSM_TV_SYNC_3 0x1c +#define MSM_TV_SYNC_4 0x20 +#define MSM_TV_SYNC_5 0x24 +#define MSM_TV_SYNC_6 0x28 +#define MSM_TV_SYNC_7 0x2c +#define MSM_TV_BURST_V1 0x30 +#define MSM_TV_BURST_V2 0x34 +#define MSM_TV_BURST_V3 0x38 +#define MSM_TV_BURST_V4 0x3c +#define MSM_TV_BURST_H 0x40 +#define MSM_TV_SOL_REQ_ODD 0x44 +#define MSM_TV_SOL_REQ_EVEN 0x48 +#define MSM_TV_DAC_CTL 0x4c +#define MSM_TV_TEST_MUX 0x50 +#define MSM_TV_TEST_MODE 0x54 +#define MSM_TV_TEST_MISR_RESET 0x58 +#define MSM_TV_TEST_EXPORT_MISR 0x5c +#define MSM_TV_TEST_MISR_CURR_VAL 0x60 +#define MSM_TV_TEST_SOF_CFG 0x64 +#define MSM_TV_DAC_INTF 0x100 + +#endif /* TVENC_H */ diff --git a/drivers/staging/phison/Kconfig b/drivers/staging/phison/Kconfig index d3c65d315a2e..1b56119a7657 100644 --- a/drivers/staging/phison/Kconfig +++ b/drivers/staging/phison/Kconfig @@ -1,5 +1,5 @@ config IDE_PHISON tristate "PCIE ATA PS5000 IDE support" - depends on PCI && ATA && ATA_SFF + depends on PCI && ATA && ATA_SFF && ATA_BMDMA ---help--- This is an experimental driver for PS5000 IDE driver. diff --git a/drivers/staging/rar_register/Kconfig b/drivers/staging/rar_register/Kconfig deleted file mode 100644 index e9c27738199b..000000000000 --- a/drivers/staging/rar_register/Kconfig +++ /dev/null @@ -1,30 +0,0 @@ -# -# RAR device configuration -# - -menu "RAR Register Driver" -# -# Restricted Access Register Manager -# -config RAR_REGISTER - tristate "Restricted Access Region Register Driver" - depends on PCI - default n - ---help--- - This driver allows other kernel drivers access to the - contents of the restricted access region control registers. - - The restricted access region control registers - (rar_registers) are used to pass address and - locking information on restricted access regions - to other drivers that use restricted access regions. - - The restricted access regions are regions of memory - on the Intel MID Platform that are not accessible to - the x86 processor, but are accessible to dedicated - processors on board peripheral devices. - - The purpose of the restricted access regions is to - protect sensitive data from compromise by unauthorized - programs running on the x86 processor. -endmenu diff --git a/drivers/staging/rar_register/Makefile b/drivers/staging/rar_register/Makefile deleted file mode 100644 index d5954ccc16c9..000000000000 --- a/drivers/staging/rar_register/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -EXTRA_CFLAGS += -DLITTLE__ENDIAN -obj-$(CONFIG_RAR_REGISTER) += rar_register.o diff --git a/drivers/staging/rar_register/rar_register.c b/drivers/staging/rar_register/rar_register.c deleted file mode 100644 index 618503f422ef..000000000000 --- a/drivers/staging/rar_register/rar_register.c +++ /dev/null @@ -1,675 +0,0 @@ -/* - * rar_register.c - An Intel Restricted Access Region register driver - * - * Copyright(c) 2009 Intel Corporation. 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 as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * 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., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * ------------------------------------------------------------------- - * 20091204 Mark Allyn <mark.a.allyn@intel.com> - * Ossama Othman <ossama.othman@intel.com> - * Cleanup per feedback from Alan Cox and Arjan Van De Ven - * - * 20090806 Ossama Othman <ossama.othman@intel.com> - * Return zero high address if upper 22 bits is zero. - * Cleaned up checkpatch errors. - * Clarified that driver is dealing with bus addresses. - * - * 20090702 Ossama Othman <ossama.othman@intel.com> - * Removed unnecessary include directives - * Cleaned up spinlocks. - * Cleaned up logging. - * Improved invalid parameter checks. - * Fixed and simplified RAR address retrieval and RAR locking - * code. - * - * 20090626 Mark Allyn <mark.a.allyn@intel.com> - * Initial publish - */ - -#define DEBUG 1 - -#include "rar_register.h" - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/spinlock.h> -#include <linux/device.h> -#include <linux/kernel.h> - -/* === Lincroft Message Bus Interface === */ -#define LNC_MCR_OFFSET 0xD0 /* Message Control Register */ -#define LNC_MDR_OFFSET 0xD4 /* Message Data Register */ - -/* Message Opcodes */ -#define LNC_MESSAGE_READ_OPCODE 0xD0 -#define LNC_MESSAGE_WRITE_OPCODE 0xE0 - -/* Message Write Byte Enables */ -#define LNC_MESSAGE_BYTE_WRITE_ENABLES 0xF - -/* B-unit Port */ -#define LNC_BUNIT_PORT 0x3 - -/* === Lincroft B-Unit Registers - Programmed by IA32 firmware === */ -#define LNC_BRAR0L 0x10 -#define LNC_BRAR0H 0x11 -#define LNC_BRAR1L 0x12 -#define LNC_BRAR1H 0x13 -/* Reserved for SeP */ -#define LNC_BRAR2L 0x14 -#define LNC_BRAR2H 0x15 - -/* Moorestown supports three restricted access regions. */ -#define MRST_NUM_RAR 3 - -/* RAR Bus Address Range */ -struct rar_addr { - dma_addr_t low; - dma_addr_t high; -}; - -/* - * We create one of these for each RAR - */ -struct client { - int (*callback)(unsigned long data); - unsigned long driver_priv; - bool busy; -}; - -static DEFINE_MUTEX(rar_mutex); -static DEFINE_MUTEX(lnc_reg_mutex); - -/* - * One per RAR device (currently only one device) - */ -struct rar_device { - struct rar_addr rar_addr[MRST_NUM_RAR]; - struct pci_dev *rar_dev; - bool registered; - bool allocated; - struct client client[MRST_NUM_RAR]; -}; - -/* Current platforms have only one rar_device for 3 rar regions */ -static struct rar_device my_rar_device; - -/* - * Abstract out multiple device support. Current platforms only - * have a single RAR device. - */ - -/** - * alloc_rar_device - return a new RAR structure - * - * Return a new (but not yet ready) RAR device object - */ -static struct rar_device *alloc_rar_device(void) -{ - if (my_rar_device.allocated) - return NULL; - my_rar_device.allocated = 1; - return &my_rar_device; -} - -/** - * free_rar_device - free a RAR object - * @rar: the RAR device being freed - * - * Release a RAR object and any attached resources - */ -static void free_rar_device(struct rar_device *rar) -{ - pci_dev_put(rar->rar_dev); - rar->allocated = 0; -} - -/** - * _rar_to_device - return the device handling this RAR - * @rar: RAR number - * @off: returned offset - * - * Internal helper for looking up RAR devices. This and alloc are the - * two functions that need touching to go to multiple RAR devices. - */ -static struct rar_device *_rar_to_device(int rar, int *off) -{ - if (rar >= 0 && rar <= 3) { - *off = rar; - return &my_rar_device; - } - return NULL; -} - - -/** - * rar_to_device - return the device handling this RAR - * @rar: RAR number - * @off: returned offset - * - * Return the device this RAR maps to if one is present, otherwise - * returns NULL. Reports the offset relative to the base of this - * RAR device in off. - */ -static struct rar_device *rar_to_device(int rar, int *off) -{ - struct rar_device *rar_dev = _rar_to_device(rar, off); - if (rar_dev == NULL || !rar_dev->registered) - return NULL; - return rar_dev; -} - -/** - * rar_to_client - return the client handling this RAR - * @rar: RAR number - * - * Return the client this RAR maps to if a mapping is known, otherwise - * returns NULL. - */ -static struct client *rar_to_client(int rar) -{ - int idx; - struct rar_device *r = _rar_to_device(rar, &idx); - if (r != NULL) - return &r->client[idx]; - return NULL; -} - -/** - * rar_read_addr - retrieve a RAR mapping - * @pdev: PCI device for the RAR - * @offset: offset for message - * @addr: returned address - * - * Reads the address of a given RAR register. Returns 0 on success - * or an error code on failure. - */ -static int rar_read_addr(struct pci_dev *pdev, int offset, dma_addr_t *addr) -{ - /* - * ======== The Lincroft Message Bus Interface ======== - * Lincroft registers may be obtained via PCI from - * the host bridge using the Lincroft Message Bus - * Interface. That message bus interface is generally - * comprised of two registers: a control register (MCR, 0xDO) - * and a data register (MDR, 0xD4). - * - * The MCR (message control register) format is the following: - * 1. [31:24]: Opcode - * 2. [23:16]: Port - * 3. [15:8]: Register Offset - * 4. [7:4]: Byte Enables (use 0xF to set all of these bits - * to 1) - * 5. [3:0]: reserved - * - * Read (0xD0) and write (0xE0) opcodes are written to the - * control register when reading and writing to Lincroft - * registers, respectively. - * - * We're interested in registers found in the Lincroft - * B-unit. The B-unit port is 0x3. - * - * The six B-unit RAR register offsets we use are listed - * earlier in this file. - * - * Lastly writing to the MCR register requires the "Byte - * enables" bits to be set to 1. This may be achieved by - * writing 0xF at bit 4. - * - * The MDR (message data register) format is the following: - * 1. [31:0]: Read/Write Data - * - * Data being read from this register is only available after - * writing the appropriate control message to the MCR - * register. - * - * Data being written to this register must be written before - * writing the appropriate control message to the MCR - * register. - */ - - int result; - u32 addr32; - - /* Construct control message */ - u32 const message = - (LNC_MESSAGE_READ_OPCODE << 24) - | (LNC_BUNIT_PORT << 16) - | (offset << 8) - | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4); - - dev_dbg(&pdev->dev, "Offset for 'get' LNC MSG is %x\n", offset); - - /* - * We synchronize access to the Lincroft MCR and MDR registers - * until BOTH the command is issued through the MCR register - * and the corresponding data is read from the MDR register. - * Otherwise a race condition would exist between accesses to - * both registers. - */ - - mutex_lock(&lnc_reg_mutex); - - /* Send the control message */ - result = pci_write_config_dword(pdev, LNC_MCR_OFFSET, message); - if (!result) { - /* Read back the address as a 32bit value */ - result = pci_read_config_dword(pdev, LNC_MDR_OFFSET, &addr32); - *addr = (dma_addr_t)addr32; - } - mutex_unlock(&lnc_reg_mutex); - return result; -} - -/** - * rar_set_addr - Set a RAR mapping - * @pdev: PCI device for the RAR - * @offset: offset for message - * @addr: address to set - * - * Sets the address of a given RAR register. Returns 0 on success - * or an error code on failure. - */ -static int rar_set_addr(struct pci_dev *pdev, - int offset, - dma_addr_t addr) -{ - /* - * Data being written to this register must be written before - * writing the appropriate control message to the MCR - * register. - * See rar_get_addrs() for a description of the - * message bus interface being used here. - */ - - int result; - - /* Construct control message */ - u32 const message = (LNC_MESSAGE_WRITE_OPCODE << 24) - | (LNC_BUNIT_PORT << 16) - | (offset << 8) - | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4); - - /* - * We synchronize access to the Lincroft MCR and MDR registers - * until BOTH the command is issued through the MCR register - * and the corresponding data is read from the MDR register. - * Otherwise a race condition would exist between accesses to - * both registers. - */ - - mutex_lock(&lnc_reg_mutex); - - /* Send the control message */ - result = pci_write_config_dword(pdev, LNC_MDR_OFFSET, addr); - if (!result) - /* And address */ - result = pci_write_config_dword(pdev, LNC_MCR_OFFSET, message); - - mutex_unlock(&lnc_reg_mutex); - return result; -} - -/* - * rar_init_params - Initialize RAR parameters - * @rar: RAR device to initialise - * - * Initialize RAR parameters, such as bus addresses, etc. Returns 0 - * on success, or an error code on failure. - */ -static int init_rar_params(struct rar_device *rar) -{ - struct pci_dev *pdev = rar->rar_dev; - unsigned int i; - int result = 0; - int offset = 0x10; /* RAR 0 to 2 in order low/high/low/high/... */ - - /* Retrieve RAR start and end bus addresses. - * Access the RAR registers through the Lincroft Message Bus - * Interface on PCI device: 00:00.0 Host bridge. - */ - - for (i = 0; i < MRST_NUM_RAR; ++i) { - struct rar_addr *addr = &rar->rar_addr[i]; - - result = rar_read_addr(pdev, offset++, &addr->low); - if (result != 0) - return result; - - result = rar_read_addr(pdev, offset++, &addr->high); - if (result != 0) - return result; - - - /* - * Only the upper 22 bits of the RAR addresses are - * stored in their corresponding RAR registers so we - * must set the lower 10 bits accordingly. - - * The low address has its lower 10 bits cleared, and - * the high address has all its lower 10 bits set, - * e.g.: - * low = 0x2ffffc00 - */ - - addr->low &= (dma_addr_t)0xfffffc00u; - - /* - * Set bits 9:0 on uppser address if bits 31:10 are non - * zero; otherwize clear all bits - */ - - if ((addr->high & 0xfffffc00u) == 0) - addr->high = 0; - else - addr->high |= 0x3ffu; - } - /* Done accessing the device. */ - - if (result == 0) { - for (i = 0; i != MRST_NUM_RAR; ++i) { - /* - * "BRAR" refers to the RAR registers in the - * Lincroft B-unit. - */ - dev_info(&pdev->dev, "BRAR[%u] bus address range = " - "[%lx, %lx]\n", i, - (unsigned long)rar->rar_addr[i].low, - (unsigned long)rar->rar_addr[i].high); - } - } - return result; -} - -/** - * rar_get_address - get the bus address in a RAR - * @start: return value of start address of block - * @end: return value of end address of block - * - * The rar_get_address function is used by other device drivers - * to obtain RAR address information on a RAR. It takes three - * parameters: - * - * The function returns a 0 upon success or an error if there is no RAR - * facility on this system. - */ -int rar_get_address(int rar_index, dma_addr_t *start, dma_addr_t *end) -{ - int idx; - struct rar_device *rar = rar_to_device(rar_index, &idx); - - if (rar == NULL) { - WARN_ON(1); - return -ENODEV; - } - - *start = rar->rar_addr[idx].low; - *end = rar->rar_addr[idx].high; - return 0; -} -EXPORT_SYMBOL(rar_get_address); - -/** - * rar_lock - lock a RAR register - * @rar_index: RAR to lock (0-2) - * - * The rar_lock function is ued by other device drivers to lock an RAR. - * once a RAR is locked, it stays locked until the next system reboot. - * - * The function returns a 0 upon success or an error if there is no RAR - * facility on this system, or the locking fails - */ -int rar_lock(int rar_index) -{ - struct rar_device *rar; - int result; - int idx; - dma_addr_t low, high; - - rar = rar_to_device(rar_index, &idx); - - if (rar == NULL) { - WARN_ON(1); - return -EINVAL; - } - - low = rar->rar_addr[idx].low & 0xfffffc00u; - high = rar->rar_addr[idx].high & 0xfffffc00u; - - /* - * Only allow I/O from the graphics and Langwell; - * not from the x86 processor - */ - - if (rar_index == RAR_TYPE_VIDEO) { - low |= 0x00000009; - high |= 0x00000015; - } else if (rar_index == RAR_TYPE_AUDIO) { - /* Only allow I/O from Langwell; nothing from x86 */ - low |= 0x00000008; - high |= 0x00000018; - } else - /* Read-only from all agents */ - high |= 0x00000018; - - /* - * Now program the register using the Lincroft message - * bus interface. - */ - result = rar_set_addr(rar->rar_dev, - 2 * idx, low); - - if (result == 0) - result = rar_set_addr(rar->rar_dev, - 2 * idx + 1, high); - - return result; -} -EXPORT_SYMBOL(rar_lock); - -/** - * register_rar - register a RAR handler - * @num: RAR we wish to register for - * @callback: function to call when RAR support is available - * @data: data to pass to this function - * - * The register_rar function is to used by other device drivers - * to ensure that this driver is ready. As we cannot be sure of - * the compile/execute order of drivers in ther kernel, it is - * best to give this driver a callback function to call when - * it is ready to give out addresses. The callback function - * would have those steps that continue the initialization of - * a driver that do require a valid RAR address. One of those - * steps would be to call rar_get_address() - * - * This function return 0 on success an error code on failure. - */ -int register_rar(int num, int (*callback)(unsigned long data), - unsigned long data) -{ - /* For now we hardcode a single RAR device */ - struct rar_device *rar; - struct client *c; - int idx; - int retval = 0; - - mutex_lock(&rar_mutex); - - /* Do we have a client mapping for this RAR number ? */ - c = rar_to_client(num); - if (c == NULL) { - retval = -ERANGE; - goto done; - } - /* Is it claimed ? */ - if (c->busy) { - retval = -EBUSY; - goto done; - } - c->busy = 1; - - /* See if we have a handler for this RAR yet, if we do then fire it */ - rar = rar_to_device(num, &idx); - - if (rar) { - /* - * if the driver already registered, then we can simply - * call the callback right now - */ - (*callback)(data); - goto done; - } - - /* Arrange to be called back when the hardware is found */ - c->callback = callback; - c->driver_priv = data; -done: - mutex_unlock(&rar_mutex); - return retval; -} -EXPORT_SYMBOL(register_rar); - -/** - * unregister_rar - release a RAR allocation - * @num: RAR number - * - * Releases a RAR allocation, or pending allocation. If a callback is - * pending then this function will either complete before the unregister - * returns or not at all. - */ - -void unregister_rar(int num) -{ - struct client *c; - - mutex_lock(&rar_mutex); - c = rar_to_client(num); - if (c == NULL || !c->busy) - WARN_ON(1); - else - c->busy = 0; - mutex_unlock(&rar_mutex); -} -EXPORT_SYMBOL(unregister_rar); - -/** - * rar_callback - Process callbacks - * @rar: new RAR device - * - * Process the callbacks for a newly found RAR device. - */ - -static void rar_callback(struct rar_device *rar) -{ - struct client *c = &rar->client[0]; - int i; - - mutex_lock(&rar_mutex); - - rar->registered = 1; /* Ensure no more callbacks queue */ - - for (i = 0; i < MRST_NUM_RAR; i++) { - if (c->callback && c->busy) { - c->callback(c->driver_priv); - c->callback = NULL; - } - c++; - } - mutex_unlock(&rar_mutex); -} - -/** - * rar_probe - PCI probe callback - * @dev: PCI device - * @id: matching entry in the match table - * - * A RAR device has been discovered. Initialise it and if successful - * process any pending callbacks that can now be completed. - */ -static int rar_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int error; - struct rar_device *rar; - - dev_dbg(&dev->dev, "PCI probe starting\n"); - - rar = alloc_rar_device(); - if (rar == NULL) - return -EBUSY; - - /* Enable the device */ - error = pci_enable_device(dev); - if (error) { - dev_err(&dev->dev, - "Error enabling RAR register PCI device\n"); - goto end_function; - } - - /* Fill in the rar_device structure */ - rar->rar_dev = pci_dev_get(dev); - pci_set_drvdata(dev, rar); - - /* - * Initialize the RAR parameters, which have to be retrieved - * via the message bus interface. - */ - error = init_rar_params(rar); - if (error) { - pci_disable_device(dev); - dev_err(&dev->dev, "Error retrieving RAR addresses\n"); - goto end_function; - } - /* now call anyone who has registered (using callbacks) */ - rar_callback(rar); - return 0; -end_function: - free_rar_device(rar); - return error; -} - -const struct pci_device_id rar_pci_id_tbl[] = { - { PCI_VDEVICE(INTEL, 0x4110) }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl); - -const struct pci_device_id *my_id_table = rar_pci_id_tbl; - -/* field for registering driver to PCI device */ -static struct pci_driver rar_pci_driver = { - .name = "rar_register_driver", - .id_table = rar_pci_id_tbl, - .probe = rar_probe, - /* Cannot be unplugged - no remove */ -}; - -static int __init rar_init_handler(void) -{ - return pci_register_driver(&rar_pci_driver); -} - -static void __exit rar_exit_handler(void) -{ - pci_unregister_driver(&rar_pci_driver); -} - -module_init(rar_init_handler); -module_exit(rar_exit_handler); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Intel Restricted Access Region Register Driver"); diff --git a/drivers/staging/rar_register/rar_register.h b/drivers/staging/rar_register/rar_register.h deleted file mode 100644 index ffa805780f85..000000000000 --- a/drivers/staging/rar_register/rar_register.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General - * Public License as published by the Free Software Foundation. - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * The full GNU General Public License is included in this - * distribution in the file called COPYING. - */ - - -#ifndef _RAR_REGISTER_H -#define _RAR_REGISTER_H - -#include <linux/types.h> - -/* following are used both in drivers as well as user space apps */ - -#define RAR_TYPE_VIDEO 0 -#define RAR_TYPE_AUDIO 1 -#define RAR_TYPE_IMAGE 2 -#define RAR_TYPE_DATA 3 - -#ifdef __KERNEL__ - -struct rar_device; - -int register_rar(int num, - int (*callback)(unsigned long data), unsigned long data); -void unregister_rar(int num); -int rar_get_address(int rar_index, dma_addr_t *start, dma_addr_t *end); -int rar_lock(int rar_index); - -#endif /* __KERNEL__ */ -#endif /* _RAR_REGISTER_H */ diff --git a/drivers/staging/rt2860/sta_ioctl.c b/drivers/staging/rt2860/sta_ioctl.c index 112da7a6c417..6b8268d3dc75 100644 --- a/drivers/staging/rt2860/sta_ioctl.c +++ b/drivers/staging/rt2860/sta_ioctl.c @@ -2522,6 +2522,8 @@ int rt28xx_sta_ioctl(IN struct net_device *net_dev, Status = copy_to_user(erq->pointer, pAd->nickname, erq->length); + if (Status) + Status = -EFAULT; break; } case SIOCGIWRATE: /*get default bit rate (bps) */ diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c index b740662d095a..674769d2b59b 100644 --- a/drivers/staging/rt2860/usb_main_dev.c +++ b/drivers/staging/rt2860/usb_main_dev.c @@ -77,6 +77,7 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x083A, 0x7522)}, /* Arcadyan */ {USB_DEVICE(0x0CDE, 0x0022)}, /* ZCOM */ {USB_DEVICE(0x0586, 0x3416)}, /* Zyxel */ + {USB_DEVICE(0x0586, 0x341a)}, /* Zyxel NWD-270N */ {USB_DEVICE(0x0CDE, 0x0025)}, /* Zyxel */ {USB_DEVICE(0x1740, 0x9701)}, /* EnGenius */ {USB_DEVICE(0x1740, 0x9702)}, /* EnGenius */ diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index dacefea78113..49ab9fa9ffa7 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -66,8 +66,6 @@ static int hwseqnum = 0; static int hwwep = 0; static int channels = 0x3fff; -#define eqMacAddr(a, b) (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1 : 0) -#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5]) MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl); MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index 447d6474a70c..1b6890611fb6 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c @@ -112,28 +112,29 @@ u32 rt_global_debug_component = \ #define CAM_CONTENT_COUNT 8 static const struct usb_device_id rtl8192_usb_id_tbl[] = { - /* Realtek */ - {USB_DEVICE(0x0bda, 0x8171)}, - {USB_DEVICE(0x0bda, 0x8192)}, - {USB_DEVICE(0x0bda, 0x8709)}, - /* Corega */ - {USB_DEVICE(0x07aa, 0x0043)}, - /* Belkin */ - {USB_DEVICE(0x050d, 0x805E)}, - {USB_DEVICE(0x050d, 0x815F)}, /* Belkin F5D8053 v6 */ - /* Sitecom */ - {USB_DEVICE(0x0df6, 0x0031)}, - {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */ - /* EnGenius */ - {USB_DEVICE(0x1740, 0x9201)}, - /* Dlink */ - {USB_DEVICE(0x2001, 0x3301)}, - /* Zinwell */ - {USB_DEVICE(0x5a57, 0x0290)}, - /* Guillemot */ - {USB_DEVICE(0x06f8, 0xe031)}, - //92SU + {USB_DEVICE(0x0bda, 0x8171)}, /* Realtek */ {USB_DEVICE(0x0bda, 0x8172)}, + {USB_DEVICE(0x0bda, 0x8173)}, + {USB_DEVICE(0x0bda, 0x8174)}, + {USB_DEVICE(0x0bda, 0x8712)}, + {USB_DEVICE(0x0bda, 0x8713)}, + {USB_DEVICE(0x07aa, 0x0047)}, + {USB_DEVICE(0x07d1, 0x3303)}, + {USB_DEVICE(0x07d1, 0x3302)}, + {USB_DEVICE(0x07d1, 0x3300)}, + {USB_DEVICE(0x1740, 0x9603)}, + {USB_DEVICE(0x1740, 0x9605)}, + {USB_DEVICE(0x050d, 0x815F)}, + {USB_DEVICE(0x06f8, 0xe031)}, + {USB_DEVICE(0x7392, 0x7611)}, + {USB_DEVICE(0x7392, 0x7612)}, + {USB_DEVICE(0x7392, 0x7622)}, + {USB_DEVICE(0x0DF6, 0x0045)}, + {USB_DEVICE(0x0E66, 0x0015)}, + {USB_DEVICE(0x0E66, 0x0016)}, + {USB_DEVICE(0x0b05, 0x1786)}, + /* these are not in the official list */ + {USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */ {} }; diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 2bede271a2f0..f38472c2e75c 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -121,6 +121,8 @@ static const struct usb_device_id rtl8192_usb_id_tbl[] = { {USB_DEVICE(0x2001, 0x3301)}, /* Zinwell */ {USB_DEVICE(0x5a57, 0x0290)}, + /* LG */ + {USB_DEVICE(0x043e, 0x7a01)}, {} }; diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c index 0332c370fd82..ecbde3467b1b 100644 --- a/drivers/staging/sep/sep_driver.c +++ b/drivers/staging/sep/sep_driver.c @@ -594,8 +594,10 @@ static int sep_allocate_data_pool_memory_handler(struct sep_device *sep, dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n"); error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_alloc_t)); - if (error) + if (error) { + error = -EFAULT; goto end_function; + } /* allocate memory */ if ((sep->data_pool_bytes_allocated + command_args.num_bytes) > SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) { @@ -609,8 +611,10 @@ static int sep_allocate_data_pool_memory_handler(struct sep_device *sep, /* write the memory back to the user space */ error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_alloc_t)); - if (error) + if (error) { + error = -EFAULT; goto end_function; + } /* set the allocation */ sep->data_pool_bytes_allocated += command_args.num_bytes; @@ -661,6 +665,8 @@ static int sep_write_into_data_pool_handler(struct sep_device *sep, unsigned lon } /* copy the application data */ error = copy_from_user(virt_address, (void *) app_in_address, num_bytes); + if (error) + error = -EFAULT; end_function: dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n"); return error; @@ -711,6 +717,8 @@ static int sep_read_from_data_pool_handler(struct sep_device *sep, unsigned long /* copy the application data */ error = copy_to_user((void *) app_out_address, virt_address, num_bytes); + if (error) + error = -EFAULT; end_function: dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n"); return error; @@ -1448,8 +1456,10 @@ static int sep_create_sync_dma_tables_handler(struct sep_device *sep, dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n"); error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t)); - if (error) + if (error) { + error = -EFAULT; goto end_function; + } edbg("app_in_address is %08lx\n", command_args.app_in_address); edbg("app_out_address is %08lx\n", command_args.app_out_address); @@ -1799,8 +1809,10 @@ static int sep_create_flow_dma_tables_handler(struct sep_device *sep, goto end_function; error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_flow_table_t)); - if (error) + if (error) { + error = -EFAULT; goto end_function; + } /* create flow tables */ error = sep_prepare_flow_dma_tables(sep, command_args.num_virtual_buffers, command_args.virt_buff_data_addr, flow_context_ptr, &first_table_data, &last_table_data, command_args.isKernelVirtualAddress); @@ -1819,8 +1831,10 @@ static int sep_create_flow_dma_tables_handler(struct sep_device *sep, /* send the parameters to user application */ error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_build_flow_table_t)); - if (error) + if (error) { + error = -EFAULT; goto end_function_with_error; + } /* all the flow created - update the flow entry with temp id */ flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID; @@ -1861,8 +1875,10 @@ static int sep_add_flow_tables_handler(struct sep_device *sep, unsigned long arg /* get input parameters */ error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_flow_table_t)); - if (error) + if (error) { + error = -EFAULT; goto end_function; + } /* find the flow structure for the flow id */ flow_context_ptr = sep_find_flow_context(sep, command_args.flow_id); @@ -1933,6 +1949,8 @@ static int sep_add_flow_tables_handler(struct sep_device *sep, unsigned long arg /* send the parameters to user application */ error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_add_flow_table_t)); + if (error) + error = -EFAULT; end_function_with_error: /* free the allocated tables */ sep_deallocated_flow_tables(&first_table_data); @@ -1953,8 +1971,10 @@ static int sep_add_flow_tables_message_handler(struct sep_device *sep, unsigned dbg("SEP Driver:--------> sep_add_flow_tables_message_handler start\n"); error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_message_t)); - if (error) + if (error) { + error = -EFAULT; goto end_function; + } /* check input */ if (command_args.message_size_in_bytes > SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) { @@ -1970,6 +1990,8 @@ static int sep_add_flow_tables_message_handler(struct sep_device *sep, unsigned /* copy the message into context */ flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes; error = copy_from_user(flow_context_ptr->message, (void *) command_args.message_address, command_args.message_size_in_bytes); + if (error) + error = -EFAULT; end_function: dbg("SEP Driver:<-------- sep_add_flow_tables_message_handler end\n"); return error; @@ -1994,6 +2016,8 @@ static int sep_get_static_pool_addr_handler(struct sep_device *sep, unsigned lon /* send the parameters to user application */ error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_static_pool_addr_t)); + if (error) + error = -EFAULT; dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n"); return error; } @@ -2010,8 +2034,10 @@ static int sep_get_physical_mapped_offset_handler(struct sep_device *sep, unsign dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n"); error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_get_mapped_offset_t)); - if (error) + if (error) { + error = -EFAULT; goto end_function; + } if (command_args.physical_address < sep->shared_bus) { error = -EINVAL; @@ -2025,6 +2051,8 @@ static int sep_get_physical_mapped_offset_handler(struct sep_device *sep, unsign /* send the parameters to user application */ error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_get_mapped_offset_t)); + if (error) + error = -EFAULT; end_function: dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n"); return error; @@ -2070,11 +2098,11 @@ static int sep_init_handler(struct sep_device *sep, unsigned long arg) error = 0; error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_init_t)); - - dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user \n"); - - if (error) + if (error) { + error = -EFAULT; goto end_function; + } + dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user\n"); /* PATCH - configure the DMA to single -burst instead of multi-burst */ /*sep_configure_dma_burst(); */ diff --git a/drivers/staging/tm6000/Kconfig b/drivers/staging/tm6000/Kconfig index 5fe759cc2ee9..c725356cc346 100644 --- a/drivers/staging/tm6000/Kconfig +++ b/drivers/staging/tm6000/Kconfig @@ -2,7 +2,8 @@ config VIDEO_TM6000 tristate "TV Master TM5600/6000/6010 driver" depends on VIDEO_DEV && I2C && INPUT && USB && EXPERIMENTAL select VIDEO_TUNER - select TUNER_XC2028 + select MEDIA_TUNER_XC2028 + select MEDIA_TUNER_XC5000 select VIDEOBUF_VMALLOC help Support for TM5600/TM6000/TM6010 USB Device @@ -25,8 +26,8 @@ config VIDEO_TM6000_ALSA module will be called tm6000-alsa. config VIDEO_TM6000_DVB - bool "DVB Support for tm6000 based TV cards" - depends on VIDEO_TM6000 && DVB_CORE && EXPERIMENTAL + tristate "DVB Support for tm6000 based TV cards" + depends on VIDEO_TM6000 && DVB_CORE && USB && EXPERIMENTAL select DVB_ZL10353 ---help--- This adds support for DVB cards based on the tm5600/tm6000 chip. diff --git a/drivers/staging/tm6000/Makefile b/drivers/staging/tm6000/Makefile index 93370fccc073..77e06bfd2c46 100644 --- a/drivers/staging/tm6000/Makefile +++ b/drivers/staging/tm6000/Makefile @@ -2,14 +2,12 @@ tm6000-objs := tm6000-cards.o \ tm6000-core.o \ tm6000-i2c.o \ tm6000-video.o \ - tm6000-stds.o - -ifeq ($(CONFIG_VIDEO_TM6000_DVB),y) -tm6000-objs += tm6000-dvb.o -endif + tm6000-stds.o \ + tm6000-input.o obj-$(CONFIG_VIDEO_TM6000) += tm6000.o obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o +obj-$(CONFIG_VIDEO_TM6000_DVB) += tm6000-dvb.o EXTRA_CFLAGS = -Idrivers/media/video EXTRA_CFLAGS += -Idrivers/media/common/tuners diff --git a/drivers/staging/tm6000/tm6000-alsa.c b/drivers/staging/tm6000/tm6000-alsa.c index bc89f9d28002..087137d9164d 100644 --- a/drivers/staging/tm6000/tm6000-alsa.c +++ b/drivers/staging/tm6000/tm6000-alsa.c @@ -15,6 +15,8 @@ #include <linux/device.h> #include <linux/interrupt.h> #include <linux/usb.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> #include <asm/delay.h> #include <sound/core.h> @@ -35,34 +37,11 @@ } while (0) /**************************************************************************** - Data type declarations - Can be moded to a header file later - ****************************************************************************/ - -struct snd_tm6000_card { - struct snd_card *card; - - spinlock_t reg_lock; - - atomic_t count; - - unsigned int period_size; - unsigned int num_periods; - - struct tm6000_core *core; - struct tm6000_buffer *buf; - - int bufsize; - - struct snd_pcm_substream *substream; -}; - - -/**************************************************************************** Module global static vars ****************************************************************************/ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ + static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; module_param_array(enable, bool, NULL, 0444); @@ -99,11 +78,15 @@ static int _tm6000_start_audio_dma(struct snd_tm6000_card *chip) struct tm6000_core *core = chip->core; int val; + dprintk(1, "Starting audio DMA\n"); + /* Enables audio */ val = tm6000_get_reg(core, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, 0x0); val |= 0x20; tm6000_set_reg(core, TM6010_REQ07_RCC_ACTIVE_VIDEO_IF, val); + tm6000_set_audio_bitrate(core, 48000); + tm6000_set_reg(core, TM6010_REQ08_R01_A_INIT, 0x80); return 0; @@ -128,19 +111,39 @@ static int _tm6000_stop_audio_dma(struct snd_tm6000_card *chip) return 0; } -static int dsp_buffer_free(struct snd_tm6000_card *chip) +static void dsp_buffer_free(struct snd_pcm_substream *substream) { - BUG_ON(!chip->bufsize); + struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); dprintk(2, "Freeing buffer\n"); - /* FIXME: Frees buffer */ + vfree(substream->runtime->dma_area); + substream->runtime->dma_area = NULL; + substream->runtime->dma_bytes = 0; +} + +static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size) +{ + struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - chip->bufsize = 0; + dprintk(2, "Allocating buffer\n"); - return 0; + if (substream->runtime->dma_area) { + if (substream->runtime->dma_bytes > size) + return 0; + dsp_buffer_free(substream); + } + + substream->runtime->dma_area = vmalloc(size); + if (!substream->runtime->dma_area) + return -ENOMEM; + + substream->runtime->dma_bytes = size; + + return 0; } + /**************************************************************************** ALSA PCM Interface ****************************************************************************/ @@ -157,16 +160,16 @@ static struct snd_pcm_hardware snd_tm6000_digital_hw = { SNDRV_PCM_INFO_MMAP_VALID, .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .rate_min = 44100, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, .rate_max = 48000, .channels_min = 2, .channels_max = 2, - .period_bytes_min = DEFAULT_FIFO_SIZE/4, - .period_bytes_max = DEFAULT_FIFO_SIZE/4, + .period_bytes_min = 62720, + .period_bytes_max = 62720, .periods_min = 1, .periods_max = 1024, - .buffer_bytes_max = (1024*1024), + .buffer_bytes_max = 62720 * 8, }; /* @@ -201,29 +204,64 @@ static int snd_tm6000_close(struct snd_pcm_substream *substream) return 0; } +static int tm6000_fillbuf(struct tm6000_core *core, char *buf, int size) +{ + struct snd_tm6000_card *chip = core->adev; + struct snd_pcm_substream *substream = chip->substream; + struct snd_pcm_runtime *runtime; + int period_elapsed = 0; + unsigned int stride, buf_pos; + + if (!size || !substream) + return -EINVAL; + + runtime = substream->runtime; + if (!runtime || !runtime->dma_area) + return -EINVAL; + + buf_pos = chip->buf_pos; + stride = runtime->frame_bits >> 3; + + dprintk(1, "Copying %d bytes at %p[%d] - buf size=%d x %d\n", size, + runtime->dma_area, buf_pos, + (unsigned int)runtime->buffer_size, stride); + + if (buf_pos + size >= runtime->buffer_size * stride) { + unsigned int cnt = runtime->buffer_size * stride - buf_pos; + memcpy(runtime->dma_area + buf_pos, buf, cnt); + memcpy(runtime->dma_area, buf + cnt, size - cnt); + } else + memcpy(runtime->dma_area + buf_pos, buf, size); + + chip->buf_pos += size; + if (chip->buf_pos >= runtime->buffer_size * stride) + chip->buf_pos -= runtime->buffer_size * stride; + + chip->period_pos += size; + if (chip->period_pos >= runtime->period_size) { + chip->period_pos -= runtime->period_size; + period_elapsed = 1; + } + + if (period_elapsed) + snd_pcm_period_elapsed(substream); + + return 0; +} + /* * hw_params callback */ static int snd_tm6000_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - - if (substream->runtime->dma_area) { - dsp_buffer_free(chip); - substream->runtime->dma_area = NULL; - } - - chip->period_size = params_period_bytes(hw_params); - chip->num_periods = params_periods(hw_params); - chip->bufsize = chip->period_size * params_periods(hw_params); + int size, rc; - BUG_ON(!chip->bufsize); - - dprintk(1, "Setting buffer\n"); - - /* FIXME: Allocate buffer for audio */ + size = params_period_bytes(hw_params) * params_periods(hw_params); + rc = dsp_buffer_alloc(substream, size); + if (rc < 0) + return rc; return 0; } @@ -233,13 +271,9 @@ static int snd_tm6000_hw_params(struct snd_pcm_substream *substream, */ static int snd_tm6000_hw_free(struct snd_pcm_substream *substream) { - struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - if (substream->runtime->dma_area) { - dsp_buffer_free(chip); - substream->runtime->dma_area = NULL; - } + _tm6000_stop_audio_dma(chip); return 0; } @@ -249,6 +283,11 @@ static int snd_tm6000_hw_free(struct snd_pcm_substream *substream) */ static int snd_tm6000_prepare(struct snd_pcm_substream *substream) { + struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); + + chip->buf_pos = 0; + chip->period_pos = 0; + return 0; } @@ -286,12 +325,8 @@ static int snd_tm6000_card_trigger(struct snd_pcm_substream *substream, int cmd) static snd_pcm_uframes_t snd_tm6000_pointer(struct snd_pcm_substream *substream) { struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - u16 count; - - count = atomic_read(&chip->count); - return runtime->period_size * (count & (runtime->periods-1)); + return chip->buf_pos; } /* @@ -311,21 +346,6 @@ static struct snd_pcm_ops snd_tm6000_pcm_ops = { /* * create a PCM device */ -static int __devinit snd_tm6000_pcm(struct snd_tm6000_card *chip, - int device, char *name) -{ - int err; - struct snd_pcm *pcm; - - err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); - if (err < 0) - return err; - pcm->private_data = chip; - strcpy(pcm->name, name); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops); - - return 0; -} /* FIXME: Control interface - How to control volume/mute? */ @@ -336,27 +356,41 @@ static int __devinit snd_tm6000_pcm(struct snd_tm6000_card *chip, /* * Alsa Constructor - Component probe */ - -int tm6000_audio_init(struct tm6000_core *dev, int idx) +int tm6000_audio_init(struct tm6000_core *dev) { - struct snd_card *card; - struct snd_tm6000_card *chip; - int rc, len; - char component[14]; + struct snd_card *card; + struct snd_tm6000_card *chip; + int rc; + static int devnr; + char component[14]; + struct snd_pcm *pcm; - if (idx >= SNDRV_CARDS) + if (!dev) + return 0; + + if (devnr >= SNDRV_CARDS) return -ENODEV; - if (!enable[idx]) + if (!enable[devnr]) return -ENOENT; - rc = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card); + rc = snd_card_create(index[devnr], "tm6000", THIS_MODULE, 0, &card); if (rc < 0) { - snd_printk(KERN_ERR "cannot create card instance %d\n", idx); + snd_printk(KERN_ERR "cannot create card instance %d\n", devnr); return rc; } + strcpy(card->driver, "tm6000-alsa"); + strcpy(card->shortname, "TM5600/60x0"); + sprintf(card->longname, "TM5600/60x0 Audio at bus %d device %d", + dev->udev->bus->busnum, dev->udev->devnum); - chip = kzalloc(sizeof(*chip), GFP_KERNEL); + sprintf(component, "USB%04x:%04x", + le16_to_cpu(dev->udev->descriptor.idVendor), + le16_to_cpu(dev->udev->descriptor.idProduct)); + snd_component_add(card, component); + snd_card_set_dev(card, &dev->udev->dev); + + chip = kzalloc(sizeof(struct snd_tm6000_card), GFP_KERNEL); if (!chip) { rc = -ENOMEM; goto error; @@ -364,45 +398,24 @@ int tm6000_audio_init(struct tm6000_core *dev, int idx) chip->core = dev; chip->card = card; + dev->adev = chip; + spin_lock_init(&chip->reg_lock); - strcpy(card->driver, "tm6000-alsa"); - sprintf(component, "USB%04x:%04x", - le16_to_cpu(dev->udev->descriptor.idVendor), - le16_to_cpu(dev->udev->descriptor.idProduct)); - snd_component_add(card, component); - - if (dev->udev->descriptor.iManufacturer) - len = usb_string(dev->udev, - dev->udev->descriptor.iManufacturer, - card->longname, sizeof(card->longname)); - else - len = 0; - - if (len > 0) - strlcat(card->longname, " ", sizeof(card->longname)); - - strlcat(card->longname, card->shortname, sizeof(card->longname)); - - len = strlcat(card->longname, " at ", sizeof(card->longname)); - - if (len < sizeof(card->longname)) - usb_make_path(dev->udev, card->longname + len, - sizeof(card->longname) - len); - - strlcat(card->longname, - dev->udev->speed == USB_SPEED_LOW ? ", low speed" : - dev->udev->speed == USB_SPEED_FULL ? ", full speed" : - ", high speed", - sizeof(card->longname)); - - rc = snd_tm6000_pcm(chip, 0, "tm6000 Digital"); + rc = snd_pcm_new(card, "TM6000 Audio", 0, 0, 1, &pcm); if (rc < 0) goto error; + pcm->info_flags = 0; + pcm->private_data = chip; + strcpy(pcm->name, "Trident TM5600/60x0"); + + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops); + rc = snd_card_register(card); if (rc < 0) goto error; + dprintk(1,"Registered audio driver for %s\n", card->longname); return 0; @@ -410,5 +423,45 @@ error: snd_card_free(card); return rc; } -EXPORT_SYMBOL_GPL(tm6000_audio_init); +static int tm6000_audio_fini(struct tm6000_core *dev) +{ + struct snd_tm6000_card *chip = dev->adev; + + if (!dev) + return 0; + + if (!chip) + return 0; + + if (!chip->card) + return 0; + + snd_card_free(chip->card); + chip->card = NULL; + kfree(chip); + dev->adev = NULL; + + return 0; +} + +struct tm6000_ops audio_ops = { + .type = TM6000_AUDIO, + .name = "TM6000 Audio Extension", + .init = tm6000_audio_init, + .fini = tm6000_audio_fini, + .fillbuf = tm6000_fillbuf, +}; + +static int __init tm6000_alsa_register(void) +{ + return tm6000_register_extension(&audio_ops); +} + +static void __exit tm6000_alsa_unregister(void) +{ + tm6000_unregister_extension(&audio_ops); +} + +module_init(tm6000_alsa_register); +module_exit(tm6000_alsa_unregister); diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c index 6143e20d139d..9d091c34991b 100644 --- a/drivers/staging/tm6000/tm6000-cards.c +++ b/drivers/staging/tm6000/tm6000-cards.c @@ -24,10 +24,12 @@ #include <linux/i2c.h> #include <linux/usb.h> #include <linux/version.h> +#include <linux/slab.h> #include <media/v4l2-common.h> #include <media/tuner.h> #include <media/tvaudio.h> #include <media/i2c-addr.h> +#include <media/rc-map.h> #include "tm6000.h" #include "tm6000-regs.h" @@ -68,6 +70,8 @@ struct tm6000_board { int demod_addr; /* demodulator address */ struct tm6000_gpio gpio; + + char *ir_codes; }; struct tm6000_board tm6000_boards[] = { @@ -275,6 +279,7 @@ struct tm6000_board tm6000_boards[] = { .dvb_led = TM6010_GPIO_5, .ir = TM6010_GPIO_0, }, + .ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS, }, [TM6010_BOARD_TWINHAN_TU501] = { .name = "Twinhan TU501(704D1)", @@ -346,7 +351,7 @@ int tm6000_xc5000_callback(void *ptr, int component, int command, int arg) } return (rc); } - +EXPORT_SYMBOL_GPL(tm6000_xc5000_callback); /* Tuner callback to provide the proper gpio changes needed for xc2028 */ @@ -360,16 +365,12 @@ int tm6000_tuner_callback(void *ptr, int component, int command, int arg) switch (command) { case XC2028_RESET_CLK: + tm6000_ir_wait(dev, 0); + tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x02, arg); msleep(10); - rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - TM6000_GPIO_CLK, 0); - if (rc < 0) - return rc; - msleep(10); - rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - TM6000_GPIO_CLK, 1); + rc = tm6000_i2c_reset(dev, 10); break; case XC2028_TUNER_RESET: /* Reset codes during load firmware */ @@ -415,27 +416,22 @@ int tm6000_tuner_callback(void *ptr, int component, int command, int arg) msleep(130); break; } + + tm6000_ir_wait(dev, 1); break; case 1: tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x01); msleep(10); break; - case 2: - rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - TM6000_GPIO_CLK, 0); - if (rc < 0) - return rc; - msleep(100); - rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, - TM6000_GPIO_CLK, 1); - msleep(100); + rc = tm6000_i2c_reset(dev, 100); break; } } return rc; } +EXPORT_SYMBOL_GPL(tm6000_tuner_callback); int tm6000_cards_setup(struct tm6000_core *dev) { @@ -563,7 +559,7 @@ static void tm6000_config_tuner(struct tm6000_core *dev) switch (dev->tuner_type) { case TUNER_XC2028: - tun_setup.tuner_callback = tm6000_tuner_callback;; + tun_setup.tuner_callback = tm6000_tuner_callback; break; case TUNER_XC5000: tun_setup.tuner_callback = tm6000_xc5000_callback; @@ -647,6 +643,8 @@ static int tm6000_init_dev(struct tm6000_core *dev) dev->gpio = tm6000_boards[dev->model].gpio; + dev->ir_codes = tm6000_boards[dev->model].ir_codes; + dev->demod_addr = tm6000_boards[dev->model].demod_addr; dev->caps = tm6000_boards[dev->model].caps; @@ -692,28 +690,14 @@ static int tm6000_init_dev(struct tm6000_core *dev) if (rc < 0) goto err; - if (dev->caps.has_dvb) { - dev->dvb = kzalloc(sizeof(*(dev->dvb)), GFP_KERNEL); - if (!dev->dvb) { - rc = -ENOMEM; - goto err2; - } + tm6000_add_into_devlist(dev); + tm6000_init_extension(dev); + + tm6000_ir_init(dev); -#ifdef CONFIG_VIDEO_TM6000_DVB - rc = tm6000_dvb_register(dev); - if (rc < 0) { - kfree(dev->dvb); - dev->dvb = NULL; - goto err2; - } -#endif - } mutex_unlock(&dev->lock); return 0; -err2: - v4l2_device_unregister(&dev->v4l2_dev); - err: mutex_unlock(&dev->lock); return rc; @@ -732,7 +716,7 @@ static void get_max_endpoint(struct usb_device *udev, unsigned int size = tmp & 0x7ff; if (udev->speed == USB_SPEED_HIGH) - size = size * hb_mult (tmp); + size = size * hb_mult(tmp); if (size > tm_ep->maxsize) { tm_ep->endp = curr_e; @@ -856,6 +840,19 @@ static int tm6000_usb_probe(struct usb_interface *interface, &dev->isoc_out); } break; + case USB_ENDPOINT_XFER_INT: + if (!dir_out) { + get_max_endpoint(usbdev, + &interface->altsetting[i], + "INT IN", e, + &dev->int_in); + } else { + get_max_endpoint(usbdev, + &interface->altsetting[i], + "INT OUT", e, + &dev->int_out); + } + break; } } } @@ -914,13 +911,27 @@ static void tm6000_usb_disconnect(struct usb_interface *interface) mutex_lock(&dev->lock); -#ifdef CONFIG_VIDEO_TM6000_DVB - if (dev->dvb) { - tm6000_dvb_unregister(dev); - kfree(dev->dvb); - } -#endif + tm6000_ir_fini(dev); + if (dev->gpio.power_led) { + switch (dev->model) { + case TM6010_BOARD_HAUPPAUGE_900H: + case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: + case TM6010_BOARD_TWINHAN_TU501: + /* Power led off */ + tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, + dev->gpio.power_led, 0x01); + msleep(15); + break; + case TM6010_BOARD_BEHOLD_WANDER: + case TM6010_BOARD_BEHOLD_VOYAGER: + /* Power led off */ + tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, + dev->gpio.power_led, 0x00); + msleep(15); + break; + } + } tm6000_v4l2_unregister(dev); tm6000_i2c_unregister(dev); @@ -931,6 +942,9 @@ static void tm6000_usb_disconnect(struct usb_interface *interface) usb_put_dev(dev->udev); + tm6000_close_extension(dev); + tm6000_remove_from_devlist(dev); + mutex_unlock(&dev->lock); kfree(dev); } diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c index bfbc53bd2912..cded411d8bba 100644 --- a/drivers/staging/tm6000/tm6000-core.c +++ b/drivers/staging/tm6000/tm6000-core.c @@ -22,6 +22,7 @@ #include <linux/module.h> #include <linux/kernel.h> +#include <linux/slab.h> #include <linux/usb.h> #include <linux/i2c.h> #include "tm6000.h" @@ -31,66 +32,64 @@ #define USB_TIMEOUT 5*HZ /* ms */ -int tm6000_read_write_usb (struct tm6000_core *dev, u8 req_type, u8 req, - u16 value, u16 index, u8 *buf, u16 len) +int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req, + u16 value, u16 index, u8 *buf, u16 len) { int ret, i; unsigned int pipe; - static int ini=0, last=0, n=0; - u8 *data=NULL; + static int ini = 0, last = 0, n = 0; + u8 *data = NULL; if (len) data = kzalloc(len, GFP_KERNEL); if (req_type & USB_DIR_IN) - pipe=usb_rcvctrlpipe(dev->udev, 0); + pipe = usb_rcvctrlpipe(dev->udev, 0); else { - pipe=usb_sndctrlpipe(dev->udev, 0); + pipe = usb_sndctrlpipe(dev->udev, 0); memcpy(data, buf, len); } if (tm6000_debug & V4L2_DEBUG_I2C) { if (!ini) - last=ini=jiffies; + last = ini = jiffies; printk("%06i (dev %p, pipe %08x): ", n, dev->udev, pipe); - printk( "%s: %06u ms %06u ms %02x %02x %02x %02x %02x %02x %02x %02x ", - (req_type & USB_DIR_IN)?" IN":"OUT", + printk("%s: %06u ms %06u ms %02x %02x %02x %02x %02x %02x %02x %02x ", + (req_type & USB_DIR_IN) ? " IN" : "OUT", jiffies_to_msecs(jiffies-last), jiffies_to_msecs(jiffies-ini), - req_type, req,value&0xff,value>>8, index&0xff, index>>8, - len&0xff, len>>8); - last=jiffies; + req_type, req, value&0xff, value>>8, index&0xff, + index>>8, len&0xff, len>>8); + last = jiffies; n++; - if ( !(req_type & USB_DIR_IN) ) { + if (!(req_type & USB_DIR_IN)) { printk(">>> "); - for (i=0;i<len;i++) { - printk(" %02x",buf[i]); - } + for (i = 0; i < len; i++) + printk(" %02x", buf[i]); printk("\n"); } } - ret = usb_control_msg(dev->udev, pipe, req, req_type, value, index, data, - len, USB_TIMEOUT); + ret = usb_control_msg(dev->udev, pipe, req, req_type, value, index, + data, len, USB_TIMEOUT); if (req_type & USB_DIR_IN) memcpy(buf, data, len); if (tm6000_debug & V4L2_DEBUG_I2C) { - if (ret<0) { + if (ret < 0) { if (req_type & USB_DIR_IN) - printk("<<< (len=%d)\n",len); + printk("<<< (len=%d)\n", len); printk("%s: Error #%d\n", __FUNCTION__, ret); } else if (req_type & USB_DIR_IN) { printk("<<< "); - for (i=0;i<len;i++) { - printk(" %02x",buf[i]); - } + for (i = 0; i < len; i++) + printk(" %02x", buf[i]); printk("\n"); } } @@ -102,57 +101,73 @@ int tm6000_read_write_usb (struct tm6000_core *dev, u8 req_type, u8 req, return ret; } -int tm6000_set_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index) +int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index) { return - tm6000_read_write_usb (dev, USB_DIR_OUT | USB_TYPE_VENDOR, - req, value, index, NULL, 0); + tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR, + req, value, index, NULL, 0); } EXPORT_SYMBOL_GPL(tm6000_set_reg); -int tm6000_get_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index) +int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index) { int rc; u8 buf[1]; - rc=tm6000_read_write_usb (dev, USB_DIR_IN | USB_TYPE_VENDOR, req, - value, index, buf, 1); + rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, + value, index, buf, 1); - if (rc<0) + if (rc < 0) return rc; return *buf; } EXPORT_SYMBOL_GPL(tm6000_get_reg); -int tm6000_get_reg16 (struct tm6000_core *dev, u8 req, u16 value, u16 index) +int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index) { int rc; u8 buf[2]; - rc=tm6000_read_write_usb (dev, USB_DIR_IN | USB_TYPE_VENDOR, req, - value, index, buf, 2); + rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, + value, index, buf, 2); - if (rc<0) + if (rc < 0) return rc; return buf[1]|buf[0]<<8; } -int tm6000_get_reg32 (struct tm6000_core *dev, u8 req, u16 value, u16 index) +int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index) { int rc; u8 buf[4]; - rc=tm6000_read_write_usb (dev, USB_DIR_IN | USB_TYPE_VENDOR, req, - value, index, buf, 4); + rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, + value, index, buf, 4); - if (rc<0) + if (rc < 0) return rc; return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24; } +int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep) +{ + int rc; + + rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0); + if (rc < 0) + return rc; + + msleep(tsleep); + + rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1); + msleep(tsleep); + + return rc; +} + void tm6000_set_fourcc_format(struct tm6000_core *dev) { if (dev->dev_type == TM6010) { @@ -171,7 +186,7 @@ void tm6000_set_fourcc_format(struct tm6000_core *dev) } } -int tm6000_init_analog_mode (struct tm6000_core *dev) +int tm6000_init_analog_mode(struct tm6000_core *dev) { if (dev->dev_type == TM6010) { int val; @@ -277,12 +292,10 @@ int tm6000_init_analog_mode (struct tm6000_core *dev) /* Enables soft reset */ tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01); - if (dev->scaler) { + if (dev->scaler) tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x20); - } else { - /* Enable Hfilter and disable TS Drop err */ + else /* Enable Hfilter and disable TS Drop err */ tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x80); - } tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x88); tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0x23); @@ -315,18 +328,24 @@ int tm6000_init_analog_mode (struct tm6000_core *dev) /*FIXME: Hack!!! */ struct v4l2_frequency f; mutex_lock(&dev->lock); - f.frequency=dev->freq; + f.frequency = dev->freq; v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f); mutex_unlock(&dev->lock); msleep(100); - tm6000_set_standard (dev, &dev->norm); - tm6000_set_audio_bitrate (dev,48000); + tm6000_set_standard(dev, &dev->norm); + tm6000_set_audio_bitrate(dev, 48000); + + /* switch dvb led off */ + if (dev->gpio.dvb_led) { + tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, + dev->gpio.dvb_led, 0x01); + } return 0; } -int tm6000_init_digital_mode (struct tm6000_core *dev) +int tm6000_init_digital_mode(struct tm6000_core *dev) { if (dev->dev_type == TM6010) { int val; @@ -343,10 +362,8 @@ int tm6000_init_digital_mode (struct tm6000_core *dev) tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xfc); tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0xff); tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe); - tm6000_read_write_usb (dev, 0xc0, 0x0e, 0x00c2, 0x0008, buf, 2); - printk (KERN_INFO "buf %#x %#x \n", buf[0], buf[1]); - - + tm6000_read_write_usb(dev, 0xc0, 0x0e, 0x00c2, 0x0008, buf, 2); + printk(KERN_INFO"buf %#x %#x\n", buf[0], buf[1]); } else { tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08); tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00); @@ -354,7 +371,7 @@ int tm6000_init_digital_mode (struct tm6000_core *dev) tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0x08); tm6000_set_reg(dev, TM6010_REQ07_RE2_OUT_SEL2, 0x0c); tm6000_set_reg(dev, TM6010_REQ07_RE8_TYPESEL_MOS_I2S, 0xff); - tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00eb, 0xd8); + tm6000_set_reg(dev, REQ_07_SET_GET_AVREG, 0x00eb, 0xd8); tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x40); tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0); tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x09); @@ -365,18 +382,26 @@ int tm6000_init_digital_mode (struct tm6000_core *dev) tm6000_set_reg(dev, TM6010_REQ07_RE2_OUT_SEL2, 0x0c); tm6000_set_reg(dev, TM6010_REQ07_RE8_TYPESEL_MOS_I2S, 0xff); - tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0x00eb, 0x08); + tm6000_set_reg(dev, REQ_07_SET_GET_AVREG, 0x00eb, 0x08); msleep(50); - tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00); + tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00); msleep(50); - tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01); + tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01); msleep(50); - tm6000_set_reg (dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00); + tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00); msleep(100); } + + /* switch dvb led on */ + if (dev->gpio.dvb_led) { + tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, + dev->gpio.dvb_led, 0x00); + } + return 0; } +EXPORT_SYMBOL(tm6000_init_digital_mode); struct reg_init { u8 req; @@ -536,9 +561,9 @@ struct reg_init tm6010_init_tab[] = { { TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff }, }; -int tm6000_init (struct tm6000_core *dev) +int tm6000_init(struct tm6000_core *dev) { - int board, rc=0, i, size; + int board, rc = 0, i, size; struct reg_init *tab; if (dev->dev_type == TM6010) { @@ -550,12 +575,12 @@ int tm6000_init (struct tm6000_core *dev) } /* Load board's initialization table */ - for (i=0; i< size; i++) { - rc= tm6000_set_reg (dev, tab[i].req, tab[i].reg, tab[i].val); - if (rc<0) { - printk (KERN_ERR "Error %i while setting req %d, " - "reg %d to value %d\n", rc, - tab[i].req,tab[i].reg, tab[i].val); + for (i = 0; i < size; i++) { + rc = tm6000_set_reg(dev, tab[i].req, tab[i].reg, tab[i].val); + if (rc < 0) { + printk(KERN_ERR "Error %i while setting req %d, " + "reg %d to value %d\n", rc, + tab[i].req, tab[i].reg, tab[i].val); return rc; } } @@ -563,12 +588,11 @@ int tm6000_init (struct tm6000_core *dev) msleep(5); /* Just to be conservative */ /* Check board version - maybe 10Moons specific */ - board=tm6000_get_reg32 (dev, REQ_40_GET_VERSION, 0, 0); - if (board >=0) { - printk (KERN_INFO "Board version = 0x%08x\n",board); - } else { - printk (KERN_ERR "Error %i while retrieving board version\n",board); - } + board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0); + if (board >= 0) + printk(KERN_INFO "Board version = 0x%08x\n", board); + else + printk(KERN_ERR "Error %i while retrieving board version\n", board); rc = tm6000_cards_setup(dev); @@ -579,24 +603,142 @@ int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate) { int val; - val=tm6000_get_reg (dev, REQ_07_SET_GET_AVREG, 0xeb, 0x0); -printk("Original value=%d\n",val); - if (val<0) + if (dev->dev_type == TM6010) { + val = tm6000_get_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, 0); + if (val < 0) + return val; + val = (val & 0xf0) | 0x1; /* 48 kHz, not muted */ + val = tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, val); + if (val < 0) + return val; + } + + val = tm6000_get_reg(dev, REQ_07_SET_GET_AVREG, 0xeb, 0x0); + if (val < 0) return val; val &= 0x0f; /* Preserve the audio input control bits */ switch (bitrate) { case 44100: - val|=0xd0; - dev->audio_bitrate=bitrate; + val |= 0xd0; + dev->audio_bitrate = bitrate; break; case 48000: - val|=0x60; - dev->audio_bitrate=bitrate; + val |= 0x60; + dev->audio_bitrate = bitrate; break; } - val=tm6000_set_reg (dev, REQ_07_SET_GET_AVREG, 0xeb, val); + val = tm6000_set_reg(dev, REQ_07_SET_GET_AVREG, 0xeb, val); return val; } EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate); + +static LIST_HEAD(tm6000_devlist); +static DEFINE_MUTEX(tm6000_devlist_mutex); + +/* + * tm6000_realease_resource() + */ + +void tm6000_remove_from_devlist(struct tm6000_core *dev) +{ + mutex_lock(&tm6000_devlist_mutex); + list_del(&dev->devlist); + mutex_unlock(&tm6000_devlist_mutex); +}; + +void tm6000_add_into_devlist(struct tm6000_core *dev) +{ + mutex_lock(&tm6000_devlist_mutex); + list_add_tail(&dev->devlist, &tm6000_devlist); + mutex_unlock(&tm6000_devlist_mutex); +}; + +/* + * Extension interface + */ + +static LIST_HEAD(tm6000_extension_devlist); +static DEFINE_MUTEX(tm6000_extension_devlist_lock); + +int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type, + char *buf, int size) +{ + struct tm6000_ops *ops = NULL; + + /* FIXME: tm6000_extension_devlist_lock should be a spinlock */ + + if (!list_empty(&tm6000_extension_devlist)) { + list_for_each_entry(ops, &tm6000_extension_devlist, next) { + if (ops->fillbuf && ops->type == type) + ops->fillbuf(dev, buf, size); + } + } + + return 0; +} + +int tm6000_register_extension(struct tm6000_ops *ops) +{ + struct tm6000_core *dev = NULL; + + mutex_lock(&tm6000_devlist_mutex); + mutex_lock(&tm6000_extension_devlist_lock); + list_add_tail(&ops->next, &tm6000_extension_devlist); + list_for_each_entry(dev, &tm6000_devlist, devlist) { + ops->init(dev); + printk(KERN_INFO "%s: Initialized (%s) extension\n", + dev->name, ops->name); + } + mutex_unlock(&tm6000_extension_devlist_lock); + mutex_unlock(&tm6000_devlist_mutex); + return 0; +} +EXPORT_SYMBOL(tm6000_register_extension); + +void tm6000_unregister_extension(struct tm6000_ops *ops) +{ + struct tm6000_core *dev = NULL; + + mutex_lock(&tm6000_devlist_mutex); + list_for_each_entry(dev, &tm6000_devlist, devlist) { + if (dev) + ops->fini(dev); + } + + mutex_lock(&tm6000_extension_devlist_lock); + printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name); + list_del(&ops->next); + mutex_unlock(&tm6000_extension_devlist_lock); + mutex_unlock(&tm6000_devlist_mutex); +} +EXPORT_SYMBOL(tm6000_unregister_extension); + +void tm6000_init_extension(struct tm6000_core *dev) +{ + struct tm6000_ops *ops = NULL; + + mutex_lock(&tm6000_extension_devlist_lock); + if (!list_empty(&tm6000_extension_devlist)) { + list_for_each_entry(ops, &tm6000_extension_devlist, next) { + if (ops->init) + ops->init(dev); + } + } + mutex_unlock(&tm6000_extension_devlist_lock); +} + +void tm6000_close_extension(struct tm6000_core *dev) +{ + struct tm6000_ops *ops = NULL; + + mutex_lock(&tm6000_extension_devlist_lock); + if (!list_empty(&tm6000_extension_devlist)) { + list_for_each_entry(ops, &tm6000_extension_devlist, next) { + if (ops->fini) + ops->fini(dev); + } + } + mutex_unlock(&tm6000_extension_devlist_lock); +} diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/staging/tm6000/tm6000-dvb.c index eafc89c22b6b..f501edccf9c4 100644 --- a/drivers/staging/tm6000/tm6000-dvb.c +++ b/drivers/staging/tm6000/tm6000-dvb.c @@ -18,6 +18,7 @@ */ #include <linux/kernel.h> +#include <linux/slab.h> #include <linux/usb.h> #include "tm6000.h" @@ -28,13 +29,27 @@ #include <media/tuner.h> #include "tuner-xc2028.h" +#include "xc5000.h" -static void inline print_err_status (struct tm6000_core *dev, - int packet, int status) +MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards"); +MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); +MODULE_LICENSE("GPL"); + +MODULE_SUPPORTED_DEVICE("{{Trident, tm5600}," + "{{Trident, tm6000}," + "{{Trident, tm6010}"); + +static int debug; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "enable debug message"); + +static inline void print_err_status(struct tm6000_core *dev, + int packet, int status) { char *errmsg = "Unknown"; - switch(status) { + switch (status) { case -ENOENT: errmsg = "unlinked synchronuously"; break; @@ -60,7 +75,7 @@ static void inline print_err_status (struct tm6000_core *dev, errmsg = "Device does not respond"; break; } - if (packet<0) { + if (packet < 0) { dprintk(dev, 1, "URB status %d [%s].\n", status, errmsg); } else { @@ -72,19 +87,17 @@ static void inline print_err_status (struct tm6000_core *dev, static void tm6000_urb_received(struct urb *urb) { int ret; - struct tm6000_core* dev = urb->context; + struct tm6000_core *dev = urb->context; - if(urb->status != 0) { - print_err_status (dev,0,urb->status); - } - else if(urb->actual_length>0){ + if (urb->status != 0) + print_err_status(dev, 0, urb->status); + else if (urb->actual_length > 0) dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer, urb->actual_length); - } - if(dev->dvb->streams > 0) { + if (dev->dvb->streams > 0) { ret = usb_submit_urb(urb, GFP_ATOMIC); - if(ret < 0) { + if (ret < 0) { printk(KERN_ERR "tm6000: error %s\n", __FUNCTION__); kfree(urb->transfer_buffer); usb_free_urb(urb); @@ -98,12 +111,15 @@ int tm6000_start_stream(struct tm6000_core *dev) unsigned int pipe, size; struct tm6000_dvb *dvb = dev->dvb; - printk(KERN_INFO "tm6000: got start stream request %s\n",__FUNCTION__); + printk(KERN_INFO "tm6000: got start stream request %s\n", __FUNCTION__); - tm6000_init_digital_mode(dev); + if (dev->mode != TM6000_MODE_DIGITAL) { + tm6000_init_digital_mode(dev); + dev->mode = TM6000_MODE_DIGITAL; + } dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); - if(dvb->bulk_urb == NULL) { + if (dvb->bulk_urb == NULL) { printk(KERN_ERR "tm6000: couldn't allocate urb\n"); return -ENOMEM; } @@ -115,7 +131,7 @@ int tm6000_start_stream(struct tm6000_core *dev) size = size * 15; /* 512 x 8 or 12 or 15 */ dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); - if(dvb->bulk_urb->transfer_buffer == NULL) { + if (dvb->bulk_urb->transfer_buffer == NULL) { usb_free_urb(dvb->bulk_urb); printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n"); return -ENOMEM; @@ -127,20 +143,20 @@ int tm6000_start_stream(struct tm6000_core *dev) tm6000_urb_received, dev); ret = usb_clear_halt(dev->udev, pipe); - if(ret < 0) { - printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",ret,__FUNCTION__); + if (ret < 0) { + printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n", + ret, __FUNCTION__); return ret; - } - else { + } else printk(KERN_ERR "tm6000: pipe resetted\n"); - } /* mutex_lock(&tm6000_driver.open_close_mutex); */ ret = usb_submit_urb(dvb->bulk_urb, GFP_KERNEL); /* mutex_unlock(&tm6000_driver.open_close_mutex); */ if (ret) { - printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",ret); + printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n", + ret); kfree(dvb->bulk_urb->transfer_buffer); usb_free_urb(dvb->bulk_urb); @@ -154,10 +170,10 @@ void tm6000_stop_stream(struct tm6000_core *dev) { struct tm6000_dvb *dvb = dev->dvb; - if(dvb->bulk_urb) { - printk (KERN_INFO "urb killing\n"); + if (dvb->bulk_urb) { + printk(KERN_INFO "urb killing\n"); usb_kill_urb(dvb->bulk_urb); - printk (KERN_INFO "urb buffer free\n"); + printk(KERN_INFO "urb buffer free\n"); kfree(dvb->bulk_urb->transfer_buffer); usb_free_urb(dvb->bulk_urb); dvb->bulk_urb = NULL; @@ -169,35 +185,34 @@ int tm6000_start_feed(struct dvb_demux_feed *feed) struct dvb_demux *demux = feed->demux; struct tm6000_core *dev = demux->priv; struct tm6000_dvb *dvb = dev->dvb; - printk(KERN_INFO "tm6000: got start feed request %s\n",__FUNCTION__); + printk(KERN_INFO "tm6000: got start feed request %s\n", __FUNCTION__); mutex_lock(&dvb->mutex); - if(dvb->streams == 0) { + if (dvb->streams == 0) { dvb->streams = 1; /* mutex_init(&tm6000_dev->streming_mutex); */ tm6000_start_stream(dev); - } - else { + } else ++(dvb->streams); - } mutex_unlock(&dvb->mutex); return 0; } -int tm6000_stop_feed(struct dvb_demux_feed *feed) { +int tm6000_stop_feed(struct dvb_demux_feed *feed) +{ struct dvb_demux *demux = feed->demux; struct tm6000_core *dev = demux->priv; struct tm6000_dvb *dvb = dev->dvb; - printk(KERN_INFO "tm6000: got stop feed request %s\n",__FUNCTION__); + printk(KERN_INFO "tm6000: got stop feed request %s\n", __FUNCTION__); mutex_lock(&dvb->mutex); - printk (KERN_INFO "stream %#x\n", dvb->streams); + printk(KERN_INFO "stream %#x\n", dvb->streams); --(dvb->streams); - if(dvb->streams == 0) { - printk (KERN_INFO "stop stream\n"); + if (dvb->streams == 0) { + printk(KERN_INFO "stop stream\n"); tm6000_stop_stream(dev); /* mutex_destroy(&tm6000_dev->streaming_mutex); */ } @@ -211,9 +226,9 @@ int tm6000_dvb_attach_frontend(struct tm6000_core *dev) { struct tm6000_dvb *dvb = dev->dvb; - if(dev->caps.has_zl10353) { - struct zl10353_config config = - {.demod_address = dev->demod_addr, + if (dev->caps.has_zl10353) { + struct zl10353_config config = { + .demod_address = dev->demod_addr, .no_tuner = 1, .parallel_ts = 1, .if2 = 45700, @@ -222,8 +237,7 @@ int tm6000_dvb_attach_frontend(struct tm6000_core *dev) dvb->frontend = dvb_attach(zl10353_attach, &config, &dev->i2c_adap); - } - else { + } else { printk(KERN_ERR "tm6000: no frontend defined for the device!\n"); return -1; } @@ -233,7 +247,7 @@ int tm6000_dvb_attach_frontend(struct tm6000_core *dev) DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -int tm6000_dvb_register(struct tm6000_core *dev) +int register_dvb(struct tm6000_core *dev) { int ret = -1; struct tm6000_dvb *dvb = dev->dvb; @@ -244,40 +258,67 @@ int tm6000_dvb_register(struct tm6000_core *dev) /* attach the frontend */ ret = tm6000_dvb_attach_frontend(dev); - if(ret < 0) { + if (ret < 0) { printk(KERN_ERR "tm6000: couldn't attach the frontend!\n"); goto err; } ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T", - THIS_MODULE, &dev->udev->dev, adapter_nr); + THIS_MODULE, &dev->udev->dev, adapter_nr); dvb->adapter.priv = dev; if (dvb->frontend) { - struct xc2028_config cfg = { - .i2c_adap = &dev->i2c_adap, - .i2c_addr = dev->tuner_addr, - }; - - dvb->frontend->callback = tm6000_tuner_callback; - ret = dvb_register_frontend(&dvb->adapter, dvb->frontend); - if (ret < 0) { - printk(KERN_ERR - "tm6000: couldn't register frontend\n"); - goto adapter_err; + switch (dev->tuner_type) { + case TUNER_XC2028: { + struct xc2028_config cfg = { + .i2c_adap = &dev->i2c_adap, + .i2c_addr = dev->tuner_addr, + }; + + dvb->frontend->callback = tm6000_tuner_callback; + ret = dvb_register_frontend(&dvb->adapter, dvb->frontend); + if (ret < 0) { + printk(KERN_ERR + "tm6000: couldn't register frontend\n"); + goto adapter_err; + } + + if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) { + printk(KERN_ERR "tm6000: couldn't register " + "frontend (xc3028)\n"); + ret = -EINVAL; + goto frontend_err; + } + printk(KERN_INFO "tm6000: XC2028/3028 asked to be " + "attached to frontend!\n"); + break; + } + case TUNER_XC5000: { + struct xc5000_config cfg = { + .i2c_address = dev->tuner_addr, + }; + + dvb->frontend->callback = tm6000_xc5000_callback; + ret = dvb_register_frontend(&dvb->adapter, dvb->frontend); + if (ret < 0) { + printk(KERN_ERR + "tm6000: couldn't register frontend\n"); + goto adapter_err; + } + + if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) { + printk(KERN_ERR "tm6000: couldn't register " + "frontend (xc5000)\n"); + ret = -EINVAL; + goto frontend_err; + } + printk(KERN_INFO "tm6000: XC5000 asked to be " + "attached to frontend!\n"); + break; + } } - - if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) { - printk(KERN_ERR "tm6000: couldn't register " - "frontend (xc3028)\n"); - ret = -EINVAL; - goto frontend_err; - } - printk(KERN_INFO "tm6000: XC2028/3028 asked to be " - "attached to frontend!\n"); - } else { + } else printk(KERN_ERR "tm6000: no frontend found\n"); - } dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING; @@ -288,7 +329,7 @@ int tm6000_dvb_register(struct tm6000_core *dev) dvb->demux.stop_feed = tm6000_stop_feed; dvb->demux.write_to_decoder = NULL; ret = dvb_dmx_init(&dvb->demux); - if(ret < 0) { + if (ret < 0) { printk("tm6000: dvb_dmx_init failed (errno = %d)\n", ret); goto frontend_err; } @@ -298,7 +339,7 @@ int tm6000_dvb_register(struct tm6000_core *dev) dvb->dmxdev.capabilities = 0; ret = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); - if(ret < 0) { + if (ret < 0) { printk("tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret); goto dvb_dmx_err; } @@ -308,7 +349,7 @@ int tm6000_dvb_register(struct tm6000_core *dev) dvb_dmx_err: dvb_dmx_release(&dvb->demux); frontend_err: - if(dvb->frontend) { + if (dvb->frontend) { dvb_frontend_detach(dvb->frontend); dvb_unregister_frontend(dvb->frontend); } @@ -318,11 +359,11 @@ err: return ret; } -void tm6000_dvb_unregister(struct tm6000_core *dev) +void unregister_dvb(struct tm6000_core *dev) { struct tm6000_dvb *dvb = dev->dvb; - if(dvb->bulk_urb != NULL) { + if (dvb->bulk_urb != NULL) { struct urb *bulk_urb = dvb->bulk_urb; kfree(bulk_urb->transfer_buffer); @@ -332,7 +373,7 @@ void tm6000_dvb_unregister(struct tm6000_core *dev) } /* mutex_lock(&tm6000_driver.open_close_mutex); */ - if(dvb->frontend) { + if (dvb->frontend) { dvb_frontend_detach(dvb->frontend); dvb_unregister_frontend(dvb->frontend); } @@ -342,5 +383,70 @@ void tm6000_dvb_unregister(struct tm6000_core *dev) dvb_unregister_adapter(&dvb->adapter); mutex_destroy(&dvb->mutex); /* mutex_unlock(&tm6000_driver.open_close_mutex); */ +} + +static int dvb_init(struct tm6000_core *dev) +{ + struct tm6000_dvb *dvb; + int rc; + if (!dev) + return 0; + + if (!dev->caps.has_dvb) + return 0; + + dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL); + if (!dvb) { + printk(KERN_INFO "Cannot allocate memory\n"); + return -ENOMEM; + } + + dev->dvb = dvb; + + rc = register_dvb(dev); + if (rc < 0) { + kfree(dvb); + dev->dvb = NULL; + return 0; + } + + return 0; } + +static int dvb_fini(struct tm6000_core *dev) +{ + if (!dev) + return 0; + + if (!dev->caps.has_dvb) + return 0; + + if (dev->dvb) { + unregister_dvb(dev); + kfree(dev->dvb); + dev->dvb = NULL; + } + + return 0; +} + +static struct tm6000_ops dvb_ops = { + .type = TM6000_DVB, + .name = "TM6000 dvb Extension", + .init = dvb_init, + .fini = dvb_fini, +}; + +static int __init tm6000_dvb_register(void) +{ + return tm6000_register_extension(&dvb_ops); +} + +static void __exit tm6000_dvb_unregister(void) +{ + tm6000_unregister_extension(&dvb_ops); +} + +module_init(tm6000_dvb_register); +module_exit(tm6000_dvb_unregister); diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c index 94ff489a1bbb..79bc67f0311f 100644 --- a/drivers/staging/tm6000/tm6000-i2c.c +++ b/drivers/staging/tm6000/tm6000-i2c.c @@ -40,7 +40,7 @@ static unsigned int i2c_debug = 0; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); -#define i2c_dprintk(lvl,fmt, args...) if (i2c_debug>=lvl) do{ \ +#define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \ printk(KERN_DEBUG "%s at %s: " fmt, \ dev->name, __FUNCTION__ , ##args); } while (0) @@ -171,7 +171,7 @@ static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap, return 0; for (i = 0; i < num; i++) { addr = (msgs[i].addr << 1) & 0xff; - i2c_dprintk(2,"%s %s addr=0x%x len=%d:", + i2c_dprintk(2, "%s %s addr=0x%x len=%d:", (msgs[i].flags & I2C_M_RD) ? "read" : "write", i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); if (msgs[i].flags & I2C_M_RD) { @@ -235,7 +235,7 @@ static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap, return num; err: - i2c_dprintk(2," ERROR: %i\n", rc); + i2c_dprintk(2, " ERROR: %i\n", rc); return rc; } @@ -266,11 +266,10 @@ static int tm6000_i2c_eeprom(struct tm6000_core *dev, if (0 == (i % 16)) printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i); printk(" %02x", eedata[i]); - if ((eedata[i] >= ' ') && (eedata[i] <= 'z')) { + if ((eedata[i] >= ' ') && (eedata[i] <= 'z')) bytes[i%16] = eedata[i]; - } else { - bytes[i%16]='.'; - } + else + bytes[i%16] = '.'; i++; @@ -305,15 +304,15 @@ static u32 functionality(struct i2c_adapter *adap) } #define mass_write(addr, reg, data...) \ - { const static u8 _val[] = data; \ - rc=tm6000_read_write_usb(dev,USB_DIR_OUT | USB_TYPE_VENDOR, \ - REQ_16_SET_GET_I2C_WR1_RDN,(reg<<8)+addr, 0x00, (u8 *) _val, \ + { static const u8 _val[] = data; \ + rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR, \ + REQ_16_SET_GET_I2C_WR1_RDN, (reg<<8)+addr, 0x00, (u8 *) _val, \ ARRAY_SIZE(_val)); \ - if (rc<0) { \ - printk(KERN_ERR "Error on line %d: %d\n",__LINE__,rc); \ + if (rc < 0) { \ + printk(KERN_ERR "Error on line %d: %d\n", __LINE__, rc); \ return rc; \ } \ - msleep (10); \ + msleep(10); \ } static struct i2c_algorithm tm6000_algo = { diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c new file mode 100644 index 000000000000..32f7a0af6938 --- /dev/null +++ b/drivers/staging/tm6000/tm6000-input.c @@ -0,0 +1,364 @@ +/* + tm6000-input.c - driver for TM5600/TM6000/TM6010 USB video capture devices + + Copyright (C) 2010 Stefan Ringel <stefan.ringel@arcor.de> + + 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 + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/delay.h> + +#include <linux/input.h> +#include <linux/usb.h> + +#include <media/ir-core.h> +#include <media/ir-common.h> + +#include "tm6000.h" +#include "tm6000-regs.h" + +static unsigned int ir_debug; +module_param(ir_debug, int, 0644); +MODULE_PARM_DESC(ir_debug, "enable debug message [IR]"); + +static unsigned int enable_ir = 1; +module_param(enable_ir, int, 0644); +MODULE_PARM_DESC(enable_ir, "enable ir (default is enable"); + +#undef dprintk + +#define dprintk(fmt, arg...) \ + if (ir_debug) { \ + printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ + } + +struct tm6000_ir_poll_result { + u8 rc_data[4]; +}; + +struct tm6000_IR { + struct tm6000_core *dev; + struct ir_input_dev *input; + struct ir_input_state ir; + char name[32]; + char phys[32]; + + /* poll expernal decoder */ + int polling; + struct delayed_work work; + u8 wait:1; + struct urb *int_urb; + u8 *urb_data; + u8 key:1; + + int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *); + + /* IR device properties */ + struct ir_dev_props props; +}; + + +void tm6000_ir_wait(struct tm6000_core *dev, u8 state) +{ + struct tm6000_IR *ir = dev->ir; + + if (!dev->ir) + return; + + if (state) + ir->wait = 1; + else + ir->wait = 0; +} + + +static int tm6000_ir_config(struct tm6000_IR *ir) +{ + struct tm6000_core *dev = ir->dev; + u8 buf[10]; + int rc; + + /* hack */ + buf[0] = 0xff; + buf[1] = 0xff; + buf[2] = 0xf2; + buf[3] = 0x2b; + buf[4] = 0x20; + buf[5] = 0x35; + buf[6] = 0x60; + buf[7] = 0x04; + buf[8] = 0xc0; + buf[9] = 0x08; + + rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a); + msleep(100); + + if (rc < 0) { + printk(KERN_INFO "IR configuration failed"); + return rc; + } + return 0; +} + +static void tm6000_ir_urb_received(struct urb *urb) +{ + struct tm6000_core *dev = urb->context; + struct tm6000_IR *ir = dev->ir; + int rc; + + if (urb->status != 0) + printk(KERN_INFO "not ready\n"); + else if (urb->actual_length > 0) + memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length); + + dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0], + ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]); + + ir->key = 1; + + rc = usb_submit_urb(urb, GFP_ATOMIC); +} + +static int default_polling_getkey(struct tm6000_IR *ir, + struct tm6000_ir_poll_result *poll_result) +{ + struct tm6000_core *dev = ir->dev; + int rc; + u8 buf[2]; + + if (ir->wait && !&dev->int_in) { + poll_result->rc_data[0] = 0xff; + return 0; + } + + if (&dev->int_in) { + poll_result->rc_data[0] = ir->urb_data[0]; + poll_result->rc_data[1] = ir->urb_data[1]; + } else { + tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); + msleep(10); + tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); + msleep(10); + + rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, REQ_02_GET_IR_CODE, 0, 0, buf, 1); + + msleep(10); + + dprintk("read data=%02x\n", buf[0]); + if (rc < 0) + return rc; + + poll_result->rc_data[0] = buf[0]; + } + return 0; +} + +static void tm6000_ir_handle_key(struct tm6000_IR *ir) +{ + int result; + struct tm6000_ir_poll_result poll_result; + + /* read the registers containing the IR status */ + result = ir->get_key(ir, &poll_result); + if (result < 0) { + printk(KERN_INFO "ir->get_key() failed %d\n", result); + return; + } + + dprintk("ir->get_key result data=%02x %02x\n", + poll_result.rc_data[0], poll_result.rc_data[1]); + + if (poll_result.rc_data[0] != 0xff && ir->key == 1) { + ir_input_keydown(ir->input->input_dev, &ir->ir, + poll_result.rc_data[0] | poll_result.rc_data[1] << 8); + + ir_input_nokey(ir->input->input_dev, &ir->ir); + ir->key = 0; + } + return; +} + +static void tm6000_ir_work(struct work_struct *work) +{ + struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work); + + tm6000_ir_handle_key(ir); + schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); +} + +static int tm6000_ir_start(void *priv) +{ + struct tm6000_IR *ir = priv; + + INIT_DELAYED_WORK(&ir->work, tm6000_ir_work); + schedule_delayed_work(&ir->work, 0); + + return 0; +} + +static void tm6000_ir_stop(void *priv) +{ + struct tm6000_IR *ir = priv; + + cancel_delayed_work_sync(&ir->work); +} + +int tm6000_ir_change_protocol(void *priv, u64 ir_type) +{ + struct tm6000_IR *ir = priv; + + ir->get_key = default_polling_getkey; + + tm6000_ir_config(ir); + /* TODO */ + return 0; +} + +int tm6000_ir_init(struct tm6000_core *dev) +{ + struct tm6000_IR *ir; + struct ir_input_dev *ir_input_dev; + int err = -ENOMEM; + int pipe, size, rc; + + if (!enable_ir) + return -ENODEV; + + if (!dev->caps.has_remote) + return 0; + + if (!dev->ir_codes) + return 0; + + ir = kzalloc(sizeof(*ir), GFP_KERNEL); + ir_input_dev = kzalloc(sizeof(*ir_input_dev), GFP_KERNEL); + ir_input_dev->input_dev = input_allocate_device(); + if (!ir || !ir_input_dev || !ir_input_dev->input_dev) + goto err_out_free; + + /* record handles to ourself */ + ir->dev = dev; + dev->ir = ir; + + ir->input = ir_input_dev; + + /* input einrichten */ + ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; + ir->props.priv = ir; + ir->props.change_protocol = tm6000_ir_change_protocol; + ir->props.open = tm6000_ir_start; + ir->props.close = tm6000_ir_stop; + ir->props.driver_type = RC_DRIVER_SCANCODE; + + ir->polling = 50; + + snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)", + dev->name); + + usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); + strlcat(ir->phys, "/input0", sizeof(ir->phys)); + + tm6000_ir_change_protocol(ir, IR_TYPE_UNKNOWN); + err = ir_input_init(ir_input_dev->input_dev, &ir->ir, IR_TYPE_OTHER); + if (err < 0) + goto err_out_free; + + ir_input_dev->input_dev->name = ir->name; + ir_input_dev->input_dev->phys = ir->phys; + ir_input_dev->input_dev->id.bustype = BUS_USB; + ir_input_dev->input_dev->id.version = 1; + ir_input_dev->input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); + ir_input_dev->input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); + + ir_input_dev->input_dev->dev.parent = &dev->udev->dev; + + if (&dev->int_in) { + dprintk("IR over int\n"); + + ir->int_urb = usb_alloc_urb(0, GFP_KERNEL); + + pipe = usb_rcvintpipe(dev->udev, + dev->int_in.endp->desc.bEndpointAddress + & USB_ENDPOINT_NUMBER_MASK); + + size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); + dprintk("IR max size: %d\n", size); + + ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); + if (ir->int_urb->transfer_buffer == NULL) { + usb_free_urb(ir->int_urb); + goto err_out_stop; + } + dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval); + usb_fill_int_urb(ir->int_urb, dev->udev, pipe, + ir->int_urb->transfer_buffer, size, + tm6000_ir_urb_received, dev, + dev->int_in.endp->desc.bInterval); + rc = usb_submit_urb(ir->int_urb, GFP_KERNEL); + if (rc) { + kfree(ir->int_urb->transfer_buffer); + usb_free_urb(ir->int_urb); + err = rc; + goto err_out_stop; + } + ir->urb_data = kzalloc(size, GFP_KERNEL); + } + + /* ir register */ + err = ir_input_register(ir->input->input_dev, dev->ir_codes, + &ir->props, "tm6000"); + if (err) + goto err_out_stop; + + return 0; + +err_out_stop: + dev->ir = NULL; +err_out_free: + kfree(ir_input_dev); + kfree(ir); + return err; +} + +int tm6000_ir_fini(struct tm6000_core *dev) +{ + struct tm6000_IR *ir = dev->ir; + + /* skip detach on non attached board */ + + if (!ir) + return 0; + + ir_input_unregister(ir->input->input_dev); + + if (ir->int_urb) { + usb_kill_urb(ir->int_urb); + kfree(ir->int_urb->transfer_buffer); + usb_free_urb(ir->int_urb); + ir->int_urb = NULL; + kfree(ir->urb_data); + ir->urb_data = NULL; + } + + kfree(ir->input); + ir->input = NULL; + kfree(ir); + dev->ir = NULL; + + return 0; +} diff --git a/drivers/staging/tm6000/tm6000-stds.c b/drivers/staging/tm6000/tm6000-stds.c index b3564f611e5e..6bf4a73b320d 100644 --- a/drivers/staging/tm6000/tm6000-stds.c +++ b/drivers/staging/tm6000/tm6000-stds.c @@ -77,7 +77,7 @@ static struct tm6000_std_tv_settings tv_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a}, @@ -135,7 +135,7 @@ static struct tm6000_std_tv_settings tv_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f}, @@ -193,7 +193,7 @@ static struct tm6000_std_tv_settings tv_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63}, @@ -251,7 +251,7 @@ static struct tm6000_std_tv_settings tv_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8}, @@ -308,7 +308,7 @@ static struct tm6000_std_tv_settings tv_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2}, @@ -354,7 +354,7 @@ static struct tm6000_std_settings composite_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a}, @@ -396,7 +396,7 @@ static struct tm6000_std_settings composite_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f}, @@ -438,7 +438,7 @@ static struct tm6000_std_settings composite_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63}, @@ -480,7 +480,7 @@ static struct tm6000_std_settings composite_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8}, @@ -521,7 +521,7 @@ static struct tm6000_std_settings composite_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2}, @@ -567,7 +567,7 @@ static struct tm6000_std_settings svideo_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a}, @@ -609,7 +609,7 @@ static struct tm6000_std_settings svideo_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f}, @@ -651,7 +651,7 @@ static struct tm6000_std_settings svideo_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x00}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63}, @@ -693,7 +693,7 @@ static struct tm6000_std_settings svideo_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92}, {TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8}, @@ -734,7 +734,7 @@ static struct tm6000_std_settings svideo_stds[] = { {TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f}, {TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f}, {TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03}, - {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x00}, + {TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30}, {TM6010_REQ07_R17_HLOOP_MAXSTATE, 0x8b}, {TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e}, {TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b}, @@ -763,11 +763,11 @@ static struct tm6000_std_settings svideo_stds[] = { void tm6000_get_std_res(struct tm6000_core *dev) { /* Currently, those are the only supported resoltions */ - if (dev->norm & V4L2_STD_525_60) { + if (dev->norm & V4L2_STD_525_60) dev->height = 480; - } else { + else dev->height = 576; - } + dev->width = 720; } diff --git a/drivers/staging/tm6000/tm6000-usb-isoc.h b/drivers/staging/tm6000/tm6000-usb-isoc.h index 5a5049acd4ec..138716a8f056 100644 --- a/drivers/staging/tm6000/tm6000-usb-isoc.h +++ b/drivers/staging/tm6000/tm6000-usb-isoc.h @@ -39,7 +39,7 @@ struct usb_isoc_ctl { int pos, size, pktsize; /* Last field: ODD or EVEN? */ - int field; + int vfield; /* Stores incomplete commands */ u32 tmp_buf; @@ -47,7 +47,4 @@ struct usb_isoc_ctl { /* Stores already requested buffers */ struct tm6000_buffer *buf; - - /* Stores the number of received fields */ - int nfields; }; diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c index f2b7fe4a3581..ce0a089a0771 100644 --- a/drivers/staging/tm6000/tm6000-video.c +++ b/drivers/staging/tm6000/tm6000-video.c @@ -48,7 +48,7 @@ #define TM6000_MIN_BUF 4 #define TM6000_DEF_BUF 8 -#define TM6000_MAX_ISO_PACKETS 40 /* Max number of ISO packets */ +#define TM6000_MAX_ISO_PACKETS 46 /* Max number of ISO packets */ /* Declare static vars that will be used as parameters */ static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ @@ -56,6 +56,7 @@ static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ /* Debug level */ int tm6000_debug; +EXPORT_SYMBOL_GPL(tm6000_debug); /* supported controls */ static struct v4l2_queryctrl tm6000_qctrl[] = { @@ -149,8 +150,6 @@ static inline void get_next_buf(struct tm6000_dmaqueue *dma_q, /* Cleans up buffer - Usefull for testing for frame/URB loss */ outp = videobuf_to_vmalloc(&(*buf)->vb); -// if (outp) -// memset(outp, 0, (*buf)->vb.size); return; } @@ -186,249 +185,189 @@ const char *tm6000_msg_type[] = { /* * Identify the tm5600/6000 buffer header type and properly handles */ -static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp, - u8 *out_p, struct tm6000_buffer **buf) -{ - struct tm6000_dmaqueue *dma_q = urb->context; - struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq); - u8 c; - unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0; - int rc = 0; - /* FIXME: move to tm6000-isoc */ - static int last_line = -2, start_line = -2, last_field = -2; - - /* FIXME: this is the hardcoded window size - */ - unsigned int linewidth = (*buf)->vb.width << 1; - - if (!dev->isoc_ctl.cmd) { - c = (header >> 24) & 0xff; - - /* split the header fields */ - size = (((header & 0x7e) << 1) -1) *4; - block = (header >> 7) & 0xf; - field = (header >> 11) & 0x1; - line = (header >> 12) & 0x1ff; - cmd = (header >> 21) & 0x7; - - /* Validates header fields */ - if(size > TM6000_URB_MSG_LEN) - size = TM6000_URB_MSG_LEN; - - if (cmd == TM6000_URB_MSG_VIDEO) { - if ((block+1)*TM6000_URB_MSG_LEN>linewidth) - cmd = TM6000_URB_MSG_ERR; - - /* FIXME: Mounts the image as field0+field1 - * It should, instead, check if the user selected - * entrelaced or non-entrelaced mode - */ - pos = ((line << 1) - field - 1) * linewidth + - block * TM6000_URB_MSG_LEN; - - /* Don't allow to write out of the buffer */ - if (pos+TM6000_URB_MSG_LEN > (*buf)->vb.size) { - dprintk(dev, V4L2_DEBUG_ISOC, - "ERR: size=%d, num=%d, line=%d, " - "field=%d\n", - size, block, line, field); - - cmd = TM6000_URB_MSG_ERR; - } - } else { - pos=0; - } - - /* Prints debug info */ - dprintk(dev, V4L2_DEBUG_ISOC, "size=%d, num=%d, " - " line=%d, field=%d\n", - size, block, line, field); - - if ((last_line!=line)&&(last_line+1!=line) && - (cmd != TM6000_URB_MSG_ERR) ) { - if (cmd != TM6000_URB_MSG_VIDEO) { - dprintk(dev, V4L2_DEBUG_ISOC, "cmd=%d, " - "size=%d, num=%d, line=%d, field=%d\n", - cmd, size, block, line, field); - } - if (start_line<0) - start_line=last_line; - /* Prints debug info */ - dprintk(dev, V4L2_DEBUG_ISOC, "lines= %d-%d, " - "field=%d\n", - start_line, last_line, field); - - if ((start_line<6 && last_line>200) && - (last_field != field) ) { - - dev->isoc_ctl.nfields++; - if (dev->isoc_ctl.nfields>=2) { - dev->isoc_ctl.nfields=0; - - /* Announces that a new buffer were filled */ - buffer_filled (dev, dma_q, *buf); - dprintk(dev, V4L2_DEBUG_ISOC, - "new buffer filled\n"); - get_next_buf (dma_q, buf); - if (!*buf) - return rc; - out_p = videobuf_to_vmalloc(&((*buf)->vb)); - if (!out_p) - return rc; - - pos = dev->isoc_ctl.pos = 0; - } - } - - start_line=line; - last_field=field; - } - if (cmd == TM6000_URB_MSG_VIDEO) - last_line = line; - - pktsize = TM6000_URB_MSG_LEN; - } else { - /* Continue the last copy */ - cmd = dev->isoc_ctl.cmd; - size= dev->isoc_ctl.size; - pos = dev->isoc_ctl.pos; - pktsize = dev->isoc_ctl.pktsize; - } - - cpysize = (endp-(*ptr) > size) ? size : endp - *ptr; - - if (cpysize) { - /* handles each different URB message */ - switch(cmd) { - case TM6000_URB_MSG_VIDEO: - /* Fills video buffer */ - memcpy(&out_p[pos], *ptr, cpysize); - break; - case TM6000_URB_MSG_PTS: - break; - case TM6000_URB_MSG_AUDIO: -/* Need some code to process audio */ -printk ("%ld: cmd=%s, size=%d\n", jiffies, - tm6000_msg_type[cmd],size); - break; - default: - dprintk (dev, V4L2_DEBUG_ISOC, "cmd=%s, size=%d\n", - tm6000_msg_type[cmd],size); - } - } - if (cpysize<size) { - /* End of URB packet, but cmd processing is not - * complete. Preserve the state for a next packet - */ - dev->isoc_ctl.pos = pos+cpysize; - dev->isoc_ctl.size= size-cpysize; - dev->isoc_ctl.cmd = cmd; - dev->isoc_ctl.pktsize = pktsize-cpysize; - (*ptr)+=cpysize; - } else { - dev->isoc_ctl.cmd = 0; - (*ptr)+=pktsize; - } - - return rc; -} - -static int copy_streams(u8 *data, u8 *out_p, unsigned long len, - struct urb *urb, struct tm6000_buffer **buf) +static int copy_streams(u8 *data, unsigned long len, + struct urb *urb) { struct tm6000_dmaqueue *dma_q = urb->context; struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); - u8 *ptr=data, *endp=data+len; + u8 *ptr=data, *endp=data+len, c; unsigned long header=0; int rc=0; + unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0; + struct tm6000_buffer *vbuf; + char *voutp = NULL; + unsigned int linewidth; - for (ptr=data; ptr<endp;) { + /* get video buffer */ + get_next_buf (dma_q, &vbuf); + if (!vbuf) + return rc; + voutp = videobuf_to_vmalloc(&vbuf->vb); + if (!voutp) + return 0; + + for (ptr = data; ptr < endp;) { if (!dev->isoc_ctl.cmd) { - u8 *p=(u8 *)&dev->isoc_ctl.tmp_buf; - /* FIXME: This seems very complex - * It just recovers up to 3 bytes of the header that - * might be at the previous packet - */ - if (dev->isoc_ctl.tmp_buf_len) { - while (dev->isoc_ctl.tmp_buf_len) { - if ( *(ptr+3-dev->isoc_ctl.tmp_buf_len) == 0x47) { - break; - } - p++; - dev->isoc_ctl.tmp_buf_len--; - } - if (dev->isoc_ctl.tmp_buf_len) { - memcpy(&header, p, - dev->isoc_ctl.tmp_buf_len); - memcpy((u8 *)&header + + /* Header */ + if (dev->isoc_ctl.tmp_buf_len > 0) { + /* from last urb or packet */ + header = dev->isoc_ctl.tmp_buf; + if (4 - dev->isoc_ctl.tmp_buf_len > 0) { + memcpy ((u8 *)&header + dev->isoc_ctl.tmp_buf_len, ptr, 4 - dev->isoc_ctl.tmp_buf_len); ptr += 4 - dev->isoc_ctl.tmp_buf_len; - goto HEADER; } - } - /* Seek for sync */ - for (;ptr<endp-3;ptr++) { - if (*(ptr+3)==0x47) - break; + dev->isoc_ctl.tmp_buf_len = 0; + } else { + if (ptr + 3 >= endp) { + /* have incomplete header */ + dev->isoc_ctl.tmp_buf_len = endp - ptr; + memcpy (&dev->isoc_ctl.tmp_buf, ptr, + dev->isoc_ctl.tmp_buf_len); + return rc; + } + /* Seek for sync */ + for (; ptr < endp - 3; ptr++) { + if (*(ptr + 3) == 0x47) + break; + } + /* Get message header */ + header = *(unsigned long *)ptr; + ptr += 4; } - if (ptr+3>=endp) { - dev->isoc_ctl.tmp_buf_len=endp-ptr; - memcpy (&dev->isoc_ctl.tmp_buf,ptr, - dev->isoc_ctl.tmp_buf_len); - dev->isoc_ctl.cmd=0; - return rc; + /* split the header fields */ + c = (header >> 24) & 0xff; + size = ((header & 0x7e) << 1); + if (size > 0) + size -= 4; + block = (header >> 7) & 0xf; + field = (header >> 11) & 0x1; + line = (header >> 12) & 0x1ff; + cmd = (header >> 21) & 0x7; + /* Validates haeder fields */ + if (size > TM6000_URB_MSG_LEN) + size = TM6000_URB_MSG_LEN; + pktsize = TM6000_URB_MSG_LEN; + /* calculate position in buffer + * and change the buffer + */ + switch (cmd) { + case TM6000_URB_MSG_VIDEO: + if ((dev->isoc_ctl.vfield != field) && + (field == 1)) { + /* Announces that a new buffer + * were filled + */ + buffer_filled (dev, dma_q, vbuf); + dprintk (dev, V4L2_DEBUG_ISOC, + "new buffer filled\n"); + get_next_buf (dma_q, &vbuf); + if (!vbuf) + return rc; + voutp = videobuf_to_vmalloc (&vbuf->vb); + if (!voutp) + return rc; + memset(voutp, 0, vbuf->vb.size); + } + linewidth = vbuf->vb.width << 1; + pos = ((line << 1) - field - 1) * linewidth + + block * TM6000_URB_MSG_LEN; + /* Don't allow to write out of the buffer */ + if (pos + size > vbuf->vb.size) + cmd = TM6000_URB_MSG_ERR; + dev->isoc_ctl.vfield = field; + break; + case TM6000_URB_MSG_VBI: + break; + case TM6000_URB_MSG_AUDIO: + case TM6000_URB_MSG_PTS: + size = pktsize; /* Size is always 180 bytes */ + break; } - - /* Get message header */ - header=*(unsigned long *)ptr; - ptr+=4; + } else { + /* Continue the last copy */ + cmd = dev->isoc_ctl.cmd; + size = dev->isoc_ctl.size; + pos = dev->isoc_ctl.pos; + pktsize = dev->isoc_ctl.pktsize; } -HEADER: - /* Copy or continue last copy */ - rc=copy_packet(urb,header,&ptr,endp,out_p,buf); - if (rc<0) { - buf=NULL; - printk(KERN_ERR "tm6000: buffer underrun at %ld\n", - jiffies); - return rc; + cpysize = (endp - ptr > size) ? size : endp - ptr; + if (cpysize) { + /* copy data in different buffers */ + switch (cmd) { + case TM6000_URB_MSG_VIDEO: + /* Fills video buffer */ + if (vbuf) + memcpy (&voutp[pos], ptr, cpysize); + break; + case TM6000_URB_MSG_AUDIO: + tm6000_call_fillbuf(dev, TM6000_AUDIO, ptr, cpysize); + break; + case TM6000_URB_MSG_VBI: + /* Need some code to copy vbi buffer */ + break; + case TM6000_URB_MSG_PTS: + /* Need some code to copy pts */ + break; + } + } + if (ptr + pktsize > endp) { + /* End of URB packet, but cmd processing is not + * complete. Preserve the state for a next packet + */ + dev->isoc_ctl.pos = pos + cpysize; + dev->isoc_ctl.size = size - cpysize; + dev->isoc_ctl.cmd = cmd; + dev->isoc_ctl.pktsize = pktsize - (endp - ptr); + ptr += endp - ptr; + } else { + dev->isoc_ctl.cmd = 0; + ptr += pktsize; } - if (!*buf) - return 0; } - return 0; } + /* * Identify the tm5600/6000 buffer header type and properly handles */ -static int copy_multiplexed(u8 *ptr, u8 *out_p, unsigned long len, - struct urb *urb, struct tm6000_buffer **buf) +static int copy_multiplexed(u8 *ptr, unsigned long len, + struct urb *urb) { struct tm6000_dmaqueue *dma_q = urb->context; struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); unsigned int pos=dev->isoc_ctl.pos,cpysize; int rc=1; + struct tm6000_buffer *buf; + char *outp = NULL; + + get_next_buf(dma_q, &buf); + if (buf) + outp = videobuf_to_vmalloc(&buf->vb); + + if (!outp) + return 0; while (len>0) { - cpysize=min(len,(*buf)->vb.size-pos); -//printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos); - memcpy(&out_p[pos], ptr, cpysize); + cpysize=min(len,buf->vb.size-pos); + //printk("Copying %d bytes (max=%lu) from %p to %p[%u]\n",cpysize,(*buf)->vb.size,ptr,out_p,pos); + memcpy(&outp[pos], ptr, cpysize); pos+=cpysize; ptr+=cpysize; len-=cpysize; - if (pos >= (*buf)->vb.size) { + if (pos >= buf->vb.size) { pos=0; /* Announces that a new buffer were filled */ - buffer_filled (dev, dma_q, *buf); + buffer_filled (dev, dma_q, buf); dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n"); - get_next_buf (dma_q, buf); - if (!*buf) + get_next_buf (dma_q, &buf); + if (!buf) break; - out_p = videobuf_to_vmalloc(&((*buf)->vb)); - if (!out_p) + outp = videobuf_to_vmalloc(&(buf->vb)); + if (!outp) return rc; pos = 0; } @@ -486,53 +425,36 @@ static inline int tm6000_isoc_copy(struct urb *urb) { struct tm6000_dmaqueue *dma_q = urb->context; struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq); - struct tm6000_buffer *buf; - int i, len=0, rc=1; - int size; - char *outp = NULL, *p; - unsigned long copied; - - get_next_buf(dma_q, &buf); - if (buf) - outp = videobuf_to_vmalloc(&buf->vb); + int i, len=0, rc=1, status; + char *p; - if (!outp) - return 0; - - size = buf->vb.size; - - copied=0; - - if (urb->status<0) { - print_err_status (dev,-1,urb->status); + if (urb->status < 0) { + print_err_status (dev, -1, urb->status); return 0; } for (i = 0; i < urb->number_of_packets; i++) { - int status = urb->iso_frame_desc[i].status; + status = urb->iso_frame_desc[i].status; if (status<0) { print_err_status (dev,i,status); continue; } - len=urb->iso_frame_desc[i].actual_length; + len = urb->iso_frame_desc[i].actual_length; -// if (len>=TM6000_URB_MSG_LEN) { - p=urb->transfer_buffer + urb->iso_frame_desc[i].offset; + if (len > 0) { + p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; if (!urb->iso_frame_desc[i].status) { - if ((buf->fmt->fourcc)==V4L2_PIX_FMT_TM6000) { - rc=copy_multiplexed(p, outp, len, urb, &buf); + if ((dev->fourcc)==V4L2_PIX_FMT_TM6000) { + rc=copy_multiplexed(p, len, urb); if (rc<=0) return rc; } else { - copy_streams(p, outp, len, urb, &buf); + copy_streams(p, len, urb); } } - copied += len; - if (copied >= size || !buf) - break; -// } + } } return rc; } @@ -577,7 +499,6 @@ static void tm6000_uninit_isoc(struct tm6000_core *dev) struct urb *urb; int i; - dev->isoc_ctl.nfields = -1; dev->isoc_ctl.buf = NULL; for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { urb=dev->isoc_ctl.urb[i]; @@ -602,8 +523,6 @@ static void tm6000_uninit_isoc(struct tm6000_core *dev) dev->isoc_ctl.urb=NULL; dev->isoc_ctl.transfer_buffer=NULL; dev->isoc_ctl.num_bufs = 0; - - dev->isoc_ctl.num_bufs=0; } /* @@ -612,7 +531,7 @@ static void tm6000_uninit_isoc(struct tm6000_core *dev) static int tm6000_prepare_isoc(struct tm6000_core *dev, unsigned int framesize) { struct tm6000_dmaqueue *dma_q = &dev->vidq; - int i, j, sb_size, pipe, size, max_packets, num_bufs = 5; + int i, j, sb_size, pipe, size, max_packets, num_bufs = 8; struct urb *urb; /* De-allocates all pending stuff */ diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h index 6812d6867d57..1ec1bff9b294 100644 --- a/drivers/staging/tm6000/tm6000.h +++ b/drivers/staging/tm6000/tm6000.h @@ -20,8 +20,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -// Use the tm6000-hack, instead of the proper initialization code -//#define HACK 1 +/* Use the tm6000-hack, instead of the proper initialization code i*/ +/* #define HACK 1 */ #include <linux/videodev2.h> #include <media/v4l2-common.h> @@ -98,7 +98,7 @@ enum tm6000_io_method { }; enum tm6000_mode { - TM6000_MODE_UNKNOWN=0, + TM6000_MODE_UNKNOWN = 0, TM6000_MODE_ANALOG, TM6000_MODE_DIGITAL, }; @@ -128,10 +128,21 @@ struct tm6000_dvb { struct dvb_frontend *frontend; struct dmxdev dmxdev; unsigned int streams; - struct urb *bulk_urb; + struct urb *bulk_urb; struct mutex mutex; }; +struct snd_tm6000_card { + struct snd_card *card; + spinlock_t reg_lock; + struct tm6000_core *core; + struct snd_pcm_substream *substream; + + /* temporary data for buffer fill processing */ + unsigned buf_pos; + unsigned period_pos; +}; + struct tm6000_endpoint { struct usb_host_endpoint *endp; __u8 bInterfaceNumber; @@ -147,7 +158,7 @@ struct tm6000_core { enum tm6000_devtype dev_type; /* type of device */ v4l2_std_id norm; /* Current norm */ - int width,height; /* Selected resolution */ + int width, height; /* Selected resolution */ enum tm6000_core_state state; @@ -160,6 +171,8 @@ struct tm6000_core { struct tm6000_gpio gpio; + char *ir_codes; + /* Demodulator configuration */ int demod_addr; /* demodulator address */ @@ -168,6 +181,10 @@ struct tm6000_core { struct i2c_adapter i2c_adap; struct i2c_client i2c_client; + + /* extension */ + struct list_head devlist; + /* video for linux */ int users; @@ -186,6 +203,11 @@ struct tm6000_core { /* DVB-T support */ struct tm6000_dvb *dvb; + /* audio support */ + struct snd_tm6000_card *adev; + + struct tm6000_IR *ir; + /* locks */ struct mutex lock; @@ -193,6 +215,7 @@ struct tm6000_core { struct usb_device *udev; /* the usb device */ struct tm6000_endpoint bulk_in, bulk_out, isoc_in, isoc_out; + struct tm6000_endpoint int_in, int_out; /* scaler!=0 if scaler is active*/ int scaler; @@ -203,12 +226,26 @@ struct tm6000_core { spinlock_t slock; }; +enum tm6000_ops_type { + TM6000_AUDIO = 0x10, + TM6000_DVB = 0x20, +}; + +struct tm6000_ops { + struct list_head next; + char *name; + enum tm6000_ops_type type; + int (*init)(struct tm6000_core *); + int (*fini)(struct tm6000_core *); + int (*fillbuf)(struct tm6000_core *, char *buf, int size); +}; + struct tm6000_fh { struct tm6000_core *dev; /* video capture */ struct tm6000_fmt *fmt; - unsigned int width,height; + unsigned int width, height; struct videobuf_queue vb_vidq; enum v4l2_buf_type type; @@ -220,35 +257,43 @@ struct tm6000_fh { /* In tm6000-cards.c */ -int tm6000_tuner_callback (void *ptr, int component, int command, int arg); -int tm6000_xc5000_callback (void *ptr, int component, int command, int arg); +int tm6000_tuner_callback(void *ptr, int component, int command, int arg); +int tm6000_xc5000_callback(void *ptr, int component, int command, int arg); int tm6000_cards_setup(struct tm6000_core *dev); /* In tm6000-core.c */ -int tm6000_read_write_usb (struct tm6000_core *dev, u8 reqtype, u8 req, +int tm6000_read_write_usb(struct tm6000_core *dev, u8 reqtype, u8 req, u16 value, u16 index, u8 *buf, u16 len); -int tm6000_get_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index); +int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index); int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index); int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index); -int tm6000_set_reg (struct tm6000_core *dev, u8 req, u16 value, u16 index); -int tm6000_init (struct tm6000_core *dev); - -int tm6000_init_analog_mode (struct tm6000_core *dev); -int tm6000_init_digital_mode (struct tm6000_core *dev); -int tm6000_set_audio_bitrate (struct tm6000_core *dev, int bitrate); +int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index); +int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep); +int tm6000_init(struct tm6000_core *dev); -int tm6000_dvb_register(struct tm6000_core *dev); -void tm6000_dvb_unregister(struct tm6000_core *dev); +int tm6000_init_analog_mode(struct tm6000_core *dev); +int tm6000_init_digital_mode(struct tm6000_core *dev); +int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate); int tm6000_v4l2_register(struct tm6000_core *dev); int tm6000_v4l2_unregister(struct tm6000_core *dev); int tm6000_v4l2_exit(void); void tm6000_set_fourcc_format(struct tm6000_core *dev); +void tm6000_remove_from_devlist(struct tm6000_core *dev); +void tm6000_add_into_devlist(struct tm6000_core *dev); +int tm6000_register_extension(struct tm6000_ops *ops); +void tm6000_unregister_extension(struct tm6000_ops *ops); +void tm6000_init_extension(struct tm6000_core *dev); +void tm6000_close_extension(struct tm6000_core *dev); +int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type, + char *buf, int size); + + /* In tm6000-stds.c */ void tm6000_get_std_res(struct tm6000_core *dev); -int tm6000_set_standard (struct tm6000_core *dev, v4l2_std_id *norm); +int tm6000_set_standard(struct tm6000_core *dev, v4l2_std_id *norm); /* In tm6000-i2c.c */ int tm6000_i2c_register(struct tm6000_core *dev); @@ -262,21 +307,25 @@ int tm6000_vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i); int tm6000_vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i); -int tm6000_vidioc_reqbufs (struct file *file, void *priv, - struct v4l2_requestbuffers *rb); -int tm6000_vidioc_querybuf (struct file *file, void *priv, - struct v4l2_buffer *b); -int tm6000_vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *b); -int tm6000_vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *b); +int tm6000_vidioc_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *rb); +int tm6000_vidioc_querybuf(struct file *file, void *priv, + struct v4l2_buffer *b); +int tm6000_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b); +int tm6000_vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b); ssize_t tm6000_v4l2_read(struct file *filp, char __user * buf, size_t count, - loff_t * f_pos); + loff_t *f_pos); unsigned int tm6000_v4l2_poll(struct file *file, struct poll_table_struct *wait); int tm6000_queue_init(struct tm6000_core *dev); /* In tm6000-alsa.c */ -int tm6000_audio_init(struct tm6000_core *dev, int idx); +/*int tm6000_audio_init(struct tm6000_core *dev, int idx);*/ +/* In tm6000-input.c */ +int tm6000_ir_init(struct tm6000_core *dev); +int tm6000_ir_fini(struct tm6000_core *dev); +void tm6000_ir_wait(struct tm6000_core *dev, u8 state); /* Debug stuff */ @@ -284,7 +333,7 @@ extern int tm6000_debug; #define dprintk(dev, level, fmt, arg...) do {\ if (tm6000_debug & level) \ - printk(KERN_INFO "(%lu) %s %s :"fmt, jiffies, \ + printk(KERN_INFO "(%lu) %s %s :"fmt, jiffies, \ dev->name, __FUNCTION__ , ##arg); } while (0) #define V4L2_DEBUG_REG 0x0004 @@ -297,5 +346,3 @@ extern int tm6000_debug; #define tm6000_err(fmt, arg...) do {\ printk(KERN_ERR "tm6000 %s :"fmt, \ __FUNCTION__ , ##arg); } while (0) - - diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c index 52408164036f..6a499f0eb594 100644 --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -378,47 +378,67 @@ int usbip_thread(void *param) complete_and_exit(&ut->thread_done, 0); } +static void stop_rx_thread(struct usbip_device *ud) +{ + if (ud->tcp_rx.thread != NULL) { + send_sig(SIGKILL, ud->tcp_rx.thread, 1); + wait_for_completion(&ud->tcp_rx.thread_done); + usbip_udbg("rx_thread for ud %p has finished\n", ud); + } +} + +static void stop_tx_thread(struct usbip_device *ud) +{ + if (ud->tcp_tx.thread != NULL) { + send_sig(SIGKILL, ud->tcp_tx.thread, 1); + wait_for_completion(&ud->tcp_tx.thread_done); + usbip_udbg("tx_thread for ud %p has finished\n", ud); + } +} + int usbip_start_threads(struct usbip_device *ud) { /* * threads are invoked per one device (per one connection). */ struct task_struct *th; + int err = 0; th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip"); if (IS_ERR(th)) { printk(KERN_WARNING "Unable to start control thread\n"); - return PTR_ERR(th); + err = PTR_ERR(th); + goto ust_exit; } + th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip"); if (IS_ERR(th)) { printk(KERN_WARNING "Unable to start control thread\n"); - return PTR_ERR(th); + err = PTR_ERR(th); + goto tx_thread_err; } /* confirm threads are starting */ wait_for_completion(&ud->tcp_rx.thread_done); wait_for_completion(&ud->tcp_tx.thread_done); + return 0; + +tx_thread_err: + stop_rx_thread(ud); + +ust_exit: + return err; } EXPORT_SYMBOL_GPL(usbip_start_threads); void usbip_stop_threads(struct usbip_device *ud) { /* kill threads related to this sdev, if v.c. exists */ - if (ud->tcp_rx.thread != NULL) { - send_sig(SIGKILL, ud->tcp_rx.thread, 1); - wait_for_completion(&ud->tcp_rx.thread_done); - usbip_udbg("rx_thread for ud %p has finished\n", ud); - } - - if (ud->tcp_tx.thread != NULL) { - send_sig(SIGKILL, ud->tcp_tx.thread, 1); - wait_for_completion(&ud->tcp_tx.thread_done); - usbip_udbg("tx_thread for ud %p has finished\n", ud); - } + stop_rx_thread(ud); + stop_tx_thread(ud); } EXPORT_SYMBOL_GPL(usbip_stop_threads); diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c index 0c82eb47a28d..0f9ea58ff717 100644 --- a/drivers/staging/vme/bridges/vme_ca91cx42.c +++ b/drivers/staging/vme/bridges/vme_ca91cx42.c @@ -523,7 +523,7 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image, } if (image->bus_resource.name == NULL) { - image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL); + image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); if (image->bus_resource.name == NULL) { dev_err(ca91cx42_bridge->parent, "Unable to allocate " "memory for resource name\n"); diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c index abe88a380b72..f09cac163139 100644 --- a/drivers/staging/vme/bridges/vme_tsi148.c +++ b/drivers/staging/vme/bridges/vme_tsi148.c @@ -828,7 +828,7 @@ static int tsi148_alloc_resource(struct vme_master_resource *image, return 0; if (image->bus_resource.name == NULL) { - image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL); + image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); if (image->bus_resource.name == NULL) { dev_err(tsi148_bridge->parent, "Unable to allocate " "memory for resource name\n"); diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index 681419d6856e..251caa052eee 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c @@ -1,5 +1,5 @@ /* - * Copyright 2008 Pavel Machek <pavel@suse.cz> + * Copyright 2008 Pavel Machek <pavel@ucw.cz> * * Distribute under GPLv2. * diff --git a/drivers/staging/wlags49_h2/Kconfig b/drivers/staging/wlags49_h2/Kconfig index b6fc2ca7d85c..3efcbf8afedf 100644 --- a/drivers/staging/wlags49_h2/Kconfig +++ b/drivers/staging/wlags49_h2/Kconfig @@ -1,9 +1,11 @@ config WLAGS49_H2 tristate "Agere Systems HERMES II Wireless PC Card Model 0110" - depends on WLAN && WIRELESS_EXT && PCMCIA + depends on WLAN && PCMCIA + select WIRELESS_EXT select WEXT_SPY + select WEXT_PRIV ---help--- - Driver for wireless cards using Agere's HERMES II chipset - which are identified with Manufacture ID: 0156,0003 - The software is a modified version of wl_lkm_722_abg.tar.gz - from the Agere Systems website, addapted for Ubuntu 9.04. + Driver for wireless cards using Agere's HERMES II chipset + which are identified with Manufacture ID: 0156,0003 + The software is a modified version of wl_lkm_722_abg.tar.gz + from the Agere Systems website, addapted for Ubuntu 9.04. diff --git a/drivers/staging/wlags49_h2/wl_enc.c b/drivers/staging/wlags49_h2/wl_enc.c index 48c44c8fdb28..26cf5486edd6 100644 --- a/drivers/staging/wlags49_h2/wl_enc.c +++ b/drivers/staging/wlags49_h2/wl_enc.c @@ -62,6 +62,7 @@ /******************************************************************************* * include files ******************************************************************************/ +#include <linux/string.h> #include <wl_version.h> #include <debug.h> diff --git a/drivers/staging/wlags49_h2/wl_sysfs.h b/drivers/staging/wlags49_h2/wl_sysfs.h index 6d96d03cf490..fa658c38001e 100644 --- a/drivers/staging/wlags49_h2/wl_sysfs.h +++ b/drivers/staging/wlags49_h2/wl_sysfs.h @@ -2,6 +2,6 @@ extern void register_wlags_sysfs(struct net_device *); extern void unregister_wlags_sysfs(struct net_device *); #else -static void register_wlags_sysfs(struct net_device *) { return; }; -static void unregister_wlags_sysfs(struct net_device *) { return; }; +static inline void register_wlags_sysfs(struct net_device *net) { } +static inline void unregister_wlags_sysfs(struct net_device *net) { } #endif diff --git a/drivers/staging/wlags49_h25/Kconfig b/drivers/staging/wlags49_h25/Kconfig index dcc170929c13..bf5664a51cd4 100644 --- a/drivers/staging/wlags49_h25/Kconfig +++ b/drivers/staging/wlags49_h25/Kconfig @@ -1,9 +1,11 @@ config WLAGS49_H25 tristate "Linksys HERMES II.5 WCF54G_Wireless-G_CompactFlash_Card" - depends on WLAN && WIRELESS_EXT && PCMCIA + depends on WLAN && PCMCIA + select WIRELESS_EXT select WEXT_SPY + select WEXT_PRIV ---help--- - Driver for wireless cards using Agere's HERMES II.5 chipset - which are identified with Manufacture ID: 0156,0004 - The software is a modified version of wl_lkm_722_abg.tar.gz - from the Agere Systems website, addapted for Ubuntu 9.04. + Driver for wireless cards using Agere's HERMES II.5 chipset + which are identified with Manufacture ID: 0156,0004 + The software is a modified version of wl_lkm_722_abg.tar.gz + from the Agere Systems website, addapted for Ubuntu 9.04. diff --git a/drivers/staging/xgifb/Kconfig b/drivers/staging/xgifb/Kconfig new file mode 100644 index 000000000000..bb0ca5974ea0 --- /dev/null +++ b/drivers/staging/xgifb/Kconfig @@ -0,0 +1,11 @@ +config FB_XGI + tristate "XGI display support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This driver supports notebooks with XGI Z7,Z9,Z11 PCI chips. + Say Y if you have such a graphics card. + To compile this driver as a module, choose M here: the + module will be called xgifb.ko diff --git a/drivers/staging/xgifb/Makefile b/drivers/staging/xgifb/Makefile new file mode 100644 index 000000000000..2a317707de0f --- /dev/null +++ b/drivers/staging/xgifb/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_FB_XGI) += xgifb.o + +xgifb-objs := XGI_main_26.o XGI_accel.o vb_init.o vb_setmode.o vb_util.o vb_ext.o + diff --git a/drivers/staging/xgifb/TODO b/drivers/staging/xgifb/TODO new file mode 100644 index 000000000000..7d71019b84c2 --- /dev/null +++ b/drivers/staging/xgifb/TODO @@ -0,0 +1,15 @@ +This drivers still need a lot of work. I can list all cleanups to do but it's +going to be long. So, I'm writing "cleanups" and not the list. + +Arnaud + +TODO: +- clean ups +- fix build warnings when module +- sort out dup ids with SiS driver +- remove useless/wrong/unused #ifdef/code/... +- fix printk usages +- get rid of non-linux related stuff + +Please send patches to: +Arnaud Patard <apatard@mandriva.com> diff --git a/drivers/staging/xgifb/XGI.h b/drivers/staging/xgifb/XGI.h new file mode 100644 index 000000000000..87803dd032de --- /dev/null +++ b/drivers/staging/xgifb/XGI.h @@ -0,0 +1,10 @@ +#ifndef _XGI_H +#define _XGI_H + +#if 1 +#define TWDEBUG(x) +#else +#define TWDEBUG(x) printk(KERN_INFO x "\n"); +#endif + +#endif diff --git a/drivers/staging/xgifb/XGI_accel.c b/drivers/staging/xgifb/XGI_accel.c new file mode 100644 index 000000000000..86ec3421942f --- /dev/null +++ b/drivers/staging/xgifb/XGI_accel.c @@ -0,0 +1,596 @@ +/* + * XGI 300/630/730/540/315/550/650/740 frame buffer driver + * for Linux kernels 2.4.x and 2.5.x + * + * 2D acceleration part + * + * Based on the X driver's XGI300_accel.c which is + * Copyright Xavier Ducoin <x.ducoin@lectra.com> + * Copyright 2002 by Thomas Winischhofer, Vienna, Austria + * and XGI310_accel.c which is + * Copyright 2002 by Thomas Winischhofer, Vienna, Austria + * + * Author: Thomas Winischhofer <thomas@winischhofer.net> + * (see http://www.winischhofer.net/ + * for more information and updates) + */ + +//#include <linux/config.h> +#include <linux/version.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/console.h> +#include <linux/selection.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/vt_kern.h> +#include <linux/capability.h> +#include <linux/fs.h> +#include <linux/agp_backend.h> + +#include <linux/types.h> +/* +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include <linux/XGIfb.h> +#else +#include <video/XGIfb.h> +#endif +*/ +#include <asm/io.h> + +#ifdef CONFIG_MTRR +#include <asm/mtrr.h> +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#include <video/fbcon.h> +#include <video/fbcon-cfb8.h> +#include <video/fbcon-cfb16.h> +#include <video/fbcon-cfb24.h> +#include <video/fbcon-cfb32.h> +#endif + +#include "osdef.h" +#include "vgatypes.h" +#include "vb_struct.h" +#include "XGIfb.h" +#include "XGI_accel.h" + + +extern struct video_info xgi_video_info; +extern int XGIfb_accel; + +static const int XGIALUConv[] = +{ + 0x00, /* dest = 0; 0, GXclear, 0 */ + 0x88, /* dest &= src; DSa, GXand, 0x1 */ + 0x44, /* dest = src & ~dest; SDna, GXandReverse, 0x2 */ + 0xCC, /* dest = src; S, GXcopy, 0x3 */ + 0x22, /* dest &= ~src; DSna, GXandInverted, 0x4 */ + 0xAA, /* dest = dest; D, GXnoop, 0x5 */ + 0x66, /* dest = ^src; DSx, GXxor, 0x6 */ + 0xEE, /* dest |= src; DSo, GXor, 0x7 */ + 0x11, /* dest = ~src & ~dest; DSon, GXnor, 0x8 */ + 0x99, /* dest ^= ~src ; DSxn, GXequiv, 0x9 */ + 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ + 0xDD, /* dest = src|~dest ; SDno, GXorReverse, 0xB */ + 0x33, /* dest = ~src; Sn, GXcopyInverted, 0xC */ + 0xBB, /* dest |= ~src; DSno, GXorInverted, 0xD */ + 0x77, /* dest = ~src|~dest; DSan, GXnand, 0xE */ + 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ +}; +/* same ROP but with Pattern as Source */ +static const int XGIPatALUConv[] = +{ + 0x00, /* dest = 0; 0, GXclear, 0 */ + 0xA0, /* dest &= src; DPa, GXand, 0x1 */ + 0x50, /* dest = src & ~dest; PDna, GXandReverse, 0x2 */ + 0xF0, /* dest = src; P, GXcopy, 0x3 */ + 0x0A, /* dest &= ~src; DPna, GXandInverted, 0x4 */ + 0xAA, /* dest = dest; D, GXnoop, 0x5 */ + 0x5A, /* dest = ^src; DPx, GXxor, 0x6 */ + 0xFA, /* dest |= src; DPo, GXor, 0x7 */ + 0x05, /* dest = ~src & ~dest; DPon, GXnor, 0x8 */ + 0xA5, /* dest ^= ~src ; DPxn, GXequiv, 0x9 */ + 0x55, /* dest = ~dest; Dn, GXInvert, 0xA */ + 0xF5, /* dest = src|~dest ; PDno, GXorReverse, 0xB */ + 0x0F, /* dest = ~src; Pn, GXcopyInverted, 0xC */ + 0xAF, /* dest |= ~src; DPno, GXorInverted, 0xD */ + 0x5F, /* dest = ~src|~dest; DPan, GXnand, 0xE */ + 0xFF, /* dest = 0xFF; 1, GXset, 0xF */ +}; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) +static const unsigned char myrops[] = { + 3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 + }; +#endif + +/* 300 series */ +#if 0 +static void +XGI300Sync(void) +{ + XGI300Idle +} +#endif +static void +XGI310Sync(void) +{ + XGI310Idle +} +#if 0 +static void +XGI300SetupForScreenToScreenCopy(int xdir, int ydir, int rop, + unsigned int planemask, int trans_color) +{ + XGI300SetupDSTColorDepth(xgi_video_info.DstColor); + XGI300SetupSRCPitch(xgi_video_info.video_linelength) + XGI300SetupDSTRect(xgi_video_info.video_linelength, 0xFFF) + + if(trans_color != -1) { + XGI300SetupROP(0x0A) + XGI300SetupSRCTrans(trans_color) + XGI300SetupCMDFlag(TRANSPARENT_BITBLT) + } else { + XGI300SetupROP(XGIALUConv[rop]) + } + if(xdir > 0) { + XGI300SetupCMDFlag(X_INC) + } + if(ydir > 0) { + XGI300SetupCMDFlag(Y_INC) + } +} + +static void +XGI300SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y, + int width, int height) +{ + long srcbase, dstbase; + + srcbase = dstbase = 0; + if (src_y >= 2048) { + srcbase = xgi_video_info.video_linelength * src_y; + src_y = 0; + } + if (dst_y >= 2048) { + dstbase = xgi_video_info.video_linelength * dst_y; + dst_y = 0; + } + + XGI300SetupSRCBase(srcbase); + XGI300SetupDSTBase(dstbase); + + if(!(xgi_video_info.CommandReg & X_INC)) { + src_x += width-1; + dst_x += width-1; + } + if(!(xgi_video_info.CommandReg & Y_INC)) { + src_y += height-1; + dst_y += height-1; + } + XGI300SetupRect(width, height) + XGI300SetupSRCXY(src_x, src_y) + XGI300SetupDSTXY(dst_x, dst_y) + XGI300DoCMD +} + +static void +XGI300SetupForSolidFill(int color, int rop, unsigned int planemask) +{ + XGI300SetupPATFG(color) + XGI300SetupDSTRect(xgi_video_info.video_linelength, 0xFFF) + XGI300SetupDSTColorDepth(xgi_video_info.DstColor); + XGI300SetupROP(XGIPatALUConv[rop]) + XGI300SetupCMDFlag(PATFG) +} + +static void +XGI300SubsequentSolidFillRect(int x, int y, int w, int h) +{ + long dstbase; + + dstbase = 0; + if(y >= 2048) { + dstbase = xgi_video_info.video_linelength * y; + y = 0; + } + XGI300SetupDSTBase(dstbase) + XGI300SetupDSTXY(x,y) + XGI300SetupRect(w,h) + XGI300SetupCMDFlag(X_INC | Y_INC | BITBLT) + XGI300DoCMD +} +#endif +/* 310/325 series ------------------------------------------------ */ + +static void +XGI310SetupForScreenToScreenCopy(int xdir, int ydir, int rop, + unsigned int planemask, int trans_color) +{ + XGI310SetupDSTColorDepth(xgi_video_info.DstColor); + XGI310SetupSRCPitch(xgi_video_info.video_linelength) + XGI310SetupDSTRect(xgi_video_info.video_linelength, 0xFFF) + if (trans_color != -1) { + XGI310SetupROP(0x0A) + XGI310SetupSRCTrans(trans_color) + XGI310SetupCMDFlag(TRANSPARENT_BITBLT) + } else { + XGI310SetupROP(XGIALUConv[rop]) + /* Set command - not needed, both 0 */ + /* XGISetupCMDFlag(BITBLT | SRCVIDEO) */ + } + XGI310SetupCMDFlag(xgi_video_info.XGI310_AccelDepth) + /* TW: The 310/325 series is smart enough to know the direction */ +} + +static void +XGI310SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y, + int width, int height) +{ + long srcbase, dstbase; + int mymin, mymax; + + srcbase = dstbase = 0; + mymin = min(src_y, dst_y); + mymax = max(src_y, dst_y); + + /* Although the chip knows the direction to use + * if the source and destination areas overlap, + * that logic fails if we fiddle with the bitmap + * addresses. Therefore, we check if the source + * and destination blitting areas overlap and + * adapt the bitmap addresses synchronously + * if the coordinates exceed the valid range. + * The the areas do not overlap, we do our + * normal check. + */ + if((mymax - mymin) < height) { + if((src_y >= 2048) || (dst_y >= 2048)) { + srcbase = xgi_video_info.video_linelength * mymin; + dstbase = xgi_video_info.video_linelength * mymin; + src_y -= mymin; + dst_y -= mymin; + } + } else { + if(src_y >= 2048) { + srcbase = xgi_video_info.video_linelength * src_y; + src_y = 0; + } + if(dst_y >= 2048) { + dstbase = xgi_video_info.video_linelength * dst_y; + dst_y = 0; + } + } + + XGI310SetupSRCBase(srcbase); + XGI310SetupDSTBase(dstbase); + XGI310SetupRect(width, height) + XGI310SetupSRCXY(src_x, src_y) + XGI310SetupDSTXY(dst_x, dst_y) + XGI310DoCMD +} + +static void +XGI310SetupForSolidFill(int color, int rop, unsigned int planemask) +{ + XGI310SetupPATFG(color) + XGI310SetupDSTRect(xgi_video_info.video_linelength, 0xFFF) + XGI310SetupDSTColorDepth(xgi_video_info.DstColor); + XGI310SetupROP(XGIPatALUConv[rop]) + XGI310SetupCMDFlag(PATFG | xgi_video_info.XGI310_AccelDepth) +} + +static void +XGI310SubsequentSolidFillRect(int x, int y, int w, int h) +{ + long dstbase; + + dstbase = 0; + if(y >= 2048) { + dstbase = xgi_video_info.video_linelength * y; + y = 0; + } + XGI310SetupDSTBase(dstbase) + XGI310SetupDSTXY(x,y) + XGI310SetupRect(w,h) + XGI310SetupCMDFlag(BITBLT) + XGI310DoCMD +} + +/* --------------------------------------------------------------------- */ + +/* The exported routines */ + +int XGIfb_initaccel(void) +{ +#ifdef XGIFB_USE_SPINLOCKS + spin_lock_init(&xgi_video_info.lockaccel); +#endif + return(0); +} + +void XGIfb_syncaccel(void) +{ + + XGI310Sync(); + +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) /* --- KERNEL 2.5.34 and later --- */ + +int fbcon_XGI_sync(struct fb_info *info) +{ + if(!XGIfb_accel) return 0; + CRITFLAGS + + XGI310Sync(); + + CRITEND + return 0; +} + +void fbcon_XGI_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ + int col=0; + CRITFLAGS + + + if(!rect->width || !rect->height) + return; + + if(!XGIfb_accel) { + cfb_fillrect(info, rect); + return; + } + + switch(info->var.bits_per_pixel) { + case 8: col = rect->color; + break; + case 16: col = ((u32 *)(info->pseudo_palette))[rect->color]; + break; + case 32: col = ((u32 *)(info->pseudo_palette))[rect->color]; + break; + } + + + CRITBEGIN + XGI310SetupForSolidFill(col, myrops[rect->rop], 0); + XGI310SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height); + CRITEND + XGI310Sync(); + + +} + +void fbcon_XGI_copyarea(struct fb_info *info, const struct fb_copyarea *area) +{ + int xdir, ydir; + CRITFLAGS + + + if(!XGIfb_accel) { + cfb_copyarea(info, area); + return; + } + + if(!area->width || !area->height) + return; + + if(area->sx < area->dx) xdir = 0; + else xdir = 1; + if(area->sy < area->dy) ydir = 0; + else ydir = 1; + + CRITBEGIN + XGI310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1); + XGI310SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height); + CRITEND + XGI310Sync(); + +} + +#endif + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) /* ------ KERNEL <2.5.34 ------ */ + +void fbcon_XGI_bmove(struct display *p, int srcy, int srcx, + int dsty, int dstx, int height, int width) +{ + int xdir, ydir; + CRITFLAGS + + if(!xgi_video_info.accel) { + switch(xgi_video_info.video_bpp) { + case 8: +#ifdef FBCON_HAS_CFB8 + fbcon_cfb8_bmove(p, srcy, srcx, dsty, dstx, height, width); +#endif + break; + case 16: +#ifdef FBCON_HAS_CFB16 + fbcon_cfb16_bmove(p, srcy, srcx, dsty, dstx, height, width); +#endif + break; + case 32: +#ifdef FBCON_HAS_CFB32 + fbcon_cfb32_bmove(p, srcy, srcx, dsty, dstx, height, width); +#endif + break; + } + return; + } + + srcx *= fontwidth(p); + srcy *= fontheight(p); + dstx *= fontwidth(p); + dsty *= fontheight(p); + width *= fontwidth(p); + height *= fontheight(p); + + if(srcx < dstx) xdir = 0; + else xdir = 1; + if(srcy < dsty) ydir = 0; + else ydir = 1; + + + CRITBEGIN + XGI310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1); + XGI310SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height); + CRITEND + XGI310Sync(); +#if 0 + printk(KERN_INFO "XGI_bmove sx %d sy %d dx %d dy %d w %d h %d\n", + srcx, srcy, dstx, dsty, width, height); +#endif + +} + + +static void fbcon_XGI_clear(struct vc_data *conp, struct display *p, + int srcy, int srcx, int height, int width, int color) +{ + CRITFLAGS + + srcx *= fontwidth(p); + srcy *= fontheight(p); + width *= fontwidth(p); + height *= fontheight(p); + + + CRITBEGIN + XGI310SetupForSolidFill(color, 3, 0); + XGI310SubsequentSolidFillRect(srcx, srcy, width, height); + CRITEND + XGI310Sync(); + +} + +void fbcon_XGI_clear8(struct vc_data *conp, struct display *p, + int srcy, int srcx, int height, int width) +{ + u32 bgx; + + if(!xgi_video_info.accel) { +#ifdef FBCON_HAS_CFB8 + fbcon_cfb8_clear(conp, p, srcy, srcx, height, width); +#endif + return; + } + + bgx = attr_bgcol_ec(p, conp); + fbcon_XGI_clear(conp, p, srcy, srcx, height, width, bgx); +} + +void fbcon_XGI_clear16(struct vc_data *conp, struct display *p, + int srcy, int srcx, int height, int width) +{ + u32 bgx; + if(!xgi_video_info.accel) { +#ifdef FBCON_HAS_CFB16 + fbcon_cfb16_clear(conp, p, srcy, srcx, height, width); +#endif + return; + } + + bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)]; + fbcon_XGI_clear(conp, p, srcy, srcx, height, width, bgx); +} + +void fbcon_XGI_clear32(struct vc_data *conp, struct display *p, + int srcy, int srcx, int height, int width) +{ + u32 bgx; + + if(!xgi_video_info.accel) { +#ifdef FBCON_HAS_CFB32 + fbcon_cfb32_clear(conp, p, srcy, srcx, height, width); +#endif + return; + } + + bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)]; + fbcon_XGI_clear(conp, p, srcy, srcx, height, width, bgx); +} + +void fbcon_XGI_revc(struct display *p, int srcx, int srcy) +{ + CRITFLAGS + + if(!xgi_video_info.accel) { + switch(xgi_video_info.video_bpp) { + case 16: +#ifdef FBCON_HAS_CFB16 + fbcon_cfb16_revc(p, srcx, srcy); +#endif + break; + case 32: +#ifdef FBCON_HAS_CFB32 + fbcon_cfb32_revc(p, srcx, srcy); +#endif + break; + } + return; + } + + srcx *= fontwidth(p); + srcy *= fontheight(p); + + + CRITBEGIN + XGI310SetupForSolidFill(0, 0x0a, 0); + XGI310SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p)); + CRITEND + XGI310Sync(); + +} + +#ifdef FBCON_HAS_CFB8 +struct display_switch fbcon_XGI8 = { + setup: fbcon_cfb8_setup, + bmove: fbcon_XGI_bmove, + clear: fbcon_XGI_clear8, + putc: fbcon_cfb8_putc, + putcs: fbcon_cfb8_putcs, + revc: fbcon_cfb8_revc, + clear_margins: fbcon_cfb8_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif +#ifdef FBCON_HAS_CFB16 +struct display_switch fbcon_XGI16 = { + setup: fbcon_cfb16_setup, + bmove: fbcon_XGI_bmove, + clear: fbcon_XGI_clear16, + putc: fbcon_cfb16_putc, + putcs: fbcon_cfb16_putcs, + revc: fbcon_XGI_revc, + clear_margins: fbcon_cfb16_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif +#ifdef FBCON_HAS_CFB32 +struct display_switch fbcon_XGI32 = { + setup: fbcon_cfb32_setup, + bmove: fbcon_XGI_bmove, + clear: fbcon_XGI_clear32, + putc: fbcon_cfb32_putc, + putcs: fbcon_cfb32_putcs, + revc: fbcon_XGI_revc, + clear_margins: fbcon_cfb32_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif + +#endif /* KERNEL VERSION */ + + diff --git a/drivers/staging/xgifb/XGI_accel.h b/drivers/staging/xgifb/XGI_accel.h new file mode 100644 index 000000000000..04e126772bb8 --- /dev/null +++ b/drivers/staging/xgifb/XGI_accel.h @@ -0,0 +1,511 @@ +/* + * XGI 300/630/730/540/315/550/650/740 frame buffer driver + * for Linux kernels 2.4.x and 2.5.x + * + * 2D acceleration part + * + * Based on the X driver's XGI300_accel.h which is + * Copyright Xavier Ducoin <x.ducoin@lectra.com> + * Copyright 2002 by Thomas Winischhofer, Vienna, Austria + * and XGI310_accel.h which is + * Copyright 2002 by Thomas Winischhofer, Vienna, Austria + * + * Author: Thomas Winischhofer <thomas@winischhofer.net>: + * (see http://www.winischhofer.net/ + * for more information and updates) + */ + +#ifndef _XGIFB_ACCEL_H +#define _XGIFB_ACCEL_H + +/* Guard accelerator accesses with spin_lock_irqsave? Works well without. */ +#undef XGIFB_USE_SPINLOCKS + +#ifdef XGIFB_USE_SPINLOCKS +#include <linux/spinlock.h> +#define CRITBEGIN spin_lock_irqsave(&xgi_video_info.lockaccel), critflags); +#define CRITEND spin_unlock_irqrestore(&xgi_video_info.lockaccel), critflags); +#define CRITFLAGS unsigned long critflags; +#else +#define CRITBEGIN +#define CRITEND +#define CRITFLAGS +#endif + +/* Definitions for the XGI engine communication. */ + +#define PATREGSIZE 384 /* Pattern register size. 384 bytes @ 0x8300 */ +#define BR(x) (0x8200 | (x) << 2) +#define PBR(x) (0x8300 | (x) << 2) + +/* XGI300 engine commands */ +#define BITBLT 0x00000000 /* Blit */ +#define COLOREXP 0x00000001 /* Color expand */ +#define ENCOLOREXP 0x00000002 /* Enhanced color expand */ +#define MULTIPLE_SCANLINE 0x00000003 /* ? */ +#define LINE 0x00000004 /* Draw line */ +#define TRAPAZOID_FILL 0x00000005 /* Fill trapezoid */ +#define TRANSPARENT_BITBLT 0x00000006 /* Transparent Blit */ + +/* Additional engine commands for 310/325 */ +#define ALPHA_BLEND 0x00000007 /* Alpha blend ? */ +#define A3D_FUNCTION 0x00000008 /* 3D command ? */ +#define CLEAR_Z_BUFFER 0x00000009 /* ? */ +#define GRADIENT_FILL 0x0000000A /* Gradient fill */ +#define STRETCH_BITBLT 0x0000000B /* Stretched Blit */ + +/* source select */ +#define SRCVIDEO 0x00000000 /* source is video RAM */ +#define SRCSYSTEM 0x00000010 /* source is system memory */ +#define SRCCPUBLITBUF SRCSYSTEM /* source is CPU-driven BitBuffer (for color expand) */ +#define SRCAGP 0x00000020 /* source is AGP memory (?) */ + +/* Pattern flags */ +#define PATFG 0x00000000 /* foreground color */ +#define PATPATREG 0x00000040 /* pattern in pattern buffer (0x8300) */ +#define PATMONO 0x00000080 /* mono pattern */ + +/* blitting direction (300 series only) */ +#define X_INC 0x00010000 +#define X_DEC 0x00000000 +#define Y_INC 0x00020000 +#define Y_DEC 0x00000000 + +/* Clipping flags */ +#define NOCLIP 0x00000000 +#define NOMERGECLIP 0x04000000 +#define CLIPENABLE 0x00040000 +#define CLIPWITHOUTMERGE 0x04040000 + +/* Transparency */ +#define OPAQUE 0x00000000 +#define TRANSPARENT 0x00100000 + +/* ? */ +#define DSTAGP 0x02000000 +#define DSTVIDEO 0x02000000 + +/* Line */ +#define LINE_STYLE 0x00800000 +#define NO_RESET_COUNTER 0x00400000 +#define NO_LAST_PIXEL 0x00200000 + +/* Subfunctions for Color/Enhanced Color Expansion (310/325 only) */ +#define COLOR_TO_MONO 0x00100000 +#define AA_TEXT 0x00200000 + +/* Some general registers for 310/325 series */ +#define SRC_ADDR 0x8200 +#define SRC_PITCH 0x8204 +#define AGP_BASE 0x8206 /* color-depth dependent value */ +#define SRC_Y 0x8208 +#define SRC_X 0x820A +#define DST_Y 0x820C +#define DST_X 0x820E +#define DST_ADDR 0x8210 +#define DST_PITCH 0x8214 +#define DST_HEIGHT 0x8216 +#define RECT_WIDTH 0x8218 +#define RECT_HEIGHT 0x821A +#define PAT_FGCOLOR 0x821C +#define PAT_BGCOLOR 0x8220 +#define SRC_FGCOLOR 0x8224 +#define SRC_BGCOLOR 0x8228 +#define MONO_MASK 0x822C +#define LEFT_CLIP 0x8234 +#define TOP_CLIP 0x8236 +#define RIGHT_CLIP 0x8238 +#define BOTTOM_CLIP 0x823A +#define COMMAND_READY 0x823C +#define FIRE_TRIGGER 0x8240 + +#define PATTERN_REG 0x8300 /* 384 bytes pattern buffer */ + +/* Line registers */ +#define LINE_X0 SRC_Y +#define LINE_X1 DST_Y +#define LINE_Y0 SRC_X +#define LINE_Y1 DST_X +#define LINE_COUNT RECT_WIDTH +#define LINE_STYLE_PERIOD RECT_HEIGHT +#define LINE_STYLE_0 MONO_MASK +#define LINE_STYLE_1 0x8230 +#define LINE_XN PATTERN_REG +#define LINE_YN PATTERN_REG+2 + +/* Transparent bitblit registers */ +#define TRANS_DST_KEY_HIGH PAT_FGCOLOR +#define TRANS_DST_KEY_LOW PAT_BGCOLOR +#define TRANS_SRC_KEY_HIGH SRC_FGCOLOR +#define TRANS_SRC_KEY_LOW SRC_BGCOLOR + +/* Queue */ +#define Q_BASE_ADDR 0x85C0 /* Base address of software queue (?) */ +#define Q_WRITE_PTR 0x85C4 /* Current write pointer (?) */ +#define Q_READ_PTR 0x85C8 /* Current read pointer (?) */ +#define Q_STATUS 0x85CC /* queue status */ + + +#define MMIO_IN8(base, offset) \ + *(volatile u8 *)(((u8*)(base)) + (offset)) +#define MMIO_IN16(base, offset) \ + *(volatile u16 *)(void *)(((u8*)(base)) + (offset)) +#define MMIO_IN32(base, offset) \ + *(volatile u32 *)(void *)(((u8*)(base)) + (offset)) +#define MMIO_OUT8(base, offset, val) \ + *(volatile u8 *)(((u8*)(base)) + (offset)) = (val) +#define MMIO_OUT16(base, offset, val) \ + *(volatile u16 *)(void *)(((u8*)(base)) + (offset)) = (val) +#define MMIO_OUT32(base, offset, val) \ + *(volatile u32 *)(void *)(((u8*)(base)) + (offset)) = (val) + + + +/* ------------- XGI 300 series -------------- */ + +/* Macros to do useful things with the XGI BitBLT engine */ + +/* BR(16) (0x8420): + + bit 31 2D engine: 1 is idle, + bit 30 3D engine: 1 is idle, + bit 29 Command queue: 1 is empty + + bits 28:24: Current CPU driven BitBlt buffer stage bit[4:0] + + bits 15:0: Current command queue length + +*/ + +/* TW: BR(16)+2 = 0x8242 */ + +int xgiCmdQueLen; + +#define XGI300Idle \ + { \ + while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \ + while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \ + while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \ + xgiCmdQueLen=MMIO_IN16(xgi_video_info.mmio_vbase, 0x8240); \ + } +/* TW: (do three times, because 2D engine seems quite unsure about whether or not it's idle) */ + +#define XGI300SetupSRCBase(base) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(0), base);\ + xgiCmdQueLen --; + +#define XGI300SetupSRCPitch(pitch) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT16(xgi_video_info.mmio_vbase, BR(1), pitch);\ + xgiCmdQueLen --; + +#define XGI300SetupSRCXY(x,y) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(2), (x)<<16 | (y) );\ + xgiCmdQueLen --; + +#define XGI300SetupDSTBase(base) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(4), base);\ + xgiCmdQueLen --; + +#define XGI300SetupDSTXY(x,y) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(3), (x)<<16 | (y) );\ + xgiCmdQueLen --; + +#define XGI300SetupDSTRect(x,y) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(5), (y)<<16 | (x) );\ + xgiCmdQueLen --; + +#define XGI300SetupDSTColorDepth(bpp) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT16(xgi_video_info.mmio_vbase, BR(1)+2, bpp);\ + xgiCmdQueLen --; + +#define XGI300SetupRect(w,h) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(6), (h)<<16 | (w) );\ + xgiCmdQueLen --; + +#define XGI300SetupPATFG(color) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(7), color);\ + xgiCmdQueLen --; + +#define XGI300SetupPATBG(color) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(8), color);\ + xgiCmdQueLen --; + +#define XGI300SetupSRCFG(color) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(9), color);\ + xgiCmdQueLen --; + +#define XGI300SetupSRCBG(color) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(10), color);\ + xgiCmdQueLen --; + +/* 0x8224 src colorkey high */ +/* 0x8228 src colorkey low */ +/* 0x821c dest colorkey high */ +/* 0x8220 dest colorkey low */ +#define XGI300SetupSRCTrans(color) \ + if (xgiCmdQueLen <= 1) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8224, color);\ + MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8228, color);\ + xgiCmdQueLen -= 2; + +#define XGI300SetupDSTTrans(color) \ + if (xgiCmdQueLen <= 1) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, 0x821C, color); \ + MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8220, color); \ + xgiCmdQueLen -= 2; + +#define XGI300SetupMONOPAT(p0,p1) \ + if (xgiCmdQueLen <= 1) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(11), p0);\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(12), p1);\ + xgiCmdQueLen -= 2; + +#define XGI300SetupClipLT(left,top) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\ + xgiCmdQueLen--; + +#define XGI300SetupClipRB(right,bottom) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\ + xgiCmdQueLen--; + +/* General */ +#define XGI300SetupROP(rop) \ + xgi_video_info.CommandReg = (rop) << 8; + +#define XGI300SetupCMDFlag(flags) \ + xgi_video_info.CommandReg |= (flags); + +#define XGI300DoCMD \ + if (xgiCmdQueLen <= 1) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(15), xgi_video_info.CommandReg); \ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(16), 0);\ + xgiCmdQueLen -= 2; + +/* Line */ +#define XGI300SetupX0Y0(x,y) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(2), (y)<<16 | (x) );\ + xgiCmdQueLen--; + +#define XGI300SetupX1Y1(x,y) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(3), (y)<<16 | (x) );\ + xgiCmdQueLen--; + +#define XGI300SetupLineCount(c) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT16(xgi_video_info.mmio_vbase, BR(6), c);\ + xgiCmdQueLen--; + +#define XGI300SetupStylePeriod(p) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT16(xgi_video_info.mmio_vbase, BR(6)+2, p);\ + xgiCmdQueLen--; + +#define XGI300SetupStyleLow(ls) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(11), ls);\ + xgiCmdQueLen--; + +#define XGI300SetupStyleHigh(ls) \ + if (xgiCmdQueLen <= 0) XGI300Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, BR(12), ls);\ + xgiCmdQueLen--; + + + +/* ----------- XGI 310/325 series --------------- */ + +/* Q_STATUS: + bit 31 = 1: All engines idle and all queues empty + bit 30 = 1: Hardware Queue (=HW CQ, 2D queue, 3D queue) empty + bit 29 = 1: 2D engine is idle + bit 28 = 1: 3D engine is idle + bit 27 = 1: HW command queue empty + bit 26 = 1: 2D queue empty + bit 25 = 1: 3D queue empty + bit 24 = 1: SW command queue empty + bits 23:16: 2D counter 3 + bits 15:8: 2D counter 2 + bits 7:0: 2D counter 1 + + Where is the command queue length (current amount of commands the queue + can accept) on the 310/325 series? (The current implementation is taken + from 300 series and certainly wrong...) +*/ + +/* TW: FIXME: xgiCmdQueLen is... where....? */ +#define XGI310Idle \ + { \ + while( (MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \ + while( (MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \ + xgiCmdQueLen=MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS); \ + } + +#define XGI310SetupSRCBase(base) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_ADDR, base);\ + xgiCmdQueLen--; + +#define XGI310SetupSRCPitch(pitch) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT16(xgi_video_info.mmio_vbase, SRC_PITCH, pitch);\ + xgiCmdQueLen--; + +#define XGI310SetupSRCXY(x,y) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_Y, (x)<<16 | (y) );\ + xgiCmdQueLen--; + +#define XGI310SetupDSTBase(base) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, DST_ADDR, base);\ + xgiCmdQueLen--; + +#define XGI310SetupDSTXY(x,y) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, DST_Y, (x)<<16 | (y) );\ + xgiCmdQueLen--; + +#define XGI310SetupDSTRect(x,y) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, DST_PITCH, (y)<<16 | (x) );\ + xgiCmdQueLen--; + +#define XGI310SetupDSTColorDepth(bpp) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT16(xgi_video_info.mmio_vbase, AGP_BASE, bpp);\ + xgiCmdQueLen--; + +#define XGI310SetupRect(w,h) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\ + xgiCmdQueLen--; + +#define XGI310SetupPATFG(color) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, PAT_FGCOLOR, color);\ + xgiCmdQueLen--; + +#define XGI310SetupPATBG(color) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, PAT_BGCOLOR, color);\ + xgiCmdQueLen--; + +#define XGI310SetupSRCFG(color) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_FGCOLOR, color);\ + xgiCmdQueLen--; + +#define XGI310SetupSRCBG(color) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_BGCOLOR, color);\ + xgiCmdQueLen--; + +#define XGI310SetupSRCTrans(color) \ + if (xgiCmdQueLen <= 1) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_SRC_KEY_HIGH, color);\ + MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_SRC_KEY_LOW, color);\ + xgiCmdQueLen -= 2; + +#define XGI310SetupDSTTrans(color) \ + if (xgiCmdQueLen <= 1) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_DST_KEY_HIGH, color); \ + MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_DST_KEY_LOW, color); \ + xgiCmdQueLen -= 2; + +#define XGI310SetupMONOPAT(p0,p1) \ + if (xgiCmdQueLen <= 1) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, MONO_MASK, p0);\ + MMIO_OUT32(xgi_video_info.mmio_vbase, MONO_MASK+4, p1);\ + xgiCmdQueLen -= 2; + +#define XGI310SetupClipLT(left,top) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\ + xgiCmdQueLen--; + +#define XGI310SetupClipRB(right,bottom) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\ + xgiCmdQueLen--; + +#define XGI310SetupROP(rop) \ + xgi_video_info.CommandReg = (rop) << 8; + +#define XGI310SetupCMDFlag(flags) \ + xgi_video_info.CommandReg |= (flags); + +#define XGI310DoCMD \ + if (xgiCmdQueLen <= 1) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, COMMAND_READY, xgi_video_info.CommandReg); \ + MMIO_OUT32(xgi_video_info.mmio_vbase, FIRE_TRIGGER, 0); \ + xgiCmdQueLen -= 2; + +#define XGI310SetupX0Y0(x,y) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_X0, (y)<<16 | (x) );\ + xgiCmdQueLen--; + +#define XGI310SetupX1Y1(x,y) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_X1, (y)<<16 | (x) );\ + xgiCmdQueLen--; + +#define XGI310SetupLineCount(c) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT16(xgi_video_info.mmio_vbase, LINE_COUNT, c);\ + xgiCmdQueLen--; + +#define XGI310SetupStylePeriod(p) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT16(xgi_video_info.mmio_vbase, LINE_STYLE_PERIOD, p);\ + xgiCmdQueLen--; + +#define XGI310SetupStyleLow(ls) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_STYLE_0, ls);\ + xgiCmdQueLen--; + +#define XGI310SetupStyleHigh(ls) \ + if (xgiCmdQueLen <= 0) XGI310Idle;\ + MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_STYLE_1, ls);\ + xgiCmdQueLen--; + +int XGIfb_initaccel(void); +void XGIfb_syncaccel(void); + +extern struct video_info xgi_video_info; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) +void fbcon_XGI_bmove(struct display *p, int srcy, int srcx, int dsty, + int dstx, int height, int width); +void fbcon_XGI_revc(struct display *p, int srcy, int srcx); +void fbcon_XGI_clear8(struct vc_data *conp, struct display *p, int srcy, + int srcx, int height, int width); +void fbcon_XGI_clear16(struct vc_data *conp, struct display *p, int srcy, + int srcx, int height, int width); +void fbcon_XGI_clear32(struct vc_data *conp, struct display *p, int srcy, + int srcx, int height, int width); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) +extern int XGIfb_accel; +void fbcon_XGI_fillrect(struct fb_info *info, const struct fb_fillrect *rect); +void fbcon_XGI_copyarea(struct fb_info *info, const struct fb_copyarea *area); +#endif + +#endif diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h new file mode 100644 index 000000000000..4f4171e8a68a --- /dev/null +++ b/drivers/staging/xgifb/XGI_main.h @@ -0,0 +1,1023 @@ +#ifndef _XGIFB_MAIN +#define _XGIFB_MAIN + + +/* ------------------- Constant Definitions ------------------------- */ + + +#include "XGIfb.h" +#include "vb_struct.h" +#include "vb_def.h" + +//#define LINUXBIOS /* turn this on when compiling for LINUXBIOS */ +#define AGPOFF /* default is turn off AGP */ + +#define XGIFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0) + +#define VER_MAJOR 0 +#define VER_MINOR 8 +#define VER_LEVEL 1 + +#define DRIVER_DESC "XGI Volari Frame Buffer Module Version 0.8.1" + +#ifndef PCI_VENDOR_ID_XG +#define PCI_VENDOR_ID_XG 0x18CA +#endif + +#ifndef PCI_DEVICE_ID_XG_40 +#define PCI_DEVICE_ID_XG_40 0x040 +#endif +#ifndef PCI_DEVICE_ID_XG_41 +#define PCI_DEVICE_ID_XG_41 0x041 +#endif +#ifndef PCI_DEVICE_ID_XG_42 +#define PCI_DEVICE_ID_XG_42 0x042 +#endif +#ifndef PCI_DEVICE_ID_XG_20 +#define PCI_DEVICE_ID_XG_20 0x020 +#endif +#ifndef PCI_DEVICE_ID_XG_27 +#define PCI_DEVICE_ID_XG_27 0x027 +#endif + + + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) +#define XGI_IOTYPE1 void __iomem +#define XGI_IOTYPE2 __iomem +#define XGIINITSTATIC static +#else +#define XGI_IOTYPE1 unsigned char +#define XGI_IOTYPE2 +#define XGIINITSTATIC +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +static struct pci_device_id __devinitdata xgifb_pci_table[] = { + + { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_27, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_40, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_XG, PCI_DEVICE_ID_XG_42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, xgifb_pci_table); +#endif +/* To be included in fb.h */ +#ifndef FB_ACCEL_XGI_GLAMOUR_2 +#define FB_ACCEL_XGI_GLAMOUR_2 40 /* XGI 315, 650, 740 */ +#endif +#ifndef FB_ACCEL_XGI_XABRE +#define FB_ACCEL_XGI_XABRE 41 /* XGI 330 ("Xabre") */ +#endif + +#define MAX_ROM_SCAN 0x10000 + +#define HW_CURSOR_CAP 0x80 +#define TURBO_QUEUE_CAP 0x40 +#define AGP_CMD_QUEUE_CAP 0x20 +#define VM_CMD_QUEUE_CAP 0x10 +#define MMIO_CMD_QUEUE_CAP 0x08 + + + +/* For 315 series */ + +#define COMMAND_QUEUE_AREA_SIZE 0x80000 /* 512K */ +#define COMMAND_QUEUE_THRESHOLD 0x1F + + +/* TW */ +#define HW_CURSOR_AREA_SIZE_315 0x4000 /* 16K */ +#define HW_CURSOR_AREA_SIZE_300 0x1000 /* 4K */ + +#define OH_ALLOC_SIZE 4000 +#define SENTINEL 0x7fffffff + +#define SEQ_ADR 0x14 +#define SEQ_DATA 0x15 +#define DAC_ADR 0x18 +#define DAC_DATA 0x19 +#define CRTC_ADR 0x24 +#define CRTC_DATA 0x25 +#define DAC2_ADR (0x16-0x30) +#define DAC2_DATA (0x17-0x30) +#define VB_PART1_ADR (0x04-0x30) +#define VB_PART1_DATA (0x05-0x30) +#define VB_PART2_ADR (0x10-0x30) +#define VB_PART2_DATA (0x11-0x30) +#define VB_PART3_ADR (0x12-0x30) +#define VB_PART3_DATA (0x13-0x30) +#define VB_PART4_ADR (0x14-0x30) +#define VB_PART4_DATA (0x15-0x30) + +#define XGISR XGI_Pr.P3c4 +#define XGICR XGI_Pr.P3d4 +#define XGIDACA XGI_Pr.P3c8 +#define XGIDACD XGI_Pr.P3c9 +#define XGIPART1 XGI_Pr.Part1Port +#define XGIPART2 XGI_Pr.Part2Port +#define XGIPART3 XGI_Pr.Part3Port +#define XGIPART4 XGI_Pr.Part4Port +#define XGIPART5 XGI_Pr.Part5Port +#define XGIDAC2A XGIPART5 +#define XGIDAC2D (XGIPART5 + 1) +#define XGIMISCR (XGI_Pr.RelIO + 0x1c) +#define XGIINPSTAT (XGI_Pr.RelIO + 0x2a) + +#define IND_XGI_PASSWORD 0x05 /* SRs */ +#define IND_XGI_COLOR_MODE 0x06 +#define IND_XGI_RAMDAC_CONTROL 0x07 +#define IND_XGI_DRAM_SIZE 0x14 +#define IND_XGI_SCRATCH_REG_16 0x16 +#define IND_XGI_SCRATCH_REG_17 0x17 +#define IND_XGI_SCRATCH_REG_1A 0x1A +#define IND_XGI_MODULE_ENABLE 0x1E +#define IND_XGI_PCI_ADDRESS_SET 0x20 +#define IND_XGI_TURBOQUEUE_ADR 0x26 +#define IND_XGI_TURBOQUEUE_SET 0x27 +#define IND_XGI_POWER_ON_TRAP 0x38 +#define IND_XGI_POWER_ON_TRAP2 0x39 +#define IND_XGI_CMDQUEUE_SET 0x26 +#define IND_XGI_CMDQUEUE_THRESHOLD 0x27 + +#define IND_XGI_SCRATCH_REG_CR30 0x30 /* CRs */ +#define IND_XGI_SCRATCH_REG_CR31 0x31 +#define IND_XGI_SCRATCH_REG_CR32 0x32 +#define IND_XGI_SCRATCH_REG_CR33 0x33 +#define IND_XGI_LCD_PANEL 0x36 +#define IND_XGI_SCRATCH_REG_CR37 0x37 +#define IND_XGI_AGP_IO_PAD 0x48 + +#define IND_BRI_DRAM_STATUS 0x63 /* PCI config memory size offset */ + +#define MMIO_QUEUE_PHYBASE 0x85C0 +#define MMIO_QUEUE_WRITEPORT 0x85C4 +#define MMIO_QUEUE_READPORT 0x85C8 + +#define IND_XGI_CRT2_WRITE_ENABLE_300 0x24 +#define IND_XGI_CRT2_WRITE_ENABLE_315 0x2F + +#define XGI_PASSWORD 0x86 /* SR05 */ +#define XGI_INTERLACED_MODE 0x20 /* SR06 */ +#define XGI_8BPP_COLOR_MODE 0x0 +#define XGI_15BPP_COLOR_MODE 0x1 +#define XGI_16BPP_COLOR_MODE 0x2 +#define XGI_32BPP_COLOR_MODE 0x4 + +#define XGI_DRAM_SIZE_MASK 0xF0 /*SR14 */ +#define XGI_DRAM_SIZE_1MB 0x00 +#define XGI_DRAM_SIZE_2MB 0x01 +#define XGI_DRAM_SIZE_4MB 0x02 +#define XGI_DRAM_SIZE_8MB 0x03 +#define XGI_DRAM_SIZE_16MB 0x04 +#define XGI_DRAM_SIZE_32MB 0x05 +#define XGI_DRAM_SIZE_64MB 0x06 +#define XGI_DRAM_SIZE_128MB 0x07 +#define XGI_DRAM_SIZE_256MB 0x08 +#define XGI_DATA_BUS_MASK 0x02 +#define XGI_DATA_BUS_64 0x00 +#define XGI_DATA_BUS_128 0x01 +#define XGI_DUAL_CHANNEL_MASK 0x0C +#define XGI_SINGLE_CHANNEL_1_RANK 0x0 +#define XGI_SINGLE_CHANNEL_2_RANK 0x1 +#define XGI_ASYM_DDR 0x02 +#define XGI_DUAL_CHANNEL_1_RANK 0x3 + +#define XGI550_DRAM_SIZE_MASK 0x3F /* 550/650/740 SR14 */ +#define XGI550_DRAM_SIZE_4MB 0x00 +#define XGI550_DRAM_SIZE_8MB 0x01 +#define XGI550_DRAM_SIZE_16MB 0x03 +#define XGI550_DRAM_SIZE_24MB 0x05 +#define XGI550_DRAM_SIZE_32MB 0x07 +#define XGI550_DRAM_SIZE_64MB 0x0F +#define XGI550_DRAM_SIZE_96MB 0x17 +#define XGI550_DRAM_SIZE_128MB 0x1F +#define XGI550_DRAM_SIZE_256MB 0x3F + +#define XGI_SCRATCH_REG_1A_MASK 0x10 + +#define XGI_ENABLE_2D 0x40 /* SR1E */ + +#define XGI_MEM_MAP_IO_ENABLE 0x01 /* SR20 */ +#define XGI_PCI_ADDR_ENABLE 0x80 + +#define XGI_AGP_CMDQUEUE_ENABLE 0x80 /* 315/650/740 SR26 */ +#define XGI_VRAM_CMDQUEUE_ENABLE 0x40 +#define XGI_MMIO_CMD_ENABLE 0x20 +#define XGI_CMD_QUEUE_SIZE_512k 0x00 +#define XGI_CMD_QUEUE_SIZE_1M 0x04 +#define XGI_CMD_QUEUE_SIZE_2M 0x08 +#define XGI_CMD_QUEUE_SIZE_4M 0x0C +#define XGI_CMD_QUEUE_RESET 0x01 +#define XGI_CMD_AUTO_CORR 0x02 + +#define XGI_SIMULTANEOUS_VIEW_ENABLE 0x01 /* CR30 */ +#define XGI_MODE_SELECT_CRT2 0x02 +#define XGI_VB_OUTPUT_COMPOSITE 0x04 +#define XGI_VB_OUTPUT_SVIDEO 0x08 +#define XGI_VB_OUTPUT_SCART 0x10 +#define XGI_VB_OUTPUT_LCD 0x20 +#define XGI_VB_OUTPUT_CRT2 0x40 +#define XGI_VB_OUTPUT_HIVISION 0x80 + +#define XGI_VB_OUTPUT_DISABLE 0x20 /* CR31 */ +#define XGI_DRIVER_MODE 0x40 + +#define XGI_VB_COMPOSITE 0x01 /* CR32 */ +#define XGI_VB_SVIDEO 0x02 +#define XGI_VB_SCART 0x04 +#define XGI_VB_LCD 0x08 +#define XGI_VB_CRT2 0x10 +#define XGI_CRT1 0x20 +#define XGI_VB_HIVISION 0x40 +#define XGI_VB_YPBPR 0x80 +#define XGI_VB_TV (XGI_VB_COMPOSITE | XGI_VB_SVIDEO | \ + XGI_VB_SCART | XGI_VB_HIVISION|XGI_VB_YPBPR) + +#define XGI_EXTERNAL_CHIP_MASK 0x0E /* CR37 */ +#define XGI_EXTERNAL_CHIP_XGI301 0x01 /* in CR37 << 1 ! */ +#define XGI_EXTERNAL_CHIP_LVDS 0x02 /* in CR37 << 1 ! */ +#define XGI_EXTERNAL_CHIP_TRUMPION 0x03 /* in CR37 << 1 ! */ +#define XGI_EXTERNAL_CHIP_LVDS_CHRONTEL 0x04 /* in CR37 << 1 ! */ +#define XGI_EXTERNAL_CHIP_CHRONTEL 0x05 /* in CR37 << 1 ! */ +#define XGI310_EXTERNAL_CHIP_LVDS 0x02 /* in CR37 << 1 ! */ +#define XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03 /* in CR37 << 1 ! */ + +#define XGI_AGP_2X 0x20 /* CR48 */ + +#define BRI_DRAM_SIZE_MASK 0x70 /* PCI bridge config data */ +#define BRI_DRAM_SIZE_2MB 0x00 +#define BRI_DRAM_SIZE_4MB 0x01 +#define BRI_DRAM_SIZE_8MB 0x02 +#define BRI_DRAM_SIZE_16MB 0x03 +#define BRI_DRAM_SIZE_32MB 0x04 +#define BRI_DRAM_SIZE_64MB 0x05 + +#define HW_DEVICE_EXTENSION XGI_HW_DEVICE_INFO +#define PHW_DEVICE_EXTENSION PXGI_HW_DEVICE_INFO + +#define SR_BUFFER_SIZE 5 +#define CR_BUFFER_SIZE 5 + +/* Useful macros */ +#define inXGIREG(base) inb(base) +#define outXGIREG(base,val) outb(val,base) +#define orXGIREG(base,val) do { \ + unsigned char __Temp = inb(base); \ + outXGIREG(base, __Temp | (val)); \ + } while (0) +#define andXGIREG(base,val) do { \ + unsigned char __Temp = inb(base); \ + outXGIREG(base, __Temp & (val)); \ + } while (0) +#define inXGIIDXREG(base,idx,var) do { \ + outb(idx,base); var=inb((base)+1); \ + } while (0) +#define outXGIIDXREG(base,idx,val) do { \ + outb(idx,base); outb((val),(base)+1); \ + } while (0) +#define orXGIIDXREG(base,idx,val) do { \ + unsigned char __Temp; \ + outb(idx,base); \ + __Temp = inb((base)+1)|(val); \ + outXGIIDXREG(base,idx,__Temp); \ + } while (0) +#define andXGIIDXREG(base,idx,and) do { \ + unsigned char __Temp; \ + outb(idx,base); \ + __Temp = inb((base)+1)&(and); \ + outXGIIDXREG(base,idx,__Temp); \ + } while (0) +#define setXGIIDXREG(base,idx,and,or) do { \ + unsigned char __Temp; \ + outb(idx,base); \ + __Temp = (inb((base)+1)&(and))|(or); \ + outXGIIDXREG(base,idx,__Temp); \ + } while (0) + +/* ------------------- Global Variables ----------------------------- */ + +/* Fbcon variables */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +static struct fb_info* fb_info; +#else +static struct fb_info XGI_fb_info; +#endif + + +static int video_type = FB_TYPE_PACKED_PIXELS; + +static struct fb_var_screeninfo default_var = { + .xres = 0, + .yres = 0, + .xres_virtual = 0, + .yres_virtual = 0, + .xoffset = 0, + .yoffset = 0, + .bits_per_pixel = 0, + .grayscale = 0, + .red = {0, 8, 0}, + .green = {0, 8, 0}, + .blue = {0, 8, 0}, + .transp = {0, 0, 0}, + .nonstd = 0, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .accel_flags = 0, + .pixclock = 0, + .left_margin = 0, + .right_margin = 0, + .upper_margin = 0, + .lower_margin = 0, + .hsync_len = 0, + .vsync_len = 0, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + .reserved = {0, 0, 0, 0, 0, 0} +#endif +}; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +static struct fb_fix_screeninfo XGIfb_fix = { + .id = "XGI", + .type = FB_TYPE_PACKED_PIXELS, + .xpanstep = 1, + .ypanstep = 1, +}; +static char myid[20]; +static u32 pseudo_palette[17]; +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +static struct display XGI_disp; + +static struct display_switch XGIfb_sw; + +static struct { + u16 blue, green, red, pad; +} XGI_palette[256]; + +static union { +#ifdef FBCON_HAS_CFB16 + u16 cfb16[16]; +#endif +#ifdef FBCON_HAS_CFB32 + u32 cfb32[16]; +#endif +} XGI_fbcon_cmap; + +static int XGIfb_inverse = 0; +#endif + +/* display status */ +static int XGIfb_off = 0; +static int XGIfb_crt1off = 0; +static int XGIfb_forcecrt1 = -1; +static int XGIvga_enabled = 0; +static int XGIfb_userom = 0; +//static int XGIfb_useoem = -1; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +static int currcon = 0; +#endif + +/* global flags */ +static int XGIfb_registered; +static int XGIfb_tvmode = 0; +static int XGIfb_mem = 0; +static int XGIfb_pdc = 0; +static int enable_dstn = 0; +static int XGIfb_ypan = -1; + + +int XGIfb_accel = 0; + + +static int XGIfb_hwcursor_size = 0; +static int XGIfb_CRT2_write_enable = 0; + +int XGIfb_crt2type = -1; /* TW: CRT2 type (for overriding autodetection) */ +int XGIfb_tvplug = -1; /* PR: Tv plug type (for overriding autodetection) */ + +int XGIfb_queuemode = -1; /* TW: Use MMIO queue mode by default (310/325 series only) */ + +unsigned char XGIfb_detectedpdc = 0; + +unsigned char XGIfb_detectedlcda = 0xff; + + + + +/* TW: For ioctl XGIFB_GET_INFO */ +/* XGIfb_info XGIfbinfo; */ + +/* TW: Hardware extension; contains data on hardware */ +HW_DEVICE_EXTENSION XGIhw_ext; + +/* TW: XGI private structure */ +VB_DEVICE_INFO XGI_Pr; + +/* card parameters */ +static unsigned long XGIfb_mmio_size = 0; +static u8 XGIfb_caps = 0; + +typedef enum _XGI_CMDTYPE { + MMIO_CMD = 0, + AGP_CMD_QUEUE, + VM_CMD_QUEUE, +} XGI_CMDTYPE; + +#define MD_XGI300 1 +#define MD_XGI315 2 + +/* mode table */ +/* NOT const - will be patched for 1280x960 mode number chaos reasons */ +struct _XGIbios_mode { + char name[15]; + u8 mode_no; + u16 vesa_mode_no_1; /* "XGI defined" VESA mode number */ + u16 vesa_mode_no_2; /* Real VESA mode numbers */ + u16 xres; + u16 yres; + u16 bpp; + u16 rate_idx; + u16 cols; + u16 rows; + u8 chipset; +} XGIbios_mode[] = { +#define MODE_INDEX_NONE 0 /* TW: index for mode=none */ + {"none", 0xFF, 0x0000, 0x0000, 0, 0, 0, 0, 0, 0, MD_XGI300|MD_XGI315}, /* TW: for mode "none" */ + {"320x240x16", 0x56, 0x0000, 0x0000, 320, 240, 16, 1, 40, 15, MD_XGI315}, + {"320x480x8", 0x5A, 0x0000, 0x0000, 320, 480, 8, 1, 40, 30, MD_XGI315}, /* TW: FSTN */ + {"320x480x16", 0x5B, 0x0000, 0x0000, 320, 480, 16, 1, 40, 30, MD_XGI315}, /* TW: FSTN */ + {"640x480x8", 0x2E, 0x0101, 0x0101, 640, 480, 8, 1, 80, 30, MD_XGI300|MD_XGI315}, + {"640x480x16", 0x44, 0x0111, 0x0111, 640, 480, 16, 1, 80, 30, MD_XGI300|MD_XGI315}, + {"640x480x24", 0x62, 0x013a, 0x0112, 640, 480, 32, 1, 80, 30, MD_XGI300|MD_XGI315}, /* TW: That's for people who mix up color- and fb depth */ + {"640x480x32", 0x62, 0x013a, 0x0112, 640, 480, 32, 1, 80, 30, MD_XGI300|MD_XGI315}, + {"720x480x8", 0x31, 0x0000, 0x0000, 720, 480, 8, 1, 90, 30, MD_XGI300|MD_XGI315}, + {"720x480x16", 0x33, 0x0000, 0x0000, 720, 480, 16, 1, 90, 30, MD_XGI300|MD_XGI315}, + {"720x480x24", 0x35, 0x0000, 0x0000, 720, 480, 32, 1, 90, 30, MD_XGI300|MD_XGI315}, + {"720x480x32", 0x35, 0x0000, 0x0000, 720, 480, 32, 1, 90, 30, MD_XGI300|MD_XGI315}, + {"720x576x8", 0x32, 0x0000, 0x0000, 720, 576, 8, 1, 90, 36, MD_XGI300|MD_XGI315}, + {"720x576x16", 0x34, 0x0000, 0x0000, 720, 576, 16, 1, 90, 36, MD_XGI300|MD_XGI315}, + {"720x576x24", 0x36, 0x0000, 0x0000, 720, 576, 32, 1, 90, 36, MD_XGI300|MD_XGI315}, + {"720x576x32", 0x36, 0x0000, 0x0000, 720, 576, 32, 1, 90, 36, MD_XGI300|MD_XGI315}, + {"800x480x8", 0x70, 0x0000, 0x0000, 800, 480, 8, 1, 100, 30, MD_XGI300|MD_XGI315}, + {"800x480x16", 0x7a, 0x0000, 0x0000, 800, 480, 16, 1, 100, 30, MD_XGI300|MD_XGI315}, + {"800x480x24", 0x76, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_XGI300|MD_XGI315}, + {"800x480x32", 0x76, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_XGI300|MD_XGI315}, +#define DEFAULT_MODE 21 /* TW: index for 800x600x8 */ +#define DEFAULT_LCDMODE 21 /* TW: index for 800x600x8 */ +#define DEFAULT_TVMODE 21 /* TW: index for 800x600x8 */ + {"800x600x8", 0x30, 0x0103, 0x0103, 800, 600, 8, 1, 100, 37, MD_XGI300|MD_XGI315}, + {"800x600x16", 0x47, 0x0114, 0x0114, 800, 600, 16, 1, 100, 37, MD_XGI300|MD_XGI315}, + {"800x600x24", 0x63, 0x013b, 0x0115, 800, 600, 32, 1, 100, 37, MD_XGI300|MD_XGI315}, + {"800x600x32", 0x63, 0x013b, 0x0115, 800, 600, 32, 1, 100, 37, MD_XGI300|MD_XGI315}, + {"1024x576x8", 0x71, 0x0000, 0x0000, 1024, 576, 8, 1, 128, 36, MD_XGI300|MD_XGI315}, + {"1024x576x16", 0x74, 0x0000, 0x0000, 1024, 576, 16, 1, 128, 36, MD_XGI300|MD_XGI315}, + {"1024x576x24", 0x77, 0x0000, 0x0000, 1024, 576, 32, 1, 128, 36, MD_XGI300|MD_XGI315}, + {"1024x576x32", 0x77, 0x0000, 0x0000, 1024, 576, 32, 1, 128, 36, MD_XGI300|MD_XGI315}, + {"1024x600x8", 0x20, 0x0000, 0x0000, 1024, 600, 8, 1, 128, 37, MD_XGI300 }, /* TW: 300 series only */ + {"1024x600x16", 0x21, 0x0000, 0x0000, 1024, 600, 16, 1, 128, 37, MD_XGI300 }, + {"1024x600x24", 0x22, 0x0000, 0x0000, 1024, 600, 32, 1, 128, 37, MD_XGI300 }, + {"1024x600x32", 0x22, 0x0000, 0x0000, 1024, 600, 32, 1, 128, 37, MD_XGI300 }, + {"1024x768x8", 0x38, 0x0105, 0x0105, 1024, 768, 8, 1, 128, 48, MD_XGI300|MD_XGI315}, + {"1024x768x16", 0x4A, 0x0117, 0x0117, 1024, 768, 16, 1, 128, 48, MD_XGI300|MD_XGI315}, + {"1024x768x24", 0x64, 0x013c, 0x0118, 1024, 768, 32, 1, 128, 48, MD_XGI300|MD_XGI315}, + {"1024x768x32", 0x64, 0x013c, 0x0118, 1024, 768, 32, 1, 128, 48, MD_XGI300|MD_XGI315}, + {"1152x768x8", 0x23, 0x0000, 0x0000, 1152, 768, 8, 1, 144, 48, MD_XGI300 }, /* TW: 300 series only */ + {"1152x768x16", 0x24, 0x0000, 0x0000, 1152, 768, 16, 1, 144, 48, MD_XGI300 }, + {"1152x768x24", 0x25, 0x0000, 0x0000, 1152, 768, 32, 1, 144, 48, MD_XGI300 }, + {"1152x768x32", 0x25, 0x0000, 0x0000, 1152, 768, 32, 1, 144, 48, MD_XGI300 }, + {"1280x720x8", 0x79, 0x0000, 0x0000, 1280, 720, 8, 1, 160, 45, MD_XGI300|MD_XGI315}, + {"1280x720x16", 0x75, 0x0000, 0x0000, 1280, 720, 16, 1, 160, 45, MD_XGI300|MD_XGI315}, + {"1280x720x24", 0x78, 0x0000, 0x0000, 1280, 720, 32, 1, 160, 45, MD_XGI300|MD_XGI315}, + {"1280x720x32", 0x78, 0x0000, 0x0000, 1280, 720, 32, 1, 160, 45, MD_XGI300|MD_XGI315}, + {"1280x768x8", 0x23, 0x0000, 0x0000, 1280, 768, 8, 1, 160, 48, MD_XGI315}, /* TW: 310/325 series only */ + {"1280x768x16", 0x24, 0x0000, 0x0000, 1280, 768, 16, 1, 160, 48, MD_XGI315}, + {"1280x768x24", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48, MD_XGI315}, + {"1280x768x32", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48, MD_XGI315}, +#define MODEINDEX_1280x960 48 + {"1280x960x8", 0x7C, 0x0000, 0x0000, 1280, 960, 8, 1, 160, 60, MD_XGI300|MD_XGI315}, /* TW: Modenumbers being patched */ + {"1280x960x16", 0x7D, 0x0000, 0x0000, 1280, 960, 16, 1, 160, 60, MD_XGI300|MD_XGI315}, + {"1280x960x24", 0x7E, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_XGI300|MD_XGI315}, + {"1280x960x32", 0x7E, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_XGI300|MD_XGI315}, + {"1280x1024x8", 0x3A, 0x0107, 0x0107, 1280, 1024, 8, 1, 160, 64, MD_XGI300|MD_XGI315}, + {"1280x1024x16", 0x4D, 0x011a, 0x011a, 1280, 1024, 16, 1, 160, 64, MD_XGI300|MD_XGI315}, + {"1280x1024x24", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 1, 160, 64, MD_XGI300|MD_XGI315}, + {"1280x1024x32", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 1, 160, 64, MD_XGI300|MD_XGI315}, + {"1400x1050x8", 0x26, 0x0000, 0x0000, 1400, 1050, 8, 1, 175, 65, MD_XGI315}, /* TW: 310/325 series only */ + {"1400x1050x16", 0x27, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65, MD_XGI315}, + {"1400x1050x24", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_XGI315}, + {"1400x1050x32", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_XGI315}, + {"1600x1200x8", 0x3C, 0x0130, 0x011c, 1600, 1200, 8, 1, 200, 75, MD_XGI300|MD_XGI315}, + {"1600x1200x16", 0x3D, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_XGI300|MD_XGI315}, + {"1600x1200x24", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_XGI300|MD_XGI315}, + {"1600x1200x32", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_XGI300|MD_XGI315}, + {"1920x1440x8", 0x68, 0x013f, 0x0000, 1920, 1440, 8, 1, 240, 75, MD_XGI300|MD_XGI315}, + {"1920x1440x16", 0x69, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_XGI300|MD_XGI315}, + {"1920x1440x24", 0x6B, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_XGI300|MD_XGI315}, + {"1920x1440x32", 0x6B, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_XGI300|MD_XGI315}, + {"2048x1536x8", 0x6c, 0x0000, 0x0000, 2048, 1536, 8, 1, 256, 96, MD_XGI315}, /* TW: 310/325 series only */ + {"2048x1536x16", 0x6d, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96, MD_XGI315}, + {"2048x1536x24", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96, MD_XGI315}, + {"2048x1536x32", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96, MD_XGI315}, + {"\0", 0x00, 0, 0, 0, 0, 0, 0, 0} +}; + +/* mode-related variables */ +#ifdef MODULE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +static int xgifb_mode_idx = 1; +#else +static int XGIfb_mode_idx = MODE_INDEX_NONE; /* Don't use a mode by default if we are a module */ +#endif +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +static int xgifb_mode_idx = -1; /* Use a default mode if we are inside the kernel */ +#else +static int XGIfb_mode_idx = -1; +#endif +#endif +u8 XGIfb_mode_no = 0; +u8 XGIfb_rate_idx = 0; + +/* TW: CR36 evaluation */ +const USHORT XGI300paneltype[] = + { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024, + LCD_1280x960, LCD_640x480, LCD_1024x600, LCD_1152x768, + LCD_1024x768, LCD_1024x768, LCD_1024x768, + LCD_1024x768, LCD_1024x768, LCD_1024x768, LCD_1024x768 }; + +const USHORT XGI310paneltype[] = + { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024, + LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960, + LCD_1152x768, LCD_1400x1050,LCD_1280x768, LCD_1600x1200, + LCD_1024x768, LCD_1024x768, LCD_1024x768 }; + +static const struct _XGI_crt2type { + char name[10]; + int type_no; + int tvplug_no; +} XGI_crt2type[] = { + {"NONE", 0, -1}, + {"LCD", DISPTYPE_LCD, -1}, + {"TV", DISPTYPE_TV, -1}, + {"VGA", DISPTYPE_CRT2, -1}, + {"SVIDEO", DISPTYPE_TV, TVPLUG_SVIDEO}, + {"COMPOSITE", DISPTYPE_TV, TVPLUG_COMPOSITE}, + {"SCART", DISPTYPE_TV, TVPLUG_SCART}, + {"none", 0, -1}, + {"lcd", DISPTYPE_LCD, -1}, + {"tv", DISPTYPE_TV, -1}, + {"vga", DISPTYPE_CRT2, -1}, + {"svideo", DISPTYPE_TV, TVPLUG_SVIDEO}, + {"composite", DISPTYPE_TV, TVPLUG_COMPOSITE}, + {"scart", DISPTYPE_TV, TVPLUG_SCART}, + {"\0", -1, -1} +}; + +/* Queue mode selection for 310 series */ +static const struct _XGI_queuemode { + char name[6]; + int type_no; +} XGI_queuemode[] = { + {"AGP", AGP_CMD_QUEUE}, + {"VRAM", VM_CMD_QUEUE}, + {"MMIO", MMIO_CMD}, + {"agp", AGP_CMD_QUEUE}, + {"vram", VM_CMD_QUEUE}, + {"mmio", MMIO_CMD}, + {"\0", -1} +}; + +/* TV standard */ +static const struct _XGI_tvtype { + char name[6]; + int type_no; +} XGI_tvtype[] = { + {"PAL", 1}, + {"NTSC", 2}, + {"pal", 1}, + {"ntsc", 2}, + {"\0", -1} +}; + +static const struct _XGI_vrate { + u16 idx; + u16 xres; + u16 yres; + u16 refresh; +} XGIfb_vrate[] = { + {1, 640, 480, 60}, {2, 640, 480, 72}, {3, 640, 480, 75}, {4, 640, 480, 85}, + {5, 640, 480,100}, {6, 640, 480, 120}, {7, 640, 480, 160}, {8, 640, 480, 200}, + {1, 720, 480, 60}, + {1, 720, 576, 58}, + {1, 800, 480, 60}, {2, 800, 480, 75}, {3, 800, 480, 85}, + {1, 800, 600, 60}, {2, 800, 600, 72}, {3, 800, 600, 75}, + {4, 800, 600, 85}, {5, 800, 600, 100}, {6, 800, 600, 120}, {7, 800, 600, 160}, + {1, 1024, 768, 60}, {2, 1024, 768, 70}, {3, 1024, 768, 75}, + {4, 1024, 768, 85}, {5, 1024, 768, 100}, {6, 1024, 768, 120}, + {1, 1024, 576, 60}, {2, 1024, 576, 75}, {3, 1024, 576, 85}, + {1, 1024, 600, 60}, + {1, 1152, 768, 60}, + {1, 1280, 720, 60}, {2, 1280, 720, 75}, {3, 1280, 720, 85}, + {1, 1280, 768, 60}, + {1, 1280, 1024, 60}, {2, 1280, 1024, 75}, {3, 1280, 1024, 85}, + {1, 1280, 960, 70}, + {1, 1400, 1050, 60}, + {1, 1600, 1200, 60}, {2, 1600, 1200, 65}, {3, 1600, 1200, 70}, {4, 1600, 1200, 75}, + {5, 1600, 1200, 85}, {6, 1600, 1200, 100}, {7, 1600, 1200, 120}, + {1, 1920, 1440, 60}, {2, 1920, 1440, 65}, {3, 1920, 1440, 70}, {4, 1920, 1440, 75}, + {5, 1920, 1440, 85}, {6, 1920, 1440, 100}, + {1, 2048, 1536, 60}, {2, 2048, 1536, 65}, {3, 2048, 1536, 70}, {4, 2048, 1536, 75}, + {5, 2048, 1536, 85}, + {0, 0, 0, 0} +}; + +static const struct _chswtable { + int subsysVendor; + int subsysCard; + char *vendorName; + char *cardName; +} mychswtable[] = { + { 0x1631, 0x1002, "Mitachi", "0x1002" }, + { 0, 0, "" , "" } +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +/* Offscreen layout */ +typedef struct _XGI_GLYINFO { + unsigned char ch; + int fontwidth; + int fontheight; + u8 gmask[72]; + int ngmask; +} XGI_GLYINFO; +#endif + +typedef struct _XGI_OH { + struct _XGI_OH *poh_next; + struct _XGI_OH *poh_prev; + unsigned long offset; + unsigned long size; +} XGI_OH; + +typedef struct _XGI_OHALLOC { + struct _XGI_OHALLOC *poha_next; + XGI_OH aoh[1]; +} XGI_OHALLOC; + +typedef struct _XGI_HEAP { + XGI_OH oh_free; + XGI_OH oh_used; + XGI_OH *poh_freelist; + XGI_OHALLOC *poha_chain; + unsigned long max_freesize; +} XGI_HEAP; + +static unsigned long XGIfb_hwcursor_vbase; + +static unsigned long XGIfb_heap_start; +static unsigned long XGIfb_heap_end; +static unsigned long XGIfb_heap_size; +static XGI_HEAP XGIfb_heap; + +// Eden Chen +static const struct _XGI_TV_filter { + u8 filter[9][4]; +} XGI_TV_filter[] = { + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_0 */ + {0x00,0xE0,0x10,0x60}, + {0x00,0xEE,0x10,0x44}, + {0x00,0xF4,0x10,0x38}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0x00,0x00,0x10,0x20}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_1 */ + {0x00,0xE0,0x10,0x60}, + {0x00,0xEE,0x10,0x44}, + {0x00,0xF4,0x10,0x38}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0x00,0x00,0x10,0x20}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_2 */ + {0xF5,0xEE,0x1B,0x44}, + {0xF8,0xF4,0x18,0x38}, + {0xEB,0x04,0x25,0x18}, + {0xF1,0x05,0x1F,0x16}, + {0xF6,0x06,0x1A,0x14}, + {0xFA,0x06,0x16,0x14}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_3 */ + {0xF1,0x04,0x1F,0x18}, + {0xEE,0x0D,0x22,0x06}, + {0xF7,0x06,0x19,0x14}, + {0xF4,0x0B,0x1C,0x0A}, + {0xFA,0x07,0x16,0x12}, + {0xF9,0x0A,0x17,0x0C}, + {0x00,0x07,0x10,0x12}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_4 */ + {0x00,0xE0,0x10,0x60}, + {0x00,0xEE,0x10,0x44}, + {0x00,0xF4,0x10,0x38}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0x00,0x00,0x10,0x20}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_5 */ + {0xF5,0xEE,0x1B,0x44}, + {0xF8,0xF4,0x18,0x38}, + {0xEB,0x04,0x25,0x18}, + {0xF1,0x05,0x1F,0x16}, + {0xF6,0x06,0x1A,0x14}, + {0xFA,0x06,0x16,0x14}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_6 */ + {0xEB,0x04,0x25,0x18}, + {0xE7,0x0E,0x29,0x04}, + {0xEE,0x0C,0x22,0x08}, + {0xF6,0x0B,0x1A,0x0A}, + {0xF9,0x0A,0x17,0x0C}, + {0xFC,0x0A,0x14,0x0C}, + {0x00,0x08,0x10,0x10}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* NTSCFilter_7 */ + {0xEC,0x02,0x24,0x1C}, + {0xF2,0x04,0x1E,0x18}, + {0xEB,0x15,0x25,0xF6}, + {0xF4,0x10,0x1C,0x00}, + {0xF8,0x0F,0x18,0x02}, + {0x00,0x04,0x10,0x18}, + {0x01,0x06,0x0F,0x14}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_0 */ + {0x00,0xE0,0x10,0x60}, + {0x00,0xEE,0x10,0x44}, + {0x00,0xF4,0x10,0x38}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0x00,0x00,0x10,0x20}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_1 */ + {0x00,0xE0,0x10,0x60}, + {0x00,0xEE,0x10,0x44}, + {0x00,0xF4,0x10,0x38}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0x00,0x00,0x10,0x20}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_2 */ + {0xF5,0xEE,0x1B,0x44}, + {0xF8,0xF4,0x18,0x38}, + {0xF1,0xF7,0x01,0x32}, + {0xF5,0xFB,0x1B,0x2A}, + {0xF9,0xFF,0x17,0x22}, + {0xFB,0x01,0x15,0x1E}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_3 */ + {0xF5,0xFB,0x1B,0x2A}, + {0xEE,0xFE,0x22,0x24}, + {0xF3,0x00,0x1D,0x20}, + {0xF9,0x03,0x17,0x1A}, + {0xFB,0x02,0x14,0x1E}, + {0xFB,0x04,0x15,0x18}, + {0x00,0x06,0x10,0x14}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_4 */ + {0x00,0xE0,0x10,0x60}, + {0x00,0xEE,0x10,0x44}, + {0x00,0xF4,0x10,0x38}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0x00,0x00,0x10,0x20}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_5 */ + {0xF5,0xEE,0x1B,0x44}, + {0xF8,0xF4,0x18,0x38}, + {0xF1,0xF7,0x1F,0x32}, + {0xF5,0xFB,0x1B,0x2A}, + {0xF9,0xFF,0x17,0x22}, + {0xFB,0x01,0x15,0x1E}, + {0x00,0x04,0x10,0x18}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_6 */ + {0xF5,0xEE,0x1B,0x2A}, + {0xEE,0xFE,0x22,0x24}, + {0xF3,0x00,0x1D,0x20}, + {0xF9,0x03,0x17,0x1A}, + {0xFB,0x02,0x14,0x1E}, + {0xFB,0x04,0x15,0x18}, + {0x00,0x06,0x10,0x14}, + {0xFF,0xFF,0xFF,0xFF} }}, + { {{0x00,0x00,0x00,0x40}, /* PALFilter_7 */ + {0xF5,0xEE,0x1B,0x44}, + {0xF8,0xF4,0x18,0x38}, + {0xFC,0xFB,0x14,0x2A}, + {0xEB,0x05,0x25,0x16}, + {0xF1,0x05,0x1F,0x16}, + {0xFA,0x07,0x16,0x12}, + {0x00,0x07,0x10,0x12}, + {0xFF,0xFF,0xFF,0xFF} }} +}; + +static int filter = -1; +static unsigned char filter_tb; + + +/* ---------------------- Routine prototypes ------------------------- */ + +/* Interface used by the world */ +#ifndef MODULE +XGIINITSTATIC int __init XGIfb_setup(char *options); +#endif + +/* Interface to the low level console driver */ + + + +/* fbdev routines */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + int XGIfb_init(void); +static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, + int con, + struct fb_info *info); +static int XGIfb_get_var(struct fb_var_screeninfo *var, + int con, + struct fb_info *info); +static int XGIfb_set_var(struct fb_var_screeninfo *var, + int con, + struct fb_info *info); +static void XGIfb_crtc_to_var(struct fb_var_screeninfo *var); +static int XGIfb_get_cmap(struct fb_cmap *cmap, + int kspc, + int con, + struct fb_info *info); +static int XGIfb_set_cmap(struct fb_cmap *cmap, + int kspc, + int con, + struct fb_info *info); +static int XGIfb_update_var(int con, + struct fb_info *info); +static int XGIfb_switch(int con, + struct fb_info *info); +static void XGIfb_blank(int blank, + struct fb_info *info); +static void XGIfb_set_disp(int con, + struct fb_var_screeninfo *var, + struct fb_info *info); +static int XGI_getcolreg(unsigned regno, unsigned *red, unsigned *green, + unsigned *blue, unsigned *transp, + struct fb_info *fb_info); +static void XGIfb_do_install_cmap(int con, + struct fb_info *info); +static void XGI_get_glyph(struct fb_info *info, + XGI_GLYINFO *gly); +static int XGIfb_mmap(struct fb_info *info, struct file *file, + struct vm_area_struct *vma); +static int XGIfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +XGIINITSTATIC int __init xgifb_init(void); +static int XGIfb_set_par(struct fb_info *info); +static int XGIfb_blank(int blank, + struct fb_info *info); +/*static int XGIfb_mmap(struct fb_info *info, struct file *file, + struct vm_area_struct *vma); +*/ +extern void fbcon_XGI_fillrect(struct fb_info *info, + const struct fb_fillrect *rect); +extern void fbcon_XGI_copyarea(struct fb_info *info, + const struct fb_copyarea *area); +#if 0 +extern void cfb_imageblit(struct fb_info *info, + const struct fb_image *image); +#endif +extern int fbcon_XGI_sync(struct fb_info *info); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) +static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg); +#else +static int XGIfb_ioctl(struct inode *inode, + struct file *file, + unsigned int cmd, + unsigned long arg, + struct fb_info *info); +#endif + +/* +extern int XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, + PXGI_HW_DEVICE_INFO HwDeviceExtension, + unsigned char modeno, unsigned char rateindex); +extern int XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension, + unsigned char modeno, unsigned char rateindex, + unsigned int *left_margin, unsigned int *right_margin, + unsigned int *upper_margin, unsigned int *lower_margin, + unsigned int *hsync_len, unsigned int *vsync_len, + unsigned int *sync, unsigned int *vmode); +*/ +#endif + extern BOOLEAN XGI_SearchModeID( USHORT ModeNo,USHORT *ModeIdIndex, PVB_DEVICE_INFO ); +static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); + +/* Internal 2D accelerator functions */ +extern int XGIfb_initaccel(void); +extern void XGIfb_syncaccel(void); + +/* Internal general routines */ +static void XGIfb_search_mode(const char *name); +static int XGIfb_validate_mode(int modeindex); +static u8 XGIfb_search_refresh_rate(unsigned int rate); +static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *fb_info); +static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, + struct fb_info *info); +static void XGIfb_pre_setmode(void); +static void XGIfb_post_setmode(void); + +static BOOLEAN XGIfb_CheckVBRetrace(void); +static BOOLEAN XGIfbcheckvretracecrt2(void); +static BOOLEAN XGIfbcheckvretracecrt1(void); +static BOOLEAN XGIfb_bridgeisslave(void); + +struct XGI_memreq { + unsigned long offset; + unsigned long size; +}; + +/* XGI-specific Export functions */ +void XGI_dispinfo(struct ap_data *rec); +void XGI_malloc(struct XGI_memreq *req); +void XGI_free(unsigned long base); + +/* Internal hardware access routines */ +void XGIfb_set_reg4(u16 port, unsigned long data); +u32 XGIfb_get_reg3(u16 port); + +/* Chipset-dependent internal routines */ + + +static int XGIfb_get_dram_size(void); +static void XGIfb_detect_VB(void); +static void XGIfb_get_VB_type(void); +static int XGIfb_has_VB(void); + + +/* Internal heap routines */ +static int XGIfb_heap_init(void); +static XGI_OH *XGIfb_poh_new_node(void); +static XGI_OH *XGIfb_poh_allocate(unsigned long size); +static void XGIfb_delete_node(XGI_OH *poh); +static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh); +static XGI_OH *XGIfb_poh_free(unsigned long base); +static void XGIfb_free_node(XGI_OH *poh); + +/* Internal routines to access PCI configuration space */ +BOOLEAN XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext, + unsigned long offset, unsigned long set, unsigned long *value); +//BOOLEAN XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext, +// unsigned long offset, unsigned long set, unsigned long *value); + + +/* Routines from init.c/init301.c */ +extern void InitTo330Pointer(UCHAR,PVB_DEVICE_INFO pVBInfo); +extern BOOLEAN XGIInitNew(PXGI_HW_DEVICE_INFO HwDeviceExtension); +extern BOOLEAN XGISetModeNew(PXGI_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo); +//extern void XGI_SetEnableDstn(VB_DEVICE_INFO *XGI_Pr); +extern void XGI_LongWait(VB_DEVICE_INFO *XGI_Pr); +extern USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo ); +/* TW: Chrontel TV functions */ +extern USHORT XGI_GetCH700x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx); +extern void XGI_SetCH700x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx); +extern USHORT XGI_GetCH701x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx); +extern void XGI_SetCH701x(VB_DEVICE_INFO *XGI_Pr, USHORT tempbx); +extern void XGI_SetCH70xxANDOR(VB_DEVICE_INFO *XGI_Pr, USHORT tempax,USHORT tempbh); +extern void XGI_DDC2Delay(VB_DEVICE_INFO *XGI_Pr, USHORT delaytime); + +/* TW: Sensing routines */ +void XGI_Sense30x(void); +int XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch); + +extern XGI21_LVDSCapStruct XGI21_LCDCapList[13]; +#endif diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c new file mode 100644 index 000000000000..867012b48a01 --- /dev/null +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -0,0 +1,3773 @@ +/* + * XG20, XG21, XG40, XG42 frame buffer device + * for Linux kernels 2.5.x, 2.6.x + * Base on TW's sis fbdev code. + */ + +//#include <linux/config.h> +#include <linux/version.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/console.h> +#include <linux/selection.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/vmalloc.h> +#include <linux/vt_kern.h> +#include <linux/capability.h> +#include <linux/fs.h> +#include <linux/types.h> +#include <linux/proc_fs.h> +#include <linux/kernel.h> + +#include "osdef.h" + + +#ifndef XGIFB_PAN +#define XGIFB_PAN +#endif + +#include <asm/io.h> +#ifdef CONFIG_MTRR +#include <asm/mtrr.h> +#endif + +#include "XGIfb.h" +#include "vgatypes.h" +#include "XGI_main.h" +#include "vb_util.h" + + +#define Index_CR_GPIO_Reg1 0x48 +#define Index_CR_GPIO_Reg2 0x49 +#define Index_CR_GPIO_Reg3 0x4a + +#define GPIOG_EN (1<<6) +#define GPIOG_WRITE (1<<6) +#define GPIOG_READ (1<<1) +int XGIfb_GetXG21DefaultLVDSModeIdx(void); + +/* -------------------- Macro definitions ---------------------------- */ + +#undef XGIFBDEBUG + +#ifdef XGIFBDEBUG +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +#ifdef XGIFBDEBUG +static void dumpVGAReg(void) +{ + u8 i,reg; + +outXGIIDXREG(XGISR, 0x05, 0x86); +/* +outXGIIDXREG(XGISR, 0x08, 0x4f); +outXGIIDXREG(XGISR, 0x0f, 0x20); +outXGIIDXREG(XGISR, 0x11, 0x4f); +outXGIIDXREG(XGISR, 0x13, 0x45); +outXGIIDXREG(XGISR, 0x14, 0x51); +outXGIIDXREG(XGISR, 0x1e, 0x41); +outXGIIDXREG(XGISR, 0x1f, 0x0); +outXGIIDXREG(XGISR, 0x20, 0xa1); +outXGIIDXREG(XGISR, 0x22, 0xfb); +outXGIIDXREG(XGISR, 0x26, 0x22); +outXGIIDXREG(XGISR, 0x3e, 0x07); +*/ + +//outXGIIDXREG(XGICR, 0x19, 0x00); +//outXGIIDXREG(XGICR, 0x1a, 0x3C); +//outXGIIDXREG(XGICR, 0x22, 0xff); +//outXGIIDXREG(XGICR, 0x3D, 0x10); + +//outXGIIDXREG(XGICR, 0x4a, 0xf3); + +//outXGIIDXREG(XGICR, 0x57, 0x0); +//outXGIIDXREG(XGICR, 0x7a, 0x2c); + +//outXGIIDXREG(XGICR, 0x82, 0xcc); +//outXGIIDXREG(XGICR, 0x8c, 0x0); +/* +outXGIIDXREG(XGICR, 0x99, 0x1); +outXGIIDXREG(XGICR, 0x41, 0x40); +*/ + + for(i=0; i < 0x4f; i++) + { + inXGIIDXREG(XGISR, i, reg); + printk("\no 3c4 %x",i); + printk("\ni 3c5 => %x",reg); + } + + for(i=0; i < 0xF0; i++) + { + inXGIIDXREG(XGICR, i, reg); + printk("\no 3d4 %x",i); + printk("\ni 3d5 => %x",reg); + } +/* + + outXGIIDXREG(XGIPART1,0x2F,1); + for(i=1; i < 0x50; i++) + { + inXGIIDXREG(XGIPART1, i, reg); + printk("\no d004 %x",i); + printk("\ni d005 => %x",reg); + } + + for(i=0; i < 0x50; i++) + { + inXGIIDXREG(XGIPART2, i, reg); + printk("\no d010 %x",i); + printk("\ni d011 => %x",reg); + } + for(i=0; i < 0x50; i++) + { + inXGIIDXREG(XGIPART3, i, reg); + printk("\no d012 %x",i); + printk("\ni d013 => %x",reg); + } + for(i=0; i < 0x50; i++) + { + inXGIIDXREG(XGIPART4, i, reg); + printk("\no d014 %x",i); + printk("\ni d015 => %x",reg); + } +*/ +} +#else +static inline void dumpVGAReg(void) {} +#endif + +/* data for XGI components */ +struct video_info xgi_video_info; + + +#if 1 +#define DEBUGPRN(x) +#else +#define DEBUGPRN(x) printk(KERN_INFO x "\n"); +#endif + + +/* --------------- Hardware Access Routines -------------------------- */ + +#ifdef LINUX_KERNEL +int +XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension, + unsigned char modeno, unsigned char rateindex) +{ + USHORT ModeNo = modeno; + USHORT ModeIdIndex = 0, ClockIndex = 0; + USHORT RefreshRateTableIndex = 0; + + /*ULONG temp = 0;*/ + int Clock; + XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase; + InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ; + + RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ; + +/* + temp = XGI_SearchModeID( ModeNo , &ModeIdIndex, XGI_Pr ) ; + if(!temp) { + printk(KERN_ERR "Could not find mode %x\n", ModeNo); + return 65000; + } + + RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex; + RefreshRateTableIndex += (rateindex - 1); + +*/ + ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; + if(HwDeviceExtension->jChipType < XGI_315H) { + ClockIndex &= 0x3F; + } + Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000 ; + + return(Clock); +} + +int +XGIfb_mode_rate_to_ddata(VB_DEVICE_INFO *XGI_Pr, PXGI_HW_DEVICE_INFO HwDeviceExtension, + unsigned char modeno, unsigned char rateindex, + u32 *left_margin, u32 *right_margin, + u32 *upper_margin, u32 *lower_margin, + u32 *hsync_len, u32 *vsync_len, + u32 *sync, u32 *vmode) +{ + USHORT ModeNo = modeno; + USHORT ModeIdIndex = 0, index = 0; + USHORT RefreshRateTableIndex = 0; + + unsigned short VRE, VBE, VRS, VBS, VDE, VT; + unsigned short HRE, HBE, HRS, HBS, HDE, HT; + unsigned char sr_data, cr_data, cr_data2; + unsigned long cr_data3; + int A, B, C, D, E, F, temp, j; + XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase; + InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ; + RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ; +/* + temp = XGI_SearchModeID( ModeNo, &ModeIdIndex, XGI_Pr); + if(!temp) return 0; + + RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex; + RefreshRateTableIndex += (rateindex - 1); +*/ + index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; + + sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5]; + + cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0]; + + /* Horizontal total */ + HT = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x03) << 8); + A = HT + 5; + + /*cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1]; + + Horizontal display enable end + HDE = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x0C) << 6);*/ + HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) -1; + E = HDE + 1; + + cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3]; + + /* Horizontal retrace (=sync) start */ + HRS = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0xC0) << 2); + F = HRS - E - 3; + + cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1]; + + /* Horizontal blank start */ + HBS = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x30) << 4); + + sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6]; + + cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2]; + + cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4]; + + /* Horizontal blank end */ + HBE = (cr_data & 0x1f) | + ((unsigned short) (cr_data2 & 0x80) >> 2) | + ((unsigned short) (sr_data & 0x03) << 6); + + /* Horizontal retrace (=sync) end */ + HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3); + + temp = HBE - ((E - 1) & 255); + B = (temp > 0) ? temp : (temp + 256); + + temp = HRE - ((E + F + 3) & 63); + C = (temp > 0) ? temp : (temp + 64); + + D = B - F - C; + + *left_margin = D * 8; + *right_margin = F * 8; + *hsync_len = C * 8; + + sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14]; + + cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8]; + + cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9]; + + /* Vertical total */ + VT = (cr_data & 0xFF) | + ((unsigned short) (cr_data2 & 0x01) << 8) | + ((unsigned short)(cr_data2 & 0x20) << 4) | + ((unsigned short) (sr_data & 0x01) << 10); + A = VT + 2; + + //cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; + + /* Vertical display enable end */ +/* VDE = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x02) << 7) | + ((unsigned short) (cr_data2 & 0x40) << 3) | + ((unsigned short) (sr_data & 0x02) << 9); */ + VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes -1; + E = VDE + 1; + + cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; + + /* Vertical retrace (=sync) start */ + VRS = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x04) << 6) | + ((unsigned short) (cr_data2 & 0x80) << 2) | + ((unsigned short) (sr_data & 0x08) << 7); + F = VRS + 1 - E; + + cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12]; + + cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5; + + /* Vertical blank start */ + VBS = (cr_data & 0xff) | + ((unsigned short) (cr_data2 & 0x08) << 5) | + ((unsigned short) (cr_data3 & 0x20) << 4) | + ((unsigned short) (sr_data & 0x04) << 8); + + cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13]; + + /* Vertical blank end */ + VBE = (cr_data & 0xff) | + ((unsigned short) (sr_data & 0x10) << 4); + temp = VBE - ((E - 1) & 511); + B = (temp > 0) ? temp : (temp + 512); + + cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11]; + + /* Vertical retrace (=sync) end */ + VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1); + temp = VRE - ((E + F - 1) & 31); + C = (temp > 0) ? temp : (temp + 32); + + D = B - F - C; + + *upper_margin = D; + *lower_margin = F; + *vsync_len = C; + + if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000) + *sync &= ~FB_SYNC_VERT_HIGH_ACT; + else + *sync |= FB_SYNC_VERT_HIGH_ACT; + + if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000) + *sync &= ~FB_SYNC_HOR_HIGH_ACT; + else + *sync |= FB_SYNC_HOR_HIGH_ACT; + + *vmode = FB_VMODE_NONINTERLACED; + if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080) + *vmode = FB_VMODE_INTERLACED; + else { + j = 0; + while(XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) { + if(XGI_Pr->EModeIDTable[j].Ext_ModeID == + XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) { + if(XGI_Pr->EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) { + *vmode = FB_VMODE_DOUBLE; + } + break; + } + j++; + } + } + +#if 0 /* That's bullshit, only the resolution needs to be shifted */ + if((*vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { + *upper_margin <<= 1; + *lower_margin <<= 1; + *vsync_len <<= 1; + } else if((*vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { + *upper_margin >>= 1; + *lower_margin >>= 1; + *vsync_len >>= 1; + } +#endif + + return 1; +} + +#endif + + + +void XGIRegInit(VB_DEVICE_INFO *XGI_Pr, ULONG BaseAddr) +{ + XGI_Pr->RelIO = BaseAddr; + XGI_Pr->P3c4 = BaseAddr + 0x14; + XGI_Pr->P3d4 = BaseAddr + 0x24; + XGI_Pr->P3c0 = BaseAddr + 0x10; + XGI_Pr->P3ce = BaseAddr + 0x1e; + XGI_Pr->P3c2 = BaseAddr + 0x12; + XGI_Pr->P3ca = BaseAddr + 0x1a; + XGI_Pr->P3c6 = BaseAddr + 0x16; + XGI_Pr->P3c7 = BaseAddr + 0x17; + XGI_Pr->P3c8 = BaseAddr + 0x18; + XGI_Pr->P3c9 = BaseAddr + 0x19; + XGI_Pr->P3da = BaseAddr + 0x2A; + XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04; /* Digital video interface registers (LCD) */ + XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10; /* 301 TV Encoder registers */ + XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12; /* 301 Macrovision registers */ + XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */ + XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14+2; /* 301 palette address port registers */ + +} + + +void XGIfb_set_reg4(u16 port, unsigned long data) +{ + outl((u32) (data & 0xffffffff), port); +} + +u32 XGIfb_get_reg3(u16 port) +{ + u32 data; + + data = inl(port); + return (data); +} + +/* ------------ Interface for init & mode switching code ------------- */ + +BOOLEAN +XGIfb_query_VGA_config_space(PXGI_HW_DEVICE_INFO pXGIhw_ext, + unsigned long offset, unsigned long set, unsigned long *value) +{ + static struct pci_dev *pdev = NULL; + static unsigned char init = 0, valid_pdev = 0; + + if (!set) + DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset); + else + DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value); + + if (!init) { + init = TRUE; + pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id, pdev); + if (pdev) { + valid_pdev = TRUE; + pci_dev_put(pdev); + } + } + + if (!valid_pdev) { + printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n", + xgi_video_info.chip_id); + return FALSE; + } + + if (set == 0) + pci_read_config_dword(pdev, offset, (u32 *)value); + else + pci_write_config_dword(pdev, offset, (u32)(*value)); + + return TRUE; +} + +/*BOOLEAN XGIfb_query_north_bridge_space(PXGI_HW_DEVICE_INFO pXGIhw_ext, + unsigned long offset, unsigned long set, unsigned long *value) +{ + static struct pci_dev *pdev = NULL; + static unsigned char init = 0, valid_pdev = 0; + u16 nbridge_id = 0; + + if (!init) { + init = TRUE; + switch (xgi_video_info.chip) { + case XGI_540: + nbridge_id = PCI_DEVICE_ID_XG_540; + break; + case XGI_630: + nbridge_id = PCI_DEVICE_ID_XG_630; + break; + case XGI_730: + nbridge_id = PCI_DEVICE_ID_XG_730; + break; + case XGI_550: + nbridge_id = PCI_DEVICE_ID_XG_550; + break; + case XGI_650: + nbridge_id = PCI_DEVICE_ID_XG_650; + break; + case XGI_740: + nbridge_id = PCI_DEVICE_ID_XG_740; + break; + default: + nbridge_id = 0; + break; + } + + pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev); + if (pdev) + valid_pdev = TRUE; + } + + if (!valid_pdev) { + printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n", + nbridge_id); + return FALSE; + } + + if (set == 0) + pci_read_config_dword(pdev, offset, (u32 *)value); + else + pci_write_config_dword(pdev, offset, (u32)(*value)); + + return TRUE; +} +*/ +/* ------------------ Internal helper routines ----------------- */ + +static void XGIfb_search_mode(const char *name) +{ + int i = 0, j = 0, l; + + if(name == NULL) { + printk(KERN_ERR "XGIfb: Internal error, using default mode.\n"); + xgifb_mode_idx = DEFAULT_MODE; + if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)) + { + xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx(); + } + return; + } + + + if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) { + printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n"); + xgifb_mode_idx = DEFAULT_MODE; + if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)) + { + xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx(); + } + return; + } + + while(XGIbios_mode[i].mode_no != 0) { + l = min(strlen(name), strlen(XGIbios_mode[i].name)); + if (!strncmp(name, XGIbios_mode[i].name, l)) { + xgifb_mode_idx = i; + j = 1; + break; + } + i++; + } + if(!j) printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name); +} + +static void XGIfb_search_vesamode(unsigned int vesamode) +{ + int i = 0, j = 0; + + if(vesamode == 0) { + + printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n"); + xgifb_mode_idx = DEFAULT_MODE; + if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)) + { + xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx(); + } + return; + } + + vesamode &= 0x1dff; /* Clean VESA mode number from other flags */ + + while(XGIbios_mode[i].mode_no != 0) { + if( (XGIbios_mode[i].vesa_mode_no_1 == vesamode) || + (XGIbios_mode[i].vesa_mode_no_2 == vesamode) ) { + xgifb_mode_idx = i; + j = 1; + break; + } + i++; + } + if(!j) printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode); +} + +int XGIfb_GetXG21LVDSData(void) +{ + u8 tmp; + unsigned char *pData; + int i,j,k; + + inXGIIDXREG(XGISR,0x1e,tmp); + outXGIIDXREG(XGISR, 0x1e, tmp|4); + + pData = xgi_video_info.mmio_vbase+0x20000; + if ((pData[0x0]==0x55) && (pData[0x1]==0xAA) && (pData[0x65] & 0x1)) + { + i = pData[ 0x316 ] | ( pData[ 0x317 ] << 8 ); + j = pData[ i-1 ] ; + if ( j == 0xff ) + { + j = 1; + } + k = 0; + do + { + XGI21_LCDCapList[k].LVDS_Capability = pData[ i ] | ( pData[ i + 1 ] << 8 ); + XGI21_LCDCapList[k].LVDSHT = pData[ i + 2 ] | ( pData[ i + 3 ] << 8 ) ; + XGI21_LCDCapList[k].LVDSVT = pData[ i + 4 ] | ( pData[ i + 5 ] << 8 ); + XGI21_LCDCapList[k].LVDSHDE = pData[ i + 6 ] | ( pData[ i + 7 ] << 8 ); + XGI21_LCDCapList[k].LVDSVDE = pData[ i + 8 ] | ( pData[ i + 9 ] << 8 ); + XGI21_LCDCapList[k].LVDSHFP = pData[ i + 10 ] | ( pData[ i + 11 ] << 8 ); + XGI21_LCDCapList[k].LVDSVFP = pData[ i + 12 ] | ( pData[ i + 13 ] << 8 ); + XGI21_LCDCapList[k].LVDSHSYNC = pData[ i + 14 ] | ( pData[ i + 15 ] << 8 ); + XGI21_LCDCapList[k].LVDSVSYNC = pData[ i + 16 ] | ( pData[ i + 17 ] << 8 ); + XGI21_LCDCapList[k].VCLKData1 = pData[ i + 18 ] ; + XGI21_LCDCapList[k].VCLKData2 = pData[ i + 19 ] ; + XGI21_LCDCapList[k].PSC_S1 = pData[ i + 20 ] ; + XGI21_LCDCapList[k].PSC_S2 = pData[ i + 21 ] ; + XGI21_LCDCapList[k].PSC_S3 = pData[ i + 22 ] ; + XGI21_LCDCapList[k].PSC_S4 = pData[ i + 23 ] ; + XGI21_LCDCapList[k].PSC_S5 = pData[ i + 24 ] ; + i += 25; + j--; + k++; + } while ( (j>0) && ( k < (sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) ) ); + return 1; + } + return 0; +} + +int XGIfb_GetXG21DefaultLVDSModeIdx(void) +{ + + int found_mode = 0; + int XGIfb_mode_idx = 0; + + found_mode = 0; + while( (XGIbios_mode[XGIfb_mode_idx].mode_no != 0) && + (XGIbios_mode[XGIfb_mode_idx].xres <= XGI21_LCDCapList[0].LVDSHDE) ) + { + if( (XGIbios_mode[XGIfb_mode_idx].xres == XGI21_LCDCapList[0].LVDSHDE) && + (XGIbios_mode[XGIfb_mode_idx].yres == XGI21_LCDCapList[0].LVDSVDE) && + (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) + { + XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no; + found_mode = 1; + break; + } + XGIfb_mode_idx++; + } + if (!found_mode) + XGIfb_mode_idx = 0; + + return (XGIfb_mode_idx); +} + + +static int XGIfb_validate_mode(int myindex) +{ + u16 xres, yres; + + if (xgi_video_info.chip == XG21) + { + if ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD) + { + xres = XGI21_LCDCapList[0].LVDSHDE; + yres = XGI21_LCDCapList[0].LVDSVDE; + if(XGIbios_mode[myindex].xres > xres) + return(-1); + if(XGIbios_mode[myindex].yres > yres) + return(-1); + if ((XGIbios_mode[myindex].xres < xres) && (XGIbios_mode[myindex].yres < yres) ) + { + if (XGIbios_mode[myindex].bpp > 8) + return(-1); + } + + } + return(myindex); + + } + + /* FIXME: for now, all is valid on XG27 */ + if (xgi_video_info.chip == XG27) + return(myindex); + + if(!(XGIbios_mode[myindex].chipset & MD_XGI315)) + return(-1); + + switch (xgi_video_info.disp_state & DISPTYPE_DISP2) { + case DISPTYPE_LCD: + switch (XGIhw_ext.ulCRT2LCDType) { + case LCD_640x480: + xres = 640; yres = 480; break; + case LCD_800x600: + xres = 800; yres = 600; break; + case LCD_1024x600: + xres = 1024; yres = 600; break; + case LCD_1024x768: + xres = 1024; yres = 768; break; + case LCD_1152x768: + xres = 1152; yres = 768; break; + case LCD_1280x960: + xres = 1280; yres = 960; break; + case LCD_1280x768: + xres = 1280; yres = 768; break; + case LCD_1280x1024: + xres = 1280; yres = 1024; break; + case LCD_1400x1050: + xres = 1400; yres = 1050; break; + case LCD_1600x1200: + xres = 1600; yres = 1200; break; +// case LCD_320x480: // TW: FSTN +// xres = 320; yres = 480; break; + default: + xres = 0; yres = 0; break; + } + if(XGIbios_mode[myindex].xres > xres) { + return(-1); + } + if(XGIbios_mode[myindex].yres > yres) { + return(-1); + } + if((XGIhw_ext.ulExternalChip == 0x01) || // LVDS + (XGIhw_ext.ulExternalChip == 0x05)) // LVDS+Chrontel + { + switch (XGIbios_mode[myindex].xres) { + case 512: + if(XGIbios_mode[myindex].yres != 512) return -1; + if(XGIhw_ext.ulCRT2LCDType == LCD_1024x600) return -1; + break; + case 640: + if((XGIbios_mode[myindex].yres != 400) && + (XGIbios_mode[myindex].yres != 480)) + return -1; + break; + case 800: + if(XGIbios_mode[myindex].yres != 600) return -1; + break; + case 1024: + if((XGIbios_mode[myindex].yres != 600) && + (XGIbios_mode[myindex].yres != 768)) + return -1; + if((XGIbios_mode[myindex].yres == 600) && + (XGIhw_ext.ulCRT2LCDType != LCD_1024x600)) + return -1; + break; + case 1152: + if((XGIbios_mode[myindex].yres) != 768) return -1; + if(XGIhw_ext.ulCRT2LCDType != LCD_1152x768) return -1; + break; + case 1280: + if((XGIbios_mode[myindex].yres != 768) && + (XGIbios_mode[myindex].yres != 1024)) + return -1; + if((XGIbios_mode[myindex].yres == 768) && + (XGIhw_ext.ulCRT2LCDType != LCD_1280x768)) + return -1; + break; + case 1400: + if(XGIbios_mode[myindex].yres != 1050) return -1; + break; + case 1600: + if(XGIbios_mode[myindex].yres != 1200) return -1; + break; + default: + return -1; + } + } else { + switch (XGIbios_mode[myindex].xres) { + case 512: + if(XGIbios_mode[myindex].yres != 512) return -1; + break; + case 640: + if((XGIbios_mode[myindex].yres != 400) && + (XGIbios_mode[myindex].yres != 480)) + return -1; + break; + case 800: + if(XGIbios_mode[myindex].yres != 600) return -1; + break; + case 1024: + if(XGIbios_mode[myindex].yres != 768) return -1; + break; + case 1280: + if((XGIbios_mode[myindex].yres != 960) && + (XGIbios_mode[myindex].yres != 1024)) + return -1; + if(XGIbios_mode[myindex].yres == 960) { + if(XGIhw_ext.ulCRT2LCDType == LCD_1400x1050) + return -1; + } + break; + case 1400: + if(XGIbios_mode[myindex].yres != 1050) return -1; + break; + case 1600: + if(XGIbios_mode[myindex].yres != 1200) return -1; + break; + default: + return -1; + } + } + break; + case DISPTYPE_TV: + switch (XGIbios_mode[myindex].xres) { + case 512: + case 640: + case 800: + break; + case 720: + if (xgi_video_info.TV_type == TVMODE_NTSC) { + if (XGIbios_mode[myindex].yres != 480) { + return(-1); + } + } else if (xgi_video_info.TV_type == TVMODE_PAL) { + if (XGIbios_mode[myindex].yres != 576) { + return(-1); + } + } + // TW: LVDS/CHRONTEL does not support 720 + if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL || + xgi_video_info.hasVB == HASVB_CHRONTEL) { + return(-1); + } + break; + case 1024: + if (xgi_video_info.TV_type == TVMODE_NTSC) { + if(XGIbios_mode[myindex].bpp == 32) { + return(-1); + } + } + // TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019) + if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL || + xgi_video_info.hasVB == HASVB_CHRONTEL) { + if(xgi_video_info.chip < XGI_315H) { + return(-1); + } + } + break; + default: + return(-1); + } + break; + case DISPTYPE_CRT2: + if(XGIbios_mode[myindex].xres > 1280) return -1; + break; + } + return(myindex); + +} + +static void XGIfb_search_crt2type(const char *name) +{ + int i = 0; + + if(name == NULL) + return; + + while(XGI_crt2type[i].type_no != -1) { + if (!strcmp(name, XGI_crt2type[i].name)) { + XGIfb_crt2type = XGI_crt2type[i].type_no; + XGIfb_tvplug = XGI_crt2type[i].tvplug_no; + break; + } + i++; + } + if(XGIfb_crt2type < 0) + printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name); +} + +static void XGIfb_search_queuemode(const char *name) +{ + int i = 0; + + if(name == NULL) + return; + + while (XGI_queuemode[i].type_no != -1) { + if (!strcmp(name, XGI_queuemode[i].name)) { + XGIfb_queuemode = XGI_queuemode[i].type_no; + break; + } + i++; + } + if (XGIfb_queuemode < 0) + printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name); +} + +static u8 XGIfb_search_refresh_rate(unsigned int rate) +{ + u16 xres, yres; + int i = 0; + + xres = XGIbios_mode[xgifb_mode_idx].xres; + yres = XGIbios_mode[xgifb_mode_idx].yres; + + XGIfb_rate_idx = 0; + while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) { + if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres == yres)) { + if (XGIfb_vrate[i].refresh == rate) { + XGIfb_rate_idx = XGIfb_vrate[i].idx; + break; + } else if (XGIfb_vrate[i].refresh > rate) { + if ((XGIfb_vrate[i].refresh - rate) <= 3) { + DPRINTK("XGIfb: Adjusting rate from %d up to %d\n", + rate, XGIfb_vrate[i].refresh); + XGIfb_rate_idx = XGIfb_vrate[i].idx; + xgi_video_info.refresh_rate = XGIfb_vrate[i].refresh; + } else if (((rate - XGIfb_vrate[i-1].refresh) <= 2) + && (XGIfb_vrate[i].idx != 1)) { + DPRINTK("XGIfb: Adjusting rate from %d down to %d\n", + rate, XGIfb_vrate[i-1].refresh); + XGIfb_rate_idx = XGIfb_vrate[i-1].idx; + xgi_video_info.refresh_rate = XGIfb_vrate[i-1].refresh; + } + break; + } else if((rate - XGIfb_vrate[i].refresh) <= 2) { + DPRINTK("XGIfb: Adjusting rate from %d down to %d\n", + rate, XGIfb_vrate[i].refresh); + XGIfb_rate_idx = XGIfb_vrate[i].idx; + break; + } + } + i++; + } + if (XGIfb_rate_idx > 0) { + return XGIfb_rate_idx; + } else { + printk(KERN_INFO + "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres); + return 0; + } +} + +static void XGIfb_search_tvstd(const char *name) +{ + int i = 0; + + if(name == NULL) + return; + + while (XGI_tvtype[i].type_no != -1) { + if (!strcmp(name, XGI_tvtype[i].name)) { + XGIfb_tvmode = XGI_tvtype[i].type_no; + break; + } + i++; + } +} + +static BOOLEAN XGIfb_bridgeisslave(void) +{ + unsigned char usScratchP1_00; + + if(xgi_video_info.hasVB == HASVB_NONE) return FALSE; + + inXGIIDXREG(XGIPART1,0x00,usScratchP1_00); + if( (usScratchP1_00 & 0x50) == 0x10) { + return TRUE; + } else { + return FALSE; + } +} + +static BOOLEAN XGIfbcheckvretracecrt1(void) +{ + unsigned char temp; + + inXGIIDXREG(XGICR,0x17,temp); + if(!(temp & 0x80)) return FALSE; + + + inXGIIDXREG(XGISR,0x1f,temp); + if(temp & 0xc0) return FALSE; + + + if(inXGIREG(XGIINPSTAT) & 0x08) return TRUE; + else return FALSE; +} + +static BOOLEAN XGIfbcheckvretracecrt2(void) +{ + unsigned char temp; + if(xgi_video_info.hasVB == HASVB_NONE) return FALSE; + inXGIIDXREG(XGIPART1, 0x30, temp); + if(temp & 0x02) return FALSE; + else return TRUE; +} + +static BOOLEAN XGIfb_CheckVBRetrace(void) +{ + if(xgi_video_info.disp_state & DISPTYPE_DISP2) { + if(XGIfb_bridgeisslave()) { + return(XGIfbcheckvretracecrt1()); + } else { + return(XGIfbcheckvretracecrt2()); + } + } + return(XGIfbcheckvretracecrt1()); +} + +/* ----------- FBDev related routines for all series ----------- */ + + +static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var) +{ + switch(var->bits_per_pixel) { + case 8: + var->red.offset = var->green.offset = var->blue.offset = 0; + var->red.length = var->green.length = var->blue.length = 6; + xgi_video_info.video_cmap_len = 256; + break; + case 16: + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + xgi_video_info.video_cmap_len = 16; + break; + case 32: + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 24; + var->transp.length = 8; + xgi_video_info.video_cmap_len = 16; + break; + } +} + + + +static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, + struct fb_info *info) +{ + + unsigned int htotal = var->left_margin + var->xres + + var->right_margin + var->hsync_len; + unsigned int vtotal = var->upper_margin + var->yres + + var->lower_margin + var->vsync_len; +#if defined(__powerpc__) + u8 sr_data, cr_data; +#endif + unsigned int drate = 0, hrate = 0; + int found_mode = 0; + int old_mode; +// unsigned char reg,reg1; + + DEBUGPRN("Inside do_set_var"); +// printk(KERN_DEBUG "XGIfb:var->yres=%d, var->upper_margin=%d, var->lower_margin=%d, var->vsync_len=%d\n", var->yres,var->upper_margin,var->lower_margin,var->vsync_len); + + info->var.xres_virtual = var->xres_virtual; + info->var.yres_virtual = var->yres_virtual; + info->var.bits_per_pixel = var->bits_per_pixel; + + if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) + vtotal <<= 1; + else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) + vtotal <<= 2; + else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) + { +// vtotal <<= 1; +// var->yres <<= 1; + } + + if(!htotal || !vtotal) { + DPRINTK("XGIfb: Invalid 'var' information\n"); + return -EINVAL; + } + printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n", + var->pixclock,htotal,vtotal); + + + + if(var->pixclock && htotal && vtotal) { + drate = 1000000000 / var->pixclock; + hrate = (drate * 1000) / htotal; + xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal); + } else { + xgi_video_info.refresh_rate = 60; + } + + printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n", + var->xres,var->yres,var->bits_per_pixel,xgi_video_info.refresh_rate); + + old_mode = xgifb_mode_idx; + xgifb_mode_idx = 0; + + while( (XGIbios_mode[xgifb_mode_idx].mode_no != 0) && + (XGIbios_mode[xgifb_mode_idx].xres <= var->xres) ) { + if( (XGIbios_mode[xgifb_mode_idx].xres == var->xres) && + (XGIbios_mode[xgifb_mode_idx].yres == var->yres) && + (XGIbios_mode[xgifb_mode_idx].bpp == var->bits_per_pixel)) { + XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no; + found_mode = 1; + break; + } + xgifb_mode_idx++; + } + + if(found_mode) + xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx); + else + xgifb_mode_idx = -1; + + if(xgifb_mode_idx < 0) { + printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres, + var->yres, var->bits_per_pixel); + xgifb_mode_idx = old_mode; + return -EINVAL; + } + + if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) { + XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx; + xgi_video_info.refresh_rate = 60; + } + + if(isactive) { + + + XGIfb_pre_setmode(); + if(XGISetModeNew( &XGIhw_ext, XGIfb_mode_no) == 0) { + printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no); + return -EINVAL; + } + info->fix.line_length = ((info->var.xres_virtual * info->var.bits_per_pixel)>>6); + + outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD); + + outXGIIDXREG(XGICR,0x13,(info->fix.line_length & 0x00ff)); + outXGIIDXREG(XGISR,0x0E,(info->fix.line_length & 0xff00)>>8); + + XGIfb_post_setmode(); + + DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d \n", + XGIbios_mode[xgifb_mode_idx].xres, + XGIbios_mode[xgifb_mode_idx].yres, + XGIbios_mode[xgifb_mode_idx].bpp, + xgi_video_info.refresh_rate); + + xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp; + xgi_video_info.video_vwidth = info->var.xres_virtual; + xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres; + xgi_video_info.video_vheight = info->var.yres_virtual; + xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres; + xgi_video_info.org_x = xgi_video_info.org_y = 0; + xgi_video_info.video_linelength = info->var.xres_virtual * (xgi_video_info.video_bpp >> 3); + xgi_video_info.accel = 0; + if(XGIfb_accel) { + xgi_video_info.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0; + } + switch(xgi_video_info.video_bpp) + { + case 8: + xgi_video_info.DstColor = 0x0000; + xgi_video_info.XGI310_AccelDepth = 0x00000000; + xgi_video_info.video_cmap_len = 256; +#if defined(__powerpc__) + inXGIIDXREG (XGICR, 0x4D, cr_data); + outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0)); +#endif + break; + case 16: + xgi_video_info.DstColor = 0x8000; + xgi_video_info.XGI310_AccelDepth = 0x00010000; +#if defined(__powerpc__) + inXGIIDXREG (XGICR, 0x4D, cr_data); + outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B)); +#endif + xgi_video_info.video_cmap_len = 16; + break; + case 32: + xgi_video_info.DstColor = 0xC000; + xgi_video_info.XGI310_AccelDepth = 0x00020000; + xgi_video_info.video_cmap_len = 16; +#if defined(__powerpc__) + inXGIIDXREG (XGICR, 0x4D, cr_data); + outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15)); +#endif + break; + default: + xgi_video_info.video_cmap_len = 16; + printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp); + xgi_video_info.accel = 0; + break; + } + } + XGIfb_bpp_to_var(var); /*update ARGB info*/ + DEBUGPRN("End of do_set_var"); + + dumpVGAReg(); + return 0; +} + +#ifdef XGIFB_PAN +static int XGIfb_pan_var(struct fb_var_screeninfo *var) +{ + unsigned int base; + +// printk("Inside pan_var"); + + if (var->xoffset > (var->xres_virtual - var->xres)) { +// printk( "Pan: xo: %d xv %d xr %d\n", +// var->xoffset, var->xres_virtual, var->xres); + return -EINVAL; + } + if(var->yoffset > (var->yres_virtual - var->yres)) { +// printk( "Pan: yo: %d yv %d yr %d\n", +// var->yoffset, var->yres_virtual, var->yres); + return -EINVAL; + } + base = var->yoffset * var->xres_virtual + var->xoffset; + + /* calculate base bpp dep. */ + switch(var->bits_per_pixel) { + case 16: + base >>= 1; + break; + case 32: + break; + case 8: + default: + base >>= 2; + break; + } + + outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD); + + outXGIIDXREG(XGICR, 0x0D, base & 0xFF); + outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF); + outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF); + outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03); + setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04); + + if(xgi_video_info.disp_state & DISPTYPE_DISP2) { + orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01); + outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF)); + outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF)); + outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF)); + setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); + } +// printk("End of pan_var"); + return 0; +} +#endif + + +void XGI_dispinfo(struct ap_data *rec) +{ + rec->minfo.bpp = xgi_video_info.video_bpp; + rec->minfo.xres = xgi_video_info.video_width; + rec->minfo.yres = xgi_video_info.video_height; + rec->minfo.v_xres = xgi_video_info.video_vwidth; + rec->minfo.v_yres = xgi_video_info.video_vheight; + rec->minfo.org_x = xgi_video_info.org_x; + rec->minfo.org_y = xgi_video_info.org_y; + rec->minfo.vrate = xgi_video_info.refresh_rate; + rec->iobase = xgi_video_info.vga_base - 0x30; + rec->mem_size = xgi_video_info.video_size; + rec->disp_state = xgi_video_info.disp_state; + rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL; + rec->hasVB = xgi_video_info.hasVB; + rec->TV_type = xgi_video_info.TV_type; + rec->TV_plug = xgi_video_info.TV_plug; + rec->chip = xgi_video_info.chip; +} + + + + +static int XGIfb_open(struct fb_info *info, int user) +{ + return 0; +} + +static int XGIfb_release(struct fb_info *info, int user) +{ + return 0; +} + +static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var) +{ + int rc = 16; + + switch(var->bits_per_pixel) { + case 8: + rc = 256; + break; + case 16: + rc = 16; + break; + case 32: + rc = 16; + break; + } + return rc; +} + +static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + if (regno >= XGIfb_get_cmap_len(&info->var)) + return 1; + + switch (info->var.bits_per_pixel) { + case 8: + outXGIREG(XGIDACA, regno); + outXGIREG(XGIDACD, (red >> 10)); + outXGIREG(XGIDACD, (green >> 10)); + outXGIREG(XGIDACD, (blue >> 10)); + if (xgi_video_info.disp_state & DISPTYPE_DISP2) { + outXGIREG(XGIDAC2A, regno); + outXGIREG(XGIDAC2D, (red >> 8)); + outXGIREG(XGIDAC2D, (green >> 8)); + outXGIREG(XGIDAC2D, (blue >> 8)); + } + break; + case 16: + ((u32 *)(info->pseudo_palette))[regno] = + ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); + break; + case 32: + red >>= 8; + green >>= 8; + blue >>= 8; + ((u32 *) (info->pseudo_palette))[regno] = + (red << 16) | (green << 8) | (blue); + break; + } + return 0; +} + +static int XGIfb_set_par(struct fb_info *info) +{ + int err; + +// printk("XGIfb: inside set_par\n"); + if((err = XGIfb_do_set_var(&info->var, 1, info))) + return err; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) + XGIfb_get_fix(&info->fix, info->currcon, info); +#else + XGIfb_get_fix(&info->fix, -1, info); +#endif +// printk("XGIfb:end of set_par\n"); + return 0; +} + +static int XGIfb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + unsigned int htotal = + var->left_margin + var->xres + var->right_margin + + var->hsync_len; + unsigned int vtotal = 0; + unsigned int drate = 0, hrate = 0; + int found_mode = 0; + int refresh_rate, search_idx; + + DEBUGPRN("Inside check_var"); + + if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) { + vtotal = var->upper_margin + var->yres + var->lower_margin + + var->vsync_len; + vtotal <<= 1; + } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { + vtotal = var->upper_margin + var->yres + var->lower_margin + + var->vsync_len; + vtotal <<= 2; + } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { + vtotal = var->upper_margin + (var->yres/2) + var->lower_margin + + var->vsync_len; + } else vtotal = var->upper_margin + var->yres + var->lower_margin + + var->vsync_len; + + if(!(htotal) || !(vtotal)) { + XGIFAIL("XGIfb: no valid timing data"); + } + + + if(var->pixclock && htotal && vtotal) { + drate = 1000000000 / var->pixclock; + hrate = (drate * 1000) / htotal; + xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal); + printk(KERN_DEBUG \ + "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" \ + "%s: drate=%d, hrate=%d, refresh_rate=%d\n", + __func__,var->pixclock, htotal, vtotal, + __func__, drate, hrate, xgi_video_info.refresh_rate); + } else { + xgi_video_info.refresh_rate = 60; + } + +/* + if((var->pixclock) && (htotal)) { + drate = 1E12 / var->pixclock; + hrate = drate / htotal; + refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5); + } else refresh_rate = 60; +*/ + /* TW: Calculation wrong for 1024x600 - force it to 60Hz */ + if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60; + + search_idx = 0; + while((XGIbios_mode[search_idx].mode_no != 0) && + (XGIbios_mode[search_idx].xres <= var->xres) ) { + if((XGIbios_mode[search_idx].xres == var->xres) && + (XGIbios_mode[search_idx].yres == var->yres) && + (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) { + if(XGIfb_validate_mode(search_idx) > 0) { + found_mode = 1; + break; + } + } + search_idx++; + } + + if(!found_mode) { + + printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n", + var->xres, var->yres, var->bits_per_pixel); + + search_idx = 0; + while(XGIbios_mode[search_idx].mode_no != 0) { + + if( (var->xres <= XGIbios_mode[search_idx].xres) && + (var->yres <= XGIbios_mode[search_idx].yres) && + (var->bits_per_pixel == XGIbios_mode[search_idx].bpp) ) { + if(XGIfb_validate_mode(search_idx) > 0) { + found_mode = 1; + break; + } + } + search_idx++; + } + if(found_mode) { + var->xres = XGIbios_mode[search_idx].xres; + var->yres = XGIbios_mode[search_idx].yres; + printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n", + var->xres, var->yres, var->bits_per_pixel); + + } else { + printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n", + var->xres, var->yres, var->bits_per_pixel); + return -EINVAL; + } + } + + /* TW: TODO: Check the refresh rate */ + + /* Adapt RGB settings */ + XGIfb_bpp_to_var(var); + + /* Sanity check for offsets */ + if (var->xoffset < 0) + var->xoffset = 0; + if (var->yoffset < 0) + var->yoffset = 0; + + + if(!XGIfb_ypan) { + if(var->xres != var->xres_virtual) + var->xres_virtual = var->xres; + if(var->yres != var->yres_virtual) + var->yres_virtual = var->yres; + }/* else { + // TW: Now patch yres_virtual if we use panning + // May I do this? + var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3)); + if(var->yres_virtual <= var->yres) { + // TW: Paranoia check + var->yres_virtual = var->yres; + } + }*/ + + /* Truncate offsets to maximum if too high */ + if (var->xoffset > var->xres_virtual - var->xres) + var->xoffset = var->xres_virtual - var->xres - 1; + + if (var->yoffset > var->yres_virtual - var->yres) + var->yoffset = var->yres_virtual - var->yres - 1; + + /* Set everything else to 0 */ + var->red.msb_right = + var->green.msb_right = + var->blue.msb_right = + var->transp.offset = var->transp.length = var->transp.msb_right = 0; + + DEBUGPRN("end of check_var"); + return 0; +} + +#ifdef XGIFB_PAN +static int XGIfb_pan_display( struct fb_var_screeninfo *var, + struct fb_info* info) +{ + int err; + +// printk("\nInside pan_display:"); + + if (var->xoffset > (var->xres_virtual - var->xres)) + return -EINVAL; + if (var->yoffset > (var->yres_virtual - var->yres)) + return -EINVAL; + + if (var->vmode & FB_VMODE_YWRAP) { + if (var->yoffset < 0 + || var->yoffset >= info->var.yres_virtual + || var->xoffset) return -EINVAL; + } else { + if (var->xoffset + info->var.xres > info->var.xres_virtual || + var->yoffset + info->var.yres > info->var.yres_virtual) + return -EINVAL; + } + + if((err = XGIfb_pan_var(var)) < 0) return err; + + info->var.xoffset = var->xoffset; + info->var.yoffset = var->yoffset; + if (var->vmode & FB_VMODE_YWRAP) + info->var.vmode |= FB_VMODE_YWRAP; + else + info->var.vmode &= ~FB_VMODE_YWRAP; + +// printk(" End of pan_display"); + return 0; +} +#endif + +#if 0 +static int XGIfb_mmap(struct fb_info *info, struct file *file, + struct vm_area_struct *vma) +{ + unsigned long start; + unsigned long off; + u32 len, mmio_off; + + DEBUGPRN("inside mmap"); + if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) return -EINVAL; + + off = vma->vm_pgoff << PAGE_SHIFT; + + start = (unsigned long) xgi_video_info.video_base; + len = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.video_size); + start &= PAGE_MASK; +#if 0 + if (off >= len) { + off -= len; +#endif + /* By Jake Page: Treat mmap request with offset beyond heapstart + * as request for mapping the mmio area + */ + #if 1 + mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + xgi_video_info.heapstart); + if(off >= mmio_off) { + off -= mmio_off; + if(info->var.accel_flags) return -EINVAL; + + start = (unsigned long) xgi_video_info.mmio_base; + len = PAGE_ALIGN((start & ~PAGE_MASK) + XGIfb_mmio_size); + } + start &= PAGE_MASK; + #endif + if((vma->vm_end - vma->vm_start + off) > len) return -EINVAL; + + off += start; + vma->vm_pgoff = off >> PAGE_SHIFT; + vma->vm_flags |= VM_IO; /* by Jake Page; is that really needed? */ + +#if defined(__i386__) || defined(__x86_64__) + if (boot_cpu_data.x86 > 3) + pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; +#endif + if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start, + vma->vm_page_prot)) + return -EAGAIN; + + DEBUGPRN("end of mmap"); + return 0; +} +#endif +static int XGIfb_blank(int blank, struct fb_info *info) +{ + u8 reg; + + inXGIIDXREG(XGICR, 0x17, reg); + + if(blank > 0) + reg &= 0x7f; + else + reg |= 0x80; + + outXGIIDXREG(XGICR, 0x17, reg); + outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */ + outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */ + return(0); +} + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) +static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +#else +static int XGIfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + struct fb_info *info) +#endif + +{ + DEBUGPRN("inside ioctl"); + switch (cmd) { + case FBIO_ALLOC: + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + XGI_malloc((struct XGI_memreq *) arg); + break; + case FBIO_FREE: + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + XGI_free(*(unsigned long *) arg); + break; + case FBIOGET_HWCINFO: + { + unsigned long *hwc_offset = (unsigned long *) arg; + + if (XGIfb_caps & HW_CURSOR_CAP) + *hwc_offset = XGIfb_hwcursor_vbase - + (unsigned long) xgi_video_info.video_vbase; + else + *hwc_offset = 0; + + break; + } + case FBIOPUT_MODEINFO: + { + struct mode_info *x = (struct mode_info *)arg; + + xgi_video_info.video_bpp = x->bpp; + xgi_video_info.video_width = x->xres; + xgi_video_info.video_height = x->yres; + xgi_video_info.video_vwidth = x->v_xres; + xgi_video_info.video_vheight = x->v_yres; + xgi_video_info.org_x = x->org_x; + xgi_video_info.org_y = x->org_y; + xgi_video_info.refresh_rate = x->vrate; + xgi_video_info.video_linelength = xgi_video_info.video_vwidth * (xgi_video_info.video_bpp >> 3); + switch(xgi_video_info.video_bpp) { + case 8: + xgi_video_info.DstColor = 0x0000; + xgi_video_info.XGI310_AccelDepth = 0x00000000; + xgi_video_info.video_cmap_len = 256; + break; + case 16: + xgi_video_info.DstColor = 0x8000; + xgi_video_info.XGI310_AccelDepth = 0x00010000; + xgi_video_info.video_cmap_len = 16; + break; + case 32: + xgi_video_info.DstColor = 0xC000; + xgi_video_info.XGI310_AccelDepth = 0x00020000; + xgi_video_info.video_cmap_len = 16; + break; + default: + xgi_video_info.video_cmap_len = 16; + printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp); + xgi_video_info.accel = 0; + break; + } + + break; + } + case FBIOGET_DISPINFO: + XGI_dispinfo((struct ap_data *)arg); + break; + case XGIFB_GET_INFO: /* TW: New for communication with X driver */ + { + XGIfb_info *x = (XGIfb_info *)arg; + + //x->XGIfb_id = XGIFB_ID; + x->XGIfb_version = VER_MAJOR; + x->XGIfb_revision = VER_MINOR; + x->XGIfb_patchlevel = VER_LEVEL; + x->chip_id = xgi_video_info.chip_id; + x->memory = xgi_video_info.video_size / 1024; + x->heapstart = xgi_video_info.heapstart / 1024; + x->fbvidmode = XGIfb_mode_no; + x->XGIfb_caps = XGIfb_caps; + x->XGIfb_tqlen = 512; /* yet unused */ + x->XGIfb_pcibus = xgi_video_info.pcibus; + x->XGIfb_pcislot = xgi_video_info.pcislot; + x->XGIfb_pcifunc = xgi_video_info.pcifunc; + x->XGIfb_lcdpdc = XGIfb_detectedpdc; + x->XGIfb_lcda = XGIfb_detectedlcda; + break; + } + case XGIFB_GET_VBRSTATUS: + { + unsigned long *vbrstatus = (unsigned long *) arg; + if(XGIfb_CheckVBRetrace()) *vbrstatus = 1; + else *vbrstatus = 0; + } + default: + return -EINVAL; + } + DEBUGPRN("end of ioctl"); + return 0; + +} + + + +/* ----------- FBDev related routines for all series ---------- */ + +static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + DEBUGPRN("inside get_fix"); + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + + strcpy(fix->id, myid); + + fix->smem_start = xgi_video_info.video_base; + + fix->smem_len = xgi_video_info.video_size; + + +/* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) { + if (xgi_video_info.video_size > 0x1000000) { + fix->smem_len = 0xD00000; + } else if (xgi_video_info.video_size > 0x800000) + fix->smem_len = 0x800000; + else + fix->smem_len = 0x400000; + } else + fix->smem_len = XGIfb_mem * 1024; +*/ + fix->type = video_type; + fix->type_aux = 0; + if(xgi_video_info.video_bpp == 8) + fix->visual = FB_VISUAL_PSEUDOCOLOR; + else + fix->visual = FB_VISUAL_DIRECTCOLOR; + fix->xpanstep = 0; +#ifdef XGIFB_PAN + if(XGIfb_ypan) fix->ypanstep = 1; +#endif + fix->ywrapstep = 0; + fix->line_length = xgi_video_info.video_linelength; + fix->mmio_start = xgi_video_info.mmio_base; + fix->mmio_len = XGIfb_mmio_size; + if(xgi_video_info.chip >= XG40) + fix->accel = FB_ACCEL_XGI_XABRE; + else + fix->accel = FB_ACCEL_XGI_GLAMOUR_2; + + + DEBUGPRN("end of get_fix"); + return 0; +} + + +static struct fb_ops XGIfb_ops = { + .owner = THIS_MODULE, + .fb_open = XGIfb_open, + .fb_release = XGIfb_release, + .fb_check_var = XGIfb_check_var, + .fb_set_par = XGIfb_set_par, + .fb_setcolreg = XGIfb_setcolreg, +#ifdef XGIFB_PAN + .fb_pan_display = XGIfb_pan_display, +#endif + .fb_blank = XGIfb_blank, + .fb_fillrect = fbcon_XGI_fillrect, + .fb_copyarea = fbcon_XGI_copyarea, + .fb_imageblit = cfb_imageblit, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) + .fb_cursor = soft_cursor, +#endif + .fb_sync = fbcon_XGI_sync, + .fb_ioctl = XGIfb_ioctl, +// .fb_mmap = XGIfb_mmap, +}; + +/* ---------------- Chip generation dependent routines ---------------- */ + + +/* for XGI 315/550/650/740/330 */ + +static int XGIfb_get_dram_size(void) +{ + + u8 ChannelNum,tmp; + u8 reg = 0; + + /* xorg driver sets 32MB * 1 channel */ + if (xgi_video_info.chip == XG27) + outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51); + + inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg); + switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) { + case XGI_DRAM_SIZE_1MB: + xgi_video_info.video_size = 0x100000; + break; + case XGI_DRAM_SIZE_2MB: + xgi_video_info.video_size = 0x200000; + break; + case XGI_DRAM_SIZE_4MB: + xgi_video_info.video_size = 0x400000; + break; + case XGI_DRAM_SIZE_8MB: + xgi_video_info.video_size = 0x800000; + break; + case XGI_DRAM_SIZE_16MB: + xgi_video_info.video_size = 0x1000000; + break; + case XGI_DRAM_SIZE_32MB: + xgi_video_info.video_size = 0x2000000; + break; + case XGI_DRAM_SIZE_64MB: + xgi_video_info.video_size = 0x4000000; + break; + case XGI_DRAM_SIZE_128MB: + xgi_video_info.video_size = 0x8000000; + break; + case XGI_DRAM_SIZE_256MB: + xgi_video_info.video_size = 0x10000000; + break; + default: + return -1; + } + + tmp = (reg & 0x0c) >> 2; + switch(xgi_video_info.chip) + { + case XG20: + case XG21: + case XG27: + ChannelNum = 1; + break; + + case XG42: + if(reg & 0x04) + ChannelNum = 2; + else + ChannelNum = 1; + break; + + case XG45: + if(tmp == 1) + ChannelNum = 2; + else + if(tmp == 2) + ChannelNum = 3; + else + if(tmp == 3) + ChannelNum = 4; + else + ChannelNum = 1; + break; + + case XG40: + default: + if(tmp == 2) + ChannelNum = 2; + else + if(tmp == 3) + ChannelNum = 3; + else + ChannelNum = 1; + break; + } + + + xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum; + //PLiad fixed for benchmarking and fb set + //xgi_video_info.video_size = 0x200000;//1024x768x16 + //xgi_video_info.video_size = 0x1000000;//benchmark + + printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",reg,xgi_video_info.video_size ,ChannelNum ); + return 0; + +} + +static void XGIfb_detect_VB(void) +{ + u8 cr32, temp=0; + + xgi_video_info.TV_plug = xgi_video_info.TV_type = 0; + + switch(xgi_video_info.hasVB) { + case HASVB_LVDS_CHRONTEL: + case HASVB_CHRONTEL: + break; + case HASVB_301: + case HASVB_302: +// XGI_Sense30x(); //Yi-Lin TV Sense? + break; + } + + inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32); + + if ((cr32 & XGI_CRT1) && !XGIfb_crt1off) + XGIfb_crt1off = 0; + else { + if (cr32 & 0x5F) + XGIfb_crt1off = 1; + else + XGIfb_crt1off = 0; + } + + if (XGIfb_crt2type != -1) + /* TW: Override with option */ + xgi_video_info.disp_state = XGIfb_crt2type; + else if (cr32 & XGI_VB_TV) + xgi_video_info.disp_state = DISPTYPE_TV; + else if (cr32 & XGI_VB_LCD) + xgi_video_info.disp_state = DISPTYPE_LCD; + else if (cr32 & XGI_VB_CRT2) + xgi_video_info.disp_state = DISPTYPE_CRT2; + else + xgi_video_info.disp_state = 0; + + if(XGIfb_tvplug != -1) + /* PR/TW: Override with option */ + xgi_video_info.TV_plug = XGIfb_tvplug; + else if (cr32 & XGI_VB_HIVISION) { + xgi_video_info.TV_type = TVMODE_HIVISION; + xgi_video_info.TV_plug = TVPLUG_SVIDEO; + } + else if (cr32 & XGI_VB_SVIDEO) + xgi_video_info.TV_plug = TVPLUG_SVIDEO; + else if (cr32 & XGI_VB_COMPOSITE) + xgi_video_info.TV_plug = TVPLUG_COMPOSITE; + else if (cr32 & XGI_VB_SCART) + xgi_video_info.TV_plug = TVPLUG_SCART; + + if(xgi_video_info.TV_type == 0) { + /* TW: PAL/NTSC changed for 650 */ + if((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip >= XGI_330)) { + + inXGIIDXREG(XGICR, 0x38, temp); + if(temp & 0x10) + xgi_video_info.TV_type = TVMODE_PAL; + else + xgi_video_info.TV_type = TVMODE_NTSC; + + } else { + + inXGIIDXREG(XGICR, 0x79, temp); + if(temp & 0x20) + xgi_video_info.TV_type = TVMODE_PAL; + else + xgi_video_info.TV_type = TVMODE_NTSC; + } + } + + /* TW: Copy forceCRT1 option to CRT1off if option is given */ + if (XGIfb_forcecrt1 != -1) { + if (XGIfb_forcecrt1) XGIfb_crt1off = 0; + else XGIfb_crt1off = 1; + } +} + +static void XGIfb_get_VB_type(void) +{ + u8 reg; + + if (!XGIfb_has_VB()) { + inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg); + switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) { + case XGI310_EXTERNAL_CHIP_LVDS: + xgi_video_info.hasVB = HASVB_LVDS; + break; + case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL: + xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL; + break; + default: + break; + } + } +} + + +static int XGIfb_has_VB(void) +{ + u8 vb_chipid; + + inXGIIDXREG(XGIPART4, 0x00, vb_chipid); + switch (vb_chipid) { + case 0x01: + xgi_video_info.hasVB = HASVB_301; + break; + case 0x02: + xgi_video_info.hasVB = HASVB_302; + break; + default: + xgi_video_info.hasVB = HASVB_NONE; + return FALSE; + } + return TRUE; +} + + + +/* ------------------ Sensing routines ------------------ */ + +/* TW: Determine and detect attached devices on XGI30x */ +int +XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch) +{ + int temp,i; + + outXGIIDXREG(XGIPART4,0x11,tempbl); + temp = tempbh | tempcl; + setXGIIDXREG(XGIPART4,0x10,0xe0,temp); + for(i=0; i<10; i++) XGI_LongWait(&XGI_Pr); + tempch &= 0x7f; + inXGIIDXREG(XGIPART4,0x03,temp); + temp ^= 0x0e; + temp &= tempch; + return(temp); +} + +void +XGI_Sense30x(void) +{ + u8 backupP4_0d; + u8 testsvhs_tempbl, testsvhs_tempbh; + u8 testsvhs_tempcl, testsvhs_tempch; + u8 testcvbs_tempbl, testcvbs_tempbh; + u8 testcvbs_tempcl, testcvbs_tempch; + u8 testvga2_tempbl, testvga2_tempbh; + u8 testvga2_tempcl, testvga2_tempch; + int myflag, result; + + inXGIIDXREG(XGIPART4,0x0d,backupP4_0d); + outXGIIDXREG(XGIPART4,0x0d,(backupP4_0d | 0x04)); + + + + testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1; + testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9; + testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3; + if((XGIhw_ext.ujVBChipID != VB_CHIP_301) && + (XGIhw_ext.ujVBChipID != VB_CHIP_302)) { + testvga2_tempbh = 0x01; testvga2_tempbl = 0x90; + testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b; + testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74; + if(XGIhw_ext.ujVBChipID == VB_CHIP_301LV || + XGIhw_ext.ujVBChipID == VB_CHIP_302LV) { + testvga2_tempbh = 0x00; testvga2_tempbl = 0x00; + testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00; + testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00; + } + } + if(XGIhw_ext.ujVBChipID != VB_CHIP_301LV && + XGIhw_ext.ujVBChipID != VB_CHIP_302LV) { + inXGIIDXREG(XGIPART4,0x01,myflag); + if(myflag & 0x04) { + testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd; + testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd; + testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee; + } + } + if((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) || + (XGIhw_ext.ujVBChipID == VB_CHIP_302LV) ) { + testvga2_tempbh = 0x00; testvga2_tempbl = 0x00; + testvga2_tempch = 0x00; testvga2_tempcl = 0x00; + testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08; + testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08; + } else { + testvga2_tempch = 0x0e; testvga2_tempcl = 0x08; + testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04; + testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04; + } + + + if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) { + result = XGIDoSense(testvga2_tempbl, testvga2_tempbh, + testvga2_tempcl, testvga2_tempch); + if(result) { + printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n"); + orXGIIDXREG(XGICR, 0x32, 0x10); + } + } + + result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh, + testsvhs_tempcl, testsvhs_tempch); + if(result) { + printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n"); + /* TW: So we can be sure that there IS a SVHS output */ + xgi_video_info.TV_plug = TVPLUG_SVIDEO; + orXGIIDXREG(XGICR, 0x32, 0x02); + } + + if(!result) { + result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh, + testcvbs_tempcl, testcvbs_tempch); + if(result) { + printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n"); + /* TW: So we can be sure that there IS a CVBS output */ + xgi_video_info.TV_plug = TVPLUG_COMPOSITE; + orXGIIDXREG(XGICR, 0x32, 0x01); + } + } + XGIDoSense(0, 0, 0, 0); + + outXGIIDXREG(XGIPART4,0x0d,backupP4_0d); +} + + + +/* ------------------------ Heap routines -------------------------- */ + +static int XGIfb_heap_init(void) +{ + XGI_OH *poh; + u8 temp=0; + + int agp_enabled = 1; + u32 agp_size; + unsigned long *cmdq_baseport = 0; + unsigned long *read_port = 0; + unsigned long *write_port = 0; + XGI_CMDTYPE cmd_type; +#ifndef AGPOFF + struct agp_kern_info *agp_info; + struct agp_memory *agp; + u32 agp_phys; +#endif + +/* TW: The heap start is either set manually using the "mem" parameter, or + * defaults as follows: + * -) If more than 16MB videoRAM available, let our heap start at 12MB. + * -) If more than 8MB videoRAM available, let our heap start at 8MB. + * -) If 4MB or less is available, let it start at 4MB. + * This is for avoiding a clash with X driver which uses the beginning + * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem + * in XF86Config-4. + * The heap start can also be specified by parameter "mem" when starting the XGIfb + * driver. XGIfb mem=1024 lets heap starts at 1MB, etc. + */ + if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) { + if (xgi_video_info.video_size > 0x1000000) { + xgi_video_info.heapstart = 0xD00000; + } else if (xgi_video_info.video_size > 0x800000) { + xgi_video_info.heapstart = 0x800000; + } else { + xgi_video_info.heapstart = 0x400000; + } + } else { + xgi_video_info.heapstart = XGIfb_mem * 1024; + } + XGIfb_heap_start = + (unsigned long) (xgi_video_info.video_vbase + xgi_video_info.heapstart); + printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n", + (int)(xgi_video_info.heapstart / 1024)); + + XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase + xgi_video_info.video_size; + XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start; + + + + /* TW: Now initialize the 310 series' command queue mode. + * On 310/325, there are three queue modes available which + * are chosen by setting bits 7:5 in SR26: + * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep + * track of the queue, the FIFO, command parsing and so + * on. This is the one comparable to the 300 series. + * 2. VRAM queue mode (bit 6, 0x40). In this case, one will + * have to do queue management himself. Register 0x85c4 will + * hold the location of the next free queue slot, 0x85c8 + * is the "queue read pointer" whose way of working is + * unknown to me. Anyway, this mode would require a + * translation of the MMIO commands to some kind of + * accelerator assembly and writing these commands + * to the memory location pointed to by 0x85c4. + * We will not use this, as nobody knows how this + * "assembly" works, and as it would require a complete + * re-write of the accelerator code. + * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the + * queue in AGP memory space. + * + * SR26 bit 4 is called "Bypass H/W queue". + * SR26 bit 1 is called "Enable Command Queue Auto Correction" + * SR26 bit 0 resets the queue + * Size of queue memory is encoded in bits 3:2 like this: + * 00 (0x00) 512K + * 01 (0x04) 1M + * 10 (0x08) 2M + * 11 (0x0C) 4M + * The queue location is to be written to 0x85C0. + * + */ + cmdq_baseport = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_PHYBASE); + write_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_WRITEPORT); + read_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_READPORT); + + DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port); + + agp_size = COMMAND_QUEUE_AREA_SIZE; + +#ifndef AGPOFF + if (XGIfb_queuemode == AGP_CMD_QUEUE) { + agp_info = vmalloc(sizeof(*agp_info)); + memset((void*)agp_info, 0x00, sizeof(*agp_info)); + agp_copy_info(agp_info); + + agp_backend_acquire(); + + agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE, + AGP_NORMAL_MEMORY); + if (agp == NULL) { + DPRINTK("XGIfb: Allocating AGP buffer failed.\n"); + agp_enabled = 0; + } else { + if (agp_bind_memory(agp, agp->pg_start) != 0) { + DPRINTK("XGIfb: AGP: Failed to bind memory\n"); + /* TODO: Free AGP memory here */ + agp_enabled = 0; + } else { + agp_enable(0); + } + } + } +#else + agp_enabled = 0; +#endif + + /* TW: Now select the queue mode */ + + if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) { + cmd_type = AGP_CMD_QUEUE; + printk(KERN_INFO "XGIfb: Using AGP queue mode\n"); +/* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */ + } else if (XGIfb_queuemode == VM_CMD_QUEUE) { + cmd_type = VM_CMD_QUEUE; + printk(KERN_INFO "XGIfb: Using VRAM queue mode\n"); + } else { + printk(KERN_INFO "XGIfb: Using MMIO queue mode\n"); + cmd_type = MMIO_CMD; + } + + switch (agp_size) { + case 0x80000: + temp = XGI_CMD_QUEUE_SIZE_512k; + break; + case 0x100000: + temp = XGI_CMD_QUEUE_SIZE_1M; + break; + case 0x200000: + temp = XGI_CMD_QUEUE_SIZE_2M; + break; + case 0x400000: + temp = XGI_CMD_QUEUE_SIZE_4M; + break; + } + + switch (cmd_type) { + case AGP_CMD_QUEUE: +#ifndef AGPOFF + DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n", + agp_info->aper_base, agp->physical, agp_size/1024); + + agp_phys = agp_info->aper_base + agp->physical; + + outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0); + outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X); + + outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); + + outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET); + + *write_port = *read_port; + + temp |= XGI_AGP_CMDQUEUE_ENABLE; + outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp); + + *cmdq_baseport = agp_phys; + + XGIfb_caps |= AGP_CMD_QUEUE_CAP; +#endif + break; + + case VM_CMD_QUEUE: + XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE; + XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE; + + outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); + + outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET); + + *write_port = *read_port; + + temp |= XGI_VRAM_CMDQUEUE_ENABLE; + outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp); + + *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE; + + XGIfb_caps |= VM_CMD_QUEUE_CAP; + + DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n", + *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024); + break; + + default: /* MMIO */ + +// printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__); + /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE + * to IND_XGI_CMDQUEUE_SET. I doubt that this is + * enough. Reserve memory in any way. + */ +// FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE; +// FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE; +// FIXME +// FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); +// FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET); +// FIXME +// FIXME *write_port = *read_port; +// FIXME +// FIXME /* TW: Set Auto_Correction bit */ +// FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR); +// FIXME // FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp); +// FIXME +// FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE; +// FIXME +// FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP; +// FIXME +// FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n", +// FIXME *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024); + break; + } + + + + + /* TW: Now reserve memory for the HWCursor. It is always located at the very + top of the videoRAM, right below the TB memory area (if used). */ + if (XGIfb_heap_size >= XGIfb_hwcursor_size) { + XGIfb_heap_end -= XGIfb_hwcursor_size; + XGIfb_heap_size -= XGIfb_hwcursor_size; + XGIfb_hwcursor_vbase = XGIfb_heap_end; + + XGIfb_caps |= HW_CURSOR_CAP; + + DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n", + XGIfb_heap_end, XGIfb_hwcursor_size/1024); + } + + XGIfb_heap.poha_chain = NULL; + XGIfb_heap.poh_freelist = NULL; + + poh = XGIfb_poh_new_node(); + + if(poh == NULL) return 1; + + poh->poh_next = &XGIfb_heap.oh_free; + poh->poh_prev = &XGIfb_heap.oh_free; + poh->size = XGIfb_heap_end - XGIfb_heap_start + 1; + poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase; + + DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n", + (char *) XGIfb_heap_start, (char *) XGIfb_heap_end, + (unsigned int) poh->size / 1024); + + DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n", + (unsigned int) poh->offset, (unsigned int) poh->size / 1024); + + XGIfb_heap.oh_free.poh_next = poh; + XGIfb_heap.oh_free.poh_prev = poh; + XGIfb_heap.oh_free.size = 0; + XGIfb_heap.max_freesize = poh->size; + + XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used; + XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used; + XGIfb_heap.oh_used.size = SENTINEL; + + return 0; +} + +static XGI_OH *XGIfb_poh_new_node(void) +{ + int i; + unsigned long cOhs; + XGI_OHALLOC *poha; + XGI_OH *poh; + + if (XGIfb_heap.poh_freelist == NULL) { + poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL); + if(!poha) return NULL; + + poha->poha_next = XGIfb_heap.poha_chain; + XGIfb_heap.poha_chain = poha; + + cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH) + 1; + + poh = &poha->aoh[0]; + for (i = cOhs - 1; i != 0; i--) { + poh->poh_next = poh + 1; + poh = poh + 1; + } + + poh->poh_next = NULL; + XGIfb_heap.poh_freelist = &poha->aoh[0]; + } + + poh = XGIfb_heap.poh_freelist; + XGIfb_heap.poh_freelist = poh->poh_next; + + return (poh); +} + +static XGI_OH *XGIfb_poh_allocate(unsigned long size) +{ + XGI_OH *pohThis; + XGI_OH *pohRoot; + int bAllocated = 0; + + if (size > XGIfb_heap.max_freesize) { + DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n", + (unsigned int) size / 1024); + return (NULL); + } + + pohThis = XGIfb_heap.oh_free.poh_next; + + while (pohThis != &XGIfb_heap.oh_free) { + if (size <= pohThis->size) { + bAllocated = 1; + break; + } + pohThis = pohThis->poh_next; + } + + if (!bAllocated) { + DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n", + (unsigned int) size / 1024); + return (NULL); + } + + if (size == pohThis->size) { + pohRoot = pohThis; + XGIfb_delete_node(pohThis); + } else { + pohRoot = XGIfb_poh_new_node(); + + if (pohRoot == NULL) { + return (NULL); + } + + pohRoot->offset = pohThis->offset; + pohRoot->size = size; + + pohThis->offset += size; + pohThis->size -= size; + } + + XGIfb_heap.max_freesize -= size; + + pohThis = &XGIfb_heap.oh_used; + XGIfb_insert_node(pohThis, pohRoot); + + return (pohRoot); +} + +static void XGIfb_delete_node(XGI_OH *poh) +{ + XGI_OH *poh_prev; + XGI_OH *poh_next; + + poh_prev = poh->poh_prev; + poh_next = poh->poh_next; + + poh_prev->poh_next = poh_next; + poh_next->poh_prev = poh_prev; + +} + +static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh) +{ + XGI_OH *pohTemp; + + pohTemp = pohList->poh_next; + + pohList->poh_next = poh; + pohTemp->poh_prev = poh; + + poh->poh_prev = pohList; + poh->poh_next = pohTemp; +} + +static XGI_OH *XGIfb_poh_free(unsigned long base) +{ + XGI_OH *pohThis; + XGI_OH *poh_freed; + XGI_OH *poh_prev; + XGI_OH *poh_next; + unsigned long ulUpper; + unsigned long ulLower; + int foundNode = 0; + + poh_freed = XGIfb_heap.oh_used.poh_next; + + while(poh_freed != &XGIfb_heap.oh_used) { + if(poh_freed->offset == base) { + foundNode = 1; + break; + } + + poh_freed = poh_freed->poh_next; + } + + if (!foundNode) return (NULL); + + XGIfb_heap.max_freesize += poh_freed->size; + + poh_prev = poh_next = NULL; + ulUpper = poh_freed->offset + poh_freed->size; + ulLower = poh_freed->offset; + + pohThis = XGIfb_heap.oh_free.poh_next; + + while (pohThis != &XGIfb_heap.oh_free) { + if (pohThis->offset == ulUpper) { + poh_next = pohThis; + } + else if ((pohThis->offset + pohThis->size) == + ulLower) { + poh_prev = pohThis; + } + pohThis = pohThis->poh_next; + } + + XGIfb_delete_node(poh_freed); + + if (poh_prev && poh_next) { + poh_prev->size += (poh_freed->size + poh_next->size); + XGIfb_delete_node(poh_next); + XGIfb_free_node(poh_freed); + XGIfb_free_node(poh_next); + return (poh_prev); + } + + if (poh_prev) { + poh_prev->size += poh_freed->size; + XGIfb_free_node(poh_freed); + return (poh_prev); + } + + if (poh_next) { + poh_next->size += poh_freed->size; + poh_next->offset = poh_freed->offset; + XGIfb_free_node(poh_freed); + return (poh_next); + } + + XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed); + + return (poh_freed); +} + +static void XGIfb_free_node(XGI_OH *poh) +{ + if(poh == NULL) return; + + poh->poh_next = XGIfb_heap.poh_freelist; + XGIfb_heap.poh_freelist = poh; + +} + +void XGI_malloc(struct XGI_memreq *req) +{ + XGI_OH *poh; + + poh = XGIfb_poh_allocate(req->size); + + if(poh == NULL) { + req->offset = 0; + req->size = 0; + DPRINTK("XGIfb: Video RAM allocation failed\n"); + } else { + DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n", + (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase)); + + req->offset = poh->offset; + req->size = poh->size; + } + +} + +void XGI_free(unsigned long base) +{ + XGI_OH *poh; + + poh = XGIfb_poh_free(base); + + if(poh == NULL) { + DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n", + (unsigned int) base); + } +} + +/* --------------------- SetMode routines ------------------------- */ + +static void XGIfb_pre_setmode(void) +{ + u8 cr30 = 0, cr31 = 0; + + inXGIIDXREG(XGICR, 0x31, cr31); + cr31 &= ~0x60; + + switch (xgi_video_info.disp_state & DISPTYPE_DISP2) { + case DISPTYPE_CRT2: + cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE); + cr31 |= XGI_DRIVER_MODE; + break; + case DISPTYPE_LCD: + cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE); + cr31 |= XGI_DRIVER_MODE; + break; + case DISPTYPE_TV: + if (xgi_video_info.TV_type == TVMODE_HIVISION) + cr30 = (XGI_VB_OUTPUT_HIVISION | XGI_SIMULTANEOUS_VIEW_ENABLE); + else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) + cr30 = (XGI_VB_OUTPUT_SVIDEO | XGI_SIMULTANEOUS_VIEW_ENABLE); + else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) + cr30 = (XGI_VB_OUTPUT_COMPOSITE | XGI_SIMULTANEOUS_VIEW_ENABLE); + else if (xgi_video_info.TV_plug == TVPLUG_SCART) + cr30 = (XGI_VB_OUTPUT_SCART | XGI_SIMULTANEOUS_VIEW_ENABLE); + cr31 |= XGI_DRIVER_MODE; + + if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL) + cr31 |= 0x01; + else + cr31 &= ~0x01; + break; + default: /* disable CRT2 */ + cr30 = 0x00; + cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE); + } + + outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30); + outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31); + outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F)); + + if(xgi_video_info.accel) XGIfb_syncaccel(); + + +} + +static void XGIfb_post_setmode(void) +{ + u8 reg; + BOOLEAN doit = TRUE; +#if 0 /* TW: Wrong: Is not in MMIO space, but in RAM */ + /* Backup mode number to MMIO space */ + if(xgi_video_info.mmio_vbase) { + *(volatile u8 *)(((u8*)xgi_video_info.mmio_vbase) + 0x449) = (unsigned char)XGIfb_mode_no; + } +#endif +/* outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD); + outXGIIDXREG(XGICR,0x13,0x00); + setXGIIDXREG(XGISR,0x0E,0xF0,0x01); +*test**/ + if (xgi_video_info.video_bpp == 8) { + /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */ + if ((xgi_video_info.hasVB == HASVB_LVDS) || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) { + doit = FALSE; + } + /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */ + if (xgi_video_info.disp_state & DISPTYPE_LCD) { + doit = FALSE; + } + } + + /* TW: We can't switch off CRT1 if bridge is in slave mode */ + if(xgi_video_info.hasVB != HASVB_NONE) { + inXGIIDXREG(XGIPART1, 0x00, reg); + + + if((reg & 0x50) == 0x10) { + doit = FALSE; + } + + } else XGIfb_crt1off = 0; + + inXGIIDXREG(XGICR, 0x17, reg); + if((XGIfb_crt1off) && (doit)) + reg &= ~0x80; + else + reg |= 0x80; + outXGIIDXREG(XGICR, 0x17, reg); + + andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04); + + if((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB == HASVB_301)) { + + inXGIIDXREG(XGIPART4, 0x01, reg); + + if(reg < 0xB0) { /* Set filter for XGI301 */ + + switch (xgi_video_info.video_width) { + case 320: + filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12; + break; + case 640: + filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13; + break; + case 720: + filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14; + break; + case 800: + filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15; + break; + default: + filter = -1; + break; + } + + orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01); + + if(xgi_video_info.TV_type == TVMODE_NTSC) { + + andXGIIDXREG(XGIPART2, 0x3a, 0x1f); + + if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) { + + andXGIIDXREG(XGIPART2, 0x30, 0xdf); + + } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) { + + orXGIIDXREG(XGIPART2, 0x30, 0x20); + + switch (xgi_video_info.video_width) { + case 640: + outXGIIDXREG(XGIPART2, 0x35, 0xEB); + outXGIIDXREG(XGIPART2, 0x36, 0x04); + outXGIIDXREG(XGIPART2, 0x37, 0x25); + outXGIIDXREG(XGIPART2, 0x38, 0x18); + break; + case 720: + outXGIIDXREG(XGIPART2, 0x35, 0xEE); + outXGIIDXREG(XGIPART2, 0x36, 0x0C); + outXGIIDXREG(XGIPART2, 0x37, 0x22); + outXGIIDXREG(XGIPART2, 0x38, 0x08); + break; + case 800: + outXGIIDXREG(XGIPART2, 0x35, 0xEB); + outXGIIDXREG(XGIPART2, 0x36, 0x15); + outXGIIDXREG(XGIPART2, 0x37, 0x25); + outXGIIDXREG(XGIPART2, 0x38, 0xF6); + break; + } + } + + } else if(xgi_video_info.TV_type == TVMODE_PAL) { + + andXGIIDXREG(XGIPART2, 0x3A, 0x1F); + + if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) { + + andXGIIDXREG(XGIPART2, 0x30, 0xDF); + + } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) { + + orXGIIDXREG(XGIPART2, 0x30, 0x20); + + switch (xgi_video_info.video_width) { + case 640: + outXGIIDXREG(XGIPART2, 0x35, 0xF1); + outXGIIDXREG(XGIPART2, 0x36, 0xF7); + outXGIIDXREG(XGIPART2, 0x37, 0x1F); + outXGIIDXREG(XGIPART2, 0x38, 0x32); + break; + case 720: + outXGIIDXREG(XGIPART2, 0x35, 0xF3); + outXGIIDXREG(XGIPART2, 0x36, 0x00); + outXGIIDXREG(XGIPART2, 0x37, 0x1D); + outXGIIDXREG(XGIPART2, 0x38, 0x20); + break; + case 800: + outXGIIDXREG(XGIPART2, 0x35, 0xFC); + outXGIIDXREG(XGIPART2, 0x36, 0xFB); + outXGIIDXREG(XGIPART2, 0x37, 0x14); + outXGIIDXREG(XGIPART2, 0x38, 0x2A); + break; + } + } + } + + if ((filter >= 0) && (filter <=7)) { + DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter, + XGI_TV_filter[filter_tb].filter[filter][0], + XGI_TV_filter[filter_tb].filter[filter][1], + XGI_TV_filter[filter_tb].filter[filter][2], + XGI_TV_filter[filter_tb].filter[filter][3] + ); + outXGIIDXREG(XGIPART2, 0x35, (XGI_TV_filter[filter_tb].filter[filter][0])); + outXGIIDXREG(XGIPART2, 0x36, (XGI_TV_filter[filter_tb].filter[filter][1])); + outXGIIDXREG(XGIPART2, 0x37, (XGI_TV_filter[filter_tb].filter[filter][2])); + outXGIIDXREG(XGIPART2, 0x38, (XGI_TV_filter[filter_tb].filter[filter][3])); + } + + } + + } + +} + +#ifndef MODULE +XGIINITSTATIC int __init XGIfb_setup(char *options) +{ + char *this_opt; + + + + xgi_video_info.refresh_rate = 0; + + printk(KERN_INFO "XGIfb: Options %s\n", options); + + if (!options || !*options) + return 0; + + while((this_opt = strsep(&options, ",")) != NULL) { + + if (!*this_opt) continue; + + if (!strncmp(this_opt, "mode:", 5)) { + XGIfb_search_mode(this_opt + 5); + } else if (!strncmp(this_opt, "vesa:", 5)) { + XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0)); + } else if (!strncmp(this_opt, "mode:", 5)) { + XGIfb_search_mode(this_opt + 5); + } else if (!strncmp(this_opt, "vesa:", 5)) { + XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0)); + } else if (!strncmp(this_opt, "vrate:", 6)) { + xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0); + } else if (!strncmp(this_opt, "rate:", 5)) { + xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0); + } else if (!strncmp(this_opt, "off", 3)) { + XGIfb_off = 1; + } else if (!strncmp(this_opt, "crt1off", 7)) { + XGIfb_crt1off = 1; + } else if (!strncmp(this_opt, "filter:", 7)) { + filter = (int)simple_strtoul(this_opt + 7, NULL, 0); + } else if (!strncmp(this_opt, "forcecrt2type:", 14)) { + XGIfb_search_crt2type(this_opt + 14); + } else if (!strncmp(this_opt, "forcecrt1:", 10)) { + XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0); + } else if (!strncmp(this_opt, "tvmode:",7)) { + XGIfb_search_tvstd(this_opt + 7); + } else if (!strncmp(this_opt, "tvstandard:",11)) { + XGIfb_search_tvstd(this_opt + 7); + } else if (!strncmp(this_opt, "mem:",4)) { + XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0); + } else if (!strncmp(this_opt, "dstn", 4)) { + enable_dstn = 1; + /* TW: DSTN overrules forcecrt2type */ + XGIfb_crt2type = DISPTYPE_LCD; + } else if (!strncmp(this_opt, "queuemode:", 10)) { + XGIfb_search_queuemode(this_opt + 10); + } else if (!strncmp(this_opt, "pdc:", 4)) { + XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0); + if(XGIfb_pdc & ~0x3c) { + printk(KERN_INFO "XGIfb: Illegal pdc parameter\n"); + XGIfb_pdc = 0; + } + } else if (!strncmp(this_opt, "noaccel", 7)) { + XGIfb_accel = 0; + } else if (!strncmp(this_opt, "noypan", 6)) { + XGIfb_ypan = 0; + } else if (!strncmp(this_opt, "userom:", 7)) { + XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0); +// } else if (!strncmp(this_opt, "useoem:", 7)) { +// XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); + } else { + XGIfb_search_mode(this_opt); +// printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt); + } + + /* TW: Acceleration only with MMIO mode */ + if((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) { + XGIfb_ypan = 0; + XGIfb_accel = 0; + } + /* TW: Panning only with acceleration */ + if(XGIfb_accel == 0) XGIfb_ypan = 0; + + } + printk("\nxgifb: outa xgifb_setup 3450"); + return 0; +} +#endif + +static unsigned char VBIOS_BUF[65535]; + +unsigned char* attempt_map_rom(struct pci_dev *dev,void *copy_address) +{ + u32 rom_size = 0; + u32 rom_address = 0; + int j; + + /* Get the size of the expansion rom */ + pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF); + pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size); + if ((rom_size & 0x01) == 0) + { + printk("No ROM\n"); + return NULL; + } + + rom_size &= 0xFFFFF800; + rom_size = (~rom_size)+1; + + rom_address = pci_resource_start(dev, 0); + if (rom_address == 0 || rom_address == 0xFFFFFFF0) + { + printk("No suitable rom address found\n"); return NULL; + } + + printk("ROM Size is %dK, Address is %x\n", rom_size/1024, rom_address); + + /* Map ROM */ + pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address | PCI_ROM_ADDRESS_ENABLE); + + /* memcpy(copy_address, rom_address, rom_size); */ + { + unsigned char *virt_addr = ioremap(rom_address, 0x8000000); + + unsigned char *from = (unsigned char *)virt_addr; + unsigned char *to = (unsigned char *)copy_address; + for (j=0; j<65536 /*rom_size*/; j++) *to++ = *from++; + } + + pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0); + + printk("Copy is done\n"); + + return copy_address; +} + +int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + u16 reg16; + u8 reg, reg1; + u8 CR48,CR38; + if (XGIfb_off) + return -ENXIO; + + XGIfb_registered = 0; + + memset(&XGIhw_ext, 0, sizeof(HW_DEVICE_EXTENSION)); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3)) + fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev); + if(!fb_info) return -ENOMEM; +#else + XGI_fb_info = kmalloc( sizeof(struct fb_info), GFP_KERNEL); + if(!XGI_fb_info) return -ENOMEM; + memset(XGI_fb_info, 0, sizeof(struct fb_info)); +#endif + + xgi_video_info.chip_id = pdev->device; + pci_read_config_byte(pdev, PCI_REVISION_ID,&xgi_video_info.revision_id); + pci_read_config_word(pdev, PCI_COMMAND, ®16); + XGIhw_ext.jChipRevision = xgi_video_info.revision_id; + XGIvga_enabled = reg16 & 0x01; + + xgi_video_info.pcibus = pdev->bus->number; + xgi_video_info.pcislot = PCI_SLOT(pdev->devfn); + xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn); + xgi_video_info.subsysvendor = pdev->subsystem_vendor; + xgi_video_info.subsysdevice = pdev->subsystem_device; + + xgi_video_info.video_base = pci_resource_start(pdev, 0); + xgi_video_info.mmio_base = pci_resource_start(pdev, 1); + XGIfb_mmio_size = pci_resource_len(pdev, 1); + xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30; + XGIhw_ext.pjIOAddress = (PUCHAR)xgi_video_info.vga_base; + //XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; + printk("XGIfb: Relocate IO address: %lx [%08lx] \n", (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO); + + if (pci_enable_device(pdev)) + return -EIO; + + XGIRegInit(&XGI_Pr, (ULONG)XGIhw_ext.pjIOAddress); + + outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD); + inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1); + + if(reg1 != 0xa1) /*I/O error */ + { + printk("\nXGIfb: I/O error!!!"); + return -EIO; + } + + switch (xgi_video_info.chip_id) { + case PCI_DEVICE_ID_XG_20: + orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN); + inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48); + if (CR48&GPIOG_READ) + xgi_video_info.chip = XG21; + else + xgi_video_info.chip = XG20; + XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2; + XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315; + break; + case PCI_DEVICE_ID_XG_40: + xgi_video_info.chip = XG40; + XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2; + XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315; + break; + case PCI_DEVICE_ID_XG_41: + xgi_video_info.chip = XG41; + XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2; + XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315; + break; + case PCI_DEVICE_ID_XG_42: + xgi_video_info.chip = XG42; + XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2; + XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315; + break; + case PCI_DEVICE_ID_XG_27: + xgi_video_info.chip = XG27; + XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2; + XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315; + break; + default: + return -ENODEV; + } + + printk("XGIfb:chipid = %x\n",xgi_video_info.chip); + XGIhw_ext.jChipType = xgi_video_info.chip; + + switch (xgi_video_info.chip) { + case XG40: + case XG41: + case XG42: + case XG45: + case XG20: + case XG21: + case XG27: + XGIhw_ext.bIntegratedMMEnabled = TRUE; + break; + + default: + break; + } + + + XGIhw_ext.pDevice = NULL; + if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) + { + XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF); + + if(XGIhw_ext.pjVirtualRomBase) + printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",XGIhw_ext.pjVirtualRomBase); + else + printk(KERN_INFO "XGIfb: Video ROM not found\n"); + } else { + XGIhw_ext.pjVirtualRomBase = NULL; + printk(KERN_INFO "XGIfb: Video ROM usage disabled\n"); + } + XGIhw_ext.pjCustomizedROMImage = NULL; + XGIhw_ext.bSkipDramSizing = 0; + XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space; +// XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space; + strcpy(XGIhw_ext.szVBIOSVer, "0.84"); + + + XGIhw_ext.pSR = vmalloc(sizeof(XGI_DSReg) * SR_BUFFER_SIZE); + if (XGIhw_ext.pSR == NULL) + { + printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n"); + return -ENODEV; + } + XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF; + + XGIhw_ext.pCR = vmalloc(sizeof(XGI_DSReg) * CR_BUFFER_SIZE); + if (XGIhw_ext.pCR == NULL) + { + vfree(XGIhw_ext.pSR); + printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n"); + return -ENODEV; + } + XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF; + + + + + if (!XGIvga_enabled) + { + /* Mapping Max FB Size for 315 Init */ + XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000); + if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) + { +#ifdef LINUXBIOS + printk("XGIfb: XGIInit() ..."); + /* XGIInitNewt for LINUXBIOS only */ + if(XGIInitNew(&XGIhw_ext)) + { + printk("OK\n"); + } + else + { + printk("Fail\n"); + } +#endif + + outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD); + + + } + } +#ifdef LINUXBIOS + else + { + XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000); + if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) + { + + outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD); + + // yilin Because no VBIOS DRAM Sizing, Dram size will error. + // Set SR13 ,14 temporarily for UDtech + outXGIIDXREG(XGISR, 0x13, 0x45); + outXGIIDXREG(XGISR, 0x14, 0x51); + + + } + } +#endif + if (XGIfb_get_dram_size()) + { + vfree(XGIhw_ext.pSR); + vfree(XGIhw_ext.pCR); + printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n"); + return -ENODEV; + } + + + + if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) + { + /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ + orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE)); + /* Enable 2D accelerator engine */ + orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D); + } + + XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size; + + if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB")) + { printk("unable request memory size %x",xgi_video_info.video_size); + printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n"); + printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n"); + vfree(XGIhw_ext.pSR); + vfree(XGIhw_ext.pCR); + return -ENODEV; + } + + if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO")) + { + printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n"); + release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size); + vfree(XGIhw_ext.pSR); + vfree(XGIhw_ext.pCR); + return -ENODEV; + } + + xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress = + ioremap(xgi_video_info.video_base, xgi_video_info.video_size); + xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size); + + printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n", + xgi_video_info.video_base, xgi_video_info.video_vbase,xgi_video_info.video_size / 1024); + + printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n", + xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,XGIfb_mmio_size / 1024); + printk("XGIfb: XGIInitNew() ..."); + if(XGIInitNew(&XGIhw_ext)) + { + printk("OK\n"); + } + else + { + printk("Fail\n"); + } + + if(XGIfb_heap_init()) + { + printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n"); + } + + + xgi_video_info.mtrr = (unsigned int) 0; + + if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) + { + xgi_video_info.hasVB = HASVB_NONE; + if((xgi_video_info.chip == XG20)||(xgi_video_info.chip == XG27)) + xgi_video_info.hasVB = HASVB_NONE; + else if(xgi_video_info.chip == XG21) { + inXGIIDXREG(XGICR,0x38,CR38); + if ((CR38&0xE0) == 0xC0) { + xgi_video_info.disp_state = DISPTYPE_LCD; + if (!XGIfb_GetXG21LVDSData()) { + int m; + for (m=0; m < sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct); m++) { + if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) && + (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) { + XGINew_SetReg1( XGI_Pr.P3d4 , 0x36, m) ; + } + } + } + } + else if ((CR38&0xE0) == 0x60) + xgi_video_info.hasVB = HASVB_CHRONTEL ; + else + xgi_video_info.hasVB = HASVB_NONE; + } + else + XGIfb_get_VB_type(); + + XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN; + + XGIhw_ext.ulExternalChip = 0; + + switch (xgi_video_info.hasVB) { + case HASVB_301: + inXGIIDXREG(XGIPART4, 0x01, reg); + if (reg >= 0xE0) { + XGIhw_ext.ujVBChipID = VB_CHIP_302LV; + printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg); + } else if (reg >= 0xD0) { + XGIhw_ext.ujVBChipID = VB_CHIP_301LV; + printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n",reg); + } + /* else if (reg >= 0xB0) { + XGIhw_ext.ujVBChipID = VB_CHIP_301B; + inXGIIDXREG(XGIPART4,0x23,reg1); + printk("XGIfb: XGI301B bridge detected\n"); + }*/ + else { + XGIhw_ext.ujVBChipID = VB_CHIP_301; + printk("XGIfb: XGI301 bridge detected\n"); + } + break; + case HASVB_302: + inXGIIDXREG(XGIPART4, 0x01, reg); + if (reg >= 0xE0) { + XGIhw_ext.ujVBChipID = VB_CHIP_302LV; + printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg); + } else if (reg >= 0xD0) { + XGIhw_ext.ujVBChipID = VB_CHIP_301LV; + printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg); + } else if (reg >= 0xB0) { + inXGIIDXREG(XGIPART4,0x23,reg1); + + XGIhw_ext.ujVBChipID = VB_CHIP_302B; + + } else { + XGIhw_ext.ujVBChipID = VB_CHIP_302; + printk(KERN_INFO "XGIfb: XGI302 bridge detected\n"); + } + break; + case HASVB_LVDS: + XGIhw_ext.ulExternalChip = 0x1; + printk(KERN_INFO "XGIfb: LVDS transmitter detected\n"); + break; + case HASVB_TRUMPION: + XGIhw_ext.ulExternalChip = 0x2; + printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n"); + break; + case HASVB_CHRONTEL: + XGIhw_ext.ulExternalChip = 0x4; + printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n"); + break; + case HASVB_LVDS_CHRONTEL: + XGIhw_ext.ulExternalChip = 0x5; + printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n"); + break; + default: + printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n"); + break; + } + + if (xgi_video_info.hasVB != HASVB_NONE) { + XGIfb_detect_VB(); + } + + if (xgi_video_info.disp_state & DISPTYPE_DISP2) { + if (XGIfb_crt1off) + xgi_video_info.disp_state |= DISPMODE_SINGLE; + else + xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1); + } else { + xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1; + } + + if (xgi_video_info.disp_state & DISPTYPE_LCD) { + if (!enable_dstn) { + inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg); + reg &= 0x0f; + XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg]; + + } else { + // TW: FSTN/DSTN + XGIhw_ext.ulCRT2LCDType = LCD_320x480; + } + } + + XGIfb_detectedpdc = 0; + + XGIfb_detectedlcda = 0xff; +#ifndef LINUXBIOS + + /* TW: Try to find about LCDA */ + + if((XGIhw_ext.ujVBChipID == VB_CHIP_302B) || + (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) || + (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) + { + int tmp; + inXGIIDXREG(XGICR,0x34,tmp); + if(tmp <= 0x13) + { + // Currently on LCDA? (Some BIOSes leave CR38) + inXGIIDXREG(XGICR,0x38,tmp); + if((tmp & 0x03) == 0x03) + { +// XGI_Pr.XGI_UseLCDA = TRUE; + }else + { + // Currently on LCDA? (Some newer BIOSes set D0 in CR35) + inXGIIDXREG(XGICR,0x35,tmp); + if(tmp & 0x01) + { +// XGI_Pr.XGI_UseLCDA = TRUE; + }else + { + inXGIIDXREG(XGICR,0x30,tmp); + if(tmp & 0x20) + { + inXGIIDXREG(XGIPART1,0x13,tmp); + if(tmp & 0x04) + { +// XGI_Pr.XGI_UseLCDA = TRUE; + } + } + } + } + } + + } + + +#endif + + if (xgifb_mode_idx >= 0) + xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx); + + if (xgifb_mode_idx < 0) { + switch (xgi_video_info.disp_state & DISPTYPE_DISP2) { + case DISPTYPE_LCD: + xgifb_mode_idx = DEFAULT_LCDMODE; + if (xgi_video_info.chip == XG21) + { + xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx(); + } + break; + case DISPTYPE_TV: + xgifb_mode_idx = DEFAULT_TVMODE; + break; + default: + xgifb_mode_idx = DEFAULT_MODE; + break; + } + } + + XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no; + + + if( xgi_video_info.refresh_rate == 0) + xgi_video_info.refresh_rate = 60; /*yilin set default refresh rate */ + if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) + { + XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx; + xgi_video_info.refresh_rate = 60; + } + + xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp; + xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres; + xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres; + xgi_video_info.org_x = xgi_video_info.org_y = 0; + xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3); + switch(xgi_video_info.video_bpp) { + case 8: + xgi_video_info.DstColor = 0x0000; + xgi_video_info.XGI310_AccelDepth = 0x00000000; + xgi_video_info.video_cmap_len = 256; + break; + case 16: + xgi_video_info.DstColor = 0x8000; + xgi_video_info.XGI310_AccelDepth = 0x00010000; + xgi_video_info.video_cmap_len = 16; + break; + case 32: + xgi_video_info.DstColor = 0xC000; + xgi_video_info.XGI310_AccelDepth = 0x00020000; + xgi_video_info.video_cmap_len = 16; + break; + default: + xgi_video_info.video_cmap_len = 16; + printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp); + break; + } + + + + printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n", + xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp, + xgi_video_info.refresh_rate); + + default_var.xres = default_var.xres_virtual = xgi_video_info.video_width; + default_var.yres = default_var.yres_virtual = xgi_video_info.video_height; + default_var.bits_per_pixel = xgi_video_info.video_bpp; + + XGIfb_bpp_to_var(&default_var); + + default_var.pixclock = (u32) (1000000000 / + XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext, + XGIfb_mode_no, XGIfb_rate_idx)); + + if(XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext, + XGIfb_mode_no, XGIfb_rate_idx, + &default_var.left_margin, &default_var.right_margin, + &default_var.upper_margin, &default_var.lower_margin, + &default_var.hsync_len, &default_var.vsync_len, + &default_var.sync, &default_var.vmode)) { + + if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { + default_var.yres <<= 1; + default_var.yres_virtual <<= 1; + } else if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { + default_var.pixclock >>= 1; + default_var.yres >>= 1; + default_var.yres_virtual >>= 1; + } + + } + + +#if 0 +#ifdef XGIFB_PAN + if(XGIfb_ypan) { + default_var.yres_virtual = + xgi_video_info.heapstart / (default_var.xres * (default_var.bits_per_pixel >> 3)); + if(default_var.yres_virtual <= default_var.yres) { + default_var.yres_virtual = default_var.yres; + } + } +#endif +#endif + + + xgi_video_info.accel = 0; + if(XGIfb_accel) { + xgi_video_info.accel = -1; + default_var.accel_flags |= FB_ACCELF_TEXT; + XGIfb_initaccel(); + } + + fb_info->flags = FBINFO_FLAG_DEFAULT; + fb_info->var = default_var; + fb_info->fix = XGIfb_fix; + fb_info->par = &xgi_video_info; + fb_info->screen_base = xgi_video_info.video_vbase; + fb_info->fbops = &XGIfb_ops; + XGIfb_get_fix(&fb_info->fix, -1, fb_info); + fb_info->pseudo_palette = pseudo_palette; + + fb_alloc_cmap(&fb_info->cmap, 256 , 0); + + +#ifdef CONFIG_MTRR + xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base, + (unsigned int) xgi_video_info.video_size, + MTRR_TYPE_WRCOMB, 1); + if(xgi_video_info.mtrr) { + printk(KERN_INFO "XGIfb: Added MTRRs\n"); + } +#endif + + if(register_framebuffer(fb_info) < 0) + { + return -EINVAL; + } + + XGIfb_registered = 1; + + printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%x)\n", XGIFB_GET_INFO); + +/* printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n", + XGIfb_accel ? "enabled" : "disabled", + XGIfb_ypan ? "ypan" : "redraw"); +*/ + printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n", + fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL); + + + } + + dumpVGAReg(); + + return 0; +} + + +/*****************************************************/ +/* PCI DEVICE HANDLING */ +/*****************************************************/ + +static void __devexit xgifb_remove(struct pci_dev *pdev) +{ + /* Unregister the framebuffer */ +// if(xgi_video_info.registered) { + unregister_framebuffer(fb_info); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3)) + framebuffer_release(fb_info); +#else + kfree(fb_info); +#endif +// } + + pci_set_drvdata(pdev, NULL); + +}; + +static struct pci_driver xgifb_driver = { + .name = "xgifb", + .id_table = xgifb_pci_table, + .probe = xgifb_probe, + .remove = __devexit_p(xgifb_remove) +}; + +XGIINITSTATIC int __init xgifb_init(void) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) +#ifndef MODULE + char *option = NULL; + + if (fb_get_options("xgifb", &option)) + return -ENODEV; + XGIfb_setup(option); +#endif +#endif + return(pci_register_driver(&xgifb_driver)); +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) +#ifndef MODULE +module_init(xgifb_init); +#endif +#endif + +/*****************************************************/ +/* MODULE */ +/*****************************************************/ + +#ifdef MODULE + +static char *mode = NULL; +static int vesa = 0; +static unsigned int rate = 0; +static unsigned int crt1off = 1; +static unsigned int mem = 0; +static char *forcecrt2type = NULL; +static int forcecrt1 = -1; +static int pdc = -1; +static int pdc1 = -1; +static int noaccel = -1; +static int noypan = -1; +static int nomax = -1; +static int userom = -1; +static int useoem = -1; +static char *tvstandard = NULL; +static int nocrt2rate = 0; +static int scalelcd = -1; +static char *specialtiming = NULL; +static int lvdshl = -1; +static int tvxposoffset = 0, tvyposoffset = 0; +#if !defined(__i386__) && !defined(__x86_64__) +static int resetcard = 0; +static int videoram = 0; +#endif + +MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("XGITECH , Others"); + + + +module_param(mem, int, 0); +module_param(noaccel, int, 0); +module_param(noypan, int, 0); +module_param(nomax, int, 0); +module_param(userom, int, 0); +module_param(useoem, int, 0); +module_param(mode, charp, 0); +module_param(vesa, int, 0); +module_param(rate, int, 0); +module_param(forcecrt1, int, 0); +module_param(forcecrt2type, charp, 0); +module_param(scalelcd, int, 0); +module_param(pdc, int, 0); +module_param(pdc1, int, 0); +module_param(specialtiming, charp, 0); +module_param(lvdshl, int, 0); +module_param(tvstandard, charp, 0); +module_param(tvxposoffset, int, 0); +module_param(tvyposoffset, int, 0); +module_param(filter, int, 0); +module_param(nocrt2rate, int, 0); +#if !defined(__i386__) && !defined(__x86_64__) +module_param(resetcard, int, 0); +module_param(videoram, int, 0); +#endif + + +MODULE_PARM_DESC(mem, + "\nDetermines the beginning of the video memory heap in KB. This heap is used\n" + "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n" + "on the amount of video RAM available. If 8MB of video RAM or less is available,\n" + "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n" + "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n" + "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n" + "for XFree86 4.x/X.org 6.7 and later.\n"); + +MODULE_PARM_DESC(noaccel, + "\nIf set to anything other than 0, 2D acceleration will be disabled.\n" + "(default: 0)\n"); + +MODULE_PARM_DESC(noypan, + "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n" + "will be performed by redrawing the screen. (default: 0)\n"); + +MODULE_PARM_DESC(nomax, + "\nIf y-panning is enabled, xgifb will by default use the entire available video\n" + "memory for the virtual screen in order to optimize scrolling performance. If\n" + "this is set to anything other than 0, xgifb will not do this and thereby \n" + "enable the user to positively specify a virtual Y size of the screen using\n" + "fbset. (default: 0)\n"); + + + +MODULE_PARM_DESC(mode, + "\nSelects the desired default display mode in the format XxYxDepth,\n" + "eg. 1024x768x16. Other formats supported include XxY-Depth and\n" + "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n" + "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n"); + +MODULE_PARM_DESC(vesa, + "\nSelects the desired default display mode by VESA defined mode number, eg.\n" + "0x117 (default: 0x0103)\n"); + + +MODULE_PARM_DESC(rate, + "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n" + "If the mode is specified in the format XxY-Depth@Rate, this parameter\n" + "will be ignored (default: 60)\n"); + +MODULE_PARM_DESC(forcecrt1, + "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n" + "connected. With this option, the detection can be overridden (1=CRT1 ON,\n" + "0=CRT1 OFF) (default: [autodetected])\n"); + +MODULE_PARM_DESC(forcecrt2type, + "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n" + "LCD, TV or secondary VGA. With this option, this autodetection can be\n" + "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n" + "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n" + "be used instead of TV to override the TV detection. Furthermore, on systems\n" + "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n" + "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n" + "depends on the very hardware in use. (default: [autodetected])\n"); + +MODULE_PARM_DESC(scalelcd, + "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n" + "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n" + "show black bars around the image, TMDS panels will probably do the scaling\n" + "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n"); + +MODULE_PARM_DESC(pdc, + "\nThis is for manually selecting the LCD panel delay compensation. The driver\n" + "should detect this correctly in most cases; however, sometimes this is not\n" + "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n" + "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n" + "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n" + "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n"); + +MODULE_PARM_DESC(pdc1, + "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n" + "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n" + "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n" + "implemented yet.\n"); + +MODULE_PARM_DESC(specialtiming, + "\nPlease refer to documentation for more information on this option.\n"); + +MODULE_PARM_DESC(lvdshl, + "\nPlease refer to documentation for more information on this option.\n"); + +MODULE_PARM_DESC(tvstandard, + "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n" + "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n"); + +MODULE_PARM_DESC(tvxposoffset, + "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n" + "Default: 0\n"); + +MODULE_PARM_DESC(tvyposoffset, + "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n" + "Default: 0\n"); + +MODULE_PARM_DESC(filter, + "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n" + "(Possible values 0-7, default: [no filter])\n"); + +MODULE_PARM_DESC(nocrt2rate, + "\nSetting this to 1 will force the driver to use the default refresh rate for\n" + "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n"); + + + + +int __init xgifb_init_module(void) +{ + printk("\nXGIfb_init_module"); + if(mode) + XGIfb_search_mode(mode); + else if (vesa != -1) + XGIfb_search_vesamode(vesa); + + return(xgifb_init()); +} + +static void __exit xgifb_remove_module(void) +{ + pci_unregister_driver(&xgifb_driver); + printk(KERN_DEBUG "xgifb: Module unloaded\n"); +} + +module_init(xgifb_init_module); +module_exit(xgifb_remove_module); + +#endif /* /MODULE */ + +EXPORT_SYMBOL(XGI_malloc); +EXPORT_SYMBOL(XGI_free); + diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h new file mode 100644 index 000000000000..41bf163d4e6b --- /dev/null +++ b/drivers/staging/xgifb/XGIfb.h @@ -0,0 +1,215 @@ +#ifndef _LINUX_XGIFB +#define _LINUX_XGIFB +#include <linux/spinlock.h> +#include <asm/ioctl.h> +#include <asm/types.h> + +#define DISPTYPE_CRT1 0x00000008L +#define DISPTYPE_CRT2 0x00000004L +#define DISPTYPE_LCD 0x00000002L +#define DISPTYPE_TV 0x00000001L +#define DISPTYPE_DISP1 DISPTYPE_CRT1 +#define DISPTYPE_DISP2 (DISPTYPE_CRT2 | DISPTYPE_LCD | DISPTYPE_TV) +#define DISPMODE_SINGLE 0x00000020L +#define DISPMODE_MIRROR 0x00000010L +#define DISPMODE_DUALVIEW 0x00000040L + +#define HASVB_NONE 0x00 +#define HASVB_301 0x01 +#define HASVB_LVDS 0x02 +#define HASVB_TRUMPION 0x04 +#define HASVB_LVDS_CHRONTEL 0x10 +#define HASVB_302 0x20 +#define HASVB_303 0x40 +#define HASVB_CHRONTEL 0x80 + +#ifndef XGIFB_ID +#define XGIFB_ID 0x53495346 /* Identify myself with 'XGIF' */ +#endif + +typedef enum _XGI_CHIP_TYPE { + XGI_VGALegacy = 0, + XGI_300, + XGI_630, + XGI_730, + XGI_540, + XGI_315H, + XGI_315, + XGI_315PRO, + XGI_550, + XGI_640, + XGI_740, + XGI_650, + XGI_650M, + XGI_330 = 16, + XGI_660, + XGI_661, + XGI_760, + XG40 = 32, + XG41, + XG42, + XG45, + XG20 = 48, + XG21, + XG27, + MAX_XGI_CHIP +} XGI_CHIP_TYPE; + +typedef enum _TVTYPE { + TVMODE_NTSC = 0, + TVMODE_PAL, + TVMODE_HIVISION, + TVTYPE_PALM, // vicki@030226 + TVTYPE_PALN, // vicki@030226 + TVTYPE_NTSCJ, // vicki@030226 + TVMODE_TOTAL +} XGI_TV_TYPE; + + +typedef struct _XGIFB_INFO XGIfb_info; +struct _XGIFB_INFO { + +unsigned long XGIfb_id; + int chip_id; /* PCI ID of detected chip */ + int memory; /* video memory in KB which XGIfb manages */ + int heapstart; /* heap start (= XGIfb "mem" argument) in KB */ + unsigned char fbvidmode; /* current XGIfb mode */ + + unsigned char XGIfb_version; + unsigned char XGIfb_revision; + unsigned char XGIfb_patchlevel; + + unsigned char XGIfb_caps; /* XGIfb capabilities */ + + int XGIfb_tqlen; /* turbo queue length (in KB) */ + + unsigned int XGIfb_pcibus; /* The card's PCI ID */ + unsigned int XGIfb_pcislot; + unsigned int XGIfb_pcifunc; + + unsigned char XGIfb_lcdpdc; /* PanelDelayCompensation */ + + unsigned char XGIfb_lcda; /* Detected status of LCDA for low res/text modes */ + + char reserved[235]; /* for future use */ +}; + + + + +typedef enum _TVPLUGTYPE { // vicki@030226 +// TVPLUG_Legacy = 0, +// TVPLUG_COMPOSITE, +// TVPLUG_SVIDEO, +// TVPLUG_SCART, +// TVPLUG_TOTAL + TVPLUG_UNKNOWN = 0, + TVPLUG_COMPOSITE = 1, + TVPLUG_SVIDEO = 2, + TVPLUG_COMPOSITE_AND_SVIDEO = 3, + TVPLUG_SCART = 4, + TVPLUG_YPBPR_525i = 5, + TVPLUG_YPBPR_525P = 6, + TVPLUG_YPBPR_750P = 7, + TVPLUG_YPBPR_1080i = 8, + TVPLUG_TOTAL +} XGI_TV_PLUG; + + +struct mode_info { + int bpp; + int xres; + int yres; + int v_xres; + int v_yres; + int org_x; + int org_y; + unsigned int vrate; +}; + +struct ap_data { + struct mode_info minfo; + unsigned long iobase; + unsigned int mem_size; + unsigned long disp_state; + XGI_CHIP_TYPE chip; + unsigned char hasVB; + XGI_TV_TYPE TV_type; + XGI_TV_PLUG TV_plug; + unsigned long version; + char reserved[256]; +}; + + + +/* If changing this, vgatypes.h must also be changed (for X driver) */ + + +/* + * NOTE! The ioctl types used to be "size_t" by mistake, but were + * really meant to be __u32. Changed to "__u32" even though that + * changes the value on 64-bit architectures, because the value + * (with a 4-byte size) is also hardwired in vgatypes.h for user + * space exports. So "__u32" is actually more compatible, duh! + */ +#define XGIFB_GET_INFO _IOR('n',0xF8,__u32) +#define XGIFB_GET_VBRSTATUS _IOR('n',0xF9,__u32) + + + +struct video_info{ + int chip_id; + unsigned int video_size; + unsigned long video_base; + char * video_vbase; + unsigned long mmio_base; + char * mmio_vbase; + unsigned long vga_base; + unsigned long mtrr; + unsigned long heapstart; + + int video_bpp; + int video_cmap_len; + int video_width; + int video_height; + int video_vwidth; + int video_vheight; + int org_x; + int org_y; + int video_linelength; + unsigned int refresh_rate; + + unsigned long disp_state; + unsigned char hasVB; + unsigned char TV_type; + unsigned char TV_plug; + + XGI_CHIP_TYPE chip; + unsigned char revision_id; + + unsigned short DstColor; + unsigned long XGI310_AccelDepth; + unsigned long CommandReg; + + spinlock_t lockaccel; + + unsigned int pcibus; + unsigned int pcislot; + unsigned int pcifunc; + + int accel; + unsigned short subsysvendor; + unsigned short subsysdevice; + + char reserved[236]; +}; + + +extern struct video_info xgi_video_info; + +#ifdef __KERNEL__ +//extern void xgi_malloc(struct xgi_memreq *req); +extern void xgi_free(unsigned long base); +extern void xgi_dispinfo(struct ap_data *rec); +#endif +#endif diff --git a/drivers/staging/xgifb/osdef.h b/drivers/staging/xgifb/osdef.h new file mode 100644 index 000000000000..4bc7d3a7440c --- /dev/null +++ b/drivers/staging/xgifb/osdef.h @@ -0,0 +1,153 @@ +#ifndef _OSDEF_H_ +#define _OSDEF_H_ + +/* #define WINCE_HEADER*/ +/*#define WIN2000*/ +/* #define TC */ +#define LINUX_KERNEL +/* #define LINUX_XF86 */ + +/**********************************************************************/ +#ifdef LINUX_KERNEL +//#include <linux/config.h> +#endif + + +/**********************************************************************/ +#ifdef TC +#endif +#ifdef WIN2000 +#endif +#ifdef WINCE_HEADER +#endif +#ifdef LINUX_XF86 +#define LINUX +#endif +#ifdef LINUX_KERNEL +#define LINUX +#endif + +/**********************************************************************/ +#ifdef TC +#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize); +#endif +#ifdef WIN2000 +#define XGI_SetMemory(MemoryAddress,MemorySize,value) MemFill((PVOID) MemoryAddress,(ULONG) MemorySize,(UCHAR) value); +#endif +#ifdef WINCE_HEADER +#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize); +#endif +#ifdef LINUX_XF86 +#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize) +#endif +#ifdef LINUX_KERNEL +#define XGI_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize) +#endif +/**********************************************************************/ + +/**********************************************************************/ + +#ifdef TC +#define XGI_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length); +#endif +#ifdef WIN2000 +#define XGI_MemoryCopy(Destination,Soruce,Length) /*VideoPortMoveMemory((PUCHAR)Destination , Soruce,length);*/ +#endif +#ifdef WINCE_HEADER +#define XGI_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length); +#endif +#ifdef LINUX_XF86 +#define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length) +#endif +#ifdef LINUX_KERNEL +#define XGI_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length) +#endif + +/**********************************************************************/ + +#ifdef OutPortByte +#undef OutPortByte +#endif /* OutPortByte */ + +#ifdef OutPortWord +#undef OutPortWord +#endif /* OutPortWord */ + +#ifdef OutPortLong +#undef OutPortLong +#endif /* OutPortLong */ + +#ifdef InPortByte +#undef InPortByte +#endif /* InPortByte */ + +#ifdef InPortWord +#undef InPortWord +#endif /* InPortWord */ + +#ifdef InPortLong +#undef InPortLong +#endif /* InPortLong */ + +/**********************************************************************/ +/* TC */ +/**********************************************************************/ + +#ifdef TC +#define OutPortByte(p,v) outp((unsigned short)(p),(unsigned char)(v)) +#define OutPortWord(p,v) outp((unsigned short)(p),(unsigned short)(v)) +#define OutPortLong(p,v) outp((unsigned short)(p),(unsigned long)(v)) +#define InPortByte(p) inp((unsigned short)(p)) +#define InPortWord(p) inp((unsigned short)(p)) +#define InPortLong(p) ((inp((unsigned short)(p+2))<<16) | inp((unsigned short)(p))) +#endif + +/**********************************************************************/ +/* LINUX XF86 */ +/**********************************************************************/ + +#ifdef LINUX_XF86 +#define OutPortByte(p,v) outb((CARD16)(p),(CARD8)(v)) +#define OutPortWord(p,v) outw((CARD16)(p),(CARD16)(v)) +#define OutPortLong(p,v) outl((CARD16)(p),(CARD32)(v)) +#define InPortByte(p) inb((CARD16)(p)) +#define InPortWord(p) inw((CARD16)(p)) +#define InPortLong(p) inl((CARD16)(p)) +#endif + +#ifdef LINUX_KERNEL +#define OutPortByte(p,v) outb((u8)(v),(p)) +#define OutPortWord(p,v) outw((u16)(v),(p)) +#define OutPortLong(p,v) outl((u32)(v),(p)) +#define InPortByte(p) inb(p) +#define InPortWord(p) inw(p) +#define InPortLong(p) inl(p) +#endif + +/**********************************************************************/ +/* WIN 2000 */ +/**********************************************************************/ + +#ifdef WIN2000 +#define OutPortByte(p,v) VideoPortWritePortUchar ((PUCHAR) (p), (UCHAR) (v)) +#define OutPortWord(p,v) VideoPortWritePortUshort((PUSHORT) (p), (USHORT) (v)) +#define OutPortLong(p,v) VideoPortWritePortUlong ((PULONG) (p), (ULONG) (v)) +#define InPortByte(p) VideoPortReadPortUchar ((PUCHAR) (p)) +#define InPortWord(p) VideoPortReadPortUshort ((PUSHORT) (p)) +#define InPortLong(p) VideoPortReadPortUlong ((PULONG) (p)) +#endif + + +/**********************************************************************/ +/* WIN CE */ +/**********************************************************************/ + +#ifdef WINCE_HEADER +#define OutPortByte(p,v) WRITE_PORT_UCHAR ((PUCHAR) (p), (UCHAR) (v)) +#define OutPortWord(p,v) WRITE_PORT_USHORT((PUSHORT) (p), (USHORT) (v)) +#define OutPortLong(p,v) WRITE_PORT_ULONG ((PULONG) (p), (ULONG) (v)) +#define InPortByte(p) READ_PORT_UCHAR ((PUCHAR) (p)) +#define InPortWord(p) READ_PORT_USHORT ((PUSHORT) (p)) +#define InPortLong(p) READ_PORT_ULONG ((PULONG) (p)) +#endif +#endif // _OSDEF_H_ diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h new file mode 100644 index 000000000000..17a7ada4926e --- /dev/null +++ b/drivers/staging/xgifb/vb_def.h @@ -0,0 +1,1017 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/xgi/initdef.h,v 1.4 2000/12/02 01:16:17 dawes Exp $ */ +#ifndef _INITDEF_ +#define _INITDEF_ + +#ifndef NewScratch +#define NewScratch +#endif +/* shampoo */ +#ifdef LINUX_KERNEL +#define SEQ_ADDRESS_PORT 0x0014 +#define SEQ_DATA_PORT 0x0015 +#define MISC_OUTPUT_REG_READ_PORT 0x001C +#define MISC_OUTPUT_REG_WRITE_PORT 0x0012 +#define GRAPH_DATA_PORT 0x1F +#define GRAPH_ADDRESS_PORT 0x1E +#define XGI_MASK_DUAL_CHIP 0x04 /* SR3A */ +#define CRTC_ADDRESS_PORT_COLOR 0x0024 +#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013 +#define PCI_COMMAND 0x04 +#endif +/* ~shampoo */ + + +#define VB_XGI301 0x0001 /*301b*/ +#define VB_XGI301B 0x0002 +#define VB_XGI302B 0x0004 +#define VB_XGI301LV 0x0008 /*301lv*/ +#define VB_XGI302LV 0x0010 +#define VB_XGI301C 0x0020 /* for 301C */ +#define VB_NoLCD 0x8000 +/*end 301b*/ + +#define VB_YPbPrInfo 0x07 /*301lv*/ +#define VB_YPbPr525i 0x00 +#define VB_YPbPr525p 0x01 +#define VB_YPbPr750p 0x02 +#define VB_YPbPr1080i 0x03 + +/* #define CRT1Len 17 */ +#define LVDSCRT1Len 15 +#define CHTVRegDataLen 5 + +/* #define ModeInfoFlag 0x07 */ +/* #define IsTextMode 0x07 */ +/* #define ModeText 0x00 */ +/* #define ModeCGA 0x01 */ +/* #define ModeEGA 0x02 */ +/* #define ModeVGA 0x03 */ +/* #define Mode15Bpp 0x04 */ +/* #define Mode16Bpp 0x05 */ +/* #define Mode24Bpp 0x06 */ +/* #define Mode32Bpp 0x07 */ + +/* #define DACInfoFlag 0x18 */ +/* #define MemoryInfoFlag 0x1E0 */ +/* #define MemorySizeShift 0x05 */ + +#define Charx8Dot 0x0200 +#define LineCompareOff 0x0400 +#define CRT2Mode 0x0800 +#define HalfDCLK 0x1000 +#define NoSupportSimuTV 0x2000 +#define DoubleScanMode 0x8000 + +#define SupportAllCRT2 0x0078 +#define SupportTV 0x0008 +#define SupportHiVisionTV 0x0010 +#define SupportLCD 0x0020 +#define SupportRAMDAC2 0x0040 +#define NoSupportTV 0x0070 +#define NoSupportHiVisionTV 0x0060 +#define NoSupportLCD 0x0058 +#define SupportCHTV 0x0800 +#define SupportCRT2in301C 0x0100 /* for 301C */ +#define SupportTV1024 0x0800 /*301b*/ +#define SupportYPbPr 0x1000 /*301lv*/ +#define InterlaceMode 0x0080 +#define SyncPP 0x0000 +#define SyncPN 0x4000 +#define SyncNP 0x8000 +/* #define SyncNN 0xc000 */ +#define ECLKindex0 0x0000 +#define ECLKindex1 0x0100 +#define ECLKindex2 0x0200 +#define ECLKindex3 0x0300 +#define ECLKindex4 0x0400 + +#define SetSimuScanMode 0x0001 +#define SwitchToCRT2 0x0002 +/* #define SetCRT2ToTV 0x009C */ +#define SetCRT2ToAVIDEO 0x0004 +#define SetCRT2ToSVIDEO 0x0008 +#define SetCRT2ToSCART 0x0010 +#define SetCRT2ToLCD 0x0020 +#define SetCRT2ToRAMDAC 0x0040 +#define SetCRT2ToHiVisionTV 0x0080 +#define SetNTSCTV 0x0000 +/* #define SetPALTV 0x0100 */ +#define SetInSlaveMode 0x0200 +#define SetNotSimuMode 0x0400 +#define SetNotSimuTVMode 0x0400 +#define SetDispDevSwitch 0x0800 +#define LoadDACFlag 0x1000 +#define DisableCRT2Display 0x2000 +#define DriverMode 0x4000 +#define HotKeySwitch 0x8000 +#define SetCHTVOverScan 0x8000 +/* #define SetCRT2ToLCDA 0x8000 301b */ +#define PanelRGB18Bit 0x0100 +#define PanelRGB24Bit 0x0000 + +#define TVOverScan 0x10 +#define TVOverScanShift 4 +#define ClearBufferFlag 0x20 +#define EnableDualEdge 0x01 /*301b*/ +#define SetToLCDA 0x02 + +#define YPbPrModeInfo 0x38 +/* #define YPbPrMode525i 0x00 */ +/* #define YPbPrMode525p 0x08 */ +/* #define YPbPrMode750p 0x10 */ +/* #define YPbPrMode1080i 0x18 */ + +#define SetSCARTOutput 0x01 +#define BoardTVType 0x02 +#define EnablePALMN 0x40 +/* #define ProgrammingCRT2 0x01 */ +/* #define TVSimuMode 0x02 */ +/* #define RPLLDIV2XO 0x04 */ +/* #define LCDVESATiming 0x08 */ +/* #define EnableLVDSDDA 0x10 */ +#define SetDispDevSwitchFlag 0x20 +#define CheckWinDos 0x40 +#define SetJDOSMode 0x80 + +#define Panel320x480 0x07/*fstn*/ +/* [ycchen] 02/12/03 Modify for Multi-Sync. LCD Support */ +#define PanelResInfo 0x1F /* CR36 Panel Type/LCDResInfo */ +#define PanelRefInfo 0x60 +#define Panel800x600 0x01 +#define Panel1024x768 0x02 +#define Panel1024x768x75 0x22 +#define Panel1280x1024 0x03 +#define Panel1280x1024x75 0x23 +#define Panel640x480 0x04 +#define Panel1024x600 0x05 +#define Panel1152x864 0x06 +#define Panel1280x960 0x07 +#define Panel1152x768 0x08 +#define Panel1400x1050 0x09 +#define Panel1280x768 0x0A +#define Panel1600x1200 0x0B + +#define PanelRef60Hz 0x00 +#define PanelRef75Hz 0x20 +#define LCDRGB18Bit 0x01 + +#define ExtChipTrumpion 0x06 +#define ExtChipCH7005 0x08 +#define ExtChipMitacTV 0x0a +#define LCDNonExpanding 0x10 +#define LCDNonExpandingShift 4 +#define LCDSync 0x20 +#define LCDSyncBit 0xe0 +#define LCDSyncShift 6 + +/* #define DDC2DelayTime 300 */ + +#define CRT2DisplayFlag 0x2000 +/* #define LCDDataLen 8 */ +/* #define HiTVDataLen 12 */ +/* #define TVDataLen 16 */ +/* #define SetPALTV 0x0100 */ +#define HalfDCLK 0x1000 +#define NTSCHT 1716 +#define NTSCVT 525 +#define PALHT 1728 +#define PALVT 625 +#define StHiTVHT 892 +#define StHiTVVT 1126 +#define StHiTextTVHT 1000 +#define StHiTextTVVT 1126 +#define ExtHiTVHT 2100 +#define ExtHiTVVT 1125 + +#define St750pTVHT 1716 +#define St750pTVVT 525 +#define Ext750pTVHT 1716 +#define Ext750pTVVT 525 +#define St525pTVHT 1716 +#define St525pTVVT 525 +#define Ext525pTVHT 1716 +#define Ext525pTVVT 525 +#define St525iTVHT 1716 +#define St525iTVVT 525 +#define Ext525iTVHT 1716 +#define Ext525iTVVT 525 + +#define VCLKStartFreq 25 +#define SoftDramType 0x80 +#define VCLK40 0x04 + +#define VCLK162 0x21 + +#define LCDRGB18Bit 0x01 +#define LoadDACFlag 0x1000 +#define AfterLockCRT2 0x4000 +#define SetCRT2ToAVIDEO 0x0004 +#define SetCRT2ToSCART 0x0010 +#define Ext2StructSize 5 + + +#define YPbPr525iVCLK 0x03B +#define YPbPr525iVCLK_2 0x03A + +#define SwitchToCRT2 0x0002 +/* #define LCDVESATiming 0x08 */ +#define SetSCARTOutput 0x01 +#define AVIDEOSense 0x01 +#define SVIDEOSense 0x02 +#define SCARTSense 0x04 +#define LCDSense 0x08 +#define Monitor1Sense 0x20 +#define Monitor2Sense 0x10 +#define HiTVSense 0x40 +#define BoardTVType 0x02 +#define HotPlugFunction 0x08 +#define StStructSize 0x06 + + +#define XGI_CRT2_PORT_00 0x00 - 0x030 +#define XGI_CRT2_PORT_04 0x04 - 0x030 +#define XGI_CRT2_PORT_10 0x10 - 0x30 +#define XGI_CRT2_PORT_12 0x12 - 0x30 +#define XGI_CRT2_PORT_14 0x14 - 0x30 + + +#define LCDNonExpanding 0x10 +#define ADR_CRT2PtrData 0x20E +#define offset_Zurac 0x210 +#define ADR_LVDSDesPtrData 0x212 +#define ADR_LVDSCRT1DataPtr 0x214 +#define ADR_CHTVVCLKPtr 0x216 +#define ADR_CHTVRegDataPtr 0x218 + +#define LVDSDataLen 6 +/* #define EnableLVDSDDA 0x10 */ +/* #define LVDSDesDataLen 3 */ +#define ActiveNonExpanding 0x40 +#define ActiveNonExpandingShift 6 +/* #define ActivePAL 0x20 */ +#define ActivePALShift 5 +/* #define ModeSwitchStatus 0x0F */ +#define SoftTVType 0x40 +#define SoftSettingAddr 0x52 +#define ModeSettingAddr 0x53 + +/* #define SelectCRT1Rate 0x4 */ + +#define _PanelType00 0x00 +#define _PanelType01 0x08 +#define _PanelType02 0x10 +#define _PanelType03 0x18 +#define _PanelType04 0x20 +#define _PanelType05 0x28 +#define _PanelType06 0x30 +#define _PanelType07 0x38 +#define _PanelType08 0x40 +#define _PanelType09 0x48 +#define _PanelType0A 0x50 +#define _PanelType0B 0x58 +#define _PanelType0C 0x60 +#define _PanelType0D 0x68 +#define _PanelType0E 0x70 +#define _PanelType0F 0x78 + + +#define PRIMARY_VGA 0 /* 1: XGI is primary vga 0:XGI is secondary vga */ +#define BIOSIDCodeAddr 0x235 +#define OEMUtilIDCodeAddr 0x237 +#define VBModeIDTableAddr 0x239 +#define OEMTVPtrAddr 0x241 +#define PhaseTableAddr 0x243 +#define NTSCFilterTableAddr 0x245 +#define PALFilterTableAddr 0x247 +#define OEMLCDPtr_1Addr 0x249 +#define OEMLCDPtr_2Addr 0x24B +#define LCDHPosTable_1Addr 0x24D +#define LCDHPosTable_2Addr 0x24F +#define LCDVPosTable_1Addr 0x251 +#define LCDVPosTable_2Addr 0x253 +#define OEMLCDPIDTableAddr 0x255 + +#define VBModeStructSize 5 +#define PhaseTableSize 4 +#define FilterTableSize 4 +#define LCDHPosTableSize 7 +#define LCDVPosTableSize 5 +#define OEMLVDSPIDTableSize 4 +#define LVDSHPosTableSize 4 +#define LVDSVPosTableSize 6 + +#define VB_ModeID 0 +#define VB_TVTableIndex 1 +#define VB_LCDTableIndex 2 +#define VB_LCDHIndex 3 +#define VB_LCDVIndex 4 + +#define OEMLCDEnable 0x0001 +#define OEMLCDDelayEnable 0x0002 +#define OEMLCDPOSEnable 0x0004 +#define OEMTVEnable 0x0100 +#define OEMTVDelayEnable 0x0200 +#define OEMTVFlickerEnable 0x0400 +#define OEMTVPhaseEnable 0x0800 +#define OEMTVFilterEnable 0x1000 + +#define OEMLCDPanelIDSupport 0x0080 + +/* #define LCDVESATiming 0x0001 //LCD Info CR37 */ +/* #define EnableLVDSDDA 0x0002 */ +#define EnableScalingLCD 0x0008 +#define SetPWDEnable 0x0004 +#define SetLCDtoNonExpanding 0x0010 +/* #define SetLCDPolarity 0x00E0 */ +#define SetLCDDualLink 0x0100 +#define SetLCDLowResolution 0x0200 +#define SetLCDStdMode 0x0400 +#define SetTVStdMode 0x0200 +#define SetTVLowResolution 0x0400 +/* ============================================================= + for 310 +============================================================== */ +#define SoftDRAMType 0x80 +#define SoftSetting_OFFSET 0x52 +#define SR07_OFFSET 0x7C +#define SR15_OFFSET 0x7D +#define SR16_OFFSET 0x81 +#define SR17_OFFSET 0x85 +#define SR19_OFFSET 0x8D +#define SR1F_OFFSET 0x99 +#define SR21_OFFSET 0x9A +#define SR22_OFFSET 0x9B +#define SR23_OFFSET 0x9C +#define SR24_OFFSET 0x9D +#define SR25_OFFSET 0x9E +#define SR31_OFFSET 0x9F +#define SR32_OFFSET 0xA0 +#define SR33_OFFSET 0xA1 + +#define CR40_OFFSET 0xA2 +#define SR25_1_OFFSET 0xF6 +#define CR49_OFFSET 0xF7 + +#define VB310Data_1_2_Offset 0xB6 +#define VB310Data_4_D_Offset 0xB7 +#define VB310Data_4_E_Offset 0xB8 +#define VB310Data_4_10_Offset 0xBB + +#define RGBSenseDataOffset 0xBD +#define YCSenseDataOffset 0xBF +#define VideoSenseDataOffset 0xC1 +#define OutputSelectOffset 0xF3 + +#define ECLK_MCLK_DISTANCE 0x14 +#define VBIOSTablePointerStart 0x200 +#define StandTablePtrOffset VBIOSTablePointerStart+0x02 +#define EModeIDTablePtrOffset VBIOSTablePointerStart+0x04 +#define CRT1TablePtrOffset VBIOSTablePointerStart+0x06 +#define ScreenOffsetPtrOffset VBIOSTablePointerStart+0x08 +#define VCLKDataPtrOffset VBIOSTablePointerStart+0x0A +#define MCLKDataPtrOffset VBIOSTablePointerStart+0x0E +#define CRT2PtrDataPtrOffset VBIOSTablePointerStart+0x10 +#define TVAntiFlickPtrOffset VBIOSTablePointerStart+0x12 +#define TVDelayPtr1Offset VBIOSTablePointerStart+0x14 +#define TVPhaseIncrPtr1Offset VBIOSTablePointerStart+0x16 +#define TVYFilterPtr1Offset VBIOSTablePointerStart+0x18 +#define LCDDelayPtr1Offset VBIOSTablePointerStart+0x20 +#define TVEdgePtr1Offset VBIOSTablePointerStart+0x24 +#define CRT2Delay1Offset VBIOSTablePointerStart+0x28 +#define LCDDataDesOffset VBIOSTablePointerStart-0x02 +#define LCDDataPtrOffset VBIOSTablePointerStart+0x2A +#define LCDDesDataPtrOffset VBIOSTablePointerStart+0x2C +#define LCDDataList VBIOSTablePointerStart+0x22 /* add for GetLCDPtr */ +#define TVDataList VBIOSTablePointerStart+0x36 /* add for GetTVPtr */ +/* */ +/* Modify from 310.inc */ +/* */ +/* */ + + +#define ShowMsgFlag 0x20 /* SoftSetting */ +#define ShowVESAFlag 0x10 +#define HotPlugFunction 0x08 +#define ModeSoftSetting 0x04 +#define TVSoftSetting 0x02 +#define LCDSoftSetting 0x01 + +#define GatingCRTinLCDA 0x10 +#define SetHiTVOutput 0x08 +#define SetYPbPrOutput 0x04 +#define BoardTVType 0x02 +#define SetSCARTOutput 0x01 + +#define ModeSettingYPbPr 0x02 /* TVModeSetting, Others as same as CR30 */ + +/* TVModeSetting same as CR35 */ + +/* LCDModeSetting same as CR37 */ + +#define EnableNewTVFont 0x10 /* MiscCapability */ + +#define EnableLCDOutput 0x80 /* LCDCfgSetting */ + +#define SoftDRAMType 0x80 /* DRAMSetting */ +#define SoftDRAMConfig 0x40 +#define MosSelDRAMType 0x20 +#define SDRAM 000h +#define SGRAM 0x01 +#define ESDRAM 0x02 + +#define EnableAGPCfgSetting 0x01 /* AGPCfgSetting */ + +/* ---------------- SetMode Stack */ +#define CRT1Len 15 +#define VCLKLen 4 +#define DefThreshold 0x0100 +#define ExtRegsSize (57+8+37+70+63+28+768+1)/64+1 + +#define VGA_XGI315 0x0001 /* VGA Type Info */ +#define VGA_SNewis315e 0x0002 /* 315 series */ +#define VGA_XGI550 0x0004 +#define VGA_XGI640 0x0008 +#define VGA_XGI740 0x0010 +#define VGA_XGI650 0x0020 +#define VGA_XGI650M 0x0040 +#define VGA_XGI651 0x0080 +#define VGA_XGI340 0x0001 /* 340 series */ +#define VGA_XGI330 0x0001 /* 330 series */ +#define VGA_XGI660 0x0001 /* 660 series */ + +#define VB_XGI301 0x0001 /* VB Type Info */ +#define VB_XGI301B 0x0002 /* 301 series */ +#define VB_XGI302B 0x0004 +#define VB_NoLCD 0x8000 +#define VB_XGI301LV 0x0008 +#define VB_XGI302LV 0x0010 +#define VB_LVDS_NS 0x0001 /* 3rd party chip */ +#define VB_CH7017 0x0002 +#define VB_CH7007 0x0080 /* [Billy] 07/05/03 */ +/* #define VB_LVDS_SI 0x0004 */ + +#define ModeInfoFlag 0x0007 +#define IsTextMode 0x0007 +#define ModeText 0x0000 +#define ModeCGA 0x0001 +#define ModeEGA 0x0002 /* 16 colors mode */ +#define ModeVGA 0x0003 /* 256 colors mode */ +#define Mode15Bpp 0x0004 /* 15 Bpp Color Mode */ +#define Mode16Bpp 0x0005 /* 16 Bpp Color Mode */ +#define Mode24Bpp 0x0006 /* 24 Bpp Color Mode */ +#define Mode32Bpp 0x0007 /* 32 Bpp Color Mode */ + +#define DACInfoFlag 0x0018 +#define MONODAC 0x0000 +#define CGADAC 0x0008 +#define EGADAC 0x0010 +#define VGADAC 0x0018 + +#define MemoryInfoFlag 0x01e0 +#define MemorySizeShift 5 +#define Need1MSize 0x0000 +#define Need2MSize 0x0020 +#define Need4MSize 0x0060 +#define Need8MSize 0x00e0 +#define Need16MSize 0x01e0 + +#define Charx8Dot 0x0200 +#define LineCompareOff 0x0400 +#define CRT2Mode 0x0800 +#define HalfDCLK 0x1000 +#define NoSupportSimuTV 0x2000 +#define DoubleScanMode 0x8000 + +/* -------------- Ext_InfoFlag */ +#define SupportModeInfo 0x0007 +#define Support256 0x0003 +#define Support15Bpp 0x0004 +#define Support16Bpp 0x0005 +#define Support24Bpp 0x0006 +#define Support32Bpp 0x0007 + +#define SupportAllCRT2 0x0078 +#define SupportTV 0x0008 +#define SupportHiVisionTV 0x0010 +#define SupportLCD 0x0020 +#define SupportRAMDAC2 0x0040 +#define NoSupportTV 0x0070 +#define NoSupportHiVisionTV 0x0060 +#define NoSupportLCD 0x0058 +#define SupportTV1024 0x0800 /* 301btest */ +#define SupportYPbPr 0x1000 /* 301lv */ +#define InterlaceMode 0x0080 +#define SyncPP 0x0000 +#define SyncPN 0x4000 +#define SyncNP 0x8000 +#define SyncNN 0xC000 + +/* -------------- SetMode Stack/Scratch */ +#define SetSimuScanMode 0x0001 /* VBInfo/CR30 & CR31 */ +#define SwitchToCRT2 0x0002 +#define SetCRT2ToTV1 0x009C +#define SetCRT2ToTV 0x089C +#define SetCRT2ToAVIDEO 0x0004 +#define SetCRT2ToSVIDEO 0x0008 +#define SetCRT2ToSCART 0x0010 +#define SetCRT2ToLCD 0x0020 +#define SetCRT2ToRAMDAC 0x0040 +#define SetCRT2ToHiVisionTV 0x0080 +#define SetCRT2ToLCDA 0x0100 +#define SetInSlaveMode 0x0200 +#define SetNotSimuMode 0x0400 +#define HKEventMode 0x0800 +#define SetCRT2ToYPbPr 0x0800 +#define LoadDACFlag 0x1000 +#define DisableCRT2Display 0x2000 +#define DriverMode 0x4000 +#define SetCRT2ToDualEdge 0x8000 +#define HotKeySwitch 0x8000 + +#define ProgrammingCRT2 0x0001 /* Set Flag */ +#define EnableVCMode 0x0002 +#define SetHKEventMode 0x0004 +#define ReserveTVOption 0x0008 +#define DisableRelocateIO 0x0010 +#define Win9xDOSMode 0x0020 +#define JDOSMode 0x0040 +/* #define SetWin9xforJap 0x0080 // not used now */ +/* #define SetWin9xforKorea 0x0100 // not used now */ +#define GatingCRT 0x0800 +#define DisableChB 0x1000 +#define EnableChB 0x2000 +#define DisableChA 0x4000 +#define EnableChA 0x8000 + +#define SetNTSCTV 0x0000 /* TV Info */ +#define SetPALTV 0x0001 +#define SetNTSCJ 0x0002 +#define SetPALMTV 0x0004 +#define SetPALNTV 0x0008 +#define SetCHTVUnderScan 0x0000 +/* #define SetCHTVOverScan 0x0010 */ +#define SetYPbPrMode525i 0x0020 +#define SetYPbPrMode525p 0x0040 +#define SetYPbPrMode750p 0x0080 +#define SetYPbPrMode1080i 0x0100 +#define SetTVStdMode 0x0200 +#define SetTVLowResolution 0x0400 +#define SetTVSimuMode 0x0800 +#define TVSimuMode 0x0800 +#define RPLLDIV2XO 0x1000 +#define NTSC1024x768 0x2000 +#define SetTVLockMode 0x4000 + +#define LCDVESATiming 0x0001 /* LCD Info/CR37 */ +#define EnableLVDSDDA 0x0002 +#define EnableScalingLCD 0x0008 +#define SetPWDEnable 0x0004 +#define SetLCDtoNonExpanding 0x0010 +#define SetLCDPolarity 0x00e0 +#define SetLCDDualLink 0x0100 +#define SetLCDLowResolution 0x0200 +#define SetLCDStdMode 0x0400 + +#define DefaultLCDCap 0x80ea /* LCD Capability shampoo */ +#define RLVDSDHL00 0x0000 +#define RLVDSDHL01 0x0001 +#define RLVDSDHL10 0x0002 /* default */ +#define RLVDSDHL11 0x0003 +#define EnableLCD24bpp 0x0004 /* default */ +#define DisableLCD24bpp 0x0000 +#define RLVDSClkSFT0 0x0000 +#define RLVDSClkSFT1 0x0008 /* default */ +#define EnableLVDSDCBal 0x0010 +#define DisableLVDSDCBal 0x0000 /* default */ +#define SinglePolarity 0x0020 /* default */ +#define MultiPolarity 0x0000 +#define LCDPolarity 0x00c0 /* default: SyncNN */ +#define LCDSingleLink 0x0000 /* default */ +#define LCDDualLink 0x0100 +#define EnableSpectrum 0x0200 +#define DisableSpectrum 0x0000 /* default */ +#define PWDEnable 0x0400 +#define PWDDisable 0x0000 /* default */ +#define PWMEnable 0x0800 +#define PWMDisable 0x0000 /* default */ +#define EnableVBCLKDRVLOW 0x4000 +#define EnableVBCLKDRVHigh 0x0000 /* default */ +#define EnablePLLSPLOW 0x8000 +#define EnablePLLSPHigh 0x0000 /* default */ + +#define LCDBToA 0x20 /* LCD SetFlag */ +#define StLCDBToA 0x40 +#define LockLCDBToA 0x80 +#define LCDToFull 0x10 +#define AVIDEOSense 0x01 /* CR32 */ +#define SVIDEOSense 0x02 +#define SCARTSense 0x04 +#define LCDSense 0x08 +#define Monitor2Sense 0x10 +#define Monitor1Sense 0x20 +#define HiTVSense 0x40 + +#ifdef NewScratch +#define YPbPrSense 0x80 /* NEW SCRATCH */ +#endif + +#define TVSense 0xc7 + +#define TVOverScan 0x10 /* CR35 */ +#define TVOverScanShift 4 + +#ifdef NewScratch +#define NTSCMode 0x00 +#define PALMode 0x00 +#define NTSCJMode 0x02 +#define PALMNMode 0x0c +#define YPbPrMode 0xe0 +#define YPbPrMode525i 0x00 +#define YPbPrMode525p 0x20 +#define YPbPrMode750p 0x40 +#define YPbPrMode1080i 0x60 +#else /* Old Scratch */ +#define ClearBufferFlag 0x20 +#endif + + +#define LCDRGB18Bit 0x01 /* CR37 */ +#define LCDNonExpanding 0x10 +#define LCDNonExpandingShift 4 +#define LCDSync 0x20 +#define LCDSyncBit 0xe0 /* H/V polarity & sync ID */ +#define LCDSyncShift 6 + +#ifdef NewScratch +#define ScalingLCD 0x08 +#else /* Old Scratch */ +#define ExtChipType 0x0e +#define ExtChip301 0x02 +#define ExtChipLVDS 0x04 +#define ExtChipCH7019 0x06 +#define ScalingLCD 0x10 +#endif + +#define EnableDualEdge 0x01 /* CR38 */ +#define SetToLCDA 0x02 +#ifdef NewScratch +#define SetYPbPr 0x04 +#define DisableChannelA 0x08 +#define DisableChannelB 0x10 +#define ExtChipType 0xe0 +#define ExtChip301 0x20 +#define ExtChipLVDS 0x40 +#define ExtChipCH7019 0x60 +#else /* Old Scratch */ +#define YPbPrSense 0x04 +#define SetYPbPr 0x08 +#define YPbPrMode 0x30 +#define YPbPrMode525i 0x00 +#define YPbPrMode525p 0x10 +#define YPbPrMode750p 0x20 +#define YPbPrMode1080i 0x30 +#define PALMNMode 0xc0 +#endif + +#define BacklightControlBit 0x01 /* CR3A */ +#define Win9xforJap 0x40 +#define Win9xforKorea 0x80 + +#define ForceMDBits 0x07 /* CR3B */ +#define ForceMD_JDOS 0x00 +#define ForceMD_640x400T 0x01 +#define ForceMD_640x350T 0x02 +#define ForceMD_720x400T 0x03 +#define ForceMD_640x480E 0x04 +#define ForceMD_640x400E 0x05 +#define ForceP1Bit 0x10 +#define ForceP2Bit 0x20 +#define EnableForceMDinBIOS 0x40 +#define EnableForceMDinDrv 0x80 + +#ifdef NewScratch /* New Scratch */ +/* ---------------------- VUMA Information */ +#define LCDSettingFromCMOS 0x04 /* CR3C */ +#define TVSettingFromCMOS 0x08 +#define DisplayDeviceFromCMOS 0x10 +#define HKSupportInSBIOS 0x20 +#define OSDSupportInSBIOS 0x40 +#define DisableLogo 0x80 + +/* ---------------------- HK Evnet Definition */ +#define HKEvent 0x0f /* CR3D */ +#define HK_ModeSwitch 0x01 +#define HK_Expanding 0x02 +#define HK_OverScan 0x03 +#define HK_Brightness 0x04 +#define HK_Contrast 0x05 +#define HK_Mute 0x06 +#define HK_Volume 0x07 +#define ModeSwitchStatus 0xf0 +#define ActiveCRT1 0x10 +#define ActiveLCD 0x0020 +#define ActiveTV 0x40 +#define ActiveCRT2 0x80 + +#define TVSwitchStatus 0x1f /* CR3E */ +#define ActiveAVideo 0x01 +#define ActiveSVideo 0x02 +#define ActiveSCART 0x04 +#define ActiveHiTV 0x08 +#define ActiveYPbPr 0x10 + +#define EnableHKEvent 0x01 /* CR3F */ +#define EnableOSDEvent 0x02 +#define StartOSDEvent 0x04 +#define IgnoreHKEvent 0x08 +#define IgnoreOSDEvent 0x10 +#else /* Old Scratch */ +#define OSD_SBIOS 0x02 /* SR17 */ +#define DisableLogo 0x04 +#define SelectKDOS 0x08 +#define KorWinMode 0x10 +#define KorMode3Bit 0x0020 +#define PSCCtrlBit 0x40 +#define NPSCCtrlBitShift 6 +#define BlueScreenBit 0x80 + +#define HKEvent 0x0f /* CR79 */ +#define HK_ModeSwitch 0x01 +#define HK_Expanding 0x02 +#define HK_OverScan 0x03 +#define HK_Brightness 0x04 +#define HK_Contrast 0x05 +#define HK_Mute 0x06 +#define HK_Volume 0x07 +#define ActivePAL 0x0020 +#define ActivePALShift 5 +#define ActiveNonExpanding 0x40 +#define ActiveNonExpandingShift 6 +#define ActiveOverScan 0x80 +#define ActiveOverScanShift 7 + +#define ModeSwitchStatus 0x0b /* SR15 */ +#define ActiveCRT1 0x01 +#define ActiveLCD 0x02 +#define ActiveCRT2 0x08 + +#define TVSwitchStatus 0xf0 /* SR16 */ +#define TVConfigShift 3 +#define ActiveTV 0x01 +#define ActiveYPbPr 0x04 +#define ActiveAVideo 0x10 +#define ActiveSVideo 0x0020 +#define ActiveSCART 0x40 +#define ActiveHiTV 0x80 + +#define EnableHKEvent 0x01 /* CR7A */ +#define EnableOSDEvent 0x02 +#define StartOSDEvent 0x04 +#define CMOSSupport 0x08 +#define HotKeySupport 0x10 +#define IngoreHKOSDEvent 0x20 +#endif + +/* //------------- Misc. Definition */ +#define SelectCRT1Rate 00h +/* #define SelectCRT2Rate 04h */ + +#define DDC1DelayTime 1000 +#ifdef TRUMPION +#define DDC2DelayTime 15 +#else +#define DDC2DelayTime 150 +#endif + +#define R_FACTOR 04Dh +#define G_FACTOR 097h +#define B_FACTOR 01Ch +/* --------------------------------------------------------- */ +/* translated from asm code 301def.h */ +/* */ +/* --------------------------------------------------------- */ +#define LCDDataLen 8 +#define HiTVDataLen 12 +#define TVDataLen 12 +#define LVDSCRT1Len_H 8 +#define LVDSCRT1Len_V 7 +#define LVDSDataLen 6 +#define LVDSDesDataLen 6 +#define LCDDesDataLen 6 +#define LVDSDesDataLen2 8 +#define LCDDesDataLen2 8 +#define CHTVRegLen 16 +#define CHLVRegLen 12 + +#define StHiTVHT 892 +#define StHiTVVT 1126 +#define StHiTextTVHT 1000 +#define StHiTextTVVT 1126 +#define ExtHiTVHT 2100 +#define ExtHiTVVT 1125 +#define NTSCHT 1716 +#define NTSCVT 525 +#define NTSC1024x768HT 1908 +#define NTSC1024x768VT 525 +#define PALHT 1728 +#define PALVT 625 + +#define YPbPrTV525iHT 1716 /* YPbPr */ +#define YPbPrTV525iVT 525 +#define YPbPrTV525pHT 1716 +#define YPbPrTV525pVT 525 +#define YPbPrTV750pHT 1650 +#define YPbPrTV750pVT 750 + +#define CRT2VCLKSel 0xc0 + +#define CRT2Delay1 0x04 /* XGI301 */ +#define CRT2Delay2 0x0A /* 301B,302 */ + + +#define VCLK25_175 0x00 +#define VCLK28_322 0x01 +#define VCLK31_5 0x02 +#define VCLK36 0x03 +#define VCLK40 0x04 +#define VCLK43_163 0x05 +#define VCLK44_9 0x06 +#define VCLK49_5 0x07 +#define VCLK50 0x08 +#define VCLK52_406 0x09 +#define VCLK56_25 0x0A +#define VCLK65 0x0B +#define VCLK67_765 0x0C +#define VCLK68_179 0x0D +#define VCLK72_852 0x0E +#define VCLK75 0x0F +#define VCLK75_8 0x10 +#define VCLK78_75 0x11 +#define VCLK79_411 0x12 +#define VCLK83_95 0x13 +#define VCLK84_8 0x14 +#define VCLK86_6 0x15 +#define VCLK94_5 0x16 +#define VCLK104_998 0x17 +#define VCLK105_882 0x18 +#define VCLK108_2 0x19 +#define VCLK109_175 0x1A +#define VCLK113_309 0x1B +#define VCLK116_406 0x1C +#define VCLK132_258 0x1D +#define VCLK135_5 0x1E +#define VCLK139_054 0x1F +#define VCLK157_5 0x20 +#define VCLK162 0x21 +#define VCLK175 0x22 +#define VCLK189 0x23 +#define VCLK194_4 0x24 +#define VCLK202_5 0x25 +#define VCLK229_5 0x26 +#define VCLK234 0x27 +#define VCLK252_699 0x28 +#define VCLK254_817 0x29 +#define VCLK265_728 0x2A +#define VCLK266_952 0x2B +#define VCLK269_655 0x2C +#define VCLK272_042 0x2D +#define VCLK277_015 0x2E +#define VCLK286_359 0x2F +#define VCLK291_132 0x30 +#define VCLK291_766 0x31 +#define VCLK309_789 0x32 +#define VCLK315_195 0x33 +#define VCLK323_586 0x34 +#define VCLK330_615 0x35 +#define VCLK332_177 0x36 +#define VCLK340_477 0x37 +#define VCLK375_847 0x38 +#define VCLK388_631 0x39 +#define VCLK125_999 0x51 +#define VCLK148_5 0x52 +#define VCLK178_992 0x54 +#define VCLK217_325 0x55 +#define VCLK299_505 0x56 +#define YPbPr750pVCLK 0x57 + +#define TVVCLKDIV2 0x3A +#define TVVCLK 0x3B +#define HiTVVCLKDIV2 0x3C +#define HiTVVCLK 0x3D +#define HiTVSimuVCLK 0x3E +#define HiTVTextVCLK 0x3F +#define VCLK39_77 0x40 +/* #define YPbPr750pVCLK 0x0F */ +#define YPbPr525pVCLK 0x3A +/* #define ;;YPbPr525iVCLK 0x3B */ +/* #define ;;YPbPr525iVCLK_2 0x3A */ +#define NTSC1024VCLK 0x41 +#define VCLK25_175_41 0x42 /* ; ScaleLCD */ +#define VCLK25_175_42 0x43 +#define VCLK28_322_43 0x44 +#define VCLK40_44 0x45 +#define VCLKQVGA_1 0x46 /* ; QVGA */ +#define VCLKQVGA_2 0x47 +#define VCLKQVGA_3 0x48 +#define VCLK35_2 0x49 /* ; 800x480 */ +#define VCLK122_61 0x4A +#define VCLK80_350 0x4B +#define VCLK107_385 0x4C + +#define CHTVVCLK30_2 0x50 /* ;;CHTV */ +#define CHTVVCLK28_1 0x51 +#define CHTVVCLK43_6 0x52 +#define CHTVVCLK26_4 0x53 +#define CHTVVCLK24_6 0x54 +#define CHTVVCLK47_8 0x55 +#define CHTVVCLK31_5 0x56 +#define CHTVVCLK26_2 0x57 +#define CHTVVCLK39 0x58 +#define CHTVVCLK36 0x59 + +#define CH7007TVVCLK30_2 0x00 /* [Billy] 2007/05/18 For CH7007 */ +#define CH7007TVVCLK28_1 0x01 +#define CH7007TVVCLK43_6 0x02 +#define CH7007TVVCLK26_4 0x03 +#define CH7007TVVCLK24_6 0x04 +#define CH7007TVVCLK47_8 0x05 +#define CH7007TVVCLK31_5 0x06 +#define CH7007TVVCLK26_2 0x07 +#define CH7007TVVCLK39 0x08 +#define CH7007TVVCLK36 0x09 + +#define RES320x200 0x00 +#define RES320x240 0x01 +#define RES400x300 0x02 +#define RES512x384 0x03 +#define RES640x400 0x04 +#define RES640x480x60 0x05 +#define RES640x480x72 0x06 +#define RES640x480x75 0x07 +#define RES640x480x85 0x08 +#define RES640x480x100 0x09 +#define RES640x480x120 0x0A +#define RES640x480x160 0x0B +#define RES640x480x200 0x0C +#define RES800x600x56 0x0D +#define RES800x600x60 0x0E +#define RES800x600x72 0x0F +#define RES800x600x75 0x10 +#define RES800x600x85 0x11 +#define RES800x600x100 0x12 +#define RES800x600x120 0x13 +#define RES800x600x160 0x14 +#define RES1024x768x43 0x15 +#define RES1024x768x60 0x16 +#define RES1024x768x70 0x17 +#define RES1024x768x75 0x18 +#define RES1024x768x85 0x19 +#define RES1024x768x100 0x1A +#define RES1024x768x120 0x1B +#define RES1280x1024x43 0x1C +#define RES1280x1024x60 0x1D +#define RES1280x1024x75 0x1E +#define RES1280x1024x85 0x1F +#define RES1600x1200x60 0x20 +#define RES1600x1200x65 0x21 +#define RES1600x1200x70 0x22 +#define RES1600x1200x75 0x23 +#define RES1600x1200x85 0x24 +#define RES1600x1200x100 0x25 +#define RES1600x1200x120 0x26 +#define RES1920x1440x60 0x27 +#define RES1920x1440x65 0x28 +#define RES1920x1440x70 0x29 +#define RES1920x1440x75 0x2A +#define RES1920x1440x85 0x2B +#define RES1920x1440x100 0x2C +#define RES2048x1536x60 0x2D +#define RES2048x1536x65 0x2E +#define RES2048x1536x70 0x2F +#define RES2048x1536x75 0x30 +#define RES2048x1536x85 0x31 +#define RES800x480x60 0x32 +#define RES800x480x75 0x33 +#define RES800x480x85 0x34 +#define RES1024x576x60 0x35 +#define RES1024x576x75 0x36 +#define RES1024x576x85 0x37 +#define RES1280x720x60 0x38 +#define RES1280x720x75 0x39 +#define RES1280x720x85 0x3A +#define RES1280x960x60 0x3B +#define RES720x480x60 0x3C +#define RES720x576x56 0x3D +#define RES856x480x79I 0x3E +#define RES856x480x60 0x3F +#define RES1280x768x60 0x40 +#define RES1400x1050x60 0x41 +#define RES1152x864x60 0x42 +#define RES1152x864x75 0x43 +#define RES1024x768x160 0x44 +#define RES1280x960x75 0x45 +#define RES1280x960x85 0x46 +#define RES1280x960x120 0x47 + +#define LFBDRAMTrap 0x30 +#endif diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c new file mode 100644 index 000000000000..49b39ee93a89 --- /dev/null +++ b/drivers/staging/xgifb/vb_ext.c @@ -0,0 +1,1370 @@ +#include "osdef.h" + + + + +#ifdef WIN2000 + +#include <dderror.h> +#include <devioctl.h> +#include <miniport.h> +#include <ntddvdeo.h> +#include <video.h> +#include "xgiv.h" +#include "dd_i2c.h" +#include "tools.h" +#endif /* WIN2000 */ + +#ifdef LINUX_XF86 +#include "xf86.h" +#include "xf86PciInfo.h" +#include "xgi.h" +#include "xgi_regs.h" +#endif + +#ifdef LINUX_KERNEL +#include <linux/version.h> +#include <asm/io.h> +#include <linux/types.h> +#include "XGIfb.h" +/*#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#include <video/XGIfb.h> +#else +#include <linux/XGIfb.h> +#endif*/ +#endif + + + +#include "vb_def.h" +#include "vgatypes.h" +#include "vb_struct.h" +#include "vb_util.h" +#include "vb_setmode.h" +#include "vb_ext.h" +extern UCHAR XGI330_SoftSetting; +extern UCHAR XGI330_OutputSelect; +extern USHORT XGI330_RGBSenseData2; +extern USHORT XGI330_YCSenseData2; +extern USHORT XGI330_VideoSenseData2; +#ifdef WIN2000 +extern UCHAR SenseCHTV(PHW_DEVICE_EXTENSION pHWDE); /* 2007/05/17 Billy */ +#endif +void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ); +BOOLEAN XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo); +USHORT XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo); +BOOLEAN XGINew_GetLCDDDCInfo(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo); +void XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE ) ; +BOOLEAN XGINew_BridgeIsEnable(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo ); +BOOLEAN XGINew_Sense(USHORT tempbx,USHORT tempcx, PVB_DEVICE_INFO pVBInfo); +BOOLEAN XGINew_SenseHiTV( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ; + +/************************************************************** + Dynamic Sense +*************************************************************/ + +void XGI_WaitDisplay(void); +BOOLEAN XGI_Is301C(PVB_DEVICE_INFO); +BOOLEAN XGI_Is301LV(PVB_DEVICE_INFO); + +#ifdef WIN2000 +UCHAR XGI_SenseLCD(PHW_DEVICE_EXTENSION, PVB_DEVICE_INFO); +UCHAR XGI_GetLCDDDCInfo(PHW_DEVICE_EXTENSION,PVB_DEVICE_INFO); + +extern BOOL bGetDdcInfo( +PHW_DEVICE_EXTENSION pHWDE, +ULONG ulWhichOne, +PUCHAR pjQueryBuffer, +ULONG ulBufferSize + ); + +#endif + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_Is301B */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGINew_Is301B( PVB_DEVICE_INFO pVBInfo ) +{ + USHORT flag ; + + flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) ; + + if ( flag > 0x0B0 ) + return( 0 ) ; /* 301b */ + else + return( 1 ) ; +} + +/* --------------------------------------------------------------------- */ +/* Function : XGI_Is301C */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGI_Is301C( PVB_DEVICE_INFO pVBInfo ) +{ + if ( ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) & 0xF0 ) == 0xC0 ) + return( 1 ) ; + + if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) >= 0xD0 ) + { + if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x39 ) == 0xE0 ) + return( 1 ) ; + } + + return( 0 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_Is301LV */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGI_Is301LV( PVB_DEVICE_INFO pVBInfo ) +{ + if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) >= 0xD0 ) + { + if ( XGINew_GetReg1( pVBInfo->Part4Port , 0x39 ) == 0xFF ) + { + return( 1 ) ; + } + } + return( 0 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_Sense */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGINew_Sense( USHORT tempbx , USHORT tempcx, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT temp , i , tempch ; + + temp = tempbx & 0xFF ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ; + temp = ( tempbx & 0xFF00 ) >> 8 ; + temp |= ( tempcx & 0x00FF ) ; + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ; + + for( i = 0 ; i < 10 ; i++ ) + XGI_LongWait( pVBInfo) ; + + tempch = ( tempcx & 0x7F00 ) >> 8 ; + temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ; + temp = temp ^ ( 0x0E ) ; + temp &= tempch ; + + if ( temp > 0 ) + return( 1 ) ; + else + return( 0 ) ; +} + +#ifdef WIN2000 +/* --------------------------------------------------------------------- */ +/* Function : XGI_SenseLCD */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +UCHAR XGI_SenseLCD( PHW_DEVICE_EXTENSION pHWDE, PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempax , tempbx , tempcx ; + UCHAR SoftSetting = XGI330_SoftSetting ; + + if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV ) ) + return( 1 ) ; + + + if ( SoftSetting & HotPlugFunction ) /* Hot Plug Detection */ + { + XGINew_SetRegAND( pVBInfo->Part4Port , 0x0F , 0x3F ) ; + tempbx = 0 ; + tempcx = 0x9010 ; + if ( XGINew_Sense( tempbx , tempcx, pVBInfo ) ) + return( 1 ) ; + + return( 0 ) ; + } + else /* Get LCD Info from EDID */ + return(XGI_GetLCDDDCInfo(pHWDE, pVBInfo)); +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetLCDDDCInfo */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +UCHAR XGI_GetLCDDDCInfo( PHW_DEVICE_EXTENSION pHWDE , PVB_DEVICE_INFO pVBInfo) +{ + UCHAR tempah , tempbl , tempbh ; + USHORT tempbx , temp ; + UCHAR pjEDIDBuf[ 256 ] ; + ULONG ulBufferSize = 256 ; + UCHAR bMASK_OUTPUTSTATE_CRT2LCD = 2 ; /* 0423 shampoo */ + + bGetDdcInfo( pHWDE , MASK_OUTPUTSTATE_CRT2LCD , pjEDIDBuf , ulBufferSize ) ; + if ( ( *( ( PULONG )pjEDIDBuf ) == 0xFFFFFF00 ) && ( *( ( PULONG )( pjEDIDBuf + 4 ) ) == 0x00FFFFFF ) ) + { + tempah = Panel1024x768 ; + tempbl=( *( pjEDIDBuf + 0x3A ) ) & 0xf0 ; + + if ( tempbl != 0x40 ) + { + tempah = Panel1600x1200 ; + if ( tempbl != 0x60 ) + { + tempah = Panel1280x1024 ; + tempbh = ( *( pjEDIDBuf + 0x3B ) ) ; + if ( tempbh != 0x00 ) + { + tempah = Panel1280x960 ; + if ( tempbh != 0x0C0 ) + { + tempbx = ( ( *( pjEDIDBuf + 0x24 ) ) << 8 ) | ( *( pjEDIDBuf + 0x23 ) ) ; + tempah = Panel1280x1024 ; + if ( !( tempbx & 0x0100 ) ) + { + tempah = Panel1024x768 ; + if ( !( tempbx & 0x0E00 ) ) + { + tempah = Panel1280x1024 ; + } + } + } + + if ( tempbx & 0x00FF ) + { + temp = ScalingLCD ; + XGINew_SetRegOR( pVBInfo->P3d4 , 0x37 , temp ) ; + } + } + } + } + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , ( ~0x07 ) , tempah ) ; + tempah = ( ( *( pjEDIDBuf + 0x47 ) ) & 0x06 ) ; /* Polarity */ + tempah = ( tempah ^ 0x06 ) << 4 ; + tempah |= LCDSync ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ( ~LCDSyncBit ) , tempah ) ; + tempbh= XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ; + tempbh &= 0x07 ; + if ( tempbh == Panel1280x960 ) + XGINew_SetRegAND( pVBInfo->P3d4 , 0x37 , 0x0E ) ; + } + else if ( *pjEDIDBuf == 0x20 ) + { + tempah = Panel1024x768 ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , ( ~0x07 ) , tempah ) ; + } + else + { + return( 0 ) ; + } + + return( 1 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_DySense */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGI_DySense( PHW_DEVICE_EXTENSION pHWDE , PUCHAR ujConnectStatus) +{ + UCHAR pre_CRD,pre_SR1E , pre_Part2_0 , pre_Part4_D ; + USHORT tempax , tempbx , tempcx , pushax , temp ; + VB_DEVICE_INFO VBINF; + PVB_DEVICE_INFO pVBInfo = &VBINF; + UCHAR OutputSelect = XGI330_OutputSelect ; + PXGI_HW_DEVICE_INFO HwDeviceExtension= pHWDE->pXGIHWDE ; + UCHAR bConnectStatus = 0 ; + pVBInfo->BaseAddr = HwDeviceExtension->pjIOAddress ; + pVBInfo->ROMAddr = pHWDE->pjVirtualRomBase ; + + pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ; + pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ; + pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ; + pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ; + pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ; + pushax = XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ; /* 0512 Fix Dysense hanged */ + temp = ( pushax & 0x00FF ) | 0x80 ; + XGINew_SetRegOR( pVBInfo->P3d4 , 0x17 , temp ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ; + /* beginning of dynamic sense CRT1 */ + + pVBInfo->IF_DEF_CH7007 = 0; + if (pHWDE->bCH7007) + { + InitTo330Pointer( pHWDE->pXGIHWDE->jChipType, pVBInfo ) ; + HwDeviceExtension->pDevice = (PVOID)pHWDE; + pVBInfo->IF_DEF_CH7007 = 1; + /* [Billy] 2007/05/14 For CH7007 */ + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + bConnectStatus = SenseCHTV(HwDeviceExtension->pDevice) ; /* 07/05/28 */ + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~0x03 , (UCHAR)bConnectStatus ) ; + } + } + if(( pHWDE->jChipID >= XG40 ) || ( pHWDE->jChipID >= XG20 )) + { + + if ( pHWDE->jChipID >= XG40 ) + XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x4A ) ; /* write sense pattern 30->4a */ + else + XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x5F ) ; /* write sense pattern */ + + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x53 , 0xFF , 0x02 ) ; /* enable sense DAC */ + XGI_WaitDisply(pVBInfo) ; + + if(XGINew_GetReg2( pVBInfo->P3c2 ) & 0x10 ) + bConnectStatus |= Monitor1Sense ; + + XGINew_SetRegAND( pVBInfo->P3d4 , 0x53 , 0xFD ) ; /* disable sense DAC */ + XGINew_SetRegAND( pVBInfo->P3d4 , 0x57 , 0x00 ) ; /* clear sense pattern */ + + + /* ---------- End of dynamic sense CRT1 ----------- */ + + /* ---------- beginning of dynamic sense VB ------------ */ + pre_SR1E = XGINew_GetReg1( pVBInfo->P3c4 , 0x1E ) ; + XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x20 ) ; /* Enable CRT2,work-a-round for 301B/301LV/302LV */ + pre_Part2_0 = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ; + pre_Part4_D = XGINew_GetReg1( pVBInfo->Part4Port , 0x0D ) ; + + if ( XGI_Is301C( pVBInfo ) ) /* 301C only */ + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~0x07 , 0x01 ) ; /* Set Part4 0x0D D[2:0] to 001b */ + + /* tempax = 0 ; */ + if ( !XGI_Is301LV( pVBInfo ) ) + { + tempbx = XGI330_RGBSenseData2 ; + tempcx = 0x0E08 ; + if(XGINew_Sense( tempbx , tempcx, pVBInfo ) ) + { + bConnectStatus |= Monitor2Sense ; + if ( OutputSelect & SetSCARTOutput ) + { + bConnectStatus ^= ( Monitor2Sense | SCARTSense ) ; + } + } + } + if ( XGI_Is301C( pVBInfo ) ) /* 301C only */ + XGINew_SetRegOR( pVBInfo->Part4Port , 0x0D , 0x04 ) ; /* Set Part4 0x0D D[2]=1 for dynamic sense */ + + if ( ( XGINew_Is301B( pVBInfo ) ) ) + XGINew_SetRegOR( pVBInfo->Part2Port , 0x00 , 0x0C ) ; /* ????????? */ + + if ( XGINew_SenseHiTV( HwDeviceExtension , pVBInfo) ) /* add by kuku for Dysense HiTV //start */ + { + bConnectStatus|= YPbPrSense ; + } + else + { + tempbx = XGI330_YCSenseData2 ; /* Y/C Sense Data Ptr */ + tempcx = 0x0604 ; + if ( XGINew_Sense( tempbx , tempcx , pVBInfo) ) + bConnectStatus |= SVIDEOSense ; + + if ( OutputSelect & BoardTVType ) + { + tempbx = XGI330_VideoSenseData2 ; + tempcx = 0x0804 ; + if ( XGINew_Sense(tempbx , tempcx, pVBInfo) ) + bConnectStatus|= AVIDEOSense ; + } + else + { + if ( !( bConnectStatus & SVIDEOSense ) ) + { + tempbx = XGI330_VideoSenseData2 ; + tempcx = 0x0804 ; + if ( XGINew_Sense( tempbx , tempcx, pVBInfo ) ) + bConnectStatus |= AVIDEOSense ; + } + } + } /* end */ + /* DySenseVBCnt */ + + tempbx = 0 ; + tempcx = 0 ; + XGINew_Sense(tempbx , tempcx, pVBInfo ) ; + + if ( !( bConnectStatus & Monitor2Sense ) ) + { + if ( XGI_SenseLCD( pHWDE , pVBInfo ) ) + bConnectStatus |= LCDSense ; + } + + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~( AVIDEOSense | SVIDEOSense | LCDSense | Monitor2Sense | Monitor1Sense ) , bConnectStatus ) ; + + XGINew_SetReg1( pVBInfo->Part4Port , 0x0D , pre_Part4_D ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , pre_Part2_0 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x1E , pre_SR1E ) ; + + if ( XGI_Is301C( pVBInfo ) ) /* 301C only */ + { + tempax = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ; + if ( tempax & 0x20 ) + { + /* Reset VBPro */ + for( tempcx = 2 ; tempcx > 0 ; tempcx-- ) + { + tempax ^= 0x20 ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , tempax ) ; + } + } + } + /* End of dynamic sense VB */ + } + else + { + XGI_SenseCRT1(pVBInfo) ; + XGI_GetSenseStatus( HwDeviceExtension, pVBInfo ) ; /* sense CRT2 */ + bConnectStatus = XGINew_GetReg1( pVBInfo->P3d4 , 0x32 ) ; + } + temp = pushax & 0x00FF ; /* 0512 Fix Dysense hanged */ + XGINew_SetReg1( pVBInfo->P3d4 , 0x17 , temp ) ; + if ( bConnectStatus ) + { + *ujConnectStatus = bConnectStatus ; + return( 1 ) ; + } + else + return( 0 ) ; +} + +#endif /* WIN2000 */ + +/* --------------------------------------------------------------------- */ +/* Function : XGISetDPMS */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +VOID XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE ) +{ + USHORT ModeNo, ModeIdIndex ; + UCHAR temp ; + VB_DEVICE_INFO VBINF; + PVB_DEVICE_INFO pVBInfo = &VBINF; + pVBInfo->BaseAddr = (ULONG)pXGIHWDE->pjIOAddress ; + pVBInfo->ROMAddr = pXGIHWDE->pjVirtualRomBase ; + + + pVBInfo->IF_DEF_LVDS = 0 ; + pVBInfo->IF_DEF_CH7005 = 0 ; + pVBInfo->IF_DEF_HiVision = 1 ; + pVBInfo->IF_DEF_LCDA = 1 ; + pVBInfo->IF_DEF_CH7017 = 0 ; + pVBInfo->IF_DEF_YPbPr = 1 ; + pVBInfo->IF_DEF_CRT2Monitor = 0 ; + pVBInfo->IF_DEF_VideoCapture = 0 ; + pVBInfo->IF_DEF_ScaleLCD = 0 ; + pVBInfo->IF_DEF_OEMUtil = 0 ; + pVBInfo->IF_DEF_PWD = 0 ; + + InitTo330Pointer( pXGIHWDE->jChipType, pVBInfo ) ; + ReadVBIOSTablData( pXGIHWDE->jChipType , pVBInfo) ; + + pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ; + pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ; + pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ; + pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ; + pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ; + pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ; + pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ; + pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ; + pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ; + pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ; + pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ; + pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ; + pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ; + pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ; + pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ; + pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ; + pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ; + + if ( pXGIHWDE->jChipType == XG27 ) + { + if ( ( XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) & 0xE0 ) == 0xC0 ) + { + if ( XGINew_GetReg1( pVBInfo->P3d4 , 0x30 ) & 0x20 ) + { + pVBInfo->IF_DEF_LVDS = 1 ; + } + } + } + + if ( pVBInfo->IF_DEF_CH7007 == 0 ) + { + XGINew_SetModeScratch ( pXGIHWDE , pVBInfo ) ; + } + XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ; /* 1.Openkey */ + XGI_UnLockCRT2( pXGIHWDE , pVBInfo) ; + ModeNo = XGINew_GetReg1( pVBInfo->P3d4 , 0x34 ) ; + XGI_SearchModeID( ModeNo , &ModeIdIndex, pVBInfo ) ; + XGI_GetVGAType( pXGIHWDE , pVBInfo ) ; + + if ( ( pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) || ( pVBInfo->IF_DEF_CH7007 == 1 )) + { + XGI_GetVBType( pVBInfo ) ; + XGI_GetVBInfo( ModeNo , ModeIdIndex , pXGIHWDE, pVBInfo ) ; + XGI_GetTVInfo( ModeNo , ModeIdIndex, pVBInfo ) ; + XGI_GetLCDInfo( ModeNo , ModeIdIndex, pVBInfo ) ; + } + + if ( VESA_POWER_STATE == 0x00000400 ) + XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , ( UCHAR )( XGINew_GetReg1( pVBInfo->Part4Port , 0x31 ) & 0xFE ) ) ; + else + XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , ( UCHAR )( XGINew_GetReg1( pVBInfo->Part4Port , 0x31 ) | 0x01 ) ) ; + + temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x1f ) ; + temp &= 0x3f ; + switch ( VESA_POWER_STATE ) + { + case 0x00000000: /* on */ + if ( ( pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) ) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x00 ) ) ; + XGI_EnableBridge( pXGIHWDE, pVBInfo ) ; + } + else + { + if ( pXGIHWDE->jChipType == XG21 ) + { + if ( pVBInfo->IF_DEF_LVDS == 1 ) + { + XGI_XG21BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */ + XGI_XG21SetPanelDelay( 2,pVBInfo ) ; + } + } + if ( pXGIHWDE->jChipType == XG27 ) + { + if ( pVBInfo->IF_DEF_LVDS == 1 ) + { + XGI_XG27BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */ + XGI_XG21SetPanelDelay( 2,pVBInfo ) ; + } + } + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1F , ~0xC0 , 0x00 ) ; + XGINew_SetRegAND( pVBInfo->P3c4 , 0x01 , ~0x20 ) ; /* CRT on */ + + if ( pXGIHWDE->jChipType == XG21 ) + { + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ; + if ( temp & 0xE0 ) + { + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0x80 , 0x80 ) ; /* DVO ON */ + XGI_SetXG21FPBits( pVBInfo ); + XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ; /* Enable write GPIOF */ + /*XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x48 , ~0x20 , 0x20 ) ;*/ /* LCD Display ON */ + } + XGI_XG21BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */ + XGI_DisplayOn( pXGIHWDE, pVBInfo ); + } + if ( pXGIHWDE->jChipType == XG27 ) + { + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ; + if ( temp & 0xE0 ) + { + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0x80 , 0x80 ) ; /* DVO ON */ + XGI_SetXG27FPBits( pVBInfo ); + XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ; /* Enable write GPIOF */ + /*XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x48 , ~0x20 , 0x20 ) ;*/ /* LCD Display ON */ + } + XGI_XG27BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */ + XGI_DisplayOn( pXGIHWDE, pVBInfo ); + } + } + break ; + case 0x00000100: /* standby */ + if ( pXGIHWDE->jChipType >= XG21 ) + { + XGI_DisplayOff( pXGIHWDE, pVBInfo ); + } + + XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x40 ) ) ; + break ; + case 0x00000200: /* suspend */ + if ( pXGIHWDE->jChipType == XG21 ) + { + XGI_DisplayOff( pXGIHWDE, pVBInfo ); + XGI_XG21BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */ + } + if ( pXGIHWDE->jChipType == XG27 ) + { + XGI_DisplayOff( pXGIHWDE, pVBInfo ); + XGI_XG27BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */ + } + XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0x80 ) ) ; + break ; + case 0x00000400: /* off */ + if ( (pXGIHWDE->ujVBChipID == VB_CHIP_301 ) || ( pXGIHWDE->ujVBChipID == VB_CHIP_302 ) ) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x1f , ( UCHAR )( temp | 0xc0 ) ) ; + XGI_DisableBridge( pXGIHWDE, pVBInfo ) ; + } + else + { + if ( pXGIHWDE->jChipType == XG21 ) + { + XGI_DisplayOff( pXGIHWDE, pVBInfo ); + + XGI_XG21BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */ + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ; + if ( temp & 0xE0 ) + { + XGINew_SetRegAND( pVBInfo->P3c4 , 0x09 , ~0x80 ) ; /* DVO Off */ + XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ; /* Enable write GPIOF */ + /*XGINew_SetRegAND( pVBInfo->P3d4 , 0x48 , ~0x20 ) ;*/ /* LCD Display OFF */ + } + } + if ( pXGIHWDE->jChipType == XG27 ) + { + XGI_DisplayOff( pXGIHWDE, pVBInfo ); + + XGI_XG27BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* LVDS signal off */ + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ; + if ( temp & 0xE0 ) + { + XGINew_SetRegAND( pVBInfo->P3c4 , 0x09 , ~0x80 ) ; /* DVO Off */ + } + } + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1F , ~0xC0 , 0xC0 ) ; + XGINew_SetRegOR( pVBInfo->P3c4 , 0x01 , 0x20 ) ; /* CRT Off */ + + if ( ( pXGIHWDE->jChipType == XG21 ) && ( pVBInfo->IF_DEF_LVDS == 1 ) ) + { + XGI_XG21SetPanelDelay( 4,pVBInfo ) ; + XGI_XG21BLSignalVDD( 0x01 , 0x00, pVBInfo ) ; /* LVDS VDD off */ + XGI_XG21SetPanelDelay( 5,pVBInfo ) ; + } + if ( ( pXGIHWDE->jChipType == XG27 ) && ( pVBInfo->IF_DEF_LVDS == 1 ) ) + { + XGI_XG21SetPanelDelay( 4,pVBInfo ) ; + XGI_XG27BLSignalVDD( 0x01 , 0x00, pVBInfo ) ; /* LVDS VDD off */ + XGI_XG21SetPanelDelay( 5,pVBInfo ) ; + } + } + break ; + + default: + break ; + } + XGI_LockCRT2( pXGIHWDE , pVBInfo ) ; +} + + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetSenseStatus */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempax = 0 , tempbx , tempcx , temp , + P2reg0 = 0 , SenseModeNo = 0 , OutputSelect = *pVBInfo->pOutputSelect , + ModeIdIndex , i ; + pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ; + + if ( pVBInfo->IF_DEF_LVDS == 1 ) + { + tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ; /* ynlai 02/27/2002 */ + tempbx = XGINew_GetReg1( pVBInfo->P3c4 , 0x1B ) ; + tempax = ( ( tempax & 0xFE ) >> 1 ) | ( tempbx << 8 ) ; + if ( tempax == 0x00 ) + { /* Get Panel id from DDC */ + temp = XGINew_GetLCDDDCInfo( HwDeviceExtension, pVBInfo ) ; + if ( temp == 1 ) + { /* LCD connect */ + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x39 , 0xFF , 0x01 ) ; /* set CR39 bit0="1" */ + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , 0xEF , 0x00 ) ; /* clean CR37 bit4="0" */ + temp = LCDSense ; + } + else + { /* LCD don't connect */ + temp = 0 ; + } + } + else + { + XGINew_GetPanelID(pVBInfo) ; + temp = LCDSense ; + } + + tempbx = ~( LCDSense | AVIDEOSense | SVIDEOSense ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , tempbx , temp ) ; + } + else + { /* for 301 */ + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { /* for HiVision */ + tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x38 ) ; + temp = tempax & 0x01 ; + tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x3A ) ; + temp = temp | ( tempax & 0x02 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , 0xA0 , temp ) ; + } + else + { + if ( XGI_BridgeIsOn( pVBInfo ) ) + { + P2reg0 = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ; + if ( !XGINew_BridgeIsEnable( HwDeviceExtension, pVBInfo ) ) + { + SenseModeNo = 0x2e ; + /* XGINew_SetReg1( pVBInfo->P3d4 , 0x30 , 0x41 ) ; */ + /* XGISetModeNew( HwDeviceExtension , 0x2e ) ; // ynlai InitMode */ + + temp = XGI_SearchModeID( SenseModeNo , &ModeIdIndex, pVBInfo ) ; + XGI_GetVGAType( HwDeviceExtension , pVBInfo) ; + XGI_GetVBType( pVBInfo ) ; + pVBInfo->SetFlag = 0x00 ; + pVBInfo->ModeType = ModeVGA ; + pVBInfo->VBInfo = SetCRT2ToRAMDAC | LoadDACFlag | SetInSlaveMode ; + XGI_GetLCDInfo( 0x2e , ModeIdIndex, pVBInfo ) ; + XGI_GetTVInfo( 0x2e , ModeIdIndex, pVBInfo ) ; + XGI_EnableBridge( HwDeviceExtension, pVBInfo ) ; + XGI_SetCRT2Group301( SenseModeNo , HwDeviceExtension, pVBInfo ) ; + XGI_SetCRT2ModeRegs( 0x2e , HwDeviceExtension, pVBInfo ) ; + /* XGI_DisableBridge( HwDeviceExtension, pVBInfo ) ; */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xDF , 0x20 ) ; /* Display Off 0212 */ + for( i = 0 ; i < 20 ; i++ ) + { + XGI_LongWait(pVBInfo) ; + } + } + XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , 0x1c ) ; + tempax = 0 ; + tempbx = *pVBInfo->pRGBSenseData ; + + if ( !( XGINew_Is301B( pVBInfo ) ) ) + { + tempbx = *pVBInfo->pRGBSenseData2 ; + } + + tempcx = 0x0E08 ; + if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) ) + { + if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) ) + { + tempax |= Monitor2Sense ; + } + } + + if ( pVBInfo->VBType & VB_XGI301C) + { + XGINew_SetRegOR( pVBInfo->Part4Port , 0x0d , 0x04 ) ; + } + + if ( XGINew_SenseHiTV( HwDeviceExtension , pVBInfo) ) /* add by kuku for Multi-adapter sense HiTV */ + { + tempax |= HiTVSense ; + if ( ( pVBInfo->VBType & VB_XGI301C ) ) + { + tempax ^= ( HiTVSense | YPbPrSense ) ; + } + } + + if ( !( tempax & ( HiTVSense | YPbPrSense ) ) ) /* start */ + { + + tempbx = *pVBInfo->pYCSenseData ; + + if ( !( XGINew_Is301B( pVBInfo ) ) ) + { + tempbx=*pVBInfo->pYCSenseData2; + } + + tempcx = 0x0604 ; + if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) ) + { + if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) ) + { + tempax |= SVIDEOSense ; + } + } + + if ( OutputSelect & BoardTVType ) + { + tempbx = *pVBInfo->pVideoSenseData ; + + if ( !( XGINew_Is301B( pVBInfo ) ) ) + { + tempbx = *pVBInfo->pVideoSenseData2 ; + } + + tempcx = 0x0804 ; + if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) ) + { + if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) ) + { + tempax |= AVIDEOSense ; + } + } + } + else + { + if ( !( tempax & SVIDEOSense ) ) + { + tempbx = *pVBInfo->pVideoSenseData ; + + if ( !( XGINew_Is301B( pVBInfo ) ) ) + { + tempbx=*pVBInfo->pVideoSenseData2; + } + + tempcx = 0x0804 ; + if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) ) + { + if ( XGINew_Sense(tempbx , tempcx, pVBInfo ) ) + { + tempax |= AVIDEOSense ; + } + } + } + } + } + } /* end */ + if ( !( tempax & Monitor2Sense ) ) + { + if ( XGINew_SenseLCD( HwDeviceExtension, pVBInfo ) ) + { + tempax |= LCDSense ; + } + } + tempbx = 0 ; + tempcx = 0 ; + XGINew_Sense(tempbx , tempcx, pVBInfo ) ; + + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~0xDF , tempax ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , P2reg0 ) ; + + if ( !( P2reg0 & 0x20 ) ) + { + pVBInfo->VBInfo = DisableCRT2Display ; + /* XGI_SetCRT2Group301( SenseModeNo , HwDeviceExtension, pVBInfo ) ; */ + } + } + } + XGI_DisableBridge( HwDeviceExtension, pVBInfo ) ; /* shampoo 0226 */ + +} + + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SenseLCD */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +USHORT XGINew_SenseLCD( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo) +{ + /* USHORT SoftSetting ; */ + USHORT temp ; + + if ( ( HwDeviceExtension->jChipType >= XG20 ) || ( HwDeviceExtension->jChipType >= XG40 ) ) + temp = 0 ; + else + temp=XGINew_GetPanelID(pVBInfo) ; + + if( !temp ) + temp = XGINew_GetLCDDDCInfo( HwDeviceExtension, pVBInfo ) ; + + return( temp ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_GetLCDDDCInfo */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGINew_GetLCDDDCInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo) +{ + USHORT temp ; + + /* add lcd sense */ + if ( HwDeviceExtension->ulCRT2LCDType == LCD_UNKNOWN ) + { + return( 0 ) ; + } + else + { + temp = ( USHORT )HwDeviceExtension->ulCRT2LCDType ; + switch( HwDeviceExtension->ulCRT2LCDType ) + { + case LCD_INVALID: + case LCD_800x600: + case LCD_1024x768: + case LCD_1280x1024: + break ; + + case LCD_640x480: + case LCD_1024x600: + case LCD_1152x864: + case LCD_1280x960: + case LCD_1152x768: + temp = 0 ; + break ; + + case LCD_1400x1050: + case LCD_1280x768: + case LCD_1600x1200: + break ; + + case LCD_1920x1440: + case LCD_2048x1536: + temp = 0 ; + break ; + + default: + break ; + } + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x36 , 0xF0 , temp ) ; + return( 1 ) ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGINew_GetPanelID(PVB_DEVICE_INFO pVBInfo ) +{ + USHORT PanelTypeTable[ 16 ] = { SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType00 , + SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType01 , + SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType02 , + SyncNN | PanelRGB18Bit | Panel640x480 | _PanelType03 , + SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType04 , + SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType05 , + SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType06 , + SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType07 , + SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType08 , + SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType09 , + SyncNN | PanelRGB18Bit | Panel800x600 | _PanelType0A , + SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0B , + SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0C , + SyncNN | PanelRGB24Bit | Panel1024x768 | _PanelType0D , + SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0E , + SyncNN | PanelRGB18Bit | Panel1024x768 | _PanelType0F } ; + USHORT tempax , tempbx , temp ; + /* USHORT return_flag ; */ + + tempax = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ; + tempbx = tempax & 0x1E ; + + if ( tempax == 0 ) + return( 0 ) ; + else + { +/* + if ( !( tempax & 0x10 ) ) + { + if ( pVBInfo->IF_DEF_LVDS == 1 ) + { + tempbx = 0 ; + temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x38 ) ; + if ( temp & 0x40 ) + tempbx |= 0x08 ; + if ( temp & 0x20 ) + tempbx |= 0x02 ; + if ( temp & 0x01 ) + tempbx |= 0x01 ; + + temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) ; + if ( temp & 0x80 ) + tempbx |= 0x04 ; + } + else + { + return( 0 ) ; + } + } +*/ + + tempbx = tempbx >> 1 ; + temp = tempbx & 0x00F ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x36 , temp ) ; + tempbx-- ; + tempbx = PanelTypeTable[ tempbx ] ; + + temp = ( tempbx & 0xFF00 ) >> 8 ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ~( LCDSyncBit | LCDRGB18Bit ) , temp ) ; + return( 1 ) ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_BridgeIsEnable */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGINew_BridgeIsEnable( PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo) +{ + USHORT flag ; + + if ( XGI_BridgeIsOn( pVBInfo ) == 0 ) + { + flag = XGINew_GetReg1( pVBInfo->Part1Port , 0x0 ) ; + + if ( flag & 0x050 ) + { + return( 1 ) ; + } + else + { + return( 0 ) ; + } + + } + return( 0 ) ; +} + +/* ------------------------------------------------------ */ +/* Function : XGINew_SenseHiTV */ +/* Input : */ +/* Output : */ +/* Description : */ +/* ------------------------------------------------------ */ +BOOLEAN XGINew_SenseHiTV( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempbx , tempcx , temp , i , tempch; + + tempbx = *pVBInfo->pYCSenseData2 ; + + tempcx = 0x0604 ; + + temp = tempbx & 0xFF ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ; + temp = ( tempbx & 0xFF00 ) >> 8 ; + temp |= ( tempcx & 0x00FF ) ; + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ; + + for( i = 0 ; i < 10 ; i++ ) + XGI_LongWait(pVBInfo) ; + + tempch = ( tempcx & 0xFF00 ) >> 8; + temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ; + temp = temp ^ ( 0x0E ) ; + temp &= tempch ; + + if ( temp != tempch ) + return( 0 ) ; + + tempbx = *pVBInfo->pVideoSenseData2 ; + + tempcx = 0x0804 ; + temp = tempbx & 0xFF ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ; + temp = ( tempbx & 0xFF00 ) >> 8 ; + temp |= ( tempcx & 0x00FF ) ; + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ; + + for( i = 0 ; i < 10 ; i++ ) + XGI_LongWait(pVBInfo) ; + + tempch = ( tempcx & 0xFF00 ) >> 8; + temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ; + temp = temp ^ ( 0x0E ) ; + temp &= tempch ; + + if ( temp != tempch ) + return( 0 ) ; + else + { + tempbx = 0x3FF ; + tempcx = 0x0804 ; + temp = tempbx & 0xFF ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x11 , temp ) ; + temp = ( tempbx & 0xFF00 ) >> 8 ; + temp |= ( tempcx & 0x00FF ) ; + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x10 , ~0x1F , temp ) ; + + for( i = 0 ; i < 10 ; i++ ) + XGI_LongWait(pVBInfo) ; + + tempch = ( tempcx & 0xFF00 ) >> 8; + temp = XGINew_GetReg1( pVBInfo->Part4Port , 0x03 ) ; + temp = temp ^ ( 0x0E ) ; + temp &= tempch ; + + if ( temp != tempch ) + return( 1 ) ; + else + return( 0 ) ; + } +} + + + +/* +;----------------------------------------------------------------------------- +; Description: Get Panel support +; O/P : +; BL: Panel ID=81h for no scaler LVDS +; BH: Panel enhanced Mode Count +; CX: Panel H. resolution +; DX: PAnel V. resolution +;----------------------------------------------------------------------------- +*/ +void XGI_XG21Fun14Sub70( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments ) +{ + + USHORT ModeIdIndex; + USHORT ModeNo; + + USHORT EModeCount; + USHORT lvdstableindex; + + lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo ); + pBiosArguments->h.bl = 0x81; + pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE; + pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE; + EModeCount = 0; + + pBiosArguments->x.ax = 0x0014; + for( ModeIdIndex = 0 ; ; ModeIdIndex ++ ) + { + ModeNo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID; + if ( pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID == 0xFF ) + { + pBiosArguments->h.bh = (UCHAR) EModeCount; + return; + } + if ( !XGI_XG21CheckLVDSMode( ModeNo , ModeIdIndex, pVBInfo) ) + { + continue; + } + EModeCount++ ; + } +} +/*( +;----------------------------------------------------------------------------- +; +; Description: Get Panel mode ID for enhanced mode +; I/P : BH: EModeIndex ( which < Panel enhanced Mode Count ) +; O/P : +; BL: Mode ID +; CX: H. resolution of the assigned by the index +; DX: V. resolution of the assigned by the index +; +;----------------------------------------------------------------------------- +*/ +void XGI_XG21Fun14Sub71( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments ) +{ + + USHORT EModeCount; + USHORT ModeIdIndex,resindex; + USHORT ModeNo; + USHORT EModeIndex = pBiosArguments->h.bh; + + EModeCount = 0; + for( ModeIdIndex = 0 ; ; ModeIdIndex ++ ) + { + ModeNo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID; + if ( pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeID == 0xFF ) + { + pBiosArguments->x.ax = 0x0114; + return; + } + if ( !XGI_XG21CheckLVDSMode( ModeNo , ModeIdIndex, pVBInfo) ) + { + continue; + } + if (EModeCount == EModeIndex) + { + resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ; + pBiosArguments->h.bl = (UCHAR) ModeNo; + pBiosArguments->x.cx = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */ + pBiosArguments->x.dx = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */ + pBiosArguments->x.ax = 0x0014; + } + EModeCount++ ; + + } + +} +/* +;----------------------------------------------------------------------------- +; +; Description: Validate Panel modes ID support +; I/P : +; BL: ModeID +; O/P : +; CX: H. resolution of the assigned by the index +; DX: V. resolution of the assigned by the index +; +;----------------------------------------------------------------------------- +*/ +void XGI_XG21Fun14Sub72( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments ) +{ + USHORT ModeIdIndex,resindex; + USHORT ModeNo; + + + ModeNo = pBiosArguments->h.bl ; + XGI_SearchModeID( ModeNo, &ModeIdIndex, pVBInfo); + if ( !XGI_XG21CheckLVDSMode( ModeNo , ModeIdIndex, pVBInfo) ) + { + pBiosArguments->x.cx = 0; + pBiosArguments->x.dx = 0; + pBiosArguments->x.ax = 0x0114; + return; + } + resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ; + if ( ModeNo <= 0x13 ) + { + pBiosArguments->x.cx = pVBInfo->StResInfo[ resindex ].HTotal ; + pBiosArguments->x.dx = pVBInfo->StResInfo[ resindex ].VTotal ; + } + else + { + pBiosArguments->x.cx = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */ + pBiosArguments->x.dx = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */ + } + + pBiosArguments->x.ax = 0x0014; + +} + +/* +;----------------------------------------------------------------------------- +; Description: Get Customized Panel misc. information support +; I/P : Select +; to get panel horizontal timing +; to get panel vertical timing +; to get channel clock parameter +; to get panel misc information +; +; O/P : +; BL: for input Select = 0 ; +; BX: *Value1 = Horizontal total +; CX: *Value2 = Horizontal front porch +; DX: *Value2 = Horizontal sync width +; BL: for input Select = 1 ; +; BX: *Value1 = Vertical total +; CX: *Value2 = Vertical front porch +; DX: *Value2 = Vertical sync width +; BL: for input Select = 2 ; +; BX: Value1 = The first CLK parameter +; CX: Value2 = The second CLK parameter +; BL: for input Select = 4 ; +; BX[15]: *Value1 D[15] VESA V. Polarity +; BX[14]: *Value1 D[14] VESA H. Polarity +; BX[7]: *Value1 D[7] Panel V. Polarity +; BX[6]: *Value1 D[6] Panel H. Polarity +;----------------------------------------------------------------------------- +*/ +void XGI_XG21Fun14Sub73( PVB_DEVICE_INFO pVBInfo , PX86_REGS pBiosArguments ) +{ + UCHAR Select; + + USHORT lvdstableindex; + + lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo ); + Select = pBiosArguments->h.bl; + + switch (Select) + { + case 0: + pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT; + pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP; + pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC; + break; + case 1: + pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT; + pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP; + pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC; + break; + case 2: + pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1; + pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2; + break; + case 4: + pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability; + break; + } + + pBiosArguments->x.ax = 0x0014; +} + + +void XGI_XG21Fun14( PXGI_HW_DEVICE_INFO pXGIHWDE, PX86_REGS pBiosArguments) +{ + VB_DEVICE_INFO VBINF; + PVB_DEVICE_INFO pVBInfo = &VBINF; + + pVBInfo->IF_DEF_LVDS = 0 ; + pVBInfo->IF_DEF_CH7005 = 0 ; + pVBInfo->IF_DEF_HiVision = 1 ; + pVBInfo->IF_DEF_LCDA = 1 ; + pVBInfo->IF_DEF_CH7017 = 0 ; + pVBInfo->IF_DEF_YPbPr = 1 ; + pVBInfo->IF_DEF_CRT2Monitor = 0 ; + pVBInfo->IF_DEF_VideoCapture = 0 ; + pVBInfo->IF_DEF_ScaleLCD = 0 ; + pVBInfo->IF_DEF_OEMUtil = 0 ; + pVBInfo->IF_DEF_PWD = 0 ; + + InitTo330Pointer( pXGIHWDE->jChipType, pVBInfo ) ; + ReadVBIOSTablData( pXGIHWDE->jChipType , pVBInfo) ; + + pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ; + pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ; + pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ; + pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ; + pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ; + pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ; + pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ; + pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ; + pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ; + pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ; + pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ; + pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ; + pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ; + pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ; + pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ; + pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ; + pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ; + + switch(pBiosArguments->x.ax) + { + case 0x1470: + XGI_XG21Fun14Sub70( pVBInfo , pBiosArguments ) ; + break; + case 0x1471: + XGI_XG21Fun14Sub71( pVBInfo , pBiosArguments ) ; + break; + case 0x1472: + XGI_XG21Fun14Sub72( pVBInfo , pBiosArguments ) ; + break; + case 0x1473: + XGI_XG21Fun14Sub73( pVBInfo , pBiosArguments ) ; + break; + } +} diff --git a/drivers/staging/xgifb/vb_ext.h b/drivers/staging/xgifb/vb_ext.h new file mode 100644 index 000000000000..9a72f5ecb713 --- /dev/null +++ b/drivers/staging/xgifb/vb_ext.h @@ -0,0 +1,32 @@ +#ifndef _VBEXT_ +#define _VBEXT_ + +struct DWORDREGS { + ULONG Eax, Ebx, Ecx, Edx, Esi, Edi, Ebp; +}; + +struct WORDREGS { + USHORT ax, hi_ax, bx, hi_bx, cx, hi_cx, dx, hi_dx, si, hi_si, di ,hi_di, bp, hi_bp; +}; + +struct BYTEREGS { + UCHAR al, ah, hi_al, hi_ah, bl, bh, hi_bl, hi_bh, cl, ch, hi_cl, hi_ch, dl, dh, hi_dl, hi_dh; +}; + +typedef union _X86_REGS { + struct DWORDREGS e; + struct WORDREGS x; + struct BYTEREGS h; +} X86_REGS, *PX86_REGS; + +extern void XGI_XG21Fun14( PXGI_HW_DEVICE_INFO pXGIHWDE, PX86_REGS pBiosArguments); +extern void XGISetDPMS( PXGI_HW_DEVICE_INFO pXGIHWDE , ULONG VESA_POWER_STATE ) ; +extern void XGI_GetSenseStatus( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ); +extern void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ; +extern void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo); +extern USHORT XGINew_SenseLCD(PXGI_HW_DEVICE_INFO,PVB_DEVICE_INFO pVBInfo); +#ifdef WIN2000 +extern BOOLEAN XGI_DySense( PHW_DEVICE_EXTENSION pHWDE , PUCHAR ujConnectStatus ); +#endif /* WIN2000 */ + +#endif diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c new file mode 100644 index 000000000000..b85ca9ba8076 --- /dev/null +++ b/drivers/staging/xgifb/vb_init.c @@ -0,0 +1,3444 @@ +#include "osdef.h" +#include "vgatypes.h" + + +#ifdef LINUX_KERNEL +#include <linux/version.h> +#include <linux/types.h> +#include <linux/delay.h> /* udelay */ +#include "XGIfb.h" +/*#if LINUX_VERSxION_CODE >= KERNEL_VERSION(2,5,0) +#include <video/XGIfb.h> +#else +#include <linux/XGIfb.h> +#endif */ +#endif + +#ifdef WIN2000 +#include <dderror.h> +#include <devioctl.h> +#include <miniport.h> +#include <ntddvdeo.h> +#include <video.h> +#include "xgiv.h" +#include "dd_i2c.h" +#include "tools.h" +#endif + +#include "vb_def.h" +#include "vb_struct.h" +#include "vb_util.h" +#include "vb_setmode.h" +#include "vb_init.h" +#include "vb_ext.h" + +#ifdef LINUX_XF86 +#include "xf86.h" +#include "xf86PciInfo.h" +#include "xgi.h" +#include "xgi_regs.h" +#endif + +#ifdef LINUX_KERNEL +#include <asm/io.h> +#include <linux/types.h> +#endif + + + + +UCHAR XGINew_ChannelAB,XGINew_DataBusWidth; + +USHORT XGINew_DRAMType[17][5]={{0x0C,0x0A,0x02,0x40,0x39},{0x0D,0x0A,0x01,0x40,0x48}, + {0x0C,0x09,0x02,0x20,0x35},{0x0D,0x09,0x01,0x20,0x44}, + {0x0C,0x08,0x02,0x10,0x31},{0x0D,0x08,0x01,0x10,0x40}, + {0x0C,0x0A,0x01,0x20,0x34},{0x0C,0x09,0x01,0x08,0x32}, + {0x0B,0x08,0x02,0x08,0x21},{0x0C,0x08,0x01,0x08,0x30}, + {0x0A,0x08,0x02,0x04,0x11},{0x0B,0x0A,0x01,0x10,0x28}, + {0x09,0x08,0x02,0x02,0x01},{0x0B,0x09,0x01,0x08,0x24}, + {0x0B,0x08,0x01,0x04,0x20},{0x0A,0x08,0x01,0x02,0x10}, + {0x09,0x08,0x01,0x01,0x00}}; + +USHORT XGINew_SDRDRAM_TYPE[13][5]= +{ +{ 2,12, 9,64,0x35}, +{ 1,13, 9,64,0x44}, +{ 2,12, 8,32,0x31}, +{ 2,11, 9,32,0x25}, +{ 1,12, 9,32,0x34}, +{ 1,13, 8,32,0x40}, +{ 2,11, 8,16,0x21}, +{ 1,12, 8,16,0x30}, +{ 1,11, 9,16,0x24}, +{ 1,11, 8, 8,0x20}, +{ 2, 9, 8, 4,0x01}, +{ 1,10, 8, 4,0x10}, +{ 1, 9, 8, 2,0x00} +}; + +USHORT XGINew_DDRDRAM_TYPE[4][5]= +{ +{ 2,12, 9,64,0x35}, +{ 2,12, 8,32,0x31}, +{ 2,11, 8,16,0x21}, +{ 2, 9, 8, 4,0x01} +}; +USHORT XGINew_DDRDRAM_TYPE340[4][5]= +{ +{ 2,13, 9,64,0x45}, +{ 2,12, 9,32,0x35}, +{ 2,12, 8,16,0x31}, +{ 2,11, 8, 8,0x21} +}; +USHORT XGINew_DDRDRAM_TYPE20[12][5]= +{ +{ 2,14,11,128,0x5D}, +{ 2,14,10,64,0x59}, +{ 2,13,11,64,0x4D}, +{ 2,14, 9,32,0x55}, +{ 2,13,10,32,0x49}, +{ 2,12,11,32,0x3D}, +{ 2,14, 8,16,0x51}, +{ 2,13, 9,16,0x45}, +{ 2,12,10,16,0x39}, +{ 2,13, 8, 8,0x41}, +{ 2,12, 9, 8,0x35}, +{ 2,12, 8, 4,0x31} +}; + +void XGINew_SetDRAMSize_340(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO); +void XGINew_SetDRAMSize_310(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO); +void XGINew_SetMemoryClock(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO ); +void XGINew_SetDRAMModeRegister(PVB_DEVICE_INFO ); +void XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension ); +void XGINew_SetDRAMDefaultRegister340(PXGI_HW_DEVICE_INFO HwDeviceExtension, ULONG, PVB_DEVICE_INFO ); +UCHAR XGINew_GetXG20DRAMType( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo); +BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension) ; + +int XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO ); +void XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO ,PVB_DEVICE_INFO) ; +void XGINew_CheckBusWidth_310( PVB_DEVICE_INFO) ; +int XGINew_SDRSizing(PVB_DEVICE_INFO); +int XGINew_DDRSizing( PVB_DEVICE_INFO ); +void XGINew_EnableRefresh( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO); +int XGINew_RAMType; /*int ModeIDOffset,StandTable,CRT1Table,ScreenOffset,REFIndex;*/ +ULONG UNIROM; /* UNIROM */ +BOOLEAN ChkLFB( PVB_DEVICE_INFO ); +void XGINew_Delay15us(ULONG); +void SetPowerConsume (PXGI_HW_DEVICE_INFO HwDeviceExtension,ULONG XGI_P3d4Port); +void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo); +void XGINew_DDR1x_MRS_XG20( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo); +void XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension ); +void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension ); +void XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ; +void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) ; +void XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ; +UCHAR GetXG21FPBits(PVB_DEVICE_INFO pVBInfo); +void XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) ; +UCHAR GetXG27FPBits(PVB_DEVICE_INFO pVBInfo); + +#ifdef WIN2000 +/* [Billy] 2007/05/20 For CH7007 */ +extern UCHAR CH7007TVReg_UNTSC[][8],CH7007TVReg_ONTSC[][8],CH7007TVReg_UPAL[][8],CH7007TVReg_OPAL[][8]; +extern UCHAR XGI7007_CHTVVCLKUNTSC[],XGI7007_CHTVVCLKONTSC[],XGI7007_CHTVVCLKUPAL[],XGI7007_CHTVVCLKOPAL[]; +#endif + +#ifdef LINUX_KERNEL +void DelayUS(ULONG MicroSeconds) +{ + udelay(MicroSeconds); +} +#endif + +/* --------------------------------------------------------------------- */ +/* Function : XGIInitNew */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension ) +{ + + VB_DEVICE_INFO VBINF; + PVB_DEVICE_INFO pVBInfo = &VBINF; + UCHAR i , temp = 0 , temp1 ; + // VBIOSVersion[ 5 ] ; + PUCHAR volatile pVideoMemory; + + /* ULONG j, k ; */ + + PXGI_DSReg pSR ; + + ULONG Temp ; + + pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ; + + pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; + + pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ; + + pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr; + + +// Newdebugcode( 0x99 ) ; + + + /* if ( pVBInfo->ROMAddr == 0 ) */ + /* return( FALSE ) ; */ + + if ( pVBInfo->FBAddr == 0 ) +{ + printk("\n pVBInfo->FBAddr == 0 "); + return( FALSE ) ; +} +printk("1"); + if ( pVBInfo->BaseAddr == 0 ) +{ + printk("\npVBInfo->BaseAddr == 0 "); + return( FALSE ) ; +} +printk("2"); + + XGINew_SetReg3( ( pVBInfo->BaseAddr + 0x12 ) , 0x67 ) ; /* 3c2 <- 67 ,ynlai */ + + pVBInfo->ISXPDOS = 0 ; +printk("3"); + +if ( !HwDeviceExtension->bIntegratedMMEnabled ) +{ + return( FALSE ) ; /* alan */ +} +printk("4"); + +// XGI_MemoryCopy( VBIOSVersion , HwDeviceExtension->szVBIOSVer , 4 ) ; + + // VBIOSVersion[ 4 ] = 0x0 ; + + /* 09/07/99 modify by domao */ + + pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ; + pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ; + pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ; + pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ; + pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ; + pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ; + pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ; + pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ; + pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ; + pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ; + pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ; + pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ; + pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ; + pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ; + pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ; + pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ; + pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ; +printk("5"); + + if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */ + XGI_GetVBType( pVBInfo ) ; /* Run XGI_GetVBType before InitTo330Pointer */ + + InitTo330Pointer( HwDeviceExtension->jChipType, pVBInfo ) ; + + /* ReadVBIOSData */ + ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ; + + /* 1.Openkey */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ; +printk("6"); + + /* GetXG21Sense (GPIO) */ + if ( HwDeviceExtension->jChipType == XG21 ) + { + XGINew_GetXG21Sense(HwDeviceExtension, pVBInfo) ; + } + if ( HwDeviceExtension->jChipType == XG27 ) + { + XGINew_GetXG27Sense(HwDeviceExtension, pVBInfo) ; + } +printk("7"); + + /* 2.Reset Extended register */ + + for( i = 0x06 ; i < 0x20 ; i++ ) + XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ; + + for( i = 0x21 ; i <= 0x27 ; i++ ) + XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ; + + /* for( i = 0x06 ; i <= 0x27 ; i++ ) */ + /* XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ; */ + +printk("8"); + + if(( HwDeviceExtension->jChipType >= XG20 ) || ( HwDeviceExtension->jChipType >= XG40)) + { + for( i = 0x31 ; i <= 0x3B ; i++ ) + XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ; + } + else + { + for( i = 0x31 ; i <= 0x3D ; i++ ) + XGINew_SetReg1( pVBInfo->P3c4 , i , 0 ) ; + } +printk("9"); + + if ( HwDeviceExtension->jChipType == XG42 ) /* [Hsuan] 2004/08/20 Auto over driver for XG42 */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x3B , 0xC0 ) ; + + /* for( i = 0x30 ; i <= 0x3F ; i++ ) */ + /* XGINew_SetReg1( pVBInfo->P3d4 , i , 0 ) ; */ + + for( i = 0x79 ; i <= 0x7C ; i++ ) + XGINew_SetReg1( pVBInfo->P3d4 , i , 0 ) ; /* shampoo 0208 */ + +printk("10"); + + if ( HwDeviceExtension->jChipType >= XG20 ) + XGINew_SetReg1( pVBInfo->P3d4 , 0x97 , *pVBInfo->pXGINew_CR97 ) ; + + /* 3.SetMemoryClock + + if ( HwDeviceExtension->jChipType >= XG40 ) + XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo) ; + + if ( HwDeviceExtension->jChipType < XG40 ) + XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ; */ + +printk("11"); + + /* 4.SetDefExt1Regs begin */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x07 , *pVBInfo->pSR07 ) ; + if ( HwDeviceExtension->jChipType == XG27 ) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x40 , *pVBInfo->pSR40 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x41 , *pVBInfo->pSR41 ) ; + } + XGINew_SetReg1( pVBInfo->P3c4 , 0x11 , 0x0F ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , *pVBInfo->pSR1F ) ; + /* XGINew_SetReg1( pVBInfo->P3c4 , 0x20 , 0x20 ) ; */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x20 , 0xA0 ) ; /* alan, 2001/6/26 Frame buffer can read/write SR20 */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x36 , 0x70 ) ; /* Hsuan, 2006/01/01 H/W request for slow corner chip */ + if ( HwDeviceExtension->jChipType == XG27 ) /* Alan 12/07/2006 */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x36 , *pVBInfo->pSR36 ) ; + + /* SR11 = 0x0F ; */ + /* XGINew_SetReg1( pVBInfo->P3c4 , 0x11 , SR11 ) ; */ + +printk("12"); + + if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */ + { +// /* Set AGP Rate */ +// temp1 = XGINew_GetReg1( pVBInfo->P3c4 , 0x3B ) ; +// temp1 &= 0x02 ; +// if ( temp1 == 0x02 ) +// { +// XGINew_SetReg4( 0xcf8 , 0x80000000 ) ; +// ChipsetID = XGINew_GetReg3( 0x0cfc ) ; +// XGINew_SetReg4( 0xcf8 , 0x8000002C ) ; +// VendorID = XGINew_GetReg3( 0x0cfc ) ; +// VendorID &= 0x0000FFFF ; +// XGINew_SetReg4( 0xcf8 , 0x8001002C ) ; +// GraphicVendorID = XGINew_GetReg3( 0x0cfc ) ; +// GraphicVendorID &= 0x0000FFFF; +// +// if ( ChipsetID == 0x7301039 ) +/// XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x09 ) ; +// +// ChipsetID &= 0x0000FFFF ; +/// +// if ( ( ChipsetID == 0x700E ) || ( ChipsetID == 0x1022 ) || ( ChipsetID == 0x1106 ) || ( ChipsetID == 0x10DE ) ) +// { +// if ( ChipsetID == 0x1106 ) +// { +// if ( ( VendorID == 0x1019 ) && ( GraphicVendorID == 0x1019 ) ) +// XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x0D ) ; +// else +// XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x0B ) ; +// } +// else +// XGINew_SetReg1( pVBInfo->P3d4 , 0x5F , 0x0B ) ; +// } +// } + +printk("13"); + + if ( HwDeviceExtension->jChipType >= XG40 ) + { + /* Set AGP customize registers (in SetDefAGPRegs) Start */ + for( i = 0x47 ; i <= 0x4C ; i++ ) + XGINew_SetReg1( pVBInfo->P3d4 , i , pVBInfo->AGPReg[ i - 0x47 ] ) ; + + for( i = 0x70 ; i <= 0x71 ; i++ ) + XGINew_SetReg1( pVBInfo->P3d4 , i , pVBInfo->AGPReg[ 6 + i - 0x70 ] ) ; + + for( i = 0x74 ; i <= 0x77 ; i++ ) + XGINew_SetReg1( pVBInfo->P3d4 , i , pVBInfo->AGPReg[ 8 + i - 0x74 ] ) ; + /* Set AGP customize registers (in SetDefAGPRegs) End */ + /*[Hsuan]2004/12/14 AGP Input Delay Adjustment on 850 */ +// XGINew_SetReg4( 0xcf8 , 0x80000000 ) ; +// ChipsetID = XGINew_GetReg3( 0x0cfc ) ; +// if ( ChipsetID == 0x25308086 ) +// XGINew_SetReg1( pVBInfo->P3d4 , 0x77 , 0xF0 ) ; + + HwDeviceExtension->pQueryVGAConfigSpace( HwDeviceExtension , 0x50 , 0 , &Temp ) ; /* Get */ + Temp >>= 20 ; + Temp &= 0xF ; + + if ( Temp == 1 ) + XGINew_SetReg1( pVBInfo->P3d4 , 0x48 , 0x20 ) ; /* CR48 */ + } +printk("14"); + + if ( HwDeviceExtension->jChipType < XG40 ) + XGINew_SetReg1( pVBInfo->P3d4 , 0x49 , pVBInfo->CR49[ 0 ] ) ; + } /* != XG20 */ + + /* Set PCI */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x23 , *pVBInfo->pSR23 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x24 , *pVBInfo->pSR24 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x25 , pVBInfo->SR25[ 0 ] ) ; +printk("15"); + + if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */ + { + /* Set VB */ + XGI_UnLockCRT2( HwDeviceExtension, pVBInfo) ; + XGINew_SetRegANDOR( pVBInfo->Part0Port , 0x3F , 0xEF , 0x00 ) ; /* alan, disable VideoCapture */ + XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , 0x00 ) ; + temp1 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x7B ) ; /* chk if BCLK>=100MHz */ + temp = ( UCHAR )( ( temp1 >> 4 ) & 0x0F ) ; + + + XGINew_SetReg1( pVBInfo->Part1Port , 0x02 , ( *pVBInfo->pCRT2Data_1_2 ) ) ; + +printk("16"); + + XGINew_SetReg1( pVBInfo->Part1Port , 0x2E , 0x08 ) ; /* use VB */ + } /* != XG20 */ + + + XGINew_SetReg1( pVBInfo->P3c4 , 0x27 , 0x1F ) ; + + if ( ( HwDeviceExtension->jChipType == XG42 ) && XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo) != 0 ) /* Not DDR */ + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , ( *pVBInfo->pSR31 & 0x3F ) | 0x40 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , ( *pVBInfo->pSR32 & 0xFC ) | 0x01 ) ; + } + else + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , *pVBInfo->pSR31 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , *pVBInfo->pSR32 ) ; + } + XGINew_SetReg1( pVBInfo->P3c4 , 0x33 , *pVBInfo->pSR33 ) ; +printk("17"); + +/* + if ( HwDeviceExtension->jChipType >= XG40 ) + SetPowerConsume ( HwDeviceExtension , pVBInfo->P3c4); */ + + if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */ + { + if ( XGI_BridgeIsOn( pVBInfo ) == 1 ) + { + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + XGINew_SetReg1( pVBInfo->Part2Port , 0x00 , 0x1C ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x0D , *pVBInfo->pCRT2Data_4_D ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x0E , *pVBInfo->pCRT2Data_4_E ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x10 , *pVBInfo->pCRT2Data_4_10 ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x0F , 0x3F ) ; + } + + XGI_LockCRT2( HwDeviceExtension, pVBInfo ) ; + } + } /* != XG20 */ +printk("18"); + + if ( HwDeviceExtension->jChipType < XG40 ) + XGINew_SetReg1( pVBInfo->P3d4 , 0x83 , 0x00 ) ; +printk("181"); + + if ( HwDeviceExtension->bSkipSense == FALSE ) + { +printk("182"); + + XGI_SenseCRT1(pVBInfo) ; + +printk("183"); + /* XGINew_DetectMonitor( HwDeviceExtension ) ; */ +pVBInfo->IF_DEF_CH7007 = 0; + if ( ( HwDeviceExtension->jChipType == XG21 ) && (pVBInfo->IF_DEF_CH7007) ) + { +printk("184"); + XGI_GetSenseStatus( HwDeviceExtension , pVBInfo ) ; /* sense CRT2 */ +printk("185"); + + } + if ( HwDeviceExtension->jChipType == XG21 ) + { +printk("186"); + + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~Monitor1Sense , Monitor1Sense ) ; /* Z9 default has CRT */ + temp = GetXG21FPBits( pVBInfo ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ~0x01, temp ) ; +printk("187"); + + } + if ( HwDeviceExtension->jChipType == XG27 ) + { + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , ~Monitor1Sense , Monitor1Sense ) ; /* Z9 default has CRT */ + temp = GetXG27FPBits( pVBInfo ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x37 , ~0x03, temp ) ; + } + } +printk("19"); + + if ( HwDeviceExtension->jChipType >= XG40 ) + { + if ( HwDeviceExtension->jChipType >= XG40 ) + { + XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ; + } + + XGINew_SetDRAMDefaultRegister340( HwDeviceExtension , pVBInfo->P3d4, pVBInfo ) ; + + if ( HwDeviceExtension->bSkipDramSizing == TRUE ) + { + pSR = HwDeviceExtension->pSR ; + if ( pSR!=NULL ) + { + while( pSR->jIdx != 0xFF ) + { + XGINew_SetReg1( pVBInfo->P3c4 , pSR->jIdx , pSR->jVal ) ; + pSR++ ; + } + } + /* XGINew_SetDRAMModeRegister340( pVBInfo ) ; */ + } /* SkipDramSizing */ + else + { +#if 0 + if ( HwDeviceExtension->jChipType == XG20 ) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , pVBInfo->SR15[0][XGINew_RAMType] ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , pVBInfo->SR15[1][XGINew_RAMType] ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x20 , 0x20 ) ; + } + else +#endif +{ +printk("20"); + + XGINew_SetDRAMSize_340( HwDeviceExtension , pVBInfo) ; +} +printk("21"); + + } + } /* XG40 */ + +printk("22"); + + + /* SetDefExt2Regs begin */ +/* + AGP = 1 ; + temp =( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x3A ) ; + temp &= 0x30 ; + if ( temp == 0x30 ) + AGP = 0 ; + + if ( AGP == 0 ) + *pVBInfo->pSR21 &= 0xEF ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , *pVBInfo->pSR21 ) ; + if ( AGP == 1 ) + *pVBInfo->pSR22 &= 0x20 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x22 , *pVBInfo->pSR22 ) ; +*/ + +// base = 0x80000000 ; +// OutPortLong( 0xcf8 , base ) ; +// Temp = ( InPortLong( 0xcfc ) & 0xFFFF ) ; +// if ( Temp == 0x1039 ) +// { + XGINew_SetReg1( pVBInfo->P3c4 , 0x22 , ( UCHAR )( ( *pVBInfo->pSR22 ) & 0xFE ) ) ; +// } +// else +// { +// XGINew_SetReg1( pVBInfo->P3c4 , 0x22 , *pVBInfo->pSR22 ) ; +// } + + XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , *pVBInfo->pSR21 ) ; + +printk("23"); + + + XGINew_ChkSenseStatus ( HwDeviceExtension , pVBInfo ) ; + XGINew_SetModeScratch ( HwDeviceExtension , pVBInfo ) ; + +printk("24"); + + +XGINew_SetReg1( pVBInfo->P3d4 , 0x8c , 0x87); +XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x31); +printk("25"); + + return( TRUE ) ; +} /* end of init */ + + + + + +/* ============== alan ====================== */ + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_GetXG20DRAMType */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +UCHAR XGINew_GetXG20DRAMType( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo) +{ + UCHAR data, temp ; + + if ( HwDeviceExtension->jChipType < XG20 ) + { + if ( *pVBInfo->pSoftSetting & SoftDRAMType ) + { + data = *pVBInfo->pSoftSetting & 0x07 ; + return( data ) ; + } + else + { + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) & 0x02 ; + + if ( data == 0 ) + data = ( XGINew_GetReg1( pVBInfo->P3c4 , 0x3A ) & 0x02 ) >> 1 ; + + return( data ) ; + } + } + else if ( HwDeviceExtension->jChipType == XG27 ) + { + if ( *pVBInfo->pSoftSetting & SoftDRAMType ) + { + data = *pVBInfo->pSoftSetting & 0x07 ; + return( data ) ; + } + temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x3B ) ; + + if (( temp & 0x88 )==0x80) /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */ + data = 0 ; /*DDR*/ + else + data = 1 ; /*DDRII*/ + return( data ) ; + } + else if ( HwDeviceExtension->jChipType == XG21 ) + { + XGINew_SetRegAND( pVBInfo->P3d4 , 0xB4 , ~0x02 ) ; /* Independent GPIO control */ + DelayUS(800); + XGINew_SetRegOR( pVBInfo->P3d4 , 0x4A , 0x80 ) ; /* Enable GPIOH read */ + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ; /* GPIOF 0:DVI 1:DVO */ +// HOTPLUG_SUPPORT +// for current XG20 & XG21, GPIOH is floating, driver will fix DDR temporarily + if ( temp & 0x01 ) /* DVI read GPIOH */ + data = 1 ; /*DDRII*/ + else + data = 0 ; /*DDR*/ +//~HOTPLUG_SUPPORT + XGINew_SetRegOR( pVBInfo->P3d4 , 0xB4 , 0x02 ) ; + return( data ) ; + } + else + { + data = XGINew_GetReg1( pVBInfo->P3d4 , 0x97 ) & 0x01 ; + + if ( data == 1 ) + data ++ ; + + return( data ); + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_Get310DRAMType */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +UCHAR XGINew_Get310DRAMType(PVB_DEVICE_INFO pVBInfo) +{ + UCHAR data ; + + /* index = XGINew_GetReg1( pVBInfo->P3c4 , 0x1A ) ; */ + /* index &= 07 ; */ + + if ( *pVBInfo->pSoftSetting & SoftDRAMType ) + data = *pVBInfo->pSoftSetting & 0x03 ; + else + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x3a ) & 0x03 ; + + return( data ) ; +} + + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_Delay15us */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +/* +void XGINew_Delay15us(ULONG ulMicrsoSec) +{ +} +*/ + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SDR_MRS */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_SDR_MRS( PVB_DEVICE_INFO pVBInfo ) +{ + USHORT data ; + + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ; + data &= 0x3F ; /* SR16 D7=0,D6=0 */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; /* enable mode register set(MRS) low */ + /* XGINew_Delay15us( 0x100 ) ; */ + data |= 0x80 ; /* SR16 D7=1,D6=0 */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; /* enable mode register set(MRS) high */ + /* XGINew_Delay15us( 0x100 ) ; */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DDR1x_MRS_340 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_DDR1x_MRS_340( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo) +{ + XGINew_SetReg1( P3c4 , 0x18 , 0x01 ) ; + XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; + + if ( *pVBInfo->pXGINew_DRAMTypeDefinition != 0x0C ) /* Samsung F Die */ + { + DelayUS( 3000 ) ; /* Delay 67 x 3 Delay15us */ + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; + XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; + } + + DelayUS( 60 ) ; + XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */ + XGINew_SetReg1( P3c4 , 0x19 , 0x01 ) ; + XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 0 ] ) ; + XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 1 ] ) ; + DelayUS( 1000 ) ; + XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ; + DelayUS( 500 ) ; + XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */ + XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ; + XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 2 ] ) ; + XGINew_SetReg1( P3c4 , 0x16 , pVBInfo->SR16[ 3 ] ) ; + XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DDR2x_MRS_340 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_DDR2x_MRS_340( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo) +{ + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; + XGINew_SetReg1( P3c4 , 0x19 , 0x20 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; + DelayUS( 60 ) ; + XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */ + /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */ + XGINew_SetReg1( P3c4 , 0x19 , 0x01 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ; + DelayUS( 1000 ) ; + XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ; + DelayUS( 500 ) ; + /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */ + XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */ + XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ; + XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ; +} + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DDRII_Bootup_XG27 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_DDRII_Bootup_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG P3c4 , PVB_DEVICE_INFO pVBInfo) +{ + ULONG P3d4 = P3c4 + 0x10 ; + XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ; + XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ; + + /* Set Double Frequency */ + /* XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ; */ /* CR97 */ + XGINew_SetReg1( P3d4 , 0x97 , *pVBInfo->pXGINew_CR97 ) ; /* CR97 */ + + DelayUS( 200 ) ; + + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* Set SR18 */ //EMRS2 + XGINew_SetReg1( P3c4 , 0x19 , 0x80 ) ; /* Set SR19 */ + XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */ + DelayUS( 15 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */ + DelayUS( 15 ) ; + + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* Set SR18 */ //EMRS3 + XGINew_SetReg1( P3c4 , 0x19 , 0xC0 ) ; /* Set SR19 */ + XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */ + DelayUS( 15 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */ + DelayUS( 15) ; + + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* Set SR18 */ //EMRS1 + XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ; /* Set SR19 */ + XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */ + DelayUS( 30 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */ + DelayUS( 15 ) ; + + XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* Set SR18 */ //MRS, DLL Enable + XGINew_SetReg1( P3c4 , 0x19 , 0x0A ) ; /* Set SR19 */ + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; /* Set SR16 */ + DelayUS( 30 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; /* Set SR16 */ + XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; /* Set SR16 */ + /* DelayUS( 15 ) ; */ + + XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* Set SR1B */ + DelayUS( 60 ) ; + XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ; /* Set SR1B */ + + XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* Set SR18 */ //MRS, DLL Reset + XGINew_SetReg1( P3c4 , 0x19 , 0x08 ) ; /* Set SR19 */ + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; /* Set SR16 */ + + DelayUS( 30 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x83 ) ; /* Set SR16 */ + DelayUS( 15 ) ; + + XGINew_SetReg1( P3c4 , 0x18 , 0x80 ) ; /* Set SR18 */ //MRS, ODT + XGINew_SetReg1( P3c4 , 0x19 , 0x46 ) ; /* Set SR19 */ + XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */ + DelayUS( 30 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */ + DelayUS( 15 ) ; + + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* Set SR18 */ //EMRS + XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ; /* Set SR19 */ + XGINew_SetReg1( P3c4 , 0x16 , 0x20 ) ; /* Set SR16 */ + DelayUS( 30 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0xA0 ) ; /* Set SR16 */ + DelayUS( 15 ) ; + + XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* Set SR1B refresh control 000:close; 010:open */ + DelayUS( 200 ) ; + + +} +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DDR2_MRS_XG20 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_DDR2_MRS_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG P3c4 , PVB_DEVICE_INFO pVBInfo) +{ + ULONG P3d4 = P3c4 + 0x10 ; + + XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ; + XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ; + + XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ; /* CR97 */ + + DelayUS( 200 ) ; + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS2 */ + XGINew_SetReg1( P3c4 , 0x19 , 0x80 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ; + + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS3 */ + XGINew_SetReg1( P3c4 , 0x19 , 0xC0 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ; + + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS1 */ + XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ; + + // XGINew_SetReg1( P3c4 , 0x18 , 0x52 ) ; /* MRS1 */ + XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* MRS1 */ + XGINew_SetReg1( P3c4 , 0x19 , 0x02 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ; + + DelayUS( 15 ) ; + XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* SR1B */ + DelayUS( 30 ) ; + XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ; /* SR1B */ + DelayUS( 100 ) ; + + //XGINew_SetReg1( P3c4 , 0x18 , 0x52 ) ; /* MRS2 */ + XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* MRS1 */ + XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x05 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x85 ) ; + + DelayUS( 200 ) ; +} + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DDR2_MRS_XG20 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_DDR2_MRS_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG P3c4 , PVB_DEVICE_INFO pVBInfo) +{ + ULONG P3d4 = P3c4 + 0x10 ; + + XGINew_RAMType = ( int )XGINew_GetXG20DRAMType( HwDeviceExtension , pVBInfo ) ; + XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ; + + XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ; /* CR97 */ + DelayUS( 200 ) ; + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS2 */ + XGINew_SetReg1( P3c4 , 0x19 , 0x80 ) ; + + XGINew_SetReg1( P3c4 , 0x16 , 0x10 ) ; + DelayUS( 15 ) ; ////06/11/23 XG27 A0 for CKE enable + XGINew_SetReg1( P3c4 , 0x16 , 0x90 ) ; + + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS3 */ + XGINew_SetReg1( P3c4 , 0x19 , 0xC0 ) ; + + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; + DelayUS( 15 ) ; ////06/11/22 XG27 A0 + XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; + + + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; /* EMRS1 */ + XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ; + + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; + DelayUS( 15 ) ; ////06/11/22 XG27 A0 + XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; + + XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* MRS1 */ + XGINew_SetReg1( P3c4 , 0x19 , 0x06 ) ; ////[Billy]06/11/22 DLL Reset for XG27 Hynix DRAM + + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; + DelayUS( 15 ) ; ////06/11/23 XG27 A0 + XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; + + DelayUS( 30 ) ; ////06/11/23 XG27 A0 Start Auto-PreCharge + XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* SR1B */ + DelayUS( 60 ) ; + XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ; /* SR1B */ + + + XGINew_SetReg1( P3c4 , 0x18 , 0x42 ) ; /* MRS1 */ + XGINew_SetReg1( P3c4 , 0x19 , 0x04 ) ; //// DLL without Reset for XG27 Hynix DRAM + + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; + DelayUS( 30 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; + + XGINew_SetReg1( P3c4 , 0x18 , 0x80 ); ////XG27 OCD ON + XGINew_SetReg1( P3c4 , 0x19 , 0x46 ); + + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; + DelayUS( 30 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; + + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ); + XGINew_SetReg1( P3c4 , 0x19 , 0x40 ); + + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; + DelayUS( 30 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; + + DelayUS( 15 ) ; ////Start Auto-PreCharge + XGINew_SetReg1( P3c4 , 0x1B , 0x04 ) ; /* SR1B */ + DelayUS( 200 ) ; + XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ; /* SR1B */ + +} + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DDR1x_DefaultRegister */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_DDR1x_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG Port , PVB_DEVICE_INFO pVBInfo) +{ + ULONG P3d4 = Port , + P3c4 = Port - 0x10 ; + + if ( HwDeviceExtension->jChipType >= XG20 ) + { + XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ; + XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */ + XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */ + XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ; /* CR86 */ + + XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ; + XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ; + + XGINew_DDR1x_MRS_XG20( P3c4 , pVBInfo) ; + } + else + { + XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ; + + switch( HwDeviceExtension->jChipType ) + { + case XG41: + case XG42: + XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */ + XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */ + XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ; /* CR86 */ + break ; + default: + XGINew_SetReg1( P3d4 , 0x82 , 0x88 ) ; + XGINew_SetReg1( P3d4 , 0x86 , 0x00 ) ; + XGINew_GetReg1( P3d4 , 0x86 ) ; /* Insert read command for delay */ + XGINew_SetReg1( P3d4 , 0x86 , 0x88 ) ; + XGINew_GetReg1( P3d4 , 0x86 ) ; + XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ; + XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ; + XGINew_SetReg1( P3d4 , 0x85 , 0x00 ) ; + XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */ + XGINew_SetReg1( P3d4 , 0x85 , 0x88 ) ; + XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */ + XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */ + XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */ + break ; + } + + XGINew_SetReg1( P3d4 , 0x97 , 0x00 ) ; + XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ; + XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ; + XGINew_DDR1x_MRS_340( P3c4 , pVBInfo ) ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DDR2x_DefaultRegister */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_DDR2x_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG Port ,PVB_DEVICE_INFO pVBInfo) +{ + ULONG P3d4 = Port , + P3c4 = Port - 0x10 ; + + XGINew_SetMemoryClock( HwDeviceExtension , pVBInfo ) ; + + /* 20040906 Hsuan modify CR82, CR85, CR86 for XG42 */ + switch( HwDeviceExtension->jChipType ) + { + case XG41: + case XG42: + XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */ + XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */ + XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ; /* CR86 */ + break ; + default: + /* keep following setting sequence, each setting in the same reg insert idle */ + XGINew_SetReg1( P3d4 , 0x82 , 0x88 ) ; + XGINew_SetReg1( P3d4 , 0x86 , 0x00 ) ; + XGINew_GetReg1( P3d4 , 0x86 ) ; /* Insert read command for delay */ + XGINew_SetReg1( P3d4 , 0x86 , 0x88 ) ; + XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ; + XGINew_SetReg1( P3d4 , 0x85 , 0x00 ) ; + XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */ + XGINew_SetReg1( P3d4 , 0x85 , 0x88 ) ; + XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */ + XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */ + XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */ + } + XGINew_SetReg1( P3d4 , 0x97 , 0x11 ) ; + if ( HwDeviceExtension->jChipType == XG42 ) + { + XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ; + } + else + { + XGINew_SetReg1( P3d4 , 0x98 , 0x03 ) ; + } + XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ; + + XGINew_DDR2x_MRS_340( P3c4 , pVBInfo ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DDR2_DefaultRegister */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_DDR2_DefaultRegister( PXGI_HW_DEVICE_INFO HwDeviceExtension, ULONG Port , PVB_DEVICE_INFO pVBInfo) +{ + ULONG P3d4 = Port , + P3c4 = Port - 0x10 ; + + /* keep following setting sequence, each setting in the same reg insert idle */ + XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ; + XGINew_SetReg1( P3d4 , 0x86 , 0x00 ) ; + XGINew_GetReg1( P3d4 , 0x86 ) ; /* Insert read command for delay */ + XGINew_SetReg1( P3d4 , 0x86 , 0x88 ) ; + XGINew_GetReg1( P3d4 , 0x86 ) ; /* Insert read command for delay */ + XGINew_SetReg1( P3d4 , 0x86 , pVBInfo->CR40[ 13 ][ XGINew_RAMType ] ) ; /* CR86 */ + XGINew_SetReg1( P3d4 , 0x82 , 0x77 ) ; + XGINew_SetReg1( P3d4 , 0x85 , 0x00 ) ; + XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */ + XGINew_SetReg1( P3d4 , 0x85 , 0x88 ) ; + XGINew_GetReg1( P3d4 , 0x85 ) ; /* Insert read command for delay */ + XGINew_SetReg1( P3d4 , 0x85 , pVBInfo->CR40[ 12 ][ XGINew_RAMType ] ) ; /* CR85 */ + if ( HwDeviceExtension->jChipType == XG27 ) + XGINew_SetReg1( P3d4 , 0x82 , pVBInfo->CR40[ 11 ][ XGINew_RAMType ] ) ; /* CR82 */ + else + XGINew_SetReg1( P3d4 , 0x82 , 0xA8 ) ; /* CR82 */ + + XGINew_SetReg1( P3d4 , 0x98 , 0x01 ) ; + XGINew_SetReg1( P3d4 , 0x9A , 0x02 ) ; + if ( HwDeviceExtension->jChipType == XG27 ) + XGINew_DDRII_Bootup_XG27( HwDeviceExtension , P3c4 , pVBInfo) ; + else + XGINew_DDR2_MRS_XG20( HwDeviceExtension , P3c4, pVBInfo ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetDRAMDefaultRegister340 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_SetDRAMDefaultRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG Port , PVB_DEVICE_INFO pVBInfo) +{ + UCHAR temp , temp1 , temp2 , temp3 , + i , j , k ; + + ULONG P3d4 = Port , + P3c4 = Port - 0x10 ; + + XGINew_SetReg1( P3d4 , 0x6D , pVBInfo->CR40[ 8 ][ XGINew_RAMType ] ) ; + XGINew_SetReg1( P3d4 , 0x68 , pVBInfo->CR40[ 5 ][ XGINew_RAMType ] ) ; + XGINew_SetReg1( P3d4 , 0x69 , pVBInfo->CR40[ 6 ][ XGINew_RAMType ] ) ; + XGINew_SetReg1( P3d4 , 0x6A , pVBInfo->CR40[ 7 ][ XGINew_RAMType ] ) ; + + temp2 = 0 ; + for( i = 0 ; i < 4 ; i++ ) + { + temp = pVBInfo->CR6B[ XGINew_RAMType ][ i ] ; /* CR6B DQS fine tune delay */ + for( j = 0 ; j < 4 ; j++ ) + { + temp1 = ( ( temp >> ( 2 * j ) ) & 0x03 ) << 2 ; + temp2 |= temp1 ; + XGINew_SetReg1( P3d4 , 0x6B , temp2 ) ; + XGINew_GetReg1( P3d4 , 0x6B ) ; /* Insert read command for delay */ + temp2 &= 0xF0 ; + temp2 += 0x10 ; + } + } + + temp2 = 0 ; + for( i = 0 ; i < 4 ; i++ ) + { + temp = pVBInfo->CR6E[ XGINew_RAMType ][ i ] ; /* CR6E DQM fine tune delay */ + for( j = 0 ; j < 4 ; j++ ) + { + temp1 = ( ( temp >> ( 2 * j ) ) & 0x03 ) << 2 ; + temp2 |= temp1 ; + XGINew_SetReg1( P3d4 , 0x6E , temp2 ) ; + XGINew_GetReg1( P3d4 , 0x6E ) ; /* Insert read command for delay */ + temp2 &= 0xF0 ; + temp2 += 0x10 ; + } + } + + temp3 = 0 ; + for( k = 0 ; k < 4 ; k++ ) + { + XGINew_SetRegANDOR( P3d4 , 0x6E , 0xFC , temp3 ) ; /* CR6E_D[1:0] select channel */ + temp2 = 0 ; + for( i = 0 ; i < 8 ; i++ ) + { + temp = pVBInfo->CR6F[ XGINew_RAMType ][ 8 * k + i ] ; /* CR6F DQ fine tune delay */ + for( j = 0 ; j < 4 ; j++ ) + { + temp1 = ( temp >> ( 2 * j ) ) & 0x03 ; + temp2 |= temp1 ; + XGINew_SetReg1( P3d4 , 0x6F , temp2 ) ; + XGINew_GetReg1( P3d4 , 0x6F ) ; /* Insert read command for delay */ + temp2 &= 0xF8 ; + temp2 += 0x08 ; + } + } + temp3 += 0x01 ; + } + + XGINew_SetReg1( P3d4 , 0x80 , pVBInfo->CR40[ 9 ][ XGINew_RAMType ] ) ; /* CR80 */ + XGINew_SetReg1( P3d4 , 0x81 , pVBInfo->CR40[ 10 ][ XGINew_RAMType ] ) ; /* CR81 */ + + temp2 = 0x80 ; + temp = pVBInfo->CR89[ XGINew_RAMType ][ 0 ] ; /* CR89 terminator type select */ + for( j = 0 ; j < 4 ; j++ ) + { + temp1 = ( temp >> ( 2 * j ) ) & 0x03 ; + temp2 |= temp1 ; + XGINew_SetReg1( P3d4 , 0x89 , temp2 ) ; + XGINew_GetReg1( P3d4 , 0x89 ) ; /* Insert read command for delay */ + temp2 &= 0xF0 ; + temp2 += 0x10 ; + } + + temp = pVBInfo->CR89[ XGINew_RAMType ][ 1 ] ; + temp1 = temp & 0x03 ; + temp2 |= temp1 ; + XGINew_SetReg1( P3d4 , 0x89 , temp2 ) ; + + temp = pVBInfo->CR40[ 3 ][ XGINew_RAMType ] ; + temp1 = temp & 0x0F ; + temp2 = ( temp >> 4 ) & 0x07 ; + temp3 = temp & 0x80 ; + XGINew_SetReg1( P3d4 , 0x45 , temp1 ) ; /* CR45 */ + XGINew_SetReg1( P3d4 , 0x99 , temp2 ) ; /* CR99 */ + XGINew_SetRegOR( P3d4 , 0x40 , temp3 ) ; /* CR40_D[7] */ + XGINew_SetReg1( P3d4 , 0x41 , pVBInfo->CR40[ 0 ][ XGINew_RAMType ] ) ; /* CR41 */ + + if ( HwDeviceExtension->jChipType == XG27 ) + XGINew_SetReg1( P3d4 , 0x8F , *pVBInfo->pCR8F ) ; /* CR8F */ + + for( j = 0 ; j <= 6 ; j++ ) + XGINew_SetReg1( P3d4 , ( 0x90 + j ) , pVBInfo->CR40[ 14 + j ][ XGINew_RAMType ] ) ; /* CR90 - CR96 */ + + for( j = 0 ; j <= 2 ; j++ ) + XGINew_SetReg1( P3d4 , ( 0xC3 + j ) , pVBInfo->CR40[ 21 + j ][ XGINew_RAMType ] ) ; /* CRC3 - CRC5 */ + + for( j = 0 ; j < 2 ; j++ ) + XGINew_SetReg1( P3d4 , ( 0x8A + j ) , pVBInfo->CR40[ 1 + j ][ XGINew_RAMType ] ) ; /* CR8A - CR8B */ + + if ( ( HwDeviceExtension->jChipType == XG41 ) || ( HwDeviceExtension->jChipType == XG42 ) ) + XGINew_SetReg1( P3d4 , 0x8C , 0x87 ) ; + + XGINew_SetReg1( P3d4 , 0x59 , pVBInfo->CR40[ 4 ][ XGINew_RAMType ] ) ; /* CR59 */ + + XGINew_SetReg1( P3d4 , 0x83 , 0x09 ) ; /* CR83 */ + XGINew_SetReg1( P3d4 , 0x87 , 0x00 ) ; /* CR87 */ + XGINew_SetReg1( P3d4 , 0xCF , *pVBInfo->pCRCF ) ; /* CRCF */ + if ( XGINew_RAMType ) + { + //XGINew_SetReg1( P3c4 , 0x17 , 0xC0 ) ; /* SR17 DDRII */ + XGINew_SetReg1( P3c4 , 0x17 , 0x80 ) ; /* SR17 DDRII */ + if ( HwDeviceExtension->jChipType == XG27 ) + XGINew_SetReg1( P3c4 , 0x17 , 0x02 ) ; /* SR17 DDRII */ + + } + else + XGINew_SetReg1( P3c4 , 0x17 , 0x00 ) ; /* SR17 DDR */ + XGINew_SetReg1( P3c4 , 0x1A , 0x87 ) ; /* SR1A */ + + temp = XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) ; + if( temp == 0 ) + XGINew_DDR1x_DefaultRegister( HwDeviceExtension, P3d4, pVBInfo ) ; + else + { + XGINew_SetReg1( P3d4 , 0xB0 , 0x80 ) ; /* DDRII Dual frequency mode */ + XGINew_DDR2_DefaultRegister( HwDeviceExtension, P3d4, pVBInfo ) ; + } + XGINew_SetReg1( P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ; /* SR1B */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DDR_MRS */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_DDR_MRS(PVB_DEVICE_INFO pVBInfo) +{ + USHORT data ; + + PUCHAR volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ; + + /* SR16 <- 1F,DF,2F,AF */ + /* yriver modified SR16 <- 0F,DF,0F,AF */ + /* enable DLL of DDR SD/SGRAM , SR16 D4=1 */ + data = pVideoMemory[ 0xFB ] ; + /* data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ; */ + + data &= 0x0F ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; + data |= 0xC0 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; + data &= 0x0F ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; + data |= 0x80 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; + data &= 0x0F ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; + data |= 0xD0 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; + data &= 0x0F ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; + data |= 0xA0 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , data ) ; +/* + else { + data &= 0x0F; + data |= 0x10; + XGINew_SetReg1(pVBInfo->P3c4,0x16,data); + + if (!(pVBInfo->SR15[1][XGINew_RAMType] & 0x10)) + { + data &= 0x0F; + } + + data |= 0xC0; + XGINew_SetReg1(pVBInfo->P3c4,0x16,data); + + + data &= 0x0F; + data |= 0x20; + XGINew_SetReg1(pVBInfo->P3c4,0x16,data); + if (!(pVBInfo->SR15[1][XGINew_RAMType] & 0x10)) + { + data &= 0x0F; + } + + data |= 0x80; + XGINew_SetReg1(pVBInfo->P3c4,0x16,data); + } +*/ +} + + +/* check if read cache pointer is correct */ + + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_VerifyMclk */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_VerifyMclk( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo) +{ + PUCHAR pVideoMemory = pVBInfo->FBAddr ; + UCHAR i , j ; + USHORT Temp , SR21 ; + + pVideoMemory[ 0 ] = 0xaa ; /* alan */ + pVideoMemory[ 16 ] = 0x55 ; /* note: PCI read cache is off */ + + if ( ( pVideoMemory[ 0 ] != 0xaa ) || ( pVideoMemory[ 16 ] != 0x55 ) ) + { + for( i = 0 , j = 16 ; i < 2 ; i++ , j += 16 ) + { + SR21 = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ; + Temp = SR21 & 0xFB ; /* disable PCI post write buffer empty gating */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , Temp ) ; + + Temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x3C ) ; + Temp |= 0x01 ; /* MCLK reset */ + + + Temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x3C ) ; + Temp &= 0xFE ; /* MCLK normal operation */ + + XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , SR21 ) ; + + pVideoMemory[ 16 + j ] = j ; + if ( pVideoMemory[ 16 + j ] == j ) + { + pVideoMemory[ j ] = j ; + break ; + } + } + } +} + + + + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetDRAMSize_340 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_SetDRAMSize_340( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo) +{ + USHORT data ; + + pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ; + pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; + + XGISetModeNew( HwDeviceExtension , 0x2e ) ; + + + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data & 0xDF ) ) ; /* disable read cache */ + XGI_DisplayOff( HwDeviceExtension, pVBInfo ); + + /*data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1 ) ;*/ + /*data |= 0x20 ;*/ + /*XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , data ) ;*/ /* Turn OFF Display */ + XGINew_DDRSizing340( HwDeviceExtension, pVBInfo ) ; + data=XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data | 0x20 ) ) ; /* enable read cache */ + +} + + +/* --------------------------------------------------------------------- */ +/* Function : */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_SetDRAMSize_310( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo) +{ + USHORT data ; + pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase , + pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; +#ifdef XGI301 + /* XGINew_SetReg1( pVBInfo->P3d4 , 0x30 , 0x40 ) ; */ +#endif + +#ifdef XGI302 /* alan,should change value */ + XGINew_SetReg1( pVBInfo->P3d4 , 0x30 , 0x4D ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x31 , 0xc0 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x34 , 0x3F ) ; +#endif + + XGISetModeNew( HwDeviceExtension , 0x2e ) ; + + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x21 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data & 0xDF ) ) ; /* disable read cache */ + + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1 ) ; + data |= 0x20 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , data ) ; /* Turn OFF Display */ + + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x16 ) ; + + + XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , ( USHORT )( data | 0x0F ) ) ; /* assume lowest speed DRAM */ + + XGINew_SetDRAMModeRegister( pVBInfo ) ; + XGINew_DisableRefresh( HwDeviceExtension, pVBInfo ) ; + XGINew_CheckBusWidth_310( pVBInfo) ; + XGINew_VerifyMclk( HwDeviceExtension, pVBInfo ) ; /* alan 2000/7/3 */ + + + + if ( XGINew_Get310DRAMType( pVBInfo ) < 2 ) + { + XGINew_SDRSizing( pVBInfo ) ; + } + else + { + XGINew_DDRSizing( pVBInfo) ; + } + + + + + XGINew_SetReg1( pVBInfo->P3c4 , 0x16 , pVBInfo->SR15[ 1 ][ XGINew_RAMType ] ) ; /* restore SR16 */ + + XGINew_EnableRefresh( HwDeviceExtension, pVBInfo ) ; + data=XGINew_GetReg1( pVBInfo->P3c4 ,0x21 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x21 , ( USHORT )( data | 0x20 ) ) ; /* enable read cache */ +} + + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetDRAMModeRegister340 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ + +void XGINew_SetDRAMModeRegister340( PXGI_HW_DEVICE_INFO HwDeviceExtension ) +{ + UCHAR data ; + VB_DEVICE_INFO VBINF; + PVB_DEVICE_INFO pVBInfo = &VBINF; + pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ; + pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; + pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ; + pVBInfo->ISXPDOS = 0 ; + + pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ; + pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ; + pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ; + pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ; + pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ; + pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ; + pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ; + pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ; + pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ; + pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ; + pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ; + pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ; + pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ; + pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ; + pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ; + pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ; + pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ; + if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */ + XGI_GetVBType( pVBInfo ) ; /* Run XGI_GetVBType before InitTo330Pointer */ + + InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo); + + ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ; + + if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 ) + { + data = ( XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) & 0x02 ) >> 1 ; + if ( data == 0x01 ) + XGINew_DDR2x_MRS_340( pVBInfo->P3c4, pVBInfo ) ; + else + XGINew_DDR1x_MRS_340( pVBInfo->P3c4, pVBInfo ) ; + } + else + XGINew_DDR2_MRS_XG20( HwDeviceExtension, pVBInfo->P3c4, pVBInfo); + + XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ; +} + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetDRAMModeRegister */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_SetDRAMModeRegister( PVB_DEVICE_INFO pVBInfo) +{ + if ( XGINew_Get310DRAMType( pVBInfo ) < 2 ) + { + XGINew_SDR_MRS(pVBInfo ) ; + } + else + { + /* SR16 <- 0F,CF,0F,8F */ + XGINew_DDR_MRS( pVBInfo ) ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DisableRefresh */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_DisableRefresh( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo) +{ + USHORT data ; + + + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1B ) ; + data &= 0xF8 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , data ) ; + +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_EnableRefresh */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_EnableRefresh( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo) +{ + + XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ; /* SR1B */ + + +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DisableChannelInterleaving */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_DisableChannelInterleaving( int index , USHORT XGINew_DDRDRAM_TYPE[][ 5 ] , PVB_DEVICE_INFO pVBInfo) +{ + USHORT data ; + + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x15 ) ; + data &= 0x1F ; + + switch( XGINew_DDRDRAM_TYPE[ index ][ 3 ] ) + { + case 64: + data |= 0 ; + break ; + case 32: + data |= 0x20 ; + break ; + case 16: + data |= 0x40 ; + break ; + case 4: + data |= 0x60 ; + break ; + default: + break ; + } + XGINew_SetReg1( pVBInfo->P3c4 , 0x15 , data ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetDRAMSizingType */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_SetDRAMSizingType( int index , USHORT DRAMTYPE_TABLE[][ 5 ] ,PVB_DEVICE_INFO pVBInfo) +{ + USHORT data ; + + data = DRAMTYPE_TABLE[ index ][ 4 ] ; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x13 , 0x80 , data ) ; + DelayUS( 15 ) ; + /* should delay 50 ns */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_CheckBusWidth_310 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_CheckBusWidth_310( PVB_DEVICE_INFO pVBInfo) +{ + USHORT data ; + PULONG volatile pVideoMemory ; + + pVideoMemory = (PULONG) pVBInfo->FBAddr; + + if ( XGINew_Get310DRAMType( pVBInfo ) < 2 ) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x00 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x12 ) ; + /* should delay */ + XGINew_SDR_MRS( pVBInfo ) ; + + XGINew_ChannelAB = 0 ; + XGINew_DataBusWidth = 128 ; + pVideoMemory[ 0 ] = 0x01234567L ; + pVideoMemory[ 1 ] = 0x456789ABL ; + pVideoMemory[ 2 ] = 0x89ABCDEFL ; + pVideoMemory[ 3 ] = 0xCDEF0123L ; + pVideoMemory[ 4 ] = 0x55555555L ; + pVideoMemory[ 5 ] = 0x55555555L ; + pVideoMemory[ 6 ] = 0xFFFFFFFFL ; + pVideoMemory[ 7 ] = 0xFFFFFFFFL ; + + if ( ( pVideoMemory[ 3 ] != 0xCDEF0123L ) || ( pVideoMemory[ 2 ] != 0x89ABCDEFL ) ) + { + /* ChannelA64Bit */ + XGINew_DataBusWidth = 64 ; + XGINew_ChannelAB = 0 ; + data=XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( USHORT )( data & 0xFD ) ) ; + } + + if ( ( pVideoMemory[ 1 ] != 0x456789ABL ) || ( pVideoMemory[ 0 ] != 0x01234567L ) ) + { + /* ChannelB64Bit */ + XGINew_DataBusWidth = 64 ; + XGINew_ChannelAB = 1 ; + data=XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( USHORT )( ( data & 0xFD ) | 0x01 ) ) ; + } + + return ; + } + else + { + /* DDR Dual channel */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x00 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x02 ) ; /* Channel A, 64bit */ + /* should delay */ + XGINew_DDR_MRS( pVBInfo ) ; + + XGINew_ChannelAB = 0 ; + XGINew_DataBusWidth = 64 ; + pVideoMemory[ 0 ] = 0x01234567L ; + pVideoMemory[ 1 ] = 0x456789ABL ; + pVideoMemory[ 2 ] = 0x89ABCDEFL ; + pVideoMemory[ 3 ] = 0xCDEF0123L ; + pVideoMemory[ 4 ] = 0x55555555L ; + pVideoMemory[ 5 ] = 0x55555555L ; + pVideoMemory[ 6 ] = 0xAAAAAAAAL ; + pVideoMemory[ 7 ] = 0xAAAAAAAAL ; + + if ( pVideoMemory[ 1 ] == 0x456789ABL ) + { + if ( pVideoMemory[ 0 ] == 0x01234567L ) + { + /* Channel A 64bit */ + return ; + } + } + else + { + if ( pVideoMemory[ 0 ] == 0x01234567L ) + { + /* Channel A 32bit */ + XGINew_DataBusWidth = 32 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x00 ) ; + return ; + } + } + + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x03 ) ; /* Channel B, 64bit */ + XGINew_DDR_MRS( pVBInfo); + + XGINew_ChannelAB = 1 ; + XGINew_DataBusWidth = 64 ; + pVideoMemory[ 0 ] = 0x01234567L ; + pVideoMemory[ 1 ] = 0x456789ABL ; + pVideoMemory[ 2 ] = 0x89ABCDEFL ; + pVideoMemory[ 3 ] = 0xCDEF0123L ; + pVideoMemory[ 4 ] = 0x55555555L ; + pVideoMemory[ 5 ] = 0x55555555L ; + pVideoMemory[ 6 ] = 0xAAAAAAAAL ; + pVideoMemory[ 7 ] = 0xAAAAAAAAL ; + + if ( pVideoMemory[ 1 ] == 0x456789ABL ) + { + /* Channel B 64 */ + if ( pVideoMemory[ 0 ] == 0x01234567L ) + { + /* Channel B 64bit */ + return ; + } + else + { + /* error */ + } + } + else + { + if ( pVideoMemory[ 0 ] == 0x01234567L ) + { + /* Channel B 32 */ + XGINew_DataBusWidth = 32 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x01 ) ; + } + else + { + /* error */ + } + } + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetRank */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +int XGINew_SetRank( int index , UCHAR RankNo , UCHAR XGINew_ChannelAB , USHORT DRAMTYPE_TABLE[][ 5 ] , PVB_DEVICE_INFO pVBInfo) +{ + USHORT data ; + int RankSize ; + + if ( ( RankNo == 2 ) && ( DRAMTYPE_TABLE[ index ][ 0 ] == 2 ) ) + return 0 ; + + RankSize = DRAMTYPE_TABLE[ index ][ 3 ] / 2 * XGINew_DataBusWidth / 32 ; + + if ( ( RankNo * RankSize ) <= 128 ) + { + data = 0 ; + + while( ( RankSize >>= 1 ) > 0 ) + { + data += 0x10 ; + } + data |= ( RankNo - 1 ) << 2 ; + data |= ( XGINew_DataBusWidth / 64 ) & 2 ; + data |= XGINew_ChannelAB ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ; + /* should delay */ + XGINew_SDR_MRS( pVBInfo ) ; + return( 1 ) ; + } + else + return( 0 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetDDRChannel */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +int XGINew_SetDDRChannel( int index , UCHAR ChannelNo , UCHAR XGINew_ChannelAB , USHORT DRAMTYPE_TABLE[][ 5 ] , PVB_DEVICE_INFO pVBInfo) +{ + USHORT data ; + int RankSize ; + + RankSize = DRAMTYPE_TABLE[index][3]/2 * XGINew_DataBusWidth/32; + /* RankSize = DRAMTYPE_TABLE[ index ][ 3 ] ; */ + if ( ChannelNo * RankSize <= 128 ) + { + data = 0 ; + while( ( RankSize >>= 1 ) > 0 ) + { + data += 0x10 ; + } + + if ( ChannelNo == 2 ) + data |= 0x0C ; + + data |= ( XGINew_DataBusWidth / 32 ) & 2 ; + data |= XGINew_ChannelAB ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ; + /* should delay */ + XGINew_DDR_MRS( pVBInfo ) ; + return( 1 ) ; + } + else + return( 0 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_CheckColumn */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +int XGINew_CheckColumn( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo) +{ + int i ; + ULONG Increment , Position ; + + /* Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + XGINew_DataBusWidth / 64 + 1 ) ; */ + Increment = 1 << ( 10 + XGINew_DataBusWidth / 64 ) ; + + for( i = 0 , Position = 0 ; i < 2 ; i++ ) + { + *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ; + Position += Increment ; + } + +#ifdef WIN2000 /* chiawen for linux solution */ + DelayUS( 100 ) ; +#endif + + for( i = 0 , Position = 0 ; i < 2 ; i++ ) + { + /* if ( pVBInfo->FBAddr[ Position ] != Position ) */ + if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position ) + return( 0 ) ; + Position += Increment ; + } + return( 1 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_CheckBanks */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +int XGINew_CheckBanks( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo) +{ + int i ; + ULONG Increment , Position ; + + Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + XGINew_DataBusWidth / 64 + 2 ) ; + + for( i = 0 , Position = 0 ; i < 4 ; i++ ) + { + /* pVBInfo->FBAddr[ Position ] = Position ; */ + *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ; + Position += Increment ; + } + + for( i = 0 , Position = 0 ; i < 4 ; i++ ) + { + /* if (pVBInfo->FBAddr[ Position ] != Position ) */ + if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position ) + return( 0 ) ; + Position += Increment ; + } + return( 1 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_CheckRank */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +int XGINew_CheckRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo) +{ + int i ; + ULONG Increment , Position ; + + Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + DRAMTYPE_TABLE[ index ][ 1 ] + + DRAMTYPE_TABLE[ index ][ 0 ] + XGINew_DataBusWidth / 64 + RankNo ) ; + + for( i = 0 , Position = 0 ; i < 2 ; i++ ) + { + /* pVBInfo->FBAddr[ Position ] = Position ; */ + /* *( ( PULONG )( pVBInfo->FBAddr ) ) = Position ; */ + *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ; + Position += Increment ; + } + + for( i = 0 , Position = 0 ; i < 2 ; i++ ) + { + /* if ( pVBInfo->FBAddr[ Position ] != Position ) */ + /* if ( ( *( PULONG )( pVBInfo->FBAddr ) ) != Position ) */ + if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position ) + return( 0 ) ; + Position += Increment ; + } + return( 1 ); +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_CheckDDRRank */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +int XGINew_CheckDDRRank( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo) +{ + ULONG Increment , Position ; + USHORT data ; + + Increment = 1 << ( DRAMTYPE_TABLE[ index ][ 2 ] + DRAMTYPE_TABLE[ index ][ 1 ] + + DRAMTYPE_TABLE[ index ][ 0 ] + XGINew_DataBusWidth / 64 + RankNo ) ; + + Increment += Increment / 2 ; + + Position = 0; + *( ( PULONG )( pVBInfo->FBAddr + Position + 0 ) ) = 0x01234567 ; + *( ( PULONG )( pVBInfo->FBAddr + Position + 1 ) ) = 0x456789AB ; + *( ( PULONG )( pVBInfo->FBAddr + Position + 2 ) ) = 0x55555555 ; + *( ( PULONG )( pVBInfo->FBAddr + Position + 3 ) ) = 0x55555555 ; + *( ( PULONG )( pVBInfo->FBAddr + Position + 4 ) ) = 0xAAAAAAAA ; + *( ( PULONG )( pVBInfo->FBAddr + Position + 5 ) ) = 0xAAAAAAAA ; + + if ( ( *( PULONG )( pVBInfo->FBAddr + 1 ) ) == 0x456789AB ) + return( 1 ) ; + + if ( ( *( PULONG )( pVBInfo->FBAddr + 0 ) ) == 0x01234567 ) + return( 0 ) ; + + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ; + data &= 0xF3 ; + data |= 0x0E ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ; + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x15 ) ; + data += 0x20 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x15 , data ) ; + + return( 1 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_CheckRanks */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +int XGINew_CheckRanks( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo) +{ + int r ; + + for( r = RankNo ; r >= 1 ; r-- ) + { + if ( !XGINew_CheckRank( r , index , DRAMTYPE_TABLE, pVBInfo ) ) + return( 0 ) ; + } + + if ( !XGINew_CheckBanks( index , DRAMTYPE_TABLE, pVBInfo ) ) + return( 0 ) ; + + if ( !XGINew_CheckColumn( index , DRAMTYPE_TABLE, pVBInfo ) ) + return( 0 ) ; + + return( 1 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_CheckDDRRanks */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +int XGINew_CheckDDRRanks( int RankNo , int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo) +{ + int r ; + + for( r = RankNo ; r >= 1 ; r-- ) + { + if ( !XGINew_CheckDDRRank( r , index , DRAMTYPE_TABLE, pVBInfo ) ) + return( 0 ) ; + } + + if ( !XGINew_CheckBanks( index , DRAMTYPE_TABLE, pVBInfo ) ) + return( 0 ) ; + + if ( !XGINew_CheckColumn( index , DRAMTYPE_TABLE, pVBInfo ) ) + return( 0 ) ; + + return( 1 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +int XGINew_SDRSizing(PVB_DEVICE_INFO pVBInfo) +{ + int i ; + UCHAR j ; + + for( i = 0 ; i < 13 ; i++ ) + { + XGINew_SetDRAMSizingType( i , XGINew_SDRDRAM_TYPE , pVBInfo) ; + + for( j = 2 ; j > 0 ; j-- ) + { + if ( !XGINew_SetRank( i , ( UCHAR )j , XGINew_ChannelAB , XGINew_SDRDRAM_TYPE , pVBInfo) ) + continue ; + else + { + if ( XGINew_CheckRanks( j , i , XGINew_SDRDRAM_TYPE, pVBInfo) ) + return( 1 ) ; + } + } + } + return( 0 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetDRAMSizeReg */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +USHORT XGINew_SetDRAMSizeReg( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo) +{ + USHORT data = 0 , memsize = 0 ; + int RankSize ; + UCHAR ChannelNo ; + + RankSize = DRAMTYPE_TABLE[ index ][ 3 ] * XGINew_DataBusWidth / 32 ; + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x13 ) ; + data &= 0x80 ; + + if ( data == 0x80 ) + RankSize *= 2 ; + + data = 0 ; + + if( XGINew_ChannelAB == 3 ) + ChannelNo = 4 ; + else + ChannelNo = XGINew_ChannelAB ; + + if ( ChannelNo * RankSize <= 256 ) + { + while( ( RankSize >>= 1 ) > 0 ) + { + data += 0x10 ; + } + + memsize = data >> 4 ; + + /* [2004/03/25] Vicent, Fix DRAM Sizing Error */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) & 0x0F ) | ( data & 0xF0 ) ) ; + + /* data |= XGINew_ChannelAB << 2 ; */ + /* data |= ( XGINew_DataBusWidth / 64 ) << 1 ; */ + /* XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ; */ + + /* should delay */ + /* XGINew_SetDRAMModeRegister340( pVBInfo ) ; */ + } + return( memsize ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetDRAMSize20Reg */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +USHORT XGINew_SetDRAMSize20Reg( int index , USHORT DRAMTYPE_TABLE[][ 5 ], PVB_DEVICE_INFO pVBInfo) +{ + USHORT data = 0 , memsize = 0 ; + int RankSize ; + UCHAR ChannelNo ; + + RankSize = DRAMTYPE_TABLE[ index ][ 3 ] * XGINew_DataBusWidth / 8 ; + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x13 ) ; + data &= 0x80 ; + + if ( data == 0x80 ) + RankSize *= 2 ; + + data = 0 ; + + if( XGINew_ChannelAB == 3 ) + ChannelNo = 4 ; + else + ChannelNo = XGINew_ChannelAB ; + + if ( ChannelNo * RankSize <= 256 ) + { + while( ( RankSize >>= 1 ) > 0 ) + { + data += 0x10 ; + } + + memsize = data >> 4 ; + + /* [2004/03/25] Vicent, Fix DRAM Sizing Error */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , ( XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) & 0x0F ) | ( data & 0xF0 ) ) ; + DelayUS( 15 ) ; + + /* data |= XGINew_ChannelAB << 2 ; */ + /* data |= ( XGINew_DataBusWidth / 64 ) << 1 ; */ + /* XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , data ) ; */ + + /* should delay */ + /* XGINew_SetDRAMModeRegister340( pVBInfo ) ; */ + } + return( memsize ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_ReadWriteRest */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +int XGINew_ReadWriteRest( USHORT StopAddr , USHORT StartAddr, PVB_DEVICE_INFO pVBInfo) +{ + int i ; + ULONG Position = 0 ; + + *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ; + + for( i = StartAddr ; i <= StopAddr ; i++ ) + { + Position = 1 << i ; + *( ( PULONG )( pVBInfo->FBAddr + Position ) ) = Position ; + } + + DelayUS( 500 ) ; /* [Vicent] 2004/04/16. Fix #1759 Memory Size error in Multi-Adapter. */ + + Position = 0 ; + + if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position ) + return( 0 ) ; + + for( i = StartAddr ; i <= StopAddr ; i++ ) + { + Position = 1 << i ; + if ( ( *( PULONG )( pVBInfo->FBAddr + Position ) ) != Position ) + return( 0 ) ; + } + return( 1 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_CheckFrequence */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +UCHAR XGINew_CheckFrequence( PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR data ; + + data = XGINew_GetReg1( pVBInfo->P3d4 , 0x97 ) ; + + if ( ( data & 0x10 ) == 0 ) + { + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x39 ) ; + data = ( data & 0x02 ) >> 1 ; + return( data ) ; + } + else + return( data & 0x01 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_CheckChannel */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_CheckChannel( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) +{ + UCHAR data; + + switch( HwDeviceExtension->jChipType ) + { + case XG20: + case XG21: + data = XGINew_GetReg1( pVBInfo->P3d4 , 0x97 ) ; + data = data & 0x01; + XGINew_ChannelAB = 1 ; /* XG20 "JUST" one channel */ + + if ( data == 0 ) /* Single_32_16 */ + { + + if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x1000000) + { + + XGINew_DataBusWidth = 32 ; /* 32 bits */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ; /* 22bit + 2 rank + 32bit */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x52 ) ; + DelayUS( 15 ) ; + + if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 ) + return ; + + if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x800000) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ; /* 22bit + 1 rank + 32bit */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x42 ) ; + DelayUS( 15 ) ; + + if ( XGINew_ReadWriteRest( 23 , 23 , pVBInfo ) == 1 ) + return ; + } + } + + if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x800000) + { + XGINew_DataBusWidth = 16 ; /* 16 bits */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ; /* 22bit + 2 rank + 16bit */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x41 ) ; + DelayUS( 15 ) ; + + if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 ) + return ; + else + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ; + DelayUS( 15 ) ; + } + + } + else /* Dual_16_8 */ + { + if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x800000) + { + + XGINew_DataBusWidth = 16 ; /* 16 bits */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ; /* (0x31:12x8x2) 22bit + 2 rank */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x41 ) ; /* 0x41:16Mx16 bit*/ + DelayUS( 15 ) ; + + if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 ) + return ; + + if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x400000) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ; /* (0x31:12x8x2) 22bit + 1 rank */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x31 ) ; /* 0x31:8Mx16 bit*/ + DelayUS( 15 ) ; + + if ( XGINew_ReadWriteRest( 22 , 22 , pVBInfo ) == 1 ) + return ; + } + } + + + if (( HwDeviceExtension->ulVideoMemorySize - 1 ) > 0x400000) + { + XGINew_DataBusWidth = 8 ; /* 8 bits */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xB1 ) ; /* (0x31:12x8x2) 22bit + 2 rank */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x30 ) ; /* 0x30:8Mx8 bit*/ + DelayUS( 15 ) ; + + if ( XGINew_ReadWriteRest( 22 , 21 , pVBInfo ) == 1 ) + return ; + else + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x31 ) ; /* (0x31:12x8x2) 22bit + 1 rank */ + DelayUS( 15 ) ; + } + } + break ; + + case XG27: + XGINew_DataBusWidth = 16 ; /* 16 bits */ + XGINew_ChannelAB = 1 ; /* Single channel */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x51 ) ; /* 32Mx16 bit*/ + break ; + case XG41: + if ( XGINew_CheckFrequence(pVBInfo) == 1 ) + { + XGINew_DataBusWidth = 32 ; /* 32 bits */ + XGINew_ChannelAB = 3 ; /* Quad Channel */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4C ) ; + + if ( XGINew_ReadWriteRest( 25 , 23 , pVBInfo ) == 1 ) + return ; + + XGINew_ChannelAB = 2 ; /* Dual channels */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x48 ) ; + + if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 ) + return ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x49 ) ; + + if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 ) + return ; + + XGINew_ChannelAB = 3 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x3C ) ; + + if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 ) + return ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x38 ) ; + + if ( XGINew_ReadWriteRest( 8 , 4 , pVBInfo ) == 1 ) + return ; + else + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x39 ) ; + } + else + { /* DDR */ + XGINew_DataBusWidth = 64 ; /* 64 bits */ + XGINew_ChannelAB = 2 ; /* Dual channels */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x5A ) ; + + if ( XGINew_ReadWriteRest( 25 , 24 , pVBInfo ) == 1 ) + return ; + + XGINew_ChannelAB = 1 ; /* Single channels */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x52 ) ; + + if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 ) + return ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x53 ) ; + + if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 ) + return ; + + XGINew_ChannelAB = 2 ; /* Dual channels */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4A ) ; + + if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 ) + return ; + + XGINew_ChannelAB = 1 ; /* Single channels */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x42 ) ; + + if ( XGINew_ReadWriteRest( 8 , 4 , pVBInfo ) == 1 ) + return ; + else + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x43 ) ; + } + + break ; + + case XG42: +/* + XG42 SR14 D[3] Reserve + D[2] = 1, Dual Channel + = 0, Single Channel + + It's Different from Other XG40 Series. +*/ + if ( XGINew_CheckFrequence(pVBInfo) == 1 ) /* DDRII, DDR2x */ + { + XGINew_DataBusWidth = 32 ; /* 32 bits */ + XGINew_ChannelAB = 2 ; /* 2 Channel */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x44 ) ; + + if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 ) + return ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x34 ) ; + if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 ) + return ; + + XGINew_ChannelAB = 1 ; /* Single Channel */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x40 ) ; + + if ( XGINew_ReadWriteRest( 23 , 22 , pVBInfo ) == 1 ) + return ; + else + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x30 ) ; + } + } + else + { /* DDR */ + XGINew_DataBusWidth = 64 ; /* 64 bits */ + XGINew_ChannelAB = 1 ; /* 1 channels */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x52 ) ; + + if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 ) + return ; + else + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x42 ) ; + } + } + + break ; + + default: /* XG40 */ + + if ( XGINew_CheckFrequence(pVBInfo) == 1 ) /* DDRII */ + { + XGINew_DataBusWidth = 32 ; /* 32 bits */ + XGINew_ChannelAB = 3 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4C ) ; + + if ( XGINew_ReadWriteRest( 25 , 23 , pVBInfo ) == 1 ) + return ; + + XGINew_ChannelAB = 2 ; /* 2 channels */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x48 ) ; + + if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 ) + return ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x3C ) ; + + if ( XGINew_ReadWriteRest( 24 , 23 , pVBInfo ) == 1 ) + XGINew_ChannelAB = 3 ; /* 4 channels */ + else + { + XGINew_ChannelAB = 2 ; /* 2 channels */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x38 ) ; + } + } + else + { /* DDR */ + XGINew_DataBusWidth = 64 ; /* 64 bits */ + XGINew_ChannelAB = 2 ; /* 2 channels */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0xA1 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x5A ) ; + + if ( XGINew_ReadWriteRest( 25 , 24 , pVBInfo ) == 1 ) + return ; + else + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x13 , 0x21 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x14 , 0x4A ) ; + } + } + break ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DDRSizing340 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +int XGINew_DDRSizing340( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) +{ + int i ; + USHORT memsize , addr ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x15 , 0x00 ) ; /* noninterleaving */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x1C , 0x00 ) ; /* nontiling */ + XGINew_CheckChannel( HwDeviceExtension, pVBInfo ) ; + + + if ( HwDeviceExtension->jChipType >= XG20 ) + { + for( i = 0 ; i < 12 ; i++ ) + { + XGINew_SetDRAMSizingType( i , XGINew_DDRDRAM_TYPE20, pVBInfo ) ; + memsize = XGINew_SetDRAMSize20Reg( i , XGINew_DDRDRAM_TYPE20, pVBInfo ) ; + if ( memsize == 0 ) + continue ; + + addr = memsize + ( XGINew_ChannelAB - 2 ) + 20 ; + if ( ( HwDeviceExtension->ulVideoMemorySize - 1 ) < ( ULONG )( 1 << addr ) ) + continue ; + + if ( XGINew_ReadWriteRest( addr , 5, pVBInfo ) == 1 ) + return( 1 ) ; + } + } + else + { + for( i = 0 ; i < 4 ; i++ ) + { + XGINew_SetDRAMSizingType( i , XGINew_DDRDRAM_TYPE340, pVBInfo ) ; + memsize = XGINew_SetDRAMSizeReg( i , XGINew_DDRDRAM_TYPE340, pVBInfo ) ; + + if ( memsize == 0 ) + continue ; + + addr = memsize + ( XGINew_ChannelAB - 2 ) + 20 ; + if ( ( HwDeviceExtension->ulVideoMemorySize - 1 ) < ( ULONG )( 1 << addr ) ) + continue ; + + if ( XGINew_ReadWriteRest( addr , 9, pVBInfo ) == 1 ) + return( 1 ) ; + } + } + return( 0 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DDRSizing */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +int XGINew_DDRSizing(PVB_DEVICE_INFO pVBInfo) +{ + int i ; + UCHAR j ; + + for( i = 0 ; i < 4 ; i++ ) + { + XGINew_SetDRAMSizingType( i , XGINew_DDRDRAM_TYPE, pVBInfo ) ; + XGINew_DisableChannelInterleaving( i , XGINew_DDRDRAM_TYPE , pVBInfo) ; + for( j = 2 ; j > 0 ; j-- ) + { + XGINew_SetDDRChannel( i , j , XGINew_ChannelAB , XGINew_DDRDRAM_TYPE , pVBInfo ) ; + if ( !XGINew_SetRank( i , ( UCHAR )j , XGINew_ChannelAB , XGINew_DDRDRAM_TYPE, pVBInfo ) ) + continue ; + else + { + if ( XGINew_CheckDDRRanks( j , i , XGINew_DDRDRAM_TYPE, pVBInfo ) ) + return( 1 ) ; + } + } + } + return( 0 ) ; +} + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetMemoryClock */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_SetMemoryClock( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) +{ + + + XGINew_SetReg1( pVBInfo->P3c4 , 0x28 , pVBInfo->MCLKData[ XGINew_RAMType ].SR28 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x29 , pVBInfo->MCLKData[ XGINew_RAMType ].SR29 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2A , pVBInfo->MCLKData[ XGINew_RAMType ].SR2A ) ; + + + + XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , pVBInfo->ECLKData[ XGINew_RAMType ].SR2E ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , pVBInfo->ECLKData[ XGINew_RAMType ].SR2F ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x30 , pVBInfo->ECLKData[ XGINew_RAMType ].SR30 ) ; + + /* [Vicent] 2004/07/07, When XG42 ECLK = MCLK = 207MHz, Set SR32 D[1:0] = 10b */ + /* [Hsuan] 2004/08/20, Modify SR32 value, when MCLK=207MHZ, ELCK=250MHz, Set SR32 D[1:0] = 10b */ + if ( HwDeviceExtension->jChipType == XG42 ) + { + if ( ( pVBInfo->MCLKData[ XGINew_RAMType ].SR28 == 0x1C ) && ( pVBInfo->MCLKData[ XGINew_RAMType ].SR29 == 0x01 ) + && ( ( ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2E == 0x1C ) && ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2F == 0x01 ) ) + || ( ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2E == 0x22 ) && ( pVBInfo->ECLKData[ XGINew_RAMType ].SR2F == 0x01 ) ) ) ) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , ( ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) & 0xFC ) | 0x02 ) ; + } + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : ChkLFB */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN ChkLFB( PVB_DEVICE_INFO pVBInfo ) +{ + if ( LFBDRAMTrap & XGINew_GetReg1( pVBInfo->P3d4 , 0x78 ) ) + return( TRUE ) ; + else + return( FALSE ); +} + + +/* --------------------------------------------------------------------- */ +/* input : dx ,valid value : CR or second chip's CR */ +/* */ +/* SetPowerConsume : */ +/* Description: reduce 40/43 power consumption in first chip or */ +/* in second chip, assume CR A1 D[6]="1" in this case */ +/* output : none */ +/* --------------------------------------------------------------------- */ +void SetPowerConsume ( PXGI_HW_DEVICE_INFO HwDeviceExtension , ULONG XGI_P3d4Port ) +{ + ULONG lTemp ; + UCHAR bTemp; + + HwDeviceExtension->pQueryVGAConfigSpace( HwDeviceExtension , 0x08 , 0 , &lTemp ) ; /* Get */ + if ((lTemp&0xFF)==0) + { + /* set CR58 D[5]=0 D[3]=0 */ + XGINew_SetRegAND( XGI_P3d4Port , 0x58 , 0xD7 ) ; + bTemp = (UCHAR) XGINew_GetReg1( XGI_P3d4Port , 0xCB ) ; + if (bTemp&0x20) + { + if (!(bTemp&0x10)) + { + XGINew_SetRegANDOR( XGI_P3d4Port , 0x58 , 0xD7 , 0x20 ) ; /* CR58 D[5]=1 D[3]=0 */ + } + else + { + XGINew_SetRegANDOR( XGI_P3d4Port , 0x58 , 0xD7 , 0x08 ) ; /* CR58 D[5]=0 D[3]=1 */ + } + + } + + } +} + + + +#if defined(LINUX_XF86)||defined(LINUX_KERNEL) +void XGINew_InitVBIOSData(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) +{ + + /* ULONG ROMAddr = (ULONG)HwDeviceExtension->pjVirtualRomBase; */ + pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ; + pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; + pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ; + pVBInfo->ISXPDOS = 0 ; + + pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ; + pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ; + pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ; + pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ; + pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ; + pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ; + pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ; + pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ; + pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ; + pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ; + pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ; + pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ; + pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ; + pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ; + pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ; + pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ; + pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ; + if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */ + XGI_GetVBType( pVBInfo ) ; /* Run XGI_GetVBType before InitTo330Pointer */ + + switch(HwDeviceExtension->jChipType) + { + case XG40: + case XG41: + case XG42: + case XG20: + case XG21: + default: + InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo); + return ; + } + +} +#endif /* For Linux */ + +/* --------------------------------------------------------------------- */ +/* Function : ReadVBIOSTablData */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo) +{ + PUCHAR volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ; + ULONG i ; + UCHAR j , k ; +#if 0 + ULONG ii , jj ; + i = pVideoMemory[ 0x1CF ] | ( pVideoMemory[ 0x1D0 ] << 8 ) ; /* UniROM */ + if ( i != 0 ) + UNIROM = 1 ; + + ii = 0x90 ; + for( jj = 0x00 ; jj < 0x08 ; jj++ ) + { + pVBInfo->MCLKData[ jj ].SR28 = pVideoMemory[ ii ] ; + pVBInfo->MCLKData[ jj ].SR29 = pVideoMemory[ ii + 1] ; + pVBInfo->MCLKData[ jj ].SR2A = pVideoMemory[ ii + 2] ; + pVBInfo->MCLKData[ jj ].CLOCK = pVideoMemory[ ii + 3 ] | ( pVideoMemory[ ii + 4 ] << 8 ) ; + ii += 0x05 ; + } + + ii = 0xB8 ; + for( jj = 0x00 ; jj < 0x08 ; jj++ ) + { + pVBInfo->ECLKData[ jj ].SR2E = pVideoMemory[ ii ] ; + pVBInfo->ECLKData[ jj ].SR2F=pVideoMemory[ ii + 1 ] ; + pVBInfo->ECLKData[ jj ].SR30= pVideoMemory[ ii + 2 ] ; + pVBInfo->ECLKData[ jj ].CLOCK= pVideoMemory[ ii + 3 ] | ( pVideoMemory[ ii + 4 ] << 8 ) ; + ii += 0x05 ; + } + + /* Volari customize data area start */ + /* if ( ChipType == XG40 ) */ + if ( ChipType >= XG40 ) + { + ii = 0xE0 ; + for( jj = 0x00 ; jj < 0x03 ; jj++ ) + { + pVBInfo->SR15[ jj ][ 0 ] = pVideoMemory[ ii ] ; /* SR13, SR14, and SR18 */ + pVBInfo->SR15[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ; + pVBInfo->SR15[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ; + pVBInfo->SR15[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ; + pVBInfo->SR15[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ; + pVBInfo->SR15[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ; + pVBInfo->SR15[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ; + pVBInfo->SR15[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ; + ii += 0x08 ; + } + ii = 0x110 ; + jj = 0x03 ; + pVBInfo->SR15[ jj ][ 0 ] = pVideoMemory[ ii ] ; /* SR1B */ + pVBInfo->SR15[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ; + pVBInfo->SR15[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ; + pVBInfo->SR15[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ; + pVBInfo->SR15[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ; + pVBInfo->SR15[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ; + pVBInfo->SR15[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ; + pVBInfo->SR15[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ; + + *pVBInfo->pSR07 = pVideoMemory[ 0x74 ] ; + *pVBInfo->pSR1F = pVideoMemory[ 0x75 ] ; + *pVBInfo->pSR21 = pVideoMemory[ 0x76 ] ; + *pVBInfo->pSR22 = pVideoMemory[ 0x77 ] ; + *pVBInfo->pSR23 = pVideoMemory[ 0x78 ] ; + *pVBInfo->pSR24 = pVideoMemory[ 0x79 ] ; + pVBInfo->SR25[ 0 ] = pVideoMemory[ 0x7A ] ; + *pVBInfo->pSR31 = pVideoMemory[ 0x7B ] ; + *pVBInfo->pSR32 = pVideoMemory[ 0x7C ] ; + *pVBInfo->pSR33 = pVideoMemory[ 0x7D ] ; + ii = 0xF8 ; + + for( jj = 0 ; jj < 3 ; jj++ ) + { + pVBInfo->CR40[ jj ][ 0 ] = pVideoMemory[ ii ] ; + pVBInfo->CR40[ jj ][ 1 ] = pVideoMemory[ ii + 1 ] ; + pVBInfo->CR40[ jj ][ 2 ] = pVideoMemory[ ii + 2 ] ; + pVBInfo->CR40[ jj ][ 3 ] = pVideoMemory[ ii + 3 ] ; + pVBInfo->CR40[ jj ][ 4 ] = pVideoMemory[ ii + 4 ] ; + pVBInfo->CR40[ jj ][ 5 ] = pVideoMemory[ ii + 5 ] ; + pVBInfo->CR40[ jj ][ 6 ] = pVideoMemory[ ii + 6 ] ; + pVBInfo->CR40[ jj ][ 7 ] = pVideoMemory[ ii + 7 ] ; + ii += 0x08 ; + } + + ii = 0x118 ; + for( j = 3 ; j < 24 ; j++ ) + { + pVBInfo->CR40[ j ][ 0 ] = pVideoMemory[ ii ] ; + pVBInfo->CR40[ j ][ 1 ] = pVideoMemory[ ii + 1 ] ; + pVBInfo->CR40[ j ][ 2 ] = pVideoMemory[ ii + 2 ] ; + pVBInfo->CR40[ j ][ 3 ] = pVideoMemory[ ii + 3 ] ; + pVBInfo->CR40[ j ][ 4 ] = pVideoMemory[ ii + 4 ] ; + pVBInfo->CR40[ j ][ 5 ] = pVideoMemory[ ii + 5 ] ; + pVBInfo->CR40[ j ][ 6 ] = pVideoMemory[ ii + 6 ] ; + pVBInfo->CR40[ j ][ 7 ] = pVideoMemory[ ii + 7 ] ; + ii += 0x08 ; + } + + i = pVideoMemory[ 0x1C0 ] | ( pVideoMemory[ 0x1C1 ] << 8 ) ; + + for( j = 0 ; j < 8 ; j++ ) + { + for( k = 0 ; k < 4 ; k++ ) + pVBInfo->CR6B[ j ][ k ] = pVideoMemory[ i + 4 * j + k ] ; + } + + i = pVideoMemory[ 0x1C2 ] | ( pVideoMemory[ 0x1C3 ] << 8 ) ; + + for( j = 0 ; j < 8 ; j++ ) + { + for( k = 0 ; k < 4 ; k++ ) + pVBInfo->CR6E[ j ][ k ] = pVideoMemory[ i + 4 * j + k ] ; + } + + i = pVideoMemory[ 0x1C4 ] | ( pVideoMemory[ 0x1C5 ] << 8 ) ; + for( j = 0 ; j < 8 ; j++ ) + { + for( k = 0 ; k < 32 ; k++ ) + pVBInfo->CR6F[ j ][ k ] = pVideoMemory[ i + 32 * j + k ] ; + } + + i = pVideoMemory[ 0x1C6 ] | ( pVideoMemory[ 0x1C7 ] << 8 ) ; + + for( j = 0 ; j < 8 ; j++ ) + { + for( k = 0 ; k < 2 ; k++ ) + pVBInfo->CR89[ j ][ k ] = pVideoMemory[ i + 2 * j + k ] ; + } + + i = pVideoMemory[ 0x1C8 ] | ( pVideoMemory[ 0x1C9 ] << 8 ) ; + for( j = 0 ; j < 12 ; j++ ) + pVBInfo->AGPReg[ j ] = pVideoMemory[ i + j ] ; + + i = pVideoMemory[ 0x1CF ] | ( pVideoMemory[ 0x1D0 ] << 8 ) ; + for( j = 0 ; j < 4 ; j++ ) + pVBInfo->SR16[ j ] = pVideoMemory[ i + j ] ; + + if ( ChipType == XG21 ) + { + if (pVideoMemory[ 0x67 ] & 0x80) + { + *pVBInfo->pDVOSetting = pVideoMemory[ 0x67 ]; + } + if ( (pVideoMemory[ 0x67 ] & 0xC0) == 0xC0 ) + { + *pVBInfo->pCR2E = pVideoMemory[ i + 4 ] ; + *pVBInfo->pCR2F = pVideoMemory[ i + 5 ] ; + *pVBInfo->pCR46 = pVideoMemory[ i + 6 ] ; + *pVBInfo->pCR47 = pVideoMemory[ i + 7 ] ; + } + } + + if ( ChipType == XG27 ) + { + jj = i+j; + for( i = 0 ; i <= 0xB ; i++,jj++ ) + pVBInfo->pCRD0[i] = pVideoMemory[ jj ] ; + for( i = 0x0 ; i <= 0x1 ; i++,jj++ ) + pVBInfo->pCRDE[i] = pVideoMemory[ jj ] ; + + *pVBInfo->pSR40 = pVideoMemory[ jj ] ; + jj++; + *pVBInfo->pSR41 = pVideoMemory[ jj ] ; + + if (pVideoMemory[ 0x67 ] & 0x80) + { + *pVBInfo->pDVOSetting = pVideoMemory[ 0x67 ]; + } + if ( (pVideoMemory[ 0x67 ] & 0xC0) == 0xC0 ) + { + jj++; + *pVBInfo->pCR2E = pVideoMemory[ jj ] ; + *pVBInfo->pCR2F = pVideoMemory[ jj + 1 ] ; + *pVBInfo->pCR46 = pVideoMemory[ jj + 2 ] ; + *pVBInfo->pCR47 = pVideoMemory[ jj + 3 ] ; + } + + } + + *pVBInfo->pCRCF = pVideoMemory[ 0x1CA ] ; + *pVBInfo->pXGINew_DRAMTypeDefinition = pVideoMemory[ 0x1CB ] ; + *pVBInfo->pXGINew_I2CDefinition = pVideoMemory[ 0x1D1 ] ; + if ( ChipType >= XG20 ) + { + *pVBInfo->pXGINew_CR97 = pVideoMemory[ 0x1D2 ] ; + if ( ChipType == XG27 ) + { + *pVBInfo->pSR36 = pVideoMemory[ 0x1D3 ] ; + *pVBInfo->pCR8F = pVideoMemory[ 0x1D5 ] ; + } + } + + } +#endif + /* Volari customize data area end */ + + if ( ChipType == XG21 ) + { + pVBInfo->IF_DEF_LVDS = 0 ; + if (pVideoMemory[ 0x65 ] & 0x1) + { + pVBInfo->IF_DEF_LVDS = 1 ; + i = pVideoMemory[ 0x316 ] | ( pVideoMemory[ 0x317 ] << 8 ); + j = pVideoMemory[ i-1 ] ; + if ( j != 0xff ) + { + k = 0; + do + { + pVBInfo->XG21_LVDSCapList[k].LVDS_Capability = pVideoMemory[ i ] | ( pVideoMemory[ i + 1 ] << 8 ); + pVBInfo->XG21_LVDSCapList[k].LVDSHT = pVideoMemory[ i + 2 ] | ( pVideoMemory[ i + 3 ] << 8 ) ; + pVBInfo->XG21_LVDSCapList[k].LVDSVT = pVideoMemory[ i + 4 ] | ( pVideoMemory[ i + 5 ] << 8 ); + pVBInfo->XG21_LVDSCapList[k].LVDSHDE = pVideoMemory[ i + 6 ] | ( pVideoMemory[ i + 7 ] << 8 ); + pVBInfo->XG21_LVDSCapList[k].LVDSVDE = pVideoMemory[ i + 8 ] | ( pVideoMemory[ i + 9 ] << 8 ); + pVBInfo->XG21_LVDSCapList[k].LVDSHFP = pVideoMemory[ i + 10 ] | ( pVideoMemory[ i + 11 ] << 8 ); + pVBInfo->XG21_LVDSCapList[k].LVDSVFP = pVideoMemory[ i + 12 ] | ( pVideoMemory[ i + 13 ] << 8 ); + pVBInfo->XG21_LVDSCapList[k].LVDSHSYNC = pVideoMemory[ i + 14 ] | ( pVideoMemory[ i + 15 ] << 8 ); + pVBInfo->XG21_LVDSCapList[k].LVDSVSYNC = pVideoMemory[ i + 16 ] | ( pVideoMemory[ i + 17 ] << 8 ); + pVBInfo->XG21_LVDSCapList[k].VCLKData1 = pVideoMemory[ i + 18 ] ; + pVBInfo->XG21_LVDSCapList[k].VCLKData2 = pVideoMemory[ i + 19 ] ; + pVBInfo->XG21_LVDSCapList[k].PSC_S1 = pVideoMemory[ i + 20 ] ; + pVBInfo->XG21_LVDSCapList[k].PSC_S2 = pVideoMemory[ i + 21 ] ; + pVBInfo->XG21_LVDSCapList[k].PSC_S3 = pVideoMemory[ i + 22 ] ; + pVBInfo->XG21_LVDSCapList[k].PSC_S4 = pVideoMemory[ i + 23 ] ; + pVBInfo->XG21_LVDSCapList[k].PSC_S5 = pVideoMemory[ i + 24 ] ; + i += 25; + j--; + k++; + } while ( (j>0) && ( k < (sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) ) ); + } + else + { + pVBInfo->XG21_LVDSCapList[0].LVDS_Capability = pVideoMemory[ i ] | ( pVideoMemory[ i + 1 ] << 8 ); + pVBInfo->XG21_LVDSCapList[0].LVDSHT = pVideoMemory[ i + 2 ] | ( pVideoMemory[ i + 3 ] << 8 ) ; + pVBInfo->XG21_LVDSCapList[0].LVDSVT = pVideoMemory[ i + 4 ] | ( pVideoMemory[ i + 5 ] << 8 ); + pVBInfo->XG21_LVDSCapList[0].LVDSHDE = pVideoMemory[ i + 6 ] | ( pVideoMemory[ i + 7 ] << 8 ); + pVBInfo->XG21_LVDSCapList[0].LVDSVDE = pVideoMemory[ i + 8 ] | ( pVideoMemory[ i + 9 ] << 8 ); + pVBInfo->XG21_LVDSCapList[0].LVDSHFP = pVideoMemory[ i + 10 ] | ( pVideoMemory[ i + 11 ] << 8 ); + pVBInfo->XG21_LVDSCapList[0].LVDSVFP = pVideoMemory[ i + 12 ] | ( pVideoMemory[ i + 13 ] << 8 ); + pVBInfo->XG21_LVDSCapList[0].LVDSHSYNC = pVideoMemory[ i + 14 ] | ( pVideoMemory[ i + 15 ] << 8 ); + pVBInfo->XG21_LVDSCapList[0].LVDSVSYNC = pVideoMemory[ i + 16 ] | ( pVideoMemory[ i + 17 ] << 8 ); + pVBInfo->XG21_LVDSCapList[0].VCLKData1 = pVideoMemory[ i + 18 ] ; + pVBInfo->XG21_LVDSCapList[0].VCLKData2 = pVideoMemory[ i + 19 ] ; + pVBInfo->XG21_LVDSCapList[0].PSC_S1 = pVideoMemory[ i + 20 ] ; + pVBInfo->XG21_LVDSCapList[0].PSC_S2 = pVideoMemory[ i + 21 ] ; + pVBInfo->XG21_LVDSCapList[0].PSC_S3 = pVideoMemory[ i + 22 ] ; + pVBInfo->XG21_LVDSCapList[0].PSC_S4 = pVideoMemory[ i + 23 ] ; + pVBInfo->XG21_LVDSCapList[0].PSC_S5 = pVideoMemory[ i + 24 ] ; + } + } + } +} + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_DDR1x_MRS_XG20 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_DDR1x_MRS_XG20( ULONG P3c4 , PVB_DEVICE_INFO pVBInfo) +{ + + XGINew_SetReg1( P3c4 , 0x18 , 0x01 ) ; + XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; + DelayUS( 60 ) ; + + XGINew_SetReg1( P3c4 , 0x18 , 0x00 ) ; + XGINew_SetReg1( P3c4 , 0x19 , 0x40 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x00 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x80 ) ; + DelayUS( 60 ) ; + XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */ + /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */ + XGINew_SetReg1( P3c4 , 0x19 , 0x01 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x03 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x83 ) ; + DelayUS( 1000 ) ; + XGINew_SetReg1( P3c4 , 0x1B , 0x03 ) ; + DelayUS( 500 ) ; + /* XGINew_SetReg1( P3c4 , 0x18 , 0x31 ) ; */ + XGINew_SetReg1( P3c4 , 0x18 , pVBInfo->SR15[ 2 ][ XGINew_RAMType ] ) ; /* SR18 */ + XGINew_SetReg1( P3c4 , 0x19 , 0x00 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x03 ) ; + XGINew_SetReg1( P3c4 , 0x16 , 0x83 ) ; + XGINew_SetReg1( P3c4 , 0x1B , 0x00 ) ; +} + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetDRAMModeRegister_XG20 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_SetDRAMModeRegister_XG20( PXGI_HW_DEVICE_INFO HwDeviceExtension ) +{ + VB_DEVICE_INFO VBINF; + PVB_DEVICE_INFO pVBInfo = &VBINF; + pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ; + pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; + pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ; + pVBInfo->ISXPDOS = 0 ; + + pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ; + pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ; + pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ; + pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ; + pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ; + pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ; + pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ; + pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ; + pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ; + pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ; + pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ; + pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ; + pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ; + pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ; + pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ; + pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ; + pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ; + + InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo); + + ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ; + + if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 ) + XGINew_DDR1x_MRS_XG20( pVBInfo->P3c4, pVBInfo ) ; + else + XGINew_DDR2_MRS_XG20( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo ) ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ; +} + +void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension ) +{ + VB_DEVICE_INFO VBINF; + PVB_DEVICE_INFO pVBInfo = &VBINF; + pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ; + pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; + pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ; + pVBInfo->ISXPDOS = 0 ; + + pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ; + pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ; + pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ; + pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ; + pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ; + pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ; + pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ; + pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ; + pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ; + pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ; + pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ; + pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ; + pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ; + pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ; + pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ; + pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ; + pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ; + + InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo); + + ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ; + + if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 ) + XGINew_DDR1x_MRS_XG20( pVBInfo->P3c4, pVBInfo ) ; + else + //XGINew_DDR2_MRS_XG27( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo ) ; + XGINew_DDRII_Bootup_XG27( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo) ; + + //XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , pVBInfo->SR15[ 3 ][ XGINew_RAMType ] ) ; /* SR1B */ + +} +/* +void XGINew_SetDRAMModeRegister_XG27( PXGI_HW_DEVICE_INFO HwDeviceExtension ) +{ +#ifndef LINUX_XF86 + UCHAR data ; +#endif + VB_DEVICE_INFO VBINF; + PVB_DEVICE_INFO pVBInfo = &VBINF; + pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ; + pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; + pVBInfo->BaseAddr = HwDeviceExtension->pjIOAddress ; + pVBInfo->ISXPDOS = 0 ; + + pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ; + pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ; + pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ; + pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ; + pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ; + pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ; + pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ; + pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ; + pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ; + pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ; + pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ; + pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ; + pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ; + pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ; + pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ; + pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ; + pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ; + + InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo); + + ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ; + + if ( XGINew_GetXG20DRAMType( HwDeviceExtension, pVBInfo) == 0 ) + XGINew_DDR1x_MRS_XG20( pVBInfo->P3c4, pVBInfo ) ; + else + XGINew_DDR2_MRS_XG27( HwDeviceExtension , pVBInfo->P3c4 , pVBInfo ) ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x1B , 0x03 ) ; +} +*/ +/* -------------------------------------------------------- */ +/* Function : XGINew_ChkSenseStatus */ +/* Input : */ +/* Output : */ +/* Description : */ +/* -------------------------------------------------------- */ +void XGINew_ChkSenseStatus ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempbx=0 , temp , tempcx , CR3CData; + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x32 ) ; + + if ( temp & Monitor1Sense ) + tempbx |= ActiveCRT1 ; + if ( temp & LCDSense ) + tempbx |= ActiveLCD ; + if ( temp & Monitor2Sense ) + tempbx |= ActiveCRT2 ; + if ( temp & TVSense ) + { + tempbx |= ActiveTV ; + if ( temp & AVIDEOSense ) + tempbx |= ( ActiveAVideo << 8 ); + if ( temp & SVIDEOSense ) + tempbx |= ( ActiveSVideo << 8 ); + if ( temp & SCARTSense ) + tempbx |= ( ActiveSCART << 8 ); + if ( temp & HiTVSense ) + tempbx |= ( ActiveHiTV << 8 ); + if ( temp & YPbPrSense ) + tempbx |= ( ActiveYPbPr << 8 ); + } + + tempcx = XGINew_GetReg1( pVBInfo->P3d4 , 0x3d ) ; + tempcx |= ( XGINew_GetReg1( pVBInfo->P3d4 , 0x3e ) << 8 ) ; + + if ( tempbx & tempcx ) + { + CR3CData = XGINew_GetReg1( pVBInfo->P3d4 , 0x3c ) ; + if ( !( CR3CData & DisplayDeviceFromCMOS ) ) + { + tempcx = 0x1FF0 ; + if ( *pVBInfo->pSoftSetting & ModeSoftSetting ) + { + tempbx = 0x1FF0 ; + } + } + } + else + { + tempcx = 0x1FF0 ; + if ( *pVBInfo->pSoftSetting & ModeSoftSetting ) + { + tempbx = 0x1FF0 ; + } + } + + tempbx &= tempcx ; + XGINew_SetReg1( pVBInfo->P3d4, 0x3d , ( tempbx & 0x00FF ) ) ; + XGINew_SetReg1( pVBInfo->P3d4, 0x3e , ( ( tempbx & 0xFF00 ) >> 8 )) ; +} +/* -------------------------------------------------------- */ +/* Function : XGINew_SetModeScratch */ +/* Input : */ +/* Output : */ +/* Description : */ +/* -------------------------------------------------------- */ +void XGINew_SetModeScratch ( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo ) +{ + USHORT temp , tempcl = 0 , tempch = 0 , CR31Data , CR38Data; + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x3d ) ; + temp |= XGINew_GetReg1( pVBInfo->P3d4 , 0x3e ) << 8 ; + temp |= ( XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) & ( DriverMode >> 8) ) << 8 ; + + if ( pVBInfo->IF_DEF_CRT2Monitor == 1) + { + if ( temp & ActiveCRT2 ) + tempcl = SetCRT2ToRAMDAC ; + } + + if ( temp & ActiveLCD ) + { + tempcl |= SetCRT2ToLCD ; + if ( temp & DriverMode ) + { + if ( temp & ActiveTV ) + { + tempch = SetToLCDA | EnableDualEdge ; + temp ^= SetCRT2ToLCD ; + + if ( ( temp >> 8 ) & ActiveAVideo ) + tempcl |= SetCRT2ToAVIDEO ; + if ( ( temp >> 8 ) & ActiveSVideo ) + tempcl |= SetCRT2ToSVIDEO ; + if ( ( temp >> 8 ) & ActiveSCART ) + tempcl |= SetCRT2ToSCART ; + + if ( pVBInfo->IF_DEF_HiVision == 1 ) + { + if ( ( temp >> 8 ) & ActiveHiTV ) + tempcl |= SetCRT2ToHiVisionTV ; + } + + if ( pVBInfo->IF_DEF_YPbPr == 1 ) + { + if ( ( temp >> 8 ) & ActiveYPbPr ) + tempch |= SetYPbPr ; + } + } + } + } + else + { + if ( ( temp >> 8 ) & ActiveAVideo ) + tempcl |= SetCRT2ToAVIDEO ; + if ( ( temp >> 8 ) & ActiveSVideo ) + tempcl |= SetCRT2ToSVIDEO ; + if ( ( temp >> 8 ) & ActiveSCART ) + tempcl |= SetCRT2ToSCART ; + + if ( pVBInfo->IF_DEF_HiVision == 1 ) + { + if ( ( temp >> 8 ) & ActiveHiTV ) + tempcl |= SetCRT2ToHiVisionTV ; + } + + if ( pVBInfo->IF_DEF_YPbPr == 1 ) + { + if ( ( temp >> 8 ) & ActiveYPbPr ) + tempch |= SetYPbPr ; + } + } + + + tempcl |= SetSimuScanMode ; + if ( (!( temp & ActiveCRT1 )) && ( ( temp & ActiveLCD ) || ( temp & ActiveTV ) || ( temp & ActiveCRT2 ) ) ) + tempcl ^= ( SetSimuScanMode | SwitchToCRT2 ) ; + if ( ( temp & ActiveLCD ) && ( temp & ActiveTV ) ) + tempcl ^= ( SetSimuScanMode | SwitchToCRT2 ) ; + XGINew_SetReg1( pVBInfo->P3d4, 0x30 , tempcl ) ; + + CR31Data = XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) ; + CR31Data &= ~( SetNotSimuMode >> 8 ) ; + if ( !( temp & ActiveCRT1 ) ) + CR31Data |= ( SetNotSimuMode >> 8 ) ; + CR31Data &= ~( DisableCRT2Display >> 8 ) ; + if (!( ( temp & ActiveLCD ) || ( temp & ActiveTV ) || ( temp & ActiveCRT2 ) ) ) + CR31Data |= ( DisableCRT2Display >> 8 ) ; + XGINew_SetReg1( pVBInfo->P3d4, 0x31 , CR31Data ) ; + + CR38Data = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ; + CR38Data &= ~SetYPbPr ; + CR38Data |= tempch ; + XGINew_SetReg1( pVBInfo->P3d4, 0x38 , CR38Data ) ; + +} + +/* -------------------------------------------------------- */ +/* Function : XGINew_GetXG21Sense */ +/* Input : */ +/* Output : */ +/* Description : */ +/* -------------------------------------------------------- */ +void XGINew_GetXG21Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) +{ + UCHAR Temp; + PUCHAR volatile pVideoMemory = ( PUCHAR )pVBInfo->ROMAddr ; + + pVBInfo->IF_DEF_LVDS = 0 ; + +#ifdef WIN2000 + pVBInfo->IF_DEF_CH7007 = 0 ; + if ( ( pVideoMemory[ 0x65 ] & 0x02 ) ) /* For XG21 CH7007 */ + { + /* VideoDebugPrint((0, "ReadVBIOSTablData: pVideoMemory[ 0x65 ] =%x\n",pVideoMemory[ 0x65 ])); */ + pVBInfo->IF_DEF_CH7007 = 1 ; /* [Billy] 07/05/03 */ + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0x60 ) ; /* CH7007 on chip */ + } + else +#endif +#if 1 + if (( pVideoMemory[ 0x65 ] & 0x01 ) ) /* For XG21 LVDS */ + { + pVBInfo->IF_DEF_LVDS = 1 ; + XGINew_SetRegOR( pVBInfo->P3d4 , 0x32 , LCDSense ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xC0 ) ; /* LVDS on chip */ + } + else + { +#endif + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x03 , 0x03 ) ; /* Enable GPIOA/B read */ + Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) & 0xC0; + if ( Temp == 0xC0 ) + { /* DVI & DVO GPIOA/B pull high */ + XGINew_SenseLCD( HwDeviceExtension, pVBInfo ) ; + XGINew_SetRegOR( pVBInfo->P3d4 , 0x32 , LCDSense ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x20 , 0x20 ) ; /* Enable read GPIOF */ + Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) & 0x04 ; + if ( !Temp ) + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0x80 ) ; /* TMDS on chip */ + else + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xA0 ) ; /* Only DVO on chip */ + XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ; /* Disable read GPIOF */ + } +#if 1 + } +#endif +} + +/* -------------------------------------------------------- */ +/* Function : XGINew_GetXG27Sense */ +/* Input : */ +/* Output : */ +/* Description : */ +/* -------------------------------------------------------- */ +void XGINew_GetXG27Sense(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) +{ + UCHAR Temp,bCR4A; + + pVBInfo->IF_DEF_LVDS = 0 ; + bCR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x07 , 0x07 ) ; /* Enable GPIOA/B/C read */ + Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) & 0x07; + XGINew_SetReg1( pVBInfo->P3d4, 0x4A , bCR4A ) ; + + if ( Temp <= 0x02 ) + { + pVBInfo->IF_DEF_LVDS = 1 ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xC0 ) ; /* LVDS setting */ + XGINew_SetReg1( pVBInfo->P3d4, 0x30 , 0x21 ) ; + } + else + { + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x38 , ~0xE0 , 0xA0 ) ; /* TMDS/DVO setting */ + } + XGINew_SetRegOR( pVBInfo->P3d4 , 0x32 , LCDSense ) ; + +} + +UCHAR GetXG21FPBits(PVB_DEVICE_INFO pVBInfo) +{ + UCHAR CR38,CR4A,temp; + + CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x10 , 0x10 ) ; /* enable GPIOE read */ + CR38 = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ; + temp =0; + if ( ( CR38 & 0xE0 ) > 0x80 ) + { + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ; + temp &= 0x08; + temp >>= 3; + } + + XGINew_SetReg1( pVBInfo->P3d4, 0x4A , CR4A ) ; + + return temp; +} + +UCHAR GetXG27FPBits(PVB_DEVICE_INFO pVBInfo) +{ + UCHAR CR4A,temp; + + CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x4A , ~0x03 , 0x03 ) ; /* enable GPIOA/B/C read */ + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ; + if ( temp <= 2 ) + { + temp &= 0x03; + } + else + { + temp = ((temp&0x04)>>1) || ((~temp)&0x01); + } + XGINew_SetReg1( pVBInfo->P3d4, 0x4A , CR4A ) ; + + return temp; +} + diff --git a/drivers/staging/xgifb/vb_init.h b/drivers/staging/xgifb/vb_init.h new file mode 100644 index 000000000000..1f39d9c74cdd --- /dev/null +++ b/drivers/staging/xgifb/vb_init.h @@ -0,0 +1,7 @@ +#ifndef _VBINIT_ +#define _VBINIT_ +extern BOOLEAN XGIInitNew( PXGI_HW_DEVICE_INFO HwDeviceExtension ) ; +extern XGI21_LVDSCapStruct XGI21_LCDCapList[13]; + +#endif + diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c new file mode 100644 index 000000000000..bd7f73898644 --- /dev/null +++ b/drivers/staging/xgifb/vb_setmode.c @@ -0,0 +1,10736 @@ +#include "osdef.h" + +#ifdef TC +#include <stdio.h> +#include <string.h> +#include <conio.h> +#include <dos.h> +#endif + + +#ifdef LINUX_XF86 +#include "xf86.h" +#include "xf86PciInfo.h" +#include "xgi.h" +#include "xgi_regs.h" +#endif + +#ifdef LINUX_KERNEL +#include <asm/io.h> +#include <linux/types.h> +#include <linux/version.h> +#include "XGIfb.h" +/*#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#include <video/XGIfb.h> +#else +#include <linux/XGIfb.h> +#endif*/ +#endif + +#ifdef WIN2000 +#include <dderror.h> +#include <devioctl.h> +#include <miniport.h> +#include <ntddvdeo.h> +#include <video.h> + +#include "xgiv.h" +#include "dd_i2c.h" +#include "tools.h" +#endif + +#include "vb_def.h" +#include "vgatypes.h" +#include "vb_struct.h" +#include "vb_util.h" +#include "vb_table.h" + + + +#define IndexMask 0xff +#ifndef XGI_MASK_DUAL_CHIP +#define XGI_MASK_DUAL_CHIP 0x04 /* SR3A */ +#endif + + + +BOOLEAN XGI_IsLCDDualLink(PVB_DEVICE_INFO pVBInfo); +BOOLEAN XGI_SetCRT2Group301(USHORT ModeNo, PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo); +BOOLEAN XGI_BacklightByDrv(PVB_DEVICE_INFO pVBInfo); + +BOOLEAN XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo); +BOOLEAN XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo); +BOOLEAN XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo); +BOOLEAN XGI_AjustCRT2Rate(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,USHORT *i, PVB_DEVICE_INFO pVBInfo); +BOOLEAN XGI_SearchModeID( USHORT ModeNo,USHORT *ModeIdIndex, PVB_DEVICE_INFO pVBInfo); +BOOLEAN XGI_GetLCDInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo); +BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo ) ; +BOOLEAN XGI_BridgeIsOn(PVB_DEVICE_INFO pVBInfo); +UCHAR XGI_GetModePtr( USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo); +USHORT XGI_GetOffset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo); +USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo ); +USHORT XGI_GetResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo); +USHORT XGI_GetColorDepth(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo); +USHORT XGI_GetVGAHT2(PVB_DEVICE_INFO pVBInfo); +USHORT XGI_GetVCLK2Ptr(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo); +void XGI_VBLongWait(PVB_DEVICE_INFO pVBInfo); +void XGI_SaveCRT2Info(USHORT ModeNo, PVB_DEVICE_INFO pVBInfo); +void XGI_GetCRT2Data(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_GetCRT2ResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_PreSetGroup1(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_SetGroup1(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_SetLockRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_SetLCDRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_SetGroup2(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo); +void XGI_SetGroup3(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_SetGroup4(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo); +void XGI_SetGroup5(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo); +void* XGI_GetLcdPtr(USHORT BX, USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo); +void* XGI_GetTVPtr(USHORT BX, USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo); +void XGI_EnableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo); +void XGI_DisableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo); +void XGI_SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo); +void XGI_SetPanelPower(USHORT tempah,USHORT tempbl, PVB_DEVICE_INFO pVBInfo); +void XGI_EnablePWD( PVB_DEVICE_INFO pVBInfo); +void XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo); +void XGI_AutoThreshold( PVB_DEVICE_INFO pVBInfo); +void XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo); + +void XGI_DisplayOn(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo); +void XGI_DisplayOff( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo ); +void XGI_SetCRT1Group(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo); +void XGI_SetXG21CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo); +void XGI_SetXG27CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo); +void XGI_UpdateXG21CRTC(USHORT ModeNo, PVB_DEVICE_INFO pVBInfo, USHORT RefreshRateTableIndex); +void XGI_WaitDisply(PVB_DEVICE_INFO pVBInfo); +void XGI_SenseCRT1(PVB_DEVICE_INFO pVBInfo); +void XGI_SetSeqRegs(USHORT ModeNo,USHORT StandTableIndex,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo); +void XGI_SetMiscRegs(USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_SetCRTCRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_SetATTRegs(USHORT ModeNo,USHORT StandTableIndex,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo ); +void XGI_SetGRCRegs(USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo); + +void XGI_SetSync(USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo); +void XGI_SetCRT1CRTC(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo,PXGI_HW_DEVICE_INFO HwDeviceExtension); +void XGI_SetCRT1Timing_H(PVB_DEVICE_INFO pVBInfo,PXGI_HW_DEVICE_INFO HwDeviceExtension); +void XGI_SetCRT1Timing_V(USHORT ModeIdIndex,USHORT ModeNo,PVB_DEVICE_INFO pVBInfo); +void XGI_SetCRT1DE(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo); +void XGI_SetCRT1VCLK(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_SetCRT1FIFO(USHORT ModeNo,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo); +void XGI_SetCRT1ModeRegs(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo); +void XGI_SetVCLKState(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo); + +void XGI_LoadDAC(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo); +void XGI_WriteDAC(USHORT dl, USHORT ah, USHORT al, USHORT dh, PVB_DEVICE_INFO pVBInfo); +/*void XGI_ClearBuffer(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,PVB_DEVICE_INFO pVBInfo);*/ +void XGI_SetLCDAGroup(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo); +void XGI_GetLVDSResInfo( USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo); +void XGI_GetLVDSData(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo); +void XGI_ModCRT1Regs(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo); +void XGI_SetLVDSRegs(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo); +void XGI_UpdateModeInfo(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo); +void XGI_GetVGAType(PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo); +void XGI_GetVBType(PVB_DEVICE_INFO pVBInfo); +void XGI_GetVBInfo(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo); +void XGI_GetTVInfo(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo); +void XGI_SetCRT2ECLK( USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo); +void InitTo330Pointer(UCHAR,PVB_DEVICE_INFO pVBInfo); +void XGI_GetLCDSync(USHORT* HSyncWidth, USHORT* VSyncWidth, PVB_DEVICE_INFO pVBInfo); +void XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo); +void XGI_EnableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo); +void XGI_SetCRT2VCLK(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_OEM310Setting(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_SetDelayComp(PVB_DEVICE_INFO pVBInfo); +void XGI_SetLCDCap(PVB_DEVICE_INFO pVBInfo); +void XGI_SetLCDCap_A(USHORT tempcx,PVB_DEVICE_INFO pVBInfo); +void XGI_SetLCDCap_B(USHORT tempcx,PVB_DEVICE_INFO pVBInfo); +void SetSpectrum(PVB_DEVICE_INFO pVBInfo); +void XGI_SetAntiFlicker(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_SetEdgeEnhance(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_SetPhaseIncr(PVB_DEVICE_INFO pVBInfo); +void XGI_SetYFilter(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_GetTVPtrIndex2(USHORT* tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo); +USHORT XGI_GetTVPtrIndex( PVB_DEVICE_INFO pVBInfo ); +void XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo ); +void XGI_CloseCRTC(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo); +void XGI_OpenCRTC(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo); +void XGI_GetRAMDAC2DATA(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo); +void XGI_LockCRT2(PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO pVBInfo); +void XGINew_EnableCRT2(PVB_DEVICE_INFO pVBInfo); +void XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo); +void XGI_LongWait(PVB_DEVICE_INFO pVBInfo); +void XGI_SetCRT1Offset( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo ); +void XGI_GetLCDVCLKPtr(UCHAR* di_0,UCHAR *di_1, PVB_DEVICE_INFO pVBInfo); +UCHAR XGI_GetVCLKPtr(USHORT RefreshRateTableIndex,USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo); +void XGI_GetVCLKLen(UCHAR tempal,UCHAR* di_0,UCHAR* di_1, PVB_DEVICE_INFO pVBInfo); +USHORT XGI_GetLCDCapPtr(PVB_DEVICE_INFO pVBInfo); +USHORT XGI_GetLCDCapPtr1(PVB_DEVICE_INFO pVBInfo); +XGI301C_Tap4TimingStruct* XGI_GetTap4Ptr(USHORT tempcx, PVB_DEVICE_INFO pVBInfo); +void XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo); +void XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo); +UCHAR XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo); +UCHAR XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo); +void XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo); +void XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo); +void XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo); +BOOLEAN XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ); +void XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ); +void XGI_SetXG27LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ); +UCHAR XGI_SetDefaultVCLK( PVB_DEVICE_INFO pVBInfo ); + +extern void ReadVBIOSTablData( UCHAR ChipType , PVB_DEVICE_INFO pVBInfo); +#ifdef WIN2000 +/* [Billy] 2007/05/17 For CH7007 */ +extern UCHAR CH7007TVReg_UNTSC[][8],CH7007TVReg_ONTSC[][8],CH7007TVReg_UPAL[][8],CH7007TVReg_OPAL[][8]; +extern UCHAR CH7007TVCRT1UNTSC_H[][10],CH7007TVCRT1ONTSC_H[][10],CH7007TVCRT1UPAL_H[][10],CH7007TVCRT1OPAL_H[][10] ; +extern UCHAR CH7007TVCRT1UNTSC_V[][10],CH7007TVCRT1ONTSC_V[][10],CH7007TVCRT1UPAL_V[][10],CH7007TVCRT1OPAL_V[][10] ; +extern UCHAR XGI7007_CHTVVCLKUNTSC[],XGI7007_CHTVVCLKONTSC[],XGI7007_CHTVVCLKUPAL[],XGI7007_CHTVVCLKOPAL[]; + +extern BOOLEAN XGI_XG21CheckCH7007TVMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) ; +extern void SetCH7007Regs(PXGI_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) ; +extern VP_STATUS TurnOnCH7007(PHW_DEVICE_EXTENSION pHWDE) ; +extern VP_STATUS TurnOffCH7007(PHW_DEVICE_EXTENSION pHWDE) ; +extern BOOLEAN IsCH7007TVMode(PVB_DEVICE_INFO pVBInfo) ; +#endif + +/* USHORT XGINew_flag_clearbuffer; 0: no clear frame buffer 1:clear frame buffer */ + + + + + +USHORT XGINew_MDA_DAC[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F}; + +USHORT XGINew_CGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, + 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, + 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, + 0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F}; + +USHORT XGINew_EGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15, + 0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35, + 0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D, + 0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D, + 0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17, + 0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37, + 0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F, + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F}; + +USHORT XGINew_VGA_DAC[]={0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15, + 0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F, + 0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18, + 0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F, + + 0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F, + 0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00, + 0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18, + 0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04, + 0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10, + 0x0B,0x0C,0x0D,0x0F,0x10}; + + +/* --------------------------------------------------------------------- */ +/* Function : InitTo330Pointer */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void InitTo330Pointer( UCHAR ChipType ,PVB_DEVICE_INFO pVBInfo) +{ + pVBInfo->SModeIDTable = (XGI_StStruct *) XGI330_SModeIDTable ; + pVBInfo->StandTable = (XGI_StandTableStruct *) XGI330_StandTable ; + pVBInfo->EModeIDTable = (XGI_ExtStruct *) XGI330_EModeIDTable ; + pVBInfo->RefIndex = (XGI_Ext2Struct *) XGI330_RefIndex ; + pVBInfo->XGINEWUB_CRT1Table = (XGI_CRT1TableStruct *) XGI_CRT1Table ; + + /* add for new UNIVGABIOS */ + /* XGINew_UBLCDDataTable = (XGI_LCDDataTablStruct *) XGI_LCDDataTable ; */ + /* XGINew_UBTVDataTable = (XGI_TVDataTablStruct *) XGI_TVDataTable ; */ + + + if ( ChipType >= XG40 ) + { + pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI340New_MCLKData ; + pVBInfo->ECLKData = (XGI_ECLKDataStruct *) XGI340_ECLKData ; + } + else + { + pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI330New_MCLKData ; + pVBInfo->ECLKData = (XGI_ECLKDataStruct *) XGI330_ECLKData ; + } + + pVBInfo->VCLKData = (XGI_VCLKDataStruct *) XGI_VCLKData ; + pVBInfo->VBVCLKData = (XGI_VBVCLKDataStruct *) XGI_VBVCLKData ; + pVBInfo->ScreenOffset = XGI330_ScreenOffset ; + pVBInfo->StResInfo = (XGI_StResInfoStruct *) XGI330_StResInfo ; + pVBInfo->ModeResInfo = (XGI_ModeResInfoStruct *) XGI330_ModeResInfo ; + + pVBInfo->pOutputSelect = &XGI330_OutputSelect ; + pVBInfo->pSoftSetting = &XGI330_SoftSetting ; + pVBInfo->pSR07 = &XGI330_SR07 ; + pVBInfo->LCDResInfo = 0 ; + pVBInfo->LCDTypeInfo = 0 ; + pVBInfo->LCDInfo = 0 ; + pVBInfo->VBInfo = 0 ; + pVBInfo->TVInfo = 0; + + + pVBInfo->SR15 = XGI340_SR13 ; + pVBInfo->CR40 = XGI340_cr41 ; + pVBInfo->SR25 = XGI330_sr25 ; + pVBInfo->pSR31 = &XGI330_sr31 ; + pVBInfo->pSR32 = &XGI330_sr32 ; + pVBInfo->CR6B = XGI340_CR6B ; + pVBInfo->CR6E = XGI340_CR6E ; + pVBInfo->CR6F = XGI340_CR6F ; + pVBInfo->CR89 = XGI340_CR89 ; + pVBInfo->AGPReg = XGI340_AGPReg ; + pVBInfo->SR16 = XGI340_SR16 ; + pVBInfo->pCRCF = &XG40_CRCF ; + pVBInfo->pXGINew_DRAMTypeDefinition = &XG40_DRAMTypeDefinition ; + + + pVBInfo->CR49 = XGI330_CR49 ; + pVBInfo->pSR1F = &XGI330_SR1F ; + pVBInfo->pSR21 = &XGI330_SR21 ; + pVBInfo->pSR22 = &XGI330_SR22 ; + pVBInfo->pSR23 = &XGI330_SR23 ; + pVBInfo->pSR24 = &XGI330_SR24 ; + pVBInfo->pSR33 = &XGI330_SR33 ; + + + + pVBInfo->pCRT2Data_1_2 = &XGI330_CRT2Data_1_2 ; + pVBInfo->pCRT2Data_4_D = &XGI330_CRT2Data_4_D ; + pVBInfo->pCRT2Data_4_E = &XGI330_CRT2Data_4_E ; + pVBInfo->pCRT2Data_4_10 = &XGI330_CRT2Data_4_10 ; + pVBInfo->pRGBSenseData = &XGI330_RGBSenseData ; + pVBInfo->pVideoSenseData = &XGI330_VideoSenseData ; + pVBInfo->pYCSenseData = &XGI330_YCSenseData ; + pVBInfo->pRGBSenseData2 = &XGI330_RGBSenseData2 ; + pVBInfo->pVideoSenseData2 = &XGI330_VideoSenseData2 ; + pVBInfo->pYCSenseData2 = &XGI330_YCSenseData2 ; + + pVBInfo->NTSCTiming = XGI330_NTSCTiming ; + pVBInfo->PALTiming = XGI330_PALTiming ; + pVBInfo->HiTVExtTiming = XGI330_HiTVExtTiming ; + pVBInfo->HiTVSt1Timing = XGI330_HiTVSt1Timing ; + pVBInfo->HiTVSt2Timing = XGI330_HiTVSt2Timing ; + pVBInfo->HiTVTextTiming = XGI330_HiTVTextTiming ; + pVBInfo->YPbPr750pTiming = XGI330_YPbPr750pTiming ; + pVBInfo->YPbPr525pTiming = XGI330_YPbPr525pTiming ; + pVBInfo->YPbPr525iTiming = XGI330_YPbPr525iTiming ; + pVBInfo->HiTVGroup3Data = XGI330_HiTVGroup3Data ; + pVBInfo->HiTVGroup3Simu = XGI330_HiTVGroup3Simu ; + pVBInfo->HiTVGroup3Text = XGI330_HiTVGroup3Text ; + pVBInfo->Ren525pGroup3 = XGI330_Ren525pGroup3 ; + pVBInfo->Ren750pGroup3 = XGI330_Ren750pGroup3 ; + + + pVBInfo->TimingH = (XGI_TimingHStruct *) XGI_TimingH ; + pVBInfo->TimingV = (XGI_TimingVStruct *) XGI_TimingV ; + pVBInfo->UpdateCRT1 = (XGI_XG21CRT1Struct *) XGI_UpdateCRT1Table ; + + pVBInfo->CHTVVCLKUNTSC = XGI330_CHTVVCLKUNTSC ; + pVBInfo->CHTVVCLKONTSC = XGI330_CHTVVCLKONTSC ; + pVBInfo->CHTVVCLKUPAL = XGI330_CHTVVCLKUPAL ; + pVBInfo->CHTVVCLKOPAL = XGI330_CHTVVCLKOPAL ; + + /* 310 customization related */ + if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) ) + pVBInfo->LCDCapList = XGI_LCDDLCapList ; + else + pVBInfo->LCDCapList = XGI_LCDCapList ; + + if ( ( ChipType == XG21 ) || ( ChipType == XG27 ) ) + pVBInfo->XG21_LVDSCapList = XGI21_LCDCapList ; + + pVBInfo->XGI_TVDelayList = XGI301TVDelayList ; + pVBInfo->XGI_TVDelayList2 = XGI301TVDelayList2 ; + + + pVBInfo->pXGINew_I2CDefinition = &XG40_I2CDefinition ; + + if ( ChipType >= XG20 ) + pVBInfo->pXGINew_CR97 = &XG20_CR97 ; + + if ( ChipType == XG27 ) + { + pVBInfo->MCLKData = (XGI_MCLKDataStruct *) XGI27New_MCLKData ; + pVBInfo->CR40 = XGI27_cr41 ; + pVBInfo->pXGINew_CR97 = &XG27_CR97 ; + pVBInfo->pSR36 = &XG27_SR36 ; + pVBInfo->pCR8F = &XG27_CR8F ; + pVBInfo->pCRD0 = XG27_CRD0 ; + pVBInfo->pCRDE = XG27_CRDE ; + pVBInfo->pSR40 = &XG27_SR40 ; + pVBInfo->pSR41 = &XG27_SR41 ; + + } + + if ( ChipType >= XG20 ) + { + pVBInfo->pDVOSetting = &XG21_DVOSetting ; + pVBInfo->pCR2E = &XG21_CR2E ; + pVBInfo->pCR2F = &XG21_CR2F ; + pVBInfo->pCR46 = &XG21_CR46 ; + pVBInfo->pCR47 = &XG21_CR47 ; + } + +} + + + + + + +/* --------------------------------------------------------------------- */ +/* Function : XGISetModeNew */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo ) +{ + USHORT ModeIdIndex ; + /* PUCHAR pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress ; */ + VB_DEVICE_INFO VBINF; + PVB_DEVICE_INFO pVBInfo = &VBINF; + pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase ; + pVBInfo->BaseAddr = (ULONG)HwDeviceExtension->pjIOAddress ; + pVBInfo->IF_DEF_LVDS = 0 ; + pVBInfo->IF_DEF_CH7005 = 0 ; + pVBInfo->IF_DEF_LCDA = 1 ; + pVBInfo->IF_DEF_CH7017 = 0 ; + pVBInfo->IF_DEF_CH7007 = 0 ; /* [Billy] 2007/05/14 */ + pVBInfo->IF_DEF_VideoCapture = 0 ; + pVBInfo->IF_DEF_ScaleLCD = 0 ; + pVBInfo->IF_DEF_OEMUtil = 0 ; + pVBInfo->IF_DEF_PWD = 0 ; + + + if ( HwDeviceExtension->jChipType >= XG20 ) /* kuku 2004/06/25 */ + { + pVBInfo->IF_DEF_YPbPr = 0 ; + pVBInfo->IF_DEF_HiVision = 0 ; + pVBInfo->IF_DEF_CRT2Monitor = 0 ; + pVBInfo->VBType = 0 ; /*set VBType default 0*/ + } + else if ( HwDeviceExtension->jChipType >= XG40 ) + { + pVBInfo->IF_DEF_YPbPr = 1 ; + pVBInfo->IF_DEF_HiVision = 1 ; + pVBInfo->IF_DEF_CRT2Monitor = 1 ; + } + else + { + pVBInfo->IF_DEF_YPbPr = 1 ; + pVBInfo->IF_DEF_HiVision = 1 ; + pVBInfo->IF_DEF_CRT2Monitor = 0 ; + } + + pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14 ; + pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24 ; + pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10 ; + pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e ; + pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12 ; + pVBInfo->P3cc = pVBInfo->BaseAddr + 0x1C ; + pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a ; + pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16 ; + pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17 ; + pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18 ; + pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19 ; + pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A ; + pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00 ; + pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04 ; + pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10 ; + pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12 ; + pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 ; + pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2 ; + + if ( HwDeviceExtension->jChipType == XG21 ) /* for x86 Linux, XG21 LVDS */ + { + if ( ( XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) & 0xE0 ) == 0xC0 ) + { + pVBInfo->IF_DEF_LVDS = 1 ; + } + } + if ( HwDeviceExtension->jChipType == XG27 ) + { + if ( ( XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) & 0xE0 ) == 0xC0 ) + { + if ( XGINew_GetReg1( pVBInfo->P3d4 , 0x30 ) & 0x20 ) + { + pVBInfo->IF_DEF_LVDS = 1 ; + } + } + } + + if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */ + XGI_GetVBType( pVBInfo ) ; + + InitTo330Pointer( HwDeviceExtension->jChipType, pVBInfo ) ; +#ifdef WIN2000 + ReadVBIOSTablData( HwDeviceExtension->jChipType , pVBInfo) ; +#endif + if ( ModeNo & 0x80 ) + { + ModeNo = ModeNo & 0x7F ; +/* XGINew_flag_clearbuffer = 0 ; */ + } +/* else + { + XGINew_flag_clearbuffer = 1 ; + } +*/ + XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ; + + if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 1.Openkey */ + XGI_UnLockCRT2( HwDeviceExtension , pVBInfo ) ; + + XGI_SearchModeID( ModeNo , &ModeIdIndex, pVBInfo ) ; + + XGI_GetVGAType(HwDeviceExtension, pVBInfo) ; + + if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */ + { + XGI_GetVBInfo(ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ; + XGI_GetTVInfo(ModeNo , ModeIdIndex, pVBInfo ) ; + XGI_GetLCDInfo(ModeNo , ModeIdIndex, pVBInfo ) ; + XGI_DisableBridge( HwDeviceExtension,pVBInfo ) ; +/* XGI_OpenCRTC( HwDeviceExtension, pVBInfo ) ; */ + + if ( pVBInfo->VBInfo & ( SetSimuScanMode | SetCRT2ToLCDA ) ) + { + XGI_SetCRT1Group(HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ; + + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + { + XGI_SetLCDAGroup(ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ; + } + } + else + { + if ( !( pVBInfo->VBInfo & SwitchToCRT2) ) + { + XGI_SetCRT1Group( HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ; + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + { + XGI_SetLCDAGroup( ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ; + } + } + } + + if ( pVBInfo->VBInfo & ( SetSimuScanMode | SwitchToCRT2 ) ) + { + switch( HwDeviceExtension->ujVBChipID ) + { + case VB_CHIP_301: + XGI_SetCRT2Group301( ModeNo , HwDeviceExtension, pVBInfo ) ; /*add for CRT2 */ + break ; + + case VB_CHIP_302: + XGI_SetCRT2Group301(ModeNo , HwDeviceExtension, pVBInfo ) ; /*add for CRT2 */ + break ; + + default: + break ; + } + } + + XGI_SetCRT2ModeRegs( ModeNo, HwDeviceExtension,pVBInfo ) ; + XGI_OEM310Setting( ModeNo, ModeIdIndex,pVBInfo ) ; /*0212*/ + XGI_CloseCRTC( HwDeviceExtension, pVBInfo ) ; + XGI_EnableBridge( HwDeviceExtension ,pVBInfo) ; + } /* !XG20 */ + else + { +#ifdef WIN2000 + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + + VideoDebugPrint((0, "XGISetModeNew: pVBIfo->IF_DEF_CH7007==1\n")); + pVBInfo->VBType = VB_CH7007 ; + XGI_GetVBInfo(ModeNo , ModeIdIndex , HwDeviceExtension, pVBInfo ) ; + XGI_GetTVInfo(ModeNo , ModeIdIndex, pVBInfo ) ; + XGI_GetLCDInfo(ModeNo , ModeIdIndex, pVBInfo ) ; + if( !(XGI_XG21CheckCH7007TVMode(ModeNo, ModeIdIndex, pVBInfo )) ) + { + return FALSE; + } + } +#endif + + + if ( pVBInfo->IF_DEF_LVDS == 1 ) + { + if ( !XGI_XG21CheckLVDSMode(ModeNo , ModeIdIndex, pVBInfo) ) + { + return FALSE; + } + } + + if ( ModeNo <= 0x13 ) + { + pVBInfo->ModeType = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag & ModeInfoFlag; + } + else + { + pVBInfo->ModeType = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag & ModeInfoFlag; + } + + pVBInfo->SetFlag = 0 ; + if ( pVBInfo->IF_DEF_CH7007 != 1 ) + { + pVBInfo->VBInfo = DisableCRT2Display ; + } + + + XGI_DisplayOff(HwDeviceExtension, pVBInfo) ; + + XGI_SetCRT1Group(HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ; + + XGI_DisplayOn( HwDeviceExtension, pVBInfo ) ; + /* + if( HwDeviceExtension->jChipType == XG21 ) + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0x80 , 0x80 ) ; + */ + } + + +/* + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + } + pVBInfo->ModeType = modeflag&ModeInfoFlag ; + pVBInfo->SetFlag = 0x00 ; + pVBInfo->VBInfo = DisableCRT2Display ; + temp = XGINew_CheckMemorySize( HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ; + + if ( temp == 0 ) + return( 0 ) ; + + XGI_DisplayOff( HwDeviceExtension, pVBInfo) ; + XGI_SetCRT1Group( HwDeviceExtension , ModeNo , ModeIdIndex, pVBInfo ) ; + XGI_DisplayOn( HwDeviceExtension, pVBInfo) ; +*/ + + XGI_UpdateModeInfo( HwDeviceExtension, pVBInfo ) ; + + if ( HwDeviceExtension->jChipType < XG20 ) /* kuku 2004/06/25 */ +{ + XGI_LockCRT2( HwDeviceExtension, pVBInfo ) ; +} + + return( TRUE ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT1Group */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT1Group( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT StandTableIndex , + RefreshRateTableIndex , + b3CC , + temp ; + + USHORT XGINew_P3cc = pVBInfo->P3cc; + + /* XGINew_CRT1Mode = ModeNo ; // SaveModeID */ + StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ; + /* XGI_SetBIOSData(ModeNo , ModeIdIndex ) ; */ + /* XGI_ClearBankRegs( ModeNo , ModeIdIndex ) ; */ + XGI_SetSeqRegs( ModeNo , StandTableIndex , ModeIdIndex, pVBInfo ) ; + XGI_SetMiscRegs( StandTableIndex, pVBInfo ) ; + XGI_SetCRTCRegs( HwDeviceExtension , StandTableIndex, pVBInfo) ; + XGI_SetATTRegs( ModeNo , StandTableIndex , ModeIdIndex, pVBInfo ) ; + XGI_SetGRCRegs( StandTableIndex, pVBInfo ) ; + XGI_ClearExt1Regs(pVBInfo) ; + +/* if ( pVBInfo->IF_DEF_ExpLink ) */ + if ( HwDeviceExtension->jChipType == XG27 ) + { + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + XGI_SetDefaultVCLK( pVBInfo ) ; + } + } + + temp = ~ProgrammingCRT2 ; + pVBInfo->SetFlag &= temp ; + pVBInfo->SelectCRT2Rate = 0 ; + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + if ( pVBInfo->VBInfo & ( SetSimuScanMode | SetCRT2ToLCDA | SetInSlaveMode ) ) + { + pVBInfo->SetFlag |= ProgrammingCRT2 ; + } + } + + RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, pVBInfo ) ; + if ( RefreshRateTableIndex != 0xFFFF ) + { + XGI_SetSync( RefreshRateTableIndex, pVBInfo ) ; + XGI_SetCRT1CRTC( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo, HwDeviceExtension ) ; + XGI_SetCRT1DE( HwDeviceExtension , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + XGI_SetCRT1Offset( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ; + XGI_SetCRT1VCLK( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ; + } + + if ( ( HwDeviceExtension->jChipType >= XG20 )&& + ( HwDeviceExtension->jChipType < XG27 ) ) /* fix H/W DCLK/2 bug */ + { + if ( ( ModeNo == 0x00 ) | (ModeNo == 0x01) ) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x4E) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE9) ; + b3CC =(UCHAR) XGINew_GetReg2(XGINew_P3cc) ; + XGINew_SetReg3(XGINew_P3cc , (b3CC |= 0x0C) ) ; + } + else if ( ( ModeNo == 0x04) | ( ModeNo == 0x05) | ( ModeNo == 0x0D) ) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x1B) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE3) ; + b3CC = (UCHAR)XGINew_GetReg2(XGINew_P3cc) ; + XGINew_SetReg3(XGINew_P3cc , (b3CC |= 0x0C) ) ; + } + } + + if ( HwDeviceExtension->jChipType >= XG21 ) + { + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ; + if ( temp & 0xA0 ) + { + + /*XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x20 ) ;*/ /* Enable write GPIOF */ + /*XGINew_SetRegAND( pVBInfo->P3d4 , 0x48 , ~0x20 ) ;*/ /* P. DWN */ + /* XG21 CRT1 Timing */ + if ( HwDeviceExtension->jChipType == XG27 ) + XGI_SetXG27CRTC( ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo ); + else + XGI_SetXG21CRTC( ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo ); + + XGI_UpdateXG21CRTC( ModeNo , pVBInfo , RefreshRateTableIndex) ; + + if ( HwDeviceExtension->jChipType == XG27 ) + XGI_SetXG27LCD( pVBInfo , RefreshRateTableIndex , ModeNo ); + else + XGI_SetXG21LCD( pVBInfo , RefreshRateTableIndex , ModeNo ); + + if ( pVBInfo->IF_DEF_LVDS == 1 ) + { + if ( HwDeviceExtension->jChipType == XG27 ) + XGI_SetXG27LVDSPara(ModeNo,ModeIdIndex, pVBInfo ); + else + XGI_SetXG21LVDSPara(ModeNo,ModeIdIndex, pVBInfo ); + } + /*XGINew_SetRegOR( pVBInfo->P3d4 , 0x48 , 0x20 ) ;*/ /* P. ON */ + } + } + + pVBInfo->SetFlag &= ( ~ProgrammingCRT2 ) ; + XGI_SetCRT1FIFO( ModeNo , HwDeviceExtension, pVBInfo ) ; + XGI_SetCRT1ModeRegs( HwDeviceExtension , ModeNo , ModeIdIndex , RefreshRateTableIndex , pVBInfo) ; + + + /* XGI_LoadCharacter(); //dif ifdef TVFont */ + + XGI_LoadDAC( ModeNo , ModeIdIndex, pVBInfo ) ; + /* XGI_ClearBuffer( HwDeviceExtension , ModeNo, pVBInfo ) ; */ +#ifdef WIN2000 + if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 2007/05/14 */ + { + VideoDebugPrint((0, "XGI_SetCRT1Group: VBInfo->IF_DEF_CH7007==1\n")); + SetCH7007Regs(HwDeviceExtension, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo ) ; /* 07/05/28 */ + } +#endif +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetModePtr */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +UCHAR XGI_GetModePtr( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR index ; + + if ( ModeNo <= 0x13 ) + index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_StTableIndex ; + else + { + if ( pVBInfo->ModeType <= 0x02 ) + index = 0x1B ; /* 02 -> ModeEGA */ + else + index = 0x0F ; + } + return( index ) ; /* Get pVBInfo->StandTable index */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetBIOSData */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +/*UCHAR XGI_SetBIOSData( USHORT ModeNo , USHORT ModeIdIndex ) +{ + return( 0 ) ; +} +*/ + +/* --------------------------------------------------------------------- */ +/* Function : XGI_ClearBankRegs */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +/*UCHAR XGI_ClearBankRegs( USHORT ModeNo , USHORT ModeIdIndex ) +{ + return( 0 ) ; +} +*/ + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetSeqRegs */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetSeqRegs( USHORT ModeNo , USHORT StandTableIndex , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR tempah , + SRdata ; + + USHORT i , + modeflag ; + + if ( ModeNo <= 0x13 ) + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + else + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x00 , 0x03 ) ; /* Set SR0 */ + tempah=pVBInfo->StandTable[ StandTableIndex ].SR[ 0 ] ; + + i = SetCRT2ToLCDA ; + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + { + tempah |= 0x01 ; + } + else + { + if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToLCD ) ) + { + if ( pVBInfo->VBInfo & SetInSlaveMode ) + tempah |= 0x01 ; + } + } + + tempah |= 0x20 ; /* screen off */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , tempah ) ; /* Set SR1 */ + + for( i = 02 ; i <= 04 ; i++ ) + { + SRdata = pVBInfo->StandTable[ StandTableIndex ].SR[ i - 1 ] ; /* Get SR2,3,4 from file */ + XGINew_SetReg1( pVBInfo->P3c4 , i , SRdata ) ; /* Set SR2 3 4 */ + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetMiscRegs */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetMiscRegs( USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR Miscdata ; + + Miscdata = pVBInfo->StandTable[ StandTableIndex ].MISC ; /* Get Misc from file */ +/* + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + { + Miscdata |= 0x0C ; + } + } +*/ + + XGINew_SetReg3( pVBInfo->P3c2 , Miscdata ) ; /* Set Misc(3c2) */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRTCRegs */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRTCRegs( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR CRTCdata ; + USHORT i ; + + CRTCdata = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ; + CRTCdata &= 0x7f ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , CRTCdata ) ; /* Unlock CRTC */ + + for( i = 0 ; i <= 0x18 ; i++ ) + { + CRTCdata = pVBInfo->StandTable[ StandTableIndex ].CRTC[ i ] ; /* Get CRTC from file */ + XGINew_SetReg1( pVBInfo->P3d4 , i , CRTCdata ) ; /* Set CRTC( 3d4 ) */ + } +/* + if ( ( HwDeviceExtension->jChipType == XGI_630 )&& ( HwDeviceExtension->jChipRevision == 0x30 ) ) + { + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToTV ) ) + { + XGINew_SetReg1( pVBInfo->P3d4 , 0x18 , 0xFE ) ; + } + } + } +*/ +} + + +/* --------------------------------------------------------------------- */ +/* Function : */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetATTRegs( USHORT ModeNo , USHORT StandTableIndex , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR ARdata ; + USHORT i , + modeflag ; + + if ( ModeNo <= 0x13 ) + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + else + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + + for( i = 0 ; i <= 0x13 ; i++ ) + { + ARdata = pVBInfo->StandTable[ StandTableIndex ].ATTR[ i ] ; + if ( modeflag & Charx8Dot ) /* ifndef Dot9 */ + { + if ( i == 0x13 ) + { + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + ARdata = 0 ; + else + { + if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToLCD ) ) + { + if ( pVBInfo->VBInfo & SetInSlaveMode ) + ARdata = 0 ; + } + } + } + } + + XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */ + XGINew_SetReg3( pVBInfo->P3c0 , i ) ; /* set index */ + XGINew_SetReg3( pVBInfo->P3c0 , ARdata ) ; /* set data */ + } + + XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */ + XGINew_SetReg3( pVBInfo->P3c0 , 0x14 ) ; /* set index */ + XGINew_SetReg3( pVBInfo->P3c0 , 0x00 ) ; /* set data */ + XGINew_GetReg2( pVBInfo->P3da ) ; /* Enable Attribute */ + XGINew_SetReg3( pVBInfo->P3c0 , 0x20 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetGRCRegs */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetGRCRegs( USHORT StandTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR GRdata ; + USHORT i ; + + for( i = 0 ; i <= 0x08 ; i++ ) + { + GRdata = pVBInfo->StandTable[ StandTableIndex ].GRC[ i ] ; /* Get GR from file */ + XGINew_SetReg1( pVBInfo->P3ce , i , GRdata ) ; /* Set GR(3ce) */ + } + + if ( pVBInfo->ModeType > ModeVGA ) + { + GRdata = ( UCHAR )XGINew_GetReg1( pVBInfo->P3ce , 0x05 ) ; + GRdata &= 0xBF ; /* 256 color disable */ + XGINew_SetReg1( pVBInfo->P3ce , 0x05 , GRdata ) ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_ClearExt1Regs */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_ClearExt1Regs(PVB_DEVICE_INFO pVBInfo) +{ + USHORT i ; + + for( i = 0x0A ; i <= 0x0E ; i++ ) + XGINew_SetReg1( pVBInfo->P3c4 , i , 0x00 ) ; /* Clear SR0A-SR0E */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetDefaultVCLK */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +UCHAR XGI_SetDefaultVCLK( PVB_DEVICE_INFO pVBInfo ) +{ + + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , 0x20 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ 0 ].SR2B ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ 0 ].SR2C ) ; + + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , 0x10 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ 1 ].SR2B ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ 1 ].SR2C ) ; + + XGINew_SetRegAND( pVBInfo->P3c4 , 0x31 , ~0x30 ) ; + return( 0 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetRatePtrCRT2 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) +{ + SHORT LCDRefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 } , + LCDARefreshIndex[] = { 0x00 , 0x00 , 0x03 , 0x01 , 0x01 , 0x01 , 0x01 } ; + + USHORT RefreshRateTableIndex , i , + modeflag , index , temp ; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + } + + if ( pVBInfo->IF_DEF_CH7005 == 1 ) + { + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + if ( modeflag & HalfDCLK ) + return( 0 ) ; + } + } + + if ( ModeNo < 0x14 ) + return( 0xFFFF ) ; + + index = XGINew_GetReg1( pVBInfo->P3d4 , 0x33 ) ; + index = index >> pVBInfo->SelectCRT2Rate ; + index &= 0x0F ; + + if ( pVBInfo->LCDInfo & LCDNonExpanding ) + index = 0 ; + + if ( index > 0 ) + index-- ; + + if ( pVBInfo->SetFlag & ProgrammingCRT2 ) + { + if ( pVBInfo->IF_DEF_CH7005 == 1 ) + { + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + index = 0 ; + } + } + + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) + { + if( pVBInfo->IF_DEF_LVDS == 0 ) + { + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + temp = LCDARefreshIndex[ pVBInfo->LCDResInfo & 0x0F ] ; /* 301b */ + else + temp = LCDRefreshIndex[ pVBInfo->LCDResInfo & 0x0F ] ; + + if ( index > temp ) + { + index = temp ; + } + } + else + { + index = 0 ; + } + } + } + + RefreshRateTableIndex = pVBInfo->EModeIDTable[ ModeIdIndex ].REFindex ; + ModeNo = pVBInfo->RefIndex[ RefreshRateTableIndex ].ModeID ; + if ( pXGIHWDE->jChipType >= XG20 ) /* for XG20, XG21, XG27 */ + { + /* + if ( pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag & XG2xNotSupport ) + { + index++; + } + */ + if ( ( pVBInfo->RefIndex[ RefreshRateTableIndex ].XRes == 800 ) && + ( pVBInfo->RefIndex[ RefreshRateTableIndex ].YRes == 600 ) ) + { + index++; + } +/* Alan 10/19/2007; do the similiar adjustment like XGISearchCRT1Rate() */ + if ( ( pVBInfo->RefIndex[ RefreshRateTableIndex ].XRes == 1024 ) && + ( pVBInfo->RefIndex[ RefreshRateTableIndex ].YRes == 768 ) ) + { + index++; + } + if ( ( pVBInfo->RefIndex[ RefreshRateTableIndex ].XRes == 1280 ) && + ( pVBInfo->RefIndex[ RefreshRateTableIndex ].YRes == 1024 ) ) + { + index++; + } + } + + i = 0 ; + do + { + if ( pVBInfo->RefIndex[ RefreshRateTableIndex + i ].ModeID != ModeNo ) + break ; + temp = pVBInfo->RefIndex[ RefreshRateTableIndex + i ].Ext_InfoFlag ; + temp &= ModeInfoFlag ; + if ( temp < pVBInfo->ModeType ) + break ; + i++ ; + index-- ; + + } while( index != 0xFFFF ) ; + if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) ) + { + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + temp = pVBInfo->RefIndex[ RefreshRateTableIndex + i - 1 ].Ext_InfoFlag ; + if ( temp & InterlaceMode ) + { + i++ ; + } + } + } + i-- ; + if ( ( pVBInfo->SetFlag & ProgrammingCRT2 ) ) + { + temp = XGI_AjustCRT2Rate( ModeNo , ModeIdIndex , RefreshRateTableIndex , &i, pVBInfo) ; + } + return( RefreshRateTableIndex + i ) ; /*return(0x01|(temp1<<1)); */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_AjustCRT2Rate */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGI_AjustCRT2Rate( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , USHORT *i, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempax , + tempbx , + resinfo , + modeflag , + infoflag ; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ModeFlag */ + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + } + + resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; + tempbx = pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].ModeID ; + tempax = 0 ; + + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) + { + tempax |= SupportRAMDAC2 ; + + if ( pVBInfo->VBType & VB_XGI301C ) + tempax |= SupportCRT2in301C ; + } + + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) /* 301b */ + { + tempax |= SupportLCD ; + + if ( pVBInfo->LCDResInfo != Panel1280x1024 ) + { + if ( pVBInfo->LCDResInfo != Panel1280x960 ) + { + if ( pVBInfo->LCDInfo & LCDNonExpanding ) + { + if ( resinfo >= 9 ) + { + tempax = 0 ; + return( 0 ) ; + } + } + } + } + } + + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) /* for HiTV */ + { + if ( ( pVBInfo->VBType & VB_XGI301LV ) && ( pVBInfo->VBExtInfo == VB_YPbPr1080i ) ) + { + tempax |= SupportYPbPr ; + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + if ( resinfo == 4 ) + return( 0 ) ; + + if ( resinfo == 3 ) + return( 0 ) ; + + if ( resinfo > 7 ) + return( 0 ) ; + } + } + else + { + tempax |= SupportHiVisionTV ; + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + if ( resinfo == 4 ) + return( 0 ) ; + + if ( resinfo == 3 ) + { + if ( pVBInfo->SetFlag & TVSimuMode ) + return( 0 ) ; + } + + if ( resinfo > 7 ) + return( 0 ) ; + } + } + } + else + { + if ( pVBInfo->VBInfo & ( SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr | SetCRT2ToHiVisionTV ) ) + { + tempax |= SupportTV ; + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + tempax |= SupportTV1024 ; + } + + if ( !( pVBInfo->VBInfo & SetPALTV ) ) + { + if ( modeflag & NoSupportSimuTV ) + { + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + if ( !( pVBInfo->VBInfo & SetNotSimuMode ) ) + { + return( 0 ) ; + } + } + } + } + } + } + } + else /* for LVDS */ + { + if ( pVBInfo->IF_DEF_CH7005 == 1 ) + { + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + tempax |= SupportCHTV ; + } + } + + if ( pVBInfo->VBInfo & SetCRT2ToLCD ) + { + tempax |= SupportLCD ; + + if ( resinfo > 0x08 ) + return( 0 ) ; /* 1024x768 */ + + if ( pVBInfo->LCDResInfo < Panel1024x768 ) + { + if ( resinfo > 0x07 ) + return( 0 ) ; /* 800x600 */ + + if ( resinfo == 0x04 ) + return( 0 ) ; /* 512x384 */ + } + } + } + + for( ; pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].ModeID == tempbx ; ( *i )-- ) + { + infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].Ext_InfoFlag ; + if ( infoflag & tempax ) + { + return( 1 ) ; + } + if ( ( *i ) == 0 ) + break ; + } + + for( ( *i ) = 0 ; ; ( *i )++ ) + { + infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].Ext_InfoFlag ; + if ( pVBInfo->RefIndex[ RefreshRateTableIndex + ( *i ) ].ModeID != tempbx ) + { + return( 0 ) ; + } + + if ( infoflag & tempax ) + { + return( 1 ) ; + } + } + return( 1 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetSync */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetSync(USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT sync , + temp ; + + sync = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag >> 8 ; /* di+0x00 */ + sync &= 0xC0 ; + temp = 0x2F ; + temp |= sync ; + XGINew_SetReg3( pVBInfo->P3c2 , temp ) ; /* Set Misc(3c2) */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT1CRTC */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT1CRTC( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceExtension ) +{ + UCHAR index , + data ; + + USHORT i ; + + index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ; /* Get index */ + index = index&IndexMask ; + + data =( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ; + data &= 0x7F ; + XGINew_SetReg1(pVBInfo->P3d4,0x11,data); /* Unlock CRTC */ + + for( i = 0 ; i < 8 ; i++ ) + pVBInfo->TimingH[ 0 ].data[ i ] = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ i ] ; + + for( i = 0 ; i < 7 ; i++ ) + pVBInfo->TimingV[ 0 ].data[ i ] = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ i + 8 ] ; + + XGI_SetCRT1Timing_H( pVBInfo, HwDeviceExtension ) ; + + + + XGI_SetCRT1Timing_V( ModeIdIndex , ModeNo, pVBInfo ) ; + + + if( pVBInfo->ModeType > 0x03 ) + XGINew_SetReg1( pVBInfo->P3d4 , 0x14 , 0x4F ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT1Timing_H */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT1Timing_H( PVB_DEVICE_INFO pVBInfo, PXGI_HW_DEVICE_INFO HwDeviceExtension ) +{ + UCHAR data , data1, pushax; + USHORT i , j ; + + /* XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0 ) ; */ + /* XGINew_SetReg1( pVBInfo->P3d4 , 0x56 , 0 ) ; */ + /* XGINew_SetRegANDOR( pVBInfo->P3d4 ,0x11 , 0x7f , 0x00 ) ; */ + + data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ; /* unlock cr0-7 */ + data &= 0x7F ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , data ) ; + + data = pVBInfo->TimingH[ 0 ].data[ 0 ] ; + XGINew_SetReg1( pVBInfo->P3d4 , 0 , data ) ; + + for( i = 0x01 ; i <= 0x04 ; i++ ) + { + data = pVBInfo->TimingH[ 0 ].data[ i ] ; + XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 1 ) , data ) ; + } + + for( i = 0x05 ; i <= 0x06 ; i++ ) + { + data = pVBInfo->TimingH[ 0 ].data[ i ]; + XGINew_SetReg1( pVBInfo->P3c4 ,( USHORT )( i + 6 ) , data ) ; + } + + j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0e ) ; + j &= 0x1F ; + data = pVBInfo->TimingH[ 0 ].data[ 7 ] ; + data &= 0xE0 ; + data |= j ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x0e , data ) ; + + if ( HwDeviceExtension->jChipType >= XG20 ) + { + data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x04 ) ; + data = data - 1 ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x04 , data ) ; + data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x05 ) ; + data1 = data ; + data1 &= 0xE0 ; + data &= 0x1F ; + if ( data == 0 ) + { + pushax = data ; + data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0c ) ; + data &= 0xFB ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x0c , data ) ; + data = pushax ; + } + data = data - 1 ; + data |= data1 ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x05 , data ) ; + data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0e ) ; + data = data >> 5 ; + data = data + 3 ; + if ( data > 7 ) + data = data - 7 ; + data = data << 5 ; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0e , ~0xE0 , data ) ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT1Timing_V */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT1Timing_V( USHORT ModeIdIndex , USHORT ModeNo,PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR data ; + USHORT i , j ; + + /* XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0 ) ; */ + /* XGINew_SetReg1( pVBInfo->P3d4 , 0x56 , 0 ) ; */ + /* XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x11 , 0x7f , 0x00 ) ; */ + + for( i = 0x00 ; i <= 0x01 ; i++ ) + { + data = pVBInfo->TimingV[ 0 ].data[ i ] ; + XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 6 ) , data ) ; + } + + for( i = 0x02 ; i <= 0x03 ; i++ ) + { + data = pVBInfo->TimingV[ 0 ].data[ i ] ; + XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 0x0e ) , data ) ; + } + + for( i = 0x04 ; i <= 0x05 ; i++ ) + { + data = pVBInfo->TimingV[ 0 ].data[ i ] ; + XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 0x11 ) , data ) ; + } + + j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x0a ) ; + j &= 0xC0 ; + data = pVBInfo->TimingV[ 0 ].data[ 6 ] ; + data &= 0x3F ; + data |= j ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x0a , data ) ; + + data = pVBInfo->TimingV[ 0 ].data[ 6 ] ; + data &= 0x80 ; + data = data >> 2 ; + + if ( ModeNo <= 0x13 ) + i = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + else + i = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + + i &= DoubleScanMode ; + if ( i ) + data |= 0x80 ; + + j = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x09 ) ; + j &= 0x5F ; + data |= j ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x09 , data ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetXG21CRTC */ +/* Input : Stand or enhance CRTC table */ +/* Output : Fill CRT Hsync/Vsync to SR2E/SR2F/SR30/SR33/SR34/SR3F */ +/* Description : Set LCD timing */ +/* --------------------------------------------------------------------- */ +void XGI_SetXG21CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo) +{ + UCHAR StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx ; + USHORT Temp1, Temp2, Temp3 ; + + if ( ModeNo <= 0x13 ) + { + StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ; + Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 4 ] ; /* CR04 HRS */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ; /* SR2E [7:0]->HRS */ + Tempbx = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 5 ] ; /* Tempbx: CR05 HRE */ + Tempbx &= 0x1F ; /* Tempbx: HRE[4:0] */ + Tempcx = Tempax ; + Tempcx &= 0xE0 ; /* Tempcx: HRS[7:5] */ + Tempdx = Tempcx | Tempbx ; /* Tempdx(HRE): HRS[7:5]HRE[4:0] */ + if ( Tempbx < ( Tempax & 0x1F ) ) /* IF HRE < HRS */ + Tempdx |= 0x20 ; /* Tempdx: HRE = HRE + 0x20 */ + Tempdx <<= 2 ; /* Tempdx << 2 */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempdx ) ; /* SR2F [7:2]->HRE */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ; + + Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 16 ] ; /* Tempax: CR16 VRS */ + Tempbx = Tempax ; /* Tempbx=Tempax */ + Tempax &= 0x01 ; /* Tempax: VRS[0] */ + XGINew_SetRegOR( pVBInfo->P3c4 , 0x33 , Tempax ) ; /* SR33[0]->VRS */ + Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 7 ] ; /* Tempax: CR7 VRS */ + Tempdx = Tempbx >> 1 ; /* Tempdx: VRS[7:1] */ + Tempcx = Tempax & 0x04 ; /* Tempcx: CR7[2] */ + Tempcx <<= 5 ; /* Tempcx[7]: VRS[8] */ + Tempdx |= Tempcx ; /* Tempdx: VRS[8:1] */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempdx ) ; /* SR34[7:0]: VRS[8:1] */ + + Temp1 = Tempcx << 1 ; /* Temp1[8]: VRS[8] UCHAR -> USHORT */ + Temp1 |= Tempbx ; /* Temp1[8:0]: VRS[8:0] */ + Tempax &= 0x80 ; /* Tempax[7]: CR7[7] */ + Temp2 = Tempax << 2 ; /* Temp2[9]: VRS[9] */ + Temp1 |= Temp2 ; /* Temp1[9:0]: VRS[9:0] */ + + Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 17 ] ; /* CR16 VRE */ + Tempax &= 0x0F ; /* Tempax[3:0]: VRE[3:0] */ + Temp2 = Temp1 & 0x3F0 ; /* Temp2[9:4]: VRS[9:4] */ + Temp2 |= Tempax ; /* Temp2[9:0]: VRE[9:0] */ + Temp3 = Temp1 & 0x0F ; /* Temp3[3:0]: VRS[3:0] */ + if ( Tempax < Temp3 ) /* VRE[3:0]<VRS[3:0] */ + Temp2 |= 0x10 ; /* Temp2: VRE + 0x10 */ + Temp2 &= 0xFF ; /* Temp2[7:0]: VRE[7:0] */ + Tempax = (UCHAR)Temp2 ; /* Tempax[7:0]: VRE[7:0] */ + Tempax <<= 2 ; /* Tempax << 2: VRE[5:0] */ + Temp1 &= 0x600 ; /* Temp1[10:9]: VRS[10:9] */ + Temp1 >>= 9 ; /* [10:9]->[1:0] */ + Tempbx = (UCHAR)Temp1 ; /* Tempbx[1:0]: VRS[10:9] */ + Tempax |= Tempbx ; /* VRE[5:0]VRS[10:9] */ + Tempax &= 0x7F ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , Tempax ) ; /* SR3F D[7:2]->VRE D[1:0]->VRS */ + } + else + { + index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ; + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 3 ] ; /* Tempax: CR4 HRS */ + Tempcx = Tempax ; /* Tempcx: HRS */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ; /* SR2E[7:0]->HRS */ + + Tempdx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 5 ] ; /* SRB */ + Tempdx &= 0xC0 ; /* Tempdx[7:6]: SRB[7:6] */ + Temp1 = Tempdx ; /* Temp1[7:6]: HRS[9:8] */ + Temp1 <<= 2 ; /* Temp1[9:8]: HRS[9:8] */ + Temp1 |= Tempax ; /* Temp1[9:0]: HRS[9:0] */ + + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 4 ] ; /* CR5 HRE */ + Tempax &= 0x1F ; /* Tempax[4:0]: HRE[4:0] */ + + Tempbx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 6 ] ; /* SRC */ + Tempbx &= 0x04 ; /* Tempbx[2]: HRE[5] */ + Tempbx <<= 3 ; /* Tempbx[5]: HRE[5] */ + Tempax |= Tempbx ; /* Tempax[5:0]: HRE[5:0] */ + + Temp2 = Temp1 & 0x3C0 ; /* Temp2[9:6]: HRS[9:6] */ + Temp2 |= Tempax ; /* Temp2[9:0]: HRE[9:0] */ + + Tempcx &= 0x3F ; /* Tempcx[5:0]: HRS[5:0] */ + if( Tempax < Tempcx ) /* HRE < HRS */ + Temp2 |= 0x40 ; /* Temp2 + 0x40 */ + + Temp2 &= 0xFF ; + Tempax = (UCHAR)Temp2 ; /* Tempax: HRE[7:0] */ + Tempax <<= 2 ; /* Tempax[7:2]: HRE[5:0] */ + Tempdx >>= 6 ; /* Tempdx[7:6]->[1:0] HRS[9:8] */ + Tempax |= Tempdx ; /* HRE[5:0]HRS[9:8] */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempax ) ; /* SR2F D[7:2]->HRE, D[1:0]->HRS */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ; + + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 10 ] ; /* CR10 VRS */ + Tempbx = Tempax ; /* Tempbx: VRS */ + Tempax &= 0x01 ; /* Tempax[0]: VRS[0] */ + XGINew_SetRegOR( pVBInfo->P3c4 , 0x33 , Tempax ) ; /* SR33[0]->VRS[0] */ + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 9 ] ; /* CR7[2][7] VRE */ + Tempcx = Tempbx >> 1 ; /* Tempcx[6:0]: VRS[7:1] */ + Tempdx = Tempax & 0x04 ; /* Tempdx[2]: CR7[2] */ + Tempdx <<= 5 ; /* Tempdx[7]: VRS[8] */ + Tempcx |= Tempdx ; /* Tempcx[7:0]: VRS[8:1] */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempcx ) ; /* SR34[8:1]->VRS */ + + Temp1 = Tempdx ; /* Temp1[7]: Tempdx[7] */ + Temp1 <<= 1 ; /* Temp1[8]: VRS[8] */ + Temp1 |= Tempbx ; /* Temp1[8:0]: VRS[8:0] */ + Tempax &= 0x80 ; + Temp2 = Tempax << 2 ; /* Temp2[9]: VRS[9] */ + Temp1 |= Temp2 ; /* Temp1[9:0]: VRS[9:0] */ + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ; /* Tempax: SRA */ + Tempax &= 0x08 ; /* Tempax[3]: VRS[3] */ + Temp2 = Tempax ; + Temp2 <<= 7 ; /* Temp2[10]: VRS[10] */ + Temp1 |= Temp2 ; /* Temp1[10:0]: VRS[10:0] */ + + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 11 ] ; /* Tempax: CR11 VRE */ + Tempax &= 0x0F ; /* Tempax[3:0]: VRE[3:0] */ + Tempbx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ; /* Tempbx: SRA */ + Tempbx &= 0x20 ; /* Tempbx[5]: VRE[5] */ + Tempbx >>= 1 ; /* Tempbx[4]: VRE[4] */ + Tempax |= Tempbx ; /* Tempax[4:0]: VRE[4:0] */ + Temp2 = Temp1 & 0x7E0 ; /* Temp2[10:5]: VRS[10:5] */ + Temp2 |= Tempax ; /* Temp2[10:5]: VRE[10:5] */ + + Temp3 = Temp1 & 0x1F ; /* Temp3[4:0]: VRS[4:0] */ + if ( Tempax < Temp3 ) /* VRE < VRS */ + Temp2 |= 0x20 ; /* VRE + 0x20 */ + + Temp2 &= 0xFF ; + Tempax = (UCHAR)Temp2 ; /* Tempax: VRE[7:0] */ + Tempax <<= 2 ; /* Tempax[7:0]; VRE[5:0]00 */ + Temp1 &= 0x600 ; /* Temp1[10:9]: VRS[10:9] */ + Temp1 >>= 9 ; /* Temp1[1:0]: VRS[10:9] */ + Tempbx = (UCHAR)Temp1 ; + Tempax |= Tempbx ; /* Tempax[7:0]: VRE[5:0]VRS[10:9] */ + Tempax &= 0x7F ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , Tempax ) ; /* SR3F D[7:2]->VRE D[1:0]->VRS */ + } +} + +void XGI_SetXG27CRTC(USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo) +{ + USHORT StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx ; + + if ( ModeNo <= 0x13 ) + { + StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ; + Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 4 ] ; /* CR04 HRS */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ; /* SR2E [7:0]->HRS */ + Tempbx = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 5 ] ; /* Tempbx: CR05 HRE */ + Tempbx &= 0x1F ; /* Tempbx: HRE[4:0] */ + Tempcx = Tempax ; + Tempcx &= 0xE0 ; /* Tempcx: HRS[7:5] */ + Tempdx = Tempcx | Tempbx ; /* Tempdx(HRE): HRS[7:5]HRE[4:0] */ + if ( Tempbx < ( Tempax & 0x1F ) ) /* IF HRE < HRS */ + Tempdx |= 0x20 ; /* Tempdx: HRE = HRE + 0x20 */ + Tempdx <<= 2 ; /* Tempdx << 2 */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempdx ) ; /* SR2F [7:2]->HRE */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ; + + Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 16 ] ; /* Tempax: CR10 VRS */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempax ) ; /* SR34[7:0]->VRS */ + Tempcx = Tempax ; /* Tempcx=Tempax=VRS[7:0] */ + Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 7 ] ; /* Tempax[7][2]: CR7[7][2] VRS[9][8] */ + Tempbx = Tempax ; /* Tempbx=CR07 */ + Tempax &= 0x04 ; /* Tempax[2]: CR07[2] VRS[8] */ + Tempax >>= 2; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x01, Tempax ) ; /* SR35 D[0]->VRS D[8] */ + Tempcx |= (Tempax << 8) ; /* Tempcx[8] |= VRS[8] */ + Tempcx |= (Tempbx & 0x80)<<2; /* Tempcx[9] |= VRS[9] */ + + + Tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 17 ] ; /* CR11 VRE */ + Tempax &= 0x0F ; /* Tempax: VRE[3:0] */ + Tempbx = Tempcx ; /* Tempbx=Tempcx=VRS[9:0] */ + Tempbx &= 0x3F0 ; /* Tempbx[9:4]: VRS[9:4] */ + Tempbx |= Tempax ; /* Tempbx[9:0]: VRE[9:0] */ + if ( Tempax <= (Tempcx & 0x0F) ) /* VRE[3:0]<=VRS[3:0] */ + Tempbx |= 0x10 ; /* Tempbx: VRE + 0x10 */ + Tempax = (UCHAR)Tempbx & 0xFF; /* Tempax[7:0]: VRE[7:0] */ + Tempax <<= 2 ; /* Tempax << 2: VRE[5:0] */ + Tempcx = (Tempcx&0x600)>>8; /* Tempcx VRS[10:9] */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC, Tempax ) ; /* SR3F D[7:2]->VRE D[5:0] */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x06, Tempcx ) ; /* SR35 D[2:1]->VRS[10:9] */ + } + else + { + index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ; + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 3 ] ; /* Tempax: CR4 HRS */ + Tempbx = Tempax ; /* Tempbx: HRS[7:0] */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , Tempax ) ; /* SR2E[7:0]->HRS */ + + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 5 ] ; /* SR0B */ + Tempax &= 0xC0 ; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/ + Tempbx |= (Tempax << 2); /* Tempbx: HRS[9:0] */ + + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 4 ] ; /* CR5 HRE */ + Tempax &= 0x1F ; /* Tempax[4:0]: HRE[4:0] */ + Tempcx = Tempax ; /* Tempcx: HRE[4:0] */ + + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 6 ] ; /* SRC */ + Tempax &= 0x04 ; /* Tempax[2]: HRE[5] */ + Tempax <<= 3 ; /* Tempax[5]: HRE[5] */ + Tempcx |= Tempax ; /* Tempcx[5:0]: HRE[5:0] */ + + Tempbx = Tempbx & 0x3C0 ; /* Tempbx[9:6]: HRS[9:6] */ + Tempbx |= Tempcx ; /* Tempbx: HRS[9:6]HRE[5:0] */ + + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 3 ] ; /* Tempax: CR4 HRS */ + Tempax &= 0x3F ; /* Tempax: HRS[5:0] */ + if( Tempcx <= Tempax ) /* HRE[5:0] < HRS[5:0] */ + Tempbx += 0x40 ; /* Tempbx= Tempbx + 0x40 : HRE[9:0]*/ + + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 5 ] ; /* SR0B */ + Tempax &= 0xC0 ; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/ + Tempax >>= 6; /* Tempax[1:0]: HRS[9:8]*/ + Tempax |= ((Tempbx << 2) & 0xFF); /* Tempax[7:2]: HRE[5:0] */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , Tempax ) ; /* SR2F [7:2][1:0]: HRE[5:0]HRS[9:8] */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , 0xE3 , 00 ) ; + + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 10 ] ; /* CR10 VRS */ + XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , Tempax ) ; /* SR34[7:0]->VRS[7:0] */ + + Tempcx = Tempax ; /* Tempcx <= VRS[7:0] */ + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 9 ] ; /* CR7[7][2] VRS[9][8] */ + Tempbx = Tempax ; /* Tempbx <= CR07[7:0] */ + Tempax = Tempax & 0x04 ; /* Tempax[2]: CR7[2]: VRS[8] */ + Tempax >>= 2 ; /* Tempax[0]: VRS[8] */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x01 , Tempax ) ; /* SR35[0]: VRS[8] */ + Tempcx |= (Tempax<<8) ; /* Tempcx <= VRS[8:0] */ + Tempcx |= ((Tempbx&0x80)<<2) ; /* Tempcx <= VRS[9:0] */ + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ; /* Tempax: SR0A */ + Tempax &= 0x08; /* SR0A[3] VRS[10] */ + Tempcx |= (Tempax<<7) ; /* Tempcx <= VRS[10:0] */ + + + Tempax = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 11 ] ; /* Tempax: CR11 VRE */ + Tempax &= 0x0F ; /* Tempax[3:0]: VRE[3:0] */ + Tempbx = pVBInfo->XGINEWUB_CRT1Table[ index ].CR[ 14 ] ; /* Tempbx: SR0A */ + Tempbx &= 0x20 ; /* Tempbx[5]: SR0A[5]: VRE[4] */ + Tempbx >>= 1 ; /* Tempbx[4]: VRE[4] */ + Tempax |= Tempbx ; /* Tempax[4:0]: VRE[4:0] */ + Tempbx = Tempcx ; /* Tempbx: VRS[10:0] */ + Tempbx &= 0x7E0 ; /* Tempbx[10:5]: VRS[10:5] */ + Tempbx |= Tempax ; /* Tempbx: VRS[10:5]VRE[4:0] */ + + if ( Tempbx <= Tempcx ) /* VRE <= VRS */ + Tempbx |= 0x20 ; /* VRE + 0x20 */ + + Tempax = (Tempbx<<2) & 0xFF ; /* Tempax: Tempax[7:0]; VRE[5:0]00 */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC , Tempax ) ; /* SR3F[7:2]:VRE[5:0] */ + Tempax = Tempcx >> 8; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x07 , Tempax ) ; /* SR35[2:0]:VRS[10:8] */ + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetXG21LCD */ +/* Input : */ +/* Output : FCLK duty cycle, FCLK delay compensation */ +/* Description : All values set zero */ +/* --------------------------------------------------------------------- */ +void XGI_SetXG21LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo) +{ + USHORT Data , Temp , b3CC ; + USHORT XGI_P3cc ; + + XGI_P3cc = pVBInfo->P3cc ; + + XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , 0x00 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , 0x00 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , 0x00 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , 0x00 ) ; + if ( ((*pVBInfo->pDVOSetting)&0xC0) == 0xC0 ) + { + XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , *pVBInfo->pCR2E ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , *pVBInfo->pCR2F ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , *pVBInfo->pCR46 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , *pVBInfo->pCR47 ) ; + } + + Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ; + + if ( Temp & 0x01 ) + { + XGINew_SetRegOR( pVBInfo->P3c4 , 0x06 , 0x40 ) ; /* 18 bits FP */ + XGINew_SetRegOR( pVBInfo->P3c4 , 0x09 , 0x40 ) ; + } + + XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x01 ) ; /* Negative blank polarity */ + + XGINew_SetRegAND( pVBInfo->P3c4 , 0x30 , ~0x20 ) ; + XGINew_SetRegAND( pVBInfo->P3c4 , 0x35 , ~0x80 ) ; + + if ( ModeNo <= 0x13 ) + { + b3CC = (UCHAR) XGINew_GetReg2( XGI_P3cc ) ; + if ( b3CC & 0x40 ) + XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */ + if ( b3CC & 0x80 ) + XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */ + } + else + { + Data = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ; + if ( Data & 0x4000 ) + XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */ + if ( Data & 0x8000 ) + XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */ + } +} + +void XGI_SetXG27LCD(PVB_DEVICE_INFO pVBInfo,USHORT RefreshRateTableIndex,USHORT ModeNo) +{ + USHORT Data , Temp , b3CC ; + USHORT XGI_P3cc ; + + XGI_P3cc = pVBInfo->P3cc ; + + XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , 0x00 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , 0x00 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , 0x00 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , 0x00 ) ; + + Temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ; + if ( ( Temp & 0x03 ) == 0 ) /* dual 12 */ + { + XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , 0x13 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , 0x13 ) ; + } + + if ( ((*pVBInfo->pDVOSetting)&0xC0) == 0xC0 ) + { + XGINew_SetReg1( pVBInfo->P3d4 , 0x2E , *pVBInfo->pCR2E ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x2F , *pVBInfo->pCR2F ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x46 , *pVBInfo->pCR46 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x47 , *pVBInfo->pCR47 ) ; + } + + XGI_SetXG27FPBits(pVBInfo); + + XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x01 ) ; /* Negative blank polarity */ + + XGINew_SetRegAND( pVBInfo->P3c4 , 0x30 , ~0x20 ) ; /* Hsync polarity */ + XGINew_SetRegAND( pVBInfo->P3c4 , 0x35 , ~0x80 ) ; /* Vsync polarity */ + + if ( ModeNo <= 0x13 ) + { + b3CC = (UCHAR) XGINew_GetReg2( XGI_P3cc ) ; + if ( b3CC & 0x40 ) + XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */ + if ( b3CC & 0x80 ) + XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */ + } + else + { + Data = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ; + if ( Data & 0x4000 ) + XGINew_SetRegOR( pVBInfo->P3c4 , 0x30 , 0x20 ) ; /* Hsync polarity */ + if ( Data & 0x8000 ) + XGINew_SetRegOR( pVBInfo->P3c4 , 0x35 , 0x80 ) ; /* Vsync polarity */ + } +} + +/* --------------------------------------------------------------------- */ +/* Function : XGI_UpdateXG21CRTC */ +/* Input : */ +/* Output : CRT1 CRTC */ +/* Description : Modify CRT1 Hsync/Vsync to fix LCD mode timing */ +/* --------------------------------------------------------------------- */ +void XGI_UpdateXG21CRTC( USHORT ModeNo , PVB_DEVICE_INFO pVBInfo , USHORT RefreshRateTableIndex ) +{ + int i , index = -1; + + XGINew_SetRegAND( pVBInfo->P3d4 , 0x11 , 0x7F ) ; /* Unlock CR0~7 */ + if ( ModeNo <= 0x13 ) + { + for( i = 0 ; i < 12 ; i++ ) + { + if ( ModeNo == pVBInfo->UpdateCRT1[ i ].ModeID ) + index = i ; + } + } + else + { + if ( ModeNo == 0x2E && ( pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC == RES640x480x60 ) ) + index = 12 ; + else if ( ModeNo == 0x2E && ( pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC == RES640x480x72 ) ) + index = 13 ; + else if ( ModeNo == 0x2F ) + index = 14 ; + else if ( ModeNo == 0x50 ) + index = 15 ; + else if ( ModeNo == 0x59 ) + index = 16 ; + } + + if( index != -1 ) + { + XGINew_SetReg1( pVBInfo->P3d4 , 0x02 , pVBInfo->UpdateCRT1[ index ].CR02 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x03 , pVBInfo->UpdateCRT1[ index ].CR03 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x15 , pVBInfo->UpdateCRT1[ index ].CR15 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x16 , pVBInfo->UpdateCRT1[ index ].CR16 ) ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT1DE */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT1DE( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo,USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT resindex , + tempax , + tempbx , + tempcx , + temp , + modeflag ; + + UCHAR data ; + + resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + tempax = pVBInfo->StResInfo[ resindex ].HTotal ; + tempbx = pVBInfo->StResInfo[ resindex ].VTotal ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + tempax = pVBInfo->ModeResInfo[ resindex ].HTotal ; + tempbx = pVBInfo->ModeResInfo[ resindex ].VTotal ; + } + + if ( modeflag & HalfDCLK ) + tempax = tempax >> 1 ; + + if ( ModeNo > 0x13 ) + { + if ( modeflag & HalfDCLK ) + tempax = tempax << 1 ; + + temp = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ; + + if ( temp & InterlaceMode ) + tempbx = tempbx >> 1 ; + + if ( modeflag & DoubleScanMode ) + tempbx = tempbx << 1 ; + } + + tempcx = 8 ; + + /* if ( !( modeflag & Charx8Dot ) ) */ + /* tempcx = 9 ; */ + + tempax /= tempcx ; + tempax -= 1 ; + tempbx -= 1 ; + tempcx = tempax ; + temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ; + data = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ; + data &= 0x7F ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , data ) ; /* Unlock CRTC */ + XGINew_SetReg1( pVBInfo->P3d4 , 0x01 , ( USHORT )( tempcx & 0xff ) ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x0b , ~0x0c , ( USHORT )( ( tempcx & 0x0ff00 ) >> 10 ) ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x12 , ( USHORT )( tempbx & 0xff ) ) ; + tempax = 0 ; + tempbx = tempbx >> 8 ; + + if ( tempbx & 0x01 ) + tempax |= 0x02 ; + + if ( tempbx & 0x02 ) + tempax |= 0x40 ; + + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x42 , tempax ) ; + data =( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x07 ) ; + data &= 0xFF ; + tempax = 0 ; + + if ( tempbx & 0x04 ) + tempax |= 0x02 ; + + XGINew_SetRegANDOR( pVBInfo->P3d4 ,0x0a , ~0x02 , tempax ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetResInfo */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +USHORT XGI_GetResInfo(USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT resindex ; + + if ( ModeNo <= 0x13 ) + { + resindex = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; /* si+St_ResInfo */ + } + else + { + resindex = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo */ + } + return( resindex ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT1Offset */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT1Offset( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT temp , + ah , + al , + temp2 , + i , + DisplayUnit ; + + /* GetOffset */ + temp = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeInfo ; + temp = temp >> 8 ; + temp = pVBInfo->ScreenOffset[ temp ] ; + + temp2 = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ; + temp2 &= InterlaceMode ; + + if ( temp2 ) + temp = temp << 1; + + temp2 = pVBInfo->ModeType - ModeEGA ; + + switch( temp2 ) + { + case 0: + temp2 = 1 ; + break ; + case 1: + temp2 = 2 ; + break ; + case 2: + temp2 = 4 ; + break ; + case 3: + temp2 = 4 ; + break ; + case 4: + temp2 = 6 ; + break; + case 5: + temp2 = 8 ; + break ; + default: + break ; + } + + if ( ( ModeNo >= 0x26 ) && ( ModeNo <= 0x28 ) ) + temp = temp * temp2 + temp2 / 2 ; + else + temp *= temp2 ; + + /* SetOffset */ + DisplayUnit = temp ; + temp2 = temp ; + temp = temp >> 8 ; /* ah */ + temp &= 0x0F ; + i = XGINew_GetReg1( pVBInfo->P3c4 , 0x0E ) ; + i &= 0xF0 ; + i |= temp ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x0E , i ) ; + + temp =( UCHAR )temp2 ; + temp &= 0xFF ; /* al */ + XGINew_SetReg1( pVBInfo->P3d4 , 0x13 , temp ) ; + + /* SetDisplayUnit */ + temp2 = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ; + temp2 &= InterlaceMode ; + if ( temp2 ) + DisplayUnit >>= 1 ; + + DisplayUnit = DisplayUnit << 5 ; + ah = ( DisplayUnit & 0xff00 ) >> 8 ; + al = DisplayUnit & 0x00ff ; + if ( al == 0 ) + ah += 1 ; + else + ah += 2 ; + + if ( HwDeviceExtension->jChipType >= XG20 ) + if ( ( ModeNo == 0x4A ) | (ModeNo == 0x49 ) ) + ah -= 1 ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x10 , ah ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT1VCLK */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT1VCLK( USHORT ModeNo , USHORT ModeIdIndex , + PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR index , data ; + USHORT vclkindex ; + + if ( pVBInfo->IF_DEF_LVDS == 1 ) + { + index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ; + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) & 0xCF ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , data ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ index ].SR2B ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ index ].SR2C ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2D , 0x01 ) ; + } + else if ( ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) && ( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) + { + vclkindex = XGI_GetVCLK2Ptr( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ; + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) & 0xCF ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , data ) ; + data = pVBInfo->VBVCLKData[ vclkindex ].Part4_A ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , data ) ; + data = pVBInfo->VBVCLKData[ vclkindex ].Part4_B ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , data ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2D , 0x01 ) ; + } + else + { + index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ; + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) & 0xCF ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , data ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->VCLKData[ index ].SR2B ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->VCLKData[ index ].SR2C ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2D , 0x01 ) ; + } + + if ( HwDeviceExtension->jChipType >= XG20 ) + { + if ( pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag & HalfDCLK ) + { + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x2B ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , data ) ; + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x2C ) ; + index = data ; + index &= 0xE0 ; + data &= 0x1F ; + data = data << 1 ; + data += 1 ; + data |= index ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , data ) ; + } + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT1FIFO */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT1FIFO( USHORT ModeNo , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo ) +{ + USHORT data ; + + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x3D ) ; + data &= 0xfe ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x3D , data ) ; /* diable auto-threshold */ + + if ( ModeNo > 0x13 ) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x08 , 0x34 ) ; + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x09 ) ; + data &= 0xC0 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x09 , data | 0x30) ; + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x3D ) ; + data |= 0x01 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x3D , data ) ; + } + else + { + if (HwDeviceExtension->jChipType == XG27) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x08 , 0x0E ) ; + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x09 ) ; + data &= 0xC0 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x09 , data | 0x20 ) ; + } + else + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x08 , 0xAE ) ; + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x09 ) ; + data &= 0xF0 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x09 , data ) ; + } + } + + if (HwDeviceExtension->jChipType == XG21) + { + XGI_SetXG21FPBits(pVBInfo); /* Fix SR9[7:6] can't read back */ + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT1ModeRegs */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT1ModeRegs( PXGI_HW_DEVICE_INFO HwDeviceExtension , + USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo ) +{ + USHORT data , + data2 , + data3 , + infoflag = 0 , + modeflag , + resindex , + xres ; + + if ( ModeNo > 0x13 ) + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ; + } + else + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ModeFlag */ + + if ( XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) & 0x01 ) + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1F , 0x3F , 0x00 ) ; + + if ( ModeNo > 0x13 ) + data = infoflag ; + else + data = 0 ; + + data2 = 0 ; + + if ( ModeNo > 0x13 ) + { + if ( pVBInfo->ModeType > 0x02 ) + { + data2 |= 0x02 ; + data3 = pVBInfo->ModeType - ModeVGA ; + data3 = data3 << 2 ; + data2 |= data3 ; + } + } + + data &= InterlaceMode ; + + if ( data ) + data2 |= 0x20 ; + + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x06 , ~0x3F , data2 ) ; + /* XGINew_SetReg1(pVBInfo->P3c4,0x06,data2); */ + resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ; + if ( ModeNo <= 0x13 ) + xres = pVBInfo->StResInfo[ resindex ].HTotal ; + else + xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */ + + data = 0x0000 ; + if ( infoflag & InterlaceMode ) + { + if ( xres == 1024 ) + data = 0x0035 ; + else if ( xres == 1280 ) + data = 0x0048 ; + } + + data2 = data & 0x00FF ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x19 , 0xFF , data2 ) ; + data2 = ( data & 0xFF00 ) >> 8 ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x19 , 0xFC , data2 ) ; + + if( modeflag & HalfDCLK ) + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xF7 , 0x08 ) ; + + data2 = 0 ; + + if ( modeflag & LineCompareOff ) + data2 |= 0x08 ; + + if ( ModeNo > 0x13 ) + { + if ( pVBInfo->ModeType == ModeEGA ) + data2 |= 0x40 ; + } + + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0F , ~0x48 , data2 ) ; + data = 0x60 ; + if ( pVBInfo->ModeType != ModeText ) + { + data = data ^ 0x60 ; + if ( pVBInfo->ModeType != ModeEGA ) + { + data = data ^ 0xA0 ; + } + } + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x21 , 0x1F , data ) ; + + XGI_SetVCLKState( HwDeviceExtension , ModeNo , RefreshRateTableIndex, pVBInfo) ; + + /* if(modeflag&HalfDCLK)//030305 fix lowresolution bug */ + /* if(XGINew_IF_DEF_NEW_LOWRES) */ + /* XGI_VesaLowResolution(ModeNo,ModeIdIndex);//030305 fix lowresolution bug */ + + data=XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) ; + + if (HwDeviceExtension->jChipType == XG27 ) + { + if ( data & 0x40 ) + data = 0x2c ; + else + data = 0x6c ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x52 , data ) ; + XGINew_SetRegOR( pVBInfo->P3d4 , 0x51 , 0x10 ) ; + } + else + if (HwDeviceExtension->jChipType >= XG20 ) + { + if ( data & 0x40 ) + data = 0x33 ; + else + data = 0x73 ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x52 , data ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x51 , 0x02 ) ; + } + else + { + if ( data & 0x40 ) + data = 0x2c ; + else + data = 0x6c ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x52 , data ) ; + } + +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetVCLKState */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetVCLKState( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo , USHORT RefreshRateTableIndex,PVB_DEVICE_INFO pVBInfo ) +{ + USHORT data , + data2 = 0 ; + SHORT VCLK ; + + UCHAR index ; + + if ( ModeNo <= 0x13 ) + VCLK = 0 ; + else + { + index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ; + index &= IndexMask ; + VCLK = pVBInfo->VCLKData[ index ].CLOCK ; + } + + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) ; + data &= 0xf3 ; + if ( VCLK >= 200 ) + data |= 0x0c ; /* VCLK > 200 */ + + if ( HwDeviceExtension->jChipType >= XG20 ) + data &= ~0x04 ; /* 2 pixel mode */ + + XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , data ) ; + + if ( HwDeviceExtension->jChipType < XG20 ) + { + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ; + data &= 0xE7 ; + if ( VCLK < 200 ) + data |= 0x10 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , data ) ; + } + +/* Jong for Adavantech LCD ripple issue + if ( ( VCLK >= 0 ) && ( VCLK < 135 ) ) + data2 = 0x03 ; + else if ( ( VCLK >= 135 ) && ( VCLK < 160 ) ) + data2 = 0x02 ; + else if ( ( VCLK >= 160 ) && ( VCLK < 260 ) ) + data2 = 0x01 ; + else if ( VCLK > 260 ) + data2 = 0x00 ; +*/ + data2 = 0x00 ; + + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x07 , 0xFC , data2 ) ; + if (HwDeviceExtension->jChipType >= XG27 ) + { + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x40 , 0xFC , data2&0x03 ) ; + } + + +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_VesaLowResolution */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +/*void XGI_VesaLowResolution( USHORT ModeNo , USHORT ModeIdIndex ,PVB_DEVICE_INFO pVBInfo) +{ + USHORT modeflag; + + if ( ModeNo > 0x13 ) + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + else + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + + if ( ModeNo > 0x13 ) + { + if ( modeflag & DoubleScanMode ) + { + if ( modeflag & HalfDCLK ) + { + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) ) + { + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xf7 , 0x00 ) ; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0f , 0x7f , 0x00 ) ; + return ; + } + } + } + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0f , 0xff , 0x80 ) ; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xf7 , 0x00 ) ; + return ; + } + } + } + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0f , 0x7f , 0x00 ) ; +} +*/ + +/* --------------------------------------------------------------------- */ +/* Function : XGI_LoadDAC */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_LoadDAC( USHORT ModeNo , USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo ) +{ + USHORT data , data2 , time , + i , j , k , m , n , o , + si , di , bx , dl , al , ah , dh , + *table = NULL ; + + if ( ModeNo <= 0x13 ) + data = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + else + data = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + + data &= DACInfoFlag ; + time = 64 ; + + if ( data == 0x00 ) + table = XGINew_MDA_DAC ; + else if ( data == 0x08 ) + table = XGINew_CGA_DAC ; + else if ( data == 0x10 ) + table = XGINew_EGA_DAC ; + else if ( data == 0x18 ) + { + time = 256 ; + table = XGINew_VGA_DAC ; + } + + if ( time == 256 ) + j = 16 ; + else + j = time ; + + XGINew_SetReg3( pVBInfo->P3c6 , 0xFF ) ; + XGINew_SetReg3( pVBInfo->P3c8 , 0x00 ) ; + + for( i = 0 ; i < j ; i++ ) + { + data = table[ i ] ; + + for( k = 0 ; k < 3 ; k++ ) + { + data2 = 0 ; + + if ( data & 0x01 ) + data2 = 0x2A ; + + if ( data & 0x02 ) + data2 += 0x15 ; + + XGINew_SetReg3( pVBInfo->P3c9 , data2 ) ; + data = data >> 2 ; + } + } + + if ( time == 256 ) + { + for( i = 16 ; i < 32 ; i++ ) + { + data = table[ i ] ; + + for( k = 0 ; k < 3 ; k++ ) + XGINew_SetReg3( pVBInfo->P3c9 , data ) ; + } + + si = 32 ; + + for( m = 0 ; m < 9 ; m++ ) + { + di = si ; + bx = si + 0x04 ; + dl = 0 ; + + for( n = 0 ; n < 3 ; n++ ) + { + for( o = 0 ; o < 5 ; o++ ) + { + dh = table[ si ] ; + ah = table[ di ] ; + al = table[ bx ] ; + si++ ; + XGI_WriteDAC( dl , ah , al , dh, pVBInfo ) ; + } + + si -= 2 ; + + for( o = 0 ; o < 3 ; o++ ) + { + dh = table[ bx ] ; + ah = table[ di ] ; + al = table[ si ] ; + si-- ; + XGI_WriteDAC( dl , ah , al , dh, pVBInfo ) ; + } + + dl++ ; + } + + si += 5 ; + } + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_WriteDAC */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_WriteDAC( USHORT dl , USHORT ah , USHORT al , USHORT dh,PVB_DEVICE_INFO pVBInfo ) +{ + USHORT temp , bh , bl ; + + bh = ah ; + bl = al ; + + if ( dl != 0 ) + { + temp = bh ; + bh = dh ; + dh = temp ; + if ( dl == 1 ) + { + temp = bl ; + bl = dh ; + dh = temp ; + } + else + { + temp = bl ; + bl = bh ; + bh = temp ; + } + } + XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )dh ) ; + XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )bh ) ; + XGINew_SetReg3( pVBInfo->P3c9 , ( USHORT )bl ) ; +} + +#if 0 +/* --------------------------------------------------------------------- */ +/* Function : XGI_ClearBuffer */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_ClearBuffer( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo, PVB_DEVICE_INFO pVBInfo) +{ + PVOID VideoMemoryAddress = ( PVOID )HwDeviceExtension->pjVideoMemoryAddress ; + ULONG AdapterMemorySize = ( ULONG )HwDeviceExtension->ulVideoMemorySize ; + PUSHORT pBuffer ; +#ifndef LINUX_XF86 + int i ; +#endif + + if ( pVBInfo->ModeType >= ModeEGA ) + { + if ( ModeNo > 0x13 ) + { + AdapterMemorySize = 0x40000 ; /* clear 256k */ + /* GetDRAMSize( HwDeviceExtension ) ; */ + XGI_SetMemory( VideoMemoryAddress , AdapterMemorySize , 0 ) ; + } + else + { +/* + pBuffer = VideoMemoryAddress ; + for( i = 0 ; i < 0x4000 ; i++ ) + pBuffer[ i ] = 0x0000 ; +*/ + } + } + else + { + pBuffer = VideoMemoryAddress ; + if ( pVBInfo->ModeType < ModeCGA ) + { +/* + for ( i = 0 ; i < 0x4000 ; i++ ) + pBuffer[ i ] = 0x0720 ; +*/ + } + else + XGI_SetMemory( VideoMemoryAddress , 0x8000 , 0 ) ; + } +} + +#endif +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetLCDAGroup */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetLCDAGroup( USHORT ModeNo , USHORT ModeIdIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT RefreshRateTableIndex ; + /* USHORT temp ; */ + + /* pVBInfo->SelectCRT2Rate = 0 ; */ + + pVBInfo->SetFlag |= ProgrammingCRT2 ; + RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, pVBInfo ) ; + XGI_GetLVDSResInfo( ModeNo , ModeIdIndex, pVBInfo ) ; + XGI_GetLVDSData( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo); + XGI_ModCRT1Regs( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ; + XGI_SetLVDSRegs( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + XGI_SetCRT2ECLK( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetLVDSResInfo */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetLVDSResInfo( USHORT ModeNo , USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo ) +{ + USHORT resindex , xres , yres , modeflag ; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; /* si+St_ResInfo */ + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo */ + } + + + /* if ( ModeNo > 0x13 ) */ + /* modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; */ + /* else */ + /* modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; */ + + if ( ModeNo <= 0x13 ) + { + resindex = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; /* si+St_ResInfo */ + } + else + { + resindex = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo */ + } + + /* resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ; */ + + if ( ModeNo <= 0x13 ) + { + xres = pVBInfo->StResInfo[ resindex ].HTotal ; + yres = pVBInfo->StResInfo[ resindex ].VTotal ; + } + else + { + xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; + yres = pVBInfo->ModeResInfo[ resindex ].VTotal ; + } + if ( ModeNo > 0x13 ) + { + if ( modeflag & HalfDCLK ) + xres = xres << 1 ; + + if ( modeflag & DoubleScanMode ) + yres = yres << 1 ; + } + /* if ( modeflag & Charx8Dot ) */ + /* { */ + + if ( xres == 720 ) + xres = 640 ; + + /* } */ + pVBInfo->VGAHDE = xres ; + pVBInfo->HDE = xres ; + pVBInfo->VGAVDE = yres ; + pVBInfo->VDE = yres ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetLVDSData */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetLVDSData( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempbx ; + XGI330_LVDSDataStruct *LCDPtr = NULL ; + XGI330_CHTVDataStruct *TVPtr = NULL ; + + tempbx = 2 ; + + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) + { + LCDPtr = ( XGI330_LVDSDataStruct * )XGI_GetLcdPtr( tempbx, ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo) ; + pVBInfo->VGAHT = LCDPtr->VGAHT ; + pVBInfo->VGAVT = LCDPtr->VGAVT ; + pVBInfo->HT = LCDPtr->LCDHT ; + pVBInfo->VT = LCDPtr->LCDVT ; + } + if ( pVBInfo->IF_DEF_CH7017 == 1 ) + { + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + TVPtr = ( XGI330_CHTVDataStruct * )XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + pVBInfo->VGAHT = TVPtr->VGAHT ; + pVBInfo->VGAVT = TVPtr->VGAVT ; + pVBInfo->HT = TVPtr->LCDHT ; + pVBInfo->VT = TVPtr->LCDVT ; + } + } + + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) + { + if ( !( pVBInfo->LCDInfo & ( SetLCDtoNonExpanding | EnableScalingLCD ) ) ) + { + if ( ( pVBInfo->LCDResInfo == Panel1024x768 ) || ( pVBInfo->LCDResInfo == Panel1024x768x75 ) ) + { + pVBInfo->HDE = 1024 ; + pVBInfo->VDE = 768 ; + } + else if ( ( pVBInfo->LCDResInfo == Panel1280x1024 ) || ( pVBInfo->LCDResInfo == Panel1280x1024x75 ) ) + { + pVBInfo->HDE = 1280 ; + pVBInfo->VDE = 1024 ; + } + else if ( pVBInfo->LCDResInfo == Panel1400x1050 ) + { + pVBInfo->HDE = 1400 ; + pVBInfo->VDE = 1050 ; + } + else + { + pVBInfo->HDE = 1600 ; + pVBInfo->VDE = 1200 ; + } + } + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_ModCRT1Regs */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_ModCRT1Regs( USHORT ModeNo , USHORT ModeIdIndex , + USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR index ; + USHORT tempbx , i ; + XGI_LVDSCRT1HDataStruct *LCDPtr = NULL ; + XGI_LVDSCRT1VDataStruct *LCDPtr1 =NULL ; + /* XGI330_CHTVDataStruct *TVPtr = NULL ; */ + XGI_CH7007TV_TimingHStruct *CH7007TV_TimingHPtr = NULL; + XGI_CH7007TV_TimingVStruct *CH7007TV_TimingVPtr = NULL; + + if( ModeNo <= 0x13 ) + index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ; + else + index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + + index= index & IndexMask ; + + if ( ( pVBInfo->IF_DEF_ScaleLCD == 0 ) || ( ( pVBInfo->IF_DEF_ScaleLCD == 1 ) && ( !( pVBInfo->LCDInfo & EnableScalingLCD ) ) ) ) + { + tempbx = 0 ; + + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) + { + LCDPtr = ( XGI_LVDSCRT1HDataStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + + for( i = 0 ; i < 8 ; i++ ) + pVBInfo->TimingH[ 0 ].data[ i ] = LCDPtr[ 0 ].Reg[ i ] ; + } + + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + CH7007TV_TimingHPtr = ( XGI_CH7007TV_TimingHStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + + for( i = 0 ; i < 8 ; i++ ) + pVBInfo->TimingH[ 0 ].data[ i ] = CH7007TV_TimingHPtr[ 0 ].data[ i ] ; + } + } + + /* if ( pVBInfo->IF_DEF_CH7017 == 1 ) + { + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + TVPtr = ( XGI330_CHTVDataStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + } */ + + XGI_SetCRT1Timing_H(pVBInfo,HwDeviceExtension) ; + + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , CH7007TV_TimingHPtr[ 0 ].data[ 8 ] ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2F , CH7007TV_TimingHPtr[ 0 ].data[ 9 ] ) ; + } + + tempbx = 1 ; + + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) + { + LCDPtr1 = ( XGI_LVDSCRT1VDataStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + for( i = 0 ; i < 7 ; i++ ) + pVBInfo->TimingV[ 0 ].data[ i ] = LCDPtr1[ 0 ].Reg[ i ] ; + } + + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + CH7007TV_TimingVPtr = ( XGI_CH7007TV_TimingVStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + + for( i = 0 ; i < 7 ; i++ ) + pVBInfo->TimingV[ 0 ].data[ i ] = CH7007TV_TimingVPtr[ 0 ].data[ i ] ; + } + } + /* if ( pVBInfo->IF_DEF_CH7017 == 1 ) + { + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + TVPtr = ( XGI330_CHTVDataStruct *)XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + } */ + + XGI_SetCRT1Timing_V( ModeIdIndex , ModeNo , pVBInfo) ; + + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x33 , ~0x01 , CH7007TV_TimingVPtr[ 0 ].data[ 7 ]&0x01 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , CH7007TV_TimingVPtr[ 0 ].data[8 ] ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x3F , CH7007TV_TimingVPtr[ 0 ].data[9 ] ) ; + + } + } +} + + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetLVDSRegs */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetLVDSRegs( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempbx , tempax , tempcx , tempdx , push1 , push2 , modeflag ; + unsigned long temp , temp1 , temp2 , temp3 , push3 ; + XGI330_LCDDataDesStruct *LCDPtr = NULL ; + XGI330_LCDDataDesStruct2 *LCDPtr1 = NULL ; + + if ( ModeNo > 0x13 ) + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + else + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + + if ( !( pVBInfo->SetFlag & Win9xDOSMode ) ) + { + if ( ( pVBInfo->IF_DEF_CH7017 == 0 ) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) ) + { + if ( pVBInfo->IF_DEF_OEMUtil == 1 ) + { + tempbx = 8 ; + LCDPtr = ( XGI330_LCDDataDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + } + + if ( ( pVBInfo->IF_DEF_OEMUtil == 0 ) || ( LCDPtr == 0 ) ) + { + tempbx = 3 ; + if ( pVBInfo->LCDInfo & EnableScalingLCD ) + LCDPtr1 = ( XGI330_LCDDataDesStruct2 * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + else + LCDPtr = ( XGI330_LCDDataDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + } + + XGI_GetLCDSync( &tempax , &tempbx ,pVBInfo) ; + push1 = tempbx ; + push2 = tempax ; + + /* GetLCDResInfo */ + if ( ( pVBInfo->LCDResInfo == Panel1024x768 ) || ( pVBInfo->LCDResInfo == Panel1024x768x75 ) ) + { + tempax = 1024 ; + tempbx = 768 ; + } + else if ( ( pVBInfo->LCDResInfo == Panel1280x1024 ) || ( pVBInfo->LCDResInfo == Panel1280x1024x75 ) ) + { + tempax = 1280 ; + tempbx = 1024 ; + } + else if ( pVBInfo->LCDResInfo == Panel1400x1050 ) + { + tempax = 1400 ; + tempbx = 1050 ; + } + else + { + tempax = 1600 ; + tempbx = 1200 ; + } + + if ( pVBInfo->LCDInfo & SetLCDtoNonExpanding ) + { + pVBInfo->HDE=tempax; + pVBInfo->VDE=tempbx; + pVBInfo->VGAHDE=tempax; + pVBInfo->VGAVDE=tempbx; + } + + if ( ( pVBInfo->IF_DEF_ScaleLCD == 1 ) && ( pVBInfo->LCDInfo & EnableScalingLCD ) ) + { + tempax=pVBInfo->HDE; + tempbx=pVBInfo->VDE; + } + + tempax = pVBInfo->HT ; + + if ( pVBInfo->LCDInfo & EnableScalingLCD ) + tempbx = LCDPtr1->LCDHDES ; + else + tempbx = LCDPtr->LCDHDES ; + + tempcx = pVBInfo->HDE ; + tempbx = tempbx & 0x0fff ; + tempcx += tempbx ; + + if ( tempcx >= tempax ) + tempcx -= tempax ; + + XGINew_SetReg1( pVBInfo->Part1Port , 0x1A , tempbx & 0x07 ) ; + + tempcx = tempcx >> 3 ; + tempbx = tempbx >> 3 ; + + XGINew_SetReg1( pVBInfo->Part1Port , 0x16 , ( USHORT )( tempbx & 0xff ) ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x17 , ( USHORT )( tempcx & 0xff ) ) ; + + tempax = pVBInfo->HT ; + + if ( pVBInfo->LCDInfo & EnableScalingLCD ) + tempbx = LCDPtr1->LCDHRS ; + else + tempbx = LCDPtr->LCDHRS ; + + tempcx = push2 ; + + if ( pVBInfo->LCDInfo & EnableScalingLCD ) + tempcx = LCDPtr1->LCDHSync ; + + tempcx += tempbx ; + + if ( tempcx >= tempax ) + tempcx -= tempax ; + + tempax = tempbx & 0x07 ; + tempax = tempax >> 5 ; + tempcx = tempcx >> 3 ; + tempbx = tempbx >> 3 ; + + tempcx &= 0x1f ; + tempax |= tempcx ; + + XGINew_SetReg1( pVBInfo->Part1Port , 0x15 , tempax ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x14 , ( USHORT )( tempbx & 0xff ) ) ; + + tempax = pVBInfo->VT ; + if ( pVBInfo->LCDInfo & EnableScalingLCD ) + tempbx = LCDPtr1->LCDVDES ; + else + tempbx = LCDPtr->LCDVDES ; + tempcx = pVBInfo->VDE ; + + tempbx = tempbx & 0x0fff ; + tempcx += tempbx ; + if ( tempcx >= tempax ) + tempcx -= tempax ; + + XGINew_SetReg1( pVBInfo->Part1Port , 0x1b , ( USHORT )( tempbx & 0xff ) ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x1c , ( USHORT )( tempcx & 0xff ) ) ; + + tempbx = ( tempbx >> 8 ) & 0x07 ; + tempcx = ( tempcx >> 8 ) & 0x07 ; + + XGINew_SetReg1( pVBInfo->Part1Port , 0x1d , ( USHORT )( ( tempcx << 3 ) | tempbx ) ) ; + + tempax = pVBInfo->VT ; + if ( pVBInfo->LCDInfo & EnableScalingLCD ) + tempbx = LCDPtr1->LCDVRS ; + else + tempbx = LCDPtr->LCDVRS ; + + /* tempbx = tempbx >> 4 ; */ + tempcx = push1 ; + + if ( pVBInfo->LCDInfo & EnableScalingLCD ) + tempcx = LCDPtr1->LCDVSync ; + + tempcx += tempbx ; + if ( tempcx >= tempax ) + tempcx -= tempax ; + + XGINew_SetReg1( pVBInfo->Part1Port , 0x18 , ( USHORT )( tempbx & 0xff ) ) ; + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , ~0x0f , ( USHORT )( tempcx & 0x0f ) ) ; + + tempax = ( ( tempbx >> 8 ) & 0x07 ) << 3 ; + + tempbx = pVBInfo->VGAVDE ; + if ( tempbx != pVBInfo->VDE ) + tempax |= 0x40 ; + + if ( pVBInfo->LCDInfo & EnableLVDSDDA ) + tempax |= 0x40 ; + + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1a , 0x07 , tempax ) ; + + tempcx = pVBInfo->VGAVT ; + tempbx = pVBInfo->VDE ; + tempax = pVBInfo->VGAVDE ; + tempcx -= tempax ; + + temp = tempax ; /* 0430 ylshieh */ + temp1 = ( temp << 18 ) / tempbx ; + + tempdx = ( USHORT )( ( temp << 18 ) % tempbx ) ; + + if ( tempdx != 0 ) + temp1 += 1 ; + + temp2 = temp1 ; + push3 = temp2 ; + + XGINew_SetReg1( pVBInfo->Part1Port , 0x37 , ( USHORT )( temp2 & 0xff ) ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x36 , ( USHORT )( ( temp2 >> 8 ) & 0xff ) ) ; + + tempbx = ( USHORT )( temp2 >> 16 ) ; + tempax = tempbx & 0x03 ; + + tempbx = pVBInfo->VGAVDE ; + if ( tempbx == pVBInfo->VDE ) + tempax |= 0x04 ; + + XGINew_SetReg1( pVBInfo->Part1Port , 0x35 , tempax ) ; + + if ( pVBInfo->VBType & VB_XGI301C ) + { + temp2 = push3 ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x3c , ( USHORT )( temp2 & 0xff ) ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x3b , ( USHORT )( ( temp2 >> 8 ) & 0xff ) ) ; + tempbx = ( USHORT )( temp2 >> 16 ) ; + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x3a , ~0xc0 , ( USHORT )( ( tempbx & 0xff ) << 6 ) ) ; + + tempcx = pVBInfo->VGAVDE ; + if ( tempcx == pVBInfo->VDE ) + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x30 , ~0x0c , 0x00 ) ; + else + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x30 , ~0x0c , 0x08 ) ; + } + + tempcx = pVBInfo->VGAHDE ; + tempbx = pVBInfo->HDE ; + + temp1 = tempcx << 16 ; + + tempax = ( USHORT )( temp1 / tempbx ) ; + + if ( ( tempbx & 0xffff ) == ( tempcx & 0xffff ) ) + tempax = 65535 ; + + temp3 = tempax ; + temp1 = pVBInfo->VGAHDE << 16 ; + + temp1 /= temp3 ; + temp3 = temp3 << 16 ; + temp1 -= 1 ; + + temp3 = ( temp3 & 0xffff0000 ) + ( temp1 & 0xffff ) ; + + tempax = ( USHORT )( temp3 & 0xff ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x1f , tempax ) ; + + temp1 = pVBInfo->VGAVDE << 18 ; + temp1 = temp1 / push3 ; + tempbx = ( USHORT )( temp1 & 0xffff ) ; + + if ( pVBInfo->LCDResInfo == Panel1024x768 ) + tempbx -= 1 ; + + tempax = ( ( tempbx >> 8 ) & 0xff ) << 3 ; + tempax |= ( USHORT )( ( temp3 >> 8 ) & 0x07 ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x20 , ( USHORT )( tempax & 0xff ) ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x21 , ( USHORT )( tempbx & 0xff ) ) ; + + temp3 = temp3 >> 16 ; + + if ( modeflag & HalfDCLK ) + temp3 = temp3 >> 1 ; + + XGINew_SetReg1(pVBInfo->Part1Port , 0x22 , ( USHORT )( ( temp3 >> 8 ) & 0xff ) ) ; + XGINew_SetReg1(pVBInfo->Part1Port , 0x23 , ( USHORT )( temp3 & 0xff ) ) ; + } + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT2ECLK */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT2ECLK( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR di_0 , di_1 , tempal ; + int i ; + + tempal = XGI_GetVCLKPtr( RefreshRateTableIndex , ModeNo , ModeIdIndex, pVBInfo ) ; + XGI_GetVCLKLen( tempal , &di_0 , &di_1, pVBInfo ) ; + XGI_GetLCDVCLKPtr( &di_0 , &di_1, pVBInfo ) ; + + for( i = 0 ; i < 4 ; i++ ) + { + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x31 , ~0x30 , ( USHORT )( 0x10 * i ) ) ; + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x2b , di_0 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2c , di_1 ) ; + } + else if ( ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) && ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) ) + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x2e , di_0 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2f , di_1 ) ; + } + else + { + XGINew_SetReg1( pVBInfo->P3c4 , 0x2b , di_0 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2c , di_1 ) ; + } + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_UpdateModeInfo */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_UpdateModeInfo( PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempcl , + tempch , + temp , + tempbl , + tempax ; + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + tempcl = 0 ; + tempch = 0 ; + temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x01 ) ; + + if ( !( temp & 0x20 ) ) + { + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ; + if ( temp & 0x80 ) + { + if ( ( HwDeviceExtension->jChipType >= XG20 ) || ( HwDeviceExtension->jChipType >= XG40 ) ) + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) ; + else + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x63 ) ; + + if ( !( temp & 0x40 ) ) + tempcl |= ActiveCRT1 ; + } + } + + temp = XGINew_GetReg1( pVBInfo->Part1Port , 0x2e ) ; + temp &= 0x0f ; + + if ( !( temp == 0x08 ) ) + { + tempax = XGINew_GetReg1( pVBInfo->Part1Port , 0x13 ) ; /* Check ChannelA by Part1_13 [2003/10/03] */ + if ( tempax & 0x04 ) + tempcl = tempcl | ActiveLCD ; + + temp &= 0x05 ; + + if ( !( tempcl & ActiveLCD ) ) + if ( temp == 0x01 ) + tempcl |= ActiveCRT2 ; + + if ( temp == 0x04 ) + tempcl |= ActiveLCD ; + + if ( temp == 0x05 ) + { + temp = XGINew_GetReg1( pVBInfo->Part2Port , 0x00 ) ; + + if( !( temp & 0x08 ) ) + tempch |= ActiveAVideo ; + + if ( !( temp & 0x04 ) ) + tempch |= ActiveSVideo ; + + if ( temp & 0x02 ) + tempch |= ActiveSCART ; + + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + if ( temp & 0x01 ) + tempch |= ActiveHiTV ; + } + + if ( pVBInfo->VBInfo & SetCRT2ToYPbPr ) + { + temp = XGINew_GetReg1( pVBInfo->Part2Port , 0x4d ) ; + + if ( temp & 0x10 ) + tempch |= ActiveYPbPr ; + } + + if ( tempch != 0 ) + tempcl |= ActiveTV ; + } + } + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x3d ) ; + if ( tempcl & ActiveLCD ) + { + if ( ( pVBInfo->SetFlag & ReserveTVOption ) ) + { + if ( temp & ActiveTV ) + tempcl |= ActiveTV ; + } + } + temp = tempcl ; + tempbl = ~ModeSwitchStatus ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x3d , tempbl , temp ) ; + + if ( !( pVBInfo->SetFlag & ReserveTVOption ) ) + XGINew_SetReg1( pVBInfo->P3d4 , 0x3e , tempch ) ; + } + else + { + return ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetVGAType */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetVGAType( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) +{ + /* + if ( HwDeviceExtension->jChipType >= XG20 ) + { + pVBInfo->Set_VGAType = XG20; + } + else if ( HwDeviceExtension->jChipType >= XG40 ) + { + pVBInfo->Set_VGAType = VGA_XGI340 ; + } + */ + pVBInfo->Set_VGAType = HwDeviceExtension->jChipType; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetVBType */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetVBType(PVB_DEVICE_INFO pVBInfo) +{ + USHORT flag , tempbx , tempah ; + + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + pVBInfo->VBType = VB_CH7007 ; + return; + } + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + tempbx = VB_XGI302B ; + flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x00 ) ; + if ( flag != 0x02 ) + { + tempbx = VB_XGI301 ; + flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x01 ) ; + if ( flag >= 0xB0 ) + { + tempbx = VB_XGI301B ; + if ( flag >= 0xC0 ) + { + tempbx = VB_XGI301C ; + if ( flag >= 0xD0 ) + { + tempbx = VB_XGI301LV ; + if ( flag >= 0xE0 ) + { + tempbx = VB_XGI302LV ; + tempah = XGINew_GetReg1( pVBInfo->Part4Port , 0x39 ) ; + if ( tempah != 0xFF ) + tempbx = VB_XGI301C ; + } + } + } + + if ( tempbx & ( VB_XGI301B | VB_XGI302B ) ) + { + flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x23 ) ; + + if ( !( flag & 0x02 ) ) + tempbx = tempbx | VB_NoLCD ; + } + } + } + pVBInfo->VBType = tempbx ; + } +/* + else if ( pVBInfo->IF_DEF_CH7017 == 1 ) + pVBInfo->VBType = VB_CH7017 ; + else //LVDS + pVBInfo->VBType = VB_LVDS_NS ; +*/ + +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetVBInfo */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetVBInfo( USHORT ModeNo , USHORT ModeIdIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempax , + push , + tempbx , + temp , + modeflag ; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + } + + pVBInfo->SetFlag = 0 ; + pVBInfo->ModeType = modeflag & ModeInfoFlag ; + tempbx = 0 ; + + if ( pVBInfo->VBType & 0xFFFF ) + { + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x30 ) ; /* Check Display Device */ + tempbx = tempbx | temp ; + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x31 ) ; + push = temp ; + push = push << 8 ; + tempax = temp << 8 ; + tempbx = tempbx | tempax ; + temp = ( SetCRT2ToDualEdge | SetCRT2ToYPbPr | SetCRT2ToLCDA | SetInSlaveMode | DisableCRT2Display ) ; + temp = 0xFFFF ^ temp ; + tempbx &= temp ; + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ; + + if ( pVBInfo->IF_DEF_LCDA == 1 ) + { + + if ( ( pVBInfo->Set_VGAType >= XG20 ) || ( pVBInfo->Set_VGAType >= XG40 )) + { + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + /* if ( ( pVBInfo->VBType & VB_XGI302B ) || ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) ) */ + if ( pVBInfo->VBType & ( VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + if ( temp & EnableDualEdge ) + { + tempbx |= SetCRT2ToDualEdge ; + + if ( temp & SetToLCDA ) + tempbx |= SetCRT2ToLCDA ; + } + } + } + else if ( pVBInfo->IF_DEF_CH7017 == 1 ) + { + if ( pVBInfo->VBType & VB_CH7017 ) + { + if ( temp & EnableDualEdge ) + { + tempbx |= SetCRT2ToDualEdge ; + + if ( temp & SetToLCDA ) + tempbx |= SetCRT2ToLCDA ; + } + } + } + } + } + + if ( pVBInfo->IF_DEF_YPbPr == 1 ) + { + if ( ( ( pVBInfo->IF_DEF_LVDS == 0 ) && ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) ) ) + || ( ( pVBInfo->IF_DEF_CH7017 == 1 ) && ( pVBInfo->VBType&VB_CH7017 ) ) || ( (pVBInfo->IF_DEF_CH7007 == 1) && (pVBInfo->VBType&VB_CH7007) ) ) /* [Billy] 07/05/04 */ + { + if ( temp & SetYPbPr ) /* temp = CR38 */ + { + if ( pVBInfo->IF_DEF_HiVision == 1 ) + { + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ; /* shampoo add for new scratch */ + temp &= YPbPrMode ; + tempbx |= SetCRT2ToHiVisionTV ; + + if ( temp != YPbPrMode1080i ) { + tempbx &= ( ~SetCRT2ToHiVisionTV ) ; + tempbx |= SetCRT2ToYPbPr ; } + } + + /* tempbx |= SetCRT2ToYPbPr ; */ + } + } + } + + tempax = push ; /* restore CR31 */ + + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + if ( pVBInfo->IF_DEF_YPbPr == 1 ) + { + if ( pVBInfo->IF_DEF_HiVision == 1 ) + temp = 0x09FC ; + else + temp = 0x097C ; + } + else + { + if ( pVBInfo->IF_DEF_HiVision == 1 ) + temp = 0x01FC ; + else + temp = 0x017C ; + } + } + else /* 3nd party chip */ + { + if ( pVBInfo->IF_DEF_CH7017 == 1 ) + temp = ( SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) ; + else if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 07/05/03 */ + { + temp = SetCRT2ToTV ; + } + else + temp = SetCRT2ToLCD ; + } + + if ( !( tempbx & temp ) ) + { + tempax |= DisableCRT2Display ; + tempbx = 0 ; + } + + if ( pVBInfo->IF_DEF_LCDA == 1 ) /* Select Display Device */ + { + if ( !( pVBInfo->VBType & VB_NoLCD ) ) + { + if ( tempbx & SetCRT2ToLCDA ) + { + if ( tempbx & SetSimuScanMode ) + tempbx &= ( ~( SetCRT2ToLCD | SetCRT2ToRAMDAC | SwitchToCRT2 ) ) ; + else + tempbx &= ( ~( SetCRT2ToLCD | SetCRT2ToRAMDAC | SetCRT2ToTV | SwitchToCRT2 ) ) ; + } + } + } + + /* shampoo add */ + if ( !( tempbx & ( SwitchToCRT2 | SetSimuScanMode ) ) ) /* for driver abnormal */ + { + if ( pVBInfo->IF_DEF_CRT2Monitor == 1 ) + { + if ( tempbx & SetCRT2ToRAMDAC ) + { + tempbx &= ( 0xFF00 | SetCRT2ToRAMDAC | SwitchToCRT2 | SetSimuScanMode ) ; + tempbx &= ( 0x00FF | ( ~SetCRT2ToYPbPr ) ) ; + } + } + else + tempbx &= ( ~( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) ; + } + + if ( !( pVBInfo->VBType & VB_NoLCD ) ) + { + if ( tempbx & SetCRT2ToLCD ) + { + tempbx &= ( 0xFF00 | SetCRT2ToLCD | SwitchToCRT2 | SetSimuScanMode ) ; + tempbx &= ( 0x00FF | ( ~SetCRT2ToYPbPr ) ) ; + } + } + + if ( tempbx & SetCRT2ToSCART ) + { + tempbx &= ( 0xFF00 | SetCRT2ToSCART | SwitchToCRT2 | SetSimuScanMode ) ; + tempbx &= ( 0x00FF | ( ~SetCRT2ToYPbPr ) ) ; + } + + if ( pVBInfo->IF_DEF_YPbPr == 1 ) + { + if ( tempbx & SetCRT2ToYPbPr ) + tempbx &= ( 0xFF00 | SwitchToCRT2 | SetSimuScanMode ) ; + } + + if ( pVBInfo->IF_DEF_HiVision == 1 ) + { + if ( tempbx & SetCRT2ToHiVisionTV ) + tempbx &= ( 0xFF00 | SetCRT2ToHiVisionTV | SwitchToCRT2 | SetSimuScanMode ) ; + } + + if ( tempax & DisableCRT2Display ) /* Set Display Device Info */ + { + if ( !( tempbx & ( SwitchToCRT2 | SetSimuScanMode ) ) ) + tempbx = DisableCRT2Display ; + } + + if ( !( tempbx & DisableCRT2Display ) ) + { + if ( ( !( tempbx & DriverMode ) ) || ( !( modeflag & CRT2Mode ) ) ) + { + if ( pVBInfo->IF_DEF_LCDA == 1 ) + { + if ( !( tempbx & SetCRT2ToLCDA ) ) + tempbx |= ( SetInSlaveMode | SetSimuScanMode ) ; + } + + if ( pVBInfo->IF_DEF_VideoCapture == 1 ) + { + if ( ( ( HwDeviceExtension->jChipType == XG40 ) && ( pVBInfo->Set_VGAType == XG40 ) ) + || ( ( HwDeviceExtension->jChipType == XG41 ) && ( pVBInfo->Set_VGAType == XG41 ) ) + || ( ( HwDeviceExtension->jChipType == XG42 ) && ( pVBInfo->Set_VGAType == XG42 ) ) + || ( ( HwDeviceExtension->jChipType == XG45 ) && ( pVBInfo->Set_VGAType == XG45 ) ) ) + { + if ( ModeNo <= 13 ) + { + if ( !( tempbx & SetCRT2ToRAMDAC ) ) /*CRT2 not need to support*/ + { + tempbx &= ( 0x00FF | ( ~SetInSlaveMode ) ) ; + pVBInfo->SetFlag |= EnableVCMode ; + } + } + } + } + } + + /*LCD+TV can't support in slave mode (Force LCDA+TV->LCDB)*/ + if ( ( tempbx & SetInSlaveMode ) && ( tempbx & SetCRT2ToLCDA ) ) + { + tempbx ^= ( SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToDualEdge ) ; + pVBInfo->SetFlag |= ReserveTVOption ; + } + } + } + + pVBInfo->VBInfo = tempbx ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetTVInfo */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetTVInfo( USHORT ModeNo , USHORT ModeIdIndex ,PVB_DEVICE_INFO pVBInfo ) +{ + USHORT temp , + tempbx = 0 , + resinfo = 0 , + modeflag , + index1 ; + + tempbx = 0 ; + resinfo = 0 ; + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ModeFlag */ + resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; /* si+St_ResInfo */ + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo */ + } + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ; + tempbx = temp; + if ( tempbx & SetPALTV ) + { + tempbx &= ( SetCHTVOverScan | SetPALMTV | SetPALNTV | SetPALTV ) ; + if ( tempbx & SetPALMTV ) + tempbx &= ~SetPALTV ; /* set to NTSC if PAL-M */ + } + else + tempbx &= ( SetCHTVOverScan | SetNTSCJ | SetPALTV ) ; +/* + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + index1 = XGINew_GetReg1( pVBInfo->P3d4 , 0x38 ) ; //PAL-M/PAL-N Info + temp2 = ( index1 & 0xC0 ) >> 5 ; //00:PAL, 01:PAL-M, 10:PAL-N + tempbx |= temp2 ; + if ( temp2 & 0x02 ) //PAL-M + tempbx &= ( ~SetPALTV ) ; + } +*/ + } + + if ( pVBInfo->IF_DEF_CH7017 == 1 ) + { + tempbx = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ; + + if ( tempbx & TVOverScan ) + tempbx |= SetCHTVOverScan ; + } + + if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 07/05/04 */ + { + tempbx = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ; + + if ( tempbx & TVOverScan ) + { + tempbx |= SetCHTVOverScan ; + } + } + + + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + if ( pVBInfo->VBInfo & SetCRT2ToSCART ) + tempbx |= SetPALTV ; + } + + if ( pVBInfo->IF_DEF_YPbPr == 1 ) + { + if ( pVBInfo->VBInfo & SetCRT2ToYPbPr ) + { + index1 = XGINew_GetReg1( pVBInfo->P3d4 , 0x35 ) ; + index1 &= YPbPrMode ; + + if ( index1 == YPbPrMode525i ) + tempbx |= SetYPbPrMode525i ; + + if ( index1 == YPbPrMode525p ) + tempbx = tempbx | SetYPbPrMode525p; + if ( index1 == YPbPrMode750p) + tempbx = tempbx | SetYPbPrMode750p; + } + } + + if ( pVBInfo->IF_DEF_HiVision == 1 ) + { + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + tempbx = tempbx | SetYPbPrMode1080i | SetPALTV ; + } + } + + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { /* shampoo */ + if ( ( pVBInfo->VBInfo & SetInSlaveMode ) && ( !( pVBInfo->VBInfo & SetNotSimuMode ) ) ) + tempbx |= TVSimuMode ; + + if ( !( tempbx & SetPALTV ) && ( modeflag > 13 ) && ( resinfo == 8 ) ) /* NTSC 1024x768, */ + tempbx |= NTSC1024x768 ; + + tempbx |= RPLLDIV2XO ; + + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + if ( pVBInfo->VBInfo & SetInSlaveMode ) + tempbx &=( ~RPLLDIV2XO ) ; + } + else + { + if ( tempbx & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) + tempbx &= ( ~RPLLDIV2XO ) ; + else if ( !( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) ) + { + if ( tempbx & TVSimuMode ) + tempbx &= ( ~RPLLDIV2XO ) ; + } + } + } + } + pVBInfo->TVInfo = tempbx ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetLCDInfo */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGI_GetLCDInfo( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo) +{ + USHORT temp , + tempax , + tempbx , + modeflag , + resinfo = 0 , + LCDIdIndex ; + + pVBInfo->LCDResInfo = 0 ; + pVBInfo->LCDTypeInfo = 0 ; + pVBInfo->LCDInfo = 0 ; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ModeFlag // */ + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; /* si+Ext_ResInfo// */ + } + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ; /* Get LCD Res.Info */ + tempbx = temp & 0x0F ; + + if ( tempbx == 0 ) + tempbx = Panel1024x768 ; /* default */ + + /* LCD75 [2003/8/22] Vicent */ + if ( ( tempbx == Panel1024x768 ) || ( tempbx == Panel1280x1024 ) ) + { + if ( pVBInfo->VBInfo & DriverMode ) + { + tempax = XGINew_GetReg1( pVBInfo->P3d4 , 0x33 ) ; + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + tempax &= 0x0F ; + else + tempax = tempax >> 4 ; + + if ( ( resinfo == 6 ) || ( resinfo == 9 ) ) + { + if ( tempax >= 3 ) + tempbx |= PanelRef75Hz ; + } + else if ( ( resinfo == 7 ) || ( resinfo == 8 ) ) + { + if ( tempax >= 4 ) + tempbx |= PanelRef75Hz ; + } + } + } + + pVBInfo->LCDResInfo = tempbx ; + + /* End of LCD75 */ + + if( pVBInfo->IF_DEF_OEMUtil == 1 ) + { + pVBInfo->LCDTypeInfo = ( temp & 0xf0 ) >> 4 ; + } + + if ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) ) + { + return 0; + } + + tempbx = 0 ; + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ; + + temp &= ( ScalingLCD | LCDNonExpanding | LCDSyncBit | SetPWDEnable ) ; + + if ( ( pVBInfo->IF_DEF_ScaleLCD == 1 ) && ( temp & LCDNonExpanding ) ) + temp &= ~EnableScalingLCD ; + + tempbx |= temp ; + + LCDIdIndex = XGI_GetLCDCapPtr1(pVBInfo) ; + + tempax = pVBInfo->LCDCapList[ LCDIdIndex ].LCD_Capability ; + + if ( pVBInfo->IF_DEF_LVDS == 0 ) /* shampoo */ + { + if ( ( ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) ) && ( tempax & LCDDualLink ) ) + { + tempbx |= SetLCDDualLink ; + } + } + + if ( pVBInfo->IF_DEF_CH7017 == 1 ) + { + if ( tempax & LCDDualLink ) + { + tempbx |= SetLCDDualLink ; + } + } + + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + if ( ( pVBInfo->LCDResInfo == Panel1400x1050 ) && ( pVBInfo->VBInfo & SetCRT2ToLCD ) && ( ModeNo > 0x13 ) && ( resinfo == 9 ) && ( !( tempbx & EnableScalingLCD ) ) ) + tempbx |= SetLCDtoNonExpanding ; /* set to center in 1280x1024 LCDB for Panel1400x1050 */ + } + +/* + if ( tempax & LCDBToA ) + { + tempbx |= SetLCDBToA ; + } +*/ + + if ( pVBInfo->IF_DEF_ExpLink == 1 ) + { + if ( modeflag & HalfDCLK ) + { + /* if ( !( pVBInfo->LCDInfo&LCDNonExpanding ) ) */ + if ( !( tempbx & SetLCDtoNonExpanding ) ) + { + tempbx |= EnableLVDSDDA ; + } + else + { + if ( ModeNo > 0x13 ) + { + if ( pVBInfo->LCDResInfo == Panel1024x768 ) + { + if ( resinfo == 4 ) + { /* 512x384 */ + tempbx |= EnableLVDSDDA ; + } + } + } + } + } + } + + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + if ( pVBInfo->VBInfo & SetNotSimuMode ) + { + tempbx |= LCDVESATiming ; + } + } + else + { + tempbx |= LCDVESATiming ; + } + + pVBInfo->LCDInfo = tempbx ; + + if ( pVBInfo->IF_DEF_PWD == 1 ) + { + if ( pVBInfo->LCDInfo & SetPWDEnable ) + { + if ( ( pVBInfo->VBType & VB_XGI302LV ) || ( pVBInfo->VBType & VB_XGI301C ) ) + { + if ( !( tempax & PWDEnable ) ) + { + pVBInfo->LCDInfo &= ~SetPWDEnable ; + } + } + } + } + + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + if ( tempax & ( LockLCDBToA | StLCDBToA ) ) + { + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + if ( !( tempax & LockLCDBToA ) ) + { + if ( ModeNo <= 0x13 ) + { + pVBInfo->VBInfo &= ~( SetSimuScanMode | SetInSlaveMode | SetCRT2ToLCD ) ; + pVBInfo->VBInfo |= SetCRT2ToLCDA | SetCRT2ToDualEdge ; + } + } + } + } + } + +/* + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + if ( tempax & ( LockLCDBToA | StLCDBToA ) ) + { + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + if ( !( ( !( tempax & LockLCDBToA ) ) && ( ModeNo > 0x13 ) ) ) + { + pVBInfo->VBInfo&=~(SetSimuScanMode|SetInSlaveMode|SetCRT2ToLCD); + pVBInfo->VBInfo|=SetCRT2ToLCDA|SetCRT2ToDualEdge; + } + } + } + } +*/ + + return( 1 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SearchModeID */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGI_SearchModeID( USHORT ModeNo , USHORT *ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) +{ + +#ifdef TC + + if ( ModeNo <= 5 ) + ModeNo |= 1 ; + + if ( ModeNo <= 0x13 ) + { + /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->SModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */ + for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ ) + { + if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo ) + break ; + if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF ) + return( FALSE ) ; + } + + VGA_INFO = ( PUCHAR )MK_FP( 0 , 0x489 ) ; + + if ( ModeNo == 0x07 ) + { + if ( ( *VGA_INFO & 0x10 ) != 0 ) + ( *ModeIdIndex )++ ; /* 400 lines */ + /* else 350 lines */ + } + + if ( ModeNo <= 3 ) + { + if ( ( *VGA_INFO & 0x80 ) == 0 ) + { + ( *ModeIdIndex )++ ; + if ( ( *VGA_INFO & 0x10 ) != 0 ) + ( *ModeIdIndex )++ ; /* 400 lines */ + /* else 350 lines */ + } + /* else 200 lines */ + } + } + else + { + /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->EModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */ + for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ ) + { + if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo ) + break ; + if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF ) + return( FALSE ) ; + } + } + + +#endif + +#ifdef WIN2000 + + if ( ModeNo <= 5 ) + ModeNo |= 1 ; + if ( ModeNo <= 0x13 ) + { + /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->SModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */ + for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ ) + { + if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo ) + break ; + if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF ) + return( FALSE ) ; + } + + if ( ModeNo == 0x07 ) + ( *ModeIdIndex )++ ; /* 400 lines */ + + if ( ModeNo <=3 ) + ( *ModeIdIndex ) += 2 ; /* 400 lines */ + /* else 350 lines */ + } + else + { + /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->EModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */ + for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ ) + { + if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo ) + break ; + if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF ) + return( FALSE ) ; + } + } + +#endif + +#ifdef LINUX /* chiawen for linux solution */ + + if ( ModeNo <= 5 ) + ModeNo |= 1 ; + if ( ModeNo <= 0x13 ) + { + /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->SModeIDTable)/sizeof(XGI_StStruct);(*ModeIdIndex)++) */ + for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ ) + { + if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == ModeNo ) + break ; + if ( pVBInfo->SModeIDTable[ *ModeIdIndex ].St_ModeID == 0xFF ) + return( FALSE ) ; + } + + if ( ModeNo == 0x07 ) + ( *ModeIdIndex )++ ; /* 400 lines */ + + if ( ModeNo <= 3 ) + ( *ModeIdIndex ) += 2 ; /* 400 lines */ + /* else 350 lines */ + } + else + { + /* for (*ModeIdIndex=0;*ModeIdIndex<sizeof(pVBInfo->EModeIDTable)/sizeof(XGI_ExtStruct);(*ModeIdIndex)++) */ + for( *ModeIdIndex = 0 ; ; ( *ModeIdIndex )++ ) + { + if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == ModeNo ) + break ; + if ( pVBInfo->EModeIDTable[ *ModeIdIndex ].Ext_ModeID == 0xFF ) + return( FALSE ) ; + } + } + +#endif + + return( TRUE ) ; +} + + + + +/* win2000 MM adapter not support standard mode! */ + +/* --------------------------------------------------------------------- */ +/* Function : */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo) +{ + USHORT memorysize , + modeflag , + temp , + temp1 , + tmp ; + +/* if ( ( HwDeviceExtension->jChipType == XGI_650 ) || + ( HwDeviceExtension->jChipType == XGI_650M ) ) + { + return( TRUE ) ; + } */ + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + } + else { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + } + + /* ModeType = modeflag&ModeInfoFlag ; // Get mode type */ + + memorysize = modeflag & MemoryInfoFlag ; + memorysize = memorysize > MemorySizeShift ; + memorysize++ ; /* Get memory size */ + + temp = XGINew_GetReg1( pVBInfo->P3c4 , 0x14 ) ; /* Get DRAM Size */ + tmp = temp ; + + if ( HwDeviceExtension->jChipType == XG40 ) + { + temp = 1 << ( ( temp & 0x0F0 ) >> 4 ) ; /* memory size per channel SR14[7:4] */ + if ( ( tmp & 0x0c ) == 0x0C ) /* Qual channels */ + { + temp <<= 2 ; + } + else if ( ( tmp & 0x0c ) == 0x08 ) /* Dual channels */ + { + temp <<= 1 ; + } + } + else if ( HwDeviceExtension->jChipType == XG42 ) + { + temp = 1 << ( ( temp & 0x0F0 ) >> 4 ) ; /* memory size per channel SR14[7:4] */ + if ( ( tmp & 0x04 ) == 0x04 ) /* Dual channels */ + { + temp <<= 1 ; + } + } + else if ( HwDeviceExtension->jChipType == XG45 ) + { + temp = 1 << ( ( temp & 0x0F0 ) >> 4 ) ; /* memory size per channel SR14[7:4] */ + if ( ( tmp & 0x0c ) == 0x0C ) /* Qual channels */ + { + temp <<= 2 ; + } + else if ( ( tmp & 0x0c ) == 0x08 ) /* triple channels */ + { + temp1 = temp ; + temp <<= 1 ; + temp += temp1 ; + } + else if ( ( tmp & 0x0c ) == 0x04 ) /* Dual channels */ + { + temp <<= 1 ; + } + } + if ( temp < memorysize ) + return( FALSE ) ; + else + return( TRUE ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_IsLowResolution */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +/*void XGINew_IsLowResolution( USHORT ModeNo , USHORT ModeIdIndex, BOOLEAN XGINew_CheckMemorySize(PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO pVBInfo) +{ + USHORT data ; + USHORT ModeFlag ; + + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x0F ) ; + data &= 0x7F ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x0F , data ) ; + + if ( ModeNo > 0x13 ) + { + ModeFlag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + if ( ( ModeFlag & HalfDCLK ) && ( ModeFlag & DoubleScanMode ) ) + { + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x0F ) ; + data |= 0x80 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x0F , data ) ; + data = XGINew_GetReg1( pVBInfo->P3c4 , 0x01 ) ; + data &= 0xF7 ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , data ) ; + } + } +} + +*/ + +/* --------------------------------------------------------------------- */ +/* Function : XGI_DisplayOn */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_DisplayOn( PXGI_HW_DEVICE_INFO pXGIHWDE , PVB_DEVICE_INFO pVBInfo ) +{ + + XGINew_SetRegANDOR(pVBInfo->P3c4,0x01,0xDF,0x00); + if ( pXGIHWDE->jChipType == XG21 ) + { + if ( pVBInfo->IF_DEF_LVDS == 1 ) + { + if (!(XGI_XG21GetPSCValue( pVBInfo )&0x1)) + { + XGI_XG21BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */ + XGI_XG21SetPanelDelay( 2,pVBInfo ) ; + } + if (!(XGI_XG21GetPSCValue( pVBInfo )&0x20)) + { + XGI_XG21BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */ + } + XGI_XG21SetPanelDelay( 3,pVBInfo ) ; + XGI_XG21BLSignalVDD( 0x02 , 0x02, pVBInfo ) ; /* LVDS backlight on */ + } + else + { + XGI_XG21BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* DVO/DVI signal on */ + } + + } + + if (pVBInfo->IF_DEF_CH7007 == 1) /* [Billy] 07/05/23 For CH7007 */ + { +#ifdef WIN2000 + if ( IsCH7007TVMode( pVBInfo ) ) + { + TurnOnCH7007(pXGIHWDE->pDevice) ; /* 07/05/28 */ + } +#endif + + } + + + if ( pXGIHWDE->jChipType == XG27 ) + { + if ( pVBInfo->IF_DEF_LVDS == 1 ) + { + if (!(XGI_XG27GetPSCValue( pVBInfo )&0x1)) + { + XGI_XG27BLSignalVDD( 0x01 , 0x01, pVBInfo ) ; /* LVDS VDD on */ + XGI_XG21SetPanelDelay( 2,pVBInfo ) ; + } + if (!(XGI_XG27GetPSCValue( pVBInfo )&0x20)) + { + XGI_XG27BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* LVDS signal on */ + } + XGI_XG21SetPanelDelay( 3,pVBInfo ) ; + XGI_XG27BLSignalVDD( 0x02 , 0x02, pVBInfo ) ; /* LVDS backlight on */ + } + else + { + XGI_XG27BLSignalVDD( 0x20 , 0x20, pVBInfo ) ; /* DVO/DVI signal on */ + } + + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_DisplayOff */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_DisplayOff( PXGI_HW_DEVICE_INFO pXGIHWDE , PVB_DEVICE_INFO pVBInfo ) +{ + + if ( pXGIHWDE->jChipType == XG21 ) + { + if ( pVBInfo->IF_DEF_LVDS == 1 ) + { + XGI_XG21BLSignalVDD( 0x02 , 0x00, pVBInfo ) ; /* LVDS backlight off */ + XGI_XG21SetPanelDelay( 3,pVBInfo ) ; + } + else + { + XGI_XG21BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* DVO/DVI signal off */ + } + } + + if (pVBInfo->IF_DEF_CH7007 == 1) /*[Billy] 07/05/23 For CH7007 */ + { + /* if( IsCH7007TVMode( pVBInfo ) == 0 ) */ + { +#ifdef WIN2000 + TurnOffCH7007(pXGIHWDE->pDevice) ; /* 07/05/28 */ +#endif + } + } + + + if ( pXGIHWDE->jChipType == XG27 ) + { + if ((XGI_XG27GetPSCValue( pVBInfo )&0x2)) + { + XGI_XG27BLSignalVDD( 0x02 , 0x00, pVBInfo ) ; /* LVDS backlight off */ + XGI_XG21SetPanelDelay( 3,pVBInfo ) ; + } + + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + XGI_XG27BLSignalVDD( 0x20 , 0x00, pVBInfo ) ; /* DVO/DVI signal off */ + } + } + + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x01 , 0xDF , 0x20 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_WaitDisply */ +/* Input : */ +/* Output : */ +/* Description : chiawen for sensecrt1 */ +/* --------------------------------------------------------------------- */ +void XGI_WaitDisply( PVB_DEVICE_INFO pVBInfo ) +{ + while( ( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) ) + break ; + + while( !( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) ) + break ; +} + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SenseCRT1 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ + +void XGI_SenseCRT1( PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR CRTCData[ 17 ] = { 0x5F , 0x4F , 0x50 , 0x82 , 0x55 , 0x81 , + 0x0B , 0x3E , 0xE9 , 0x0B , 0xDF , 0xE7 , + 0x04 , 0x00 , 0x00 , 0x05 , 0x00 } ; + + UCHAR SR01 = 0 , SR1F = 0 , SR07 = 0 , SR06 = 0 ; + + UCHAR CR17 , CR63 , SR31 ; + USHORT temp ; + UCHAR DAC_TEST_PARMS[ 3 ] = { 0x0F , 0x0F , 0x0F } ; + + int i ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x05 , 0x86 ) ; + + /* [2004/05/06] Vicent to fix XG42 single LCD sense to CRT+LCD */ + XGINew_SetReg1( pVBInfo->P3d4 , 0x57 , 0x4A ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x53 , ( UCHAR )( XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) | 0x02 ) ) ; + + SR31 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x31 ) ; + CR63 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x63 ) ; + SR01 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x01 ) ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , ( UCHAR )( SR01 & 0xDF ) ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x63 , ( UCHAR )( CR63 & 0xBF ) ) ; + + CR17 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x17 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x17 , ( UCHAR )( CR17 | 0x80 ) ) ; + + SR1F = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , ( UCHAR )( SR1F | 0x04 ) ) ; + + SR07 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x07 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x07 , ( UCHAR )( SR07 & 0xFB ) ) ; + SR06 = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x06 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x06 , ( UCHAR )( SR06 & 0xC3 ) ) ; + + XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , 0x00 ) ; + + for( i = 0 ; i < 8 ; i++ ) + XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )i , CRTCData[ i ] ) ; + + for( i = 8 ; i < 11 ; i++ ) + XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 8 ) , CRTCData[ i ] ) ; + + for( i = 11 ; i < 13 ; i++ ) + XGINew_SetReg1( pVBInfo->P3d4 , ( USHORT )( i + 4 ) , CRTCData[ i ] ) ; + + for( i = 13 ; i < 16 ; i++ ) + XGINew_SetReg1( pVBInfo->P3c4 , ( USHORT )( i - 3 ) , CRTCData[ i ] ) ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x0E , ( UCHAR )( CRTCData[ 16 ] & 0xE0 ) ) ; + + XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , 0x00 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , 0x1B ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , 0xE1 ) ; + + XGINew_SetReg3( pVBInfo->P3c8 , 0x00 ) ; + + for( i = 0 ; i < 256 ; i++ ) + { + XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 0 ] ) ; + XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 1 ] ) ; + XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , ( UCHAR )DAC_TEST_PARMS[ 2 ] ) ; + } + + XGI_VBLongWait( pVBInfo ) ; + XGI_VBLongWait( pVBInfo ) ; + XGI_VBLongWait( pVBInfo ) ; + + XGINew_LCD_Wait_Time( 0x01 , pVBInfo ) ; + + XGI_WaitDisply( pVBInfo ) ; + temp = XGINew_GetReg2( pVBInfo->P3c2 ) ; + + if( temp & 0x10 ) + { + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , 0xDF , 0x20 ) ; + } + else + { + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x32 , 0xDF , 0x00 ) ; + } + + /* alan, avoid display something, set BLACK DAC if not restore DAC */ + XGINew_SetReg3( pVBInfo->P3c8 , 0x00 ) ; + + for( i = 0 ; i < 256 ; i++ ) + { + XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , 0 ) ; + XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , 0 ) ; + XGINew_SetReg3( ( pVBInfo->P3c8 + 1 ) , 0 ) ; + } + + XGINew_SetReg1( pVBInfo->P3c4 , 0x01 , SR01 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x63 , CR63 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x31 , SR31 ) ; + + /* [2004/05/11] Vicent */ + XGINew_SetReg1( pVBInfo->P3d4 , 0x53 , ( UCHAR )( XGINew_GetReg1( pVBInfo->P3d4 , 0x53 ) & 0xFD ) ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x1F , ( UCHAR ) SR1F ) ; +} + + + + + +#ifdef TC +/* --------------------------------------------------------------------- */ +/* Function : INT1AReturnCode */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +int INT1AReturnCode( union REGS regs ) +{ + if ( regs.x.cflag ) + { + /* printf( "Error to find pci device!\n" ) ; */ + return( 1 ) ; + } + + switch(regs.h.ah) + { + case 0: return 0; + break ; + case 0x81: + printf( "Function not support\n" ) ; + break ; + case 0x83: + printf( "bad vendor id\n" ) ; + break ; + case 0x86: + printf( "device not found\n" ) ; + break ; + case 0x87: + printf( "bad register number\n" ) ; + break ; + case 0x88: + printf( "set failed\n" ) ; + break ; + case 0x89: + printf( "buffer too small" ) ; + break ; + default: + break ; + } + return( 1 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : FindPCIIOBase */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +unsigned FindPCIIOBase( unsigned index , unsigned deviceid ) +{ + union REGS regs ; + + regs.h.ah = 0xb1 ; /* PCI_FUNCTION_ID */ + regs.h.al = 0x02 ; /* FIND_PCI_DEVICE */ + regs.x.cx = deviceid ; + regs.x.dx = 0x1039 ; + regs.x.si = index ; /* find n-th device */ + + int86( 0x1A , ®s , ®s ) ; + + if ( INT1AReturnCode( regs ) != 0 ) + return( 0 ) ; + + /* regs.h.bh bus number */ + /* regs.h.bl device number */ + regs.h.ah = 0xb1 ; /* PCI_FUNCTION_ID */ + regs.h.al = 0x09 ; /* READ_CONFIG_WORD */ + regs.x.cx = deviceid ; + regs.x.dx = 0x1039 ; + regs.x.di = 0x18 ; /* register number */ + int86( 0x1A , ®s , ®s ) ; + + if ( INT1AReturnCode( regs ) != 0 ) + return( 0 ) ; + + return( regs.x.cx ) ; +} + +#endif + + + +#ifdef TC +/* --------------------------------------------------------------------- */ +/* Function : main */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void main(int argc, char *argv[]) +{ + XGI_HW_DEVICE_INFO HwDeviceExtension ; + USHORT temp ; + USHORT ModeNo ; + + /* HwDeviceExtension.pjVirtualRomBase =(PUCHAR) MK_FP(0xC000,0); */ + /* HwDeviceExtension.pjVideoMemoryAddress = (PUCHAR)MK_FP(0xA000,0); */ + + + HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 ,0x6300 ) & 0xFF80 ) + 0x30 ; + HwDeviceExtension.jChipType = XGI_340 ; + + + + /* HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 , 0x5315 ) & 0xFF80 ) + 0x30 ; */ + + HwDeviceExtension.pjIOAddress = ( FindPCIIOBase( 0 , 0x330 ) & 0xFF80 ) + 0x30 ; + HwDeviceExtension.jChipType = XGI_340 ; + + + HwDeviceExtension.ujVBChipID = VB_CHIP_301 ; + StrCpy(HwDeviceExtension.szVBIOSVer , "0.84" ) ; + HwDeviceExtension.bSkipDramSizing = FALSE ; + HwDeviceExtension.ulVideoMemorySize = 0 ; + + if ( argc == 2 ) + { + ModeNo = atoi( argv[ 1 ] ) ; + } + else + { + ModeNo = 0x2e ; + /* ModeNo = 0x37 ; 1024x768x 4bpp */ + /* ModeNo = 0x38 ; 1024x768x 8bpp */ + /* ModeNo = 0x4A ; 1024x768x 16bpp */ + /* ModeNo = 0x47 ; 800x600x 16bpp */ + } + + /* XGIInitNew( &HwDeviceExtension ) ; */ + XGISetModeNew( &HwDeviceExtension , ModeNo ) ; +} +#endif + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_WaitDisplay */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_WaitDisplay( PVB_DEVICE_INFO pVBInfo ) +{ + while( !( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) ) ; + + while( XGINew_GetReg2( pVBInfo->P3da ) & 0x01 ) ; +} + + + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT2Group301 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGI_SetCRT2Group301( USHORT ModeNo , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempbx , + ModeIdIndex , + RefreshRateTableIndex ; + + tempbx=pVBInfo->VBInfo ; + pVBInfo->SetFlag |= ProgrammingCRT2 ; + XGI_SearchModeID( ModeNo , &ModeIdIndex, pVBInfo ) ; + pVBInfo->SelectCRT2Rate = 4 ; + RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, pVBInfo ) ; + XGI_SaveCRT2Info( ModeNo, pVBInfo ) ; + XGI_GetCRT2ResInfo( ModeNo , ModeIdIndex, pVBInfo) ; + XGI_GetCRT2Data( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + XGI_PreSetGroup1( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ; + XGI_SetGroup1( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ; + XGI_SetLockRegs( ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ; + XGI_SetGroup2( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ; + XGI_SetLCDRegs(ModeNo , ModeIdIndex , HwDeviceExtension , RefreshRateTableIndex, pVBInfo ) ; + XGI_SetTap4Regs(pVBInfo) ; + XGI_SetGroup3(ModeNo, ModeIdIndex, pVBInfo); + XGI_SetGroup4( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ; + XGI_SetCRT2VCLK( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + XGI_SetGroup5( ModeNo , ModeIdIndex, pVBInfo) ; + XGI_AutoThreshold( pVBInfo) ; + return 1 ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_AutoThreshold */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_AutoThreshold( PVB_DEVICE_INFO pVBInfo ) +{ + if ( !( pVBInfo->SetFlag & Win9xDOSMode ) ) + XGINew_SetRegOR( pVBInfo->Part1Port , 0x01 , 0x40 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SaveCRT2Info */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SaveCRT2Info( USHORT ModeNo , PVB_DEVICE_INFO pVBInfo) +{ + USHORT temp1 , + temp2 ; + + XGINew_SetReg1( pVBInfo->P3d4 , 0x34 , ModeNo ) ; /* reserve CR34 for CRT1 Mode No */ + temp1 = ( pVBInfo->VBInfo&SetInSlaveMode ) >> 8 ; + temp2 = ~( SetInSlaveMode >> 8 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x31 , temp2 , temp1 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetCRT2ResInfo */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetCRT2ResInfo( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT xres , + yres , + modeflag , + resindex ; + + resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo) ; + if ( ModeNo <= 0x13 ) + { + xres = pVBInfo->StResInfo[ resindex ].HTotal ; + yres = pVBInfo->StResInfo[ resindex ].VTotal ; + /* modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; si+St_ResInfo */ + } + else + { + xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */ + yres = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */ + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */ + +/* if ( pVBInfo->IF_DEF_FSTN ) + { + xres *= 2 ; + yres *= 2 ; + } + else + { +*/ + if ( modeflag & HalfDCLK ) + xres *= 2; + + if ( modeflag & DoubleScanMode ) + yres *= 2 ; +/* } */ + } + + if ( pVBInfo->VBInfo & SetCRT2ToLCD ) + { + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + if ( pVBInfo->LCDResInfo == Panel1600x1200 ) + { + if ( !( pVBInfo->LCDInfo & LCDVESATiming ) ) + { + if ( yres == 1024 ) + yres = 1056 ; + } + } + + if ( pVBInfo->LCDResInfo == Panel1280x1024 ) + { + if ( yres == 400 ) + yres = 405 ; + else if ( yres == 350 ) + yres = 360 ; + + if ( pVBInfo->LCDInfo & LCDVESATiming ) + { + if ( yres == 360 ) + yres = 375 ; + } + } + + if ( pVBInfo->LCDResInfo == Panel1024x768 ) + { + if ( !( pVBInfo->LCDInfo & LCDVESATiming ) ) + { + if ( !( pVBInfo->LCDInfo & LCDNonExpanding ) ) + { + if ( yres == 350 ) + yres = 357 ; + else if ( yres == 400 ) + yres = 420 ; + else if ( yres == 480 ) + yres = 525 ; + } + } + } + } + + if ( xres == 720 ) + xres = 640 ; + } + + pVBInfo->VGAHDE = xres ; + pVBInfo->HDE = xres ; + pVBInfo->VGAVDE = yres ; + pVBInfo->VDE = yres ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_IsLCDDualLink */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGI_IsLCDDualLink( PVB_DEVICE_INFO pVBInfo ) +{ + + if ( ( ( ( pVBInfo->VBInfo & SetCRT2ToLCD ) | SetCRT2ToLCDA ) ) && ( pVBInfo->LCDInfo & SetLCDDualLink ) ) /* shampoo0129 */ + return ( 1 ) ; + + return( 0 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetCRT2Data */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetCRT2Data( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempax = 0, + tempbx , + modeflag , + resinfo ; + + XGI_LCDDataStruct *LCDPtr = NULL ; + XGI_TVDataStruct *TVPtr = NULL ; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */ + resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */ + resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; + } + + pVBInfo->NewFlickerMode = 0 ; + pVBInfo->RVBHRS = 50 ; + + if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) + { + XGI_GetRAMDAC2DATA( ModeNo , ModeIdIndex , RefreshRateTableIndex,pVBInfo ) ; + return ; + } + + tempbx = 4 ; + + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) + { + LCDPtr = (XGI_LCDDataStruct* )XGI_GetLcdPtr( tempbx, ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + + pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX ; + pVBInfo->RVBHCFACT = LCDPtr->RVBHCFACT ; + pVBInfo->VGAHT = LCDPtr->VGAHT ; + pVBInfo->VGAVT = LCDPtr->VGAVT ; + pVBInfo->HT = LCDPtr->LCDHT ; + pVBInfo->VT = LCDPtr->LCDVT ; + + if ( pVBInfo->LCDResInfo == Panel1024x768 ) + { + tempax = 1024 ; + tempbx = 768 ; + + if ( !( pVBInfo->LCDInfo & LCDVESATiming ) ) + { + if ( pVBInfo->VGAVDE == 357 ) + tempbx = 527 ; + else if ( pVBInfo->VGAVDE == 420 ) + tempbx = 620 ; + else if ( pVBInfo->VGAVDE == 525 ) + tempbx = 775 ; + else if ( pVBInfo->VGAVDE == 600 ) + tempbx = 775 ; + /* else if(pVBInfo->VGAVDE==350) tempbx=560; */ + /* else if(pVBInfo->VGAVDE==400) tempbx=640; */ + else + tempbx = 768 ; + } + else + tempbx = 768 ; + } + else if ( pVBInfo->LCDResInfo == Panel1024x768x75 ) + { + tempax = 1024 ; + tempbx = 768 ; + } + else if ( pVBInfo->LCDResInfo == Panel1280x1024 ) + { + tempax = 1280 ; + if ( pVBInfo->VGAVDE == 360 ) + tempbx = 768 ; + else if ( pVBInfo->VGAVDE == 375 ) + tempbx = 800 ; + else if ( pVBInfo->VGAVDE == 405 ) + tempbx = 864 ; + else + tempbx = 1024 ; + } + else if ( pVBInfo->LCDResInfo == Panel1280x1024x75 ) + { + tempax = 1280 ; + tempbx = 1024 ; + } + else if ( pVBInfo->LCDResInfo == Panel1280x960 ) + { + tempax = 1280 ; + if ( pVBInfo->VGAVDE == 350 ) + tempbx = 700 ; + else if ( pVBInfo->VGAVDE == 400 ) + tempbx = 800 ; + else if ( pVBInfo->VGAVDE == 1024 ) + tempbx = 960 ; + else + tempbx = 960 ; + } + else if ( pVBInfo->LCDResInfo == Panel1400x1050 ) + { + tempax = 1400 ; + tempbx = 1050 ; + + if ( pVBInfo->VGAVDE == 1024 ) + { + tempax = 1280 ; + tempbx = 1024 ; + } + } + else if ( pVBInfo->LCDResInfo == Panel1600x1200 ) + { + tempax = 1600 ; + tempbx = 1200 ; /* alan 10/14/2003 */ + if ( !( pVBInfo->LCDInfo & LCDVESATiming ) ) + { + if ( pVBInfo->VGAVDE == 350 ) + tempbx = 875 ; + else if ( pVBInfo->VGAVDE == 400 ) + tempbx = 1000 ; + } + } + + if ( pVBInfo->LCDInfo & LCDNonExpanding ) + { + tempax = pVBInfo->VGAHDE ; + tempbx = pVBInfo->VGAVDE ; + } + + pVBInfo->HDE = tempax ; + pVBInfo->VDE = tempbx ; + return ; + } + + if ( pVBInfo->VBInfo & ( SetCRT2ToTV ) ) + { + tempbx = 4 ; + TVPtr = ( XGI_TVDataStruct * )XGI_GetTVPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + + pVBInfo->RVBHCMAX = TVPtr->RVBHCMAX ; + pVBInfo->RVBHCFACT = TVPtr->RVBHCFACT ; + pVBInfo->VGAHT = TVPtr->VGAHT ; + pVBInfo->VGAVT = TVPtr->VGAVT ; + pVBInfo->HDE = TVPtr->TVHDE ; + pVBInfo->VDE = TVPtr->TVVDE ; + pVBInfo->RVBHRS = TVPtr->RVBHRS ; + pVBInfo->NewFlickerMode = TVPtr->FlickerMode ; + + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + if ( resinfo == 0x08 ) + pVBInfo->NewFlickerMode = 0x40 ; + else if ( resinfo == 0x09 ) + pVBInfo->NewFlickerMode = 0x40 ; + else if ( resinfo == 0x12 ) + pVBInfo->NewFlickerMode = 0x40 ; + + if ( pVBInfo->VGAVDE == 350 ) + pVBInfo->TVInfo |= TVSimuMode ; + + tempax = ExtHiTVHT ; + tempbx = ExtHiTVVT ; + + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + if ( pVBInfo->TVInfo & TVSimuMode ) + { + tempax = StHiTVHT ; + tempbx = StHiTVVT ; + + if ( !( modeflag & Charx8Dot ) ) + { + tempax = StHiTextTVHT ; + tempbx = StHiTextTVVT ; + } + } + } + } + else if ( pVBInfo->VBInfo & SetCRT2ToYPbPr ) + { + if ( pVBInfo->TVInfo & SetYPbPrMode750p ) + { + tempax = YPbPrTV750pHT ; /* Ext750pTVHT */ + tempbx = YPbPrTV750pVT ; /* Ext750pTVVT */ + } + + if ( pVBInfo->TVInfo & SetYPbPrMode525p ) + { + tempax = YPbPrTV525pHT ; /* Ext525pTVHT */ + tempbx = YPbPrTV525pVT ; /* Ext525pTVVT */ + } + else if ( pVBInfo->TVInfo & SetYPbPrMode525i ) + { + tempax = YPbPrTV525iHT ; /* Ext525iTVHT */ + tempbx = YPbPrTV525iVT ; /* Ext525iTVVT */ + if ( pVBInfo->TVInfo & NTSC1024x768 ) + tempax = NTSC1024x768HT ; + } + } + else + { + tempax = PALHT ; + tempbx = PALVT ; + if ( !( pVBInfo->TVInfo & SetPALTV ) ) + { + tempax = NTSCHT ; + tempbx = NTSCVT ; + if ( pVBInfo->TVInfo & NTSC1024x768 ) + tempax = NTSC1024x768HT ; + } + } + + pVBInfo->HT = tempax ; + pVBInfo->VT = tempbx ; + return ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT2VCLK */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT2VCLK( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR di_0 , + di_1 , + tempal ; + + tempal = XGI_GetVCLKPtr( RefreshRateTableIndex , ModeNo , ModeIdIndex, pVBInfo ) ; + XGI_GetVCLKLen( tempal, &di_0 , &di_1, pVBInfo ) ; + XGI_GetLCDVCLKPtr( &di_0 , &di_1, pVBInfo ) ; + + if ( pVBInfo->VBType & VB_XGI301 ) /* shampoo 0129 */ + { /* 301 */ + XGINew_SetReg1(pVBInfo->Part4Port , 0x0A , 0x10 ) ; + XGINew_SetReg1(pVBInfo->Part4Port , 0x0B , di_1 ) ; + XGINew_SetReg1(pVBInfo->Part4Port , 0x0A , di_0 ) ; + } + else + { /* 301b/302b/301lv/302lv */ + XGINew_SetReg1( pVBInfo->Part4Port , 0x0A , di_0 ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x0B , di_1 ) ; + } + + XGINew_SetReg1( pVBInfo->Part4Port , 0x00 , 0x12 ) ; + + if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) + XGINew_SetRegOR( pVBInfo->Part4Port , 0x12 , 0x28 ) ; + else + XGINew_SetRegOR( pVBInfo->Part4Port , 0x12 , 0x08 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GETLCDVCLKPtr */ +/* Input : */ +/* Output : al -> VCLK Index */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetLCDVCLKPtr( UCHAR* di_0 , UCHAR *di_1, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT index ; + + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) + { + if ( pVBInfo->IF_DEF_ScaleLCD == 1 ) + { + if ( pVBInfo->LCDInfo & EnableScalingLCD ) + return ; + } + + /* index = XGI_GetLCDCapPtr(pVBInfo) ; */ + index = XGI_GetLCDCapPtr1( pVBInfo) ; + + if ( pVBInfo->VBInfo & SetCRT2ToLCD ) + { /* LCDB */ + *di_0 = pVBInfo->LCDCapList[ index ].LCUCHAR_VCLKData1 ; + *di_1 = pVBInfo->LCDCapList[ index ].LCUCHAR_VCLKData2 ; + } + else + { /* LCDA */ + *di_0 = pVBInfo->LCDCapList[ index ].LCDA_VCLKData1 ; + *di_1 = pVBInfo->LCDCapList[ index ].LCDA_VCLKData2 ; + } + } + return ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetVCLKPtr */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +UCHAR XGI_GetVCLKPtr(USHORT RefreshRateTableIndex,USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo) +{ + + USHORT index , + modeflag ; +#ifndef LINUX_XF86 + USHORT tempbx ; +#endif + + UCHAR tempal ; + UCHAR *CHTVVCLKPtr = NULL ; + + if ( ModeNo <= 0x13 ) + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */ + else + modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */ + + + if ( ( pVBInfo->SetFlag & ProgrammingCRT2 ) && ( !( pVBInfo->LCDInfo & EnableScalingLCD ) ) ) + { /* {LCDA/LCDB} */ + index = XGI_GetLCDCapPtr(pVBInfo) ; + tempal = pVBInfo->LCDCapList[ index ].LCD_VCLK ; + + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) + return tempal ; + + /* {TV} */ + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV| VB_XGI302LV| VB_XGI301C ) ) + { + if(pVBInfo->VBInfo&SetCRT2ToHiVisionTV) + { + tempal = HiTVVCLKDIV2; + if(!(pVBInfo->TVInfo & RPLLDIV2XO)) + tempal = HiTVVCLK; + if(pVBInfo->TVInfo & TVSimuMode) + { + tempal = HiTVSimuVCLK; + if(!(modeflag & Charx8Dot)) + tempal = HiTVTextVCLK; + + } + return tempal; + } + + if ( pVBInfo->TVInfo & SetYPbPrMode750p ) + { + tempal = YPbPr750pVCLK ; + return tempal ; + } + + if ( pVBInfo->TVInfo & SetYPbPrMode525p ) + { + tempal = YPbPr525pVCLK ; + return tempal ; + } + + tempal = NTSC1024VCLK ; + + if ( !( pVBInfo->TVInfo & NTSC1024x768 ) ) + { + tempal = TVVCLKDIV2 ; + if ( !( pVBInfo->TVInfo & RPLLDIV2XO ) ) + tempal = TVVCLK ; + } + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + return tempal ; + } + /*else + if((pVBInfo->IF_DEF_CH7017==1)&&(pVBInfo->VBType&VB_CH7017)) + { + if(ModeNo<=0x13) + *tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC; + else + *tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + *tempal = *tempal & 0x1F; + + tempbx = 0; + if(pVBInfo->TVInfo & SetPALTV) + tempbx = tempbx + 2; + if(pVBInfo->TVInfo & SetCHTVOverScan) + tempbx++; + tempbx = tempbx << 1; + } */ + } /* {End of VB} */ + + if((pVBInfo->IF_DEF_CH7007==1)&&(pVBInfo->VBType&VB_CH7007)) /* [Billy] 07/05/08 CH7007 */ + { + /* VideoDebugPrint((0, "XGI_GetVCLKPtr: pVBInfo->IF_DEF_CH7007==1\n")); */ + if ( (pVBInfo->VBInfo & SetCRT2ToTV) ) + { + if( ModeNo <= 0x13 ) + { + tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ; + } + else + { + tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC; + } + + tempal = tempal & 0x0F; + tempbx = 0; + + if(pVBInfo->TVInfo & SetPALTV) + { + tempbx = tempbx + 2; + } + if(pVBInfo->TVInfo & SetCHTVOverScan) + { + tempbx++; + } + /** tempbx = tempbx << 1; CH7007 ? **/ + +/*[Billy]07/05/29 CH7007*/ + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + switch( tempbx ) + { + case 0: + CHTVVCLKPtr = XGI7007_CHTVVCLKUNTSC ; + break ; + case 1: + CHTVVCLKPtr = XGI7007_CHTVVCLKONTSC ; + break ; + case 2: + CHTVVCLKPtr = XGI7007_CHTVVCLKUPAL ; + break ; + case 3: + CHTVVCLKPtr = XGI7007_CHTVVCLKOPAL ; + break ; + default: + break ; + + } + } + /*else + { + switch( tempbx ) + { + case 0: + CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC ; + break ; + case 1: + CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC ; + break ; + case 2: + CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL ; + break ; + case 3: + CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL ; + break ; + default: + break ; + } + }*/ + + tempal = CHTVVCLKPtr[ tempal ] ; + return tempal ; + } + + } + + tempal = ( UCHAR )XGINew_GetReg2( ( pVBInfo->P3ca + 0x02 ) ) ; + tempal = tempal >> 2 ; + tempal &= 0x03 ; + + if ( ( pVBInfo->LCDInfo & EnableScalingLCD ) && ( modeflag & Charx8Dot ) ) /* for Dot8 Scaling LCD */ + tempal = tempal ^ tempal ; /* ; set to VCLK25MHz always */ + + if ( ModeNo <= 0x13 ) + return tempal ; + + tempal = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ; + return tempal ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetVCLKLen */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetVCLKLen(UCHAR tempal,UCHAR* di_0,UCHAR* di_1, PVB_DEVICE_INFO pVBInfo) +{ + if ( pVBInfo->IF_DEF_CH7007 == 1 ) /* [Billy] 2007/05/16 */ + { + /* VideoDebugPrint((0, "XGI_GetVCLKLen: pVBInfo->IF_DEF_CH7007==1\n")); */ + *di_0 = ( UCHAR )XGI_CH7007VCLKData[ tempal ].SR2B ; + *di_1 = ( UCHAR )XGI_CH7007VCLKData[ tempal ].SR2C ; + } + else if ( pVBInfo->VBType & ( VB_XGI301 | VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + if ( ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) && ( pVBInfo->SetFlag & ProgrammingCRT2 ) ) + { + *di_0 = ( UCHAR )XGI_VBVCLKData[ tempal ].SR2B ; + *di_1 = XGI_VBVCLKData[ tempal ].SR2C ; + } + } + else + { + *di_0 = XGI_VCLKData[ tempal ].SR2B ; + *di_1 = XGI_VCLKData[ tempal ].SR2C ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT2Offset */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT2Offset( USHORT ModeNo , + USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT offset ; + UCHAR temp ; + + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + return ; + } + + offset = XGI_GetOffset( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ; + temp = ( UCHAR )( offset & 0xFF ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , temp ) ; + temp =( UCHAR)( ( offset & 0xFF00 ) >> 8 ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x09 , temp ) ; + temp =( UCHAR )( ( ( offset >> 3 ) & 0xFF ) + 1 ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , temp ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetOffset */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +USHORT XGI_GetOffset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension,PVB_DEVICE_INFO pVBInfo) +{ + USHORT temp , + colordepth , + modeinfo , + index , + infoflag , + ColorDepth[] = { 0x01 , 0x02 , 0x04 } ; + + modeinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeInfo ; + if ( ModeNo <= 0x14 ) + infoflag = 0 ; + else + infoflag = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_InfoFlag ; + + + index = ( modeinfo >> 8 ) & 0xFF ; + + temp = pVBInfo->ScreenOffset[ index ] ; + + if ( infoflag & InterlaceMode ) + { + temp = temp << 1 ; + } + + colordepth = XGI_GetColorDepth( ModeNo , ModeIdIndex, pVBInfo ) ; + + if ( ( ModeNo >= 0x7C ) && ( ModeNo <= 0x7E ) ) + { + temp = ModeNo - 0x7C ; + colordepth = ColorDepth[ temp ] ; + temp = 0x6B ; + if ( infoflag & InterlaceMode ) + { + temp = temp << 1 ; + } + return( temp * colordepth ) ; + } + else + return( temp * colordepth ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT2FIFO */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT2FIFO( PVB_DEVICE_INFO pVBInfo) +{ + XGINew_SetReg1( pVBInfo->Part1Port , 0x01 , 0x3B ) ; /* threshold high ,disable auto threshold */ + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x02 , ~( 0x3F ) , 0x04 ) ; /* threshold low default 04h */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_PreSetGroup1 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_PreSetGroup1(USHORT ModeNo , USHORT ModeIdIndex ,PXGI_HW_DEVICE_INFO HwDeviceExtension, + USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempcx = 0 , + CRT1Index = 0 , + resinfo = 0 ; + + if ( ModeNo > 0x13 ) + { + CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ; + CRT1Index &= IndexMask ; + resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; + } + + XGI_SetCRT2Offset( ModeNo , ModeIdIndex , RefreshRateTableIndex , HwDeviceExtension, pVBInfo ) ; + XGI_SetCRT2FIFO(pVBInfo) ; + /* XGI_SetCRT2Sync(ModeNo,RefreshRateTableIndex); */ + + for( tempcx = 4 ; tempcx < 7 ; tempcx++ ) + { + XGINew_SetReg1( pVBInfo->Part1Port , tempcx , 0x0 ) ; + } + + XGINew_SetReg1( pVBInfo->Part1Port , 0x50 , 0x00 ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x02 , 0x44 ) ; /* temp 0206 */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetGroup1 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetGroup1( USHORT ModeNo , USHORT ModeIdIndex , + PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT temp = 0 , + tempax = 0 , + tempbx = 0 , + tempcx = 0 , + pushbx = 0 , + CRT1Index = 0 , + modeflag , + resinfo = 0 ; + + if ( ModeNo > 0x13 ) + { + CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ; + CRT1Index &= IndexMask ; + resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; + } + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + } + + /* bainy change table name */ + if ( modeflag & HalfDCLK ) + { + temp = ( pVBInfo->VGAHT / 2 - 1 ) & 0x0FF ; /* BTVGA2HT 0x08,0x09 */ + XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , temp ) ; + temp = ( ( ( pVBInfo->VGAHT / 2 - 1 ) & 0xFF00 ) >> 8 ) << 4 ; + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x09 , ~0x0F0 , temp ) ; + temp = ( pVBInfo->VGAHDE / 2 + 16 ) & 0x0FF ; /* BTVGA2HDEE 0x0A,0x0C */ + XGINew_SetReg1( pVBInfo->Part1Port , 0x0A , temp ) ; + tempcx = ( ( pVBInfo->VGAHT - pVBInfo->VGAHDE ) / 2 ) >> 2 ; + pushbx = pVBInfo->VGAHDE / 2 + 16 ; + tempcx = tempcx >> 1 ; + tempbx = pushbx + tempcx ; /* bx BTVGA@HRS 0x0B,0x0C */ + tempcx += tempbx ; + + if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) + { + tempbx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 4 ] ; + tempbx |= ( ( pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 14 ] & 0xC0 ) << 2 ) ; + tempbx = ( tempbx - 3 ) << 3 ; /* (VGAHRS-3)*8 */ + tempcx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[ 5 ] ; + tempcx &= 0x1F ; + temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 15 ] ; + temp = ( temp & 0x04 ) << ( 5 - 2 ) ; /* VGAHRE D[5] */ + tempcx = ( ( tempcx | temp ) - 3 ) << 3 ; /* (VGAHRE-3)*8 */ + } + + tempbx += 4 ; + tempcx += 4 ; + + if ( tempcx > ( pVBInfo->VGAHT / 2 ) ) + tempcx = pVBInfo->VGAHT / 2 ; + + temp = tempbx & 0x00FF ; + + XGINew_SetReg1( pVBInfo->Part1Port , 0x0B , temp ) ; + } + else + { + temp = ( pVBInfo->VGAHT - 1 ) & 0x0FF ; /* BTVGA2HT 0x08,0x09 */ + XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , temp ) ; + temp = ( ( ( pVBInfo->VGAHT - 1 ) & 0xFF00 ) >> 8 ) << 4 ; + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x09 , ~0x0F0 , temp ) ; + temp = ( pVBInfo->VGAHDE + 16 ) & 0x0FF ; /* BTVGA2HDEE 0x0A,0x0C */ + XGINew_SetReg1( pVBInfo->Part1Port , 0x0A , temp ) ; + tempcx = ( pVBInfo->VGAHT - pVBInfo->VGAHDE ) >> 2 ; /* cx */ + pushbx = pVBInfo->VGAHDE + 16 ; + tempcx = tempcx >> 1 ; + tempbx = pushbx + tempcx ; /* bx BTVGA@HRS 0x0B,0x0C */ + tempcx += tempbx ; + + if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) + { + tempbx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 3 ] ; + tempbx |= ( ( pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 5 ] & 0xC0 ) << 2 ) ; + tempbx = ( tempbx - 3 ) << 3 ; /* (VGAHRS-3)*8 */ + tempcx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 4 ] ; + tempcx &= 0x1F ; + temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 6 ] ; + temp = ( temp & 0x04 ) << ( 5 - 2 ) ; /* VGAHRE D[5] */ + tempcx = ( ( tempcx | temp ) - 3 ) << 3 ; /* (VGAHRE-3)*8 */ + tempbx += 16 ; + tempcx += 16 ; + } + + if ( tempcx > pVBInfo->VGAHT ) + tempcx = pVBInfo->VGAHT ; + + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x0B , temp ) ; + } + + tempax = ( tempax & 0x00FF ) | ( tempbx & 0xFF00 ) ; + tempbx = pushbx ; + tempbx = ( tempbx & 0x00FF ) | ( ( tempbx & 0xFF00 ) << 4 ) ; + tempax |= ( tempbx & 0xFF00 ) ; + temp = ( tempax & 0xFF00 ) >> 8 ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , temp ) ; + temp = tempcx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x0D , temp ) ; + tempcx = ( pVBInfo->VGAVT - 1 ) ; + temp = tempcx & 0x00FF ; + + if ( pVBInfo->IF_DEF_CH7005 == 1 ) + { + if ( pVBInfo->VBInfo & 0x0C ) + { + temp-- ; + } + } + + XGINew_SetReg1( pVBInfo->Part1Port , 0x0E , temp ) ; + tempbx = pVBInfo->VGAVDE - 1 ; + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x0F , temp ) ; + temp = ( ( tempbx & 0xFF00 ) << 3 ) >> 8 ; + temp |= ( ( tempcx & 0xFF00 ) >> 8 ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x12 , temp ) ; + + tempax = pVBInfo->VGAVDE ; + tempbx = pVBInfo->VGAVDE ; + tempcx = pVBInfo->VGAVT ; + tempbx = ( pVBInfo->VGAVT + pVBInfo->VGAVDE ) >> 1 ; /* BTVGA2VRS 0x10,0x11 */ + tempcx = ( ( pVBInfo->VGAVT - pVBInfo->VGAVDE ) >> 4 ) + tempbx + 1 ; /* BTVGA2VRE 0x11 */ + + if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) + { + tempbx = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 10 ] ; + temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 9 ] ; + + if ( temp & 0x04 ) + tempbx |= 0x0100 ; + + if ( temp & 0x080 ) + tempbx |= 0x0200 ; + + temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 14 ] ; + + if ( temp & 0x08 ) + tempbx |= 0x0400 ; + + temp = pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 11 ] ; + tempcx = ( tempcx & 0xFF00 ) | ( temp & 0x00FF ) ; + } + + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x10 , temp ) ; + temp = ( ( tempbx & 0xFF00 ) >> 8 ) << 4 ; + temp = ( ( tempcx & 0x000F ) | ( temp ) ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x11 , temp ) ; + tempax = 0 ; + + if ( modeflag & DoubleScanMode ) + tempax |= 0x80 ; + + if ( modeflag & HalfDCLK ) + tempax |= 0x40 ; + + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2C , ~0x0C0 , tempax ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetLockRegs */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetLockRegs( USHORT ModeNo , USHORT ModeIdIndex , + PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT push1 , + push2 , + tempax , + tempbx = 0 , + tempcx , + temp , + resinfo , + modeflag , + CRT1Index ; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */ + resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */ + resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; + CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ; + CRT1Index &= IndexMask; + } + + if ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) + { + return ; + } + + temp = 0xFF ; /* set MAX HT */ + XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , temp ) ; + /* if ( modeflag & Charx8Dot ) tempcx = 0x08 ; */ + /* else */ + tempcx=0x08; + + if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + modeflag |= Charx8Dot ; + + tempax = pVBInfo->VGAHDE ; /* 0x04 Horizontal Display End */ + + if ( modeflag & HalfDCLK ) + tempax = tempax >> 1 ; + + tempax = ( tempax / tempcx ) - 1 ; + tempbx |= ( ( tempax & 0x00FF ) << 8 ) ; + temp = tempax & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x04 , temp ) ; + + temp = ( tempbx & 0xFF00 ) >> 8 ; + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + if ( !( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) ) + temp += 2 ; + + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + if ( pVBInfo->VBType & VB_XGI301LV ) + { + if ( pVBInfo->VBExtInfo == VB_YPbPr1080i ) + { + if ( resinfo == 7 ) + temp -= 2 ; + } + } + else + if ( resinfo == 7 ) + temp -= 2 ; + } + } + + XGINew_SetReg1( pVBInfo->Part1Port , 0x05 , temp ) ; /* 0x05 Horizontal Display Start */ + XGINew_SetReg1( pVBInfo->Part1Port , 0x06 , 0x03 ) ; /* 0x06 Horizontal Blank end */ + + if ( !( pVBInfo->VBInfo & DisableCRT2Display ) ) + { /* 030226 bainy */ + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + tempax = pVBInfo->VGAHT ; + else + tempax = XGI_GetVGAHT2( pVBInfo) ; + } + + if ( tempax >= pVBInfo->VGAHT ) + { + tempax = pVBInfo->VGAHT ; + } + + if ( modeflag & HalfDCLK ) + { + tempax = tempax >> 1 ; + } + + tempax = ( tempax / tempcx ) - 5 ; + tempcx = tempax ; /* 20030401 0x07 horizontal Retrace Start */ + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + temp = ( tempbx & 0x00FF ) - 1 ; + if ( !( modeflag & HalfDCLK ) ) + { + temp -= 6 ; + if ( pVBInfo->TVInfo & TVSimuMode ) + { + temp -= 4 ; + if ( ModeNo > 0x13 ) + temp -= 10 ; + } + } + } + else + { + /* tempcx = tempbx & 0x00FF ; */ + tempbx = ( tempbx & 0xFF00 ) >> 8 ; + tempcx = ( tempcx + tempbx ) >> 1 ; + temp = ( tempcx & 0x00FF ) + 2 ; + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + temp -= 1 ; + if ( !( modeflag & HalfDCLK ) ) + { + if ( ( modeflag & Charx8Dot ) ) + { + temp += 4 ; + if ( pVBInfo->VGAHDE >= 800 ) + { + temp -= 6 ; + } + } + } + } + else + { + if ( !( modeflag & HalfDCLK ) ) + { + temp -= 4 ; + if ( pVBInfo->LCDResInfo != Panel1280x960 ) + { + if( pVBInfo->VGAHDE >= 800 ) + { + temp -= 7 ; + if ( pVBInfo->ModeType == ModeEGA ) + { + if ( pVBInfo->VGAVDE == 1024 ) + { + temp += 15 ; + if ( pVBInfo->LCDResInfo != Panel1280x1024 ) + { + temp += 7 ; + } + } + } + + if ( pVBInfo->VGAHDE >= 1280 ) + { + if ( pVBInfo->LCDResInfo != Panel1280x960 ) + { + if ( pVBInfo->LCDInfo & LCDNonExpanding ) + { + temp += 28 ; + } + } + } + } + } + } + } + } + + XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , temp ) ; /* 0x07 Horizontal Retrace Start */ + XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0 ) ; /* 0x08 Horizontal Retrace End */ + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + if ( pVBInfo->TVInfo & TVSimuMode ) + { + if ( ( ModeNo == 0x06 ) || ( ModeNo == 0x10 ) || ( ModeNo == 0x11 ) || ( ModeNo == 0x13 ) || ( ModeNo == 0x0F ) ) + { + XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x5b ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x03 ) ; + } + + if ( ( ModeNo == 0x00 ) || ( ModeNo == 0x01 ) ) + { + if ( pVBInfo->TVInfo & SetNTSCTV ) + { + XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x2A ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x61 ) ; + } + else + { + XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x2A ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x41 ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , 0xF0 ) ; + } + } + + if ( ( ModeNo == 0x02 ) || ( ModeNo == 0x03 ) || ( ModeNo == 0x07 ) ) + { + if ( pVBInfo->TVInfo & SetNTSCTV ) + { + XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x54 ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x00 ) ; + } + else + { + XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x55 ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x00 ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , 0xF0 ) ; + } + } + + if ( ( ModeNo == 0x04 ) || ( ModeNo == 0x05 ) || ( ModeNo == 0x0D ) || ( ModeNo == 0x50 ) ) + { + if ( pVBInfo->TVInfo & SetNTSCTV ) + { + XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x30 ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x03 ) ; + } + else + { + XGINew_SetReg1( pVBInfo->Part1Port , 0x07 , 0x2f ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x08 , 0x02 ) ; + } + } + } + } + + XGINew_SetReg1( pVBInfo->Part1Port , 0x18 , 0x03 ) ; /* 0x18 SR0B */ + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0xF0 , 0x00 ) ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x09 , 0xFF ) ; /* 0x09 Set Max VT */ + + tempbx = pVBInfo->VGAVT ; + push1 = tempbx ; + tempcx = 0x121 ; + tempbx = pVBInfo->VGAVDE ; /* 0x0E Virtical Display End */ + + if ( tempbx == 357 ) + tempbx = 350 ; + if ( tempbx == 360 ) + tempbx =350 ; + if ( tempbx == 375 ) + tempbx = 350 ; + if ( tempbx == 405 ) + tempbx = 400 ; + if ( tempbx == 525 ) + tempbx = 480 ; + + push2 = tempbx ; + + if ( pVBInfo->VBInfo & SetCRT2ToLCD ) + { + if ( pVBInfo->LCDResInfo == Panel1024x768 ) + { + if ( !( pVBInfo->LCDInfo & LCDVESATiming ) ) + { + if ( tempbx == 350 ) + tempbx += 5 ; + if ( tempbx == 480 ) + tempbx += 5 ; + } + } + } + tempbx-- ; + temp = tempbx & 0x00FF ; + tempbx-- ; + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x10 ,temp ) ; /* 0x10 vertical Blank Start */ + tempbx = push2 ; + tempbx-- ; + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x0E , temp ) ; + + if ( tempbx & 0x0100 ) + { + tempcx |= 0x0002 ; + } + + tempax = 0x000B ; + + if ( modeflag & DoubleScanMode ) + { + tempax |= 0x08000 ; + } + + if ( tempbx & 0x0200 ) + { + tempcx |= 0x0040 ; + } + + temp = ( tempax & 0xFF00 ) >> 8 ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x0B , temp ) ; + + if ( tempbx & 0x0400 ) + { + tempcx |= 0x0600 ; + } + + XGINew_SetReg1( pVBInfo->Part1Port , 0x11 , 0x00 ) ; /* 0x11 Vertival Blank End */ + + tempax = push1 ; + tempax -= tempbx ; /* 0x0C Vertical Retrace Start */ + tempax = tempax >> 2 ; + push1 = tempax ; /* push ax */ + + if ( resinfo != 0x09 ) + { + tempax = tempax << 1 ; + tempbx += tempax ; + } + + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + if ( pVBInfo->VBType & VB_XGI301LV ) + { + if ( pVBInfo->TVInfo & SetYPbPrMode1080i ) + tempbx -= 10 ; + else + { + if ( pVBInfo->TVInfo & TVSimuMode ) + { + if ( pVBInfo->TVInfo & SetPALTV ) + { + if ( pVBInfo->VBType & VB_XGI301LV ) + { + if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) ) + tempbx += 40 ; + } + else + tempbx += 40 ; + } + } + } + } + else + tempbx -= 10 ; + } + else + { + if ( pVBInfo->TVInfo & TVSimuMode ) + { + if ( pVBInfo->TVInfo & SetPALTV ) + { + if ( pVBInfo->VBType & VB_XGI301LV ) + { + if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) ) + tempbx += 40 ; + } + else + tempbx += 40 ; + } + } + } + tempax = push1 ; + tempax = tempax >> 2 ; + tempax++ ; + tempax += tempbx ; + push1 = tempax ; /* push ax */ + + if ( ( pVBInfo->TVInfo & SetPALTV ) ) + { + if ( tempbx <= 513 ) + { + if ( tempax >= 513 ) + { + tempbx = 513 ; + } + } + } + + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x0C , temp ) ; + tempbx-- ; + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x10 , temp ) ; + + if ( tempbx & 0x0100 ) + { + tempcx |= 0x0008 ; + } + + if ( tempbx & 0x0200 ) + { + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x0B , 0x0FF , 0x20 ) ; + } + + tempbx++ ; + + if ( tempbx & 0x0100 ) + { + tempcx |= 0x0004 ; + } + + if ( tempbx & 0x0200 ) + { + tempcx |= 0x0080 ; + } + + if ( tempbx & 0x0400 ) + { + tempcx |= 0x0C00 ; + } + + tempbx = push1 ; /* pop ax */ + temp = tempbx & 0x00FF ; + temp &= 0x0F ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x0D , temp ) ; /* 0x0D vertical Retrace End */ + + if ( tempbx & 0x0010 ) + { + tempcx |= 0x2000 ; + } + + temp = tempcx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x0A , temp ) ; /* 0x0A CR07 */ + temp = ( tempcx & 0x0FF00 ) >> 8 ; + XGINew_SetReg1( pVBInfo->Part1Port , 0x17 , temp ) ; /* 0x17 SR0A */ + tempax = modeflag ; + temp = ( tempax & 0xFF00 ) >> 8 ; + + temp = ( temp >> 1 ) & 0x09 ; + + if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + temp |= 0x01 ; + + XGINew_SetReg1( pVBInfo->Part1Port , 0x16 , temp ) ; /* 0x16 SR01 */ + XGINew_SetReg1( pVBInfo->Part1Port , 0x0F , 0 ) ; /* 0x0F CR14 */ + XGINew_SetReg1( pVBInfo->Part1Port , 0x12 , 0 ) ; /* 0x12 CR17 */ + + if ( pVBInfo->LCDInfo & LCDRGB18Bit ) + temp = 0x80 ; + else + temp = 0x00 ; + + XGINew_SetReg1( pVBInfo->Part1Port , 0x1A , temp ) ; /* 0x1A SR0E */ + + return ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetGroup2 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetGroup2( USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, + PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT i , + j , + tempax , + tempbx , + tempcx , + temp , + push1 , + push2 , + modeflag , + resinfo , + crt2crtc ; + UCHAR *TimingPoint ; + + ULONG longtemp , + tempeax , + tempebx , + temp2 , + tempecx ; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */ + resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; + crt2crtc = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */ + resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; + crt2crtc = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ; + } + + tempax = 0 ; + + if ( !( pVBInfo->VBInfo & SetCRT2ToAVIDEO ) ) + tempax |= 0x0800 ; + + if ( !( pVBInfo->VBInfo & SetCRT2ToSVIDEO ) ) + tempax |= 0x0400 ; + + if ( pVBInfo->VBInfo & SetCRT2ToSCART ) + tempax |= 0x0200 ; + + if ( !( pVBInfo->TVInfo & SetPALTV ) ) + tempax |= 0x1000 ; + + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + tempax |= 0x0100 ; + + if ( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) + tempax &= 0xfe00 ; + + tempax = ( tempax & 0xff00 ) >> 8 ; + + XGINew_SetReg1( pVBInfo->Part2Port , 0x0 , tempax ) ; + TimingPoint = pVBInfo->NTSCTiming ; + + if ( pVBInfo->TVInfo & SetPALTV ) + { + TimingPoint = pVBInfo->PALTiming ; + } + + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + TimingPoint = pVBInfo->HiTVExtTiming ; + + if ( pVBInfo->VBInfo & SetInSlaveMode ) + TimingPoint = pVBInfo->HiTVSt2Timing ; + + if ( pVBInfo->SetFlag & TVSimuMode ) + TimingPoint = pVBInfo->HiTVSt1Timing ; + + if ( !(modeflag & Charx8Dot) ) + TimingPoint = pVBInfo->HiTVTextTiming ; + } + + if ( pVBInfo->VBInfo & SetCRT2ToYPbPr ) + { + if ( pVBInfo->TVInfo & SetYPbPrMode525i ) + TimingPoint = pVBInfo->YPbPr525iTiming ; + + if ( pVBInfo->TVInfo & SetYPbPrMode525p ) + TimingPoint = pVBInfo->YPbPr525pTiming ; + + if ( pVBInfo->TVInfo & SetYPbPrMode750p ) + TimingPoint = pVBInfo->YPbPr750pTiming ; + } + + for( i = 0x01 , j = 0 ; i <= 0x2D ; i++ , j++ ) + { + XGINew_SetReg1( pVBInfo->Part2Port , i , TimingPoint[ j ] ) ; + } + + for( i = 0x39 ; i <= 0x45 ; i++ , j++ ) + { + XGINew_SetReg1( pVBInfo->Part2Port , i , TimingPoint[ j ] ) ; /* di->temp2[j] */ + } + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x3A , 0x1F , 0x00 ) ; + } + + temp = pVBInfo->NewFlickerMode ; + temp &= 0x80 ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0A , 0xFF , temp ) ; + + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + tempax = 950 ; + + if ( pVBInfo->TVInfo & SetPALTV ) + tempax = 520 ; + else + tempax = 440 ; + + if ( pVBInfo->VDE <= tempax ) + { + tempax -= pVBInfo->VDE ; + tempax = tempax >> 2 ; + tempax = ( tempax & 0x00FF ) | ( ( tempax & 0x00FF ) << 8 ) ; + push1 = tempax ; + temp = ( tempax & 0xFF00 ) >> 8 ; + temp += ( USHORT )TimingPoint[ 0 ] ; + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + if ( pVBInfo->VBInfo & ( SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr ) ) + { + tempcx=pVBInfo->VGAHDE; + if ( tempcx >= 1024 ) + { + temp = 0x17 ; /* NTSC */ + if ( pVBInfo->TVInfo & SetPALTV ) + temp = 0x19 ; /* PAL */ + } + } + } + + XGINew_SetReg1( pVBInfo->Part2Port , 0x01 , temp ) ; + tempax = push1 ; + temp = ( tempax & 0xFF00 ) >> 8 ; + temp += TimingPoint[ 1 ] ; + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + if ( ( pVBInfo->VBInfo & ( SetCRT2ToAVIDEO | SetCRT2ToSVIDEO | SetCRT2ToSCART | SetCRT2ToYPbPr ) ) ) + { + tempcx = pVBInfo->VGAHDE ; + if ( tempcx >= 1024 ) + { + temp = 0x1D ; /* NTSC */ + if ( pVBInfo->TVInfo & SetPALTV ) + temp = 0x52 ; /* PAL */ + } + } + } + XGINew_SetReg1( pVBInfo->Part2Port , 0x02 , temp ) ; + } + + /* 301b */ + tempcx = pVBInfo->HT ; + + if ( XGI_IsLCDDualLink( pVBInfo ) ) + tempcx = tempcx >> 1 ; + + tempcx -= 2 ; + temp = tempcx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x1B , temp ) ; + + temp = ( tempcx & 0xFF00 ) >> 8 ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1D , ~0x0F , temp ) ; + + tempcx = pVBInfo->HT >> 1 ; + push1 = tempcx ; /* push cx */ + tempcx += 7 ; + + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + tempcx -= 4 ; + } + + temp = tempcx & 0x00FF ; + temp = temp << 4 ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x22 , 0x0F , temp ) ; + + tempbx = TimingPoint[ j ] | ( ( TimingPoint[ j + 1 ] ) << 8 ) ; + tempbx += tempcx ; + push2 = tempbx ; + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x24 , temp ) ; + temp = ( tempbx & 0xFF00 ) >> 8 ; + temp = temp << 4 ; + XGINew_SetRegANDOR(pVBInfo->Part2Port,0x25,0x0F,temp); + + tempbx=push2; + tempbx=tempbx+8; + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + tempbx=tempbx-4; + tempcx=tempbx; + } + + temp = ( tempbx & 0x00FF ) << 4 ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x29 , 0x0F , temp ) ; + + j += 2 ; + tempcx += ( TimingPoint[ j ] | ( ( TimingPoint[ j + 1 ] ) << 8 ) ) ; + temp = tempcx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x27 , temp ) ; + temp = ( ( tempcx & 0xFF00 ) >> 8 ) << 4 ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x28 , 0x0F , temp ) ; + + tempcx += 8 ; + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + tempcx -= 4 ; + } + + temp = tempcx & 0xFF ; + temp = temp << 4 ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x2A , 0x0F , temp ) ; + + tempcx = push1 ; /* pop cx */ + j += 2 ; + temp = TimingPoint[ j ] | ( ( TimingPoint[ j + 1 ] ) << 8 ) ; + tempcx -= temp ; + temp = tempcx & 0x00FF ; + temp = temp << 4 ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x2D , 0x0F ,temp ) ; + + tempcx -= 11 ; + + if ( !( pVBInfo->VBInfo & SetCRT2ToTV ) ) + { + tempax = XGI_GetVGAHT2( pVBInfo) ; + tempcx = tempax - 1 ; + } + temp = tempcx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x2E , temp ) ; + + tempbx = pVBInfo->VDE ; + + if ( pVBInfo->VGAVDE == 360 ) + tempbx = 746 ; + if ( pVBInfo->VGAVDE == 375 ) + tempbx = 746 ; + if ( pVBInfo->VGAVDE == 405 ) + tempbx = 853 ; + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) ) + tempbx = tempbx >> 1 ; + } + else + tempbx = tempbx >> 1 ; + } + + tempbx -= 2 ; + temp = tempbx & 0x00FF ; + + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + if ( pVBInfo->VBType & VB_XGI301LV ) + { + if ( pVBInfo->TVInfo & SetYPbPrMode1080i ) + { + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + if ( ModeNo == 0x2f ) + temp += 1 ; + } + } + } + else + { + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + if ( ModeNo == 0x2f ) + temp += 1 ; + } + } + } + + XGINew_SetReg1( pVBInfo->Part2Port , 0x2F , temp ) ; + + temp = ( tempcx & 0xFF00 ) >> 8 ; + temp |= ( ( tempbx & 0xFF00 ) >> 8 ) << 6 ; + + if ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) ) + { + if ( pVBInfo->VBType & VB_XGI301LV ) + { + if ( pVBInfo->TVInfo & SetYPbPrMode1080i ) + { + temp |= 0x10 ; + + if ( !( pVBInfo->VBInfo & SetCRT2ToSVIDEO ) ) + temp |= 0x20 ; + } + } + else + { + temp |= 0x10 ; + if ( !( pVBInfo->VBInfo & SetCRT2ToSVIDEO ) ) + temp |= 0x20 ; + } + } + + XGINew_SetReg1( pVBInfo->Part2Port , 0x30 , temp ) ; + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) /* TV gatingno */ + { + tempbx = pVBInfo->VDE ; + tempcx = tempbx - 2 ; + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) ) + tempbx = tempbx >> 1 ; + } + + if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) ) + { + temp=0; + if( tempcx & 0x0400 ) + temp |= 0x20 ; + + if ( tempbx & 0x0400 ) + temp |= 0x40 ; + + XGINew_SetReg1( pVBInfo->Part4Port , 0x10 , temp ) ; + } + + temp = ( ( ( tempbx - 3 ) & 0x0300 ) >> 8 ) << 5 ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x46 , temp ) ; + temp = ( tempbx - 3 ) & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x47 , temp ) ; + } + + tempbx = tempbx & 0x00FF ; + + if ( !( modeflag & HalfDCLK ) ) + { + tempcx = pVBInfo->VGAHDE ; + if ( tempcx >= pVBInfo->HDE ) + { + tempbx |= 0x2000 ; + tempax &= 0x00FF ; + } + } + + tempcx = 0x0101 ; + + if( pVBInfo->VBInfo & SetCRT2ToTV ) { /*301b*/ + if(pVBInfo->VGAHDE>=1024) + { + tempcx=0x1920; + if(pVBInfo->VGAHDE>=1280) + { + tempcx=0x1420; + tempbx=tempbx&0xDFFF; + } + } + } + + if ( !( tempbx & 0x2000 ) ) + { + if ( modeflag & HalfDCLK ) + { + tempcx = ( tempcx & 0xFF00 ) | ( ( tempcx & 0x00FF ) << 1 ) ; + } + + push1 = tempbx ; + tempeax = pVBInfo->VGAHDE ; + tempebx = ( tempcx & 0xFF00 ) >> 8 ; + longtemp = tempeax * tempebx ; + tempecx = tempcx & 0x00FF ; + longtemp = longtemp / tempecx ; + + /* 301b */ + tempecx = 8 * 1024 ; + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + tempecx = tempecx * 8 ; + } + + longtemp = longtemp * tempecx ; + tempecx = pVBInfo->HDE ; + temp2 = longtemp % tempecx ; + tempeax = longtemp / tempecx ; + if ( temp2 != 0 ) + { + tempeax += 1 ; + } + + tempax = ( USHORT )tempeax ; + + /* 301b */ + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + tempcx = ( ( tempax & 0xFF00 ) >> 5 ) >> 8 ; + } + /* end 301b */ + + tempbx = push1 ; + tempbx =( USHORT )( ( ( tempeax & 0x0000FF00 ) & 0x1F00 ) | ( tempbx & 0x00FF ) ) ; + tempax =( USHORT )( ( ( tempeax & 0x000000FF ) << 8 ) | ( tempax & 0x00FF ) ) ; + temp = ( tempax & 0xFF00 ) >> 8 ; + } + else + { + temp = ( tempax & 0x00FF ) >> 8 ; + } + + XGINew_SetReg1( pVBInfo->Part2Port , 0x44 , temp ) ; + temp = ( tempbx & 0xFF00 ) >> 8 ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x45 , ~0x03F , temp ) ; + temp = tempcx & 0x00FF ; + + if ( tempbx & 0x2000 ) + temp = 0 ; + + if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) ) + temp |= 0x18 ; + + XGINew_SetRegANDOR(pVBInfo->Part2Port,0x46,~0x1F,temp); + if ( pVBInfo->TVInfo & SetPALTV ) + { + tempbx = 0x0382 ; + tempcx = 0x007e ; + } + else + { + tempbx = 0x0369 ; + tempcx = 0x0061 ; + } + + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x4b , temp ) ; + temp = tempcx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x4c , temp ) ; + + temp = ( ( tempcx & 0xFF00 ) >> 8 ) & 0x03 ; + temp = temp << 2 ; + temp |= ( ( tempbx & 0xFF00 ) >> 8 ) & 0x03 ; + + if ( pVBInfo->VBInfo & SetCRT2ToYPbPr ) + { + temp |= 0x10 ; + + if ( pVBInfo->TVInfo & SetYPbPrMode525p ) + temp |= 0x20 ; + + if ( pVBInfo->TVInfo & SetYPbPrMode750p ) + temp |= 0x60 ; + } + + XGINew_SetReg1( pVBInfo->Part2Port , 0x4d , temp ) ; + temp=XGINew_GetReg1( pVBInfo->Part2Port , 0x43 ) ; /* 301b change */ + XGINew_SetReg1( pVBInfo->Part2Port , 0x43 , ( USHORT )( temp - 3 ) ) ; + + if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) ) + { + if ( pVBInfo->TVInfo & NTSC1024x768 ) + { + TimingPoint = XGI_NTSC1024AdjTime ; + for( i = 0x1c , j = 0 ; i <= 0x30 ; i++ , j++ ) + { + XGINew_SetReg1( pVBInfo->Part2Port , i , TimingPoint[ j ] ) ; + } + XGINew_SetReg1( pVBInfo->Part2Port , 0x43 , 0x72 ) ; + } + } + + /* [ycchen] 01/14/03 Modify for 301C PALM Support */ + if ( pVBInfo->VBType & VB_XGI301C ) + { + if ( pVBInfo->TVInfo & SetPALMTV ) + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x4E , ~0x08 , 0x08 ) ; /* PALM Mode */ + } + + if ( pVBInfo->TVInfo & SetPALMTV ) + { + tempax = ( UCHAR )XGINew_GetReg1( pVBInfo->Part2Port , 0x01 ) ; + tempax-- ; + XGINew_SetRegAND( pVBInfo->Part2Port , 0x01 , tempax ) ; + + /* if ( !( pVBInfo->VBType & VB_XGI301C ) ) */ + XGINew_SetRegAND( pVBInfo->Part2Port , 0x00 , 0xEF ) ; + } + + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + if ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) + { + XGINew_SetReg1( pVBInfo->Part2Port , 0x0B , 0x00 ) ; + } + } + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + return ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetLCDRegs */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetLCDRegs(USHORT ModeNo,USHORT ModeIdIndex, PXGI_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo) +{ + USHORT push1 , + push2 , + pushbx , + tempax , + tempbx , + tempcx , + temp , + tempah , + tempbh , + tempch , + resinfo , + modeflag , + CRT1Index ; + + XGI_LCDDesStruct *LCDBDesPtr = NULL ; + + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */ + resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */ + resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; + CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ; + CRT1Index &= IndexMask ; + } + + if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) ) + { + return ; + } + + tempbx = pVBInfo->HDE ; /* RHACTE=HDE-1 */ + + if ( XGI_IsLCDDualLink( pVBInfo ) ) + tempbx = tempbx >> 1 ; + + tempbx -= 1 ; + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x2C , temp ) ; + temp = ( tempbx & 0xFF00 ) >> 8 ; + temp = temp << 4 ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x2B , 0x0F , temp ) ; + temp = 0x01 ; + + if ( pVBInfo->LCDResInfo == Panel1280x1024 ) + { + if ( pVBInfo->ModeType == ModeEGA ) + { + if ( pVBInfo->VGAHDE >= 1024 ) + { + temp = 0x02 ; + if ( pVBInfo->LCDInfo & LCDVESATiming ) + temp = 0x01 ; + } + } + } + + XGINew_SetReg1( pVBInfo->Part2Port , 0x0B , temp ) ; + tempbx = pVBInfo->VDE ; /* RTVACTEO=(VDE-1)&0xFF */ + push1 = tempbx ; + tempbx-- ; + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x03 , temp ) ; + temp = ( ( tempbx & 0xFF00 ) >> 8 ) & 0x07 ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0C , ~0x07 , temp ) ; + + tempcx = pVBInfo->VT - 1 ; + push2 = tempcx + 1 ; + temp = tempcx & 0x00FF ; /* RVTVT=VT-1 */ + XGINew_SetReg1( pVBInfo->Part2Port , 0x19 , temp ) ; + temp = ( tempcx & 0xFF00 ) >> 8 ; + temp = temp << 5 ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x1A , temp ) ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x09 , 0xF0 , 0x00 ) ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0A , 0xF0 , 0x00 ) ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x17 , 0xFB , 0x00 ) ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x18 , 0xDF , 0x00 ) ; + + /* Customized LCDB Des no add */ + tempbx = 5 ; + LCDBDesPtr = ( XGI_LCDDesStruct * )XGI_GetLcdPtr( tempbx , ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; + tempah = pVBInfo->LCDResInfo ; + tempah &= PanelResInfo ; + + if ( ( tempah == Panel1024x768 ) || ( tempah == Panel1024x768x75 ) ) + { + tempbx = 1024 ; + tempcx = 768 ; + } + else if ( ( tempah == Panel1280x1024 ) || ( tempah == Panel1280x1024x75 ) ) + { + tempbx = 1280 ; + tempcx = 1024 ; + } + else if ( tempah == Panel1400x1050 ) + { + tempbx = 1400 ; + tempcx = 1050 ; + } + else + { + tempbx = 1600 ; + tempcx = 1200 ; + } + + if ( pVBInfo->LCDInfo & EnableScalingLCD ) + { + tempbx = pVBInfo->HDE ; + tempcx = pVBInfo->VDE ; + } + + pushbx = tempbx ; + tempax = pVBInfo->VT ; + pVBInfo->LCDHDES = LCDBDesPtr->LCDHDES ; + pVBInfo->LCDHRS = LCDBDesPtr->LCDHRS ; + pVBInfo->LCDVDES = LCDBDesPtr->LCDVDES ; + pVBInfo->LCDVRS = LCDBDesPtr->LCDVRS ; + tempbx = pVBInfo->LCDVDES ; + tempcx += tempbx ; + + if ( tempcx >= tempax ) + tempcx -= tempax ; /* lcdvdes */ + + temp = tempbx & 0x00FF ; /* RVEQ1EQ=lcdvdes */ + XGINew_SetReg1( pVBInfo->Part2Port , 0x05 , temp ) ; + temp = tempcx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x06 , temp ) ; + tempch = ( ( tempcx & 0xFF00 ) >> 8 ) & 0x07 ; + tempbh = ( ( tempbx & 0xFF00 ) >> 8 ) & 0x07 ; + tempah = tempch ; + tempah = tempah << 3 ; + tempah |= tempbh ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x02 , tempah ) ; + + /* getlcdsync() */ + XGI_GetLCDSync( &tempax , &tempbx,pVBInfo ) ; + tempcx = tempbx ; + tempax = pVBInfo->VT ; + tempbx = pVBInfo->LCDVRS ; + + /* if ( SetLCD_Info & EnableScalingLCD ) */ + tempcx += tempbx ; + if ( tempcx >= tempax ) + tempcx -= tempax ; + + temp = tempbx & 0x00FF ; /* RTVACTEE=lcdvrs */ + XGINew_SetReg1( pVBInfo->Part2Port , 0x04 , temp ) ; + temp = ( tempbx & 0xFF00 ) >> 8 ; + temp = temp << 4 ; + temp |= ( tempcx & 0x000F ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x01 , temp ) ; + tempcx = pushbx ; + tempax = pVBInfo->HT ; + tempbx = pVBInfo->LCDHDES ; + tempbx &= 0x0FFF ; + + if ( XGI_IsLCDDualLink( pVBInfo ) ) + { + tempax = tempax >> 1 ; + tempbx = tempbx >> 1 ; + tempcx = tempcx >> 1 ; + } + + if ( pVBInfo->VBType & VB_XGI302LV ) + tempbx += 1 ; + + if ( pVBInfo->VBType & VB_XGI301C ) /* tap4 */ + tempbx += 1 ; + + tempcx += tempbx ; + + if ( tempcx >= tempax ) + tempcx -= tempax ; + + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x1F , temp ) ; /* RHBLKE=lcdhdes */ + temp = ( ( tempbx & 0xFF00 ) >> 8 ) << 4 ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x20 , temp ) ; + temp = tempcx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x23 , temp ) ; /* RHEQPLE=lcdhdee */ + temp = ( tempcx & 0xFF00 ) >> 8 ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x25 , temp ) ; + + /* getlcdsync() */ + XGI_GetLCDSync( &tempax , &tempbx ,pVBInfo) ; + tempcx = tempax ; + tempax = pVBInfo->HT ; + tempbx = pVBInfo->LCDHRS ; + /* if ( SetLCD_Info & EnableScalingLCD) */ + if ( XGI_IsLCDDualLink( pVBInfo) ) + { + tempax = tempax >> 1 ; + tempbx = tempbx >> 1 ; + tempcx = tempcx >> 1 ; + } + + if ( pVBInfo->VBType & VB_XGI302LV ) + tempbx += 1 ; + + tempcx += tempbx ; + + if ( tempcx >= tempax ) + tempcx -= tempax ; + + temp = tempbx & 0x00FF ; /* RHBURSTS=lcdhrs */ + XGINew_SetReg1( pVBInfo->Part2Port , 0x1C , temp ) ; + + temp = ( tempbx & 0xFF00 ) >> 8 ; + temp = temp << 4 ; + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1D , ~0x0F0 , temp ) ; + temp = tempcx & 0x00FF ; /* RHSYEXP2S=lcdhre */ + XGINew_SetReg1( pVBInfo->Part2Port , 0x21 , temp ) ; + + if ( !( pVBInfo->LCDInfo & LCDVESATiming ) ) + { + if ( pVBInfo->VGAVDE == 525 ) + { + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + temp = 0xC6 ; + } + else + temp = 0xC4 ; + + XGINew_SetReg1( pVBInfo->Part2Port , 0x2f , temp ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x30 , 0xB3 ) ; + } + + if ( pVBInfo->VGAVDE == 420 ) + { + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + temp = 0x4F ; + } + else + temp = 0x4E ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x2f , temp ) ; + } + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetTap4Ptr */ +/* Input : */ +/* Output : di -> Tap4 Reg. Setting Pointer */ +/* Description : */ +/* --------------------------------------------------------------------- */ +XGI301C_Tap4TimingStruct* XGI_GetTap4Ptr(USHORT tempcx, PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempax , + tempbx , + i ; + + XGI301C_Tap4TimingStruct *Tap4TimingPtr ; + + if ( tempcx == 0 ) + { + tempax = pVBInfo->VGAHDE ; + tempbx = pVBInfo->HDE ; + } + else + { + tempax = pVBInfo->VGAVDE ; + tempbx = pVBInfo->VDE ; + } + + if ( tempax < tempbx ) + return &EnlargeTap4Timing[ 0 ] ; + else if( tempax == tempbx ) + return &NoScaleTap4Timing[ 0 ] ; /* 1:1 */ + else + Tap4TimingPtr = NTSCTap4Timing ; /* NTSC */ + + if ( pVBInfo->TVInfo & SetPALTV ) + Tap4TimingPtr = PALTap4Timing ; + + + if ( pVBInfo->VBInfo & SetCRT2ToYPbPr ) + { + if ( pVBInfo->TVInfo & SetYPbPrMode525i ) + Tap4TimingPtr = YPbPr525iTap4Timing ; + if ( pVBInfo->TVInfo & SetYPbPrMode525p ) + Tap4TimingPtr = YPbPr525pTap4Timing ; + if ( pVBInfo->TVInfo & SetYPbPrMode750p ) + Tap4TimingPtr = YPbPr750pTap4Timing ; + } + + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + Tap4TimingPtr = HiTVTap4Timing ; + + i = 0 ; + while( Tap4TimingPtr[ i ].DE != 0xFFFF ) + { + if ( Tap4TimingPtr[ i ].DE == tempax ) + break ; + i++ ; + } + return &Tap4TimingPtr[ i ] ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetTap4Regs */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetTap4Regs( PVB_DEVICE_INFO pVBInfo) +{ + USHORT i , + j ; + + XGI301C_Tap4TimingStruct *Tap4TimingPtr ; + + if ( !( pVBInfo->VBType & VB_XGI301C ) ) + return ; + +#ifndef Tap4 + XGINew_SetRegAND( pVBInfo->Part2Port , 0x4E , 0xEB ) ; /* Disable Tap4 */ +#else /* Tap4 Setting */ + + Tap4TimingPtr = XGI_GetTap4Ptr( 0 , pVBInfo) ; /* Set Horizontal Scaling */ + for( i = 0x80 , j = 0 ; i <= 0xBF ; i++ , j++ ) + XGINew_SetReg1( pVBInfo->Part2Port , i , Tap4TimingPtr->Reg[ j ] ) ; + + if ( ( pVBInfo->VBInfo & SetCRT2ToTV ) && ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) ) ) + { + Tap4TimingPtr = XGI_GetTap4Ptr( 1 , pVBInfo); /* Set Vertical Scaling */ + for( i = 0xC0 , j = 0 ; i < 0xFF ; i++ , j++ ) + XGINew_SetReg1( pVBInfo->Part2Port , i , Tap4TimingPtr->Reg[ j ] ) ; + } + + if ( ( pVBInfo->VBInfo & SetCRT2ToTV ) && ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) ) ) + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x4E , ~0x14 , 0x04 ) ; /* Enable V.Scaling */ + else + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x4E , ~0x14 , 0x10 ) ; /* Enable H.Scaling */ +#endif +} + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetGroup3 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetGroup3(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo) +{ + USHORT i; + UCHAR *tempdi; + USHORT modeflag; + + if(ModeNo<=0x13) + { + modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */ + } + else + { + modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */ + } + + + XGINew_SetReg1(pVBInfo->Part3Port,0x00,0x00); + if(pVBInfo->TVInfo&SetPALTV) + { + XGINew_SetReg1(pVBInfo->Part3Port,0x13,0xFA); + XGINew_SetReg1(pVBInfo->Part3Port,0x14,0xC8); + } + else + { + XGINew_SetReg1(pVBInfo->Part3Port,0x13,0xF5); + XGINew_SetReg1(pVBInfo->Part3Port,0x14,0xB7); + } + + if(!(pVBInfo->VBInfo&SetCRT2ToTV)) + { + return; + } + + if(pVBInfo->TVInfo&SetPALMTV) + { + XGINew_SetReg1(pVBInfo->Part3Port,0x13,0xFA); + XGINew_SetReg1(pVBInfo->Part3Port,0x14,0xC8); + XGINew_SetReg1(pVBInfo->Part3Port,0x3D,0xA8); + } + + if((pVBInfo->VBInfo&SetCRT2ToHiVisionTV)|| (pVBInfo->VBInfo&SetCRT2ToYPbPr)) + { + if(pVBInfo->TVInfo & SetYPbPrMode525i) + { + return; + } + tempdi=pVBInfo->HiTVGroup3Data; + if(pVBInfo->SetFlag&TVSimuMode) + { + tempdi=pVBInfo->HiTVGroup3Simu; + if(!(modeflag&Charx8Dot)) + { + tempdi=pVBInfo->HiTVGroup3Text; + } + } + + if(pVBInfo->TVInfo & SetYPbPrMode525p) + { + tempdi=pVBInfo->Ren525pGroup3; + } + if(pVBInfo->TVInfo & SetYPbPrMode750p) + { + tempdi=pVBInfo->Ren750pGroup3; + } + + for(i=0;i<=0x3E;i++) + { + XGINew_SetReg1(pVBInfo->Part3Port,i,tempdi[i]); + } + if(pVBInfo->VBType&VB_XGI301C) /* Marcovision */ + { + if(pVBInfo->TVInfo & SetYPbPrMode525p) + { + XGINew_SetReg1(pVBInfo->Part3Port,0x28,0x3f); + } + } + } + return; +} /* {end of XGI_SetGroup3} */ + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetGroup4 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetGroup4(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempax , + tempcx , + tempbx , + modeflag , + temp , + temp2 ; + + ULONG tempebx , + tempeax , + templong ; + + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */ + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */ + } + + temp = pVBInfo->RVBHCFACT ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x13 , temp ) ; + + tempbx = pVBInfo->RVBHCMAX ; + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x14 , temp ) ; + temp2 = ( ( tempbx & 0xFF00 ) >> 8 ) << 7 ; + tempcx = pVBInfo->VGAHT - 1 ; + temp = tempcx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x16 , temp ) ; + + temp =( ( tempcx & 0xFF00 ) >> 8 ) << 3 ; + temp2 |= temp ; + + tempcx = pVBInfo->VGAVT - 1 ; + if ( !( pVBInfo->VBInfo & SetCRT2ToTV ) ) + { + tempcx -= 5 ; + } + + temp = tempcx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x17 , temp ) ; + temp = temp2 | ( ( tempcx & 0xFF00 ) >> 8 ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x15 , temp ) ; + XGINew_SetRegOR( pVBInfo->Part4Port , 0x0D , 0x08 ) ; + tempcx = pVBInfo->VBInfo ; + tempbx = pVBInfo->VGAHDE ; + + if ( modeflag & HalfDCLK ) + { + tempbx = tempbx >> 1 ; + } + + if ( XGI_IsLCDDualLink( pVBInfo ) ) + tempbx = tempbx >> 1 ; + + if(tempcx&SetCRT2ToHiVisionTV) + { + temp=0; + if(tempbx<=1024) + temp=0xA0; + if(tempbx == 1280) + temp = 0xC0; + } + else if(tempcx&SetCRT2ToTV) + { + temp=0xA0; + if(tempbx <= 800) + temp=0x80; + } + else + { + temp=0x80; + if(pVBInfo->VBInfo&SetCRT2ToLCD) + { + temp=0; + if(tempbx>800) + temp=0x60; + } + } + + if ( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) + { + temp = 0x00 ; + if ( pVBInfo->VGAHDE == 1280 ) + temp = 0x40 ; + if ( pVBInfo->VGAHDE == 1024 ) + temp = 0x20 ; + } + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0E , ~0xEF , temp ) ; + + tempebx = pVBInfo->VDE ; + + if ( tempcx & SetCRT2ToHiVisionTV ) + { + if ( !( temp & 0xE000 ) ) + tempbx = tempbx >> 1 ; + } + + tempcx = pVBInfo->RVBHRS ; + temp = tempcx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x18 , temp ); + + tempeax = pVBInfo->VGAVDE ; + tempcx |= 0x04000 ; + + + if ( tempeax <= tempebx ) + { + tempcx=(tempcx&(~0x4000)); + tempeax = pVBInfo->VGAVDE ; + } + else + { + tempeax -= tempebx ; + } + + + templong = ( tempeax * 256 * 1024 ) % tempebx ; + tempeax = ( tempeax * 256 * 1024 ) / tempebx ; + tempebx = tempeax ; + + if ( templong != 0 ) + { + tempebx++ ; + } + + + temp = ( USHORT )( tempebx & 0x000000FF ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x1B , temp ) ; + + temp = ( USHORT )( ( tempebx & 0x0000FF00 ) >> 8 ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x1A , temp ) ; + tempbx = ( USHORT )( tempebx >> 16 ) ; + temp = tempbx & 0x00FF ; + temp = temp << 4 ; + temp |= ( ( tempcx & 0xFF00 ) >> 8 ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x19 , temp ) ; + + /* 301b */ + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + temp = 0x0028 ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x1C , temp ) ; + tempax = pVBInfo->VGAHDE ; + if ( modeflag & HalfDCLK ) + { + tempax = tempax >> 1 ; + } + + if ( XGI_IsLCDDualLink( pVBInfo ) ) + tempax = tempax >> 1 ; + + /* if((pVBInfo->VBInfo&(SetCRT2ToLCD))||((pVBInfo->TVInfo&SetYPbPrMode525p)||(pVBInfo->TVInfo&SetYPbPrMode750p))) { */ + if ( pVBInfo->VBInfo & SetCRT2ToLCD ) + { + if ( tempax > 800 ) + tempax -= 800 ; + } + else + { + if ( pVBInfo->VGAHDE > 800 ) + { + if ( pVBInfo->VGAHDE == 1024 ) + tempax = ( tempax * 25 / 32 ) - 1 ; + else + tempax = ( tempax * 20 / 32 ) - 1 ; + } + } + tempax -= 1 ; + +/* + if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToHiVisionTV ) ) + { + if ( pVBInfo->VBType & VB_XGI301LV ) + { + if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) ) + { + if ( pVBInfo->VGAHDE > 800 ) + { + if ( pVBInfo->VGAHDE == 1024 ) + tempax = ( tempax * 25 / 32 ) - 1 ; + else + tempax = ( tempax * 20 / 32 ) - 1 ; + } + } + } + else + { + if ( pVBInfo->VGAHDE > 800 ) + { + if ( pVBInfo->VGAHDE == 1024 ) + tempax = ( tempax * 25 / 32 ) - 1 ; + else + tempax = ( tempax * 20 / 32 ) - 1 ; + } + } + } +*/ + + temp = ( tempax & 0xFF00 ) >> 8 ; + temp = ( ( temp & 0x0003 ) << 4 ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x1E , temp ) ; + temp = ( tempax & 0x00FF ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x1D , temp ) ; + + if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToHiVisionTV ) ) + { + if ( pVBInfo->VGAHDE > 800 ) + { + XGINew_SetRegOR( pVBInfo->Part4Port , 0x1E , 0x08 ) ; + } + } + temp = 0x0036 ; + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + if ( !( pVBInfo->TVInfo & ( NTSC1024x768 | SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i ) ) ) + { + temp |= 0x0001 ; + if ( ( pVBInfo->VBInfo & SetInSlaveMode ) && ( !( pVBInfo->TVInfo & TVSimuMode ) ) ) + temp &= ( ~0x0001 ) ; + } + } + + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x1F , 0x00C0 , temp ) ; + tempbx = pVBInfo->HT ; + if ( XGI_IsLCDDualLink( pVBInfo ) ) + tempbx = tempbx >> 1 ; + tempbx = ( tempbx >> 1 ) - 2 ; + temp = ( ( tempbx & 0x0700 ) >> 8 ) << 3 ; + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x21 , 0x00C0 , temp ) ; + temp = tempbx & 0x00FF ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x22 , temp ) ; + } + /* end 301b */ + + if ( pVBInfo->ISXPDOS == 0 ) + XGI_SetCRT2VCLK( ModeNo , ModeIdIndex , RefreshRateTableIndex, pVBInfo ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetGroup5 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetGroup5( USHORT ModeNo , USHORT ModeIdIndex , PVB_DEVICE_INFO pVBInfo) +{ + USHORT Pindex , + Pdata ; + + Pindex = pVBInfo->Part5Port ; + Pdata = pVBInfo->Part5Port + 1 ; + if ( pVBInfo->ModeType == ModeVGA ) + { + if ( !( pVBInfo->VBInfo & ( SetInSlaveMode | LoadDACFlag | CRT2DisplayFlag ) ) ) + { + XGINew_EnableCRT2(pVBInfo) ; + /* LoadDAC2(pVBInfo->Part5Port,ModeNo,ModeIdIndex); */ + } + } + return ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetLcdPtr */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void* XGI_GetLcdPtr( USHORT BX , USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT i , + tempdx , + tempcx , + tempbx , + tempal , + modeflag , + table ; + + XGI330_LCDDataTablStruct *tempdi = 0 ; + + + tempbx = BX; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + tempal = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ; + } + + tempal = tempal & 0x0f ; + + if ( tempbx <= 1 ) /* ExpLink */ + { + if ( ModeNo <= 0x13 ) + { + tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ; /* find no Ext_CRT2CRTC2 */ + } + else + { + tempal= pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ; + } + + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + { + if ( ModeNo <= 0x13 ) + tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC2 ; + else + tempal= pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC2 ; + } + + if ( tempbx & 0x01 ) + tempal = ( tempal >> 4 ) ; + + tempal = ( tempal & 0x0f ) ; + } + + tempcx = LCDLenList[ tempbx ] ; /* mov cl,byte ptr cs:LCDLenList[bx] */ + + if ( pVBInfo->LCDInfo & EnableScalingLCD ) /* ScaleLCD */ + { + if ( ( tempbx == 5 ) || ( tempbx ) == 7 ) + tempcx = LCDDesDataLen2 ; + else if ( ( tempbx == 3 ) || ( tempbx == 8 ) ) + tempcx = LVDSDesDataLen2 ; + } + /* mov di, word ptr cs:LCDDataList[bx] */ + /* tempdi=pVideoMemory[LCDDataList+tempbx*2]|(pVideoMemory[LCDDataList+tempbx*2+1]<<8); */ + + switch( tempbx ) + { + case 0: + tempdi = XGI_EPLLCDCRT1Ptr_H ; + break ; + case 1: + tempdi = XGI_EPLLCDCRT1Ptr_V ; + break ; + case 2: + tempdi = XGI_EPLLCDDataPtr ; + break ; + case 3: + tempdi = XGI_EPLLCDDesDataPtr ; + break ; + case 4: + tempdi = XGI_LCDDataTable ; + break ; + case 5: + tempdi = XGI_LCDDesDataTable ; + break ; + case 6: + tempdi = XGI_EPLCHLCDRegPtr ; + break ; + case 7: + case 8: + case 9: + tempdi = 0 ; + break ; + default: + break ; + } + + if ( tempdi == 0x00 ) /* OEMUtil */ + return 0 ; + + table = tempbx ; + i = 0 ; + + while( tempdi[ i ].PANELID != 0xff ) + { + tempdx = pVBInfo->LCDResInfo ; + if ( tempbx & 0x0080 ) /* OEMUtil */ + { + tempbx &= ( ~0x0080 ) ; + tempdx = pVBInfo->LCDTypeInfo ; + } + + if ( pVBInfo->LCDInfo & EnableScalingLCD ) + tempdx &= ( ~PanelResInfo ) ; + + if ( tempdi[ i ].PANELID == tempdx ) + { + tempbx = tempdi[ i ].MASK ; + tempdx = pVBInfo->LCDInfo ; + + if ( ModeNo <= 0x13 ) /* alan 09/10/2003 */ + tempdx |= SetLCDStdMode ; + + if ( modeflag & HalfDCLK ) + tempdx |= SetLCDLowResolution ; + + tempbx &= tempdx; + if ( tempbx == tempdi[ i ].CAP ) + break ; + } + i++ ; + } + + if ( table == 0 ) + { + switch( tempdi[ i ].DATAPTR ) + { + case 0: + return &XGI_LVDSCRT11024x768_1_H[ tempal ] ; + break ; + case 1: + return &XGI_LVDSCRT11024x768_2_H[ tempal ] ; + break ; + case 2: + return &XGI_LVDSCRT11280x1024_1_H[ tempal ] ; + break ; + case 3: + return &XGI_LVDSCRT11280x1024_2_H[ tempal ] ; + break ; + case 4: + return &XGI_LVDSCRT11400x1050_1_H[ tempal ] ; + break ; + case 5: + return &XGI_LVDSCRT11400x1050_2_H[ tempal ] ; + break ; + case 6: + return &XGI_LVDSCRT11600x1200_1_H[ tempal ] ; + break ; + case 7: + return &XGI_LVDSCRT11024x768_1_Hx75[ tempal ] ; + break ; + case 8: + return &XGI_LVDSCRT11024x768_2_Hx75[ tempal ] ; + break ; + case 9: + return &XGI_LVDSCRT11280x1024_1_Hx75[ tempal ] ; + break ; + case 10: + return &XGI_LVDSCRT11280x1024_2_Hx75[ tempal ] ; + break ; + default: + break ; + } + } + else if ( table == 1 ) + { + switch( tempdi[ i ].DATAPTR ) + { + case 0: + return &XGI_LVDSCRT11024x768_1_V[ tempal ] ; + break ; + case 1: + return &XGI_LVDSCRT11024x768_2_V[ tempal ] ; + break ; + case 2: + return &XGI_LVDSCRT11280x1024_1_V[ tempal ] ; + break ; + case 3: + return &XGI_LVDSCRT11280x1024_2_V[ tempal ] ; + break ; + case 4: + return &XGI_LVDSCRT11400x1050_1_V[ tempal ] ; + break ; + case 5: + return &XGI_LVDSCRT11400x1050_2_V[ tempal ] ; + break ; + case 6: + return &XGI_LVDSCRT11600x1200_1_V[ tempal ] ; + break ; + case 7: + return &XGI_LVDSCRT11024x768_1_Vx75[ tempal ] ; + break ; + case 8: + return &XGI_LVDSCRT11024x768_2_Vx75[ tempal ] ; + break ; + case 9: + return &XGI_LVDSCRT11280x1024_1_Vx75[ tempal ] ; + break ; + case 10: + return &XGI_LVDSCRT11280x1024_2_Vx75[ tempal ] ; + break ; + default: + break ; + } + } + else if ( table == 2 ) + { + switch( tempdi[ i ].DATAPTR ) + { + case 0: + return &XGI_LVDS1024x768Data_1[ tempal ] ; + break ; + case 1: + return &XGI_LVDS1024x768Data_2[ tempal ] ; + break ; + case 2: + return &XGI_LVDS1280x1024Data_1[ tempal ] ; + break ; + case 3: + return &XGI_LVDS1280x1024Data_2[ tempal ] ; + break ; + case 4: + return &XGI_LVDS1400x1050Data_1[ tempal ] ; + break ; + case 5: + return &XGI_LVDS1400x1050Data_2[ tempal ] ; + break ; + case 6: + return &XGI_LVDS1600x1200Data_1[ tempal ] ; + break ; + case 7: + return &XGI_LVDSNoScalingData[ tempal ] ; + break ; + case 8: + return &XGI_LVDS1024x768Data_1x75[ tempal ] ; + break ; + case 9: + return &XGI_LVDS1024x768Data_2x75[ tempal ] ; + break ; + case 10: + return &XGI_LVDS1280x1024Data_1x75[ tempal ] ; + break ; + case 11: + return &XGI_LVDS1280x1024Data_2x75[ tempal ] ; + break ; + case 12: + return &XGI_LVDSNoScalingDatax75[ tempal ] ; + break ; + default: + break ; + } + } + else if ( table == 3 ) + { + switch( tempdi[ i ].DATAPTR ) + { + case 0: + return &XGI_LVDS1024x768Des_1[ tempal ] ; + break ; + case 1: + return &XGI_LVDS1024x768Des_3[ tempal ] ; + break ; + case 2: + return &XGI_LVDS1024x768Des_2[ tempal ] ; + break ; + case 3: + return &XGI_LVDS1280x1024Des_1[ tempal ] ; + break ; + case 4: + return &XGI_LVDS1280x1024Des_2[ tempal ] ; + break ; + case 5: + return &XGI_LVDS1400x1050Des_1[ tempal ] ; + break ; + case 6: + return &XGI_LVDS1400x1050Des_2[ tempal ] ; + break ; + case 7: + return &XGI_LVDS1600x1200Des_1[ tempal ] ; + break ; + case 8: + return &XGI_LVDSNoScalingDesData[ tempal ] ; + break ; + case 9: + return &XGI_LVDS1024x768Des_1x75[ tempal ] ; + break ; + case 10: + return &XGI_LVDS1024x768Des_3x75[ tempal ] ; + break ; + case 11: + return &XGI_LVDS1024x768Des_2x75[ tempal ] ; + break; + case 12: + return &XGI_LVDS1280x1024Des_1x75[ tempal ] ; + break ; + case 13: + return &XGI_LVDS1280x1024Des_2x75[ tempal ] ; + break ; + case 14: + return &XGI_LVDSNoScalingDesDatax75[ tempal ] ; + break ; + default: + break ; + } + } + else if ( table == 4 ) + { + switch( tempdi[ i ].DATAPTR ) + { + case 0: + return &XGI_ExtLCD1024x768Data[ tempal ] ; + break ; + case 1: + return &XGI_StLCD1024x768Data[ tempal ] ; + break ; + case 2: + return &XGI_CetLCD1024x768Data[ tempal ] ; + break ; + case 3: + return &XGI_ExtLCD1280x1024Data[ tempal ] ; + break ; + case 4: + return &XGI_StLCD1280x1024Data[ tempal ] ; + break ; + case 5: + return &XGI_CetLCD1280x1024Data[ tempal ] ; + break ; + case 6: + return &XGI_ExtLCD1400x1050Data[ tempal ] ; + break ; + case 7: + return &XGI_StLCD1400x1050Data[ tempal ] ; + break ; + case 8: + return &XGI_CetLCD1400x1050Data[ tempal ] ; + break ; + case 9: + return &XGI_ExtLCD1600x1200Data[ tempal ] ; + break ; + case 10: + return &XGI_StLCD1600x1200Data[ tempal ] ; + break ; + case 11: + return &XGI_NoScalingData[ tempal ] ; + break ; + case 12: + return &XGI_ExtLCD1024x768x75Data[ tempal ] ; + break ; + case 13: + return &XGI_ExtLCD1024x768x75Data[ tempal ] ; + break ; + case 14: + return &XGI_CetLCD1024x768x75Data[ tempal ] ; + break ; + case 15: + return &XGI_ExtLCD1280x1024x75Data[ tempal ] ; + break ; + case 16: + return &XGI_StLCD1280x1024x75Data[ tempal ] ; + break; + case 17: + return &XGI_CetLCD1280x1024x75Data[ tempal ] ; + break; + case 18: + return &XGI_NoScalingDatax75[ tempal ] ; + break ; + default: + break ; + } + } + else if ( table == 5 ) + { + switch( tempdi[ i ].DATAPTR ) + { + case 0: + return &XGI_ExtLCDDes1024x768Data[ tempal ] ; + break ; + case 1: + return &XGI_StLCDDes1024x768Data[ tempal ] ; + break ; + case 2: + return &XGI_CetLCDDes1024x768Data[ tempal ] ; + break ; + case 3: + if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) ) + return &XGI_ExtLCDDLDes1280x1024Data[ tempal ] ; + else + return &XGI_ExtLCDDes1280x1024Data[ tempal ] ; + break ; + case 4: + if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) ) + return &XGI_StLCDDLDes1280x1024Data[ tempal ] ; + else + return &XGI_StLCDDes1280x1024Data[ tempal ] ; + break ; + case 5: + if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) ) + return &XGI_CetLCDDLDes1280x1024Data[ tempal ] ; + else + return &XGI_CetLCDDes1280x1024Data[ tempal ] ; + break ; + case 6: + if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) ) + return &XGI_ExtLCDDLDes1400x1050Data[ tempal ] ; + else + return &XGI_ExtLCDDes1400x1050Data[ tempal ] ; + break ; + case 7: + if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) ) + return &XGI_StLCDDLDes1400x1050Data[ tempal ] ; + else + return &XGI_StLCDDes1400x1050Data[ tempal ] ; + break ; + case 8: + return &XGI_CetLCDDes1400x1050Data[ tempal ] ; + break ; + case 9: + return &XGI_CetLCDDes1400x1050Data2[ tempal ] ; + break ; + case 10: + if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) ) + return &XGI_ExtLCDDLDes1600x1200Data[ tempal ] ; + else + return &XGI_ExtLCDDes1600x1200Data[ tempal ] ; + break ; + case 11: + if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) ) + return &XGI_StLCDDLDes1600x1200Data[ tempal ] ; + else + return &XGI_StLCDDes1600x1200Data[ tempal ] ; + break ; + case 12: + return &XGI_NoScalingDesData[ tempal ] ; + break; + case 13: + return &XGI_ExtLCDDes1024x768x75Data[ tempal ] ; + break ; + case 14: + return &XGI_StLCDDes1024x768x75Data[ tempal ] ; + break ; + case 15: + return &XGI_CetLCDDes1024x768x75Data[ tempal ] ; + break ; + case 16: + if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) ) + return &XGI_ExtLCDDLDes1280x1024x75Data[ tempal ] ; + else + return &XGI_ExtLCDDes1280x1024x75Data[ tempal ] ; + break ; + case 17: + if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) ) + return &XGI_StLCDDLDes1280x1024x75Data[ tempal ] ; + else + return &XGI_StLCDDes1280x1024x75Data[ tempal ] ; + break ; + case 18: + if ( ( pVBInfo->VBType & VB_XGI301LV ) || ( pVBInfo->VBType & VB_XGI302LV ) ) + return &XGI_CetLCDDLDes1280x1024x75Data[ tempal ] ; + else + return &XGI_CetLCDDes1280x1024x75Data[ tempal ] ; + break ; + case 19: + return &XGI_NoScalingDesDatax75[ tempal ] ; + break ; + default: + break ; + } + } + else if ( table == 6 ) + { + switch( tempdi[ i ].DATAPTR ) + { + case 0: + return &XGI_CH7017LV1024x768[ tempal ] ; + break ; + case 1: + return &XGI_CH7017LV1400x1050[ tempal ] ; + break ; + default: + break ; + } + } + return 0 ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetTVPtr */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void* XGI_GetTVPtr (USHORT BX,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT i , tempdx , tempbx , tempal , modeflag , table ; + XGI330_TVDataTablStruct *tempdi = 0 ; + + tempbx = BX ; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + tempal = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ; + } + + tempal = tempal & 0x3f ; + table = tempbx ; + + switch( tempbx ) + { + case 0: + tempdi = 0 ; /*EPLCHTVCRT1Ptr_H;*/ + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + tempdi = XGI_EPLCHTVCRT1Ptr; + } + break ; + case 1: + tempdi = 0 ; /*EPLCHTVCRT1Ptr_V;*/ + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + tempdi = XGI_EPLCHTVCRT1Ptr; + } + break ; + case 2: + tempdi = XGI_EPLCHTVDataPtr ; + break ; + case 3: + tempdi = 0 ; + break ; + case 4: + tempdi = XGI_TVDataTable ; + break ; + case 5: + tempdi = 0 ; + break ; + case 6: + tempdi = XGI_EPLCHTVRegPtr ; + break ; + default: + break ; + } + + if ( tempdi == 0x00 ) /* OEMUtil */ + return( 0 ) ; + + tempdx = pVBInfo->TVInfo ; + + if ( pVBInfo->VBInfo & SetInSlaveMode ) + tempdx = tempdx | SetTVLockMode ; + + if ( modeflag & HalfDCLK ) + tempdx = tempdx | SetTVLowResolution ; + + i = 0 ; + + while( tempdi[ i ].MASK != 0xffff ) + { + if ( ( tempdx & tempdi[ i ].MASK ) == tempdi[ i ].CAP ) + break ; + i++ ; + } + + if ( table == 0x00 ) /* 07/05/22 */ + { +#ifdef WIN2000 + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + switch( tempdi[ i ].DATAPTR ) + { + case 0: + return &CH7007TVCRT1UNTSC_H[ tempal ] ; + break ; + case 1: + return &CH7007TVCRT1ONTSC_H[ tempal ] ; + break ; + case 2: + return &CH7007TVCRT1UPAL_H[ tempal ] ; + break ; + case 3: + return &CH7007TVCRT1OPAL_H[ tempal ] ; + break ; + default: + break ; + } + } +#endif + } + else if ( table == 0x01 ) + { +#ifdef WIN2000 + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + switch( tempdi[ i ].DATAPTR ) + { + case 0: + return &CH7007TVCRT1UNTSC_V[ tempal ] ; + break ; + case 1: + return &CH7007TVCRT1ONTSC_V[ tempal ] ; + break ; + case 2: + return &CH7007TVCRT1UPAL_V[ tempal ] ; + break ; + case 3: + return &CH7007TVCRT1OPAL_V[ tempal ] ; + break ; + default: + break ; + } + } +#endif + } + else if ( table == 0x04 ) + { + switch( tempdi[ i ].DATAPTR ) + { + case 0: + return &XGI_ExtPALData[ tempal ] ; + break ; + case 1: + return &XGI_ExtNTSCData[ tempal ] ; + break ; + case 2: + return &XGI_StPALData[ tempal ] ; + break ; + case 3: + return &XGI_StNTSCData[ tempal ] ; + break ; + case 4: + return &XGI_ExtHiTVData[ tempal ] ; + break ; + case 5: + return &XGI_St2HiTVData[ tempal ] ; + break ; + case 6: + return &XGI_ExtYPbPr525iData[ tempal ] ; + break ; + case 7: + return &XGI_ExtYPbPr525pData[ tempal ] ; + break ; + case 8: + return &XGI_ExtYPbPr750pData[ tempal ] ; + break ; + case 9: + return &XGI_StYPbPr525iData[ tempal ] ; + break ; + case 10: + return &XGI_StYPbPr525pData[ tempal ] ; + break ; + case 11: + return &XGI_StYPbPr750pData[ tempal ] ; + break; + case 12: /* avoid system hang */ + return &XGI_ExtNTSCData[ tempal ] ; + break ; + case 13: + return &XGI_St1HiTVData[ tempal ] ; + break ; + default: + break ; + } + } + else if( table == 0x02 ) + { + switch( tempdi[ i ].DATAPTR ) + { + case 0: + return &XGI_CHTVUNTSCData[ tempal ] ; + break ; + case 1: + return &XGI_CHTVONTSCData[ tempal ] ; + break ; + case 2: + return &XGI_CHTVUPALData[ tempal ] ; + break ; + case 3: + return &XGI_CHTVOPALData[ tempal ] ; + break ; + default: + break ; + } + } + else if( table == 0x06 ) + { +#ifdef WIN2000 + if ( pVBInfo->IF_DEF_CH7007 == 1 ) + { + /* VideoDebugPrint((0, "XGI_GetTVPtr: pVBInfo->IF_DEF_CH7007==1\n")); */ + switch( tempdi[ i ].DATAPTR ) + { + case 0: + return &CH7007TVReg_UNTSC[ tempal ] ; + break ; + case 1: + return &CH7007TVReg_ONTSC[ tempal ] ; + break ; + case 2: + return &CH7007TVReg_UPAL[ tempal ] ; + break ; + case 3: + return &CH7007TVReg_OPAL[ tempal ] ; + break ; + default: + break ; + } + } + else + { + switch( tempdi[ i ].DATAPTR ) + { + case 0: + return &XGI_CHTVRegUNTSC[ tempal ] ; + break ; + case 1: + return &XGI_CHTVRegONTSC[ tempal ] ; + break ; + case 2: + return &XGI_CHTVRegUPAL[ tempal ] ; + break ; + case 3: + return &XGI_CHTVRegOPAL[ tempal ] ; + break ; + default: + break ; + } + } +#endif + } + return( 0 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_BacklightByDrv */ +/* Input : */ +/* Output : TRUE -> Skip backlight control */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGI_BacklightByDrv( PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR tempah ; + + tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x3A ) ; + if ( tempah & BacklightControlBit ) + return TRUE ; + else + return FALSE ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_FirePWDDisable */ +/* Input : */ +/* Output : */ +/* Description : Turn off VDD & Backlight : Fire disable procedure */ +/* --------------------------------------------------------------------- */ +/* +void XGI_FirePWDDisable( PVB_DEVICE_INFO pVBInfo ) +{ + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x26 , 0x00 , 0xFC ) ; +} +*/ + +/* --------------------------------------------------------------------- */ +/* Function : XGI_FirePWDEnable */ +/* Input : */ +/* Output : */ +/* Description : Turn on VDD & Backlight : Fire enable procedure */ +/* --------------------------------------------------------------------- */ +void XGI_FirePWDEnable(PVB_DEVICE_INFO pVBInfo ) +{ + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x26 , 0x03 , 0xFC ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_EnableGatingCRT */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_EnableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) +{ + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x63 , 0xBF , 0x40 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_DisableGatingCRT */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_DisableGatingCRT(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) +{ + + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x63 , 0xBF , 0x00 ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetPanelDelay */ +/* Input : */ +/* Output : */ +/* Description : */ +/* I/P : bl : 1 ; T1 : the duration between CPL on and signal on */ +/* : bl : 2 ; T2 : the duration signal on and Vdd on */ +/* : bl : 3 ; T3 : the duration between CPL off and signal off */ +/* : bl : 4 ; T4 : the duration signal off and Vdd off */ +/* --------------------------------------------------------------------- */ +void XGI_SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo) +{ + USHORT index ; + + index = XGI_GetLCDCapPtr(pVBInfo) ; + + if ( tempbl == 1 ) + XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S1, pVBInfo ) ; + + if ( tempbl == 2 ) + XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S2, pVBInfo ) ; + + if ( tempbl == 3 ) + XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S3, pVBInfo ) ; + + if ( tempbl == 4 ) + XGINew_LCD_Wait_Time( pVBInfo->LCDCapList[ index ].PSC_S4, pVBInfo ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetPanelPower */ +/* Input : */ +/* Output : */ +/* Description : */ +/* I/O : ah = 0011b = 03h ; Backlight on, Power on */ +/* = 0111b = 07h ; Backlight on, Power off */ +/* = 1011b = 0Bh ; Backlight off, Power on */ +/* = 1111b = 0Fh ; Backlight off, Power off */ +/* --------------------------------------------------------------------- */ +void XGI_SetPanelPower(USHORT tempah,USHORT tempbl, PVB_DEVICE_INFO pVBInfo) +{ + if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x26 , tempbl , tempah ) ; + else + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x11 , tempbl , tempah ) ; +} + +UCHAR XG21GPIODataTransfer(UCHAR ujDate) +{ + UCHAR ujRet = 0; + UCHAR i = 0; + + for (i=0; i<8; i++) + { + ujRet = ujRet << 1; + /* ujRet |= GETBITS(ujDate >> i, 0:0); */ + ujRet |= (ujDate >> i) & 1; + } + + return ujRet; +} + +/*----------------------------------------------------------------------------*/ +/* output */ +/* bl[5] : LVDS signal */ +/* bl[1] : LVDS backlight */ +/* bl[0] : LVDS VDD */ +/*----------------------------------------------------------------------------*/ +UCHAR XGI_XG21GetPSCValue(PVB_DEVICE_INFO pVBInfo) +{ + UCHAR CR4A,temp; + + CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ; + XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x23 ) ; /* enable GPIO write */ + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ; + + temp = XG21GPIODataTransfer(temp); + temp &= 0x23; + XGINew_SetReg1( pVBInfo->P3d4 , 0x4A , CR4A ) ; + return temp; +} + +/*----------------------------------------------------------------------------*/ +/* output */ +/* bl[5] : LVDS signal */ +/* bl[1] : LVDS backlight */ +/* bl[0] : LVDS VDD */ +/*----------------------------------------------------------------------------*/ +UCHAR XGI_XG27GetPSCValue(PVB_DEVICE_INFO pVBInfo) +{ + UCHAR CR4A,CRB4,temp; + + CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ; + XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~0x0C ) ; /* enable GPIO write */ + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ; + + temp &= 0x0C; + temp >>= 2; + XGINew_SetReg1( pVBInfo->P3d4 , 0x4A , CR4A ) ; + CRB4 = XGINew_GetReg1( pVBInfo->P3d4 , 0xB4 ) ; + temp |= ((CRB4&0x04)<<3); + return temp; +} +/*----------------------------------------------------------------------------*/ +/* input */ +/* bl[5] : 1;LVDS signal on */ +/* bl[1] : 1;LVDS backlight on */ +/* bl[0] : 1:LVDS VDD on */ +/* bh: 100000b : clear bit 5, to set bit5 */ +/* 000010b : clear bit 1, to set bit1 */ +/* 000001b : clear bit 0, to set bit0 */ +/*----------------------------------------------------------------------------*/ +void XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo) +{ + UCHAR CR4A,temp; + + CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ; + tempbh &= 0x23; + tempbl &= 0x23; + XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~tempbh ) ; /* enable GPIO write */ + + if (tempbh&0x20) + { + temp = (tempbl>>4)&0x02; + + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0xB4 , ~0x02 , temp) ; /* CR B4[1] */ + + } + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x48 ) ; + + temp = XG21GPIODataTransfer(temp); + temp &= ~tempbh; + temp |= tempbl; + XGINew_SetReg1( pVBInfo->P3d4 , 0x48 , temp ) ; +} + +void XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo) +{ + UCHAR CR4A,temp; + USHORT tempbh0,tempbl0; + + tempbh0 = tempbh; + tempbl0 = tempbl; + tempbh0 &= 0x20; + tempbl0 &= 0x20; + tempbh0 >>= 3; + tempbl0 >>= 3; + + if (tempbh&0x20) + { + temp = (tempbl>>4)&0x02; + + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0xB4 , ~0x02 , temp) ; /* CR B4[1] */ + + } + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0xB4 , ~tempbh0 , tempbl0 ) ; + + CR4A = XGINew_GetReg1( pVBInfo->P3d4 , 0x4A ) ; + tempbh &= 0x03; + tempbl &= 0x03; + tempbh <<= 2; + tempbl <<= 2; /* GPIOC,GPIOD */ + XGINew_SetRegAND( pVBInfo->P3d4 , 0x4A , ~tempbh ) ; /* enable GPIO write */ + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x48 , ~tempbh , tempbl ) ; +} + +/* --------------------------------------------------------------------- */ +USHORT XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo) +{ + USHORT index ; + + index = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ; + if (index<sizeof(XGI21_LCDCapList)/sizeof(XGI21_LVDSCapStruct)) + { + return index; + } + return 0; +} + +/* --------------------------------------------------------------------- */ +/* Function : XGI_XG21SetPanelDelay */ +/* Input : */ +/* Output : */ +/* Description : */ +/* I/P : bl : 1 ; T1 : the duration between CPL on and signal on */ +/* : bl : 2 ; T2 : the duration signal on and Vdd on */ +/* : bl : 3 ; T3 : the duration between CPL off and signal off */ +/* : bl : 4 ; T4 : the duration signal off and Vdd off */ +/* --------------------------------------------------------------------- */ +void XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo) +{ + USHORT index ; + + index = XGI_GetLVDSOEMTableIndex( pVBInfo ); + if ( tempbl == 1 ) + XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S1, pVBInfo ) ; + + if ( tempbl == 2 ) + XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S2, pVBInfo ) ; + + if ( tempbl == 3 ) + XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S3, pVBInfo ) ; + + if ( tempbl == 4 ) + XGINew_LCD_Wait_Time( pVBInfo->XG21_LVDSCapList[ index ].PSC_S4, pVBInfo ) ; +} + +BOOLEAN XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT xres , + yres , + colordepth , + modeflag , + resindex , + lvdstableindex; + + resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ; + if ( ModeNo <= 0x13 ) + { + xres = pVBInfo->StResInfo[ resindex ].HTotal ; + yres = pVBInfo->StResInfo[ resindex ].VTotal ; + modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */ + } + else + { + xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */ + yres = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */ + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */ + } + + if ( !( modeflag & Charx8Dot ) ) + { + xres /= 9; + xres *= 8; + } + + if ( ModeNo > 0x13 ) + { + if ( ( ModeNo>0x13 ) && ( modeflag & HalfDCLK ) ) + { + xres *= 2 ; + } + if ( ( ModeNo>0x13 ) && ( modeflag & DoubleScanMode ) ) + { + yres *= 2 ; + } + } + + lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo ); + if ( xres > (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE) ) + return FALSE; + + if ( yres > (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE) ) + return FALSE; + + if ( ModeNo > 0x13 ) + { + if ( ( xres != (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE) ) || + ( yres != (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE)) ) + { + colordepth = XGI_GetColorDepth( ModeNo , ModeIdIndex, pVBInfo ) ; + if ( colordepth > 2 ) + { + return FALSE; + } + } + } + return TRUE; +} + +void XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo) +{ + UCHAR temp; + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ; /* D[0] 1: 18bit */ + temp = ( temp & 1 ) << 6; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x06 , ~0x40 , temp ) ; /* SR06[6] 18bit Dither */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0xc0 , temp | 0x80 ) ; /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: dual 12bits */ + +} + +void XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo) +{ + UCHAR temp; + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ; /* D[1:0] 01: 18bit, 00: dual 12, 10: single 24 */ + temp = ( temp & 3 ) << 6; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x06 , ~0xc0 , temp & 0x80 ) ; /* SR06[7]0: dual 12/1: single 24 [6] 18bit Dither <= 0 h/w recommend */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x09 , ~0xc0 , temp | 0x80 ) ; /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: 24bits */ + +} + +void XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR temp,Miscdata; + USHORT xres , + yres , + modeflag , + resindex , + lvdstableindex ; + USHORT LVDSHT,LVDSHBS,LVDSHRS,LVDSHRE,LVDSHBE; + USHORT LVDSVT,LVDSVBS,LVDSVRS,LVDSVRE,LVDSVBE; + USHORT value; + + lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo ); + + temp = (UCHAR) ( ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & (LCDPolarity << 8 ) ) >> 8 ); + temp &= LCDPolarity; + Miscdata =(UCHAR) XGINew_GetReg2(pVBInfo->P3cc) ; + + XGINew_SetReg3( pVBInfo->P3c2 , (Miscdata & 0x3F) | temp ) ; + + temp = (UCHAR) ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & LCDPolarity ) ; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x80 , temp&0x80 ) ; /* SR35[7] FP VSync polarity */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , ~0x20 , (temp&0x40)>>1 ) ; /* SR30[5] FP HSync polarity */ + + XGI_SetXG21FPBits(pVBInfo); + resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ; + if ( ModeNo <= 0x13 ) + { + xres = pVBInfo->StResInfo[ resindex ].HTotal ; + yres = pVBInfo->StResInfo[ resindex ].VTotal ; + modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */ + } + else + { + xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */ + yres = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */ + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */ + } + + if (!( modeflag & Charx8Dot )) + xres = xres * 8 / 9; + + LVDSHT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT; + + LVDSHBS = xres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE - xres ) / 2 ; + if ( ( ModeNo<=0x13 ) && ( modeflag & HalfDCLK ) ) + { + LVDSHBS -= xres/4 ; + } + if (LVDSHBS > LVDSHT) LVDSHBS -= LVDSHT ; + + LVDSHRS = LVDSHBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP ; + if (LVDSHRS > LVDSHT) LVDSHRS -= LVDSHT ; + + LVDSHRE = LVDSHRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC ; + if (LVDSHRE > LVDSHT) LVDSHRE -= LVDSHT ; + + LVDSHBE = LVDSHBS + LVDSHT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE ; + + LVDSVT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT; + + LVDSVBS = yres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE - yres ) / 2 ; + if ( ( ModeNo>0x13 ) && ( modeflag & DoubleScanMode ) ) + { + LVDSVBS += yres/2 ; + } + if (LVDSVBS > LVDSVT) LVDSVBS -= LVDSVT ; + + LVDSVRS = LVDSVBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP ; + if (LVDSVRS > LVDSVT) LVDSVRS -= LVDSVT ; + + LVDSVRE = LVDSVRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC ; + if (LVDSVRE > LVDSVT) LVDSVRE -= LVDSVT ; + + LVDSVBE = LVDSVBS + LVDSVT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE ; + + temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp & 0x7f ) ; /* Unlock CRTC */ + + if (!( modeflag & Charx8Dot )) + { + XGINew_SetRegOR( pVBInfo->P3c4 , 0x1 , 0x1 ) ; + } + + /* HT SR0B[1:0] CR00 */ + value = ( LVDSHT >> 3 ) - 5; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x03 , ( value & 0x300 ) >> 8 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x0 , (value & 0xFF) ) ; + + /* HBS SR0B[5:4] CR02 */ + value = ( LVDSHBS >> 3 ) - 1; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x30 , ( value & 0x300 ) >> 4 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x2 , (value & 0xFF) ) ; + + /* HBE SR0C[1:0] CR05[7] CR03[4:0] */ + value = ( LVDSHBE >> 3 ) - 1; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x03 , ( value & 0xC0 ) >> 6 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x80 , ( value & 0x20 ) << 2 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x03 , ~0x1F , value & 0x1F ) ; + + /* HRS SR0B[7:6] CR04 */ + value = ( LVDSHRS >> 3 ) + 2; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0xC0 , ( value & 0x300 ) >> 2 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x4 , (value & 0xFF) ) ; + + /* Panel HRS SR2F[1:0] SR2E[7:0] */ + value--; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0x03 , ( value & 0x300 ) >> 8 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , (value & 0xFF) ) ; + + /* HRE SR0C[2] CR05[4:0] */ + value = ( LVDSHRE >> 3 ) + 2; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x04 , ( value & 0x20 ) >> 3 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x1F , value & 0x1F ) ; + + /* Panel HRE SR2F[7:2] */ + value--; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0xFC , value << 2 ) ; + + /* VT SR0A[0] CR07[5][0] CR06 */ + value = LVDSVT - 2 ; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x01 , ( value & 0x400 ) >> 10 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x20 , ( value & 0x200 ) >> 4 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x01 , ( value & 0x100 ) >> 8 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x06 , (value & 0xFF) ) ; + + /* VBS SR0A[2] CR09[5] CR07[3] CR15 */ + value = LVDSVBS - 1 ; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x04 , ( value & 0x400 ) >> 8 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x09 , ~0x20 , ( value & 0x200 ) >> 4 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x08 , ( value & 0x100 ) >> 5 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x15 , (value & 0xFF) ) ; + + /* VBE SR0A[4] CR16 */ + value = LVDSVBE - 1; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x10 , ( value & 0x100 ) >> 4 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x16 , (value & 0xFF) ) ; + + /* VRS SR0A[3] CR7[7][2] CR10 */ + value = LVDSVRS - 1 ; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x08 , ( value & 0x400 ) >> 7 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x80 , ( value & 0x200 ) >> 2 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x04 , ( value & 0x100 ) >> 6 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x10 , (value & 0xFF) ) ; + + /* Panel VRS SR3F[1:0] SR34[7:0] SR33[0] */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0x03 , ( value & 0x600 ) >> 9 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , (value >> 1) & 0xFF ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x33 , ~0x01 , value & 0x01 ) ; + + /* VRE SR0A[5] CR11[3:0] */ + value = LVDSVRE - 1; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x20 , ( value & 0x10 ) << 1 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x11 , ~0x0F , value & 0x0F ) ; + + /* Panel VRE SR3F[7:2] */ /* SR3F[7] has to be 0, h/w bug */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC , ( value << 2 ) & 0x7C ) ; + + for ( temp=0, value = 0; temp < 3; temp++) + { + + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , value ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2) ; + value += 0x10; + } + + if (!( modeflag & Charx8Dot )) + { + XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */ + XGINew_SetReg3( pVBInfo->P3c0 , 0x13 ) ; /* set index */ + XGINew_SetReg3( pVBInfo->P3c0 , 0x00 ) ; /* set data, panning = 0, shift left 1 dot*/ + + XGINew_GetReg2( pVBInfo->P3da ) ; /* Enable Attribute */ + XGINew_SetReg3( pVBInfo->P3c0 , 0x20 ) ; + + XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */ + } + + +} + +/* no shadow case */ +void XGI_SetXG27LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR temp,Miscdata; + USHORT xres , + yres , + modeflag , + resindex , + lvdstableindex ; + USHORT LVDSHT,LVDSHBS,LVDSHRS,LVDSHRE,LVDSHBE; + USHORT LVDSVT,LVDSVBS,LVDSVRS,LVDSVRE,LVDSVBE; + USHORT value; + + lvdstableindex = XGI_GetLVDSOEMTableIndex( pVBInfo ); + temp = (UCHAR) ( ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & (LCDPolarity << 8 ) ) >> 8 ); + temp &= LCDPolarity; + Miscdata =(UCHAR) XGINew_GetReg2(pVBInfo->P3cc) ; + + XGINew_SetReg3( pVBInfo->P3c2 , (Miscdata & 0x3F) | temp ) ; + + temp = (UCHAR) ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability & LCDPolarity ) ; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x80 , temp&0x80 ) ; /* SR35[7] FP VSync polarity */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x30 , ~0x20 , (temp&0x40)>>1 ) ; /* SR30[5] FP HSync polarity */ + + XGI_SetXG27FPBits(pVBInfo); + resindex = XGI_GetResInfo( ModeNo , ModeIdIndex, pVBInfo ) ; + if ( ModeNo <= 0x13 ) + { + xres = pVBInfo->StResInfo[ resindex ].HTotal ; + yres = pVBInfo->StResInfo[ resindex ].VTotal ; + modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */ + } + else + { + xres = pVBInfo->ModeResInfo[ resindex ].HTotal ; /* xres->ax */ + yres = pVBInfo->ModeResInfo[ resindex ].VTotal ; /* yres->bx */ + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex].Ext_ModeFlag ; /* si+St_ModeFlag */ + } + + if (!( modeflag & Charx8Dot )) + xres = xres * 8 / 9; + + LVDSHT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT; + + LVDSHBS = xres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE - xres ) / 2 ; + if ( ( ModeNo<=0x13 ) && ( modeflag & HalfDCLK ) ) + { + LVDSHBS -= xres/4 ; + } + if (LVDSHBS > LVDSHT) LVDSHBS -= LVDSHT ; + + LVDSHRS = LVDSHBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP ; + if (LVDSHRS > LVDSHT) LVDSHRS -= LVDSHT ; + + LVDSHRE = LVDSHRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC ; + if (LVDSHRE > LVDSHT) LVDSHRE -= LVDSHT ; + + LVDSHBE = LVDSHBS + LVDSHT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE ; + + LVDSVT = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT; + + LVDSVBS = yres + ( pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE - yres ) / 2 ; + if ( ( ModeNo>0x13 ) && ( modeflag & DoubleScanMode ) ) + { + LVDSVBS += yres/2 ; + } + if (LVDSVBS > LVDSVT) LVDSVBS -= LVDSVT ; + + LVDSVRS = LVDSVBS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP ; + if (LVDSVRS > LVDSVT) LVDSVRS -= LVDSVT ; + + LVDSVRE = LVDSVRS + pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC ; + if (LVDSVRE > LVDSVT) LVDSVRE -= LVDSVT ; + + LVDSVBE = LVDSVBS + LVDSVT - pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE ; + + temp = ( UCHAR )XGINew_GetReg1( pVBInfo->P3d4 , 0x11 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x11 , temp & 0x7f ) ; /* Unlock CRTC */ + + if (!( modeflag & Charx8Dot )) + { + XGINew_SetRegOR( pVBInfo->P3c4 , 0x1 , 0x1 ) ; + } + + /* HT SR0B[1:0] CR00 */ + value = ( LVDSHT >> 3 ) - 5; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x03 , ( value & 0x300 ) >> 8 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x0 , (value & 0xFF) ) ; + + /* HBS SR0B[5:4] CR02 */ + value = ( LVDSHBS >> 3 ) - 1; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0x30 , ( value & 0x300 ) >> 4 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x2 , (value & 0xFF) ) ; + + /* HBE SR0C[1:0] CR05[7] CR03[4:0] */ + value = ( LVDSHBE >> 3 ) - 1; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x03 , ( value & 0xC0 ) >> 6 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x80 , ( value & 0x20 ) << 2 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x03 , ~0x1F , value & 0x1F ) ; + + /* HRS SR0B[7:6] CR04 */ + value = ( LVDSHRS >> 3 ) + 2; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0B , ~0xC0 , ( value & 0x300 ) >> 2 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x4 , (value & 0xFF) ) ; + + /* Panel HRS SR2F[1:0] SR2E[7:0] */ + value--; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0x03 , ( value & 0x300 ) >> 8 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2E , (value & 0xFF) ) ; + + /* HRE SR0C[2] CR05[4:0] */ + value = ( LVDSHRE >> 3 ) + 2; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0C , ~0x04 , ( value & 0x20 ) >> 3 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x05 , ~0x1F , value & 0x1F ) ; + + /* Panel HRE SR2F[7:2] */ + value--; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x2F , ~0xFC , value << 2 ) ; + + /* VT SR0A[0] CR07[5][0] CR06 */ + value = LVDSVT - 2 ; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x01 , ( value & 0x400 ) >> 10 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x20 , ( value & 0x200 ) >> 4 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x01 , ( value & 0x100 ) >> 8 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x06 , (value & 0xFF) ) ; + + /* VBS SR0A[2] CR09[5] CR07[3] CR15 */ + value = LVDSVBS - 1 ; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x04 , ( value & 0x400 ) >> 8 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x09 , ~0x20 , ( value & 0x200 ) >> 4 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x08 , ( value & 0x100 ) >> 5 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x15 , (value & 0xFF) ) ; + + /* VBE SR0A[4] CR16 */ + value = LVDSVBE - 1; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x10 , ( value & 0x100 ) >> 4 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x16 , (value & 0xFF) ) ; + + /* VRS SR0A[3] CR7[7][2] CR10 */ + value = LVDSVRS - 1 ; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x08 , ( value & 0x400 ) >> 7 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x80 , ( value & 0x200 ) >> 2 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x07 , ~0x04 , ( value & 0x100 ) >> 6 ) ; + XGINew_SetReg1( pVBInfo->P3d4 , 0x10 , (value & 0xFF) ) ; + + /* Panel VRS SR35[2:0] SR34[7:0] */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x35 , ~0x07 , ( value & 0x700 ) >> 8 ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x34 , value & 0xFF ) ; + + /* VRE SR0A[5] CR11[3:0] */ + value = LVDSVRE - 1; + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x0A , ~0x20 , ( value & 0x10 ) << 1 ) ; + XGINew_SetRegANDOR( pVBInfo->P3d4 , 0x11 , ~0x0F , value & 0x0F ) ; + + /* Panel VRE SR3F[7:2] */ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x3F , ~0xFC , ( value << 2 ) & 0xFC ) ; + + for ( temp=0, value = 0; temp < 3; temp++) + { + + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x31 , ~0x30 , value ) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2B , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1) ; + XGINew_SetReg1( pVBInfo->P3c4 , 0x2C , pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2) ; + value += 0x10; + } + + if (!( modeflag & Charx8Dot )) + { + XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */ + XGINew_SetReg3( pVBInfo->P3c0 , 0x13 ) ; /* set index */ + XGINew_SetReg3( pVBInfo->P3c0 , 0x00 ) ; /* set data, panning = 0, shift left 1 dot*/ + + XGINew_GetReg2( pVBInfo->P3da ) ; /* Enable Attribute */ + XGINew_SetReg3( pVBInfo->P3c0 , 0x20 ) ; + + XGINew_GetReg2( pVBInfo->P3da ) ; /* reset 3da */ + } + + +} + +/* --------------------------------------------------------------------- */ +/* Function : XGI_IsLCDON */ +/* Input : */ +/* Output : FALSE : Skip PSC Control */ +/* TRUE: Disable PSC */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGI_IsLCDON(PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempax ; + + tempax = pVBInfo->VBInfo ; + if ( tempax & SetCRT2ToDualEdge ) + return FALSE ; + else if ( tempax & ( DisableCRT2Display | SwitchToCRT2 | SetSimuScanMode ) ) + return TRUE ; + + return FALSE ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_EnablePWD */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_EnablePWD( PVB_DEVICE_INFO pVBInfo ) +{ + USHORT index , + temp ; + + index = XGI_GetLCDCapPtr(pVBInfo) ; + temp = pVBInfo->LCDCapList[ index ].PWD_2B ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x2B , temp ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x2C , pVBInfo->LCDCapList[ index ].PWD_2C ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x2D , pVBInfo->LCDCapList[ index ].PWD_2D ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x2E , pVBInfo->LCDCapList[ index ].PWD_2E ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x2F , pVBInfo->LCDCapList[ index ].PWD_2F ) ; + XGINew_SetRegOR( pVBInfo->Part4Port , 0x27 , 0x80 ) ; /* enable PWD */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_DisablePWD */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_DisablePWD( PVB_DEVICE_INFO pVBInfo ) +{ + XGINew_SetRegAND( pVBInfo->Part4Port , 0x27 , 0x7F ) ; /* disable PWD */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_DisableChISLCD */ +/* Input : */ +/* Output : FALSE -> Not LCD Mode */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGI_DisableChISLCD(PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempbx , + tempah ; + + tempbx = pVBInfo->SetFlag & ( DisableChA | DisableChB ) ; + tempah = ~( ( USHORT )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ) ; + + if ( tempbx & ( EnableChA | DisableChA ) ) + { + if ( !( tempah & 0x08 ) ) /* Chk LCDA Mode */ + return FALSE ; + } + + if ( !( tempbx & ( EnableChB | DisableChB ) ) ) + return FALSE ; + + if ( tempah & 0x01 ) /* Chk LCDB Mode */ + return TRUE ; + + return FALSE ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_EnableChISLCD */ +/* Input : */ +/* Output : 0 -> Not LCD mode */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGI_EnableChISLCD(PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempbx , + tempah ; + + + tempbx = pVBInfo->SetFlag & ( EnableChA | EnableChB ) ; + tempah = ~( ( USHORT )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ) ; + + if ( tempbx & ( EnableChA | DisableChA ) ) + { + if ( !( tempah & 0x08 ) ) /* Chk LCDA Mode */ + return FALSE ; + } + + if ( !( tempbx & ( EnableChB | DisableChB ) ) ) + return FALSE ; + + if ( tempah & 0x01 ) /* Chk LCDB Mode */ + return TRUE ; + + return FALSE ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetLCDCapPtr */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +USHORT XGI_GetLCDCapPtr( PVB_DEVICE_INFO pVBInfo ) +{ + UCHAR tempal , + tempah , + tempbl , + i ; + + tempah = XGINew_GetReg1( pVBInfo->P3d4 , 0x36 ) ; + tempal = tempah & 0x0F ; + tempah = tempah & 0xF0 ; + i = 0 ; + tempbl = pVBInfo->LCDCapList[ i ].LCD_ID ; + + while( tempbl != 0xFF ) + { + if ( tempbl & 0x80 ) /* OEMUtil */ + { + tempal = tempah ; + tempbl = tempbl & ~( 0x80 ) ; + } + + if ( tempal == tempbl ) + break ; + + i++ ; + + tempbl = pVBInfo->LCDCapList[ i ].LCD_ID ; + } + + return i ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetLCDCapPtr1 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +USHORT XGI_GetLCDCapPtr1( PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempah , + tempal , + tempbl , + i ; + + tempal = pVBInfo->LCDResInfo ; + tempah = pVBInfo->LCDTypeInfo ; + + i = 0 ; + tempbl = pVBInfo->LCDCapList[ i ].LCD_ID; + + while( tempbl != 0xFF ) + { + if ( ( tempbl & 0x80 ) && ( tempbl != 0x80 ) ) + { + tempal = tempah ; + tempbl &= ~0x80 ; + } + + if ( tempal == tempbl ) + break ; + + i++ ; + tempbl = pVBInfo->LCDCapList[ i ].LCD_ID ; + } + + if ( tempbl == 0xFF ) + { + pVBInfo->LCDResInfo = Panel1024x768 ; + pVBInfo->LCDTypeInfo = 0 ; + i = 0 ; + } + + return i ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetLCDSync */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetLCDSync( USHORT* HSyncWidth , USHORT* VSyncWidth, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT Index ; + + Index = XGI_GetLCDCapPtr(pVBInfo) ; + *HSyncWidth = pVBInfo->LCDCapList[ Index ].LCD_HSyncWidth ; + *VSyncWidth = pVBInfo->LCDCapList[ Index ].LCD_VSyncWidth ; + + return ; +} + + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_EnableBridge */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_EnableBridge( PXGI_HW_DEVICE_INFO HwDeviceExtension , PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempbl , + tempah ; + + if ( pVBInfo->SetFlag == Win9xDOSMode ) + { + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + XGI_DisplayOn( HwDeviceExtension, pVBInfo) ; + return ; + } + else /* LVDS or CH7017 */ + return ; + } + + + if ( HwDeviceExtension->jChipType < XG40 ) + { + if ( !XGI_DisableChISLCD(pVBInfo) ) + { + if ( ( XGI_EnableChISLCD(pVBInfo) ) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) ) + { + if ( pVBInfo->LCDInfo & SetPWDEnable ) + { + XGI_EnablePWD( pVBInfo); + } + else + { + pVBInfo->LCDInfo &= ( ~SetPWDEnable ) ; + if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + tempbl = 0xFD ; + tempah = 0x02 ; + } + else + { + tempbl = 0xFB ; + tempah = 0x00 ; + } + + XGI_SetPanelPower( tempah , tempbl, pVBInfo ) ; + XGI_SetPanelDelay( 1,pVBInfo ) ; + } + } + } + } /* Not 340 */ + + + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + if ( !( pVBInfo->SetFlag & DisableChA ) ) + { + if ( pVBInfo->SetFlag & EnableChA ) + { + XGINew_SetReg1( pVBInfo->Part1Port , 0x1E , 0x20 ) ; /* Power on */ + } + else + { + if ( pVBInfo->VBInfo & SetCRT2ToDualEdge ) /* SetCRT2ToLCDA ) */ + { + XGINew_SetReg1(pVBInfo->Part1Port,0x1E,0x20); /* Power on */ + } + } + } + + if ( !( pVBInfo->SetFlag & DisableChB ) ) + { + if ( ( pVBInfo->SetFlag & EnableChB ) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToTV | SetCRT2ToRAMDAC ) ) ) + { + tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->P3c4 , 0x32 ) ; + tempah &= 0xDF; + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) ) + tempah |= 0x20 ; + } + XGINew_SetReg1( pVBInfo->P3c4 , 0x32 , tempah ) ; + XGINew_SetRegOR( pVBInfo->P3c4 , 0x1E , 0x20 ) ; + + + tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ; + + if ( !( tempah & 0x80 ) ) + XGINew_SetRegOR( pVBInfo->Part1Port , 0x2E , 0x80 ) ; /* BVBDOENABLE = 1 */ + + XGINew_SetRegAND( pVBInfo->Part1Port , 0x00 , 0x7F ) ; /* BScreenOFF = 0 */ + } + } + + if ( ( pVBInfo->SetFlag & ( EnableChA | EnableChB ) ) || ( !( pVBInfo->VBInfo & DisableCRT2Display ) ) ) + { + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x00 , ~0xE0 , 0x20 ) ; /* shampoo 0129 */ + if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) ) + { + if ( !XGI_DisableChISLCD(pVBInfo) ) + { + if ( XGI_EnableChISLCD( pVBInfo) || ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) ) + XGINew_SetRegAND( pVBInfo->Part4Port ,0x2A , 0x7F ) ; /* LVDS PLL power on */ + } + XGINew_SetRegAND( pVBInfo->Part4Port , 0x30 , 0x7F ) ; /* LVDS Driver power on */ + } + } + + tempah = 0x00 ; + + if ( !( pVBInfo->VBInfo & DisableCRT2Display ) ) + { + tempah = 0xc0 ; + + if ( !( pVBInfo->VBInfo & SetSimuScanMode ) ) + { + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + { + if ( pVBInfo->VBInfo & SetCRT2ToDualEdge ) + { + tempah = tempah & 0x40; + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + tempah = tempah ^ 0xC0 ; + + if ( pVBInfo->SetFlag & DisableChB ) + tempah &= 0xBF ; + + if ( pVBInfo->SetFlag & DisableChA ) + tempah &= 0x7F ; + + if ( pVBInfo->SetFlag & EnableChB ) + tempah |= 0x40 ; + + if ( pVBInfo->SetFlag & EnableChA ) + tempah |= 0x80 ; + } + } + } + } + + XGINew_SetRegOR( pVBInfo->Part4Port , 0x1F , tempah ) ; /* EnablePart4_1F */ + + if ( pVBInfo->SetFlag & Win9xDOSMode ) + { + XGI_DisplayOn( HwDeviceExtension, pVBInfo) ; + return ; + } + + if ( !( pVBInfo->SetFlag & DisableChA ) ) + { + XGI_VBLongWait( pVBInfo) ; + if ( !( pVBInfo->SetFlag & GatingCRT ) ) + { + XGI_DisableGatingCRT( HwDeviceExtension, pVBInfo ) ; + XGI_DisplayOn( HwDeviceExtension, pVBInfo) ; + XGI_VBLongWait( pVBInfo) ; + } + } + } /* 301 */ + else /* LVDS */ + { + if ( pVBInfo->VBInfo & ( SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) ) + XGINew_SetRegOR( pVBInfo->Part1Port , 0x1E , 0x20 ) ; /* enable CRT2 */ + + + + tempah = ( UCHAR )XGINew_GetReg1( pVBInfo->Part1Port , 0x2E ) ; + if ( !( tempah & 0x80 ) ) + XGINew_SetRegOR( pVBInfo->Part1Port , 0x2E , 0x80 ) ; /* BVBDOENABLE = 1 */ + + XGINew_SetRegAND(pVBInfo->Part1Port,0x00,0x7F); + XGI_DisplayOn( HwDeviceExtension, pVBInfo); + } /* End of VB */ + + + if ( HwDeviceExtension->jChipType < XG40 ) + { + if ( !XGI_EnableChISLCD(pVBInfo) ) + { + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) + { + if ( XGI_BacklightByDrv(pVBInfo) ) + return ; + } + else + return ; + } + + if ( pVBInfo->LCDInfo & SetPWDEnable ) + { + XGI_FirePWDEnable(pVBInfo) ; + return ; + } + + XGI_SetPanelDelay( 2,pVBInfo ) ; + + if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + tempah = 0x01 ; + tempbl = 0xFE ; /* turn on backlght */ + } + else + { + tempbl = 0xF7 ; + tempah = 0x00 ; + } + XGI_SetPanelPower( tempah , tempbl , pVBInfo) ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_DisableBridge */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempax , + tempbx , + tempah = 0 , + tempbl = 0 ; + + if ( pVBInfo->SetFlag == Win9xDOSMode ) + return ; + + + if ( HwDeviceExtension->jChipType < XG40 ) + { + if ( ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) ) || ( XGI_DisableChISLCD(pVBInfo) ) ) + { + if ( !XGI_IsLCDON(pVBInfo) ) + { + if ( pVBInfo->LCDInfo & SetPWDEnable ) + XGI_EnablePWD( pVBInfo) ; + else + { + pVBInfo->LCDInfo &= ~SetPWDEnable ; + XGI_DisablePWD(pVBInfo) ; + if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + tempbx = 0xFE ; /* not 01h */ + tempax = 0 ; + } + else + { + tempbx = 0xF7 ; /* not 08h */ + tempax = 0x08 ; + } + XGI_SetPanelPower( tempax , tempbx , pVBInfo) ; + XGI_SetPanelDelay( 3,pVBInfo ) ; + } + } /* end if(!XGI_IsLCDON(pVBInfo)) */ + } + } + +/* if ( CH7017 ) + { + if ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2toLCDA ) ) || ( XGI_DisableChISLCD(pVBInfo) ) ) + { + if ( !XGI_IsLCDON(pVBInfo) ) + { + if ( DISCHARGE ) + { + tempbx = XGINew_GetCH7005( 0x61 ) ; + if ( tempbx < 0x01 ) //first time we power up + XGINew_SetCH7005( 0x0066 ) ; //and disable power sequence + else + XGINew_SetCH7005( 0x5f66 ) ; //leave VDD on - disable power + } + } + } + } */ + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B| VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + tempah = 0x3F ; + if ( !( pVBInfo->VBInfo & ( DisableCRT2Display | SetSimuScanMode ) ) ) + { + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + { + if ( pVBInfo->VBInfo & SetCRT2ToDualEdge ) + { + tempah = 0x7F; /* Disable Channel A */ + if ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) + tempah = 0xBF ; /* Disable Channel B */ + + if ( pVBInfo->SetFlag & DisableChB ) + tempah &= 0xBF ; /* force to disable Cahnnel */ + + if ( pVBInfo->SetFlag & DisableChA ) + tempah &= 0x7F ; /* Force to disable Channel B */ + } + } + } + + XGINew_SetRegAND( pVBInfo->Part4Port , 0x1F , tempah ) ; /* disable part4_1f */ + + if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) ) + { + if ( ( ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) ) || ( XGI_DisableChISLCD(pVBInfo) ) || ( XGI_IsLCDON(pVBInfo) ) ) + XGINew_SetRegOR( pVBInfo->Part4Port , 0x30 , 0x80 ) ; /* LVDS Driver power down */ + } + + if ( ( pVBInfo->SetFlag & DisableChA ) || ( pVBInfo->VBInfo & ( DisableCRT2Display | SetCRT2ToLCDA | SetSimuScanMode ) ) ) + { + if ( pVBInfo->SetFlag & GatingCRT ) + XGI_EnableGatingCRT( HwDeviceExtension, pVBInfo ) ; + XGI_DisplayOff( HwDeviceExtension, pVBInfo) ; + } + + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + { + if ( ( pVBInfo->SetFlag & DisableChA ) || ( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) + XGINew_SetRegAND( pVBInfo->Part1Port , 0x1e , 0xdf ) ; /* Power down */ + } + + XGINew_SetRegAND( pVBInfo->P3c4 , 0x32 , 0xdf ) ; /* disable TV as primary VGA swap */ + + if ( ( pVBInfo->VBInfo & ( SetSimuScanMode | SetCRT2ToDualEdge ) ) ) + XGINew_SetRegAND(pVBInfo->Part2Port,0x00,0xdf); + + if ( ( pVBInfo->SetFlag & DisableChB ) || ( pVBInfo->VBInfo & ( DisableCRT2Display | SetSimuScanMode ) ) + || ( ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) && ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) ) ) + XGINew_SetRegOR( pVBInfo->Part1Port , 0x00 , 0x80 ) ; /* BScreenOff=1 */ + + if ( ( pVBInfo->SetFlag & DisableChB ) || ( pVBInfo->VBInfo & ( DisableCRT2Display | SetSimuScanMode ) ) + || ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) || ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) ) + { + tempah= XGINew_GetReg1( pVBInfo->Part1Port , 0x00 ) ; /* save Part1 index 0 */ + XGINew_SetRegOR( pVBInfo->Part1Port , 0x00 , 0x10 ) ; /* BTDAC = 1, avoid VB reset */ + XGINew_SetRegAND( pVBInfo->Part1Port , 0x1E , 0xDF ) ; /* disable CRT2 */ + XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , tempah ) ; /* restore Part1 index 0 */ + } + } + else /* {301} */ + { + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToTV ) ) + { + XGINew_SetRegOR( pVBInfo->Part1Port , 0x00 , 0x80 ) ; /* BScreenOff=1 */ + XGINew_SetRegAND( pVBInfo->Part1Port , 0x1E , 0xDF ) ; /* Disable CRT2 */ + XGINew_SetRegAND( pVBInfo->P3c4 , 0x32 , 0xDF ) ; /* Disable TV asPrimary VGA swap */ + } + + if ( pVBInfo->VBInfo & ( DisableCRT2Display | SetCRT2ToLCDA | SetSimuScanMode ) ) + XGI_DisplayOff( HwDeviceExtension, pVBInfo) ; + } + + + + + if ( HwDeviceExtension->jChipType < XG40 ) + { + if ( !( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) || ( XGI_DisableChISLCD(pVBInfo) ) || ( XGI_IsLCDON(pVBInfo) ) ) + { + if ( pVBInfo->LCDInfo & SetPWDEnable ) + { + if ( pVBInfo->LCDInfo & SetPWDEnable ) + XGI_BacklightByDrv(pVBInfo) ; + else + { + XGI_SetPanelDelay( 4 ,pVBInfo) ; + if ( pVBInfo->VBType & VB_XGI301LV ) + { + tempbl = 0xFD ; + tempah = 0x00 ; + } + else + { + tempbl = 0xFB ; + tempah = 0x04 ; + } + } + } + XGI_SetPanelPower( tempah , tempbl , pVBInfo) ; + } + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetTVPtrIndex */ +/* Input : */ +/* Output : */ +/* Description : bx 0 : ExtNTSC */ +/* 1 : StNTSC */ +/* 2 : ExtPAL */ +/* 3 : StPAL */ +/* 4 : ExtHiTV */ +/* 5 : StHiTV */ +/* 6 : Ext525i */ +/* 7 : St525i */ +/* 8 : Ext525p */ +/* 9 : St525p */ +/* A : Ext750p */ +/* B : St750p */ +/* --------------------------------------------------------------------- */ +USHORT XGI_GetTVPtrIndex( PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempbx = 0 ; + + if ( pVBInfo->TVInfo & SetPALTV ) + tempbx = 2 ; + if ( pVBInfo->TVInfo & SetYPbPrMode1080i ) + tempbx = 4 ; + if ( pVBInfo->TVInfo & SetYPbPrMode525i ) + tempbx = 6 ; + if ( pVBInfo->TVInfo & SetYPbPrMode525p ) + tempbx = 8 ; + if ( pVBInfo->TVInfo & SetYPbPrMode750p ) + tempbx = 10 ; + if ( pVBInfo->TVInfo & TVSimuMode ) + tempbx++ ; + + return tempbx ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_OEM310Setting */ +/* Input : */ +/* Output : */ +/* Description : Customized Param. for 301 */ +/* --------------------------------------------------------------------- */ +void XGI_OEM310Setting( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo) +{ + if ( pVBInfo->SetFlag & Win9xDOSMode ) + return ; + + /* GetPart1IO(); */ + XGI_SetDelayComp(pVBInfo) ; + + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) + XGI_SetLCDCap(pVBInfo) ; + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + /* GetPart2IO() */ + XGI_SetPhaseIncr(pVBInfo) ; + XGI_SetYFilter( ModeNo , ModeIdIndex,pVBInfo ) ; + XGI_SetAntiFlicker( ModeNo , ModeIdIndex,pVBInfo ) ; + + if ( pVBInfo->VBType&VB_XGI301) + XGI_SetEdgeEnhance( ModeNo , ModeIdIndex ,pVBInfo) ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetDelayComp */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetDelayComp( PVB_DEVICE_INFO pVBInfo ) +{ + USHORT index ; + + UCHAR tempah , + tempbl , + tempbh ; + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToTV | SetCRT2ToRAMDAC ) ) + { + tempbl = 0; + tempbh = 0; + + index = XGI_GetTVPtrIndex(pVBInfo ) ; /* Get TV Delay */ + tempbl = pVBInfo->XGI_TVDelayList[ index ] ; + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + tempbl = pVBInfo->XGI_TVDelayList2[ index ] ; + + if ( pVBInfo->VBInfo & SetCRT2ToDualEdge ) + tempbl = tempbl >> 4 ; +/* + if ( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) + tempbl = CRT2Delay1 ; // Get CRT2 Delay + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + tempbl = CRT2Delay2 ; +*/ + if ( pVBInfo->VBInfo & ( SetCRT2ToLCD | SetCRT2ToLCDA ) ) + { + index = XGI_GetLCDCapPtr(pVBInfo) ; /* Get LCD Delay */ + tempbh=pVBInfo->LCDCapList[ index ].LCD_DelayCompensation ; + + if ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) + tempbl = tempbh ; + } + + tempbl &= 0x0F ; + tempbh &= 0xF0 ; + tempah = XGINew_GetReg1( pVBInfo->Part1Port , 0x2D ) ; + + if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToLCD | SetCRT2ToTV ) ) /* Channel B */ + { + tempah &= 0xF0 ; + tempah |= tempbl ; + } + + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) /* Channel A */ + { + tempah &= 0x0F ; + tempah |= tempbh ; + } + XGINew_SetReg1(pVBInfo->Part1Port,0x2D,tempah); + } + } + else if ( pVBInfo->IF_DEF_LVDS == 1 ) + { + tempbl = 0; + tempbh = 0; + if ( pVBInfo->VBInfo & SetCRT2ToLCD ) + { + tempah = pVBInfo->LCDCapList[ XGI_GetLCDCapPtr(pVBInfo) ].LCD_DelayCompensation ; /* / Get LCD Delay */ + tempah &= 0x0f ; + tempah = tempah << 4 ; + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2D , 0x0f , tempah ) ; + } + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetLCDCap */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetLCDCap( PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempcx ; + + tempcx = pVBInfo->LCDCapList[ XGI_GetLCDCapPtr(pVBInfo) ].LCD_Capability ; + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + if ( pVBInfo->VBType & ( VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { /* 301LV/302LV only */ + /* Set 301LV Capability */ + XGINew_SetReg1( pVBInfo->Part4Port , 0x24 , ( UCHAR )( tempcx & 0x1F ) ) ; + } + /* VB Driving */ + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~( ( EnableVBCLKDRVLOW | EnablePLLSPLOW ) >> 8 ) , ( USHORT )( ( tempcx & ( EnableVBCLKDRVLOW | EnablePLLSPLOW ) ) >> 8 ) ) ; + } + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + if ( pVBInfo->VBInfo & SetCRT2ToLCD ) + XGI_SetLCDCap_B( tempcx,pVBInfo ) ; + else if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + XGI_SetLCDCap_A( tempcx,pVBInfo ) ; + + if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) ) + { + if ( tempcx & EnableSpectrum ) + SetSpectrum( pVBInfo) ; + } + } + else /* LVDS,CH7017 */ + XGI_SetLCDCap_A( tempcx, pVBInfo ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetLCDCap_A */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetLCDCap_A(USHORT tempcx,PVB_DEVICE_INFO pVBInfo) +{ + USHORT temp ; + + temp = XGINew_GetReg1( pVBInfo->P3d4 , 0x37 ) ; + + if ( temp & LCDRGB18Bit ) + { + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0x0F , ( USHORT )( 0x20 | ( tempcx & 0x00C0 ) ) ) ; /* Enable Dither */ + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1A , 0x7F , 0x80 ) ; + } + else + { + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x19 , 0x0F , ( USHORT )( 0x30 | ( tempcx & 0x00C0 ) ) ) ; + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x1A , 0x7F , 0x00 ) ; + } + +/* + if ( tempcx & EnableLCD24bpp ) // 24bits + { + XGINew_SetRegANDOR(pVBInfo->Part1Port,0x19, 0x0F,(USHORT)(0x30|(tempcx&0x00C0)) ); + XGINew_SetRegANDOR(pVBInfo->Part1Port,0x1A,0x7F,0x00); + } + else + { + XGINew_SetRegANDOR(pVBInfo->Part1Port,0x19, 0x0F,(USHORT)(0x20|(tempcx&0x00C0)) );//Enable Dither + XGINew_SetRegANDOR(pVBInfo->Part1Port,0x1A,0x7F,0x80); + } +*/ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetLCDCap_B */ +/* Input : cx -> LCD Capability */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetLCDCap_B(USHORT tempcx,PVB_DEVICE_INFO pVBInfo) +{ + if ( tempcx & EnableLCD24bpp ) /* 24bits */ + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1A , 0xE0 , ( USHORT )( ( ( tempcx & 0x00ff ) >> 6 ) | 0x0c ) ) ; + else + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x1A , 0xE0 , ( USHORT )( ( ( tempcx & 0x00ff ) >> 6 ) | 0x18 ) ) ; /* Enable Dither */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : SetSpectrum */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void SetSpectrum( PVB_DEVICE_INFO pVBInfo ) +{ + USHORT index ; + + index = XGI_GetLCDCapPtr(pVBInfo) ; + + XGINew_SetRegAND( pVBInfo->Part4Port , 0x30 , 0x8F ) ; /* disable down spectrum D[4] */ + XGI_LongWait(pVBInfo) ; + XGINew_SetRegOR( pVBInfo->Part4Port , 0x30 , 0x20 ) ; /* reset spectrum */ + XGI_LongWait(pVBInfo) ; + + XGINew_SetReg1( pVBInfo->Part4Port , 0x31 , pVBInfo->LCDCapList[ index ].Spectrum_31 ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x32 , pVBInfo->LCDCapList[ index ].Spectrum_32 ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x33 , pVBInfo->LCDCapList[ index ].Spectrum_33 ) ; + XGINew_SetReg1( pVBInfo->Part4Port , 0x34 , pVBInfo->LCDCapList[ index ].Spectrum_34 ) ; + XGI_LongWait(pVBInfo) ; + XGINew_SetRegOR( pVBInfo->Part4Port , 0x30 , 0x40 ) ; /* enable spectrum */ +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetAntiFlicker */ +/* Input : */ +/* Output : */ +/* Description : Set TV Customized Param. */ +/* --------------------------------------------------------------------- */ +void XGI_SetAntiFlicker( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempbx , + index ; + + UCHAR tempah ; + + if (pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) + return ; + + tempbx = XGI_GetTVPtrIndex(pVBInfo ) ; + tempbx &= 0xFE ; + + if ( ModeNo <= 0x13 ) + { + index = pVBInfo->SModeIDTable[ ModeIdIndex ].VB_StTVFlickerIndex ; + } + else + { + index = pVBInfo->EModeIDTable[ ModeIdIndex ].VB_ExtTVFlickerIndex ; + } + + tempbx += index ; + tempah = TVAntiFlickList[ tempbx ] ; + tempah = tempah << 4 ; + + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x0A , 0x8F , tempah ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetEdgeEnhance */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetEdgeEnhance( USHORT ModeNo , USHORT ModeIdIndex , PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempbx , + index ; + + UCHAR tempah ; + + + tempbx = XGI_GetTVPtrIndex(pVBInfo ) ; + tempbx &= 0xFE ; + + if ( ModeNo <= 0x13 ) + { + index = pVBInfo->SModeIDTable[ ModeIdIndex ].VB_StTVEdgeIndex ; + } + else + { + index = pVBInfo->EModeIDTable[ ModeIdIndex ].VB_ExtTVEdgeIndex ; + } + + tempbx += index ; + tempah = TVEdgeList[ tempbx ] ; + tempah = tempah << 5 ; + + XGINew_SetRegANDOR( pVBInfo->Part2Port , 0x3A , 0x1F , tempah ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetPhaseIncr */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetPhaseIncr( PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempbx ; + + UCHAR tempcl , + tempch ; + + ULONG tempData ; + + XGI_GetTVPtrIndex2( &tempbx , &tempcl , &tempch, pVBInfo ) ; /* bx, cl, ch */ + tempData = TVPhaseList[ tempbx ] ; + + XGINew_SetReg1( pVBInfo->Part2Port , 0x31 , ( USHORT )( tempData & 0x000000FF ) ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x32 , ( USHORT )( ( tempData & 0x0000FF00 ) >> 8 ) ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x33 , ( USHORT )( ( tempData & 0x00FF0000 ) >> 16 ) ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x34 , ( USHORT )( ( tempData & 0xFF000000 ) >> 24 ) ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetYFilter */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_SetYFilter( USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempbx , + index ; + + UCHAR tempcl , + tempch , + tempal , + *filterPtr ; + + XGI_GetTVPtrIndex2( &tempbx , &tempcl , &tempch, pVBInfo ) ; /* bx, cl, ch */ + + switch( tempbx ) + { + case 0x00: + case 0x04: + filterPtr = NTSCYFilter1 ; + break ; + + case 0x01: + filterPtr = PALYFilter1 ; + break ; + + case 0x02: + case 0x05: + case 0x0D: + filterPtr = PALMYFilter1 ; + break ; + + case 0x03: + filterPtr = PALNYFilter1 ; + break ; + + case 0x08: + case 0x0C: + filterPtr = NTSCYFilter2 ; + break ; + + case 0x0A: + filterPtr = PALMYFilter2 ; + break ; + + case 0x0B: + filterPtr = PALNYFilter2 ; + break ; + + case 0x09: + filterPtr = PALYFilter2 ; + break ; + + default: + return ; + } + + if ( ModeNo <= 0x13 ) + tempal = pVBInfo->SModeIDTable[ ModeIdIndex ].VB_StTVYFilterIndex ; + else + tempal = pVBInfo->EModeIDTable[ ModeIdIndex ].VB_ExtTVYFilterIndex ; + + if ( tempcl == 0 ) + index = tempal * 4; + else + index = tempal * 7; + + if ( ( tempcl == 0 ) && ( tempch == 1 ) ) + { + XGINew_SetReg1( pVBInfo->Part2Port , 0x35 , 0 ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x36 , 0 ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x37 , 0 ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x38 , filterPtr[ index++ ] ) ; + } + else + { + XGINew_SetReg1( pVBInfo->Part2Port , 0x35 , filterPtr[ index++ ] ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x36 , filterPtr[ index++ ] ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x37 , filterPtr[ index++ ] ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x38 , filterPtr[ index++ ] ) ; + } + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + XGINew_SetReg1( pVBInfo->Part2Port , 0x48 , filterPtr[ index++ ] ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x49 , filterPtr[ index++ ] ) ; + XGINew_SetReg1( pVBInfo->Part2Port , 0x4A , filterPtr[ index++ ] ) ; + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetTVPtrIndex2 */ +/* Input : */ +/* Output : bx 0 : NTSC */ +/* 1 : PAL */ +/* 2 : PALM */ +/* 3 : PALN */ +/* 4 : NTSC1024x768 */ +/* 5 : PAL-M 1024x768 */ +/* 6-7: reserved */ +/* cl 0 : YFilter1 */ +/* 1 : YFilter2 */ +/* ch 0 : 301A */ +/* 1 : 301B/302B/301LV/302LV */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetTVPtrIndex2(USHORT* tempbx,UCHAR* tempcl,UCHAR* tempch, PVB_DEVICE_INFO pVBInfo) +{ + *tempbx = 0 ; + *tempcl = 0 ; + *tempch = 0 ; + + if ( pVBInfo->TVInfo & SetPALTV ) + *tempbx = 1 ; + + if ( pVBInfo->TVInfo & SetPALMTV ) + *tempbx = 2 ; + + if ( pVBInfo->TVInfo & SetPALNTV ) + *tempbx = 3 ; + + if ( pVBInfo->TVInfo & NTSC1024x768 ) + { + *tempbx = 4 ; + if ( pVBInfo->TVInfo & SetPALMTV ) + *tempbx = 5 ; + } + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + if ( ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) || ( pVBInfo->TVInfo & TVSimuMode ) ) + { + *tempbx += 8 ; + *tempcl += 1 ; + } + } + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + (*tempch)++ ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_SetCRT2ModeRegs */ +/* Input : */ +/* Output : */ +/* Description : Origin code for crt2group */ +/* --------------------------------------------------------------------- */ +void XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempbl ; + SHORT tempcl ; + + UCHAR tempah ; + + /* XGINew_SetReg1( pVBInfo->Part1Port , 0x03 , 0x00 ) ; // fix write part1 index 0 BTDRAM bit Bug */ + tempah=0; + if ( !( pVBInfo->VBInfo & DisableCRT2Display ) ) + { + tempah=XGINew_GetReg1( pVBInfo->Part1Port , 0x00 ) ; + tempah &= ~0x10 ; /* BTRAMDAC */ + tempah |= 0x40 ; /* BTRAM */ + + if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD ) ) + { + tempah=0x40; /* BTDRAM */ + if ( ModeNo > 0x13 ) + { + tempcl = pVBInfo->ModeType ; + tempcl -= ModeVGA ; + if ( tempcl >= 0 ) + { + tempah = ( 0x008 >> tempcl ) ; /* BT Color */ + if ( tempah == 0 ) + tempah = 1 ; + tempah |= 0x040 ; + } + } + if ( pVBInfo->VBInfo & SetInSlaveMode ) + tempah ^= 0x50 ; /* BTDAC */ + } + } + +/* 0210 shampoo + if ( pVBInfo->VBInfo & DisableCRT2Display ) + { + tempah = 0 ; + } + + XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , tempah ) ; + if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD ) ) + { + tempcl = pVBInfo->ModeType ; + if ( ModeNo > 0x13 ) + { + tempcl -= ModeVGA ; + if ( ( tempcl > 0 ) || ( tempcl == 0 ) ) + { + tempah=(0x008>>tempcl) ; + if ( tempah == 0 ) + tempah = 1 ; + tempah |= 0x040; + } + } + else + { + tempah = 0x040 ; + } + + if ( pVBInfo->VBInfo & SetInSlaveMode ) + { + tempah = ( tempah ^ 0x050 ) ; + } + } +*/ + + XGINew_SetReg1( pVBInfo->Part1Port , 0x00 , tempah ) ; + tempah = 0x08 ; + tempbl = 0xf0 ; + + if ( pVBInfo->VBInfo & DisableCRT2Display ) + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ; + else + { + tempah = 0x00 ; + tempbl = 0xff ; + + if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) ) + { + if ( ( pVBInfo->VBInfo & SetCRT2ToLCDA ) && ( !( pVBInfo->VBInfo & SetSimuScanMode ) ) ) + { + tempbl &= 0xf7 ; + tempah |= 0x01 ; + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ; + } + else + { + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + { + tempbl &= 0xf7 ; + tempah |= 0x01 ; + } + + if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD ) ) + { + tempbl &= 0xf8 ; + tempah = 0x01 ; + + if ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) + tempah |= 0x02 ; + + if ( !( pVBInfo->VBInfo & SetCRT2ToRAMDAC ) ) + { + tempah = tempah ^ 0x05 ; + if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) ) + tempah = tempah ^ 0x01 ; + } + + if ( !( pVBInfo->VBInfo & SetCRT2ToDualEdge ) ) + tempah |= 0x08 ; + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ; + } + else + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ; + } + } + else + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2e , tempbl , tempah ) ; + } + + if ( pVBInfo->VBInfo & ( SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA ) ) + { + tempah &= ( ~0x08 ) ; + if ( ( pVBInfo->ModeType == ModeVGA ) && ( !( pVBInfo->VBInfo & SetInSlaveMode ) ) ) + { + tempah |= 0x010 ; + } + tempah |= 0x080 ; + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + /* if ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) ) */ + /* { */ + tempah |= 0x020 ; + if ( ModeNo > 0x13 ) + { + if ( pVBInfo->VBInfo & DriverMode ) + tempah = tempah ^ 0x20 ; + } + /* } */ + } + + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x0D , ~0x0BF , tempah ) ; + tempah = 0 ; + + if ( pVBInfo->LCDInfo & SetLCDDualLink ) + tempah |= 0x40 ; + + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + /* if ( ( !( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) ) && ( !( pVBInfo->TVInfo & ( SetYPbPrMode525p | SetYPbPrMode750p ) ) ) ) */ + /* { */ + if ( pVBInfo->TVInfo & RPLLDIV2XO ) + tempah |= 0x40 ; + /* } */ + } + + if ( ( pVBInfo->LCDResInfo == Panel1280x1024 ) || ( pVBInfo->LCDResInfo == Panel1280x1024x75 ) ) + tempah |= 0x80 ; + + if ( pVBInfo->LCDResInfo == Panel1280x960 ) + tempah |= 0x80 ; + + XGINew_SetReg1( pVBInfo->Part4Port , 0x0C , tempah ) ; + } + + if ( pVBInfo->VBType & ( VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C ) ) + { + tempah = 0 ; + tempbl = 0xfb ; + + if ( pVBInfo->VBInfo & SetCRT2ToDualEdge ) + { + tempbl=0xff; + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + tempah |= 0x04 ; /* shampoo 0129 */ + } + + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x13 , tempbl , tempah ) ; + tempah = 0x00 ; + tempbl = 0xcf ; + if ( !( pVBInfo->VBInfo & DisableCRT2Display ) ) + { + if ( pVBInfo->VBInfo & SetCRT2ToDualEdge ) + tempah |= 0x30 ; + } + + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2c , tempbl , tempah ) ; + tempah = 0 ; + tempbl = 0x3f ; + + if ( !( pVBInfo->VBInfo & DisableCRT2Display ) ) + { + if ( pVBInfo->VBInfo & SetCRT2ToDualEdge ) + tempah |= 0xc0 ; + } + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x21 , tempbl , tempah ) ; + } + + tempah = 0 ; + tempbl = 0x7f ; + if ( !( pVBInfo->VBInfo & SetCRT2ToLCDA ) ) + { + tempbl = 0xff ; + if ( !( pVBInfo->VBInfo & SetCRT2ToDualEdge ) ) + tempah |= 0x80 ; + } + + XGINew_SetRegANDOR( pVBInfo->Part4Port , 0x23 , tempbl , tempah ) ; + + if ( pVBInfo->VBType & ( VB_XGI302LV | VB_XGI301C ) ) + { + if ( pVBInfo->LCDInfo & SetLCDDualLink ) + { + XGINew_SetRegOR( pVBInfo->Part4Port , 0x27 , 0x20 ) ; + XGINew_SetRegOR( pVBInfo->Part4Port , 0x34 , 0x10 ) ; + } + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_CloseCRTC */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_CloseCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempbx ; + + tempbx = 0 ; + + if ( pVBInfo->VBInfo & SetCRT2ToLCDA ) + tempbx = 0x08A0 ; + + +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_OpenCRTC */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_OpenCRTC( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempbx ; + + tempbx = 0 ; + + +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetRAMDAC2DATA */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_GetRAMDAC2DATA(USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex, PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempax , + tempbx , + temp1 , + temp2 , + modeflag = 0 , + tempcx , + StandTableIndex , + CRT1Index ; + + pVBInfo->RVBHCMAX = 1 ; + pVBInfo->RVBHCFACT = 1 ; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + StandTableIndex = XGI_GetModePtr( ModeNo , ModeIdIndex, pVBInfo ) ; + tempax = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 0 ] ; + tempbx = pVBInfo->StandTable[StandTableIndex ].CRTC[ 6 ] ; + temp1 = pVBInfo->StandTable[ StandTableIndex ].CRTC[ 7 ] ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + CRT1Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT1CRTC ; + CRT1Index &= IndexMask ; + temp1 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 0 ] ; + temp2 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 5 ] ; + tempax = ( temp1 & 0xFF ) | ( ( temp2 & 0x03 ) << 8 ) ; + tempbx = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 8 ] ; + tempcx = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 14 ] << 8 ; + tempcx &= 0x0100 ; + tempcx = tempcx << 2 ; + tempbx |= tempcx; + temp1 = ( USHORT )pVBInfo->XGINEWUB_CRT1Table[ CRT1Index ].CR[ 9 ] ; + } + + if ( temp1 & 0x01 ) + tempbx |= 0x0100 ; + + if ( temp1 & 0x20 ) + tempbx |= 0x0200 ; + tempax += 5 ; + + if ( modeflag & Charx8Dot ) + tempax *= 8 ; + else + tempax *= 9 ; + + pVBInfo->VGAHT = tempax ; + pVBInfo->HT = tempax ; + tempbx++ ; + pVBInfo->VGAVT = tempbx ; + pVBInfo->VT = tempbx ; +} + + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetColorDepth */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +USHORT XGI_GetColorDepth(USHORT ModeNo , USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo) +{ + USHORT ColorDepth[ 6 ] = { 1 , 2 , 4 , 4 , 6 , 8 } ; + SHORT index ; + USHORT modeflag ; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; + } + + index=(modeflag&ModeInfoFlag)-ModeEGA; + + if ( index < 0 ) + index = 0 ; + + return( ColorDepth[ index ] ) ; +} + + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_UnLockCRT2 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_UnLockCRT2( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo ) +{ + + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2f , 0xFF , 0x01 ) ; + +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_LockCRT2 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_LockCRT2( PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO pVBInfo ) +{ + + XGINew_SetRegANDOR( pVBInfo->Part1Port , 0x2F , 0xFE , 0x00 ) ; + + +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_EnableCRT2 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_EnableCRT2( PVB_DEVICE_INFO pVBInfo) +{ + XGINew_SetRegANDOR( pVBInfo->P3c4 , 0x1E , 0xFF , 0x20 ) ; +} + + + +/* --------------------------------------------------------------------- */ +/* Function : */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_LCD_Wait_Time(UCHAR DelayTime, PVB_DEVICE_INFO pVBInfo) +{ + USHORT i , + j ; + + ULONG temp , + flag ; + + flag = 0 ; +//printk("XGINew_LCD_Wait_Time"); +//return; + for( i = 0 ; i < DelayTime ; i++ ) + { + for( j = 0 ; j < 66 ; j++ ) + { + + temp = XGINew_GetReg3( 0x61 ) ; + + //temp &= 0x10000000; + temp &= 0x10; + if ( temp == flag ) + continue ; + + flag = temp ; + } + } +} + + + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_BridgeIsOn */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +BOOLEAN XGI_BridgeIsOn( PVB_DEVICE_INFO pVBInfo ) +{ + USHORT flag ; + + if ( pVBInfo->IF_DEF_LVDS == 1 ) + { + return( 1 ) ; + } + else + { + flag = XGINew_GetReg1( pVBInfo->Part4Port , 0x00 ) ; + if ( ( flag == 1 ) || ( flag == 2 ) ) + return( 1 ) ; /* 301b */ + else + return( 0 ) ; + } +} + + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_LongWait */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_LongWait(PVB_DEVICE_INFO pVBInfo) +{ + USHORT i ; + + i = XGINew_GetReg1( pVBInfo->P3c4 , 0x1F ) ; + + if ( !( i & 0xC0 ) ) + { + for( i = 0 ; i < 0xFFFF ; i++ ) + { + if ( !( XGINew_GetReg2( pVBInfo->P3da ) & 0x08 ) ) + break ; + } + + for( i = 0 ; i < 0xFFFF ; i++ ) + { + if ( ( XGINew_GetReg2( pVBInfo->P3da ) & 0x08 ) ) + break ; + } + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_VBLongWait */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGI_VBLongWait( PVB_DEVICE_INFO pVBInfo ) +{ + USHORT tempal , + temp , + i , + j ; +return ; + if ( !( pVBInfo->VBInfo & SetCRT2ToTV ) ) + { + temp = 0 ; + for( i = 0 ; i < 3 ; i++ ) + { + for( j = 0 ; j < 100 ; j++ ) + { + tempal = XGINew_GetReg2( pVBInfo->P3da ) ; + if ( temp & 0x01 ) + { /* VBWaitMode2 */ + if ( ( tempal & 0x08 ) ) + { + continue ; + } + + if ( !( tempal & 0x08 ) ) + { + break ; + } + } + else + { /* VBWaitMode1 */ + if ( !( tempal & 0x08 ) ) + { + continue ; + } + + if ( ( tempal & 0x08 ) ) + { + break ; + } + } + } + temp = temp ^ 0x01 ; + } + } + else + { + XGI_LongWait(pVBInfo) ; + } + return ; +} + + + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetVGAHT2 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +USHORT XGI_GetVGAHT2( PVB_DEVICE_INFO pVBInfo ) +{ + ULONG tempax , + tempbx ; + + tempbx = ( ( pVBInfo->VGAVT - pVBInfo->VGAVDE ) * pVBInfo->RVBHCMAX ) & 0xFFFF ; + tempax = ( pVBInfo->VT - pVBInfo->VDE ) * pVBInfo->RVBHCFACT ; + tempax = ( tempax * pVBInfo->HT ) /tempbx ; + + return( ( USHORT )tempax ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGI_GetVCLK2Ptr */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +USHORT XGI_GetVCLK2Ptr( USHORT ModeNo , USHORT ModeIdIndex , USHORT RefreshRateTableIndex , PXGI_HW_DEVICE_INFO HwDeviceExtension ,PVB_DEVICE_INFO pVBInfo) +{ + USHORT tempbx ; + + USHORT LCDXlat1VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ; + USHORT LCDXlat2VCLK[ 4 ] = { VCLK108_2 + 5 , VCLK108_2 + 5 , VCLK108_2 + 5 , VCLK108_2 + 5 } ; + USHORT LVDSXlat1VCLK[ 4 ] = { VCLK40 , VCLK40 , VCLK40 , VCLK40 } ; + USHORT LVDSXlat2VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ; + USHORT LVDSXlat3VCLK[ 4 ] = { VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 , VCLK65 + 2 } ; + + USHORT CRT2Index , VCLKIndex ; + USHORT modeflag , resinfo ; + UCHAR *CHTVVCLKPtr = NULL ; + + if ( ModeNo <= 0x13 ) + { + modeflag = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ModeFlag ; /* si+St_ResInfo */ + resinfo = pVBInfo->SModeIDTable[ ModeIdIndex ].St_ResInfo ; + CRT2Index = pVBInfo->SModeIDTable[ ModeIdIndex ].St_CRT2CRTC ; + } + else + { + modeflag = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_ModeFlag ; /* si+Ext_ResInfo */ + resinfo = pVBInfo->EModeIDTable[ ModeIdIndex ].Ext_RESINFO ; + CRT2Index = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRT2CRTC ; + } + + if ( pVBInfo->IF_DEF_LVDS == 0 ) + { + CRT2Index = CRT2Index >> 6 ; /* for LCD */ + if ( ( ( pVBInfo->VBInfo & SetCRT2ToLCD ) | SetCRT2ToLCDA ) ) /*301b*/ + { + if ( pVBInfo->LCDResInfo != Panel1024x768 ) + { + VCLKIndex = LCDXlat2VCLK[ CRT2Index ] ; + } + else + { + VCLKIndex = LCDXlat1VCLK[ CRT2Index ] ; + } + } + else /* for TV */ + { + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + if ( pVBInfo->VBInfo & SetCRT2ToHiVisionTV ) + { + if ( pVBInfo->SetFlag & RPLLDIV2XO ) + { + VCLKIndex = HiTVVCLKDIV2 ; + + + VCLKIndex += 25 ; + + } + else + { + VCLKIndex = HiTVVCLK ; + + + VCLKIndex += 25 ; + + } + + if ( pVBInfo->SetFlag & TVSimuMode ) + { + if( modeflag & Charx8Dot ) + { + VCLKIndex = HiTVSimuVCLK ; + + + VCLKIndex += 25 ; + + } + else + { + VCLKIndex = HiTVTextVCLK ; + + + VCLKIndex += 25 ; + + } + } + + if ( pVBInfo->VBType & VB_XGI301LV ) /* 301lv */ + { + if ( !( pVBInfo->VBExtInfo == VB_YPbPr1080i ) ) + { + VCLKIndex = YPbPr750pVCLK ; + if ( !( pVBInfo->VBExtInfo == VB_YPbPr750p ) ) + { + VCLKIndex = YPbPr525pVCLK ; + if ( !( pVBInfo->VBExtInfo == VB_YPbPr525p ) ) + { + VCLKIndex = YPbPr525iVCLK_2 ; + if ( !( pVBInfo->SetFlag & RPLLDIV2XO ) ) + VCLKIndex = YPbPr525iVCLK ; + } + } + } + } + } + else + { + if ( pVBInfo->VBInfo & SetCRT2ToTV ) + { + if ( pVBInfo->SetFlag & RPLLDIV2XO ) + { + VCLKIndex = TVVCLKDIV2 ; + + + VCLKIndex += 25 ; + + } + else + { + VCLKIndex = TVVCLK ; + + + VCLKIndex += 25 ; + + } + } + } + } + else + { /* for CRT2 */ + VCLKIndex = ( UCHAR )XGINew_GetReg2( ( pVBInfo->P3ca + 0x02 ) ) ; /* Port 3cch */ + VCLKIndex = ( ( VCLKIndex >> 2 ) & 0x03 ) ; + if ( ModeNo > 0x13 ) + { + VCLKIndex = pVBInfo->RefIndex[ RefreshRateTableIndex ].Ext_CRTVCLK ; /* di+Ext_CRTVCLK */ + VCLKIndex &= IndexMask ; + } + } + } + } + else + { /* LVDS */ + if ( ModeNo <= 0x13 ) + VCLKIndex = CRT2Index ; + else + VCLKIndex = CRT2Index ; + + if ( pVBInfo->IF_DEF_CH7005 == 1 ) + { + if ( !( pVBInfo->VBInfo & SetCRT2ToLCD ) ) + { + VCLKIndex &= 0x1f ; + tempbx = 0 ; + + if ( pVBInfo->VBInfo & SetPALTV ) + tempbx += 2 ; + + if ( pVBInfo->VBInfo & SetCHTVOverScan ) + tempbx += 1 ; + + switch( tempbx ) + { + case 0: + CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC ; + break ; + case 1: + CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC ; + break; + case 2: + CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL ; + break ; + case 3: + CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL ; + break ; + default: + break ; + } + + VCLKIndex = CHTVVCLKPtr[ VCLKIndex ] ; + } + } + else + { + VCLKIndex = VCLKIndex >> 6 ; + if ( ( pVBInfo->LCDResInfo == Panel800x600 ) || ( pVBInfo->LCDResInfo == Panel320x480 ) ) + VCLKIndex = LVDSXlat1VCLK[ VCLKIndex ] ; + else if ( ( pVBInfo->LCDResInfo == Panel1024x768 ) || ( pVBInfo->LCDResInfo == Panel1024x768x75 ) ) + VCLKIndex = LVDSXlat2VCLK[ VCLKIndex ] ; + else + VCLKIndex = LVDSXlat3VCLK[ VCLKIndex ] ; + } + } + /* VCLKIndex = VCLKIndex&IndexMask ; */ + + + + return( VCLKIndex ) ; +} + diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h new file mode 100644 index 000000000000..09753d706665 --- /dev/null +++ b/drivers/staging/xgifb/vb_setmode.h @@ -0,0 +1,40 @@ +#ifndef _VBSETMODE_ +#define _VBSETMODE_ + +extern void InitTo330Pointer(UCHAR,PVB_DEVICE_INFO); +extern void XGI_UnLockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO ); +extern void XGI_LockCRT2(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO ); +extern void XGI_LongWait( PVB_DEVICE_INFO ); +extern void XGI_SetCRT2ModeRegs(USHORT ModeNo,PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO ); +extern void XGI_DisableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO ); +extern void XGI_EnableBridge(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO ); +extern void XGI_DisplayOff( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO ); +extern void XGI_DisplayOn( PXGI_HW_DEVICE_INFO, PVB_DEVICE_INFO ); +extern void XGI_GetVBType(PVB_DEVICE_INFO); +extern void XGI_SenseCRT1(PVB_DEVICE_INFO ); +extern void XGI_GetVGAType(PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO ); +extern void XGI_GetVBInfo(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO ); +extern void XGI_GetTVInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO ); +extern void XGI_SetCRT1Offset(USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO ); +extern void XGI_SetLCDAGroup(USHORT ModeNo,USHORT ModeIdIndex,PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO ); +extern void XGI_WaitDisply( PVB_DEVICE_INFO ); +extern USHORT XGI_GetResInfo(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo); + +extern BOOLEAN XGISetModeNew( PXGI_HW_DEVICE_INFO HwDeviceExtension , USHORT ModeNo ) ; + +extern BOOLEAN XGI_SearchModeID( USHORT ModeNo,USHORT *ModeIdIndex, PVB_DEVICE_INFO ); +extern BOOLEAN XGI_GetLCDInfo(USHORT ModeNo,USHORT ModeIdIndex,PVB_DEVICE_INFO ); +extern BOOLEAN XGI_BridgeIsOn( PVB_DEVICE_INFO ); +extern BOOLEAN XGI_SetCRT2Group301(USHORT ModeNo, PXGI_HW_DEVICE_INFO HwDeviceExtension, PVB_DEVICE_INFO); +extern USHORT XGI_GetRatePtrCRT2( PXGI_HW_DEVICE_INFO pXGIHWDE, USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO ); + +extern void XGI_SetXG21FPBits(PVB_DEVICE_INFO pVBInfo); +extern void XGI_SetXG27FPBits(PVB_DEVICE_INFO pVBInfo); +extern void XGI_XG21BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo); +extern void XGI_XG27BLSignalVDD(USHORT tempbh,USHORT tempbl, PVB_DEVICE_INFO pVBInfo); +extern void XGI_XG21SetPanelDelay(USHORT tempbl, PVB_DEVICE_INFO pVBInfo); +extern BOOLEAN XGI_XG21CheckLVDSMode(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ); +extern void XGI_SetXG21LVDSPara(USHORT ModeNo,USHORT ModeIdIndex, PVB_DEVICE_INFO pVBInfo ); +extern USHORT XGI_GetLVDSOEMTableIndex(PVB_DEVICE_INFO pVBInfo); + +#endif diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h new file mode 100644 index 000000000000..bb25c0e2785e --- /dev/null +++ b/drivers/staging/xgifb/vb_struct.h @@ -0,0 +1,534 @@ +#ifndef _VB_STRUCT_ +#define _VB_STRUCT_ + +#ifdef _INITNEW_ +#define EXTERN +#else +#define EXTERN extern +#endif + + + + +typedef struct _XGI_PanelDelayTblStruct +{ + UCHAR timer[2]; +} XGI_PanelDelayTblStruct; + +typedef struct _XGI_LCDDataStruct +{ + USHORT RVBHCMAX; + USHORT RVBHCFACT; + USHORT VGAHT; + USHORT VGAVT; + USHORT LCDHT; + USHORT LCDVT; +} XGI_LCDDataStruct; + + +typedef struct _XGI_LVDSCRT1HDataStruct +{ + UCHAR Reg[8]; +} XGI_LVDSCRT1HDataStruct; +typedef struct _XGI_LVDSCRT1VDataStruct +{ + UCHAR Reg[7]; +} XGI_LVDSCRT1VDataStruct; + + +typedef struct _XGI_TVDataStruct +{ + USHORT RVBHCMAX; + USHORT RVBHCFACT; + USHORT VGAHT; + USHORT VGAVT; + USHORT TVHDE; + USHORT TVVDE; + USHORT RVBHRS; + UCHAR FlickerMode; + USHORT HALFRVBHRS; + UCHAR RY1COE; + UCHAR RY2COE; + UCHAR RY3COE; + UCHAR RY4COE; +} XGI_TVDataStruct; + +typedef struct _XGI_LVDSDataStruct +{ + USHORT VGAHT; + USHORT VGAVT; + USHORT LCDHT; + USHORT LCDVT; +} XGI_LVDSDataStruct; + +typedef struct _XGI_LVDSDesStruct +{ + USHORT LCDHDES; + USHORT LCDVDES; +} XGI_LVDSDesStruct; + +typedef struct _XGI_LVDSCRT1DataStruct +{ + UCHAR CR[15]; +} XGI_LVDSCRT1DataStruct; + +/*add for LCDA*/ + + +typedef struct _XGI_StStruct +{ + UCHAR St_ModeID; + USHORT St_ModeFlag; + UCHAR St_StTableIndex; + UCHAR St_CRT2CRTC; + UCHAR St_CRT2CRTC2; + UCHAR St_ResInfo; + UCHAR VB_StTVFlickerIndex; + UCHAR VB_StTVEdgeIndex; + UCHAR VB_StTVYFilterIndex; +} XGI_StStruct; + +typedef struct _XGI_StandTableStruct +{ + UCHAR CRT_COLS; + UCHAR ROWS; + UCHAR CHAR_HEIGHT; + USHORT CRT_LEN; + UCHAR SR[4]; + UCHAR MISC; + UCHAR CRTC[0x19]; + UCHAR ATTR[0x14]; + UCHAR GRC[9]; +} XGI_StandTableStruct; + +typedef struct _XGI_ExtStruct +{ + UCHAR Ext_ModeID; + USHORT Ext_ModeFlag; + USHORT Ext_ModeInfo; + USHORT Ext_Point; + USHORT Ext_VESAID; + UCHAR Ext_VESAMEMSize; + UCHAR Ext_RESINFO; + UCHAR VB_ExtTVFlickerIndex; + UCHAR VB_ExtTVEdgeIndex; + UCHAR VB_ExtTVYFilterIndex; + UCHAR REFindex; +} XGI_ExtStruct; + +typedef struct _XGI_Ext2Struct +{ + USHORT Ext_InfoFlag; + UCHAR Ext_CRT1CRTC; + UCHAR Ext_CRTVCLK; + UCHAR Ext_CRT2CRTC; + UCHAR Ext_CRT2CRTC2; + UCHAR ModeID; + USHORT XRes; + USHORT YRes; + /* USHORT ROM_OFFSET; */ +} XGI_Ext2Struct; + + +typedef struct _XGI_MCLKDataStruct +{ + UCHAR SR28,SR29,SR2A; + USHORT CLOCK; +} XGI_MCLKDataStruct; + +typedef struct _XGI_ECLKDataStruct +{ + UCHAR SR2E,SR2F,SR30; + USHORT CLOCK; +} XGI_ECLKDataStruct; + +typedef struct _XGI_VCLKDataStruct +{ + UCHAR SR2B,SR2C; + USHORT CLOCK; +} XGI_VCLKDataStruct; + +typedef struct _XGI_VBVCLKDataStruct +{ + UCHAR Part4_A,Part4_B; + USHORT CLOCK; +} XGI_VBVCLKDataStruct; + +typedef struct _XGI_StResInfoStruct +{ + USHORT HTotal; + USHORT VTotal; +} XGI_StResInfoStruct; + +typedef struct _XGI_ModeResInfoStruct +{ + USHORT HTotal; + USHORT VTotal; + UCHAR XChar; + UCHAR YChar; +} XGI_ModeResInfoStruct; + +typedef struct _XGI_LCDNBDesStruct +{ + UCHAR NB[12]; +} XGI_LCDNBDesStruct; + /*add for new UNIVGABIOS*/ +typedef struct _XGI_LCDDesStruct +{ + USHORT LCDHDES; + USHORT LCDHRS; + USHORT LCDVDES; + USHORT LCDVRS; +} XGI_LCDDesStruct; + +typedef struct _XGI_LCDDataTablStruct +{ + UCHAR PANELID; + USHORT MASK; + USHORT CAP; + USHORT DATAPTR; +} XGI_LCDDataTablStruct; + +typedef struct _XGI_TVTablDataStruct +{ + USHORT MASK; + USHORT CAP; + USHORT DATAPTR; +} XGI_TVDataTablStruct; + +typedef struct _XGI330_LCDDesDataStruct +{ + USHORT LCDHDES; + USHORT LCDHRS; + USHORT LCDVDES; + USHORT LCDVRS; +} XGI330_LCDDataDesStruct; + + +typedef struct _XGI330_LVDSDataStruct +{ + USHORT VGAHT; + USHORT VGAVT; + USHORT LCDHT; + USHORT LCDVT; +} XGI330_LVDSDataStruct; + +typedef struct _XGI330_LCDDesDataStruct2 +{ + USHORT LCDHDES; + USHORT LCDHRS; + USHORT LCDVDES; + USHORT LCDVRS; + USHORT LCDHSync; + USHORT LCDVSync; +} XGI330_LCDDataDesStruct2; + +typedef struct _XGI330_LCDDataStruct +{ + USHORT RVBHCMAX; + USHORT RVBHCFACT; + USHORT VGAHT; + USHORT VGAVT; + USHORT LCDHT; + USHORT LCDVT; +} XGI330_LCDDataStruct; + + +typedef struct _XGI330_TVDataStruct +{ + USHORT RVBHCMAX; + USHORT RVBHCFACT; + USHORT VGAHT; + USHORT VGAVT; + USHORT TVHDE; + USHORT TVVDE; + USHORT RVBHRS; + UCHAR FlickerMode; + USHORT HALFRVBHRS; +} XGI330_TVDataStruct; + +typedef struct _XGI330_LCDDataTablStruct +{ + UCHAR PANELID; + USHORT MASK; + USHORT CAP; + USHORT DATAPTR; +} XGI330_LCDDataTablStruct; + +typedef struct _XGI330_TVDataTablStruct +{ + USHORT MASK; + USHORT CAP; + USHORT DATAPTR; +} XGI330_TVDataTablStruct; + + +typedef struct _XGI330_CHTVDataStruct +{ + USHORT VGAHT; + USHORT VGAVT; + USHORT LCDHT; + USHORT LCDVT; +} XGI330_CHTVDataStruct; + +typedef struct _XGI_TimingHStruct +{ + UCHAR data[8]; +} XGI_TimingHStruct; + +typedef struct _XGI_TimingVStruct +{ + UCHAR data[7]; +} XGI_TimingVStruct; + +typedef struct _XGI_CH7007TV_TimingHStruct +{ + UCHAR data[10]; +} XGI_CH7007TV_TimingHStruct; + +typedef struct _XGI_CH7007TV_TimingVStruct +{ + UCHAR data[10]; +} XGI_CH7007TV_TimingVStruct; + +typedef struct _XGI_XG21CRT1Struct +{ + UCHAR ModeID,CR02,CR03,CR15,CR16; +} XGI_XG21CRT1Struct; + +typedef struct _XGI330_CHTVRegDataStruct +{ + UCHAR Reg[16]; +} XGI330_CHTVRegDataStruct; + +typedef struct _XGI330_LCDCapStruct +{ + UCHAR LCD_ID; + USHORT LCD_Capability; + UCHAR LCD_SetFlag; + UCHAR LCD_DelayCompensation; + UCHAR LCD_HSyncWidth; + UCHAR LCD_VSyncWidth; + UCHAR LCD_VCLK; + UCHAR LCDA_VCLKData1; + UCHAR LCDA_VCLKData2; + UCHAR LCUCHAR_VCLKData1; + UCHAR LCUCHAR_VCLKData2; + UCHAR PSC_S1; + UCHAR PSC_S2; + UCHAR PSC_S3; + UCHAR PSC_S4; + UCHAR PSC_S5; + UCHAR PWD_2B; + UCHAR PWD_2C; + UCHAR PWD_2D; + UCHAR PWD_2E; + UCHAR PWD_2F; + UCHAR Spectrum_31; + UCHAR Spectrum_32; + UCHAR Spectrum_33; + UCHAR Spectrum_34; +} XGI330_LCDCapStruct; + +typedef struct _XGI21_LVDSCapStruct +{ + USHORT LVDS_Capability; + USHORT LVDSHT; + USHORT LVDSVT; + USHORT LVDSHDE; + USHORT LVDSVDE; + USHORT LVDSHFP; + USHORT LVDSVFP; + USHORT LVDSHSYNC; + USHORT LVDSVSYNC; + UCHAR VCLKData1; + UCHAR VCLKData2; + UCHAR PSC_S1; + UCHAR PSC_S2; + UCHAR PSC_S3; + UCHAR PSC_S4; + UCHAR PSC_S5; +} XGI21_LVDSCapStruct; + +typedef struct _XGI_CRT1TableStruct +{ + UCHAR CR[16]; +} XGI_CRT1TableStruct; + + +typedef struct _XGI330_VCLKDataStruct +{ + UCHAR SR2B,SR2C; + USHORT CLOCK; +} XGI330_VCLKDataStruct; + +typedef struct _XGI301C_Tap4TimingStruct +{ + USHORT DE; + UCHAR Reg[64]; /* C0-FF */ +} XGI301C_Tap4TimingStruct; + +typedef struct _XGI_New_StandTableStruct +{ + UCHAR CRT_COLS; + UCHAR ROWS; + UCHAR CHAR_HEIGHT; + USHORT CRT_LEN; + UCHAR SR[4]; + UCHAR MISC; + UCHAR CRTC[0x19]; + UCHAR ATTR[0x14]; + UCHAR GRC[9]; +} XGI_New_StandTableStruct; + +typedef UCHAR DRAM8Type[8]; +typedef UCHAR DRAM4Type[4]; +typedef UCHAR DRAM32Type[32]; +typedef UCHAR DRAM2Type[2]; + +typedef struct _VB_DEVICE_INFO VB_DEVICE_INFO; +typedef VB_DEVICE_INFO * PVB_DEVICE_INFO; + +struct _VB_DEVICE_INFO +{ + BOOLEAN ISXPDOS; + ULONG P3c4,P3d4,P3c0,P3ce,P3c2,P3cc; + ULONG P3ca,P3c6,P3c7,P3c8,P3c9,P3da; + ULONG Part0Port,Part1Port,Part2Port; + ULONG Part3Port,Part4Port,Part5Port; + USHORT RVBHCFACT,RVBHCMAX,RVBHRS; + USHORT VGAVT,VGAHT,VGAVDE,VGAHDE; + USHORT VT,HT,VDE,HDE; + USHORT LCDHRS,LCDVRS,LCDHDES,LCDVDES; + + USHORT ModeType; + USHORT IF_DEF_LVDS,IF_DEF_TRUMPION,IF_DEF_DSTN;/* ,IF_DEF_FSTN; add for dstn */ + USHORT IF_DEF_CRT2Monitor,IF_DEF_VideoCapture; + USHORT IF_DEF_LCDA,IF_DEF_CH7017,IF_DEF_YPbPr,IF_DEF_ScaleLCD,IF_DEF_OEMUtil,IF_DEF_PWD; + USHORT IF_DEF_ExpLink; + USHORT IF_DEF_CH7005,IF_DEF_HiVision; + USHORT IF_DEF_CH7007; /* Billy 2007/05/03 */ + USHORT LCDResInfo,LCDTypeInfo, VBType;/*301b*/ + USHORT VBInfo,TVInfo,LCDInfo, Set_VGAType; + USHORT VBExtInfo;/*301lv*/ + USHORT SetFlag; + USHORT NewFlickerMode; + USHORT SelectCRT2Rate; + + PUCHAR ROMAddr; + PUCHAR FBAddr; + ULONG BaseAddr; + ULONG RelIO; + + DRAM4Type *CR6B; + DRAM4Type *CR6E; + DRAM32Type *CR6F; + DRAM2Type *CR89; + + DRAM8Type *SR15; /* pointer : point to array */ + DRAM8Type *CR40; + UCHAR *pSoftSetting; + UCHAR *pOutputSelect; + + USHORT *pRGBSenseData; + USHORT *pRGBSenseData2; /*301b*/ + USHORT *pVideoSenseData; + USHORT *pVideoSenseData2; + USHORT *pYCSenseData; + USHORT *pYCSenseData2; + + UCHAR *pSR07; + UCHAR *CR49; + UCHAR *pSR1F; + UCHAR *AGPReg; + UCHAR *SR16; + UCHAR *pSR21; + UCHAR *pSR22; + UCHAR *pSR23; + UCHAR *pSR24; + UCHAR *SR25; + UCHAR *pSR31; + UCHAR *pSR32; + UCHAR *pSR33; + UCHAR *pSR36; /* alan 12/07/2006 */ + UCHAR *pCRCF; + UCHAR *pCRD0; /* alan 12/07/2006 */ + UCHAR *pCRDE; /* alan 12/07/2006 */ + UCHAR *pCR8F; /* alan 12/07/2006 */ + UCHAR *pSR40; /* alan 12/07/2006 */ + UCHAR *pSR41; /* alan 12/07/2006 */ + UCHAR *pDVOSetting; + UCHAR *pCR2E; + UCHAR *pCR2F; + UCHAR *pCR46; + UCHAR *pCR47; + UCHAR *pCRT2Data_1_2; + UCHAR *pCRT2Data_4_D; + UCHAR *pCRT2Data_4_E; + UCHAR *pCRT2Data_4_10; + XGI_MCLKDataStruct *MCLKData; + XGI_ECLKDataStruct *ECLKData; + + UCHAR *XGI_TVDelayList; + UCHAR *XGI_TVDelayList2; + UCHAR *CHTVVCLKUNTSC; + UCHAR *CHTVVCLKONTSC; + UCHAR *CHTVVCLKUPAL; + UCHAR *CHTVVCLKOPAL; + UCHAR *NTSCTiming; + UCHAR *PALTiming; + UCHAR *HiTVExtTiming; + UCHAR *HiTVSt1Timing; + UCHAR *HiTVSt2Timing; + UCHAR *HiTVTextTiming; + UCHAR *YPbPr750pTiming; + UCHAR *YPbPr525pTiming; + UCHAR *YPbPr525iTiming; + UCHAR *HiTVGroup3Data; + UCHAR *HiTVGroup3Simu; + UCHAR *HiTVGroup3Text; + UCHAR *Ren525pGroup3; + UCHAR *Ren750pGroup3; + UCHAR *ScreenOffset; + UCHAR *pXGINew_DRAMTypeDefinition; + UCHAR *pXGINew_I2CDefinition ; + UCHAR *pXGINew_CR97 ; + + XGI330_LCDCapStruct *LCDCapList; + XGI21_LVDSCapStruct *XG21_LVDSCapList; + + XGI_TimingHStruct *TimingH; + XGI_TimingVStruct *TimingV; + + XGI_StStruct *SModeIDTable; + XGI_StandTableStruct *StandTable; + XGI_ExtStruct *EModeIDTable; + XGI_Ext2Struct *RefIndex; + /* XGINew_CRT1TableStruct *CRT1Table; */ + XGI_CRT1TableStruct *XGINEWUB_CRT1Table; + XGI_VCLKDataStruct *VCLKData; + XGI_VBVCLKDataStruct *VBVCLKData; + XGI_StResInfoStruct *StResInfo; + XGI_ModeResInfoStruct *ModeResInfo; + XGI_XG21CRT1Struct *UpdateCRT1; +}; /* _VB_DEVICE_INFO */ + + +typedef struct +{ + USHORT Horizontal_ACTIVE; + USHORT Horizontal_FP; + USHORT Horizontal_SYNC; + USHORT Horizontal_BP; + USHORT Vertical_ACTIVE; + USHORT Vertical_FP; + USHORT Vertical_SYNC; + USHORT Vertical_BP; + double DCLK; + UCHAR FrameRate; + UCHAR Interlace; + USHORT Margin; +} TimingInfo; + +#define _VB_STRUCT_ +#endif /* _VB_STRUCT_ */ diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h new file mode 100644 index 000000000000..781caefc56b1 --- /dev/null +++ b/drivers/staging/xgifb/vb_table.h @@ -0,0 +1,4406 @@ +#define Tap4 + + +XGI_MCLKDataStruct XGI330New_MCLKData[]= +{ + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166}, + { 0x7C,0x08,0x80,200}, + { 0x79,0x06,0x80,250}, + { 0x29,0x01,0x81,300}, + { 0x29,0x01,0x81,300}, + { 0x29,0x01,0x81,300}, + { 0x29,0x01,0x81,300} +}; +//yilin modify for xgi20 +XGI_MCLKDataStruct XGI340New_MCLKData[]= +{ + { 0x16,0x01,0x01,166}, + { 0x19,0x02,0x01,124}, + { 0x7C,0x08,0x01,200}, + { 0x79,0x06,0x01,250}, + { 0x29,0x01,0x81,301}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166} +}; + +XGI_MCLKDataStruct XGI27New_MCLKData[]= +{ + { 0x5c,0x23,0x01,166}, + { 0x19,0x02,0x01,124}, + { 0x7C,0x08,0x80,200}, + { 0x79,0x06,0x80,250}, + { 0x29,0x01,0x81,300}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166} +}; + +XGI_ECLKDataStruct XGI330_ECLKData[]= +{ + { 0x7c,0x08,0x01,200}, + { 0x7c,0x08,0x01,200}, + { 0x7C,0x08,0x80,200}, + { 0x79,0x06,0x80,250}, + { 0x29,0x01,0x81,300}, + { 0x29,0x01,0x81,300}, + { 0x29,0x01,0x81,300}, + { 0x29,0x01,0x81,300} +}; +//yilin modify for xgi20 +XGI_ECLKDataStruct XGI340_ECLKData[]= +{ + { 0x5c,0x23,0x01,166}, + { 0x55,0x84,0x01,123}, + { 0x7C,0x08,0x01,200}, + { 0x79,0x06,0x01,250}, + { 0x29,0x01,0x81,301}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166}, + { 0x5c,0x23,0x01,166} +}; + + + +UCHAR XGI340_SR13[4][8]={ +{0x35,0x45,0xb1,0x00,0x00,0x00,0x00,0x00},/* SR13 */ +{0x41,0x51,0x5c,0x00,0x00,0x00,0x00,0x00},/* SR14 */ +{0x31,0x42,0x42,0x00,0x00,0x00,0x00,0x00},/* SR18 */ +{0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00}/* SR1B */ +}; + +UCHAR XGI340_cr41[24][8]= +{{0x20,0x50,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */ +{0xc4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */ +{0xc4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */ +{0xb5,0xa4,0xa4,0x00,0x00,0x00,0x00,0x00}, +{0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00}, +{0x90,0x90,0x24,0x00,0x00,0x00,0x00,0x00},/* 5 CR68 */ +{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 6 CR69 */ +{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 7 CR6A */ +{0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00},/* 8 CR6D */ +{0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00},/* 9 CR80 */ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 10 CR81 */ +{0x88,0xa8,0x48,0x00,0x00,0x00,0x00,0x00},/* 11 CR82 */ +{0x44,0x44,0x77,0x00,0x00,0x00,0x00,0x00},/* 12 CR85 */ +{0x48,0x48,0x88,0x00,0x00,0x00,0x00,0x00},/* 13 CR86 */ +{0x54,0x54,0x44,0x00,0x00,0x00,0x00,0x00},/* 14 CR90 */ +{0x54,0x54,0x44,0x00,0x00,0x00,0x00,0x00},/* 15 CR91 */ +{0x0a,0x0a,0x07,0x00,0x00,0x00,0x00,0x00},/* 16 CR92 */ +{0x44,0x44,0x44,0x00,0x00,0x00,0x00,0x00},/* 17 CR93 */ +{0x10,0x10,0x0A,0x00,0x00,0x00,0x00,0x00},/* 18 CR94 */ +{0x11,0x11,0x0a,0x00,0x00,0x00,0x00,0x00},/* 19 CR95 */ +{0x05,0x05,0x05,0x00,0x00,0x00,0x00,0x00},/* 20 CR96 */ +{0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00},/* 21 CRC3 */ +{0x05,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/* 22 CRC4 */ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */ +}; + + +UCHAR XGI27_cr41[24][8]= +{ +{0x20,0x40,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */ +{0xC4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */ +{0xC4,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */ +{0xB5,0x13,0xa4,0x00,0x00,0x00,0x00,0x00},/* 3 CR40[7],CR99[2:0],CR45[3:0]*/ +{0xf0,0xf5,0xf0,0x00,0x00,0x00,0x00,0x00},/* 4 CR59 */ +{0x90,0x90,0x24,0x00,0x00,0x00,0x00,0x00},/* 5 CR68 */ +{0x77,0x67,0x44,0x00,0x00,0x00,0x00,0x00},/* 6 CR69 */ +{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 7 CR6A */ +{0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00},/* 8 CR6D */ +{0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00},/* 9 CR80 */ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 10 CR81 */ +{0x88,0xcc,0x48,0x00,0x00,0x00,0x00,0x00},/* 11 CR82 */ +{0x44,0x88,0x77,0x00,0x00,0x00,0x00,0x00},/* 12 CR85 */ +{0x48,0x88,0x88,0x00,0x00,0x00,0x00,0x00},/* 13 CR86 */ +{0x54,0x32,0x44,0x00,0x00,0x00,0x00,0x00},/* 14 CR90 */ +{0x54,0x33,0x44,0x00,0x00,0x00,0x00,0x00},/* 15 CR91 */ +{0x0a,0x07,0x07,0x00,0x00,0x00,0x00,0x00},/* 16 CR92 */ +{0x44,0x63,0x44,0x00,0x00,0x00,0x00,0x00},/* 17 CR93 */ +{0x10,0x14,0x0A,0x00,0x00,0x00,0x00,0x00},/* 18 CR94 */ +{0x11,0x0B,0x0C,0x00,0x00,0x00,0x00,0x00},/* 19 CR95 */ +{0x05,0x22,0x05,0x00,0x00,0x00,0x00,0x00},/* 20 CR96 */ +{0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00},/* 21 CRC3 */ +{0x05,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/* 22 CRC4 */ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */ +}; + + +#if 0 +UCHAR XGI27_cr41[24][8]= +{ +{0x20,0x60,0x60,0x00,0x00,0x00,0x00,0x00},/* 0 CR41 */ +{0x04,0x44,0x84,0x00,0x00,0x00,0x00,0x00},/* 1 CR8A */ +{0x04,0x40,0x84,0x00,0x00,0x00,0x00,0x00},/* 2 CR8B */ +{0xb5,0x03,0xa4,0x00,0x00,0x00,0x00,0x00},/* 3 CR40[7],CR99[2:0],CR45[3:0]*/ +{0xf0,0xf5,0xf0,0x00,0x00,0x00,0x00,0x00},/* 4 CR59 */ +{0xa4,0x1C,0x24,0x00,0x00,0x00,0x00,0x00},/* 5 CR68 */ +{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 6 CR69 */ +{0x77,0x77,0x44,0x00,0x00,0x00,0x00,0x00},/* 7 CR6A */ +{0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00},/* 8 CR6D */ +{0x55,0x55,0x55,0x00,0x00,0x00,0x00,0x00},/* 9 CR80 */ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 10 CR81 */ +{0x48,0xa8,0x48,0x00,0x00,0x00,0x00,0x00},/* 11 CR82 */ +{0x77,0x88,0x77,0x00,0x00,0x00,0x00,0x00},/* 12 CR85 */ +{0x88,0x88,0x88,0x00,0x00,0x00,0x00,0x00},/* 13 CR86 */ +{0x44,0x32,0x44,0x00,0x00,0x00,0x00,0x00},/* 14 CR90 */ +{0x44,0x33,0x44,0x00,0x00,0x00,0x00,0x00},/* 15 CR91 */ +{0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00},/* 16 CR92 */ +{0x44,0x63,0x44,0x00,0x00,0x00,0x00,0x00},/* 17 CR93 */ +{0x0A,0x14,0x0A,0x00,0x00,0x00,0x00,0x00},/* 18 CR94 */ +{0x0C,0x0B,0x0C,0x00,0x00,0x00,0x00,0x00},/* 19 CR95 */ +{0x05,0x22,0x05,0x00,0x00,0x00,0x00,0x00},/* 20 CR96 */ +{0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00},/* 21 CRC3 */ +{0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/* 22 CRC4 */ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/* 23 CRC5 */ +}; +#endif +UCHAR XGI340_CR6B[8][4]={ +{0xaa,0xaa,0xaa,0xaa}, +{0xaa,0xaa,0xaa,0xaa}, +{0xaa,0xaa,0xaa,0xaa}, +{0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00} +}; + +UCHAR XGI340_CR6E[8][4]={ +{0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00} +}; + +UCHAR XGI340_CR6F[8][32]={ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} +}; + +UCHAR XGI340_CR89[8][2]={ +{0x00,0x00}, +{0x00,0x00}, +{0x00,0x00}, +{0x00,0x00}, +{0x00,0x00}, +{0x00,0x00}, +{0x00,0x00}, +{0x00,0x00} +}; + /* CR47,CR48,CR49,CR4A,CR4B,CR4C,CR70,CR71,CR74,CR75,CR76,CR77 */ +UCHAR XGI340_AGPReg[12]={0x28,0x23,0x00,0x20,0x00,0x20,0x00,0x05,0xd0,0x10,0x10,0x00}; + +UCHAR XGI340_SR16[4]={0x03,0x83,0x03,0x83}; + +UCHAR XGI330_SR15_1[8][8]={ +{0x0,0x0,0x00,0x00,0x20,0x20,0x00,0x00}, +{0x5,0x15,0x15,0x15,0x15,0x15,0x00,0x00}, +{0xba,0xba,0xba,0xba,0xBA,0xBA,0x00,0x00}, +{0x55,0x57,0x57,0xAB,0xAB,0xAB,0x00,0x00}, +{0x60,0x34,0x34,0x34,0x34,0x34,0x00,0x00}, +{0x0,0x80,0x80,0x80,0x83,0x83,0x00,0x00}, +{0x50,0x50,0x50,0x3C,0x3C,0x3C,0x00,0x00}, +{0x0,0xa5,0xfb,0xf6,0xF6,0xF6,0x00,0x00} +}; + +UCHAR XGI330_cr40_1[15][8]={ +{0x66,0x40,0x40,0x28,0x24,0x24,0x00,0x00}, +{0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00}, +{0x00,0xf0,0xf0,0xf0,0xF0,0xF0,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x10,0x10,0x10,0x10,0x20,0x20,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x88,0x88,0x88,0xAA,0xAC,0xAC,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x77,0x77,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +{0x00,0xA2,0x00,0x00,0xA2,0xA2,0x00,0x00}, +}; + +UCHAR XGI330_sr25[]={0x00,0x0}; +UCHAR XGI330_sr31=0xc0; +UCHAR XGI330_sr32=0x11; +UCHAR XGI330_SR33=0x00; +UCHAR XG40_CRCF=0x13; +UCHAR XG40_DRAMTypeDefinition=0xFF ; + +XGI_StStruct XGI330_SModeIDTable[]= +{ + {0x01,0x9208,0x01,0x00,0x10,0x00,0x00,0x01,0x00}, + {0x01,0x1210,0x14,0x01,0x00,0x01,0x00,0x01,0x00}, + {0x01,0x1010,0x17,0x02,0x11,0x00,0x00,0x01,0x01}, + {0x03,0x8208,0x03,0x00,0x14,0x00,0x00,0x01,0x02}, + {0x03,0x0210,0x16,0x01,0x04,0x01,0x00,0x01,0x02}, + {0x03,0x0010,0x18,0x02,0x15,0x00,0x00,0x01,0x03}, + {0x05,0x9209,0x05,0x00,0x10,0x00,0x00,0x00,0x04}, + {0x06,0x8209,0x06,0x00,0x14,0x00,0x00,0x00,0x05}, + {0x07,0x0000,0x07,0x03,0x05,0x03,0x00,0x01,0x03}, + {0x07,0x0000,0x19,0x02,0x15,0x02,0x00,0x01,0x03}, + {0x0d,0x920a,0x0d,0x00,0x10,0x00,0x00,0x00,0x04}, + {0x0e,0x820a,0x0e,0x00,0x14,0x00,0x00,0x00,0x05}, + {0x0f,0x0202,0x11,0x01,0x04,0x01,0x00,0x00,0x05}, + {0x10,0x0212,0x12,0x01,0x04,0x01,0x00,0x00,0x05}, + {0x11,0x0212,0x1a,0x04,0x24,0x04,0x00,0x00,0x05}, + {0x12,0x0212,0x1b,0x04,0x24,0x04,0x00,0x00,0x05}, + {0x13,0x021b,0x1c,0x00,0x14,0x00,0x00,0x00,0x04}, + {0x12,0x0010,0x18,0x02,0x24,0x02,0x00,0x00,0x05},/* St_CRT2CRTC2 not sure */ + {0x12,0x0210,0x18,0x01,0x24,0x01,0x00,0x00,0x05},/* St_CRT2CRTC2 not sure */ + {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00} +}; + + +XGI_ExtStruct XGI330_EModeIDTable[]= +{ + {0x6a,0x2212,0x0407,0x3a81,0x0102,0x08,0x07,0x00,0x00,0x07,0x0e}, + {0x2e,0x0a1b,0x0306,0x3a57,0x0101,0x08,0x06,0x00,0x00,0x05,0x06}, + {0x2f,0x0a1b,0x0305,0x3a50,0x0100,0x08,0x05,0x00,0x00,0x05,0x05}, + {0x30,0x2a1b,0x0407,0x3a81,0x0103,0x08,0x07,0x00,0x00,0x07,0x0e}, + {0x31,0x0a1b,0x030d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x3d}, + {0x32,0x0a1b,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x3e}, + {0x33,0x0a1d,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x3d}, + {0x34,0x2a1d,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x3e}, + {0x35,0x0a1f,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x3d}, + {0x36,0x2a1f,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x3e}, + {0x37,0x0212,0x0508,0x3aab,0x0104,0x08,0x08,0x00,0x00,0x00,0x16}, + {0x38,0x0a1b,0x0508,0x3aab,0x0105,0x08,0x08,0x00,0x00,0x00,0x16}, + {0x3a,0x0e3b,0x0609,0x3adc,0x0107,0x08,0x09,0x00,0x00,0x00,0x1e}, + {0x3c,0x0e3b,0x070a,0x3af2,0x0130,0x08,0x0a,0x00,0x00,0x00,0x22}, /* mode 1600x1200 add CRT2MODE [2003/10/07] */ + {0x3d,0x0e7d,0x070a,0x3af2,0x0131,0x08,0x0a,0x00,0x00,0x00,0x22}, /* mode 1600x1200 add CRT2MODE */ + {0x40,0x9a1c,0x0000,0x3a34,0x010d,0x08,0x00,0x00,0x00,0x04,0x00}, + {0x41,0x9a1d,0x0000,0x3a34,0x010e,0x08,0x00,0x00,0x00,0x04,0x00}, /* ModeIdIndex = 0x10 */ + {0x43,0x0a1c,0x0306,0x3a57,0x0110,0x08,0x06,0x00,0x00,0x05,0x06}, + {0x44,0x0a1d,0x0306,0x3a57,0x0111,0x08,0x06,0x00,0x00,0x05,0x06}, + {0x46,0x2a1c,0x0407,0x3a81,0x0113,0x08,0x07,0x00,0x00,0x07,0x0e}, + {0x47,0x2a1d,0x0407,0x3a81,0x0114,0x08,0x07,0x00,0x00,0x07,0x0e}, + {0x49,0x0a3c,0x0508,0x3aab,0x0116,0x08,0x08,0x00,0x00,0x00,0x16}, + {0x4a,0x0a3d,0x0508,0x3aab,0x0117,0x08,0x08,0x00,0x00,0x00,0x16}, + {0x4c,0x0e7c,0x0609,0x3adc,0x0119,0x08,0x09,0x00,0x00,0x00,0x1e}, + {0x4d,0x0e7d,0x0609,0x3adc,0x011a,0x08,0x09,0x00,0x00,0x00,0x1e}, + {0x50,0x9a1b,0x0001,0x3a3b,0x0132,0x08,0x01,0x00,0x00,0x04,0x02}, + {0x51,0xba1b,0x0103,0x3a42,0x0133,0x08,0x03,0x00,0x00,0x07,0x03}, + {0x52,0x9a1b,0x0204,0x3a49,0x0134,0x08,0x04,0x00,0x00,0x00,0x04}, + {0x56,0x9a1d,0x0001,0x3a3b,0x0135,0x08,0x01,0x00,0x00,0x04,0x02}, + {0x57,0xba1d,0x0103,0x3a42,0x0136,0x08,0x03,0x00,0x00,0x07,0x03}, + {0x58,0x9a1d,0x0204,0x3a49,0x0137,0x08,0x04,0x00,0x00,0x00,0x04}, + {0x59,0x9a1b,0x0000,0x3a34,0x0138,0x08,0x00,0x00,0x00,0x04,0x00}, + {0x5A,0x021b,0x0014,0x3b83,0x0138,0x08,0x01,0x00,0x00,0x04,0x3f}, /* ModeIdIndex = 0x20 */ + {0x5B,0x0a1d,0x0014,0x3b83,0x0135,0x08,0x01,0x00,0x00,0x04,0x3f}, + {0x5d,0x0a1d,0x0305,0x3a50,0x0139,0x08,0x05,0x00,0x00,0x07,0x05}, + {0x62,0x0a3f,0x0306,0x3a57,0x013a,0x08,0x06,0x00,0x00,0x05,0x06}, + {0x63,0x2a3f,0x0407,0x3a81,0x013b,0x08,0x07,0x00,0x00,0x07,0x0e}, + {0x64,0x0a7f,0x0508,0x3aab,0x013c,0x08,0x08,0x00,0x00,0x00,0x16}, + {0x65,0x0eff,0x0609,0x3adc,0x013d,0x08,0x09,0x00,0x00,0x00,0x1e}, + {0x66,0x0eff,0x070a,0x3af2,0x013e,0x08,0x0a,0x00,0x00,0x00,0x22}, /* mode 1600x1200 add CRT2MODE */ + {0x68,0x067b,0x080b,0x3b17,0x013f,0x08,0x0b,0x00,0x00,0x00,0x29}, + {0x69,0x06fd,0x080b,0x3b17,0x0140,0x08,0x0b,0x00,0x00,0x00,0x29}, + {0x6b,0x07ff,0x080b,0x3b17,0x0141,0x10,0x0b,0x00,0x00,0x00,0x29}, + {0x6c,0x067b,0x090c,0x3b37,0x0000,0x08,0x0c,0x00,0x00,0x00,0x2f}, + {0x6d,0x06fd,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f}, + {0x6e,0x07ff,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f}, + {0x70,0x2a1b,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34}, + {0x71,0x0a1b,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, + {0x74,0x0a1d,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, /* ModeIdIndex = 0x30 */ + {0x75,0x0a3d,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a}, + {0x76,0x2a1f,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34}, + {0x77,0x0a1f,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, + {0x78,0x0a3f,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a}, + {0x79,0x0a3b,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a}, + {0x7a,0x2a1d,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34}, + {0x7b,0x0e3b,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x1d}, + {0x7c,0x0e7d,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x1d}, + {0x7d,0x0eff,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x1d}, + {0x20,0x0e3b,0x0D16,0x49e0,0x0000,0x08,0x16,0x00,0x00,0x00,0x43}, + {0x21,0x0e7d,0x0D16,0x49e0,0x0000,0x08,0x16,0x00,0x00,0x00,0x43}, + {0x22,0x0eff,0x0D16,0x49e0,0x0000,0x08,0x16,0x00,0x00,0x00,0x43}, + {0x23,0x0e3b,0x0614,0x49d5,0x0000,0x08,0x14,0x00,0x00,0x00,0x41}, + {0x24,0x0e7d,0x0614,0x49d5,0x0000,0x08,0x14,0x00,0x00,0x00,0x41}, + {0x25,0x0eff,0x0614,0x49d5,0x0000,0x08,0x14,0x00,0x00,0x00,0x41}, + {0x26,0x063b,0x0c15,0x49dc,0x0000,0x08,0x15,0x00,0x00,0x00,0x42}, /* ModeIdIndex = 0x40 */ + {0x27,0x067d,0x0c15,0x49dc,0x0000,0x08,0x15,0x00,0x00,0x00,0x42}, + {0x28,0x06ff,0x0c15,0x49dc,0x0000,0x08,0x15,0x00,0x00,0x00,0x42}, + {0xff,0x0000,0x0000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00} +}; + +XGI_StandTableStruct XGI330_StandTable[]= +{ +/* MD_0_200 */ + { + 0x28,0x18,0x08,0x0800, + {0x09,0x03,0x00,0x02}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, + 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* MD_1_200 */ + { + 0x28,0x18,0x08,0x0800, + {0x09,0x03,0x00,0x02}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, + 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* MD_2_200 */ + { + 0x50,0x18,0x08,0x1000, + {0x01,0x03,0x00,0x02}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* MD_3_200 */ + { + 0x50,0x18,0x08,0x1000, + {0x01,0x03,0x00,0x02}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* MD_4 */ + { + 0x28,0x18,0x08,0x4000, + {0x09,0x03,0x00,0x02}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, + 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2, + 0xff}, + {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x01,0x00,0x03,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00, + 0xff} + }, +/* MD_5 */ + { + 0x28,0x18,0x08,0x4000, + {0x09,0x03,0x00,0x02}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, + 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2, + 0xff}, + {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x01,0x00,0x03,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00, + 0xff} + }, +/* MD_6 */ + { + 0x50,0x18,0x08,0x4000, + {0x01,0x01,0x00,0x06}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2, + 0xff}, + {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0x01,0x00,0x01,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00, + 0xff} + }, +/* MD_7 */ + { + 0x50,0x18,0x0e,0x1000, + {0x00,0x03,0x00,0x03}, + 0xa6, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, + 0x83,0x85,0x5d,0x28,0x0d,0x63,0xba,0xa3, + 0xff}, + {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08, + 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x0e,0x00,0x0f,0x08}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00, + 0xff} + }, +/* MDA_DAC */ + { + 0x00,0x00,0x00,0x0000, + {0x00,0x00,0x00,0x15}, + 0x15, + {0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x15,0x15,0x15,0x15,0x15,0x15,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0x00, + 0x00}, + {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x15, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x15,0x15,0x15,0x15}, + {0x15,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f} + }, +/* CGA_DAC */ + { + 0x00,0x10,0x04,0x0114, + {0x11,0x09,0x15,0x00}, + 0x10, + {0x04,0x14,0x01,0x11,0x09,0x15,0x2a,0x3a, + 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x2a,0x3a, + 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x10, + 0x04}, + {0x14,0x01,0x11,0x09,0x15,0x00,0x10,0x04, + 0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,0x2e, + 0x3e,0x2b,0x3b,0x2f}, + {0x3f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f, + 0x3f} + }, +/* EGA_DAC */ + { + 0x00,0x10,0x04,0x0114, + {0x11,0x05,0x15,0x20}, + 0x30, + {0x24,0x34,0x21,0x31,0x25,0x35,0x08,0x18, + 0x0c,0x1c,0x09,0x19,0x0d,0x1d,0x28,0x38, + 0x2c,0x3c,0x29,0x39,0x2d,0x3d,0x02,0x12, + 0x06}, + {0x16,0x03,0x13,0x07,0x17,0x22,0x32,0x26, + 0x36,0x23,0x33,0x27,0x37,0x0a,0x1a,0x0e, + 0x1e,0x0b,0x1b,0x0f}, + {0x1f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f, + 0x3f} + }, +/* VGA_DAC */ + { + 0x00,0x10,0x04,0x0114, + {0x11,0x09,0x15,0x2a}, + 0x3a, + {0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x05, + 0x08,0x0b,0x0e,0x11,0x14,0x18,0x1c,0x20, + 0x24,0x28,0x2d,0x32,0x38,0x3f,0x00,0x10, + 0x1f}, + {0x2f,0x3f,0x1f,0x27,0x2f,0x37,0x3f,0x2d, + 0x31,0x36,0x3a,0x3f,0x00,0x07,0x0e,0x15, + 0x1c,0x0e,0x11,0x15}, + {0x18,0x1c,0x14,0x16,0x18,0x1a,0x1c,0x00, + 0x04} + }, + { + 0x08,0x0c,0x10,0x0a08, + {0x0c,0x0e,0x10,0x0b}, + 0x0c, + {0x0d,0x0f,0x10,0x10,0x01,0x08,0x00,0x00, + 0x00,0x00,0x01,0x00,0x02,0x02,0x01,0x00, + 0x04,0x04,0x01,0x00,0x05,0x02,0x05,0x00, + 0x06}, + {0x01,0x06,0x05,0x06,0x00,0x08,0x01,0x08, + 0x00,0x07,0x02,0x07,0x06,0x07,0x00,0x00, + 0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00} + }, +/* MD_D */ + { + 0x28,0x18,0x08,0x2000, + {0x09,0x0f,0x00,0x06}, + 0x63, + {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, + 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x01,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, + 0xff} + }, +/* MD_E */ + { + 0x50,0x18,0x08,0x4000, + {0x01,0x0f,0x00,0x06}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x01,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, + 0xff} + }, +/* ExtVGATable */ + { + 0x00,0x00,0x00,0x0000, + {0x01,0x0f,0x00,0x0e}, + 0x23, + {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x01,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, + 0xff} + }, +/* ROM_SAVEPTR */ + { + 0x9f,0x3b,0x00,0x00c0, + {0x00,0x00,0x00,0x00}, + 0x00, + {0x00,0x00,0x00,0x00,0x00,0x00,0xbb,0x3f, + 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1a,0x00,0xac,0x3e,0x00,0xc0, + 0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00} + }, +/* MD_F */ + { + 0x50,0x18,0x0e,0x8000, + {0x01,0x0f,0x00,0x06}, + 0xa2, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3, + 0xff}, + {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00, + 0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00, + 0x0b,0x00,0x05,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05, + 0xff} + }, +/* MD_10 */ + { + 0x50,0x18,0x0e,0x8000, + {0x01,0x0f,0x00,0x06}, + 0xa3, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x01,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, + 0xff} + }, +/* MD_0_350 */ + { + 0x28,0x18,0x0e,0x0800, + {0x09,0x03,0x00,0x02}, + 0xa3, + {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f, + 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, + 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* MD_1_350 */ + { + 0x28,0x18,0x0e,0x0800, + {0x09,0x03,0x00,0x02}, + 0xa3, + {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f, + 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, + 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* MD_2_350 */ + { + 0x50,0x18,0x0e,0x1000, + {0x01,0x03,0x00,0x02}, + 0xa3, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, + 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* MD_3_350 */ + { + 0x50,0x18,0x0e,0x1000, + {0x01,0x03,0x00,0x02}, + 0xa3, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00, + 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x08,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* MD_0_1_400 */ + { + 0x28,0x18,0x10,0x0800, + {0x08,0x03,0x00,0x02}, + 0x67, + {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f, + 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x0c,0x00,0x0f,0x08}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* MD_2_3_400 */ + { + 0x50,0x18,0x10,0x1000, + {0x00,0x03,0x00,0x02}, + 0x67, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x0c,0x00,0x0f,0x08}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, + 0xff} + }, +/* MD_7_400 */ + { + 0x50,0x18,0x10,0x1000, + {0x00,0x03,0x00,0x02}, + 0x66, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08, + 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x0e,0x00,0x0f,0x08}, + {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00, + 0xff} + }, +/* MD_11 */ + { + 0x50,0x1d,0x10,0xa000, + {0x01,0x0f,0x00,0x06}, + 0xe3, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xc3, + 0xff}, + {0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x01,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01, + 0xff} + }, +/* ExtEGATable */ + { + 0x50,0x1d,0x10,0xa000, + {0x01,0x0f,0x00,0x06}, + 0xe3, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07, + 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x01,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f, + 0xff} + }, +/* MD_13 */ + { + 0x28,0x18,0x08,0x2000, + {0x01,0x0f,0x00,0x0e}, + 0x63, + {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, + 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3, + 0xff}, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x41,0x00,0x0f,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, + 0xff} + } +}; + +XGI_TimingHStruct XGI_TimingH[]= +{{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}}; + +XGI_TimingVStruct XGI_TimingV[]= +{{{0x00,0x00,0x00,0x00,0x00,0x00,0x00}}}; + +XGI_XG21CRT1Struct XGI_UpdateCRT1Table[]= +{ + {0x01,0x27,0x91,0x8f,0xc0}, /* 00 */ + {0x03,0x4f,0x83,0x8f,0xc0}, /* 01 */ + {0x05,0x27,0x91,0x8f,0xc0}, /* 02 */ + {0x06,0x4f,0x83,0x8f,0xc0}, /* 03 */ + {0x07,0x4f,0x83,0x8f,0xc0}, /* 04 */ + {0x0d,0x27,0x91,0x8f,0xc0}, /* 05 */ + {0x0e,0x4f,0x83,0x8f,0xc0}, /* 06 */ + {0x0f,0x4f,0x83,0x5d,0xc0}, /* 07 */ + {0x10,0x4f,0x83,0x5d,0xc0}, /* 08 */ + {0x11,0x4f,0x83,0xdf,0x0c}, /* 09 */ + {0x12,0x4f,0x83,0xdf,0x0c}, /* 10 */ + {0x13,0x4f,0x83,0x8f,0xc0}, /* 11 */ + {0x2e,0x4f,0x83,0xdf,0x0c}, /* 12 */ + {0x2e,0x4f,0x87,0xdf,0xc0}, /* 13 */ + {0x2f,0x4f,0x83,0x8f,0xc0}, /* 14 */ + {0x50,0x27,0x91,0xdf,0x0c}, /* 15 */ + {0x59,0x27,0x91,0x8f,0xc0} /* 16 */ +}; + +XGI_CRT1TableStruct XGI_CRT1Table[]= +{ + {{0x2d,0x28,0x90,0x2c,0x90,0x00,0x04,0x00, + 0xbf,0x1f,0x9c,0x8e,0x96,0xb9,0x30}}, /* 0x0 */ + {{0x2d,0x28,0x90,0x2c,0x90,0x00,0x04,0x00, + 0x0b,0x3e,0xe9,0x8b,0xe7,0x04,0x00}}, /* 0x1 */ + {{0x3D,0x31,0x81,0x37,0x1F,0x00,0x05,0x00, + 0x72,0xF0,0x58,0x8C,0x57,0x73,0xA0}}, /* 0x2 */ + {{0x4F,0x3F,0x93,0x45,0x0D,0x00,0x01,0x00, + 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90}}, /* 0x3 */ + {{0x5F,0x50,0x82,0x55,0x81,0x00,0x05,0x00, + 0xBF,0x1F,0x9C,0x8E,0x96,0xB9,0x30}}, /* 0x4 */ + {{0x5F,0x50,0x82,0x55,0x81,0x00,0x05,0x00, + 0x0B,0x3E,0xE9,0x8B,0xE7,0x04,0x00}}, /* 0x5 */ + {{0x63,0x50,0x86,0x56,0x9B,0x00,0x01,0x00, + 0x06,0x3E,0xE8,0x8B,0xE7,0xFF,0x10}}, /* 0x6 */ + {{0x64,0x4F,0x88,0x55,0x9D,0x00,0x01,0x00, + 0xF2,0x1F,0xE0,0x83,0xDF,0xF3,0x10}}, /* 0x7 */ + {{0x63,0x4F,0x87,0x5A,0x81,0x00,0x05,0x00, + 0xFB,0x1F,0xE0,0x83,0xDF,0xFC,0x10}}, /* 0x8 */ + {{0x65,0x4F,0x89,0x58,0x80,0x00,0x05,0x60, + 0xFB,0x1F,0xE0,0x83,0xDF,0xFC,0x80}}, /* 0x9 */ + {{0x65,0x4F,0x89,0x58,0x80,0x00,0x05,0x60, + 0x01,0x3E,0xE0,0x83,0xDF,0x02,0x80}}, /* 0xa */ + {{0x67,0x4F,0x8B,0x58,0x81,0x00,0x05,0x60, + 0x0D,0x3E,0xE0,0x83,0xDF,0x0E,0x90}}, /* 0xb */ + {{0x65,0x4F,0x89,0x57,0x9F,0x00,0x01,0x00, + 0xFB,0x1F,0xE6,0x8A,0xDF,0xFC,0x10}}, /* 0xc */ + {{0x7B,0x63,0x9F,0x6A,0x93,0x00,0x05,0x00, /* ; 0D (800x600,56Hz) */ + 0x6F,0xF0,0x58,0x8A,0x57,0x70,0xA0}}, /* ; (VCLK 36.0MHz) */ + {{0x7F,0x63,0x83,0x6C,0x1C,0x00,0x06,0x00, /* ; 0E (800x600,60Hz) */ + 0x72,0xF0,0x58,0x8C,0x57,0x73,0xA0}}, /* ; (VCLK 40.0MHz) */ + {{0x7D,0x63,0x81,0x6E,0x1D,0x00,0x06,0x00, /* ; 0F (800x600,72Hz) */ + 0x98,0xF0,0x7C,0x82,0x57,0x99,0x80}}, /* ; (VCLK 50.0MHz) */ + {{0x7F,0x63,0x83,0x69,0x13,0x00,0x06,0x00, /* ; 10 (800x600,75Hz) */ + 0x6F,0xF0,0x58,0x8B,0x57,0x70,0xA0}}, /* ; (VCLK 49.5MHz) */ + {{0x7E,0x63,0x82,0x6B,0x13,0x00,0x06,0x00, /* ; 11 (800x600,85Hz) */ + 0x75,0xF0,0x58,0x8B,0x57,0x76,0xA0}}, /* ; (VCLK 56.25MHz) */ + {{0x81,0x63,0x85,0x6D,0x18,0x00,0x06,0x60, /* ; 12 (800x600,100Hz) */ + 0x7A,0xF0,0x58,0x8B,0x57,0x7B,0xA0}}, /* ; (VCLK 75.8MHz) */ + {{0x83,0x63,0x87,0x6E,0x19,0x00,0x06,0x60, /* ; 13 (800x600,120Hz) */ + 0x81,0xF0,0x58,0x8B,0x57,0x82,0xA0}}, /* ; (VCLK 79.411MHz) */ + {{0x85,0x63,0x89,0x6F,0x1A,0x00,0x06,0x60, /* ; 14 (800x600,160Hz) */ + 0x91,0xF0,0x58,0x8B,0x57,0x92,0xA0}}, /* ; (VCLK 105.822MHz) */ + {{0x99,0x7F,0x9D,0x84,0x1A,0x00,0x02,0x00, + 0x96,0x1F,0x7F,0x83,0x7F,0x97,0x10}}, /* 0x15 */ + {{0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00, + 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90}}, /* 0x16 */ + {{0xA1,0x7F,0x85,0x86,0x97,0x00,0x02,0x00, + 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90}}, /* 0x17 */ + {{0x9F,0x7F,0x83,0x85,0x91,0x00,0x02,0x00, + 0x1E,0xF5,0x00,0x83,0xFF,0x1F,0x90}}, /* 0x18 */ + {{0xA7,0x7F,0x8B,0x89,0x95,0x00,0x02,0x00, + 0x26,0xF5,0x00,0x83,0xFF,0x27,0x90}}, /* 0x19 */ + {{0xA9,0x7F,0x8D,0x8C,0x9A,0x00,0x02,0x62, + 0x2C,0xF5,0x00,0x83,0xFF,0x2D,0x14}}, /* 0x1a */ + {{0xAB,0x7F,0x8F,0x8D,0x9B,0x00,0x02,0x62, + 0x35,0xF5,0x00,0x83,0xFF,0x36,0x14}}, /* 0x1b */ + {{0xCF,0x9F,0x93,0xB2,0x01,0x00,0x03,0x00, + 0x14,0xBA,0x00,0x83,0xFF,0x15,0x00}}, /* 0x1c */ + {{0xCE,0x9F,0x92,0xA9,0x17,0x00,0x07,0x00, + 0x28,0x5A,0x00,0x83,0xFF,0x29,0x89}}, /* 0x1d */ + {{0xCE,0x9F,0x92,0xA5,0x17,0x00,0x07,0x00, + 0x28,0x5A,0x00,0x83,0xFF,0x29,0x89}}, /* 0x1e */ + {{0xD3,0x9F,0x97,0xAB,0x1F,0x00,0x07,0x00, + 0x2E,0x5A,0x00,0x83,0xFF,0x2F,0x89}}, /* 0x1f */ + {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00, + 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x20 */ + {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00, + 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x21 */ + {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00, + 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x22 */ + {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00, + 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x23 */ + {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00, + 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x24 */ + {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00, + 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x25 */ + {{0x09,0xC7,0x8D,0xD3,0x0B,0x01,0x04,0x00, + 0xE0,0x10,0xB0,0x83,0xAF,0xE1,0x2F}}, /* 0x26 */ + {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00, + 0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x27 */ + {{0x43,0xEF,0x87,0x06,0x00,0x41,0x05,0x62, + 0xD4,0x1F,0xA0,0x83,0x9F,0xD5,0x9F}}, /* 0x28 */ + {{0x45,0xEF,0x89,0x07,0x01,0x41,0x05,0x62, + 0xD9,0x1F,0xA0,0x83,0x9F,0xDA,0x9F}}, /* 0x29 */ + {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00, + 0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x2a */ + {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00, + 0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x2b */ + {{0x40,0xEF,0x84,0x03,0x1D,0x41,0x01,0x00, + 0xDA,0x1F,0xA0,0x83,0x9F,0xDB,0x1F}}, /* 0x2c */ + {{0x59,0xFF,0x9D,0x17,0x13,0x41,0x05,0x44, + 0x33,0xBA,0x00,0x83,0xFF,0x34,0x0F}}, /* 0x2d */ + {{0x5B,0xFF,0x9F,0x18,0x14,0x41,0x05,0x44, + 0x38,0xBA,0x00,0x83,0xFF,0x39,0x0F}}, /* 0x2e */ + {{0x5B,0xFF,0x9F,0x18,0x14,0x41,0x05,0x44, + 0x3D,0xBA,0x00,0x83,0xFF,0x3E,0x0F}}, /* 0x2f */ + {{0x5D,0xFF,0x81,0x19,0x95,0x41,0x05,0x44, + 0x41,0xBA,0x00,0x84,0xFF,0x42,0x0F}}, /* 0x30 */ + {{0x55,0xFF,0x99,0x0D,0x0C,0x41,0x05,0x00, + 0x3E,0xBA,0x00,0x84,0xFF,0x3F,0x0F}}, /* 0x31 */ + {{0x7F,0x63,0x83,0x6C,0x1C,0x00,0x06,0x00, + 0x72,0xBA,0x27,0x8B,0xDF,0x73,0x80}}, /* 0x32 */ + {{0x7F,0x63,0x83,0x69,0x13,0x00,0x06,0x00, + 0x6F,0xBA,0x26,0x89,0xDF,0x6F,0x80}}, /* 0x33 */ + {{0x7F,0x63,0x82,0x6B,0x13,0x00,0x06,0x00, + 0x75,0xBA,0x29,0x8C,0xDF,0x75,0x80}}, /* 0x34 */ + {{0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00, + 0x24,0xF1,0xAF,0x85,0x3F,0x25,0xB0}}, /* 0x35 */ + {{0x9F,0x7F,0x83,0x85,0x91,0x00,0x02,0x00, + 0x1E,0xF1,0xAD,0x81,0x3F,0x1F,0xB0}}, /* 0x36 */ + {{0xA7,0x7F,0x88,0x89,0x15,0x00,0x02,0x00, + 0x26,0xF1,0xB1,0x85,0x3F,0x27,0xB0}}, /* 0x37 */ + {{0xCE,0x9F,0x92,0xA9,0x17,0x00,0x07,0x00, + 0x28,0xC4,0x7A,0x8E,0xCF,0x29,0xA1}}, /* 0x38 */ + {{0xCE,0x9F,0x92,0xA5,0x17,0x00,0x07,0x00, + 0x28,0xD4,0x7A,0x8E,0xCF,0x29,0xA1}}, /* 0x39 */ + {{0xD3,0x9F,0x97,0xAB,0x1F,0x00,0x07,0x00, + 0x2E,0xD4,0x7D,0x81,0xCF,0x2F,0xA1}}, /* 0x3a */ + {{0xDC,0x9F,0x00,0xAB,0x19,0x00,0x07,0x00, + 0xE6,0xEF,0xC0,0xC3,0xBF,0xE7,0x90}}, /* 0x3b */ + {{0x6B,0x59,0x8F,0x5E,0x8C,0x00,0x05,0x00, + 0x0B,0x3E,0xE9,0x8B,0xE7,0x04,0x00}}, /* 0x3c */ + {{0x7B,0x63,0x9F,0x6A,0x93,0x00,0x05,0x00, + 0x6F,0xF0,0x58,0x8A,0x57,0x70,0xA0}}, /* 0x3d */ + {{0x86,0x6A,0x8a,0x74,0x06,0x00,0x02,0x00, + 0x8c,0x15,0x4f,0x83,0xef,0x8d,0x30}}, /* 0x3e */ + {{0x81,0x6A,0x85,0x70,0x00,0x00,0x02,0x00, + 0x0f,0x3e,0xeb,0x8e,0xdf,0x10,0x00}}, /* 0x3f */ + {{0xCE,0x9F,0x92,0xA9,0x17,0x00,0x07,0x00, + 0x20,0xF5,0x03,0x88,0xFF,0x21,0x90}}, /* 0x40 */ + {{0xE6,0xAE,0x8A,0xBD,0x90,0x00,0x03,0x00, + 0x3D,0x10,0x1A,0x8D,0x19,0x3E,0x2F}}, /* 0x41 */ + {{0xB9,0x8F,0x9D,0x9B,0x8A,0x00,0x06,0x00, + 0x7D,0xFF,0x60,0x83,0x5F,0x7E,0x90}}, /* 0x42 */ + {{0xC3,0x8F,0x87,0x9B,0x0B,0x00,0x07,0x00, + 0x82,0xFF,0x60,0x83,0x5F,0x83,0x90}}, /* 0x43 */ + {{0xAD,0x7F,0x91,0x8E,0x9C,0x00,0x02,0x82, + 0x49,0xF5,0x00,0x83,0xFF,0x4A,0x90}}, /* 0x44 */ + {{0xCD,0x9F,0x91,0xA7,0x19,0x00,0x07,0x60, + 0xE6,0xFF,0xC0,0x83,0xBF,0xE7,0x90}}, /* 0x45 */ + {{0xD3,0x9F,0x97,0xAB,0x1F,0x00,0x07,0x60, + 0xF1,0xFF,0xC0,0x83,0xBF,0xF2,0x90}}, /* 0x46 */ + {{0xD7,0x9F,0x9B,0xAC,0x1E,0x00,0x07,0x00, + 0x03,0xDE,0xC0,0x84,0xBF,0x04,0x90}} /* 0x47 */ +}; + +XGI330_CHTVRegDataStruct XGI_CHTVRegUNTSC[] = { + /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */ + {{ 0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 00 (640x200,640x400) */ + {{ 0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 01 (640x350) */ + {{ 0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 02 (720x400) */ + {{ 0x4A,0x77,0xBB,0x94,0x84,0x48,0xFE,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 03 (720x350) */ + {{ 0x6A,0x77,0xBB,0x6E,0x84,0x2E,0x02,0x5A,0x04,0x00,0x80,0x20,0x7E,0x80,0x97,0x00 }},/* 04 (640x480) ;;5/6/02 */ + {{ 0xCF,0x77,0xB7,0xC8,0x84,0x3B,0x02,0x5A,0x04,0x00,0x80,0x19,0x88,0xAE,0xA3,0x00 }},/* 05 (800x600) ;;1/12/02 */ + {{ 0xEE,0x77,0xBB,0x66,0x87,0x32,0x01,0x5A,0x04,0x00,0x80,0x1B,0xD4,0x2F,0x6F,0x00 }}/* 06 (1024x768) ;;5/6/02 */ + }; + +XGI330_CHTVRegDataStruct XGI_CHTVRegONTSC[]= { + /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */ + {{ 0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 00 (640x200,640x400) */ + {{ 0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 01 (640x350) */ + {{ 0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 02 (720x400) */ + {{ 0x49,0x77,0xBB,0x7B,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 03 (720x350) */ + {{ 0x69,0x77,0xBB,0x6E,0x84,0x1E,0x00,0x5A,0x04,0x00,0x80,0x25,0x1A,0x80,0x26,0x00 }},/* 04 (640x480) ;;5/6/02 */ + {{ 0xCE,0x77,0xB7,0xB6,0x83,0x2C,0x02,0x5A,0x04,0x00,0x80,0x1C,0x00,0x82,0x97,0x00 }},/* 05 (800x600) ;;5/6/02 */ + {{ 0xED,0x77,0xBB,0x66,0x8C,0x21,0x02,0x5A,0x04,0x00,0x80,0x1F,0xA0,0x7E,0x73,0x00 }}/* 06 (1024x768) ;;5/6/02 */ + }; + +XGI330_CHTVRegDataStruct XGI_CHTVRegUPAL[]= { + /* Index:000h,001h,002h,004h,003h,005h,006h,007h,008h,015h,01Fh,00Ch,00Dh,00Eh,00Fh,010h */ + {{ 0x41,0x7F,0xB7,0x34,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* ; 00 (640x200,640x400) */ + {{ 0x41,0x7F,0xB7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* ; 01 (640x350) */ + {{ 0x41,0x7F,0xB7,0x34,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* ; 02 (720x400) */ + {{ 0x41,0x7F,0xB7,0x12,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* ; 03 (720x350) */ + {{ 0x61,0x7F,0xB7,0x99,0x84,0x35,0x04,0x5A,0x05,0x00,0x80,0x26,0x2A,0x55,0x5D,0x00 }},/* ; 04 (640x480) */ + {{ 0xC3,0x7F,0xB7,0x7A,0x84,0x40,0x02,0x5A,0x05,0x00,0x80,0x1F,0x84,0x3D,0x28,0x00 }},/* ; 05 (800x600) ;;1/12/02 */ + {{ 0xE5,0x7F,0xB7,0x1D,0xA7,0x3E,0x04,0x5A,0x05,0x00,0x80,0x20,0x3E,0xE4,0x22,0x00 }}/* ; 06 (1024x768) ;;1/12/02 */ + }; + +XGI330_CHTVRegDataStruct XGI_CHTVRegOPAL[]={ + /* Index:000,0x01,0x02,0x04,0x03,0x05,0x06,0x07,0x08,0x15,0x1F,0x0C,0x0D,0x0E,0x0F,0x10h */ + {{ 0x41,0x7F,0xB7,0x36,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 00 (640x200,640x400) */ + {{ 0x41,0x7F,0xB7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 01 (640x350) */ + {{ 0x41,0x7F,0xB7,0x36,0xAD,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 02 (720x400) */ + {{ 0x41,0x7F,0xB7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01 }},/* 03 (720x350) */ + {{ 0x61,0x7F,0xB7,0x99,0x84,0x35,0x04,0x5A,0x05,0x00,0x80,0x26,0x2A,0x55,0x5D,0x00 }},/* 04 (640x480) */ + {{ 0xC1,0x7F,0xB7,0x4D,0x8C,0x1E,0x31,0x5A,0x05,0x00,0x80,0x26,0x78,0x19,0x34,0x00 }},/* 05 (800x600) ;;1/12/02 */ + {{ 0xE4,0x7F,0xB7,0x1E,0xAF,0x29,0x37,0x5A,0x05,0x00,0x80,0x25,0x8C,0xB2,0x2A,0x00 }}/* 06 (1024x768) ;;1/12/02 */ + }; + +UCHAR XGI_CH7017LV1024x768[]={0x60,0x02,0x00,0x07,0x40,0xED,0xA3, + 0xC8,0xC7,0xAC,0xE0,0x02}; +UCHAR XGI_CH7017LV1400x1050[]={0x60,0x03,0x11,0x00,0x40,0xE3,0xAD, + 0xDB,0xF6,0xAC,0xE0,0x02}; + + +/*add for new UNIVGABIOS*/ +XGI330_LCDDataStruct XGI_StLCD1024x768Data[]= +{ + { 62, 25, 800, 546,1344, 806}, + { 32, 15, 930, 546,1344, 806}, + { 62, 25, 800, 546,1344, 806}, /* chiawen for dot9 -> dot8 */ + { 104, 45, 945, 496,1344, 806}, + { 62, 25, 800, 546,1344, 806}, + { 31, 18,1008, 624,1344, 806}, + { 1, 1,1344, 806,1344, 806} +}; + +XGI330_LCDDataStruct XGI_ExtLCD1024x768Data[]= +{ + { 42, 25,1536, 419,1344, 806}, /* { 12, 5, 896, 512,1344, 806}, // alan 09/12/2003 */ + { 48, 25,1536, 369,1344, 806}, /* { 12, 5, 896, 510,1344, 806}, // alan 09/12/2003 */ + { 42, 25,1536, 419,1344, 806}, /* { 32, 15,1008, 505,1344, 806}, // alan 09/12/2003 */ + { 48, 25,1536, 369,1344, 806}, /* { 32, 15,1008, 514,1344, 806}, // alan 09/12/2003 */ + { 12, 5, 896, 500,1344, 806}, + { 42, 25,1024, 625,1344, 806}, + { 1, 1,1344, 806,1344, 806}, + { 12, 5, 896, 500,1344, 806}, + { 42, 25,1024, 625,1344, 806}, + { 1, 1,1344, 806,1344, 806}, + { 12, 5, 896, 500,1344, 806}, + { 42, 25,1024, 625,1344, 806}, + { 1, 1,1344, 806,1344, 806} +}; + +/*XGI330_LCDDataStruct XGI_St2LCD1024x768Data[]= +{ + { 62, 25, 800, 546,1344, 806}, + { 32, 15, 930, 546,1344, 806}, + { 62, 25, 800, 546,1344, 806}, + { 104, 45, 945, 496,1344, 806}, + { 62, 25, 800, 546,1344, 806}, + { 31, 18,1008, 624,1344, 806}, + { 1, 1,1344, 806,1344, 806} +};*/ + +XGI330_LCDDataStruct XGI_CetLCD1024x768Data[]= +{ + { 1,1,1344,806,1344,806 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + { 1,1,1344,806,1344,806 }, /* 01 (320x350,640x350) */ + { 1,1,1344,806,1344,806 }, /* 02 (360x400,720x400) */ + { 1,1,1344,806,1344,806 }, /* 03 (720x350) */ + { 1,1,1344,806,1344,806 }, /* 04 (640x480x60Hz) */ + { 1,1,1344,806,1344,806 }, /* 05 (800x600x60Hz) */ + { 1,1,1344,806,1344,806 } /* 06 (1024x768x60Hz) */ +}; + +XGI330_LCDDataStruct XGI_StLCD1280x1024Data[]= +{ + { 22, 5, 800, 510,1650,1088}, + { 22, 5, 800, 510,1650,1088}, + { 176, 45, 900, 510,1650,1088}, + { 176, 45, 900, 510,1650,1088}, + { 22, 5, 800, 510,1650,1088}, + { 13, 5,1024, 675,1560,1152}, + { 16, 9,1266, 804,1688,1072}, + { 1, 1,1688,1066,1688,1066} +}; + +XGI330_LCDDataStruct XGI_ExtLCD1280x1024Data[]= +{ + { 211, 60,1024, 501,1688,1066}, + { 211, 60,1024, 508,1688,1066}, + { 211, 60,1024, 501,1688,1066}, + { 211, 60,1024, 508,1688,1066}, + { 211, 60,1024, 500,1688,1066}, + { 211, 75,1024, 625,1688,1066}, + { 211, 120,1280, 798,1688,1066}, + { 1, 1,1688,1066,1688,1066} +}; + +XGI330_LCDDataStruct XGI_St2LCD1280x1024Data[]= +{ + { 22, 5, 800, 510,1650,1088}, + { 22, 5, 800, 510,1650,1088}, + { 176, 45, 900, 510,1650,1088}, + { 176, 45, 900, 510,1650,1088}, + { 22, 5, 800, 510,1650,1088}, + { 13, 5,1024, 675,1560,1152}, + { 16, 9,1266, 804,1688,1072}, + { 1, 1,1688,1066,1688,1066} +}; + +XGI330_LCDDataStruct XGI_CetLCD1280x1024Data[]= +{ + { 1,1,1688,1066,1688,1066 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 1,1,1688,1066,1688,1066 }, /* 01 (320x350,640x350) */ + { 1,1,1688,1066,1688,1066 }, /* 02 (360x400,720x400) */ + { 1,1,1688,1066,1688,1066 }, /* 03 (720x350) */ + { 1,1,1688,1066,1688,1066 }, /* 04 (640x480x60Hz) */ + { 1,1,1688,1066,1688,1066 }, /* 05 (800x600x60Hz) */ + { 1,1,1688,1066,1688,1066 }, /* 06 (1024x768x60Hz) */ + { 1,1,1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz) */ + { 1,1,1688,1066,1688,1066 } /* 08 (1400x1050x60Hz) */ +}; + +XGI330_LCDDataStruct XGI_StLCD1400x1050Data[]= +{ + { 211,100,2100,408,1688,1066 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 211,64,1536,358,1688,1066 }, /* 01 (320x350,640x350) */ + { 211,100,2100,408,1688,1066 }, /* 02 (360x400,720x400) */ + { 211,64,1536,358,1688,1066 }, /* 03 (720x350) */ + { 211,48,840,488,1688,1066 }, /* 04 (640x480x60Hz) */ + { 211,72,1008,609,1688,1066 }, /* 05 (800x600x60Hz) */ + { 211,128,1400,776,1688,1066 }, /* 06 (1024x768x60Hz) */ + { 1,1,1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz w/o Scaling) */ + { 1,1,1688,1066,1688,1066 } /* 08 (1400x1050x60Hz) */ +}; + +XGI330_LCDDataStruct XGI_ExtLCD1400x1050Data[]= +{ + { 211,100,2100,408,1688,1066 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 211,64,1536,358,1688,1066 }, /* 01 (320x350,640x350) */ + { 211,100,2100,408,1688,1066 }, /* 02 (360x400,720x400) */ + { 211,64,1536,358,1688,1066 }, /* 03 (720x350) */ + { 211,48,840,488,1688,1066 }, /* 04 (640x480x60Hz) */ + { 211,72,1008,609,1688,1066 }, /* 05 (800x600x60Hz) */ + { 211,128,1400,776,1688,1066 }, /* 06 (1024x768x60Hz) */ + { 1,1,1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz w/o Scaling) */ + { 1,1,1688,1066,1688,1066 } /* 08 (1400x1050x60Hz) */ +}; + +XGI330_LCDDataStruct XGI_ExtLCD1600x1200Data[]= +{ + { 4,1,1620,420,2160,1250 }, /* { 3,1,2160,425,2160,1250 }, // 00 (320x200,320x400,640x200,640x400) // alan 10/14/2003 */ + { 27,7,1920,375,2160,1250 }, /* 01 (320x350,640x350) */ + { 4,1,1620,420,2160,1250 }, /* { 3,1,2160,425,2160,1250 }, // 02 (360x400,720x400) // alan 10/14/2003 */ + { 27,7,1920,375,2160,1250 }, /* 03 (720x350) */ + { 27,4,800,500,2160,1250 }, /* 04 (640x480x60Hz) */ + { 4,1,1080,625,2160,1250 }, /* 05 (800x600x60Hz) */ + { 5,2,1350,800,2160,1250 }, /* 06 (1024x768x60Hz) */ + { 27,16,1500,1064,2160,1250 }, /* 07 (1280x1024x60Hz) */ + { 9,7,1920,1106,2160,1250 }, /* 08 (1400x1050x60Hz) */ + { 1,1,2160,1250,2160,1250 } /* 09 (1600x1200x60Hz) ;302lv */ +}; + +XGI330_LCDDataStruct XGI_StLCD1600x1200Data[]= +{ + { 27,4,800,500,2160,1250 },/* 00 (320x200,320x400,640x200,640x400) */ + { 27,4,800,500,2160,1250 },/* 01 (320x350,640x350) */ + { 27,4,800,500,2160,1250 },/* 02 (360x400,720x400) */ + { 27,4,800,500,2160,1250 },/* 03 (720x350) */ + { 27,4,800,500,2160,1250 },/* 04 (320x240,640x480) */ + { 4,1,1080,625,2160,1250 },/* 05 (400x300,800x600) */ + { 5,2,1350,800,2160,1250 },/* 06 (512x384,1024x768) */ + { 135,88,1600,1100,2160,1250 },/* 07 (1280x1024) */ + { 1,1,1800,1500,2160,1250 },/* 08 (1400x1050) */ + { 1,1,2160,1250,2160,1250 } /* 09 (1600x1200) */ +}; + +XGI330_LCDDataStruct XGI_CetLCD1400x1050Data[]= +{ + { 1,1,1688,1066,1688,1066 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 1,1,1688,1066,1688,1066 }, /* 01 (320x350,640x350) */ + { 1,1,1688,1066,1688,1066 }, /* 02 (360x400,720x400) */ + { 1,1,1688,1066,1688,1066 }, /* 03 (720x350) */ + { 1,1,1688,1066,1688,1066 }, /* 04 (640x480x60Hz) */ + { 1,1,1688,1066,1688,1066 }, /* 05 (800x600x60Hz) */ + { 1,1,1688,1066,1688,1066 }, /* 06 (1024x768x60Hz) */ + { 1,1,1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz) */ + { 1,1,1688,1066,1688,1066 } /* 08 (1400x1050x60Hz) */ +}; + +XGI330_LCDDataStruct XGI_NoScalingData[]= +{ + { 1, 1, 800, 449, 800, 449}, + { 1, 1, 800, 449, 800, 449}, + { 1, 1, 900, 449, 900, 449}, + { 1, 1, 900, 449, 900, 449}, + { 1, 1, 800, 525, 800, 525}, + { 1, 1,1056, 628,1056, 628}, + { 1, 1,1344, 806,1344, 806}, + { 1, 1,1688,1066,1688,1066} +}; + +XGI330_LCDDataStruct XGI_ExtLCD1024x768x75Data[]= +{ + {42,25,1536,419,1344,806 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + {48,25,1536,369,1344,806 }, /* ; 01 (320x350,640x350) */ + {42,25,1536,419,1344,806 }, /* ; 02 (360x400,720x400) */ + {48,25,1536,369,1344,806 }, /* ; 03 (720x350) */ + {8,5,1312,500,1312,800 }, /* ; 04 (640x480x75Hz) */ + {41,25,1024,625,1312,800 }, /* ; 05 (800x600x75Hz) */ + {1,1,1312,800,1312,800 } /* ; 06 (1024x768x75Hz) */ +}; + +XGI330_LCDDataStruct XGI_StLCD1024x768x75Data[]= +{ + {42,25,1536,419,1344,806 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + {48,25,1536,369,1344,806 }, /* ; 01 (320x350,640x350) */ + {42,25,1536,419,1344,806 }, /* ; 02 (360x400,720x400) */ + {48,25,1536,369,1344,806 }, /* ; 03 (720x350) */ + {8,5,1312,500,1312,800 }, /* ; 04 (640x480x75Hz) */ + {41,25,1024,625,1312,800 }, /* ; 05 (800x600x75Hz) */ + {1,1,1312,800,1312,800 } /* ; 06 (1024x768x75Hz) */ +}; + +XGI330_LCDDataStruct XGI_CetLCD1024x768x75Data[]= +{ + {1,1,1312,800,1312,800}, /* ; 00 (320x200,320x400,640x200,640x400) */ + {1,1,1312,800,1312,800}, /* ; 01 (320x350,640x350) */ + {1,1,1312,800,1312,800}, /* ; 02 (360x400,720x400) */ + {1,1,1312,800,1312,800}, /* ; 03 (720x350) */ + {1,1,1312,800,1312,800}, /* ; 04 (640x480x75Hz) */ + {1,1,1312,800,1312,800}, /* ; 05 (800x600x75Hz) */ + {1,1,1312,800,1312,800} /* ; 06 (1024x768x75Hz) */ +}; + +XGI330_LCDDataStruct XGI_ExtLCD1280x1024x75Data[]= +{ + {211,60,1024,501,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + {211,60,1024,508,1688,1066 }, /* ; 01 (320x350,640x350) */ + {211,60,1024,501,1688,1066 }, /* ; 02 (360x400,720x400) */ + {211,60,1024,508,1688,1066 }, /* ; 03 (720x350) */ + {211,45,768,498,1688,1066 }, /* ; 04 (640x480x75Hz) */ + {211,75,1024,625,1688,1066 }, /* ; 05 (800x600x75Hz) */ + {211,120,1280,798,1688,1066 }, /* ; 06 (1024x768x75Hz) */ + {1,1,1688,1066,1688,1066 } /* ; 07 (1280x1024x75Hz) */ +}; + +XGI330_LCDDataStruct XGI_StLCD1280x1024x75Data[]= +{ + {211,60,1024,501,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + {211,60,1024,508,1688,1066 }, /* ; 01 (320x350,640x350) */ + {211,60,1024,501,1688,1066 }, /* ; 02 (360x400,720x400) */ + {211,60,1024,508,1688,1066 }, /* ; 03 (720x350) */ + {211,45,768,498,1688,1066 }, /* ; 04 (640x480x75Hz) */ + {211,75,1024,625,1688,1066 }, /* ; 05 (800x600x75Hz) */ + {211,120,1280,798,1688,1066}, /* ; 06 (1024x768x75Hz) */ + {1,1,1688,1066,1688,1066 } /* ; 07 (1280x1024x75Hz) */ +}; + +XGI330_LCDDataStruct XGI_CetLCD1280x1024x75Data[]= +{ + {1,1,1688,1066,1688,1066}, /* ; 00 (320x200,320x400,640x200,640x400) */ + {1,1,1688,1066,1688,1066}, /* ; 01 (320x350,640x350) */ + {1,1,1688,1066,1688,1066}, /* ; 02 (360x400,720x400) */ + {1,1,1688,1066,1688,1066}, /* ; 03 (720x350) */ + {1,1,1688,1066,1688,1066}, /* ; 04 (640x480x75Hz) */ + {1,1,1688,1066,1688,1066}, /* ; 05 (800x600x75Hz) */ + {1,1,1688,1066,1688,1066}, /* ; 06 (1024x768x75Hz) */ + {1,1,1688,1066,1688,1066} /* ; 07 (1280x1024x75Hz) */ +}; + +XGI330_LCDDataStruct XGI_NoScalingDatax75[]= +{ + {1,1,800,449,800,449 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + {1,1,800,449,800,449 }, /* ; 01 (320x350,640x350) */ + {1,1,900,449,900,449 }, /* ; 02 (360x400,720x400) */ + {1,1,900,449,900,449 }, /* ; 03 (720x350) */ + {1,1,840,500,840,500 }, /* ; 04 (640x480x75Hz) */ + {1,1,1056,625,1056,625 }, /* ; 05 (800x600x75Hz) */ + {1,1,1312,800,1312,800 }, /* ; 06 (1024x768x75Hz) */ + {1,1,1688,1066,1688,1066}, /* ; 07 (1280x1024x75Hz) */ + {1,1,1688,1066,1688,1066}, /* ; 08 (1400x1050x75Hz) ;;[ycchen] 12/19/02 */ + {1,1,2160,1250,2160,1250}, /* ; 09 (1600x1200x75Hz) */ + {1,1,1688,806,1688,806 } /* ; 0A (1280x768x75Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_ExtLCDDes1024x768Data[]= +{ + { 9,1057,0, 771 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + { 9,1057,0, 771 }, /* ; 01 (320x350,640x350) */ + { 9,1057,0, 771 }, /* ; 02 (360x400,720x400) */ + { 9,1057,0, 771 }, /* ; 03 (720x350) */ + { 9,1057,0, 771 }, /* ; 04 (640x480x60Hz) */ + { 9,1057,0, 771 }, /* ; 05 (800x600x60Hz) */ + { 9,1057,805, 770 } /* ; 06 (1024x768x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_StLCDDes1024x768Data[]= +{ + { 9,1057,737,703 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + { 9,1057,686,651 }, /* ; 01 (320x350,640x350) */ + { 9,1057,737,703 }, /* ; 02 (360x400,720x400) */ + { 9,1057,686,651 }, /* ; 03 (720x350) */ + { 9,1057,776,741 }, /* ; 04 (640x480x60Hz) */ + { 9,1057, 0 ,771 }, /* ; 05 (800x600x60Hz) */ + { 9,1057,805,770 } /* ; 06 (1024x768x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_CetLCDDes1024x768Data[]= +{ + { 1152,856,622,587 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + { 1152,856,597,562 }, /* ; 01 (320x350,640x350) */ + { 1152,856,622,587 }, /* ; 02 (360x400,720x400) */ + { 1152,856,597,562 }, /* ; 03 (720x350) */ + { 1152,856,662,627 }, /* ; 04 (640x480x60Hz) */ + { 1232,936,722,687 }, /* ; 05 (800x600x60Hz) */ + { 0,1048,805,770 } /* ; 06 (1024x768x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1280x1024Data[]= +{ + { 18,1346,981,940 },/* 00 (320x200,320x400,640x200,640x400) */ + { 18,1346,926,865 },/* 01 (320x350,640x350) */ + { 18,1346,981,940 },/* 02 (360x400,720x400) */ + { 18,1346,926,865 },/* 03 (720x350) */ + { 18,1346,0,1025 },/* 04 (640x480x60Hz) */ + { 18,1346,0,1025 },/* 05 (800x600x60Hz) */ + { 18,1346,1065,1024 },/* 06 (1024x768x60Hz) */ + { 18,1346,1065,1024 }/* 07 (1280x1024x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_StLCDDLDes1280x1024Data[]= +{ + { 18,1346,970,907 },/* 00 (320x200,320x400,640x200,640x400) */ + { 18,1346,917,854 },/* 01 (320x350,640x350) */ + { 18,1346,970,907 },/* 02 (360x400,720x400) */ + { 18,1346,917,854 },/* 03 (720x350) */ + { 18,1346,0,1025 },/* 04 (640x480x60Hz) */ + { 18,1346,0,1025 },/* 05 (800x600x60Hz) */ + { 18,1346,1065,1024 },/* 06 (1024x768x60Hz) */ + { 18,1346,1065,1024 }/* 07 (1280x1024x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_CetLCDDLDes1280x1024Data[]= +{ + { 1368,1008,752,711 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 1368,1008,729,688 }, /* 01 (320x350,640x350) */ + { 1368,1008,752,711 }, /* 02 (360x400,720x400) */ + { 1368,1008,729,688 }, /* 03 (720x350) */ + { 1368,1008,794,753 }, /* 04 (640x480x60Hz) */ + { 1448,1068,854,813 }, /* 05 (800x600x60Hz) */ + { 1560,1200,938,897 }, /* 06 (1024x768x60Hz) */ + { 18,1346,1065,1024 } /* 07 (1280x1024x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_ExtLCDDes1280x1024Data[]= +{ + { 9,1337,981,940 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + { 9,1337,926,884 }, /* ; 01 (320x350,640x350) alan, 2003/09/30 */ + { 9,1337,981,940 }, /* ; 02 (360x400,720x400) */ + { 9,1337,926,884 }, /* ; 03 (720x350) alan, 2003/09/30 */ + { 9,1337,0,1025 }, /* ; 04 (640x480x60Hz) */ + { 9,1337,0,1025 }, /* ; 05 (800x600x60Hz) */ + { 9,1337,1065,1024 }, /* ; 06 (1024x768x60Hz) */ + { 9,1337,1065,1024 } /* ; 07 (1280x1024x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_StLCDDes1280x1024Data[]= +{ + { 9,1337,970,907 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + { 9,1337,917,854 }, /* ; 01 (320x350,640x350) */ + { 9,1337,970,907 }, /* ; 02 (360x400,720x400) */ + { 9,1337,917,854 }, /* ; 03 (720x350) */ + { 9,1337,0,1025 }, /* ; 04 (640x480x60Hz) */ + { 9,1337,0,1025 }, /* ; 05 (800x600x60Hz) */ + { 9,1337,1065,1024 }, /* ; 06 (1024x768x60Hz) */ + { 9,1337,1065,1024 } /* ; 07 (1280x1024x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_CetLCDDes1280x1024Data[]= +{ + { 1368,1008,752,711 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 1368,1008,729,688 }, /* 01 (320x350,640x350) */ + { 1368,1008,752,711 }, /* 02 (360x400,720x400) */ + { 1368,1008,729,688 }, /* 03 (720x350) */ + { 1368,1008,794,753 }, /* 04 (640x480x60Hz) */ + { 1448,1068,854,813 }, /* 05 (800x600x60Hz) */ + { 1560,1200,938,897 }, /* 06 (1024x768x60Hz) */ + { 9,1337,1065,1024 } /* 07 (1280x1024x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_StLCDDLDes1400x1050Data[]= +{ + { 18,1464,0,1051 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 18,1464,0,1051 }, /* 01 (320x350,640x350) */ + { 18,1464,0,1051 }, /* 02 (360x400,720x400) */ + { 18,1464,0,1051 }, /* 03 (720x350) */ + { 18,1464,0,1051 }, /* 04 (640x480x60Hz) */ + { 18,1464,0,1051 }, /* 05 (800x600x60Hz) */ + { 18,1464,0,1051 }, /* 06 (1024x768x60Hz) */ + { 1646,1406,1053,1038 }, /* 07 (1280x1024x60Hz) */ + { 18,1464,0,1051 } /* 08 (1400x1050x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1400x1050Data[]= +{ + { 18,1464,0,1051 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 18,1464,0,1051 }, /* 01 (320x350,640x350) */ + { 18,1464,0,1051 }, /* 02 (360x400,720x400) */ + { 18,1464,0,1051 }, /* 03 (720x350) */ + { 18,1464,0,1051 }, /* 04 (640x480x60Hz) */ + { 18,1464,0,1051 }, /* 05 (800x600x60Hz) */ + { 18,1464,0,1051 }, /* 06 (1024x768x60Hz) */ + { 1646,1406,1053,1038 }, /* 07 (1280x1024x60Hz) */ + { 18,1464,0,1051 } /* 08 (1400x1050x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_StLCDDes1400x1050Data[]= +{ + { 9,1455,0,1051 },/* 00 (320x200,320x400,640x200,640x400) */ + { 9,1455,0,1051 },/* 01 (320x350,640x350) */ + { 9,1455,0,1051 },/* 02 (360x400,720x400) */ + { 9,1455,0,1051 },/* 03 (720x350) */ + { 9,1455,0,1051 },/* 04 (640x480x60Hz) */ + { 9,1455,0,1051 },/* 05 (800x600x60Hz) */ + { 9,1455,0,1051 },/* 06 (1024x768x60Hz) */ + { 1637,1397,1053,1038 },/* 07 (1280x1024x60Hz) */ + { 9,1455,0,1051 } /* 08 (1400x1050x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_ExtLCDDes1400x1050Data[]= +{ + { 9,1455,0,1051 },/* 00 (320x200,320x400,640x200,640x400) */ + { 9,1455,0,1051 },/* 01 (320x350,640x350) */ + { 9,1455,0,1051 },/* 02 (360x400,720x400) */ + { 9,1455,0,1051 },/* 03 (720x350) */ + { 9,1455,0,1051 },/* 04 (640x480x60Hz) */ + { 9,1455,0,1051 },/* 05 (800x600x60Hz) */ + { 9,1455,0,1051 },/* 06 (1024x768x60Hz) */ + { 1637,1397,1053,1038 },/* 07 (1280x1024x60Hz) */ + { 9,1455,0,1051 } /* 08 (1400x1050x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_CetLCDDes1400x1050Data[]= +{ + { 1308,1068,781,766 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 1308,1068,781,766 }, /* 01 (320x350,640x350) */ + { 1308,1068,781,766 }, /* 02 (360x400,720x400) */ + { 1308,1068,781,766 }, /* 03 (720x350) */ + { 1308,1068,781,766 }, /* 04 (640x480x60Hz) */ + { 1388,1148,841,826 }, /* 05 (800x600x60Hz) */ + { 1490,1250,925,910 }, /* 06 (1024x768x60Hz) */ + { 1646,1406,1053,1038 }, /* 07 (1280x1024x60Hz) */ + { 18,1464,0,1051 } /* 08 (1400x1050x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_CetLCDDes1400x1050Data2[]= +{ + { 0,1448,0,1051 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 0,1448,0,1051 }, /* 01 (320x350,640x350) */ + { 0,1448,0,1051 }, /* 02 (360x400,720x400) */ + { 0,1448,0,1051 }, /* 03 (720x350) */ + { 0,1448,0,1051 } /* 04 (640x480x60Hz) */ +}; + + + +XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1600x1200Data[]= +{ + { 18,1682,0,1201 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 18,1682,0,1201 }, /* 01 (320x350,640x350) */ + { 18,1682,0,1201 }, /* 02 (360x400,720x400) */ + { 18,1682,0,1201 }, /* 03 (720x350) */ + { 18,1682,0,1201 }, /* 04 (640x480x60Hz) */ + { 18,1682,0,1201 }, /* 05 (800x600x60Hz) */ + { 18,1682,0,1201 }, /* 06 (1024x768x60Hz) */ + { 18,1682,0,1201 }, /* 07 (1280x1024x60Hz) */ + { 18,1682,0,1201 }, /* 08 (1400x1050x60Hz) */ + { 18,1682,0,1201 } /* 09 (1600x1200x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_StLCDDLDes1600x1200Data[]= +{ + { 18,1682,1150,1101 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 18,1682,1083,1034 }, /* 01 (320x350,640x350) */ + { 18,1682,1150,1101 }, /* 02 (360x400,720x400) */ + { 18,1682,1083,1034 }, /* 03 (720x350) */ + { 18,1682,0,1201 }, /* 04 (640x480x60Hz) */ + { 18,1682,0,1201 }, /* 05 (800x600x60Hz) */ + { 18,1682,0,1201 }, /* 06 (1024x768x60Hz) */ + { 18,1682,1232,1183 }, /* 07 (1280x1024x60Hz) */ + { 18,1682,0,1201 }, /* 08 (1400x1050x60Hz) */ + { 18,1682,0,1201 } /* 09 (1600x1200x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_ExtLCDDes1600x1200Data[]= +{ + { 9,1673,0,1201 },/* 00 (320x200,320x400,640x200,640x400) */ + { 9,1673,0,1201 },/* 01 (320x350,640x350) */ + { 9,1673,0,1201 },/* 02 (360x400,720x400) */ + { 9,1673,0,1201 },/* 03 (720x350) */ + { 9,1673,0,1201 },/* 04 (640x480x60Hz) */ + { 9,1673,0,1201 },/* 05 (800x600x60Hz) */ + { 9,1673,0,1201 },/* 06 (1024x768x60Hz) */ + { 9,1673,0,1201 },/* 07 (1280x1024x60Hz) */ + { 9,1673,0,1201 },/* 08 (1400x1050x60Hz) */ + { 9,1673,0,1201 } /* 09 (1600x1200x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_StLCDDes1600x1200Data[]= +{ + { 9,1673,1150,1101 },/* 00 (320x200,320x400,640x200,640x400) */ + { 9,1673,1083,1034 },/* 01 (320x350,640x350) */ + { 9,1673,1150,1101 },/* 02 (360x400,720x400) */ + { 9,1673,1083,1034 },/* 03 (720x350) */ + { 9,1673,0,1201 },/* 04 (640x480x60Hz) */ + { 9,1673,0,1201 },/* 05 (800x600x60Hz) */ + { 9,1673,0,1201 },/* 06 (1024x768x60Hz) */ + { 9,1673,1232,1183 },/* 07 (1280x1024x60Hz) */ + { 9,1673,0,1201 },/* 08 (1400x1050x60Hz) */ + { 9,1673,0,1201 } /* 09 (1600x1200x60Hz) */ +}; + +XGI330_LCDDataDesStruct2 XGI_NoScalingDesData[]= +{ + { 9,657,448,405,96,2 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 9,657,448,355,96,2 }, /* 01 (320x350,640x350) */ + { 9,657,448,405,96,2 }, /* 02 (360x400,720x400) */ + { 9,657,448,355,96,2 }, /* 03 (720x350) */ + { 9,657,1,483,96,2 }, /* 04 (640x480x60Hz) */ + { 9,849,627,600,128,4 }, /* 05 (800x600x60Hz) */ + { 9,1057,805,770,0136,6 }, /* 06 (1024x768x60Hz) */ + { 9,1337,0,1025,112,3 }, /* 07 (1280x1024x60Hz) */ + { 9,1457,0,1051,112,3 }, /* 08 (1400x1050x60Hz) }, //;[ycchen] 12/19/02 */ + { 9,1673,0,1201,192,3 }, /* 09 (1600x1200x60Hz) */ + { 9,1337,0,771,112,6 } /* 0A (1280x768x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_ExtLCDDes1024x768x75Data[]= /* ;;1024x768x75Hz */ +{ + {9,1049,0,769}, /* ; 00 (320x200,320x400,640x200,640x400) */ + {9,1049,0,769}, /* ; 01 (320x350,640x350) */ + {9,1049,0,769}, /* ; 02 (360x400,720x400) */ + {9,1049,0,769}, /* ; 03 (720x350) */ + {9,1049,0,769}, /* ; 04 (640x480x75Hz) */ + {9,1049,0,769}, /* ; 05 (800x600x75Hz) */ + {9,1049,0,769} /* ; 06 (1024x768x75Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_StLCDDes1024x768x75Data[]= +{ + {9,1049,0,769}, /* ; 00 (320x200,320x400,640x200,640x400) */ + {9,1049,0,769}, /* ; 01 (320x350,640x350) */ + {9,1049,0,769}, /* ; 02 (360x400,720x400) */ + {9,1049,0,769}, /* ; 03 (720x350) */ + {9,1049,0,769}, /* ; 04 (640x480x75Hz) */ + {9,1049,0,769}, /* ; 05 (800x600x75Hz) */ + {9,1049,0,769} /* ; 06 (1024x768x75Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_CetLCDDes1024x768x75Data[]= /* ;;1024x768x75Hz */ +{ + {1152,856,622,587}, /* ; 00 (320x200,320x400,640x200,640x400) */ + {1152,856,597,562}, /* ; 01 (320x350,640x350) */ + {1192,896,622,587}, /* ; 02 (360x400,720x400) */ + {1192,896,597,562}, /* ; 03 (720x350) */ + {1129,857,656,625}, /* ; 04 (640x480x75Hz) */ + {1209,937,716,685}, /* ; 05 (800x600x75Hz) */ + {9,1049,0,769} /* ; 06 (1024x768x75Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_ExtLCDDLDes1280x1024x75Data[]= /* ;;1280x1024x75Hz */ +{ + {18,1314,0,1025 },/* ; 00 (320x200,320x400,640x200,640x400) */ + {18,1314,0,1025 },/* ; 01 (320x350,640x350) */ + {18,1314,0,1025 },/* ; 02 (360x400,720x400) */ + {18,1314,0,1025 },/* ; 03 (720x350) */ + {18,1314,0,1025 },/* ; 04 (640x480x60Hz) */ + {18,1314,0,1025 },/* ; 05 (800x600x60Hz) */ + {18,1314,0,1025 },/* ; 06 (1024x768x60Hz) */ + {18,1314,0,1025 }/* ; 07 (1280x1024x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_StLCDDLDes1280x1024x75Data[]= +{ + {18,1314,0,1025 },/* ; 00 (320x200,320x400,640x200,640x400) */ + {18,1314,0,1025 },/* ; 01 (320x350,640x350) */ + {18,1314,0,1025 },/* ; 02 (360x400,720x400) */ + {18,1314,0,1025 },/* ; 03 (720x350) */ + {18,1314,0,1025 },/* ; 04 (640x480x60Hz) */ + {18,1314,0,1025 },/* ; 05 (800x600x60Hz) */ + {18,1314,0,1025 },/* ; 06 (1024x768x60Hz) */ + {18,1314,0,1025 }/* ; 07 (1280x1024x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_CetLCDDLDes1280x1024x75Data[]= /* 1280x1024x75Hz */ +{ + {1368,1008,752,711}, /* ; 00 (320x200,320x400,640x200,640x400) */ + {1368,1008,729,688}, /* ; 01 (320x350,640x350) */ + {1408,1048,752,711}, /* ; 02 (360x400,720x400) */ + {1408,1048,729,688}, /* ; 03 (720x350) */ + {1377,985,794,753}, /* ; 04 (640x480x75Hz) */ + {1457,1065,854,813}, /* ; 05 (800x600x75Hz) */ + {1569,1177,938,897}, /* ; 06 (1024x768x75Hz) */ + {18,1314,0,1025} /* ; 07 (1280x1024x75Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_ExtLCDDes1280x1024x75Data[]= /* ;;1280x1024x75Hz */ +{ + {9,1305,0,1025},/* ; 00 (320x200,320x400,640x200,640x400) */ + {9,1305,0,1025},/* ; 01 (320x350,640x350) */ + {9,1305,0,1025},/* ; 02 (360x400,720x400) */ + {9,1305,0,1025},/* ; 03 (720x350) */ + {9,1305,0,1025},/* ; 04 (640x480x60Hz) */ + {9,1305,0,1025},/* ; 05 (800x600x60Hz) */ + {9,1305,0,1025},/* ; 06 (1024x768x60Hz) */ + {9,1305,0,1025} /* ; 07 (1280x1024x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_StLCDDes1280x1024x75Data[]= +{ + {9,1305,0,1025},/* ; 00 (320x200,320x400,640x200,640x400) */ + {9,1305,0,1025},/* ; 01 (320x350,640x350) */ + {9,1305,0,1025},/* ; 02 (360x400,720x400) */ + {9,1305,0,1025},/* ; 03 (720x350) */ + {9,1305,0,1025},/* ; 04 (640x480x60Hz) */ + {9,1305,0,1025},/* ; 05 (800x600x60Hz) */ + {9,1305,0,1025},/* ; 06 (1024x768x60Hz) */ + {9,1305,0,1025} /* ; 07 (1280x1024x60Hz) */ +}; + +XGI330_LCDDataDesStruct XGI_CetLCDDes1280x1024x75Data[]= /* 1280x1024x75Hz */ +{ + {1368,1008,752,711}, /* ; 00 (320x200,320x400,640x200,640x400) */ + {1368,1008,729,688}, /* ; 01 (320x350,640x350) */ + {1408,1048,752,711}, /* ; 02 (360x400,720x400) */ + {1408,1048,729,688}, /* ; 03 (720x350) */ + {1377,985,794,753}, /* ; 04 (640x480x75Hz) */ + {1457,1065,854,813}, /* ; 05 (800x600x75Hz) */ + {1569,1177,938,897}, /* ; 06 (1024x768x75Hz) */ + {9,1305,0,1025} /* ; 07 (1280x1024x75Hz) */ +}; + +XGI330_LCDDataDesStruct2 XGI_NoScalingDesDatax75[]= /* Scaling LCD 75Hz */ +{ + {9,657,448,405,96,2}, /* ; 00 (320x200,320x400,640x200,640x400) */ + {9,657,448,355,96,2}, /* ; 01 (320x350,640x350) */ + {9,738,448,405,108,2}, /* ; 02 (360x400,720x400) */ + {9,738,448,355,108,2}, /* ; 03 (720x350) */ + {9,665,0,481,64,3}, /* ; 04 (640x480x75Hz) */ + {9,825,0,601,80,3}, /* ; 05 (800x600x75Hz) */ + {9,1049,0,769,96,3}, /* ; 06 (1024x768x75Hz) */ + {9,1305,0,1025,144,3}, /* ; 07 (1280x1024x75Hz) */ + {9,1457,0,1051,112,3}, /* ; 08 (1400x1050x60Hz) ;;[ycchen] 12/19/02 */ + {9,1673,0,1201,192,3}, /* ; 09 (1600x1200x75Hz) */ + {9,1337,0,771,112,6} /* ; 0A (1280x768x60Hz) */ +}; + +XGI330_TVDataStruct XGI_StPALData[]= +{ + { 1, 1, 864, 525,1270, 400, 100, 0, 760}, + { 1, 1, 864, 525,1270, 350, 100, 0, 760}, + { 1, 1, 864, 525,1270, 400, 0, 0, 720}, + { 1, 1, 864, 525,1270, 350, 0, 0, 720}, + { 1, 1, 864, 525,1270, 480, 50, 0, 760}, + { 1, 1, 864, 525,1270, 600, 50, 0, 0} +}; + +XGI330_TVDataStruct XGI_ExtPALData[]= +{ + { 2, 1,1080, 463,1270, 500, 50, 0, 50}, + { 15, 7,1152, 413,1270, 500, 50, 0, 50}, + { 2, 1,1080, 463,1270, 500, 50, 0, 50}, + { 15, 7,1152, 413,1270, 500, 50, 0, 50}, + { 2, 1, 900, 543,1270, 500, 0, 0, 50}, + { 4, 3,1080, 663,1270, 500, 438, 0, 438}, + { 1, 1,1125, 831,1270, 500, 686, 0, 686}, /*301b*/ + { 3, 2,1080, 619,1270, 540, 438, 0, 438} +}; + +XGI330_TVDataStruct XGI_StNTSCData[]= +{ + { 1, 1, 858, 525,1270, 400, 50, 0, 760}, + { 1, 1, 858, 525,1270, 350, 50, 0, 640}, + { 1, 1, 858, 525,1270, 400, 0, 0, 720}, + { 1, 1, 858, 525,1270, 350, 0, 0, 720}, + { 1, 1, 858, 525,1270, 480, 0, 0, 760} +}; + +XGI330_TVDataStruct XGI_ExtNTSCData[]= +{ + { 9, 5, 1001, 453,1270, 420, 171, 0, 171}, + { 12, 5, 858, 403,1270, 420, 171, 0, 171}, + { 9, 5, 1001, 453,1270, 420, 171, 0, 171}, + { 12, 5, 858, 403,1270, 420, 171, 0, 171}, + { 143, 80, 836, 523,1270, 420, 224, 0, 0}, + { 143, 120,1008, 643,1270, 420, 0, 1, 0}, + { 1, 1,1120, 821,1516, 420, 0, 1, 0}, /*301b*/ + { 2, 1, 858, 503,1584, 480, 0, 1, 0}, + { 3, 2,1001, 533,1270, 420, 0, 0, 0} +}; + +XGI330_TVDataStruct XGI_St1HiTVData[]= +{ + { 1,1,892,563,690,800,0,0,0 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 1,1,892,563,690,700,0,0,0 }, /* 01 (320x350,640x350) */ + { 1,1,1000,563,785,800,0,0,0 }, /* 02 (360x400,720x400) */ + { 1,1,1000,563,785,700,0,0,0 }, /* 03 (720x350) */ + { 1,1,892,563,690,960,0,0,0 }, /* 04 (320x240,640x480) */ + { 8,5,1050,683,1648,960,0x150,1,0 } /* 05 (400x300,800x600) */ +}; + +XGI330_TVDataStruct XGI_St2HiTVData[]= +{ + { 3,1,840,483,1648,960,0x032,0,0 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 1,1,892,563,690,700,0,0,0 }, /* 01 (320x350,640x350) */ + { 3,1,840,483,1648,960,0x032,0,0 }, /* 02 (360x400,720x400) */ + { 1,1,1000,563,785,700,0,0,0 }, /* 03 (720x350) */ + { 5,2,840,563,1648,960,0x08D,1,0 }, /* 04 (320x240,640x480) */ + { 8,5,1050,683,1648,960,0x17C,1,0 } /* 05 (400x300,800x600) */ + +}; + +XGI330_TVDataStruct XGI_ExtHiTVData[]= +{ + { 6,1,840,563,1632,960,0,0,0 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 3,1,960,563,1632,960,0,0,0 }, /* 01 (320x350,640x350) */ + { 3,1,840,483,1632,960,0,0,0 }, /* 02 (360x400,720x400) */ + { 3,1,960,563,1632,960,0,0,0 }, /* 03 (720x350) */ + { 5,1,840,563,1648,960,0x166,1,0 }, /* 04 (320x240,640x480) */ + { 16,5,1050,683,1648,960,0x143,1,0 }, /* 05 (400x300,800x600) */ + { 25,12,1260,851,1648,960,0x032,0,0 }, /* 06 (512x384,1024x768) */ + { 5,4,1575,1124,1648,960,0x128,0,0 }, /* 07 (1280x1024) */ + { 4,1,1050,563,1548,960,0x143,1,0 }, /* 08 (800x480) */ + { 5,2,1400,659,1648,960,0x032,0,0 }, /* 09 (1024x576) */ + { 8,5,1750,803,1648,960,0x128,0,0 } /* 0A (1280x720) */ + +}; + +XGI330_TVDataStruct XGI_ExtYPbPr525iData[]= +{ + { 9, 5, 1001, 453,1270, 420, 171, 0, 171}, + { 12, 5, 858, 403,1270, 420, 171, 0, 171}, + { 9, 5, 1001, 453,1270, 420, 171, 0, 171}, + { 12, 5, 858, 403,1270, 420, 171, 0, 171}, + { 143, 80, 836, 523,1250, 420, 224, 0, 0}, + { 143, 120,1008, 643,1250, 420, 0, 1, 0}, + { 1, 1,1120, 821,1516, 420, 0, 1, 0}, /*301b*/ + { 2, 1, 858, 503,1584, 480, 0, 1, 0}, + { 3, 2,1001, 533,1250, 420, 0, 0, 0} +}; + +XGI330_TVDataStruct XGI_StYPbPr525iData[]= +{ + { 1, 1, 858, 525,1270, 400, 50, 0, 760}, + { 1, 1, 858, 525,1270, 350, 50, 0, 640}, + { 1, 1, 858, 525,1270, 400, 0, 0, 720}, + { 1, 1, 858, 525,1270, 350, 0, 0, 720}, + { 1, 1, 858, 525,1270, 480, 0, 0, 760}, +}; + +XGI330_TVDataStruct XGI_ExtYPbPr525pData[]= +{ + { 9, 5, 1001, 453,1270, 420, 171, 0, 171}, + { 12, 5, 858, 403,1270, 420, 171, 0, 171}, + { 9, 5, 1001, 453,1270, 420, 171, 0, 171}, + { 12, 5, 858, 403,1270, 420, 171, 0, 171}, + { 143, 80, 836, 523,1270, 420, 224, 0, 0}, + { 143, 120,1008, 643,1270, 420, 0, 1, 0}, + { 1, 1,1120, 821,1516, 420, 0, 1, 0}, /*301b*/ + { 2, 1, 858, 503,1584, 480, 0, 1, 0}, + { 3, 2,1001, 533,1270, 420, 0, 0, 0} + }; + +XGI330_TVDataStruct XGI_StYPbPr525pData[]= +{ + { 1, 1,1716, 525,1270, 400, 50, 0, 760}, + { 1, 1,1716, 525,1270, 350, 50, 0, 640}, + { 1, 1,1716, 525,1270, 400, 0, 0, 720}, + { 1, 1,1716, 525,1270, 350, 0, 0, 720}, + { 1, 1,1716, 525,1270, 480, 0, 0, 760}, +}; + +XGI330_TVDataStruct XGI_ExtYPbPr750pData[]= +{ + { 3, 1, 935, 470,1130, 680, 50, 0, 0}, /* 00 (320x200,320x400,640x200,640x400) */ + { 24, 7, 935, 420,1130, 680, 50, 0, 0}, /* 01 (320x350,640x350) */ + { 3, 1, 935, 470,1130, 680, 50, 0, 0}, /* 02 (360x400,720x400) */ + { 24, 7, 935, 420,1130, 680, 50, 0, 0}, /* 03 (720x350) */ + { 2, 1,1100, 590,1130, 640, 50, 0, 0}, /* 04 (320x240,640x480) */ + { 3, 2,1210, 690,1130, 660, 50, 0, 0}, /* 05 (400x300,800x600) */ + { 1, 1,1375, 878,1130, 640, 638, 0, 0}, /* 06 (1024x768) */ + { 2, 1, 858, 503,1130, 480, 0, 1, 0}, /* 07 (720x480) */ + { 5, 4,1815, 570,1130, 660, 50, 0, 0}, + { 5, 3,1100, 686,1130, 640, 50, 1, 0}, + { 10, 9,1320, 830,1130, 640, 50, 0, 0} +}; + +XGI330_TVDataStruct XGI_StYPbPr750pData[]= +{ + { 1, 1,1650, 750,1280, 400, 50, 0, 760}, + { 1, 1,1650, 750,1280, 350, 50, 0, 640}, + { 1, 1,1650, 750,1280, 400, 0, 0, 720}, + { 1, 1,1650, 750,1280, 350, 0, 0, 720}, + { 1, 1,1650, 750,1280, 480, 0, 0, 760}, +}; + +UCHAR XGI330_NTSCTiming[] = { + 0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c, + 0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a, + 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b, + 0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17, + 0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02, + 0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40, + 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50, + 0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00}; + +UCHAR XGI330_PALTiming[] = { + 0x21,0x5A,0x35,0x6e,0x04,0x38,0x3d,0x70, + 0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d, + 0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b, + 0x70,0x50,0x00,0x9b,0x00,0xd9,0x5d,0x17, + 0x7d,0x05,0x45,0x00,0x00,0xe8,0x00,0x02, + 0x0d,0x00,0x68,0xb0,0x0b,0x92,0x8f,0x40, + 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63, + 0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00}; + +UCHAR XGI330_HiTVExtTiming[] = +{ + 0x2D,0x60,0x2C,0x5F,0x08,0x31,0x3A,0x64, + 0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D, + 0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F, + 0x64,0x90,0x33,0x8C,0x18,0x36,0x3E,0x13, + 0x2A,0xDE,0x2A,0x44,0x40,0x2A,0x44,0x40, + 0x8E,0x8E,0x82,0x07,0x0B, + 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C, + 0x60,0x14,0x3D,0x63,0x4F, + 0x27,0x00,0xfc,0xff,0x6a,0x00 + +}; + +UCHAR XGI330_HiTVSt1Timing[] = +{ + 0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x65, + 0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D, + 0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F, + 0x65,0x90,0x7B,0xA8,0x03,0xF0,0x87,0x03, + 0x11,0x15,0x11,0xCF,0x10,0x11,0xCF,0x10, + 0x35,0x35,0x3B,0x69,0x1D, + 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C, + 0x60,0x04,0x86,0xAF,0x5D, + 0x0E,0x00,0xfc,0xff,0x2d,0x00 +}; + +UCHAR XGI330_HiTVSt2Timing[] = +{ + 0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x64, + 0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D, + 0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F, + 0x64,0x90,0x33,0x8C,0x18,0x36,0x3E,0x13, + 0x2A,0xDE,0x2A,0x44,0x40,0x2A,0x44,0x40, + 0x8E,0x8E,0x82,0x07,0x0B, + 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C, + 0x60,0x14,0x3D,0x63,0x4F, + 0x27,0x00,0xFC,0xff,0x6a,0x00 +}; + +UCHAR XGI330_HiTVTextTiming[] = +{ + 0x32,0x65,0x2C,0x5F,0x08,0x31,0x3A,0x65, + 0x28,0x02,0x01,0x3D,0x06,0x3E,0x35,0x6D, + 0x06,0x14,0x3E,0x35,0x6D,0x00,0xC5,0x3F, + 0x65,0x90,0xE7,0xBC,0x03,0x0C,0x97,0x03, + 0x14,0x78,0x14,0x08,0x20,0x14,0x08,0x20, + 0xC8,0xC8,0x3B,0xD2,0x26, + 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C, + 0x60,0x04,0x96,0x72,0x5C, + 0x11,0x00,0xFC,0xFF,0x32,0x00 +}; + +UCHAR XGI330_YPbPr750pTiming[] = +{ + 0x30,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c, + 0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a, + 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f, + 0xed,0x50,0x70,0x9f,0x16,0x59,0x60,0x13, + 0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0, + 0x4b,0x4b,0x6f,0x2f,0x63, + 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C, + 0x60,0x14,0x73,0x00,0x40, + 0x11,0x00,0xfc,0xff,0x32,0x00 +}; + +UCHAR XGI330_YPbPr525pTiming[] = +{ + 0x3E,0x11,0x06,0x09,0x0b,0x0c,0x0c,0x0c, + 0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a, + 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f, + 0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13, + 0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8, + 0x51,0x5e,0x60,0x49,0x7d, + 0x92,0x0F,0x40,0x60,0x80,0x14,0x90,0x8C, + 0x60,0x14,0x4B,0x43,0x41, + 0x11,0x00,0xFC,0xFF,0x32,0x00 +}; + +UCHAR XGI330_YPbPr525iTiming[] = +{ + 0x1B,0x21,0x03,0x09,0x05,0x06,0x0C,0x0C, + 0x94,0x49,0x01,0x0A,0x06,0x0D,0x04,0x0A, + 0x06,0x14,0x0D,0x04,0x0A,0x00,0x85,0x1B, + 0x0C,0x50,0x00,0x97,0x00,0xDA,0x4A,0x17, + 0x7D,0x05,0x4B,0x00,0x00,0xE2,0x00,0x02, + 0x03,0x0A,0x65,0x9D,0x08, + 0x92,0x8F,0x40,0x60,0x80,0x14,0x90,0x8C, + 0x60,0x14,0x4B,0x00,0x40, + 0x44,0x00,0xDB,0x02,0x3B,0x00 + +}; + +UCHAR XGI330_HiTVGroup3Data[] = +{ + 0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0x5F, + 0x05,0x21,0xB2,0xB2,0x55,0x77,0x2A,0xA6, + 0x25,0x2F,0x47,0xFA,0xC8,0xFF,0x8E,0x20, + 0x8C,0x6E,0x60,0x2E,0x58,0x48,0x72,0x44, + 0x56,0x36,0x4F,0x6E,0x3F,0x80,0x00,0x80, + 0x4F,0x7F,0x03,0xA8,0x7D,0x20,0x1A,0xA9, + 0x14,0x05,0x03,0x7E,0x64,0x31,0x14,0x75, + 0x18,0x05,0x18,0x05,0x4C,0xA8,0x01 +}; + +UCHAR XGI330_HiTVGroup3Simu[] = +{ + 0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0x95, + 0xDB,0x20,0xB8,0xB8,0x55,0x47,0x2A,0xA6, + 0x25,0x2F,0x47,0xFA,0xC8,0xFF,0x8E,0x20, + 0x8C,0x6E,0x60,0x15,0x26,0xD3,0xE4,0x11, + 0x56,0x36,0x4F,0x6E,0x3F,0x80,0x00,0x80, + 0x67,0x36,0x01,0x47,0x0E,0x10,0xBE,0xB4, + 0x01,0x05,0x03,0x7E,0x65,0x31,0x14,0x75, + 0x18,0x05,0x18,0x05,0x4C,0xA8,0x01 +}; + +UCHAR XGI330_HiTVGroup3Text[] = +{ + 0x00,0x1A,0x22,0x63,0x62,0x22,0x08,0xA7, + 0xF5,0x20,0xCE,0xCE,0x55,0x47,0x2A,0xA6, + 0x25,0x2F,0x47,0xFA,0xC8,0xFF,0x8E,0x20, + 0x8C,0x6E,0x60,0x18,0x2C,0x0C,0x20,0x22, + 0x56,0x36,0x4F,0x6E,0x3F,0x80,0x00,0x80, + 0x93,0x3C,0x01,0x50,0x2F,0x10,0xF4,0xCA, + 0x01,0x05,0x03,0x7E,0x65,0x31,0x14,0x75, + 0x18,0x05,0x18,0x05,0x4C,0xA8,0x01 +}; + +UCHAR XGI330_Ren525pGroup3[] = +{ + 0x00,0x14,0x15,0x25,0x55,0x15,0x0b,0x13, + 0xB1,0x41,0x62,0x62,0xFF,0xF4,0x45,0xa6, + 0x25,0x2F,0x67,0xF6,0xbf,0xFF,0x8E,0x20, + 0xAC,0xDA,0x60,0xFe,0x6A,0x9A,0x06,0x10, + 0xd1,0x04,0x18,0x0a,0xFF,0x80,0x00,0x80, + 0x3c,0x77,0x00,0xEF,0xE0,0x10,0xB0,0xE0, + 0x10,0x4F,0x0F,0x0F,0x05,0x0F,0x08,0x6E, + 0x1a,0x1F,0x25,0x2a,0x4C,0xAA,0x01 +}; + +UCHAR XGI330_Ren750pGroup3[] = +{ + 0x00,0x14,0x15,0x25,0x55,0x15,0x0b,0x7a, + 0x54,0x41,0xE7,0xE7,0xFF,0xF4,0x45,0xa6, + 0x25,0x2F,0x67,0xF6,0xbf,0xFF,0x8E,0x20, + 0xAC,0x6A,0x60,0x2b,0x52,0xCD,0x61,0x10, + 0x51,0x04,0x18,0x0a,0x1F,0x80,0x00,0x80, + 0xFF,0xA4,0x04,0x2B,0x94,0x21,0x72,0x94, + 0x26,0x05,0x01,0x0F,0xed,0x0F,0x0A,0x64, + 0x18,0x1D,0x23,0x28,0x4C,0xAA,0x01 +}; + +XGI_PanelDelayTblStruct XGI330_PanelDelayTbl[]= +{ +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}}, +{{0x00,0x00}} +}; + +XGI330_LVDSDataStruct XGI330_LVDS320x480Data_1[]= +{ + {848, 433,400,525}, + {848, 389,400,525}, + {848, 433,400,525}, + {848, 389,400,525}, + {848, 518,400, 525}, + {1056, 628,400,525}, + {400, 525,400,525}, + {800, 449,1000, 644}, + {800, 525,1000, 635} +}; + +XGI330_LVDSDataStruct XGI330_LVDS800x600Data_1[]= +{ + {848, 433,1060, 629}, + {848, 389,1060, 629}, + {848, 433,1060, 629}, + {848, 389,1060, 629}, + {848, 518,1060, 629}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {800, 449,1000, 644}, + {800, 525,1000, 635} +}; + +XGI330_LVDSDataStruct XGI330_LVDS800x600Data_2[]= +{ + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {800, 449,1000, 644}, + {800, 525,1000, 635} +}; + +XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1[]= +{ + { 960 , 438 , 1344 , 806 } , /* 00 (320x200,320x400,640x200,640x400) */ + { 960 , 388 , 1344 , 806 } , /* 01 (320x350,640x350) */ + { 1040, 438 , 1344 , 806 } , /* 02 (360x400,720x400) */ + { 1040, 388 , 1344 , 806 } , /* 03 (720x350) */ + { 960 , 518 , 1344 , 806 } , /* 04 (320x240,640x480) */ + {1120 , 638 , 1344 , 806 } , /* 05 (400x300,800x600) */ + {1344 , 806 , 1344 , 806 } /* 06 (512x384,1024x768) */ +}; + + +XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2[]= +{ + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; + +XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1[]= +{ + {1048, 442,1688, 1066}, + {1048, 392,1688, 1066}, + {1048, 442,1688, 1066}, + {1048, 392,1688, 1066}, + {1048, 522,1688, 1066}, + {1208, 642,1688, 1066}, + {1432, 810,1688, 1066}, + {1688, 1066,1688, 1066} +}; + +XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2[]= +{ + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {800, 449,1280, 801}, + {800, 525,1280, 813} +}; +/* +XGI330_LVDSDataStruct XGI_LVDS1280x768Data_1[]= +{ + {768,438,1408,806}, + {768,388,1408,806}, + {768,438,1408,806}, + {768,388,1408,806}, + {768,518,1408,806}, + {928,638,1408,806}, + {1408,806,1408,806}, + {1408,806,1408,806}, + {1408,806,1408,806} +}; + +XGI330_LVDSDataStruct XGI_LVDS1280x768Data_2[]= +{ + {1408, 806,1408, 806}, + {1408, 806,1408, 806}, + {1408, 806,1408, 806}, + {1408, 806,1408, 806}, + {1408, 806,1408, 806}, + {1408, 806,1408, 806}, + {1408, 806,1408, 806}, + {1408, 806,1408, 806}, + {1408, 806,1408, 806} +}; + +XGI330_LVDSDataStruct XGI_LVDS1280x768NData_1[]= +{ + {704, 438,1344, 806}, + {704, 388,1344, 806}, + {704, 438,1344, 806}, + {704, 388,1344, 806}, + {704, 518,1344, 806}, + {864, 638,1344, 806}, + {1088, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806} +}; + +XGI330_LVDSDataStruct XGI_LVDS1280x768NData_2[]= +{ + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806}, + {1344, 806,1344, 806} +}; + +XGI330_LVDSDataStruct XGI_LVDS1280x768SData_1[]= +{ + {1048,438,1688,806}, + {1048,388,1688,806}, + {1148,438,1688,806}, + {1148,388,1688,806}, + {1048,518,1688,806}, + {1208,638,1688,806}, + {1432,806,1688,806}, + {1688,806,1688,806}, + {1688,806,1688,806} +}; + +XGI330_LVDSDataStruct XGI_LVDS1280x768SData_2[]= +{ + {1688,806,1688,806}, + {1688,806,1688,806}, + {1688,806,1688,806}, + {1688,806,1688,806}, + {1688,806,1688,806}, + {1688,806,1688,806}, + {1688,806,1688,806}, + {1688,806,1688,806}, + {1688,806,1688,806} +}; +*/ +XGI330_LVDSDataStruct XGI_LVDS1400x1050Data_1[]= +{ + {928,416,1688,1066}, + {928,366,1688,1066}, + {928,416,1688,1066}, + {928,366,1688,1066}, + {928,496,1688,1066}, + {1088,616,1688,1066}, + {1312,784,1688,1066}, + {1568,1040,1688,1066}, + {1688,1066,1688,1066} +}; + +XGI330_LVDSDataStruct XGI_LVDS1400x1050Data_2[]= +{ + {1688,1066,1688,1066}, + {1688,1066,1688,1066}, + {1688,1066,1688,1066}, + {1688,1066,1688,1066}, + {1688,1066,1688,1066}, + {1688,1066,1688,1066}, + {1688,1066,1688,1066}, + {1688,1066,1688,1066}, + {1688,1066,1688,1066} +}; + +XGI330_LVDSDataStruct XGI_LVDS1600x1200Data_1[]= +{ /* ;;[ycchen] 12/05/02 LCDHTxLCDVT=2048x1320 */ + { 1088,520,2048,1320 },/* 00 (320x200,320x400,640x200,640x400) */ + { 1088,470,2048,1320 },/* 01 (320x350,640x350) */ + { 1088,520,2048,1320 },/* 02 (360x400,720x400) */ + { 1088,470,2048,1320 },/* 03 (720x350) */ + { 1088,600,2048,1320 },/* 04 (320x240,640x480) */ + { 1248,720,2048,1320 },/* 05 (400x300,800x600) */ + { 1472,888,2048,1320 },/* 06 (512x384,1024x768) */ + { 1728,1144,2048,1320 },/* 07 (640x512,1280x1024) */ + { 1848,1170,2048,1320 },/* 08 (1400x1050) */ + { 2048,1320,2048,1320 } /* 09 (1600x1200) */ +}; + +XGI330_LVDSDataStruct XGI_LVDSNoScalingData[]= +{ + { 800,449,800,449 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 800,449,800,449 }, /* 01 (320x350,640x350) */ + { 800,449,800,449 }, /* 02 (360x400,720x400) */ + { 800,449,800,449 }, /* 03 (720x350) */ + { 800,525,800,525 }, /* 04 (640x480x60Hz) */ + { 1056,628,1056,628 }, /* 05 (800x600x60Hz) */ + { 1344,806,1344,806 }, /* 06 (1024x768x60Hz) */ + { 1688,1066,1688,1066 }, /* 07 (1280x1024x60Hz) */ + { 1688,1066,1688,1066 }, /* 08 (1400x1050x60Hz) ;;[ycchen] 12/19/02 */ + { 2160,1250,2160,1250 }, /* 09 (1600x1200x60Hz) */ + { 1688,806,1688,806 } /* 0A (1280x768x60Hz) */ +}; + +XGI330_LVDSDataStruct XGI_LVDS1024x768Data_1x75[]= +{ + {960,438,1312,800 }, /* 00 (320x200,320x400,640x200,640x400) */ + {960,388,1312,800 }, /* 01 (320x350,640x350) */ + {1040,438,1312,800 }, /* 02 (360x400,720x400) */ + {1040,388,1312,800 }, /* 03 (720x350) */ + {928,512,1312,800 }, /* 04 (320x240,640x480) */ + {1088,632,1312,800 }, /* 05 (400x300,800x600) */ + {1312,800,1312,800 }, /* 06 (512x384,1024x768) */ +}; + + +XGI330_LVDSDataStruct XGI_LVDS1024x768Data_2x75[]= +{ + {1312,800,1312,800}, /* ; 00 (320x200,320x400,640x200,640x400) */ + {1312,800,1312,800}, /* ; 01 (320x350,640x350) */ + {1312,800,1312,800}, /* ; 02 (360x400,720x400) */ + {1312,800,1312,800}, /* ; 03 (720x350) */ + {1312,800,1312,800}, /* ; 04 (320x240,640x480) */ + {1312,800,1312,800}, /* ; 05 (400x300,800x600) */ + {1312,800,1312,800}, /* ; 06 (512x384,1024x768) */ +}; + +XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_1x75[]= +{ + {1048,442,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + {1048,392,1688,1066 }, /* ; 01 (320x350,640x350) */ + {1128,442,1688,1066 }, /* ; 02 (360x400,720x400) */ + {1128,392,1688,1066 }, /* ; 03 (720x350) */ + {1048,522,1688,1066 }, /* ; 04 (320x240,640x480) */ + {1208,642,1688,1066 }, /* ; 05 (400x300,800x600) */ + {1432,810,1688,1066 }, /* ; 06 (512x384,1024x768) */ + {1688,1066,1688,1066 }, /* ; 06; 07 (640x512,1280x1024) */ +}; + +XGI330_LVDSDataStruct XGI_LVDS1280x1024Data_2x75[]= +{ + {1688,1066,1688,1066 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + {1688,1066,1688,1066 }, /* ; 01 (320x350,640x350) */ + {1688,1066,1688,1066 }, /* ; 02 (360x400,720x400) */ + {1688,1066,1688,1066 }, /* ; 03 (720x350) */ + {1688,1066,1688,1066 }, /* ; 04 (320x240,640x480) */ + {1688,1066,1688,1066 }, /* ; 05 (400x300,800x600) */ + {1688,1066,1688,1066 }, /* ; 06 (512x384,1024x768) */ + {1688,1066,1688,1066 }, /* ; 06; 07 (640x512,1280x1024) */ +}; + +XGI330_LVDSDataStruct XGI_LVDSNoScalingDatax75[]= +{ + {800,449,800,449 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + {800,449,800,449 }, /* ; 01 (320x350,640x350) */ + {900,449,900,449 }, /* ; 02 (360x400,720x400) */ + {900,449,900,449 }, /* ; 03 (720x350) */ + {800,500,800,500 }, /* ; 04 (640x480x75Hz) */ + {1056,625,1056,625 }, /* ; 05 (800x600x75Hz) */ + {1312,800,1312,800 }, /* ; 06 (1024x768x75Hz) */ + {1688,1066,1688,1066 }, /* ; 07 (1280x1024x75Hz) */ + {1688,1066,1688,1066 }, /* ; 08 (1400x1050x75Hz) ;;[ycchen] 12/19/02 */ + {2160,1250,2160,1250 }, /* ; 09 (1600x1200x75Hz) */ + {1688,806,1688,806 }, /* ; 0A (1280x768x75Hz) */ +}; + +XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1[]= +{ + { 0,1048, 0, 771 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 0,1048, 0, 771 }, /* 01 (320x350,640x350) */ + { 0,1048, 0, 771 }, /* 02 (360x400,720x400) */ + { 0,1048, 0, 771 }, /* 03 (720x350) */ + { 0,1048, 0, 771 }, /* 04 (640x480x60Hz) */ + { 0,1048, 0, 771 }, /* 05 (800x600x60Hz) */ + { 0,1048, 805, 770 } /* 06 (1024x768x60Hz) */ +} ; + +XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2[]= +{ + { 1142, 856, 622, 587 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 1142, 856, 597, 562 }, /* 01 (320x350,640x350) */ + { 1142, 856, 622, 587 }, /* 02 (360x400,720x400) */ + { 1142, 856, 597, 562 }, /* 03 (720x350) */ + { 1142,1048, 722, 687 }, /* 04 (640x480x60Hz) */ + { 1232, 936, 722, 687 }, /* 05 (800x600x60Hz) */ + { 0,1048, 805, 771 } /* 06 (1024x768x60Hz) */ +}; + +XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3[]= +{ + { 320, 24, 622, 587 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 320, 24, 597, 562 }, /* 01 (320x350,640x350) */ + { 320, 24, 622, 587 }, /* 02 (360x400,720x400) */ + { 320, 24, 597, 562 }, /* 03 (720x350) */ + { 320, 24, 722, 687 } /* 04 (640x480x60Hz) */ +}; + +XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1[]= +{ + { 0,1328, 0, 1025 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 0,1328, 0, 1025 }, /* 01 (320x350,640x350) */ + { 0,1328, 0, 1025 }, /* 02 (360x400,720x400) */ + { 0,1328, 0, 1025 }, /* 03 (720x350) */ + { 0,1328, 0, 1025 }, /* 04 (640x480x60Hz) */ + { 0,1328, 0, 1025 }, /* 05 (800x600x60Hz) */ + { 0,1328, 0, 1025 }, /* 06 (1024x768x60Hz) */ + { 0,1328, 1065, 1024 } /* 07 (1280x1024x60Hz) */ +}; + + /* The Display setting for DE Mode Panel */ +XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2[]= +{ + { 1368,1008,752,711 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 1368,1008,729,688 }, /* 01 (320x350,640x350) */ + { 1408,1048,752,711 }, /* 02 (360x400,720x400) */ + { 1408,1048,729,688 }, /* 03 (720x350) */ + { 1368,1008,794,753 }, /* 04 (640x480x60Hz) */ + { 1448,1068,854,813 }, /* 05 (800x600x60Hz) */ + { 1560,1200,938,897 }, /* 06 (1024x768x60Hz) */ + { 0000,1328,0,1025 } /* 07 (1280x1024x60Hz) */ +}; + +XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_1[]= +{ + { 0,1448,0,1051 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 0,1448,0,1051 }, /* 01 (320x350,640x350) */ + { 0,1448,0,1051 }, /* 02 (360x400,720x400) */ + { 0,1448,0,1051 }, /* 03 (720x350) */ + { 0,1448,0,1051 }, /* 04 (640x480x60Hz) */ + { 0,1448,0,1051 }, /* 05 (800x600x60Hz) */ + { 0,1448,0,1051 }, /* 06 (1024x768x60Hz) */ + { 0,1448,0,1051 }, /* 07 (1280x1024x60Hz) */ + { 0,1448,0,1051 } /* 08 (1400x1050x60Hz) */ +}; + +XGI330_LVDSDataStruct XGI_LVDS1400x1050Des_2[]= +{ + { 1308,1068, 781, 766 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 1308,1068, 781, 766 }, /* 01 (320x350,640x350) */ + { 1308,1068, 781, 766 }, /* 02 (360x400,720x400) */ + { 1308,1068, 781, 766 }, /* 03 (720x350) */ + { 1308,1068, 781, 766 }, /* 04 (640x480x60Hz) */ + { 1388,1148, 841, 826 }, /* 05 (800x600x60Hz) */ + { 1490,1250, 925, 910 }, /* 06 (1024x768x60Hz) */ + { 1608,1368,1053,1038 }, /* 07 (1280x1024x60Hz) */ + { 0,1448,0,1051 } /* 08 (1400x1050x60Hz) */ +}; + +XGI330_LVDSDataStruct XGI_LVDS1600x1200Des_1[]= +{ + { 0,1664,0,1201 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 0,1664,0,1201 }, /* 01 (320x350,640x350) */ + { 0,1664,0,1201 }, /* 02 (360x400,720x400) */ + { 0,1664,0,1201 }, /* 03 (720x350) */ + { 0,1664,0,1201 }, /* 04 (640x480x60Hz) */ + { 0,1664,0,1201 }, /* 05 (800x600x60Hz) */ + { 0,1664,0,1201 }, /* 06 (1024x768x60Hz) */ + { 0,1664,0,1201 }, /* 07 (1280x1024x60Hz) */ + { 0,1664,0,1201 }, /* 08 (1400x1050x60Hz) */ + { 0,1664,0,1201 } /* 09 (1600x1200x60Hz) */ +}; + + + +XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesData[]= +{ + { 0, 648, 448, 405, 96, 2 }, /* 00 (320x200,320x400,640x200,640x400) */ + { 0, 648, 448, 355, 96, 2 }, /* 01 (320x350,640x350) */ + { 0, 648, 448, 405, 96, 2 }, /* 02 (360x400,720x400) */ + { 0, 648, 448, 355, 96, 2 }, /* 03 (720x350) */ + { 0, 648, 1, 483, 96, 2 }, /* 04 (640x480x60Hz) */ + { 0, 840, 627, 600, 128, 4 }, /* 05 (800x600x60Hz) */ + { 0,1048, 805, 770, 136, 6 }, /* 06 (1024x768x60Hz) */ + { 0,1328,0,1025, 112, 3 }, /* 07 (1280x1024x60Hz) */ + { 0,1438,0,1051, 112, 3 }, /* 08 (1400x1050x60Hz) ;;[ycchen] 12/19/02 */ + { 0,1664,0,1201, 192, 3 }, /* 09 (1600x1200x60Hz) */ + { 0,1328,0,0771, 112, 6 } /* 0A (1280x768x60Hz) */ +}; + +XGI330_LVDSDataStruct XGI_LVDS1024x768Des_1x75[]= /* ; 1024x768 Full-screen */ +{ + {0,1040,0,769}, /* ; 00 (320x200,320x400,640x200,640x400) */ + {0,1040,0,769}, /* ; 01 (320x350,640x350) */ + {0,1040,0,769}, /* ; 02 (360x400,720x400) */ + {0,1040,0,769}, /* ; 03 (720x350) */ + {0,1040,0,769}, /* ; 04 (640x480x75Hz) */ + {0,1040,0,769}, /* ; 05 (800x600x75Hz) */ + {0,1040,0,769} /* ; 06 (1024x768x75Hz) */ +}; + +XGI330_LVDSDataStruct XGI_LVDS1024x768Des_2x75[]= /* ; 1024x768 center-screen (Enh. Mode) */ +{ + {1142, 856,622,587 }, /* 00 (320x200,320x400,640x200,640x400) */ + {1142, 856,597,562 }, /* 01 (320x350,640x350) */ + {1142, 856,622,587 }, /* 02 (360x400,720x400) */ + {1142, 856,597,562 }, /* 03 (720x350) */ + {1142,1048,722,687 }, /* 04 (640x480x60Hz) */ + {1232, 936,722,687 }, /* 05 (800x600x60Hz) */ + { 0,1048,805,771 } /* 06 (1024x768x60Hz) */ +}; + +XGI330_LVDSDataStruct XGI_LVDS1024x768Des_3x75[]= /* ; 1024x768 center-screen (St.Mode) */ +{ + {320,24,622,587 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + {320,24,597,562 }, /* ; 01 (320x350,640x350) */ + {320,24,622,587 }, /* ; 02 (360x400,720x400) */ + {320,24,597,562 }, /* ; 03 (720x350) */ + {320,24,722,687 } /* ; 04 (640x480x60Hz) */ +}; + +XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_1x75[]= +{ + {0,1296,0,1025}, /* ; 00 (320x200,320x400,640x200,640x400) */ + {0,1296,0,1025}, /* ; 01 (320x350,640x350) */ + {0,1296,0,1025}, /* ; 02 (360x400,720x400) */ + {0,1296,0,1025}, /* ; 03 (720x350) */ + {0,1296,0,1025}, /* ; 04 (640x480x75Hz) */ + {0,1296,0,1025}, /* ; 05 (800x600x75Hz) */ + {0,1296,0,1025}, /* ; 06 (1024x768x75Hz) */ + {0,1296,0,1025} /* ; 07 (1280x1024x75Hz) */ +}; + +/* The Display setting for DE Mode Panel */ +XGI330_LVDSDataStruct XGI_LVDS1280x1024Des_2x75[]= /* [ycchen] 02/18/03 Set DE as default */ +{ + {1368,976,752,711 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + {1368,976,729,688 }, /* ; 01 (320x350,640x350) */ + {1408,976,752,711 }, /* ; 02 (360x400,720x400) */ + {1408,976,729,688 }, /* ; 03 (720x350) */ + {1368,976,794,753 }, /* ; 04 (640x480x75Hz) */ + {1448,1036,854,813}, /* ; 05 (800x600x75Hz) */ + {1560,1168,938,897}, /* ; 06 (1024x768x75Hz) */ + {0,1296,0,1025 } /* ; 07 (1280x1024x75Hz) */ +}; + +XGI330_LCDDataDesStruct2 XGI_LVDSNoScalingDesDatax75[]= /* Scaling LCD 75Hz */ +{ + { 0,648,448,405,96,2 }, /* ; 00 (320x200,320x400,640x200,640x400) */ + { 0,648,448,355,96,2 }, /* ; 01 (320x350,640x350) */ + { 0,729,448,405,108,2 }, /* ; 02 (360x400,720x400) */ + { 0,729,448,355,108,2 }, /* ; 03 (720x350) */ + { 0,656,0,481,64,3 }, /* ; 04 (640x480x75Hz) */ + { 0,816,0,601,80,3 }, /* ; 05 (800x600x75Hz) */ + { 0,1040,0,769,96,3 }, /* ; 06 (1024x768x75Hz) */ + { 0,1296,0,1025,144,3 }, /* ; 07 (1280x1024x75Hz) */ + { 0,1448,0,1051,112,3 }, /* ; 08 (1400x1050x75Hz) ;;[ycchen] 12/19/02 */ + { 0,1664,0,1201,192,3 }, /* ; 09 (1600x1200x75Hz) */ + { 0,1328,0,771,112,6 } /* ; 0A (1280x768x75Hz) */ +}; + +XGI330_LVDSDataStruct XGI330_LVDS640x480Data_1[]= +{ + {800, 449, 800, 449}, + {800, 449, 800, 449}, + {800, 449, 800, 449}, + {800, 449, 800, 449}, + {800, 525, 800, 525}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628}, + {1056, 628,1056, 628} +}; + +XGI330_CHTVDataStruct XGI_CHTVUNTSCData[]= +{ + {840, 600, 840, 600}, + {840, 600, 840, 600}, + {840, 600, 840, 600}, + {840, 600, 840, 600}, + {784, 600, 784, 600}, + {1064, 750,1064, 750} +}; + +XGI330_CHTVDataStruct XGI_CHTVONTSCData[]= +{ + {840, 525, 840, 525}, + {840, 525, 840, 525}, + {840, 525, 840, 525}, + {840, 525, 840, 525}, + {784, 525, 784, 525}, + {1040, 700,1040, 700} +}; + +XGI330_CHTVDataStruct XGI_CHTVUPALData[]= +{ + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {840, 750, 840, 750}, + {936, 836, 936, 836} +}; + +XGI330_CHTVDataStruct XGI_CHTVOPALData[]= +{ + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {1008, 625,1008, 625}, + {840, 625, 840, 625}, + {960, 750, 960, 750} +}; + +XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_H[]= +{ + /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */ + {{ 0x4B,0x27,0x8F,0x32,0x1B,0x00,0x45,0x00 }}, /* 00 (320x) */ + {{ 0x4B,0x27,0x8F,0x2B,0x03,0x00,0x44,0x00 }}, /* 01 (360x) */ + {{ 0x55,0x31,0x99,0x46,0x1D,0x00,0x55,0x00 }}, /* 02 (400x) */ + {{ 0x63,0x3F,0x87,0x4A,0x93,0x00,0x01,0x00 }}, /* 03 (512x) */ + {{ 0x73,0x4F,0x97,0x55,0x86,0x00,0x05,0x00 }}, /* 04 (640x) */ + {{ 0x73,0x4F,0x97,0x55,0x86,0x00,0x05,0x00 }}, /* 05 (720x) */ + {{ 0x87,0x63,0x8B,0x69,0x1A,0x00,0x26,0x00 }}, /* 06 (800x) */ + {{ 0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* 07 (1024x) */ +}; + +XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_H[]= +{ + /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */ + {{ 0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }}, /* 00 (320x) */ + {{ 0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }}, /* 01 (360x) */ + {{ 0x60,0x31,0x84,0x3A,0x88,0x00,0x01,0x00 }}, /* 02 (400x) */ + {{ 0x6E,0x3F,0x92,0x48,0x96,0x00,0x01,0x00 }}, /* 03 (512x) */ + {{ 0x7E,0x4F,0x82,0x58,0x06,0x00,0x06,0x00 }}, /* 04 (640x) */ + {{ 0x7E,0x4F,0x82,0x58,0x06,0x00,0x06,0x00 }}, /* 05 (720x) */ + {{ 0x92,0x63,0x96,0x6C,0x1A,0x00,0x06,0x00 }}, /* 06 (800x) */ + {{ 0xAE,0x7F,0x92,0x88,0x96,0x00,0x02,0x00 }}, /* 07 (1024x) */ + {{ 0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* 08 (1280x) */ +}; + +XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_H[]= +{ + /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */ + {{ 0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }}, /* 00 (320x) */ + {{ 0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }}, /* 01 (360x) */ + {{ 0x63,0x31,0x87,0x3D,0x8E,0x00,0x01,0x00 }}, /* 02 (400x) */ + {{ 0x63,0x3F,0x87,0x45,0x96,0x00,0x01,0x00 }}, /* 03 (512x) */ + {{ 0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }}, /* 04 (640x) */ + {{ 0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }}, /* 05 (720x) */ + {{ 0xA3,0x63,0x87,0x78,0x89,0x00,0x02,0x00 }}, /* 06 (800x) */ + {{ 0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* 07 (1024x) */ +}; + +XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_H[]= +{ + /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */ + {{ 0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }}, /* 00 (320x) */ + {{ 0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }}, /* 01 (360x) */ + {{ 0x7E,0x40,0x84,0x49,0x91,0x00,0x01,0x00 }}, /* 02 (400x) */ + {{ 0x7E,0x47,0x93,0x50,0x9E,0x00,0x01,0x00 }}, /* 03 (512x) */ + {{ 0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }}, /* 04 (640x) */ + {{ 0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }}, /* 05 (720x) */ + {{ 0xCE,0x81,0x94,0x8A,0x98,0x00,0x02,0x00 }}, /* 06 (800x) */ + {{ 0xCE,0x8F,0x82,0x98,0x06,0x00,0x07,0x00 }}, /* 07 (1024x) */ + {{ 0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* 08 (1280x) */ +}; + +XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_1_H[]= +{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */ + {{ 0x47,0x27,0x8B,0x2C,0x1A,0x00,0x05,0x00 }}, /* 00 (320x) */ + {{ 0x47,0x27,0x8B,0x30,0x1E,0x00,0x05,0x00 }}, /* 01 (360x) */ + {{ 0x51,0x31,0x95,0x36,0x04,0x00,0x01,0x00 }}, /* 02 (400x) */ + {{ 0x5F,0x3F,0x83,0x44,0x92,0x00,0x01,0x00 }}, /* 03 (512x) */ + {{ 0x6F,0x4F,0x93,0x54,0x82,0x00,0x05,0x00 }}, /* 04 (640x) */ + {{ 0x6F,0x4F,0x93,0x54,0x82,0x00,0x05,0x00 }}, /* 05 (720x) */ + {{ 0x83,0x63,0x87,0x68,0x16,0x00,0x06,0x00 }}, /* 06 (800x) */ + {{ 0x9F,0x7F,0x83,0x84,0x92,0x00,0x02,0x00 }}, /* 07 (1024x) */ + {{ 0xBF,0x9F,0x83,0xA4,0x12,0x00,0x07,0x00 }}, /* 08 (1280x) */ + {{ 0xCE,0xAE,0x92,0xB3,0x01,0x00,0x03,0x00 }} /* 09 (1400x) */ +}; + +XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11400x1050_2_H[]= +{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */ + {{ 0x76,0x3F,0x83,0x45,0x8C,0x00,0x41,0x00 }}, /* 00 (320x) */ + {{ 0x76,0x3F,0x83,0x45,0x8C,0x00,0x41,0x00 }}, /* 01 (360x) */ + {{ 0x76,0x31,0x9A,0x48,0x9F,0x00,0x41,0x00 }}, /* 02 (400x) */ + {{ 0x76,0x3F,0x9A,0x4F,0x96,0x00,0x41,0x00 }}, /* 03 (512x) */ + {{ 0xCE,0x7E,0x82,0x87,0x9E,0x00,0x02,0x00 }}, /* 04 (640x) */ + {{ 0xCE,0x7E,0x82,0x87,0x9E,0x00,0x02,0x00 }}, /* 05 (720x) */ + {{ 0xCE,0x63,0x92,0x96,0x04,0x00,0x07,0x00 }}, /* 06 (800x) */ + {{ 0xCE,0x7F,0x92,0xA4,0x12,0x00,0x07,0x00 }}, /* 07 (1024x) */ + {{ 0xCE,0x9F,0x92,0xB4,0x02,0x00,0x03,0x00 }}, /* 08 (1280x) */ + {{ 0xCE,0xAE,0x92,0xBC,0x0A,0x00,0x03,0x00 }} /* 09 (1400x) */ +}; + +XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11600x1200_1_H[]= +/* ;302lv channelA [ycchen] 12/05/02 LCDHT=2048 */ +{ /* ; CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */ + {{ 0x5B,0x27,0x9F,0x32,0x0A,0x00,0x01,0x00 }},/* 00 (320x) */ + {{ 0x5B,0x27,0x9F,0x32,0x0A,0x00,0x01,0x00 }},/* 01 (360x) */ + {{ 0x65,0x31,0x89,0x3C,0x94,0x00,0x01,0x00 }},/* 02 (400x) */ + {{ 0x73,0x3F,0x97,0x4A,0x82,0x00,0x05,0x00 }},/* 03 (512x) */ + {{ 0x83,0x4F,0x87,0x51,0x09,0x00,0x06,0x00 }},/* 04 (640x) */ + {{ 0x83,0x4F,0x87,0x51,0x09,0x00,0x06,0x00 }},/* 05 (720x) */ + {{ 0x97,0x63,0x9B,0x65,0x1D,0x00,0x06,0xF0 }},/* 06 (800x) */ + {{ 0xB3,0x7F,0x97,0x81,0x99,0x00,0x02,0x00 }},/* 07 (1024x) */ + {{ 0xD3,0x9F,0x97,0xA1,0x19,0x00,0x07,0x00 }},/* 08 (1280x) */ + {{ 0xE2,0xAE,0x86,0xB9,0x91,0x00,0x03,0x00 }},/* 09 (1400x) */ + {{ 0xFB,0xC7,0x9F,0xC9,0x81,0x00,0x07,0x00 }} /* 0A (1600x) */ +}; + +XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_V[]= +{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */ + {{ 0x97,0x1F,0x60,0x87,0x5D,0x83,0x10 }}, /* 00 (x350) */ + {{ 0xB4,0x1F,0x92,0x89,0x8F,0xB5,0x30 }}, /* 01 (x400) */ + {{ 0x04,0x3E,0xE2,0x89,0xDF,0x05,0x00 }}, /* 02 (x480) */ + {{ 0x7C,0xF0,0x5A,0x8F,0x57,0x7D,0xA0 }}, /* 03 (x600) */ + {{ 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90 }} /* 04 (x768) */ +}; + +XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_V[]= +{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */ + {{ 0x24,0xBB,0x31,0x87,0x5D,0x25,0x30 }}, /* 00 (x350) */ + {{ 0x24,0xBB,0x4A,0x80,0x8F,0x25,0x30 }}, /* 01 (x400) */ + {{ 0x24,0xBB,0x72,0x88,0xDF,0x25,0x30 }}, /* 02 (x480) */ + {{ 0x24,0xF1,0xAE,0x84,0x57,0x25,0xB0 }}, /* 03 (x600) */ + {{ 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90 }} /* 04 (x768) */ +}; + +XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_V[]= +{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */ + {{ 0x86,0x1F,0x5E,0x82,0x5D,0x87,0x00 }}, /* 00 (x350) */ + {{ 0xB8,0x1F,0x90,0x84,0x8F,0xB9,0x30 }}, /* 01 (x400) */ + {{ 0x08,0x3E,0xE0,0x84,0xDF,0x09,0x00 }}, /* 02 (x480) */ + {{ 0x80,0xF0,0x58,0x8C,0x57,0x81,0xA0 }}, /* 03 (x600) */ + {{ 0x28,0xF5,0x00,0x84,0xFF,0x29,0x90 }}, /* 04 (x768) */ + {{ 0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9 }} /* 05 (x1024) */ +}; + +XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_V[]= +{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */ + {{ 0x28,0xD2,0xAF,0x83,0xAE,0xD8,0xA1 }}, /* 00 (x350) */ + {{ 0x28,0xD2,0xC8,0x8C,0xC7,0xF2,0x81 }}, /* 01 (x400) */ + {{ 0x28,0xD2,0xF0,0x84,0xEF,0x1A,0xB1 }}, /* 02 (x480) */ + {{ 0x28,0xDE,0x2C,0x8F,0x2B,0x56,0x91 }}, /* 03 (x600) */ + {{ 0x28,0xDE,0x80,0x83,0x7F,0xAA,0x91 }}, /* 04 (x768) */ + {{ 0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9 }} /* 05 (x1024) */ +}; + +XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_1_V[]= +{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */ + {{ 0x6C,0x1F,0x60,0x84,0x5D,0x6D,0x10 }}, /* 00 (x350) */ + {{ 0x9E,0x1F,0x93,0x86,0x8F,0x9F,0x30 }}, /* 01 (x400) */ + {{ 0xEE,0x1F,0xE2,0x86,0xDF,0xEF,0x10 }}, /* 02 (x480) */ + {{ 0x66,0xF0,0x5A,0x8e,0x57,0x67,0xA0 }}, /* 03 (x600) */ + {{ 0x0E,0xF5,0x02,0x86,0xFF,0x0F,0x90 }}, /* 04 (x768) */ + {{ 0x0E,0x5A,0x02,0x86,0xFF,0x0F,0x89 }}, /* 05 (x1024) */ + {{ 0x28,0x10,0x1A,0x80,0x19,0x29,0x0F }} /* 06 (x1050) */ +}; + +XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11400x1050_2_V[]= +{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */ + {{ 0x28,0x92,0xB6,0x83,0xB5,0xCF,0x81 }}, /* 00 (x350) */ + {{ 0x28,0x92,0xD5,0x82,0xD4,0xEE,0x81 }}, /* 01 (x400) */ + {{ 0x28,0x92,0xFD,0x8A,0xFC,0x16,0xB1 }}, /* 02 (x480) */ + {{ 0x28,0xD4,0x39,0x86,0x57,0x29,0x81 }}, /* 03 (x600) */ + {{ 0x28,0xD4,0x8D,0x9A,0xFF,0x29,0xA1 }}, /* 04 (x768) */ + {{ 0x28,0x5A,0x0D,0x9A,0xFF,0x29,0xA9 }}, /* 05 (x1024) */ + {{ 0x28,0x10,0x1A,0x87,0x19,0x29,0x8F }} /* 06 (x1050) */ +}; + +XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11600x1200_1_V[]= +{ + /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */ + {{ 0xd4,0x1F,0x81,0x84,0x5D,0xd5,0x10 }}, /* 00 (x350) */ + {{ 0x06,0x3e,0xb3,0x86,0x8F,0x07,0x20 }}, /* 01 (x400) */ + {{ 0x56,0xba,0x03,0x86,0xDF,0x57,0x00 }}, /* 02 (x480) */ + {{ 0xce,0xF0,0x7b,0x8e,0x57,0xcf,0xa0 }}, /* 03 (x600) */ + {{ 0x76,0xF5,0x23,0x86,0xFF,0x77,0x90 }}, /* 04 (x768) */ + {{ 0x76,0x5A,0x23,0x86,0xFF,0x77,0x89 }}, /* 05 (x1024) */ + {{ 0x90,0x10,0x1A,0x8E,0x19,0x91,0x2F }}, /* 06 (x1050) */ + {{ 0x26,0x11,0xd3,0x86,0xaF,0x27,0x3f }} /* 07 (x1200) */ +}; + +XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_1_Hx75[]= +{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */ + {{ 0x4B,0x27,0x8F,0x32,0x1B,0x00,0x45,0x00 }},/* ; 00 (320x) */ + {{ 0x4B,0x27,0x8F,0x2B,0x03,0x00,0x44,0x00 }},/* ; 01 (360x) */ + {{ 0x55,0x31,0x99,0x46,0x1D,0x00,0x55,0x00 }},/* ; 02 (400x) */ + {{ 0x63,0x3F,0x87,0x4A,0x93,0x00,0x01,0x00 }},/* ; 03 (512x) */ + {{ 0x6F,0x4F,0x93,0x54,0x80,0x00,0x05,0x00 }},/* ; 04 (640x) */ + {{ 0x6F,0x4F,0x93,0x54,0x80,0x00,0x05,0x00 }},/* ; 05 (720x) */ + {{ 0x83,0x63,0x87,0x68,0x14,0x00,0x26,0x00 }},/* ; 06 (800x) */ + {{ 0x9F,0x7F,0x83,0x85,0x91,0x00,0x02,0x00 }} /* ; 07 (1024x) */ +}; + +XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_1_Vx75[]= +{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A+CR09(5->7) */ + {{ 0x97,0x1F,0x60,0x87,0x5D,0x83,0x10 }},/* ; 00 (x350) */ + {{ 0xB4,0x1F,0x92,0x89,0x8F,0xB5,0x30 }},/* ; 01 (x400) */ + {{ 0xFE,0x1F,0xE0,0x84,0xDF,0xFF,0x10 }},/* ; 02 (x480) */ + {{ 0x76,0xF0,0x58,0x8C,0x57,0x77,0xA0 }},/* ; 03 (x600) */ + {{ 0x1E,0xF5,0x00,0x83,0xFF,0x1F,0x90 }} /* ; 04 (x768) */ +}; + +XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11024x768_2_Hx75[]= +{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */ + {{ 0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }},/* ; 00 (320x) */ + {{ 0x63,0x27,0x87,0x3B,0x8C,0x00,0x01,0x00 }},/* ; 01 (360x) */ + {{ 0x63,0x31,0x87,0x3D,0x8E,0x00,0x01,0x00 }},/* ; 02 (400x) */ + {{ 0x63,0x3F,0x87,0x45,0x96,0x00,0x01,0x00 }},/* ; 03 (512x) */ + {{ 0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }},/* ; 04 (640x) */ + {{ 0xA3,0x4F,0x87,0x6E,0x9F,0x00,0x06,0x00 }},/* ; 05 (720x) */ + {{ 0xA3,0x63,0x87,0x78,0x89,0x00,0x02,0x00 }},/* ; 06 (800x) */ + {{ 0xA3,0x7F,0x87,0x86,0x97,0x00,0x02,0x00 }} /* ; 07 (1024x) */ +}; + +XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11024x768_2_Vx75[]= +{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */ + {{ 0x24,0xBB,0x31,0x87,0x5D,0x25,0x30 }},/* ; 00 (x350) */ + {{ 0x24,0xBB,0x4A,0x80,0x8F,0x25,0x30 }},/* ; 01 (x400) */ + {{ 0x24,0xBB,0x72,0x88,0xDF,0x25,0x30 }},/* ; 02 (x480) */ + {{ 0x24,0xF1,0xAE,0x84,0x57,0x25,0xB0 }},/* ; 03 (x600) */ + {{ 0x24,0xF5,0x02,0x88,0xFF,0x25,0x90 }} /* ; 04 (x768) */ +}; + +XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_1_Hx75[]= +{ /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */ + {{ 0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }},/* ; 00 (320x) */ + {{ 0x56,0x27,0x9A,0x30,0x1E,0x00,0x05,0x00 }},/* ; 01 (360x) */ + {{ 0x60,0x31,0x84,0x3A,0x88,0x00,0x01,0x00 }},/* ; 02 (400x) */ + {{ 0x6E,0x3F,0x92,0x48,0x96,0x00,0x01,0x00 }},/* ; 03 (512x) */ + {{ 0x7E,0x4F,0x82,0x54,0x06,0x00,0x06,0x00 }},/* ; 04 (640x) */ + {{ 0x7E,0x4F,0x82,0x54,0x06,0x00,0x06,0x00 }},/* ; 05 (720x) */ + {{ 0x92,0x63,0x96,0x68,0x1A,0x00,0x06,0x00 }},/* ; 06 (800x) */ + {{ 0xAE,0x7F,0x92,0x84,0x96,0x00,0x02,0x00 }},/* ; 07 (1024x) */ + {{ 0xCE,0x9F,0x92,0xA5,0x17,0x00,0x07,0x00 }} /* ; 08 (1280x) */ +}; + +XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_1_Vx75[]= +{ /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */ + {{ 0x86,0xD1,0xBC,0x80,0xBB,0xE5,0x00 }},/* ; 00 (x350) */ + {{ 0xB8,0x1F,0x90,0x84,0x8F,0xB9,0x30 }},/* ; 01 (x400) */ + {{ 0x08,0x3E,0xE0,0x84,0xDF,0x09,0x00 }},/* ; 02 (x480) */ + {{ 0x80,0xF0,0x58,0x8C,0x57,0x81,0xA0 }},/* ; 03 (x600) */ + {{ 0x28,0xF5,0x00,0x84,0xFF,0x29,0x90 }},/* ; 04 (x768) */ + {{ 0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9 }} /* ; 05 (x1024) */ +}; + +XGI_LVDSCRT1HDataStruct XGI_LVDSCRT11280x1024_2_Hx75[]= +{ + /* CR00,CR02,CR03,CR04,CR05,SR0B,SR0C,SR0E */ + {{ 0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }},/* ; 00 (320x) */ + {{ 0x7E,0x3B,0x9A,0x44,0x12,0x00,0x01,0x00 }},/* ; 01 (360x) */ + {{ 0x7E,0x40,0x84,0x49,0x91,0x00,0x01,0x00 }},/* ; 02 (400x) */ + {{ 0x7E,0x47,0x93,0x50,0x9E,0x00,0x01,0x00 }},/* ; 03 (512x) */ + {{ 0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }},/* ; 04 (640x) */ + {{ 0xCE,0x77,0x8A,0x80,0x8E,0x00,0x02,0x00 }},/* ; 05 (720x) */ + {{ 0xCE,0x81,0x94,0x8A,0x98,0x00,0x02,0x00 }},/* ; 06 (800x) */ + {{ 0xCE,0x8F,0x82,0x98,0x06,0x00,0x07,0x00 }},/* ; 07 (1024x) */ + {{ 0xCE,0x9F,0x92,0xA8,0x16,0x00,0x07,0x00 }} /* ; 08 (1280x) */ +}; + +XGI_LVDSCRT1VDataStruct XGI_LVDSCRT11280x1024_2_Vx75[]= +{ + /* CR06,CR07,CR10,CR11,CR15,CR16,SR0A */ + {{ 0x28,0xD2,0xAF,0x83,0xAE,0xD8,0xA1 }},/* ; 00 (x350) */ + {{ 0x28,0xD2,0xC8,0x8C,0xC7,0xF2,0x81 }},/* ; 01 (x400) */ + {{ 0x28,0xD2,0xF0,0x84,0xEF,0x1A,0xB1 }},/* ; 02 (x480) */ + {{ 0x28,0xDE,0x2C,0x8F,0x2B,0x56,0x91 }},/* ; 03 (x600) */ + {{ 0x28,0xDE,0x80,0x83,0x7F,0xAA,0x91 }},/* ; 04 (x768) */ + {{ 0x28,0x5A,0x13,0x87,0xFF,0x29,0xA9 }} /* ; 05 (x1024) */ +}; + +XGI_LVDSCRT1DataStruct XGI_CHTVCRT1UNTSC[]= +{ + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,0x00 }}, + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,0x00 }}, + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,0x00 }}, + {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e, + 0xd0,0x82,0x5d,0x57,0x00,0x00,0x01,0x00 }}, + {{0x5d,0x4f,0x81,0x53,0x9c,0x56,0xba, + 0x18,0x84,0xdf,0x57,0x00,0x00,0x01,0x00 }}, + {{0x80,0x63,0x84,0x6c,0x17,0xec,0xf0, + 0x90,0x8c,0x57,0xed,0x20,0x00,0x06,0x01 }} +}; + +XGI_LVDSCRT1DataStruct XGI_CHTVCRT1ONTSC[]= +{ + {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e, + 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,0x00 }}, + {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e, + 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,0x00 }}, + {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e, + 0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,0x00 }}, + {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e, + 0xb0,0x8d,0x5d,0x0c,0x00,0x00,0x01,0x00 }}, + {{0x5d,0x4f,0x81,0x56,0x9c,0x0b,0x3e, + 0xe8,0x84,0xdf,0x0c,0x00,0x00,0x01,0x00 }}, + {{0x7d,0x63,0x81,0x6a,0x16,0xba,0xf0, + 0x7f,0x86,0x57,0xbb,0x00,0x00,0x06,0x01 }} +}; + +XGI_LVDSCRT1DataStruct XGI_CHTVCRT1UPAL[]= +{ + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }}, + {{0x64,0x4f,0x88,0x55,0x80,0xec,0xba, + 0x50,0x84,0xdf,0xed,0x00,0x00,0x05,0x00 }}, + {{0x70,0x63,0x94,0x68,0x8d,0x42,0xf1, + 0xc8,0x8c,0x57,0xe9,0x20,0x00,0x05,0x01 }} +}; + +XGI_LVDSCRT1DataStruct XGI_CHTVCRT1OPAL[]= +{ + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,0x00 }}, + {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e, + 0xde,0x81,0x5d,0x70,0x00,0x00,0x05,0x00 }}, + {{0x64,0x4f,0x88,0x55,0x80,0x6f,0xba, + 0x20,0x83,0xdf,0x70,0x00,0x00,0x05,0x00 }}, + {{0x73,0x63,0x97,0x69,0x8e,0xec,0xf0, + 0x90,0x8c,0x57,0xed,0x20,0x00,0x05,0x01 }} +}; + +/*add for new UNIVGABIOS*/ +XGI330_LCDDataTablStruct XGI_LCDDataTable[]= +{ + {Panel1024x768,0x0019,0x0001,0}, /* XGI_ExtLCD1024x768Data */ + {Panel1024x768,0x0019,0x0000,1}, /* XGI_StLCD1024x768Data */ + {Panel1024x768,0x0018,0x0010,2}, /* XGI_CetLCD1024x768Data */ + {Panel1280x1024,0x0019,0x0001,3}, /* XGI_ExtLCD1280x1024Data */ + {Panel1280x1024,0x0019,0x0000,4}, /* XGI_StLCD1280x1024Data */ + {Panel1280x1024,0x0018,0x0010,5}, /* XGI_CetLCD1280x1024Data */ + {Panel1400x1050,0x0019,0x0001,6}, /* XGI_ExtLCD1400x1050Data */ + {Panel1400x1050,0x0019,0x0000,7}, /* XGI_StLCD1400x1050Data */ + {Panel1400x1050,0x0018,0x0010,8}, /* XGI_CetLCD1400x1050Data */ + {Panel1600x1200,0x0019,0x0001,9}, /* XGI_ExtLCD1600x1200Data */ + {Panel1600x1200,0x0019,0x0000,10}, /* XGI_StLCD1600x1200Data */ + {PanelRef60Hz,0x0008,0x0008,11}, /* XGI_NoScalingData */ + {Panel1024x768x75,0x0019,0x0001,12}, /* XGI_ExtLCD1024x768x75Data */ + {Panel1024x768x75,0x0019,0x0000,13}, /* XGI_StLCD1024x768x75Data */ + {Panel1024x768x75,0x0018,0x0010,14}, /* XGI_CetLCD1024x768x75Data */ + {Panel1280x1024x75,0x0019,0x0001,15}, /* XGI_ExtLCD1280x1024x75Data */ + {Panel1280x1024x75,0x0019,0x0000,16}, /* XGI_StLCD1280x1024x75Data */ + {Panel1280x1024x75,0x0018,0x0010,17}, /* XGI_CetLCD1280x1024x75Data */ + {PanelRef75Hz,0x0008,0x0008,18}, /* XGI_NoScalingDatax75 */ + {0xFF,0x0000,0x0000,0} /* End of table */ +}; + +XGI330_LCDDataTablStruct XGI_LCDDesDataTable[]= +{ + {Panel1024x768,0x0019,0x0001,0}, /* XGI_ExtLCDDes1024x768Data */ + {Panel1024x768,0x0019,0x0000,1}, /* XGI_StLCDDes1024x768Data */ + {Panel1024x768,0x0018,0x0010,2}, /* XGI_CetLCDDes1024x768Data */ + {Panel1280x1024,0x0019,0x0001,3}, /* XGI_ExtLCDDes1280x1024Data */ + {Panel1280x1024,0x0019,0x0000,4}, /* XGI_StLCDDes1280x1024Data */ + {Panel1280x1024,0x0018,0x0010,5}, /* XGI_CetLCDDes1280x1024Data */ + {Panel1400x1050,0x0019,0x0001,6}, /* XGI_ExtLCDDes1400x1050Data */ + {Panel1400x1050,0x0019,0x0000,7}, /* XGI_StLCDDes1400x1050Data */ + {Panel1400x1050,0x0418,0x0010,8}, /* XGI_CetLCDDes1400x1050Data */ + {Panel1400x1050,0x0418,0x0410,9}, /* XGI_CetLCDDes1400x1050Data2 */ + {Panel1600x1200,0x0019,0x0001,10}, /* XGI_ExtLCDDes1600x1200Data */ + {Panel1600x1200,0x0019,0x0000,11}, /* XGI_StLCDDes1600x1200Data */ + {PanelRef60Hz,0x0008,0x0008,12}, /* XGI_NoScalingDesData */ + {Panel1024x768x75,0x0019,0x0001,13}, /* XGI_ExtLCDDes1024x768x75Data */ + {Panel1024x768x75,0x0019,0x0000,14}, /* XGI_StLCDDes1024x768x75Data */ + {Panel1024x768x75,0x0018,0x0010,15}, /* XGI_CetLCDDes1024x768x75Data */ + {Panel1280x1024x75,0x0019,0x0001,16}, /* XGI_ExtLCDDes1280x1024x75Data */ + {Panel1280x1024x75,0x0019,0x0000,17}, /* XGI_StLCDDes1280x1024x75Data */ + {Panel1280x1024x75,0x0018,0x0010,18}, /* XGI_CetLCDDes1280x1024x75Data */ + {PanelRef75Hz,0x0008,0x0008,19}, /* XGI_NoScalingDesDatax75 */ + {0xFF,0x0000,0x0000,0} +}; + +XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_H[]= +{ + {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDSCRT11024x768_1_H */ + {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDSCRT11024x768_2_H */ + {Panel1280x1024,0x0018,0x0000,2}, /* XGI_LVDSCRT11280x1024_1_H */ + {Panel1280x1024,0x0018,0x0010,3}, /* XGI_LVDSCRT11280x1024_2_H */ + {Panel1400x1050,0x0018,0x0000,4}, /* XGI_LVDSCRT11400x1050_1_H */ + {Panel1400x1050,0x0018,0x0010,5}, /* XGI_LVDSCRT11400x1050_2_H */ + {Panel1600x1200,0x0018,0x0000,6}, /* XGI_LVDSCRT11600x1200_1_H */ + {Panel1024x768x75,0x0018,0x0000,7}, /* XGI_LVDSCRT11024x768_1_Hx75 */ + {Panel1024x768x75,0x0018,0x0010,8}, /* XGI_LVDSCRT11024x768_2_Hx75 */ + {Panel1280x1024x75,0x0018,0x0000,9}, /* XGI_LVDSCRT11280x1024_1_Hx75 */ + {Panel1280x1024x75,0x0018,0x0010,10}, /* XGI_LVDSCRT11280x1024_2_Hx75 */ + {0xFF,0x0000,0x0000,0} +}; + +XGI330_LCDDataTablStruct XGI_EPLLCDCRT1Ptr_V[]= +{ + {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDSCRT11024x768_1_V */ + {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDSCRT11024x768_2_V */ + {Panel1280x1024,0x0018,0x0000,2}, /* XGI_LVDSCRT11280x1024_1_V */ + {Panel1280x1024,0x0018,0x0010,3}, /* XGI_LVDSCRT11280x1024_2_V */ + {Panel1400x1050,0x0018,0x0000,4}, /* XGI_LVDSCRT11400x1050_1_V */ + {Panel1400x1050,0x0018,0x0010,5}, /* XGI_LVDSCRT11400x1050_2_V */ + {Panel1600x1200,0x0018,0x0000,6}, /* XGI_LVDSCRT11600x1200_1_V */ + {Panel1024x768x75,0x0018,0x0000,7}, /* XGI_LVDSCRT11024x768_1_Vx75 */ + {Panel1024x768x75,0x0018,0x0010,8}, /* XGI_LVDSCRT11024x768_2_Vx75 */ + {Panel1280x1024x75,0x0018,0x0000,9}, /* XGI_LVDSCRT11280x1024_1_Vx75 */ + {Panel1280x1024x75,0x0018,0x0010,10}, /* XGI_LVDSCRT11280x1024_2_Vx75 */ + {0xFF,0x0000,0x0000,0} +}; + +XGI330_LCDDataTablStruct XGI_EPLLCDDataPtr[]= +{ + {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDS1024x768Data_1 */ + {Panel1024x768,0x0018,0x0010,1}, /* XGI_LVDS1024x768Data_2 */ + {Panel1280x1024,0x0018,0x0000,2}, /* XGI_LVDS1280x1024Data_1 */ + {Panel1280x1024,0x0018,0x0010,3}, /* XGI_LVDS1280x1024Data_2 */ + {Panel1400x1050,0x0018,0x0000,4}, /* XGI_LVDS1400x1050Data_1 */ + {Panel1400x1050,0x0018,0x0010,5}, /* XGI_LVDS1400x1050Data_2 */ + {Panel1600x1200,0x0018,0x0000,6}, /* XGI_LVDS1600x1200Data_1 */ + {PanelRef60Hz,0x0008,0x0008,7}, /* XGI_LVDSNoScalingData */ + {Panel1024x768x75,0x0018,0x0000,8}, /* XGI_LVDS1024x768Data_1x75 */ + {Panel1024x768x75,0x0018,0x0010,9}, /* XGI_LVDS1024x768Data_2x75 */ + {Panel1280x1024x75,0x0018,0x0000,10}, /* XGI_LVDS1280x1024Data_1x75 */ + {Panel1280x1024x75,0x0018,0x0010,11}, /* XGI_LVDS1280x1024Data_2x75 */ + {PanelRef75Hz,0x0008,0x0008,12}, /* XGI_LVDSNoScalingDatax75 */ + {0xFF,0x0000,0x0000,0} +}; + +XGI330_LCDDataTablStruct XGI_EPLLCDDesDataPtr[]= +{ + {Panel1024x768,0x0018,0x0000,0}, /* XGI_LVDS1024x768Des_1 */ + {Panel1024x768,0x0618,0x0410,1}, /* XGI_LVDS1024x768Des_3 */ + {Panel1024x768,0x0018,0x0010,2}, /* XGI_LVDS1024x768Des_2 */ + {Panel1280x1024,0x0018,0x0000,3}, /* XGI_LVDS1280x1024Des_1 */ + {Panel1280x1024,0x0018,0x0010,4}, /* XGI_LVDS1280x1024Des_2 */ + {Panel1400x1050,0x0018,0x0000,5}, /* XGI_LVDS1400x1050Des_1 */ + {Panel1400x1050,0x0018,0x0010,6}, /* XGI_LVDS1400x1050Des_2 */ + {Panel1600x1200,0x0018,0x0000,7}, /* XGI_LVDS1600x1200Des_1 */ + {PanelRef60Hz,0x0008,0x0008,8}, /* XGI_LVDSNoScalingDesData */ + {Panel1024x768x75,0x0018,0x0000,9}, /* XGI_LVDS1024x768Des_1x75 */ + {Panel1024x768x75,0x0618,0x0410,10}, /* XGI_LVDS1024x768Des_3x75 */ + {Panel1024x768x75,0x0018,0x0010,11}, /* XGI_LVDS1024x768Des_2x75 */ + {Panel1280x1024x75,0x0018,0x0000,12}, /* XGI_LVDS1280x1024Des_1x75 */ + {Panel1280x1024x75,0x0018,0x0010,13}, /* XGI_LVDS1280x1024Des_2x75 */ + {PanelRef75Hz,0x0008,0x0008,14}, /* XGI_LVDSNoScalingDesDatax75 */ + {0xFF,0x0000,0x0000,0} +}; + +XGI330_LCDDataTablStruct XGI_EPLCHLCDRegPtr[]= +{ + {Panel1024x768,0x0000,0x0000,0}, /* XGI_CH7017LV1024x768 */ + {Panel1400x1050,0x0000,0x0000,1}, /* XGI_CH7017LV1400x1050 */ + {0xFF,0x0000,0x0000,0} +}; + +XGI330_TVDataTablStruct XGI_TVDataTable[]= +{ + {0x09E1,0x0001,0}, /* XGI_ExtPALData */ + {0x09E1,0x0000,1}, /* XGI_ExtNTSCData */ + {0x09E1,0x0801,2}, /* XGI_StPALData */ + {0x09E1,0x0800,3}, /* XGI_StNTSCData */ + {0x49E0,0x0100,4}, /* XGI_ExtHiTVData */ + {0x49E0,0x4100,5}, /* XGI_St2HiTVData */ + {0x49E0,0x4900,13}, /* XGI_St1HiTVData */ + {0x09E0,0x0020,6}, /* XGI_ExtYPbPr525iData */ + {0x09E0,0x0040,7}, /* XGI_ExtYPbPr525pData */ + {0x09E0,0x0080,8}, /* XGI_ExtYPbPr750pData */ + {0x09E0,0x0820,9}, /* XGI_StYPbPr525iData */ + {0x09E0,0x0840,10}, /* XGI_StYPbPr525pData */ + {0x09E0,0x0880,11}, /* XGI_StYPbPr750pData */ + {0xffff,0x0000,12} /* END */ +}; + +USHORT TVLenList[]= +{ + LVDSCRT1Len_H, + LVDSCRT1Len_V, + LVDSDataLen, + 0, + TVDataLen, + 0, + 0, + CHTVRegLen +} ; + +/* Chrontel 7017 TV CRT1 Timing List */ +XGI330_TVDataTablStruct XGI_EPLCHTVCRT1Ptr[]= +{ + {0x0011,0x0000,0}, /* XGI_CHTVCRT1UNTSC */ + {0x0011,0x0010,1}, /* XGI_CHTVCRT1ONTSC */ + {0x0011,0x0001,2}, /* XGI_CHTVCRT1UPAL */ + {0x0011,0x0011,3}, /* XGI_CHTVCRT1OPAL */ + {0xFFFF,0x0000,4} +}; + +/* ;;Chrontel 7017 TV Timing List */ +XGI330_TVDataTablStruct XGI_EPLCHTVDataPtr[]= +{ + {0x0011,0x0000,0}, /* XGI_CHTVUNTSCData */ + {0x0011,0x0010,1}, /* XGI_CHTVONTSCData */ + {0x0011,0x0001,2}, /* XGI_CHTVUPALData */ + {0x0011,0x0011,3}, /* XGI_CHTVOPALData */ + {0xFFFF,0x0000,4} +}; + +/* ;;Chrontel 7017 TV Reg. List */ +XGI330_TVDataTablStruct XGI_EPLCHTVRegPtr[]= +{ + {0x0011,0x0000,0}, /* XGI_CHTVRegUNTSC */ + {0x0011,0x0010,1}, /* XGI_CHTVRegONTSC */ + {0x0011,0x0001,2}, /* XGI_CHTVRegUPAL */ + {0x0011,0x0011,3}, /* XGI_CHTVRegOPAL */ + {0xFFFF,0x0000,4} +}; + +USHORT LCDLenList[]= +{ + LVDSCRT1Len_H, + LVDSCRT1Len_V, + LVDSDataLen, + LCDDesDataLen, + LCDDataLen, + LCDDesDataLen, + 0, + LCDDesDataLen, + LCDDesDataLen, + 0 +} ; + +XGI330_LCDCapStruct XGI660_LCDDLCapList[]= /* 660, Dual link */ +{ +/* LCDCap1024x768 */ + {Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65, + 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, +/* LCDCap1280x1024 */ + {Panel1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2, + 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1400x1050 */ + {Panel1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2, + 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1600x1200 */ + {Panel1600x1200, LCDDualLink+DefaultLCDCap, LCDToFull, 0x053, 0xC0, 0x03, VCLK162, + 0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1024x768x75 */ + {Panel1024x768x75, DefaultLCDCap, 0, 0x014, 0x60, 0, VCLK78_75, + 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, +/* LCDCap1280x1024x75 */ + {Panel1280x1024x75, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x053, 0x90, 0x03, VCLK135_5, + 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCapDefault */ + {0xFF, DefaultLCDCap, 0, 0x053, 0x88, 0x06, VCLK65, + 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10} +}; + +XGI330_LCDCapStruct XGI_LCDDLCapList[]= /* Dual link only */ +{ +/* LCDCap1024x768 */ + {Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65, + 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, +/* LCDCap1280x1024 */ + {Panel1280x1024, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2, + 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1400x1050 */ + {Panel1400x1050, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2, + 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1600x1200 */ + {Panel1600x1200, LCDDualLink+DefaultLCDCap, LCDToFull, 0x012, 0xC0, 0x03, VCLK162, + 0x43, 0x22, 0x70, 0x24, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1024x768x75 */ + {Panel1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75, + 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, +/* LCDCap1280x1024x75 */ + {Panel1280x1024x75, LCDDualLink+DefaultLCDCap, StLCDBToA, 0x012, 0x90, 0x03, VCLK135_5, + 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCapDefault */ + {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65, + 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10} +}; + +XGI330_LCDCapStruct XGI660_LCDCapList[]= +{ +/* LCDCap1024x768 */ + {Panel1024x768, DefaultLCDCap, 0, 0x014, 0x88, 0x06, VCLK65, + 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, +/* LCDCap1280x1024 */ + {Panel1280x1024, DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2, + 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1400x1050 */ + {Panel1400x1050, DefaultLCDCap, StLCDBToA, 0x053, 0x70, 0x03, VCLK108_2, + 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1600x1200 */ + {Panel1600x1200, DefaultLCDCap, LCDToFull, 0x053, 0xC0, 0x03, VCLK162, + 0x5A, 0x23, 0x5A, 0x23, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1024x768x75 */ + {Panel1024x768x75, DefaultLCDCap, 0, 0x014, 0x60, 0, VCLK78_75, + 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, +/* LCDCap1280x1024x75 */ + {Panel1280x1024x75,+DefaultLCDCap, StLCDBToA, 0x053, 0x90, 0x03, VCLK135_5, + 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCapDefault */ + {0xFF, DefaultLCDCap, 0, 0x053, 0x88, 0x06, VCLK65, + 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10} +}; + +XGI330_LCDCapStruct XGI_LCDCapList[]= +{ +/* LCDCap1024x768 */ + {Panel1024x768, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65, + 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, +/* LCDCap1280x1024 */ + {Panel1280x1024, DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2, + 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1400x1050 */ + {Panel1400x1050, DefaultLCDCap, StLCDBToA, 0x012, 0x70, 0x03, VCLK108_2, + 0x70, 0x44, 0xF8, 0x2F, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1600x1200 */ + {Panel1600x1200, DefaultLCDCap, LCDToFull, 0x012, 0xC0, 0x03, VCLK162, + 0x5A, 0x23, 0x5A, 0x23, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCap1024x768x75 */ + {Panel1024x768x75, DefaultLCDCap, 0, 0x012, 0x60, 0, VCLK78_75, + 0x2B, 0x61, 0x2B, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10}, +/* LCDCap1280x1024x75 */ + {Panel1280x1024x75, DefaultLCDCap, StLCDBToA, 0x012, 0x90, 0x03, VCLK135_5, + 0x54, 0x42, 0x4A, 0x61, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x30, 0x10}, +/* LCDCapDefault */ + {0xFF, DefaultLCDCap, 0, 0x012, 0x88, 0x06, VCLK65, + 0x6C, 0xC3, 0x35, 0x62, 0x02, 0x14, 0x0A, 0x02, 0x00, + 0x30, 0x10, 0x5A, 0x10, 0x10, 0x0A, 0xC0, 0x28, 0x10} +}; + +XGI21_LVDSCapStruct XGI21_LCDCapList[]= +{ + {DisableLCD24bpp + LCDPolarity, + 2160,1250,1600,1200, 64, 1, 192, 3, + 0x70,0x24,0x20,0x04,0x0A,0x02,0xC8 + }, + {DisableLCD24bpp + LCDPolarity, + 1688,1066,1280,1024, 48, 1, 112, 3, + 0x70,0x44,0x20,0x04,0x0A,0x02,0xC8 + }, + {DisableLCD24bpp + LCDPolarity + (LCDPolarity << 8), + 1344, 806,1024, 768, 24, 3, 136, 6, + 0x6C,0x65,0x20,0x04,0x0A,0x02,0xC8 + }, + {DisableLCD24bpp + LCDPolarity, + 1056, 628, 800, 600, 40, 1, 128, 4, + 0x42,0xE2,0x20,0x14,0x0A,0x02,0x00 + }, + {DisableLCD24bpp + LCDPolarity, + 928, 525, 800, 480, 40, 13, 48, 3, + 0x52,0xC5,0x20,0x14,0x0A,0x02,0x00 + }, + {DisableLCD24bpp + LCDPolarity + (LCDPolarity << 8), + 800, 525, 640, 480, 16, 10, 96, 2, + 0x1B,0xE1,0x20,0x04,0x0A,0x02,0xC8 + } + +}; + +XGI_Ext2Struct XGI330_RefIndex[]= +{ +{Support32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175, 0x00,0x10,0x59, 320, 200},/* 00 */ +{Support32Bpp + SupportAllCRT2 + SyncPN, RES320x200, VCLK25_175, 0x00,0x10,0x00, 320, 400},/* 01 */ +{Support32Bpp + SupportAllCRT2 + SyncNN, RES320x240, VCLK25_175, 0x04,0x20,0x50, 320, 240},/* 02 */ +{Support32Bpp + SupportAllCRT2 + SyncPP, RES400x300, VCLK40, 0x05,0x32,0x51, 400, 300},/* 03 */ +{Support32Bpp + NoSupportTV + SyncNN + SupportTV1024, RES512x384, VCLK65, 0x06,0x43,0x52, 512, 384},/* 04 */ +{Support32Bpp + SupportAllCRT2 + SyncPN, RES640x400, VCLK25_175, 0x00,0x14,0x2f, 640, 400},/* 05 */ +{Support32Bpp + SupportAllCRT2 + SyncNN, RES640x480x60, VCLK25_175, 0x04,0x24,0x2e, 640, 480},/* 06 640x480x60Hz (LCD 640x480x60z) */ +{Support32Bpp + NoSupportHiVisionTV + SyncNN, RES640x480x72, VCLK31_5, 0x04,0x24,0x2e, 640, 480},/* 07 640x480x72Hz (LCD 640x480x70Hz) */ +{Support32Bpp + NoSupportHiVisionTV + SyncNN, RES640x480x75, VCLK31_5, 0x47,0x24,0x2e, 640, 480},/* 08 640x480x75Hz (LCD 640x480x75Hz) */ +{Support32Bpp + SupportRAMDAC2 + SyncNN, RES640x480x85, VCLK36, 0x8A,0x24,0x2e, 640, 480},/* 09 640x480x85Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x100, VCLK43_163, 0x00,0x24,0x2e, 640, 480},/* 0a 640x480x100Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x120, VCLK52_406, 0x00,0x24,0x2e, 640, 480},/* 0b 640x480x120Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPN, RES640x480x160, VCLK72_852, 0x00,0x24,0x2e, 640, 480},/* 0c 640x480x160Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncNN, RES640x480x200, VCLK86_6, 0x00,0x24,0x2e, 640, 480},/* 0d 640x480x200Hz */ +{Support32Bpp + NoSupportLCD + SyncPP, RES800x600x56, VCLK36, 0x05,0x36,0x6a, 800, 600},/* 0e 800x600x56Hz */ +{Support32Bpp + NoSupportTV + SyncPP, RES800x600x60, VCLK40, 0x05,0x36,0x6a, 800, 600},/* 0f 800x600x60Hz (LCD 800x600x60Hz) */ +{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES800x600x72, VCLK50, 0x48,0x36,0x6a, 800, 600},/* 10 800x600x72Hz (LCD 800x600x70Hz) */ +{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES800x600x75, VCLK49_5, 0x8B,0x36,0x6a, 800, 600},/* 11 800x600x75Hz (LCD 800x600x75Hz) */ +{Support32Bpp + SupportRAMDAC2 + SyncPP, RES800x600x85, VCLK56_25, 0x00,0x36,0x6a, 800, 600},/* 12 800x600x85Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x100, VCLK68_179, 0x00,0x36,0x6a, 800, 600},/* 13 800x600x100Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x120, VCLK83_95, 0x00,0x36,0x6a, 800, 600},/* 14 800x600x120Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPN, RES800x600x160, VCLK116_406,0x00,0x36,0x6a, 800, 600},/* 15 800x600x160Hz */ +{Support32Bpp + InterlaceMode + SyncPP, RES1024x768x43, VCLK44_9, 0x00,0x47,0x37,1024, 768},/* 16 1024x768x43Hz */ +{Support32Bpp + NoSupportTV + SyncNN + SupportTV1024, RES1024x768x60, VCLK65, 0x06,0x47,0x37,1024, 768},/* 17 1024x768x60Hz (LCD 1024x768x60Hz) */ +{Support32Bpp + NoSupportHiVisionTV + SyncNN, RES1024x768x70, VCLK75, 0x49,0x47,0x37,1024, 768},/* 18 1024x768x70Hz (LCD 1024x768x70Hz) */ +{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES1024x768x75, VCLK78_75, 0x00,0x47,0x37,1024, 768},/* 19 1024x768x75Hz (LCD 1024x768x75Hz) */ +{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1024x768x85, VCLK94_5, 0x8C,0x47,0x37,1024, 768},/* 1a 1024x768x85Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x100, VCLK113_309,0x00,0x47,0x37,1024, 768},/* 1b 1024x768x100Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x120, VCLK139_054,0x00,0x47,0x37,1024, 768},/* 1c 1024x768x120Hz */ +{Support32Bpp + SupportLCD + SyncPP, RES1280x960x60, VCLK108_2, 0x08,0x58,0x7b,1280, 960},/* 1d 1280x960x60Hz */ +{Support32Bpp + InterlaceMode + SyncPP, RES1280x1024x43, VCLK78_75, 0x00,0x58,0x3a,1280,1024},/* 1e 1280x1024x43Hz */ +{Support32Bpp + NoSupportTV + SyncPP, RES1280x1024x60, VCLK108_2, 0x07,0x58,0x3a,1280,1024},/* 1f 1280x1024x60Hz (LCD 1280x1024x60Hz) */ +{Support32Bpp + NoSupportTV + SyncPP, RES1280x1024x75, VCLK135_5, 0x00,0x58,0x3a,1280,1024},/* 20 1280x1024x75Hz (LCD 1280x1024x75Hz) */ +{Support32Bpp + SyncPP, RES1280x1024x85, VCLK157_5, 0x00,0x58,0x3a,1280,1024},/* 21 1280x1024x85Hz */ +{Support32Bpp + SupportLCD + SyncPP + SupportCRT2in301C, RES1600x1200x60, VCLK162, 0x09,0x7A,0x3c,1600,1200},/* 22 1600x1200x60Hz */ +{Support32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x65, VCLK175, 0x00,0x69,0x3c,1600,1200},/* 23 1600x1200x65Hz */ +{Support32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x70, VCLK189, 0x00,0x69,0x3c,1600,1200},/* 24 1600x1200x70Hz */ +{Support32Bpp + SyncPP + SupportCRT2in301C, RES1600x1200x75, VCLK202_5, 0x00,0x69,0x3c,1600,1200},/* 25 1600x1200x75Hz */ +{Support32Bpp + SyncPP, RES1600x1200x85, VCLK229_5, 0x00,0x69,0x3c,1600,1200},/* 26 1600x1200x85Hz */ +{Support32Bpp + SyncPP, RES1600x1200x100,VCLK269_655,0x00,0x69,0x3c,1600,1200},/* 27 1600x1200x100Hz */ +{Support32Bpp + SyncPP, RES1600x1200x120,VCLK323_586,0x00,0x69,0x3c,1600,1200},/* 28 1600x1200x120Hz */ +{Support32Bpp + SupportLCD + SyncNP, RES1920x1440x60, VCLK234, 0x00,0x00,0x68,1920,1440},/* 29 1920x1440x60Hz */ +{Support32Bpp + SyncPN, RES1920x1440x65, VCLK254_817,0x00,0x00,0x68,1920,1440},/* 2a 1920x1440x65Hz */ +{Support32Bpp + SyncPN, RES1920x1440x70, VCLK277_015,0x00,0x00,0x68,1920,1440},/* 2b 1920x1440x70Hz */ +{Support32Bpp + SyncPN, RES1920x1440x75, VCLK291_132,0x00,0x00,0x68,1920,1440},/* 2c 1920x1440x75Hz */ +{Support32Bpp + SyncPN, RES1920x1440x85, VCLK330_615,0x00,0x00,0x68,1920,1440},/* 2d 1920x1440x85Hz */ +{Support16Bpp + SyncPN, RES1920x1440x100,VCLK388_631,0x00,0x00,0x68,1920,1440},/* 2e 1920x1440x100Hz */ +{Support32Bpp + SupportLCD + SyncPN, RES2048x1536x60, VCLK266_952,0x00,0x00,0x6c,2048,1536},/* 2f 2048x1536x60Hz */ +{Support32Bpp + SyncPN, RES2048x1536x65, VCLK291_766,0x00,0x00,0x6c,2048,1536},/* 30 2048x1536x65Hz */ +{Support32Bpp + SyncPN, RES2048x1536x70, VCLK315_195,0x00,0x00,0x6c,2048,1536},/* 31 2048x1536x70Hz */ +{Support32Bpp + SyncPN, RES2048x1536x75, VCLK340_477,0x00,0x00,0x6c,2048,1536},/* 32 2048x1536x75Hz */ +{Support16Bpp + SyncPN, RES2048x1536x85, VCLK375_847,0x00,0x00,0x6c,2048,1536},/* 33 2048x1536x85Hz */ +{Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + SyncPP + SupportYPbPr, RES800x480x60, VCLK39_77, 0x08,0x00,0x70, 800, 480},/* 34 800x480x60Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPP, RES800x480x75, VCLK49_5, 0x08,0x00,0x70, 800, 480},/* 35 800x480x75Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPP, RES800x480x85, VCLK56_25, 0x08,0x00,0x70, 800, 480},/* 36 800x480x85Hz */ +{Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + SyncPP + SupportYPbPr, RES1024x576x60, VCLK65, 0x09,0x00,0x71,1024, 576},/* 37 1024x576x60Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1024x576x75, VCLK78_75, 0x09,0x00,0x71,1024, 576},/* 38 1024x576x75Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1024x576x85, VCLK94_5, 0x09,0x00,0x71,1024, 576},/* 39 1024x576x85Hz */ +{Support32Bpp + SupportHiVisionTV + SupportRAMDAC2 + SyncPP + SupportYPbPr, RES1280x720x60, VCLK108_2, 0x0A,0x00,0x75,1280, 720},/* 3a 1280x720x60Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1280x720x75, VCLK135_5, 0x0A,0x00,0x75,1280, 720},/* 3b 1280x720x75Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1280x720x85, VCLK157_5, 0x0A,0x00,0x75,1280, 720},/* 3c 1280x720x85Hz */ +{Support32Bpp + SupportTV + SyncNN, RES720x480x60, VCLK28_322, 0x06,0x00,0x31, 720, 480},/* 3d 720x480x60Hz */ +{Support32Bpp + SupportTV + SyncPP, RES720x576x56, VCLK36, 0x06,0x00,0x32, 720, 576},/* 3e 720x576x56Hz */ +{Support32Bpp + InterlaceMode + NoSupportLCD + SyncPP, RES856x480x79I, VCLK35_2, 0x00,0x00,0x00, 856, 480},/* 3f 856x480x79I */ +{Support32Bpp + NoSupportLCD + SyncNN, RES856x480x60, VCLK35_2, 0x00,0x00,0x00, 856, 480},/* 40 856x480x60Hz */ +{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES1280x768x60, VCLK79_411, 0x08,0x48,0x23,1280, 768},/* 41 1280x768x60Hz */ +{Support32Bpp + NoSupportHiVisionTV + SyncPP, RES1400x1050x60, VCLK122_61, 0x08,0x69,0x26,1400,1050},/* 42 1400x1050x60Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1152x864x60, VCLK80_350, 0x37,0x00,0x20,1152, 864},/* 43 1152x864x60Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPP, RES1152x864x75, VCLK107_385,0x37,0x00,0x20,1152, 864},/* 44 1152x864x75Hz */ +{Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x75, VCLK125_999,0x3A,0x88,0x7b,1280, 960},/* 45 1280x960x75Hz */ +{Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x85, VCLK148_5, 0x0A,0x88,0x7b,1280, 960},/* 46 1280x960x85Hz */ +{Support32Bpp + SupportLCD + SupportRAMDAC2 + SyncPP, RES1280x960x120, VCLK217_325,0x3A,0x88,0x7b,1280, 960},/* 47 1280x960x120Hz */ +{Support32Bpp + SupportRAMDAC2 + SyncPN, RES1024x768x160, VCLK139_054,0x30,0x47,0x37,1024, 768},/* 48 1024x768x160Hz */ +}; + + + +XGI330_VCLKDataStruct XGI330_VCLKData[]= +{ + { 0x1b,0xe1, 25}, /* 0x0 */ + { 0x4e,0xe4, 28}, /* 0x1 */ + { 0x57,0xe4, 31}, /* 0x2 */ + { 0xc3,0xc8, 36}, /* 0x3 */ + { 0x42,0xe2, 40}, /* 0x4 */ + { 0xfe,0xcd, 43}, /* 0x5 */ + { 0x5d,0xc4, 44}, /* 0x6 */ + { 0x52,0xe2, 49}, /* 0x7 */ + { 0x53,0xe2, 50}, /* 0x8 */ + { 0x74,0x67, 52}, /* 0x9 */ + { 0x6d,0x66, 56}, /* 0xa */ + { 0x6c,0xc3, 65}, /* 0xb */ + { 0x46,0x44, 67}, /* 0xc */ + { 0xb1,0x46, 68}, /* 0xd */ + { 0xd3,0x4a, 72}, /* 0xe */ + { 0x29,0x61, 75}, /* 0xf */ + { 0x6e,0x46, 76}, /* 0x10 */ + { 0x2b,0x61, 78}, /* 0x11 */ + { 0x31,0x42, 79}, /* 0x12 */ + { 0xab,0x44, 83}, /* 0x13 */ + { 0x46,0x25, 84}, /* 0x14 */ + { 0x78,0x29, 86}, /* 0x15 */ + { 0x62,0x44, 94}, /* 0x16 */ + { 0x2b,0x41,104}, /* 0x17 */ + { 0x3a,0x23,105}, /* 0x18 */ + { 0x70,0x44,108}, /* 0x19 */ + { 0x3c,0x23,109}, /* 0x1a */ + { 0x5e,0x43,113}, /* 0x1b */ + { 0xbc,0x44,116}, /* 0x1c */ + { 0xe0,0x46,132}, /* 0x1d */ + { 0x54,0x42,135}, /* 0x1e */ + { 0xea,0x2a,139}, /* 0x1f */ + { 0x41,0x22,157}, /* 0x20 */ + { 0x70,0x24,162}, /* 0x21 */ + { 0x30,0x21,175}, /* 0x22 */ + { 0x4e,0x22,189}, /* 0x23 */ + { 0xde,0x26,194}, /* 0x24 */ + { 0x62,0x06,202}, /* 0x25 */ + { 0x3f,0x03,229}, /* 0x26 */ + { 0xb8,0x06,234}, /* 0x27 */ + { 0x34,0x02,253}, /* 0x28 */ + { 0x58,0x04,255}, /* 0x29 */ + { 0x24,0x01,265}, /* 0x2a */ + { 0x9b,0x02,267}, /* 0x2b */ + { 0x70,0x05,270}, /* 0x2c */ + { 0x25,0x01,272}, /* 0x2d */ + { 0x9c,0x02,277}, /* 0x2e */ + { 0x27,0x01,286}, /* 0x2f */ + { 0x3c,0x02,291}, /* 0x30 */ + { 0xef,0x0a,292}, /* 0x31 */ + { 0xf6,0x0a,310}, /* 0x32 */ + { 0x95,0x01,315}, /* 0x33 */ + { 0xf0,0x09,324}, /* 0x34 */ + { 0xfe,0x0a,331}, /* 0x35 */ + { 0xf3,0x09,332}, /* 0x36 */ + { 0xea,0x08,340}, /* 0x37 */ + { 0xe8,0x07,376}, /* 0x38 */ + { 0xde,0x06,389}, /* 0x39 */ + { 0x52,0x2a, 54}, /* 0x3a */ + { 0x52,0x6a, 27}, /* 0x3b */ + { 0x62,0x24, 70}, /* 0x3c */ + { 0x62,0x64, 70}, /* 0x3d */ + { 0xa8,0x4c, 30}, /* 0x3e */ + { 0x20,0x26, 33}, /* 0x3f */ + { 0x31,0xc2, 39}, /* 0x40 */ + { 0x60,0x36, 30}, /* 0x41 */ + { 0x40,0x4A, 28}, /* 0x42 */ + { 0x9F,0x46, 44}, /* 0x43 */ + { 0x97,0x2C, 26}, /* 0x44 */ + { 0x44,0xE4, 25}, /* 0x45 */ + { 0x7E,0x32, 47}, /* 0x46 */ + { 0x08,0x24, 31}, /* 0x47 */ + { 0x97,0x2c, 26}, /* 0x48 */ + { 0xCE,0x3c, 39}, /* 0x49 */ + { 0x52,0x4A, 36}, /* 0x4a */ + { 0x2C,0x61, 95}, /* 0x4b */ + { 0x78,0x27,108}, /* 0x4c */ + { 0x66,0x43,123}, /* 0x4d */ + { 0x2c,0x61, 80}, /* 0x4e */ + { 0x3b,0x61,108} /* 0x4f */ +}; + +XGI_VBVCLKDataStruct XGI330_VBVCLKData[]= +{ + { 0x1b,0xe1, 25}, /* 0x0 */ + { 0x4e,0xe4, 28}, /* 0x1 */ + { 0x57,0xe4, 31}, /* 0x2 */ + { 0xc3,0xc8, 36}, /* 0x3 */ + { 0x42,0x47, 40}, /* 0x4 */ + { 0xfe,0xcd, 43}, /* 0x5 */ + { 0x5d,0xc4, 44}, /* 0x6 */ + { 0x52,0x47, 49}, /* 0x7 */ + { 0x53,0x47, 50}, /* 0x8 */ + { 0x74,0x67, 52}, /* 0x9 */ + { 0x6d,0x66, 56}, /* 0xa */ + { 0x5a,0x64, 65}, /* 0xb */ + { 0x46,0x44, 67}, /* 0xc */ + { 0xb1,0x46, 68}, /* 0xd */ + { 0xd3,0x4a, 72}, /* 0xe */ + { 0x29,0x61, 75}, /* 0xf */ + { 0x6d,0x46, 75}, /* 0x10 */ + { 0x41,0x43, 78}, /* 0x11 */ + { 0x31,0x42, 79}, /* 0x12 */ + { 0xab,0x44, 83}, /* 0x13 */ + { 0x46,0x25, 84}, /* 0x14 */ + { 0x78,0x29, 86}, /* 0x15 */ + { 0x62,0x44, 94}, /* 0x16 */ + { 0x2b,0x22,104}, /* 0x17 */ + { 0x49,0x24,105}, /* 0x18 */ + { 0xf8,0x2f,108}, /* 0x19 */ + { 0x3c,0x23,109}, /* 0x1a */ + { 0x5e,0x43,113}, /* 0x1b */ + { 0xbc,0x44,116}, /* 0x1c */ + { 0xe0,0x46,132}, /* 0x1d */ + { 0xd4,0x28,135}, /* 0x1e */ + { 0xea,0x2a,139}, /* 0x1f */ + { 0x41,0x22,157}, /* 0x20 */ + { 0x70,0x24,162}, /* 0x21 */ + { 0x30,0x21,175}, /* 0x22 */ + { 0x4e,0x22,189}, /* 0x23 */ + { 0xde,0x26,194}, /* 0x24 */ + { 0x70,0x07,202}, /* 0x25 */ + { 0x3f,0x03,229}, /* 0x26 */ + { 0xb8,0x06,234}, /* 0x27 */ + { 0x34,0x02,253}, /* 0x28 */ + { 0x58,0x04,255}, /* 0x29 */ + { 0x24,0x01,265}, /* 0x2a */ + { 0x9b,0x02,267}, /* 0x2b */ + { 0x70,0x05,270}, /* 0x2c */ + { 0x25,0x01,272}, /* 0x2d */ + { 0x9c,0x02,277}, /* 0x2e */ + { 0x27,0x01,286}, /* 0x2f */ + { 0x3c,0x02,291}, /* 0x30 */ + { 0xef,0x0a,292}, /* 0x31 */ + { 0xf6,0x0a,310}, /* 0x32 */ + { 0x95,0x01,315}, /* 0x33 */ + { 0xf0,0x09,324}, /* 0x34 */ + { 0xfe,0x0a,331}, /* 0x35 */ + { 0xf3,0x09,332}, /* 0x36 */ + { 0xea,0x08,340}, /* 0x37 */ + { 0xe8,0x07,376}, /* 0x38 */ + { 0xde,0x06,389}, /* 0x39 */ + { 0x52,0x2a, 54}, /* 0x3a */ + { 0x52,0x6a, 27}, /* 0x3b */ + { 0x62,0x24, 70}, /* 0x3c */ + { 0x62,0x64, 70}, /* 0x3d */ + { 0xa8,0x4c, 30}, /* 0x3e */ + { 0x20,0x26, 33}, /* 0x3f */ + { 0x31,0xc2, 39}, /* 0x40 */ + { 0x2e,0x48, 25}, /* 0x41 */ + { 0x24,0x46, 25}, /* 0x42 */ + { 0x26,0x64, 28}, /* 0x43 */ + { 0x37,0x64, 40}, /* 0x44 */ + { 0xa1,0x42,108}, /* 0x45 */ + { 0x37,0x61,100}, /* 0x46 */ + { 0x78,0x27,108}, /* 0x47 */ + { 0x5e,0x64,68}, /* 0x48 chiawen for fuj1280x768*/ + { 0x70,0x44,108}, /* 0x49 chiawen for 1400x1050*/ +}; + +UCHAR XGI330_ScreenOffset[]={ 0x14,0x19,0x20,0x28,0x32,0x40,0x50,0x64,0x78,0x80,0x2d,0x35,0x57,0x48 }; + +XGI_StResInfoStruct XGI330_StResInfo[]= +{ + { 640,400}, + { 640,350}, + { 720,400}, + { 720,350}, + { 640,480} +}; + +XGI_ModeResInfoStruct XGI330_ModeResInfo[]= +{ + { 320, 200, 8, 8}, + { 320, 240, 8, 8}, + { 320, 400, 8, 8}, + { 400, 300, 8, 8}, + { 512, 384, 8, 8}, + { 640, 400, 8,16}, + { 640, 480, 8,16}, + { 800, 600, 8,16}, + { 1024, 768, 8,16}, + { 1280,1024, 8,16}, + { 1600,1200, 8,16}, + { 1920,1440, 8,16}, + { 2048,1536, 8,16}, + { 720, 480, 8,16}, + { 720, 576, 8,16}, + { 1280, 960, 8,16}, + { 800, 480, 8,16}, + { 1024, 576, 8,16}, + { 1280, 720, 8,16}, + { 856, 480, 8,16}, + { 1280, 768, 8,16}, + { 1400,1050, 8,16}, + { 1152, 864, 8,16} +}; + +UCHAR XGI330_OutputSelect =0x40; +UCHAR XGI330_SoftSetting = 0x30; +UCHAR XGI330_SR07=0x18; +UCHAR XGI330New_SR15[8][8]={ +{0x0,0x4,0x60,0x60}, +{0xf,0xf,0xf,0xf}, +{0xba,0xba,0xba,0xba}, +{0xa9,0xa9,0xac,0xac}, +{0xa0,0xa0,0xa0,0xa8}, +{0x0,0x0,0x2,0x2}, +{0x30,0x30,0x40,0x40}, +{0x0,0xa5,0xfb,0xf6} +}; + +UCHAR XGI330New_CR40[5][8]={ +{0x77,0x77,0x44,0x44}, +{0x77,0x77,0x44,0x44}, +{0x0,0x0,0x0,0x0}, +{0x5b,0x5b,0xab,0xab}, +{0x0,0x0,0xf0,0xf8} +}; + +UCHAR XGI330_CR49[]={0xaa,0x88}; +UCHAR XGI330_SR1F=0x0; +UCHAR XGI330_SR21=0xa3; +UCHAR XGI330_650_SR21=0xa7; +UCHAR XGI330_SR22=0xfb; +UCHAR XGI330_SR23=0xf6; +UCHAR XGI330_SR24=0xd; + +UCHAR XGI660_SR21=0xa3;/* 2003.0312 */ +UCHAR XGI660_SR22=0xf3;/* 2003.0312 */ + +UCHAR XGI330_LVDS_SR32=0x00; /* ynlai for 650 LVDS */ +UCHAR XGI330_LVDS_SR33=0x00; /* chiawen for 650 LVDS */ +UCHAR XGI330_650_SR31=0x40; +UCHAR XGI330_650_SR33=0x04; +UCHAR XGI330_CRT2Data_1_2 = 0x0; +UCHAR XGI330_CRT2Data_4_D = 0x0; +UCHAR XGI330_CRT2Data_4_E = 0x0; +UCHAR XGI330_CRT2Data_4_10 = 0x80; +USHORT XGI330_RGBSenseData = 0xd1; +USHORT XGI330_VideoSenseData = 0xb9; +USHORT XGI330_YCSenseData = 0xb3; +USHORT XGI330_RGBSenseData2 = 0x0190; /*301b*/ +USHORT XGI330_VideoSenseData2 = 0x0110; +USHORT XGI330_YCSenseData2 = 0x016B; +UCHAR XGI330_NTSCPhase[] = {0x21,0xed,0x8a,0x8}; +UCHAR XGI330_PALPhase[] = {0x2a,0x5,0xd3,0x0}; +UCHAR XGI330_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6};/*301b*/ +UCHAR XGI330_PALPhase2[] = {0x2a,0x09,0x86,0xe9}; +UCHAR XGI330_PALMPhase[] = {0x21,0xE4,0x2E,0x9B}; /*palmn*/ +UCHAR XGI330_PALNPhase[] = {0x21,0xF4,0x3E,0xBA}; +UCHAR XG40_I2CDefinition = 0x00 ; +UCHAR XG20_CR97 = 0x10 ; + +UCHAR XG21_DVOSetting = 0x00 ; +UCHAR XG21_CR2E = 0x00 ; +UCHAR XG21_CR2F = 0x00 ; +UCHAR XG21_CR46 = 0x00 ; +UCHAR XG21_CR47 = 0x00 ; + +UCHAR XG27_CR97 = 0xC1 ; +UCHAR XG27_SR36 = 0x30 ; +UCHAR XG27_CR8F = 0x0C ; +UCHAR XG27_CRD0[] = {0,0,0,0,0,0,0,0x82,0x00,0x66,0x01,0x00} ; +UCHAR XG27_CRDE[] = {0,0} ; +UCHAR XG27_SR40 = 0x04 ; +UCHAR XG27_SR41 = 0x00 ; + +UCHAR XGI330_CHTVVCLKUNTSC[]={0x00 }; + +UCHAR XGI330_CHTVVCLKONTSC[]={0x00 }; + +UCHAR XGI330_CHTVVCLKUPAL[]={0x00 }; + +UCHAR XGI330_CHTVVCLKOPAL[]={0x00 }; + +UCHAR XGI7007_CHTVVCLKUNTSC[]={CH7007TVVCLK30_2, + CH7007TVVCLK30_2, + CH7007TVVCLK30_2, + CH7007TVVCLK30_2, + CH7007TVVCLK28_1, + CH7007TVVCLK47_8 + }; + +UCHAR XGI7007_CHTVVCLKONTSC[]={CH7007TVVCLK26_4, + CH7007TVVCLK26_4, + CH7007TVVCLK26_4, + CH7007TVVCLK26_4, + CH7007TVVCLK24_6, + CH7007TVVCLK43_6 + }; + +UCHAR XGI7007_CHTVVCLKUPAL[]={CH7007TVVCLK31_5, + CH7007TVVCLK31_5, + CH7007TVVCLK31_5, + CH7007TVVCLK31_5, + CH7007TVVCLK26_2, + CH7007TVVCLK39 + }; + +UCHAR XGI7007_CHTVVCLKOPAL[]={CH7007TVVCLK31_5, + CH7007TVVCLK31_5, + CH7007TVVCLK31_5, + CH7007TVVCLK31_5, + CH7007TVVCLK26_2, + CH7007TVVCLK36 + }; + +XGI330_VCLKDataStruct XGI_CH7007VCLKData[]= +{ + { 0x60,0x36,30}, /* 0 30.2 MHZ */ + { 0x40,0x4A,28}, /* 1 28.19 MHZ */ + { 0x9F,0x46,44}, /* 2 43.6 MHZ */ + { 0x97,0x2C,26}, /* 3 26.4 MHZ */ + { 0x44,0xE4,25}, /* 4 24.6 MHZ */ + { 0x7E,0x32,47}, /* 5 47.832 MHZ */ + { 0x8A,0x24,31}, /* 6 31.5 MHZ */ + { 0x97,0x2C,26}, /* 7 26.2 MHZ */ + { 0xCE,0x3C,39}, /* 8 39 MHZ */ + { 0x52,0x4A,36}, /* 9 36 MHZ */ + { 0xFF,0x00,0 } /* End mark */ +}; + +XGI330_VCLKDataStruct XGI_VCLKData[]= +{ + /* SR2B,SR2C,SR2D */ + { 0x1B,0xE1,25 },/* 00 (25.175MHz) */ + + { 0x4E,0xE4,28 },/* 01 (28.322MHz) */ + + { 0x57,0xE4,31 },/* 02 (31.500MHz) */ + + { 0xC3,0xC8,36 },/* 03 (36.000MHz) */ + + { 0x42,0xE2,40 },/* 04 (40.000MHz) */ + + { 0xFE,0xCD,43 },/* 05 (43.163MHz) */ + + { 0x5D,0xC4,44 },/* 06 (44.900MHz) */ + + { 0x52,0xE2,49 },/* 07 (49.500MHz) */ + + { 0x53,0xE2,50 },/* 08 (50.000MHz) */ + + { 0x74,0x67,52 },/* 09 (52.406MHz) */ + + { 0x6D,0x66,56 },/* 0A (56.250MHz) */ + + { 0x6C,0xC3,65 },/* 0B (65.000MHz) */ + + { 0x46,0x44,67 },/* 0C (67.765MHz) */ + + { 0xB1,0x46,68 },/* 0D (68.179MHz) */ + + { 0xD3,0x4A,72 },/* 0E (72.852MHz) */ + + { 0x29,0x61,75 },/* 0F (75.000MHz) */ + + { 0x6E,0x46,76 },/* 10 (75.800MHz) */ + + { 0x2B,0x61,78 },/* 11 (78.750MHz) */ + + { 0x31,0x42,79 },/* 12 (79.411MHz) */ + + { 0xAB,0x44,83 },/* 13 (83.950MHz) */ + + { 0x46,0x25,84 },/* 14 (84.800MHz) */ + + { 0x78,0x29,86 },/* 15 (86.600MHz) */ + + { 0x62,0x44,94 },/* 16 (94.500MHz) */ + + { 0x2B,0x41,104 },/* 17 (104.998MHz) */ + + { 0x3A,0x23,105 },/* 18 (105.882MHz) */ + + { 0x70,0x44,108 },/* 19 (107.862MHz) */ + + { 0x3C,0x23,109 },/* 1A (109.175MHz) */ + + { 0x5E,0x43,113 },/* 1B (113.309MHz) */ + + { 0xBC,0x44,116 },/* 1C (116.406MHz) */ + + { 0xE0,0x46,132 },/* 1D (132.258MHz) */ + + { 0x54,0x42,135 },/* 1E (135.500MHz) */ + + { 0x9C,0x22,139 },/* 1F (139.275MHz) */ + + { 0x41,0x22,157 },/* 20 (157.500MHz) */ + + { 0x70,0x24,162 },/* 21 (161.793MHz) */ + + { 0x30,0x21,175 },/* 22 (175.000MHz) */ + + { 0x4E,0x22,189 },/* 23 (188.520MHz) */ + + { 0xDE,0x26,194 },/* 24 (194.400MHz) */ + + { 0x62,0x06,202 },/* 25 (202.500MHz) */ + + { 0x3F,0x03,229 },/* 26 (229.500MHz) */ + + { 0xB8,0x06,234 },/* 27 (233.178MHz) */ + + { 0x34,0x02,253 },/* 28 (252.699MHz) */ + + { 0x58,0x04,255 },/* 29 (254.817MHz) */ + + { 0x24,0x01,265 },/* 2A (265.728MHz) */ + + { 0x9B,0x02,267 },/* 2B (266.952MHz) */ + + { 0x70,0x05,270 },/* 2C (269.65567MHz) */ + + { 0x25,0x01,272 },/* 2D (272.04199MHz) */ + + { 0x9C,0x02,277 },/* 2E (277.015MHz) */ + + { 0x27,0x01,286 },/* 2F (286.359985MHz) */ + + { 0xB3,0x04,291 },/* 30 (291.13266MHz) */ + + { 0xBC,0x05,292 },/* 31 (291.766MHz) */ + + { 0xF6,0x0A,310 },/* 32 (309.789459MHz) */ + + { 0x95,0x01,315 },/* 33 (315.195MHz) */ + + { 0xF0,0x09,324 },/* 34 (323.586792MHz) */ + + { 0xFE,0x0A,331 },/* 35 (330.615631MHz) */ + + { 0xF3,0x09,332 },/* 36 (332.177612MHz) */ + + { 0x5E,0x03,340 },/* 37 (340.477MHz) */ + + { 0xE8,0x07,376 },/* 38 (375.847504MHz) */ + + { 0xDE, 0x06,389 },/* 39 (388.631439MHz) */ + + { 0x52,0x2A,54 },/* 3A (54.000MHz) */ + + { 0x52,0x6A,27 },/* 3B (27.000MHz) */ + + { 0x62,0x24,70 },/* 3C (70.874991MHz) */ + + { 0x62,0x64,70 },/* 3D (70.1048912MHz) */ + + { 0xA8,0x4C,30 },/* 3E (30.1048912MHz) */ + + { 0x20,0x26,33 },/* 3F (33.7499957MHz) */ + + { 0x31,0xc2,39 },/* 40 (39.77MHz) */ + + { 0x11,0x21,30 },/* 41 (30MHz) }// NTSC 1024X768 */ + + { 0x2E,0x48,25 },/* 42 (25.175MHz) }// ScaleLCD */ + + { 0x24,0x46,25 },/* 43 (25.175MHz) */ + + { 0x26,0x64,28 },/* 44 (28.322MHz) */ + + { 0x37,0x64,40 },/* 45 (40.000MHz) */ + + { 0xA1,0x42,108 },/* 46 (95.000MHz) }// QVGA */ + + { 0x37,0x61,100 },/* 47 (100.00MHz) */ + + { 0x78,0x27,108 },/* 48 (108.200MHz) */ + + { 0xBF,0xC8,35 },/* 49 (35.2MHz) */ + + { 0x66,0x43,123 },/* 4A (122.61Mhz) */ + + { 0x2C,0x61,80 },/* 4B (80.350Mhz) */ + + { 0x3B,0x61,108 },/* 4C (107.385Mhz) */ + + +/* { 0x60,0x36,30 },// 4D (30.200MHz) }// No use + + { 0x60,0x36,30 },// 4E (30.200MHz) }// No use + + { 0x60,0x36,30 },// 4F (30.200MHz) }// No use + + { 0x60,0x36,30 },// 50 (30.200MHz) }// CHTV + + { 0x40,0x4A,28 },// 51 (28.190MHz) + + { 0x9F,0x46,44 },// 52 (43.600MHz) + + { 0x97,0x2C,26 },// 53 (26.400MHz) + + { 0x44,0xE4,25 },// 54 (24.600MHz) + + { 0x7E,0x32,47 },// 55 (47.832MHz) + + { 0x8A,0x24,31 },// 56 (31.500MHz) + + { 0x97,0x2C,26 },// 57 (26.200MHz) + + { 0xCE,0x3C,39 },// 58 (39.000MHz) + + { 0x52,0x4A,36 },// 59 (36.000MHz) + +*/ + { 0x69,0x61,191 }, /* 4D (190.96MHz ) */ + { 0x4F,0x22,192 }, /* 4E (192.069MHz) */ + { 0x28,0x26,322 }, /* 4F (322.273MHz) */ + { 0x5C,0x6B,27 }, /* 50 (27.74HMz) */ + { 0x57,0x24,126 }, /* 51 (125.999MHz) */ + { 0x5C,0x42,148 }, /* 52 (148.5MHz) */ + { 0x42,0x61,120 }, /* 53 (120.839MHz) */ + { 0x62,0x61,178 }, /* 54 (178.992MHz) */ + { 0x59,0x22,217 }, /* 55 (217.325MHz) */ + { 0x29,0x01,300 }, /* 56 (299.505Mhz) */ + { 0x52,0x63,74 }, /* 57 (74.25MHz) */ + + + { 0xFF,0x00,0 }/* End mark */ + } ; + +XGI330_VCLKDataStruct XGI_VBVCLKData[]= +{ + { 0x1B,0xE1,25 },/* 00 (25.175MHz) */ + + { 0x4E,0xE4,28 },/* 01 (28.322MHz) */ + + { 0x57,0xE4,31 },/* 02 (31.500MHz) */ + + { 0xC3,0xC8,36 },/* 03 (36.000MHz) */ + + { 0x42,0x47,40 },/* 04 (40.000MHz) */ + + { 0xFE,0xCD,43 },/* 05 (43.163MHz) */ + + { 0x5D,0xC4,44 },/* 06 (44.900MHz) */ + + { 0x52,0x47,49 },/* 07 (49.500MHz) */ + + { 0x53,0x47,50 },/* 08 (50.000MHz) */ + + { 0x74,0x67,52 },/* 09 (52.406MHz) */ + + { 0x6D,0x66,56 },/* 0A (56.250MHz) */ + + { 0x35,0x62,65 },/* 0B (65.000MHz) */ + + { 0x46,0x44,67 },/* 0C (67.765MHz) */ + + { 0xB1,0x46,68 },/* 0D (68.179MHz) */ + + { 0xD3,0x4A,72 },/* 0E (72.852MHz) */ + + { 0x29,0x61,75 },/* 0F (75.000MHz) */ + + { 0x6D,0x46,75 },/* 10 (75.800MHz) */ + + { 0x41,0x43,78 },/* 11 (78.750MHz) */ + + { 0x31,0x42,79 },/* 12 (79.411MHz) */ + + { 0xAB,0x44,83 },/* 13 (83.950MHz) */ + + { 0x46,0x25,84 },/* 14 (84.800MHz) */ + + { 0x78,0x29,86 },/* 15 (86.600MHz) */ + + { 0x62,0x44,94 },/* 16 (94.500MHz) */ + + { 0x2B,0x22,104 },/* 17 (104.998MHz) */ + + { 0x49,0x24,105 },/* 18 (105.882MHz) */ + + { 0xF8,0x2F,108 },/* 19 (108.279MHz) */ + + { 0x3C,0x23,109 },/* 1A (109.175MHz) */ + + { 0x5E,0x43,113 },/* 1B (113.309MHz) */ + + { 0xBC,0x44,116 },/* 1C (116.406MHz) */ + + { 0xE0,0x46,132 },/* 1D (132.258MHz) */ + + { 0xD4,0x28,135 },/* 1E (135.220MHz) */ + + { 0xEA,0x2A,139 },/* 1F (139.275MHz) */ + + { 0x41,0x22,157 },/* 20 (157.500MHz) */ + + { 0x70,0x24,162 },/* 21 (161.793MHz) */ + + { 0x30,0x21,175 },/* 22 (175.000MHz) */ + + { 0x4E,0x22,189 },/* 23 (188.520MHz) */ + + { 0xDE,0x26,194 },/* 24 (194.400MHz) */ + + { 0x70,0x07,202 },/* 25 (202.500MHz) */ + + { 0x3F,0x03,229 },/* 26 (229.500MHz) */ + + { 0xB8,0x06,234 },/* 27 (233.178MHz) */ + + { 0x34,0x02,253 },/* 28 (252.699997 MHz) */ + + { 0x58,0x04,255 },/* 29 (254.817MHz) */ + + { 0x24,0x01,265 },/* 2A (265.728MHz) */ + + { 0x9B,0x02,267 },/* 2B (266.952MHz) */ + + { 0x70,0x05,270 },/* 2C (269.65567 MHz) */ + + { 0x25,0x01,272 },/* 2D (272.041992 MHz) */ + + { 0x9C,0x02,277 },/* 2E (277.015MHz) */ + + { 0x27,0x01,286 },/* 2F (286.359985 MHz) */ + + { 0x3C,0x02,291 },/* 30 (291.132660 MHz) */ + + { 0xEF,0x0A,292 },/* 31 (291.766MHz) */ + + { 0xF6,0x0A,310 },/* 32 (309.789459 MHz) */ + + { 0x95,0x01,315 },/* 33 (315.195MHz) */ + + { 0xF0,0x09,324 },/* 34 (323.586792 MHz) */ + + { 0xFE,0x0A,331 },/* 35 (330.615631 MHz) */ + + { 0xF3,0x09,332 },/* 36 (332.177612 MHz) */ + + { 0xEA,0x08,340 },/* 37 (340.477MHz) */ + + { 0xE8,0x07,376 },/* 38 (375.847504 MHz) */ + + { 0xDE,0x06,389 },/* 39 (388.631439 MHz) */ + + { 0x52,0x2A,54 },/* 3A (54.000MHz) */ + + { 0x52,0x6A,27 },/* 3B (27.000MHz) */ + + + { 0x62,0x24,70 },/* 3C (70.874991MHz) */ + + + { 0x62,0x64,70 },/* 3D (70.1048912MHz) */ + + { 0xA8,0x4C,30 },/* 3E (30.1048912MHz) */ + + { 0x20,0x26,33 },/* 3F (33.7499957MHz) */ + + { 0x31,0xc2,39 },/* 40 (39.77MHz) */ + + { 0x11,0x21,30 },/* 41 (30MHz) }// NTSC 1024X768 */ + + { 0x2E,0x48,25 },/* 42 (25.175MHz) }// ScaleLCD */ + + { 0x24,0x46,25 },/* 43 (25.175MHz) */ + + { 0x26,0x64,28 },/* 44 (28.322MHz) */ + + { 0x37,0x64,40 },/* 45 (40.000MHz) */ + + { 0xA1,0x42,108 },/* 46 (95.000MHz) }// QVGA */ + + { 0x37,0x61,100 },/* 47 (100.00MHz) */ + + { 0x78,0x27,108 },/* 48 (108.200MHz) */ + + { 0xBF,0xC8,35 },/* 49 (35.2MHz) */ + + { 0x66,0x43,123 },/* 4A (122.61Mhz) */ + + { 0x2C,0x61,80 },/* 4B (80.350Mhz) */ + + { 0x3B,0x61,108 },/* 4C (107.385Mhz) */ + +/* + { 0x60,0x36,30 },// 4D (30.200MHz) }// No use + + { 0x60,0x36,30 },// 4E (30.200MHz) }// No use + + { 0x60,0x36,30 },// 4F (30.200MHz) }// No use + + { 0x60,0x36,30 },// 50 (30.200MHz) }// CHTV + + { 0x40,0x4A,28 },// 51 (28.190MHz) + + { 0x9F,0x46,44 },// 52 (43.600MHz) + + { 0x97,0x2C,26 },// 53 (26.400MHz) + + { 0x44,0xE4,25 },// 54 (24.600MHz) + + { 0x7E,0x32,47 },// 55 (47.832MHz) + + { 0x8A,0x24,31 },// 56 (31.500MHz) + + { 0x97,0x2C,26 },// 57 (26.200MHz) + + { 0xCE,0x3C,39 },// 58 (39.000MHz) + + { 0x52,0x4A,36 },// 59 (36.000MHz) +*/ + { 0x69,0x61,191 }, /* 4D (190.96MHz ) */ + { 0x4F,0x22,192 }, /* 4E (192.069MHz) */ + { 0x28,0x26,322 }, /* 4F (322.273MHz) */ + { 0x5C,0x6B,27 }, /* 50 (27.74HMz) */ + { 0x57,0x24,126 }, /* 51 (125.999MHz) */ + { 0x5C,0x42,148 }, /* 52 (148.5MHz) */ + { 0x42,0x61,120 }, /* 53 (120.839MHz) */ + { 0x62,0x61,178 }, /* 54 (178.992MHz) */ + { 0x59,0x22,217 }, /* 55 (217.325MHz) */ + { 0x29,0x01,300 }, /* 56 (299.505Mhz) */ + { 0x52,0x63,74 }, /* 57 (74.25MHz) */ + + + { 0xFF,0x00,0 } /* End mark */ +}; + +UCHAR XGI660_TVDelayList[]= +{ + 0x44, /* ; 0 ExtNTSCDelay */ + 0x44, /* ; 1 StNTSCDelay */ + 0x44, /* ; 2 ExtPALDelay */ + 0x44, /* ; 3 StPALDelay */ + 0x44, /* ; 4 ExtHiTVDelay(1080i) */ + 0x44, /* ; 5 StHiTVDelay(1080i) */ + 0x44, /* ; 6 ExtYPbPrDelay(525i) */ + 0x44, /* ; 7 StYPbPrDealy(525i) */ + 0x44, /* ; 8 ExtYPbPrDelay(525p) */ + 0x44, /* ; 9 StYPbPrDealy(525p) */ + 0x44, /* ; A ExtYPbPrDelay(750p) */ + 0x44 /* ; B StYPbPrDealy(750p) */ +}; + +UCHAR XGI660_TVDelayList2[]= +{ + 0x44, /* ; 0 ExtNTSCDelay */ + 0x44, /* ; 1 StNTSCDelay */ + 0x44, /* ; 2 ExtPALDelay */ + 0x44, /* ; 3 StPALDelay */ + 0x44, /* ; 4 ExtHiTVDelay */ + 0x44, /* ; 5 StHiTVDelay */ + 0x44, /* ; 6 ExtYPbPrDelay(525i) */ + 0x44, /* ; 7 StYPbPrDealy(525i) */ + 0x44, /* ; 8 ExtYPbPrDelay(525p) */ + 0x44, /* ; 9 StYPbPrDealy(525p) */ + 0x44, /* ; A ExtYPbPrDelay(750p) */ + 0x44 /* ; B StYPbPrDealy(750p) */ +}; + +UCHAR XGI301TVDelayList[]= +{ + 0x22, /* ; 0 ExtNTSCDelay */ + 0x22, /* ; 1 StNTSCDelay */ + 0x22, /* ; 2 ExtPALDelay */ + 0x22, /* ; 3 StPALDelay */ + 0x88, /* ; 4 ExtHiTVDelay(1080i) */ + 0xBB, /* ; 5 StHiTVDelay(1080i) */ + 0x22, /* ; 6 ExtYPbPrDelay(525i) */ + 0x22, /* ; 7 StYPbPrDealy(525i) */ + 0x22, /* ; 8 ExtYPbPrDelay(525p) */ + 0x22, /* ; 9 StYPbPrDealy(525p) */ + 0x22, /* ; A ExtYPbPrDelay(750p) */ + 0x22 /* B StYPbPrDealy(750p) */ +}; + +UCHAR XGI301TVDelayList2[]= +{ + 0x22, /* ; 0 ExtNTSCDelay */ + 0x22, /* ; 1 StNTSCDelay */ + 0x22, /* ; 2 ExtPALDelay */ + 0x22, /* ; 3 StPALDelay */ + 0x22, /* ; 4 ExtHiTVDelay */ + 0x22, /* ; 5 StHiTVDelay */ + 0x22, /* ; 6 ExtYPbPrDelay(525i) */ + 0x22, /* ; 7 StYPbPrDealy(525i) */ + 0x22, /* ; 8 ExtYPbPrDelay(525p) */ + 0x22, /* ; 9 StYPbPrDealy(525p) */ + 0x22, /* ; A ExtYPbPrDelay(750p) */ + 0x22 /* ; B StYPbPrDealy(750p) */ +}; + + +UCHAR TVAntiFlickList[]= +{/* NTSCAntiFlicker */ + 0x04, /* ; 0 Adaptive */ + 0x00, /* ; 1 new anti-flicker ? */ +/* PALAntiFlicker */ + 0x04, /* ; 0 Adaptive */ + 0x08, /* ; 1 new anti-flicker ? */ +/* HiTVAntiFlicker */ + 0x04, /* ; 0 ? */ + 0x00 /* ; 1 new anti-flicker ? */ +}; + + +UCHAR TVEdgeList[]= +{ + 0x00, /* ; 0 NTSC No Edge enhance */ + 0x04, /* ; 1 NTSC Adaptive Edge enhance */ + 0x00, /* ; 0 PAL No Edge enhance */ + 0x04, /* ; 1 PAL Adaptive Edge enhance */ + 0x00, /* ; 0 HiTV */ + 0x00 /* ; 1 HiTV */ +}; + +ULONG TVPhaseList[]= +{ 0x08BAED21, /* ; 0 NTSC phase */ + 0x00E3052A, /* ; 1 PAL phase */ + 0x9B2EE421, /* ; 2 PAL-M phase */ + 0xBA3EF421, /* ; 3 PAL-N phase */ + 0xA7A28B1E, /* ; 4 NTSC 1024x768 */ + 0xE00A831E, /* ; 5 PAL-M 1024x768 */ + 0x00000000, /* ; 6 reserved */ + 0x00000000, /* ; 7 reserved */ + 0xD67BF021, /* ; 8 NTSC phase */ + 0xE986092A, /* ; 9 PAL phase */ + 0xA4EFE621, /* ; A PAL-M phase */ + 0x4694F621, /* ; B PAL-N phase */ + 0x8BDE711C, /* ; C NTSC 1024x768 */ + 0xE00A831E /* ; D PAL-M 1024x768 */ +}; + +UCHAR NTSCYFilter1[]= +{ + 0x00,0xF4,0x10,0x38 ,/* 0 : 320x text mode */ + 0x00,0xF4,0x10,0x38 ,/* 1 : 360x text mode */ + 0xEB,0x04,0x25,0x18 ,/* 2 : 640x text mode */ + 0xF1,0x04,0x1F,0x18 ,/* 3 : 720x text mode */ + 0x00,0xF4,0x10,0x38 ,/* 4 : 320x gra. mode */ + 0xEB,0x04,0x25,0x18 ,/* 5 : 640x gra. mode */ + 0xEB,0x15,0x25,0xF6 /* 6 : 800x gra. mode */ +}; + +UCHAR PALYFilter1[]= +{ + 0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */ + 0x00,0xF4,0x10,0x38 ,/* 1 : 360x text mode */ + 0xF1,0xF7,0x1F,0x32 ,/* 2 : 640x text mode */ + 0xF3,0x00,0x1D,0x20 ,/* 3 : 720x text mode */ + 0x00,0xF4,0x10,0x38 ,/* 4 : 320x gra. mode */ + 0xF1,0xF7,0x1F,0x32 ,/* 5 : 640x gra. mode */ + 0xFC,0xFB,0x14,0x2A /* 6 : 800x gra. mode */ +}; + +UCHAR PALMYFilter1[]= +{ + 0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */ + 0x00,0xF4,0x10,0x38, /* 1 : 360x text mode */ + 0xEB,0x04,0x10,0x18, /* 2 : 640x text mode */ + 0xF7,0x06,0x19,0x14, /* 3 : 720x text mode */ + 0x00,0xF4,0x10,0x38, /* 4 : 320x gra. mode */ + 0xEB,0x04,0x25,0x18, /* 5 : 640x gra. mode */ + 0xEB,0x15,0x25,0xF6, /* 6 : 800x gra. mode */ + 0xFF,0xFF,0xFF,0xFF /* End of Table */ +}; + +UCHAR PALNYFilter1[]= +{ + 0x00,0xF4,0x10,0x38, /* 0 : 320x text mode */ + 0x00,0xF4,0x10,0x38, /* 1 : 360x text mode */ + 0xEB,0x04,0x10,0x18, /* 2 : 640x text mode */ + 0xF7,0x06,0x19,0x14, /* 3 : 720x text mode */ + 0x00,0xF4,0x10,0x38, /* 4 : 320x gra. mode */ + 0xEB,0x04,0x25,0x18, /* 5 : 640x gra. mode */ + 0xEB,0x15,0x25,0xF6, /* 6 : 800x gra. mode */ + 0xFF,0xFF,0xFF,0xFF /* End of Table */ +}; + +UCHAR NTSCYFilter2[]= +{ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */ + 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */ + 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */ + 0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */ + 0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28 /* 7 : 1024xgra. mode */ +}; + +UCHAR PALYFilter2[]= +{ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */ + 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */ + 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */ + 0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */ + 0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28 /* 7 : 1024xgra. mode */ +}; + +UCHAR PALMYFilter2[]= +{ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */ + 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */ + 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */ + 0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */ + 0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28 /* 7 : 1024xgra. mode */ +}; + +UCHAR PALNYFilter2[]= +{ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 0 : 320x text mode */ + 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 1 : 360x text mode */ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 2 : 640x text mode */ + 0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C, /* 3 : 720x text mode */ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 4 : 320x gra. mode */ + 0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46, /* 5 : 640x gra. mode */ + 0x01,0x01,0xFC,0xF8,0x08,0x26,0x38, /* 6 : 800x gra. mode */ + 0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28 /* 7 : 1024xgra. mode */ +}; + +UCHAR XGI_NTSC1024AdjTime[]= +{ + 0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53, + 0x13,0x40,0x34,0xF4,0x63,0xBB,0xCC,0x7A, + 0x58,0xe4,0x73,0xd0,0x13 +}; + +XGI301C_Tap4TimingStruct HiTVTap4Timing[]= +{ + {0,{ + 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */ + 0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, /* ; C8-CF */ + 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E, /* ; D0-D7 */ + 0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, /* ; D8-DF */ + 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C, /* ; E0-E7 */ + 0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, /* ; EA-EF */ + 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C, /* ; F0-F7 */ + 0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E /* ; F8-FF */ + } + } +}; + +XGI301C_Tap4TimingStruct EnlargeTap4Timing[]= +{ + {0,{ + 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */ + 0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, /* ; C8-CF */ + 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E, /* ; D0-D7 */ + 0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, /* ; D8-DF */ + 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C, /* ; E0-E7 */ + 0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, /* ; EA-EF */ + 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C, /* ; F0-F7 */ + 0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E /* ; F8-FF */ + } + } +}; + +XGI301C_Tap4TimingStruct NoScaleTap4Timing[]= +{ + {0,{ + 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F, /* ; C0-C7 */ + 0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, /* ; C8-CF */ + 0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E, /* ; D0-D7 */ + 0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C, /* ; D8-DF */ + 0x7C,0x14,0x14,0x7C,0x7C,0x11,0x17,0x7C, /* ; E0-E7 */ + 0x7D,0x0E,0x19,0x7C,0x7E,0x0B,0x1B,0x7C, /* ; EA-EF */ + 0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C, /* ; F0-F7 */ + 0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E /* ; F8-FF */ + } + } +}; + +XGI301C_Tap4TimingStruct PALTap4Timing[]= +{ + {600, { + 0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E, /* ; C0-C7 */ + 0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D, /* ; C8-CF */ + 0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C, /* ; D0-D7 */ + 0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D, /* ; D8-DF */ + 0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E, /* ; E0-E7 */ + 0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E, /* ; EA-EF */ + 0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01, /* ; F0-F7 */ + 0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04 /* ; F8-FF */ + } + }, + {768, { + 0x08,0x12,0x08,0x7E,0x07,0x12,0x09,0x7E, /* ; C0-C7 */ + 0x06,0x12,0x0A,0x7E,0x05,0x11,0x0B,0x7F, /* ; C8-CF */ + 0x04,0x11,0x0C,0x7F,0x03,0x11,0x0C,0x00, /* ; D0-D7 */ + 0x03,0x10,0x0D,0x00,0x02,0x0F,0x0E,0x01, /* ; D8-DF */ + 0x01,0x0F,0x0F,0x01,0x01,0x0E,0x0F,0x02, /* ; E0-E7 */ + 0x00,0x0D,0x10,0x03,0x7F,0x0C,0x11,0x04, /* ; EA-EF */ + 0x7F,0x0C,0x11,0x04,0x7F,0x0B,0x11,0x05, /* ; F0-F7 */ + 0x7E,0x0A,0x12,0x06,0x7E,0x09,0x12,0x07 /* ; F8-FF */ + } + }, + {0xFFFF, + { + 0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E, /* ; C0-C7 */ + 0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D, /* ; C8-CF */ + 0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D, /* ; D0-D7 */ + 0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C, /* ; D8-DF */ + 0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */ + 0x7C,0x10,0x17,0x7D,0x7C,0x0D,0x18,0x7F, /* ; EA-EF */ + 0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00, /* ; F0-F7 */ + 0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02 /* ; F8-FF */ + } + } +}; + +XGI301C_Tap4TimingStruct NTSCTap4Timing[]= +{ + {480, { + 0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */ + 0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D, /* ; C8-CF */ + 0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C, /* ; D0-D7 */ + 0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C, /* ; D8-DF */ + 0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */ + 0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E, /* ; EA-EF */ + 0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00, /* ; F0-F7 */ + 0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02 /* ; F8-FF */ + } + }, + {600, { + 0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D, /* ; C0-C7 */ + 0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E, /* ; C8-CF */ + 0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F, /* ; D0-D7 */ + 0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F, /* ; D8-DF */ + 0x01,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01, /* ; E0-E7 */ + 0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03, /* ; EA-EF */ + 0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04, /* ; F0-F7 */ + 0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06 /* ; F8-FF */ + } + }, + {0xFFFF, + { + 0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00, /* ; C0-C7 */ + 0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01, /* ; C8-CF */ + 0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02, /* ; D0-D7 */ + 0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03, /* ; D8-DF */ + 0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05, /* ; E0-E7 */ + 0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06, /* ; EA-EF */ + 0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07, /* ; F0-F7 */ + 0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08 /* ; F8-FF */ + } + } +}; + +XGI301C_Tap4TimingStruct YPbPr525pTap4Timing[]= +{ + {480, { + 0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */ + 0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D, /* ; C8-CF */ + 0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C, /* ; D0-D7 */ + 0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C, /* ; D8-DF */ + 0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */ + 0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E, /* ; EA-EF */ + 0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00, /* ; F0-F7 */ + 0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02 /* ; F8-FF */ + } + }, + {600, { + 0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D, /* ; C0-C7 */ + 0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E, /* ; C8-CF */ + 0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F, /* ; D0-D7 */ + 0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F, /* ; D8-DF */ + 0x01,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01, /* ; E0-E7 */ + 0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03, /* ; EA-EF */ + 0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04, /* ; F0-F7 */ + 0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06 /* ; F8-FF */ + } + }, + {0xFFFF, + { + 0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00, /* ; C0-C7 */ + 0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01, /* ; C8-CF */ + 0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02, /* ; D0-D7 */ + 0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03, /* ; D8-DF */ + 0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05, /* ; E0-E7 */ + 0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06, /* ; EA-EF */ + 0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07, /* ; F0-F7 */ + 0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08 /* ; F8-FF */ + } + } +}; + +XGI301C_Tap4TimingStruct YPbPr525iTap4Timing[]= +{ + {480, { + 0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D, /* ; C0-C7 */ + 0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D, /* ; C8-CF */ + 0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C, /* ; D0-D7 */ + 0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C, /* ; D8-DF */ + 0x7D,0x13,0x13,0x7D,0x7C,0x12,0x15,0x7D, /* ; E0-E7 */ + 0x7C,0x10,0x17,0x7D,0x7C,0x0E,0x18,0x7E, /* ; EA-EF */ + 0x7D,0x0C,0x19,0x7E,0x7D,0x0A,0x19,0x00, /* ; F0-F7 */ + 0x7D,0x08,0x1A,0x01,0x7E,0x06,0x1A,0x02 /* ; F8-FF */ + } + }, + {600, { + 0x07,0x14,0x07,0x7E,0x06,0x14,0x09,0x7D, /* ; C0-C7 */ + 0x05,0x14,0x0A,0x7D,0x04,0x13,0x0B,0x7E, /* ; C8-CF */ + 0x03,0x13,0x0C,0x7E,0x02,0x12,0x0D,0x7F, /* ; D0-D7 */ + 0x01,0x12,0x0E,0x7F,0x01,0x11,0x0F,0x7F, /* ; D8-DF */ + 0x01,0x10,0x10,0x00,0x7F,0x0F,0x11,0x01, /* ; E0-E7 */ + 0x7F,0x0E,0x12,0x01,0x7E,0x0D,0x12,0x03, /* ; EA-EF */ + 0x7E,0x0C,0x13,0x03,0x7E,0x0B,0x13,0x04, /* ; F0-F7 */ + 0x7E,0x0A,0x14,0x04,0x7D,0x09,0x14,0x06 /* ; F8-FF */ + } + }, + {0xFFFF, + { + 0x09,0x0F,0x09,0x7F,0x08,0x0F,0x09,0x00, /* ; C0-C7 */ + 0x07,0x0F,0x0A,0x00,0x06,0x0F,0x0A,0x01, /* ; C8-CF */ + 0x06,0x0E,0x0B,0x01,0x05,0x0E,0x0B,0x02, /* ; D0-D7 */ + 0x04,0x0E,0x0C,0x02,0x04,0x0D,0x0C,0x03, /* ; D8-DF */ + 0x03,0x0D,0x0D,0x03,0x02,0x0C,0x0D,0x05, /* ; E0-E7 */ + 0x02,0x0C,0x0E,0x04,0x01,0x0B,0x0E,0x06, /* ; EA-EF */ + 0x01,0x0B,0x0E,0x06,0x00,0x0A,0x0F,0x07, /* ; F0-F7 */ + 0x00,0x0A,0x0F,0x07,0x00,0x09,0x0F,0x08 /* ; F8-FF */ + } + } +}; + +XGI301C_Tap4TimingStruct YPbPr750pTap4Timing[]= +{ {0xFFFF, + { + 0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E, /* ; C0-C7 */ + 0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D, /* ; C8-CF */ + 0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C, /* ; D0-D7 */ + 0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D, /* ; D8-DF */ + 0x7D,0x13,0x13,0x7D,0x7D,0x11,0x14,0x7E, /* ; E0-E7 */ + 0x7D,0x0F,0x16,0x7E,0x7D,0x0E,0x17,0x7E, /* ; EA-EF */ + 0x7D,0x0C,0x18,0x7F,0x7D,0x0A,0x18,0x01, /* ; F0-F7 */ + 0x7D,0x08,0x19,0x02,0x7D,0x06,0x19,0x04 /* F8-FF */ + } + } +}; diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c new file mode 100644 index 000000000000..87531b49b739 --- /dev/null +++ b/drivers/staging/xgifb/vb_util.c @@ -0,0 +1,263 @@ +#include "osdef.h" +#include "vb_def.h" +#include "vgatypes.h" +#include "vb_struct.h" + +#ifdef LINUX_KERNEL +#include "XGIfb.h" +#include <asm/io.h> +#include <linux/types.h> +#endif + +#ifdef TC +#include <stdio.h> +#include <string.h> +#include <conio.h> +#include <dos.h> +#endif + +#ifdef WIN2000 +#include <dderror.h> +#include <devioctl.h> +#include <miniport.h> +#include <ntddvdeo.h> +#include <video.h> + +#include "xgiv.h" +#include "dd_i2c.h" +#include "tools.h" +#endif + +#ifdef LINUX_XF86 +#include "xf86.h" +#include "xf86PciInfo.h" +#include "xgi.h" +#include "xgi_regs.h" +#endif + + + + +void XGINew_SetReg1( ULONG , USHORT , USHORT ) ; +void XGINew_SetReg2( ULONG , USHORT , USHORT ) ; +void XGINew_SetReg3( ULONG , USHORT ) ; +void XGINew_SetReg4( ULONG , ULONG ) ; +UCHAR XGINew_GetReg1( ULONG , USHORT) ; +UCHAR XGINew_GetReg2( ULONG ) ; +ULONG XGINew_GetReg3( ULONG ) ; +void XGINew_ClearDAC( PUCHAR ) ; +void XGINew_SetRegANDOR(ULONG Port,USHORT Index,USHORT DataAND,USHORT DataOR); +void XGINew_SetRegOR(ULONG Port,USHORT Index,USHORT DataOR); +void XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND); + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetReg1 */ +/* Input : */ +/* Output : */ +/* Description : SR CRTC GR */ +/* --------------------------------------------------------------------- */ +void XGINew_SetReg1( ULONG port , USHORT index , USHORT data ) +{ +#ifdef LINUX_XF86 + OutPortByte( ( PUCHAR )(ULONG)port , index ) ; + OutPortByte( ( PUCHAR )(ULONG)port + 1 , data ) ; +#else + OutPortByte( port , index ) ; + OutPortByte( port + 1 , data ) ; +#endif +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetReg2 */ +/* Input : */ +/* Output : */ +/* Description : AR( 3C0 ) */ +/* --------------------------------------------------------------------- */ +/*void XGINew_SetReg2( ULONG port , USHORT index , USHORT data ) +{ + InPortByte( ( PUCHAR )port + 0x3da - 0x3c0 ) ; + OutPortByte( XGINew_P3c0 , index ) ; + OutPortByte( XGINew_P3c0 , data ) ; + OutPortByte( XGINew_P3c0 , 0x20 ) ; +}*/ + + +/* --------------------------------------------------------------------- */ +/* Function : */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_SetReg3( ULONG port , USHORT data ) +{ + OutPortByte( port , data ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetReg4 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_SetReg4( ULONG port , ULONG data ) +{ + OutPortLong( port , data ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_GetReg1 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +UCHAR XGINew_GetReg1( ULONG port , USHORT index ) +{ + UCHAR data ; + +#ifdef LINUX_XF86 + OutPortByte( ( PUCHAR )(ULONG)port , index ) ; + data = InPortByte( ( PUCHAR )(ULONG)port + 1 ) ; +#else + OutPortByte( port , index ) ; + data = InPortByte( port + 1 ) ; +#endif + + return( data ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_GetReg2 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +UCHAR XGINew_GetReg2( ULONG port ) +{ + UCHAR data ; + + data = InPortByte( port ) ; + + return( data ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_GetReg3 */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +ULONG XGINew_GetReg3( ULONG port ) +{ + ULONG data ; + + data = InPortLong( port ) ; + + return( data ) ; +} + + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetRegANDOR */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_SetRegANDOR( ULONG Port , USHORT Index , USHORT DataAND , USHORT DataOR ) +{ + USHORT temp ; + + temp = XGINew_GetReg1( Port , Index ) ; /* XGINew_Part1Port index 02 */ + temp = ( temp & ( DataAND ) ) | DataOR ; + XGINew_SetReg1( Port , Index , temp ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetRegAND */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND) +{ + USHORT temp ; + + temp = XGINew_GetReg1( Port , Index ) ; /* XGINew_Part1Port index 02 */ + temp &= DataAND ; + XGINew_SetReg1( Port , Index , temp ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : XGINew_SetRegOR */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void XGINew_SetRegOR( ULONG Port , USHORT Index , USHORT DataOR ) +{ + USHORT temp ; + + temp = XGINew_GetReg1( Port , Index ) ; /* XGINew_Part1Port index 02 */ + temp |= DataOR ; + XGINew_SetReg1( Port , Index , temp ) ; +} + + +/* --------------------------------------------------------------------- */ +/* Function : NewDelaySecond */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void NewDelaySeconds( int seconds ) +{ +#ifdef WIN2000 + int j ; +#endif + int i ; + + + for( i = 0 ; i < seconds ; i++ ) + { +#ifdef TC + delay( 1000 ) ; +#endif + +#ifdef WIN2000 + + for ( j = 0 ; j < 20000 ; j++ ) + VideoPortStallExecution( 50 ) ; +#endif + +#ifdef WINCE_HEADER +#endif + +#ifdef LINUX_KERNEL +#endif + } +} + + +/* --------------------------------------------------------------------- */ +/* Function : Newdebugcode */ +/* Input : */ +/* Output : */ +/* Description : */ +/* --------------------------------------------------------------------- */ +void Newdebugcode( UCHAR code ) +{ +// OutPortByte ( 0x80 , code ) ; + /* OutPortByte ( 0x300 , code ) ; */ + /* NewDelaySeconds( 0x3 ) ; */ +} + + + diff --git a/drivers/staging/xgifb/vb_util.h b/drivers/staging/xgifb/vb_util.h new file mode 100644 index 000000000000..91779d8cfdc6 --- /dev/null +++ b/drivers/staging/xgifb/vb_util.h @@ -0,0 +1,15 @@ +#ifndef _VBUTIL_ +#define _VBUTIL_ +extern void NewDelaySeconds( int ); +extern void Newdebugcode( UCHAR ); +extern void XGINew_SetReg1(ULONG, USHORT, USHORT); +extern void XGINew_SetReg3(ULONG, USHORT); +extern UCHAR XGINew_GetReg1(ULONG, USHORT); +extern UCHAR XGINew_GetReg2(ULONG); +extern void XGINew_SetReg4(ULONG, ULONG); +extern ULONG XGINew_GetReg3(ULONG); +extern void XGINew_SetRegOR(ULONG Port,USHORT Index,USHORT DataOR); +extern void XGINew_SetRegAND(ULONG Port,USHORT Index,USHORT DataAND); +extern void XGINew_SetRegANDOR(ULONG Port,USHORT Index,USHORT DataAND,USHORT DataOR); +#endif + diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h new file mode 100644 index 000000000000..295ea860ae47 --- /dev/null +++ b/drivers/staging/xgifb/vgatypes.h @@ -0,0 +1,325 @@ + +#ifndef _VGATYPES_ +#define _VGATYPES_ + +#include "osdef.h" + +#ifdef LINUX_XF86 +#include "xf86Version.h" +#include "xf86Pci.h" +#endif + +#ifdef LINUX_KERNEL /* We don't want the X driver to depend on kernel source */ +#include <linux/ioctl.h> +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef CHAR +typedef char CHAR; +#endif + +#ifndef SHORT +typedef short SHORT; +#endif + +#ifndef LONG +typedef long LONG; +#endif + +#ifndef UCHAR +typedef unsigned char UCHAR; +#endif + +#ifndef USHORT +typedef unsigned short USHORT; +#endif + +#ifndef ULONG +typedef unsigned long ULONG; +#endif + +#ifndef PUCHAR +typedef UCHAR *PUCHAR; +#endif + +#ifndef PUSHORT +typedef USHORT *PUSHORT; +#endif + +#ifndef PLONGU +typedef ULONG *PULONG; +#endif + +#ifndef VOID +typedef void VOID; +#endif + +#ifndef PVOID +typedef void *PVOID; +#endif + +#ifndef BOOLEAN +typedef UCHAR BOOLEAN; +#endif +/* +#ifndef bool +typedef UCHAR bool; +#endif +*/ +#ifdef LINUX_KERNEL +typedef unsigned long XGIIOADDRESS; +#endif + +#ifdef LINUX_XF86 +#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0) +typedef unsigned char IOADDRESS; +typedef unsigned char XGIIOADDRESS; +#else +typedef IOADDRESS XGIIOADDRESS; +#endif +#endif + +#ifndef VBIOS_VER_MAX_LENGTH +#define VBIOS_VER_MAX_LENGTH 4 +#endif + +#ifndef WIN2000 + +#ifndef LINUX_KERNEL /* For the linux kernel, this is defined in xgifb.h */ +#ifndef XGI_CHIP_TYPE +typedef enum _XGI_CHIP_TYPE { + XGI_VGALegacy = 0, +#ifdef LINUX_XF86 + XGI_530, + XGI_OLD, +#endif + XGI_300, + XGI_630, + XGI_640, + XGI_315H, + XGI_315, + XGI_315PRO, + XGI_550, + XGI_650, + XGI_650M, + XGI_740, + XGI_330, + XGI_661, + XGI_660, + XGI_760, + XG40 = 32, + XG41, + XG42, + XG45, + XG20 = 48, + XG21, + XG27, + MAX_XGI_CHIP +} XGI_CHIP_TYPE; +#endif +#endif + +#ifndef XGI_VB_CHIP_TYPE +typedef enum _XGI_VB_CHIP_TYPE { + VB_CHIP_Legacy = 0, + VB_CHIP_301, + VB_CHIP_301B, + VB_CHIP_301LV, + VB_CHIP_302, + VB_CHIP_302B, + VB_CHIP_302LV, + VB_CHIP_301C, + VB_CHIP_302ELV, + VB_CHIP_UNKNOWN, /* other video bridge or no video bridge */ + MAX_VB_CHIP +} XGI_VB_CHIP_TYPE; +#endif + +#ifndef XGI_LCD_TYPE +typedef enum _XGI_LCD_TYPE { + LCD_INVALID = 0, + LCD_320x480, /* FSTN, DSTN */ + LCD_640x480, + LCD_640x480_2, /* FSTN, DSTN */ + LCD_640x480_3, /* FSTN, DSTN */ + LCD_800x600, + LCD_848x480, + LCD_1024x600, + LCD_1024x768, + LCD_1152x768, + LCD_1152x864, + LCD_1280x720, + LCD_1280x768, + LCD_1280x800, + LCD_1280x960, + LCD_1280x1024, + LCD_1400x1050, + LCD_1600x1200, + LCD_1680x1050, + LCD_1920x1440, + LCD_2048x1536, + LCD_CUSTOM, + LCD_UNKNOWN +} XGI_LCD_TYPE; +#endif + +#endif /* not WIN2000 */ + +#ifndef PXGI_DSReg +typedef struct _XGI_DSReg +{ + UCHAR jIdx; + UCHAR jVal; +} XGI_DSReg, *PXGI_DSReg; +#endif + +#ifndef XGI_HW_DEVICE_INFO + +typedef struct _XGI_HW_DEVICE_INFO XGI_HW_DEVICE_INFO, *PXGI_HW_DEVICE_INFO; + +typedef BOOLEAN (*PXGI_QUERYSPACE) (PXGI_HW_DEVICE_INFO, ULONG, ULONG, ULONG *); + +struct _XGI_HW_DEVICE_INFO +{ + ULONG ulExternalChip; /* NO VB or other video bridge*/ + /* if ujVBChipID = VB_CHIP_UNKNOWN, */ +#ifdef LINUX_XF86 + PCITAG PciTag; /* PCI Tag */ +#endif + + PUCHAR pjVirtualRomBase; /* ROM image */ + + BOOLEAN UseROM; /* Use the ROM image if provided */ + + PVOID pDevice; + + PUCHAR pjVideoMemoryAddress;/* base virtual memory address */ + /* of Linear VGA memory */ + + ULONG ulVideoMemorySize; /* size, in bytes, of the memory on the board */ + + PUCHAR pjIOAddress; /* base I/O address of VGA ports (0x3B0) */ + + PUCHAR pjCustomizedROMImage; + + PUCHAR pj2ndVideoMemoryAddress; + ULONG ul2ndVideoMemorySize; + + PUCHAR pj2ndIOAddress; +/*#ifndef WIN2000 + XGIIOADDRESS pjIOAddress; // base I/O address of VGA ports (0x3B0) +#endif */ + UCHAR jChipType; /* Used to Identify Graphics Chip */ + /* defined in the data structure type */ + /* "XGI_CHIP_TYPE" */ + + UCHAR jChipRevision; /* Used to Identify Graphics Chip Revision */ + + UCHAR ujVBChipID; /* the ID of video bridge */ + /* defined in the data structure type */ + /* "XGI_VB_CHIP_TYPE" */ + + BOOLEAN bNewScratch; + + ULONG ulCRT2LCDType; /* defined in the data structure type */ + + ULONG usExternalChip; /* NO VB or other video bridge (other than */ + /* video bridge) */ + + BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */ + + BOOLEAN bSkipDramSizing; /* True: Skip video memory sizing. */ + + BOOLEAN bSkipSense; + + BOOLEAN bIsPowerSaving; /* True: XGIInit() is invoked by power management, + otherwise by 2nd adapter's initialzation */ + + PXGI_DSReg pSR; /* restore SR registers in initial function. */ + /* end data :(idx, val) = (FF, FF). */ + /* Note : restore SR registers if */ + /* bSkipDramSizing = TRUE */ + + PXGI_DSReg pCR; /* restore CR registers in initial function. */ + /* end data :(idx, val) = (FF, FF) */ + /* Note : restore cR registers if */ + /* bSkipDramSizing = TRUE */ +/* +#endif +*/ + + PXGI_QUERYSPACE pQueryVGAConfigSpace; + + PXGI_QUERYSPACE pQueryNorthBridgeSpace; + + UCHAR szVBIOSVer[VBIOS_VER_MAX_LENGTH]; + +}; +#endif + +/* Addtional IOCTL for communication xgifb <> X driver */ +/* If changing this, xgifb.h must also be changed (for xgifb) */ + +#ifdef LINUX_XF86 /* We don't want the X driver to depend on the kernel source */ + +/* ioctl for identifying and giving some info (esp. memory heap start) */ +#define XGIFB_GET_INFO 0x80046ef8 /* Wow, what a terrible hack... */ + +/* Structure argument for XGIFB_GET_INFO ioctl */ +typedef struct _XGIFB_INFO xgifb_info, *pxgifb_info; + +struct _XGIFB_INFO { + CARD32 xgifb_id; /* for identifying xgifb */ +#ifndef XGIFB_ID +#define XGIFB_ID 0x53495346 /* Identify myself with 'XGIF' */ +#endif + CARD32 chip_id; /* PCI ID of detected chip */ + CARD32 memory; /* video memory in KB which xgifb manages */ + CARD32 heapstart; /* heap start (= xgifb "mem" argument) in KB */ + CARD8 fbvidmode; /* current xgifb mode */ + + CARD8 xgifb_version; + CARD8 xgifb_revision; + CARD8 xgifb_patchlevel; + + CARD8 xgifb_caps; /* xgifb's capabilities */ + + CARD32 xgifb_tqlen; /* turbo queue length (in KB) */ + + CARD32 xgifb_pcibus; /* The card's PCI ID */ + CARD32 xgifb_pcislot; + CARD32 xgifb_pcifunc; + + CARD8 xgifb_lcdpdc; + + CARD8 xgifb_lcda; + + CARD32 xgifb_vbflags; + CARD32 xgifb_currentvbflags; + + CARD32 xgifb_scalelcd; + CARD32 xgifb_specialtiming; + + CARD8 xgifb_haveemi; + CARD8 xgifb_emi30,xgifb_emi31,xgifb_emi32,xgifb_emi33; + CARD8 xgifb_haveemilcd; + + CARD8 xgifb_lcdpdca; + + CARD8 reserved[212]; /* for future use */ +}; +#endif + +#endif + |