aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c31
-rw-r--r--drivers/video/Kconfig92
-rw-r--r--drivers/video/Makefile5
-rw-r--r--drivers/video/bf537-lq035.c914
-rw-r--r--drivers/video/bfin_adv7393fb.c832
-rw-r--r--drivers/video/bfin_adv7393fb.h321
-rw-r--r--drivers/video/fbmon.c88
-rw-r--r--drivers/video/modedb.c47
-rw-r--r--drivers/video/mx3fb.c3
-rw-r--r--drivers/video/s1d13xxxfb.c50
-rw-r--r--drivers/video/s3c-fb.c111
-rw-r--r--drivers/video/sh_mipi_dsi.c103
-rw-r--r--drivers/video/sh_mobile_hdmi.c219
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c26
-rw-r--r--drivers/video/via/via-core.c96
-rw-r--r--drivers/video/via/via-gpio.c29
-rw-r--r--drivers/video/via/viafbdev.c34
-rw-r--r--drivers/video/via/viafbdev.h2
-rw-r--r--drivers/video/vt8500lcdfb.c447
-rw-r--r--drivers/video/vt8500lcdfb.h34
-rw-r--r--drivers/video/wm8505fb.c422
-rw-r--r--drivers/video/wm8505fb_regs.h76
-rw-r--r--drivers/video/wmt_ge_rops.c186
-rw-r--r--drivers/video/wmt_ge_rops.h5
-rw-r--r--include/linux/fb.h3
-rw-r--r--include/linux/via-core.h15
-rw-r--r--include/video/s1d13xxxfb.h6
-rw-r--r--include/video/sh_mobile_hdmi.h3
28 files changed, 4002 insertions, 198 deletions
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index d440e5f456ad..a054f0d450d8 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -501,7 +501,12 @@ static struct platform_device keysc_device = {
501static struct resource mipidsi0_resources[] = { 501static struct resource mipidsi0_resources[] = {
502 [0] = { 502 [0] = {
503 .start = 0xffc60000, 503 .start = 0xffc60000,
504 .end = 0xffc68fff, 504 .end = 0xffc63073,
505 .flags = IORESOURCE_MEM,
506 },
507 [1] = {
508 .start = 0xffc68000,
509 .end = 0xffc680ef,
505 .flags = IORESOURCE_MEM, 510 .flags = IORESOURCE_MEM,
506 }, 511 },
507}; 512};
@@ -764,10 +769,15 @@ static struct platform_device lcdc1_device = {
764 }, 769 },
765}; 770};
766 771
772static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
773 unsigned long *parent_freq);
774
775
767static struct sh_mobile_hdmi_info hdmi_info = { 776static struct sh_mobile_hdmi_info hdmi_info = {
768 .lcd_chan = &sh_mobile_lcdc1_info.ch[0], 777 .lcd_chan = &sh_mobile_lcdc1_info.ch[0],
769 .lcd_dev = &lcdc1_device.dev, 778 .lcd_dev = &lcdc1_device.dev,
770 .flags = HDMI_SND_SRC_SPDIF, 779 .flags = HDMI_SND_SRC_SPDIF,
780 .clk_optimize_parent = ap4evb_clk_optimize,
771}; 781};
772 782
773static struct resource hdmi_resources[] = { 783static struct resource hdmi_resources[] = {
@@ -794,6 +804,25 @@ static struct platform_device hdmi_device = {
794 }, 804 },
795}; 805};
796 806
807static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
808 unsigned long *parent_freq)
809{
810 struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick");
811 long error;
812
813 if (IS_ERR(hdmi_ick)) {
814 int ret = PTR_ERR(hdmi_ick);
815 pr_err("Cannot get HDMI ICK: %d\n", ret);
816 return ret;
817 }
818
819 error = clk_round_parent(hdmi_ick, target, best_freq, parent_freq, 1, 64);
820
821 clk_put(hdmi_ick);
822
823 return error;
824}
825
797static struct gpio_led ap4evb_leds[] = { 826static struct gpio_led ap4evb_leds[] = {
798 { 827 {
799 .name = "led4", 828 .name = "led4",
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 27c1fb4b1e0d..e231041a5e33 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -186,6 +186,14 @@ config FB_SYS_FOPS
186 depends on FB 186 depends on FB
187 default n 187 default n
188 188
189config FB_WMT_GE_ROPS
190 tristate
191 depends on FB
192 default n
193 ---help---
194 Include functions for accelerated rectangle filling and area
195 copying using WonderMedia Graphics Engine operations.
196
189config FB_DEFERRED_IO 197config FB_DEFERRED_IO
190 bool 198 bool
191 depends on FB 199 depends on FB
@@ -635,6 +643,72 @@ config FB_BFIN_LQ035Q1
635 To compile this driver as a module, choose M here: the 643 To compile this driver as a module, choose M here: the
636 module will be called bfin-lq035q1-fb. 644 module will be called bfin-lq035q1-fb.
637 645
646config FB_BF537_LQ035
647 tristate "SHARP LQ035 TFT LCD (BF537 STAMP)"
648 depends on FB && (BF534 || BF536 || BF537) && I2C_BLACKFIN_TWI
649 select FB_CFB_FILLRECT
650 select FB_CFB_COPYAREA
651 select FB_CFB_IMAGEBLIT
652 select BFIN_GPTIMERS
653 help
654 This is the framebuffer device for a SHARP LQ035Q7DB03 TFT LCD
655 attached to a BF537.
656
657 To compile this driver as a module, choose M here: the
658 module will be called bf537-lq035.
659
660config FB_BFIN_7393
661 tristate "Blackfin ADV7393 Video encoder"
662 depends on FB && BLACKFIN
663 select I2C
664 select FB_CFB_FILLRECT
665 select FB_CFB_COPYAREA
666 select FB_CFB_IMAGEBLIT
667 help
668 This is the framebuffer device for a ADV7393 video encoder
669 attached to a Blackfin on the PPI port.
670 If your Blackfin board has a ADV7393 select Y.
671
672 To compile this driver as a module, choose M here: the
673 module will be called bfin_adv7393fb.
674
675choice
676 prompt "Video mode support"
677 depends on FB_BFIN_7393
678 default NTSC
679
680config NTSC
681 bool 'NTSC 720x480'
682
683config PAL
684 bool 'PAL 720x576'
685
686config NTSC_640x480
687 bool 'NTSC 640x480 (Experimental)'
688
689config PAL_640x480
690 bool 'PAL 640x480 (Experimental)'
691
692config NTSC_YCBCR
693 bool 'NTSC 720x480 YCbCR input'
694
695config PAL_YCBCR
696 bool 'PAL 720x576 YCbCR input'
697
698endchoice
699
700choice
701 prompt "Size of ADV7393 frame buffer memory Single/Double Size"
702 depends on (FB_BFIN_7393)
703 default ADV7393_1XMEM
704
705config ADV7393_1XMEM
706 bool 'Single'
707
708config ADV7393_2XMEM
709 bool 'Double'
710endchoice
711
638config FB_STI 712config FB_STI
639 tristate "HP STI frame buffer device support" 713 tristate "HP STI frame buffer device support"
640 depends on FB && PARISC 714 depends on FB && PARISC
@@ -1722,6 +1796,24 @@ config FB_AU1200
1722 various panels and CRTs by passing in kernel cmd line option 1796 various panels and CRTs by passing in kernel cmd line option
1723 au1200fb:panel=<name>. 1797 au1200fb:panel=<name>.
1724 1798
1799config FB_VT8500
1800 bool "VT8500 LCD Driver"
1801 depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_VT8500
1802 select FB_WMT_GE_ROPS
1803 select FB_SYS_IMAGEBLIT
1804 help
1805 This is the framebuffer driver for VIA VT8500 integrated LCD
1806 controller.
1807
1808config FB_WM8505
1809 bool "WM8505 frame buffer support"
1810 depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_WM8505
1811 select FB_WMT_GE_ROPS
1812 select FB_SYS_IMAGEBLIT
1813 help
1814 This is the framebuffer driver for WonderMedia WM8505
1815 integrated LCD controller.
1816
1725source "drivers/video/geode/Kconfig" 1817source "drivers/video/geode/Kconfig"
1726 1818
1727config FB_HIT 1819config FB_HIT
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 485e8ed1318c..bdf626419433 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_FB_SVGALIB) += svgalib.o
26obj-$(CONFIG_FB_MACMODES) += macmodes.o 26obj-$(CONFIG_FB_MACMODES) += macmodes.o
27obj-$(CONFIG_FB_DDC) += fb_ddc.o 27obj-$(CONFIG_FB_DDC) += fb_ddc.o
28obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o 28obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
29obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
29 30
30# Hardware specific drivers go first 31# Hardware specific drivers go first
31obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o 32obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
@@ -104,6 +105,8 @@ obj-$(CONFIG_FB_W100) += w100fb.o
104obj-$(CONFIG_FB_TMIO) += tmiofb.o 105obj-$(CONFIG_FB_TMIO) += tmiofb.o
105obj-$(CONFIG_FB_AU1100) += au1100fb.o 106obj-$(CONFIG_FB_AU1100) += au1100fb.o
106obj-$(CONFIG_FB_AU1200) += au1200fb.o 107obj-$(CONFIG_FB_AU1200) += au1200fb.o
108obj-$(CONFIG_FB_VT8500) += vt8500lcdfb.o
109obj-$(CONFIG_FB_WM8505) += wm8505fb.o
107obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o 110obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o
108obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o 111obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o
109obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o 112obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
@@ -141,9 +144,11 @@ obj-$(CONFIG_FB_VESA) += vesafb.o
141obj-$(CONFIG_FB_EFI) += efifb.o 144obj-$(CONFIG_FB_EFI) += efifb.o
142obj-$(CONFIG_FB_VGA16) += vga16fb.o 145obj-$(CONFIG_FB_VGA16) += vga16fb.o
143obj-$(CONFIG_FB_OF) += offb.o 146obj-$(CONFIG_FB_OF) += offb.o
147obj-$(CONFIG_FB_BF537_LQ035) += bf537-lq035.o
144obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o 148obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
145obj-$(CONFIG_FB_BFIN_LQ035Q1) += bfin-lq035q1-fb.o 149obj-$(CONFIG_FB_BFIN_LQ035Q1) += bfin-lq035q1-fb.o
146obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o 150obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o
151obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o
147obj-$(CONFIG_FB_MX3) += mx3fb.o 152obj-$(CONFIG_FB_MX3) += mx3fb.o
148obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o 153obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o
149 154
diff --git a/drivers/video/bf537-lq035.c b/drivers/video/bf537-lq035.c
new file mode 100644
index 000000000000..18c507874ff1
--- /dev/null
+++ b/drivers/video/bf537-lq035.c
@@ -0,0 +1,914 @@
1/*
2 * Analog Devices Blackfin(BF537 STAMP) + SHARP TFT LCD.
3 * http://docs.blackfin.uclinux.org/doku.php?id=hw:cards:tft-lcd
4 *
5 * Copyright 2006-2010 Analog Devices Inc.
6 * Licensed under the GPL-2.
7 */
8
9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
11#include <linux/module.h>
12#include <linux/kernel.h>
13#include <linux/errno.h>
14#include <linux/string.h>
15#include <linux/mm.h>
16#include <linux/delay.h>
17#include <linux/fb.h>
18#include <linux/ioport.h>
19#include <linux/init.h>
20#include <linux/types.h>
21#include <linux/gpio.h>
22#include <linux/interrupt.h>
23#include <linux/sched.h>
24#include <linux/timer.h>
25#include <linux/device.h>
26#include <linux/backlight.h>
27#include <linux/lcd.h>
28#include <linux/i2c.h>
29#include <linux/spinlock.h>
30#include <linux/dma-mapping.h>
31#include <linux/slab.h>
32#include <linux/platform_device.h>
33
34#include <asm/blackfin.h>
35#include <asm/irq.h>
36#include <asm/dpmc.h>
37#include <asm/dma.h>
38#include <asm/portmux.h>
39
40#define NO_BL 1
41
42#define MAX_BRIGHENESS 95
43#define MIN_BRIGHENESS 5
44#define NBR_PALETTE 256
45
46static const unsigned short ppi_pins[] = {
47 P_PPI0_CLK, P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
48 P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
49 P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
50 P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, 0
51};
52
53static unsigned char *fb_buffer; /* RGB Buffer */
54static unsigned long *dma_desc_table;
55static int t_conf_done, lq035_open_cnt;
56static DEFINE_SPINLOCK(bfin_lq035_lock);
57
58static int landscape;
59module_param(landscape, int, 0);
60MODULE_PARM_DESC(landscape,
61 "LANDSCAPE use 320x240 instead of Native 240x320 Resolution");
62
63static int bgr;
64module_param(bgr, int, 0);
65MODULE_PARM_DESC(bgr,
66 "BGR use 16-bit BGR-565 instead of RGB-565");
67
68static int nocursor = 1;
69module_param(nocursor, int, 0644);
70MODULE_PARM_DESC(nocursor, "cursor enable/disable");
71
72static unsigned long current_brightness; /* backlight */
73
74/* AD5280 vcomm */
75static unsigned char vcomm_value = 150;
76static struct i2c_client *ad5280_client;
77
78static void set_vcomm(void)
79{
80 int nr;
81
82 if (!ad5280_client)
83 return;
84
85 nr = i2c_smbus_write_byte_data(ad5280_client, 0x00, vcomm_value);
86 if (nr)
87 pr_err("i2c_smbus_write_byte_data fail: %d\n", nr);
88}
89
90static int __devinit ad5280_probe(struct i2c_client *client,
91 const struct i2c_device_id *id)
92{
93 int ret;
94 if (!i2c_check_functionality(client->adapter,
95 I2C_FUNC_SMBUS_BYTE_DATA)) {
96 dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
97 return -EIO;
98 }
99
100 ret = i2c_smbus_write_byte_data(client, 0x00, vcomm_value);
101 if (ret) {
102 dev_err(&client->dev, "write fail: %d\n", ret);
103 return ret;
104 }
105
106 ad5280_client = client;
107
108 return 0;
109}
110
111static int __devexit ad5280_remove(struct i2c_client *client)
112{
113 ad5280_client = NULL;
114 return 0;
115}
116
117static const struct i2c_device_id ad5280_id[] = {
118 {"bf537-lq035-ad5280", 0},
119 {}
120};
121
122MODULE_DEVICE_TABLE(i2c, ad5280_id);
123
124static struct i2c_driver ad5280_driver = {
125 .driver = {
126 .name = "bf537-lq035-ad5280",
127 },
128 .probe = ad5280_probe,
129 .remove = __devexit_p(ad5280_remove),
130 .id_table = ad5280_id,
131};
132
133#ifdef CONFIG_PNAV10
134#define MOD GPIO_PH13
135
136#define bfin_write_TIMER_LP_CONFIG bfin_write_TIMER0_CONFIG
137#define bfin_write_TIMER_LP_WIDTH bfin_write_TIMER0_WIDTH
138#define bfin_write_TIMER_LP_PERIOD bfin_write_TIMER0_PERIOD
139#define bfin_read_TIMER_LP_COUNTER bfin_read_TIMER0_COUNTER
140#define TIMDIS_LP TIMDIS0
141#define TIMEN_LP TIMEN0
142
143#define bfin_write_TIMER_SPS_CONFIG bfin_write_TIMER1_CONFIG
144#define bfin_write_TIMER_SPS_WIDTH bfin_write_TIMER1_WIDTH
145#define bfin_write_TIMER_SPS_PERIOD bfin_write_TIMER1_PERIOD
146#define TIMDIS_SPS TIMDIS1
147#define TIMEN_SPS TIMEN1
148
149#define bfin_write_TIMER_SP_CONFIG bfin_write_TIMER5_CONFIG
150#define bfin_write_TIMER_SP_WIDTH bfin_write_TIMER5_WIDTH
151#define bfin_write_TIMER_SP_PERIOD bfin_write_TIMER5_PERIOD
152#define TIMDIS_SP TIMDIS5
153#define TIMEN_SP TIMEN5
154
155#define bfin_write_TIMER_PS_CLS_CONFIG bfin_write_TIMER2_CONFIG
156#define bfin_write_TIMER_PS_CLS_WIDTH bfin_write_TIMER2_WIDTH
157#define bfin_write_TIMER_PS_CLS_PERIOD bfin_write_TIMER2_PERIOD
158#define TIMDIS_PS_CLS TIMDIS2
159#define TIMEN_PS_CLS TIMEN2
160
161#define bfin_write_TIMER_REV_CONFIG bfin_write_TIMER3_CONFIG
162#define bfin_write_TIMER_REV_WIDTH bfin_write_TIMER3_WIDTH
163#define bfin_write_TIMER_REV_PERIOD bfin_write_TIMER3_PERIOD
164#define TIMDIS_REV TIMDIS3
165#define TIMEN_REV TIMEN3
166#define bfin_read_TIMER_REV_COUNTER bfin_read_TIMER3_COUNTER
167
168#define FREQ_PPI_CLK (5*1024*1024) /* PPI_CLK 5MHz */
169
170#define TIMERS {P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR5, 0}
171
172#else
173
174#define UD GPIO_PF13 /* Up / Down */
175#define MOD GPIO_PF10
176#define LBR GPIO_PF14 /* Left Right */
177
178#define bfin_write_TIMER_LP_CONFIG bfin_write_TIMER6_CONFIG
179#define bfin_write_TIMER_LP_WIDTH bfin_write_TIMER6_WIDTH
180#define bfin_write_TIMER_LP_PERIOD bfin_write_TIMER6_PERIOD
181#define bfin_read_TIMER_LP_COUNTER bfin_read_TIMER6_COUNTER
182#define TIMDIS_LP TIMDIS6
183#define TIMEN_LP TIMEN6
184
185#define bfin_write_TIMER_SPS_CONFIG bfin_write_TIMER1_CONFIG
186#define bfin_write_TIMER_SPS_WIDTH bfin_write_TIMER1_WIDTH
187#define bfin_write_TIMER_SPS_PERIOD bfin_write_TIMER1_PERIOD
188#define TIMDIS_SPS TIMDIS1
189#define TIMEN_SPS TIMEN1
190
191#define bfin_write_TIMER_SP_CONFIG bfin_write_TIMER0_CONFIG
192#define bfin_write_TIMER_SP_WIDTH bfin_write_TIMER0_WIDTH
193#define bfin_write_TIMER_SP_PERIOD bfin_write_TIMER0_PERIOD
194#define TIMDIS_SP TIMDIS0
195#define TIMEN_SP TIMEN0
196
197#define bfin_write_TIMER_PS_CLS_CONFIG bfin_write_TIMER7_CONFIG
198#define bfin_write_TIMER_PS_CLS_WIDTH bfin_write_TIMER7_WIDTH
199#define bfin_write_TIMER_PS_CLS_PERIOD bfin_write_TIMER7_PERIOD
200#define TIMDIS_PS_CLS TIMDIS7
201#define TIMEN_PS_CLS TIMEN7
202
203#define bfin_write_TIMER_REV_CONFIG bfin_write_TIMER5_CONFIG
204#define bfin_write_TIMER_REV_WIDTH bfin_write_TIMER5_WIDTH
205#define bfin_write_TIMER_REV_PERIOD bfin_write_TIMER5_PERIOD
206#define TIMDIS_REV TIMDIS5
207#define TIMEN_REV TIMEN5
208#define bfin_read_TIMER_REV_COUNTER bfin_read_TIMER5_COUNTER
209
210#define FREQ_PPI_CLK (6*1000*1000) /* PPI_CLK 6MHz */
211#define TIMERS {P_TMR0, P_TMR1, P_TMR5, P_TMR6, P_TMR7, 0}
212
213#endif
214
215#define LCD_X_RES 240 /* Horizontal Resolution */
216#define LCD_Y_RES 320 /* Vertical Resolution */
217
218#define LCD_BBP 16 /* Bit Per Pixel */
219
220/* the LCD and the DMA start counting differently;
221 * since one starts at 0 and the other starts at 1,
222 * we have a difference of 1 between START_LINES
223 * and U_LINES.
224 */
225#define START_LINES 8 /* lines for field flyback or field blanking signal */
226#define U_LINES 9 /* number of undisplayed blanking lines */
227
228#define FRAMES_PER_SEC (60)
229
230#define DCLKS_PER_FRAME (FREQ_PPI_CLK/FRAMES_PER_SEC)
231#define DCLKS_PER_LINE (DCLKS_PER_FRAME/(LCD_Y_RES+U_LINES))
232
233#define PPI_CONFIG_VALUE (PORT_DIR|XFR_TYPE|DLEN_16|POLS)
234#define PPI_DELAY_VALUE (0)
235#define TIMER_CONFIG (PWM_OUT|PERIOD_CNT|TIN_SEL|CLK_SEL)
236
237#define ACTIVE_VIDEO_MEM_OFFSET (LCD_X_RES*START_LINES*(LCD_BBP/8))
238#define ACTIVE_VIDEO_MEM_SIZE (LCD_Y_RES*LCD_X_RES*(LCD_BBP/8))
239#define TOTAL_VIDEO_MEM_SIZE ((LCD_Y_RES+U_LINES)*LCD_X_RES*(LCD_BBP/8))
240#define TOTAL_DMA_DESC_SIZE (2 * sizeof(u32) * (LCD_Y_RES + U_LINES))
241
242static void start_timers(void) /* CHECK with HW */
243{
244 unsigned long flags;
245
246 local_irq_save(flags);
247
248 bfin_write_TIMER_ENABLE(TIMEN_REV);
249 SSYNC();
250
251 while (bfin_read_TIMER_REV_COUNTER() <= 11)
252 continue;
253 bfin_write_TIMER_ENABLE(TIMEN_LP);
254 SSYNC();
255
256 while (bfin_read_TIMER_LP_COUNTER() < 3)
257 continue;
258 bfin_write_TIMER_ENABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS);
259 SSYNC();
260 t_conf_done = 1;
261 local_irq_restore(flags);
262}
263
264static void config_timers(void)
265{
266 /* Stop timers */
267 bfin_write_TIMER_DISABLE(TIMDIS_SP|TIMDIS_SPS|TIMDIS_REV|
268 TIMDIS_LP|TIMDIS_PS_CLS);
269 SSYNC();
270
271 /* LP, timer 6 */
272 bfin_write_TIMER_LP_CONFIG(TIMER_CONFIG|PULSE_HI);
273 bfin_write_TIMER_LP_WIDTH(1);
274
275 bfin_write_TIMER_LP_PERIOD(DCLKS_PER_LINE);
276 SSYNC();
277
278 /* SPS, timer 1 */
279 bfin_write_TIMER_SPS_CONFIG(TIMER_CONFIG|PULSE_HI);
280 bfin_write_TIMER_SPS_WIDTH(DCLKS_PER_LINE*2);
281 bfin_write_TIMER_SPS_PERIOD((DCLKS_PER_LINE * (LCD_Y_RES+U_LINES)));
282 SSYNC();
283
284 /* SP, timer 0 */
285 bfin_write_TIMER_SP_CONFIG(TIMER_CONFIG|PULSE_HI);
286 bfin_write_TIMER_SP_WIDTH(1);
287 bfin_write_TIMER_SP_PERIOD(DCLKS_PER_LINE);
288 SSYNC();
289
290 /* PS & CLS, timer 7 */
291 bfin_write_TIMER_PS_CLS_CONFIG(TIMER_CONFIG);
292 bfin_write_TIMER_PS_CLS_WIDTH(LCD_X_RES + START_LINES);
293 bfin_write_TIMER_PS_CLS_PERIOD(DCLKS_PER_LINE);
294
295 SSYNC();
296
297#ifdef NO_BL
298 /* REV, timer 5 */
299 bfin_write_TIMER_REV_CONFIG(TIMER_CONFIG|PULSE_HI);
300
301 bfin_write_TIMER_REV_WIDTH(DCLKS_PER_LINE);
302 bfin_write_TIMER_REV_PERIOD(DCLKS_PER_LINE*2);
303
304 SSYNC();
305#endif
306}
307
308static void config_ppi(void)
309{
310 bfin_write_PPI_DELAY(PPI_DELAY_VALUE);
311 bfin_write_PPI_COUNT(LCD_X_RES-1);
312 /* 0x10 -> PORT_CFG -> 2 or 3 frame syncs */
313 bfin_write_PPI_CONTROL((PPI_CONFIG_VALUE|0x10) & (~POLS));
314}
315
316static int config_dma(void)
317{
318 u32 i;
319
320 if (landscape) {
321
322 for (i = 0; i < U_LINES; ++i) {
323 /* blanking lines point to first line of fb_buffer */
324 dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2];
325 dma_desc_table[2*i+1] = (unsigned long)fb_buffer;
326 }
327
328 for (i = U_LINES; i < U_LINES + LCD_Y_RES; ++i) {
329 /* visible lines */
330 dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2];
331 dma_desc_table[2*i+1] = (unsigned long)fb_buffer +
332 (LCD_Y_RES+U_LINES-1-i)*2;
333 }
334
335 /* last descriptor points to first */
336 dma_desc_table[2*(LCD_Y_RES+U_LINES-1)] = (unsigned long)&dma_desc_table[0];
337
338 set_dma_x_count(CH_PPI, LCD_X_RES);
339 set_dma_x_modify(CH_PPI, LCD_Y_RES * (LCD_BBP / 8));
340 set_dma_y_count(CH_PPI, 0);
341 set_dma_y_modify(CH_PPI, 0);
342 set_dma_next_desc_addr(CH_PPI, (void *)dma_desc_table[0]);
343 set_dma_config(CH_PPI, DMAFLOW_LARGE | NDSIZE_4 | WDSIZE_16);
344
345 } else {
346
347 set_dma_config(CH_PPI, set_bfin_dma_config(DIR_READ,
348 DMA_FLOW_AUTO,
349 INTR_DISABLE,
350 DIMENSION_2D,
351 DATA_SIZE_16,
352 DMA_NOSYNC_KEEP_DMA_BUF));
353 set_dma_x_count(CH_PPI, LCD_X_RES);
354 set_dma_x_modify(CH_PPI, LCD_BBP / 8);
355 set_dma_y_count(CH_PPI, LCD_Y_RES+U_LINES);
356 set_dma_y_modify(CH_PPI, LCD_BBP / 8);
357 set_dma_start_addr(CH_PPI, (unsigned long) fb_buffer);
358 }
359
360 return 0;
361}
362
363static int __devinit request_ports(void)
364{
365 u16 tmr_req[] = TIMERS;
366
367 /*
368 UD: PF13
369 MOD: PF10
370 LBR: PF14
371 PPI_CLK: PF15
372 */
373
374 if (peripheral_request_list(ppi_pins, KBUILD_MODNAME)) {
375 pr_err("requesting PPI peripheral failed\n");
376 return -EBUSY;
377 }
378
379 if (peripheral_request_list(tmr_req, KBUILD_MODNAME)) {
380 peripheral_free_list(ppi_pins);
381 pr_err("requesting timer peripheral failed\n");
382 return -EBUSY;
383 }
384
385#if (defined(UD) && defined(LBR))
386 if (gpio_request(UD, KBUILD_MODNAME)) {
387 pr_err("requesting GPIO %d failed\n", UD);
388 return -EBUSY;
389 }
390
391 if (gpio_request(LBR, KBUILD_MODNAME)) {
392 pr_err("requesting GPIO %d failed\n", LBR);
393 gpio_free(UD);
394 return -EBUSY;
395 }
396
397 gpio_direction_output(UD, 0);
398 gpio_direction_output(LBR, 1);
399
400#endif
401
402 if (gpio_request(MOD, KBUILD_MODNAME)) {
403 pr_err("requesting GPIO %d failed\n", MOD);
404#if (defined(UD) && defined(LBR))
405 gpio_free(LBR);
406 gpio_free(UD);
407#endif
408 return -EBUSY;
409 }
410
411 gpio_direction_output(MOD, 1);
412
413 SSYNC();
414 return 0;
415}
416
417static void free_ports(void)
418{
419 u16 tmr_req[] = TIMERS;
420
421 peripheral_free_list(ppi_pins);
422 peripheral_free_list(tmr_req);
423
424#if defined(UD) && defined(LBR)
425 gpio_free(LBR);
426 gpio_free(UD);
427#endif
428 gpio_free(MOD);
429}
430
431static struct fb_info bfin_lq035_fb;
432
433static struct fb_var_screeninfo bfin_lq035_fb_defined = {
434 .bits_per_pixel = LCD_BBP,
435 .activate = FB_ACTIVATE_TEST,
436 .xres = LCD_X_RES, /*default portrait mode RGB*/
437 .yres = LCD_Y_RES,
438 .xres_virtual = LCD_X_RES,
439 .yres_virtual = LCD_Y_RES,
440 .height = -1,
441 .width = -1,
442 .left_margin = 0,
443 .right_margin = 0,
444 .upper_margin = 0,
445 .lower_margin = 0,
446 .red = {11, 5, 0},
447 .green = {5, 6, 0},
448 .blue = {0, 5, 0},
449 .transp = {0, 0, 0},
450};
451
452static struct fb_fix_screeninfo bfin_lq035_fb_fix __devinitdata = {
453 .id = KBUILD_MODNAME,
454 .smem_len = ACTIVE_VIDEO_MEM_SIZE,
455 .type = FB_TYPE_PACKED_PIXELS,
456 .visual = FB_VISUAL_TRUECOLOR,
457 .xpanstep = 0,
458 .ypanstep = 0,
459 .line_length = LCD_X_RES*(LCD_BBP/8),
460 .accel = FB_ACCEL_NONE,
461};
462
463
464static int bfin_lq035_fb_open(struct fb_info *info, int user)
465{
466 unsigned long flags;
467
468 spin_lock_irqsave(&bfin_lq035_lock, flags);
469 lq035_open_cnt++;
470 spin_unlock_irqrestore(&bfin_lq035_lock, flags);
471
472 if (lq035_open_cnt <= 1) {
473 bfin_write_PPI_CONTROL(0);
474 SSYNC();
475
476 set_vcomm();
477 config_dma();
478 config_ppi();
479
480 /* start dma */
481 enable_dma(CH_PPI);
482 SSYNC();
483 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
484 SSYNC();
485
486 if (!t_conf_done) {
487 config_timers();
488 start_timers();
489 }
490 /* gpio_set_value(MOD,1); */
491 }
492
493 return 0;
494}
495
496static int bfin_lq035_fb_release(struct fb_info *info, int user)
497{
498 unsigned long flags;
499
500 spin_lock_irqsave(&bfin_lq035_lock, flags);
501 lq035_open_cnt--;
502 spin_unlock_irqrestore(&bfin_lq035_lock, flags);
503
504
505 if (lq035_open_cnt <= 0) {
506
507 bfin_write_PPI_CONTROL(0);
508 SSYNC();
509
510 disable_dma(CH_PPI);
511 }
512
513 return 0;
514}
515
516
517static int bfin_lq035_fb_check_var(struct fb_var_screeninfo *var,
518 struct fb_info *info)
519{
520 switch (var->bits_per_pixel) {
521 case 16:/* DIRECTCOLOUR, 64k */
522 var->red.offset = info->var.red.offset;
523 var->green.offset = info->var.green.offset;
524 var->blue.offset = info->var.blue.offset;
525 var->red.length = info->var.red.length;
526 var->green.length = info->var.green.length;
527 var->blue.length = info->var.blue.length;
528 var->transp.offset = 0;
529 var->transp.length = 0;
530 var->transp.msb_right = 0;
531 var->red.msb_right = 0;
532 var->green.msb_right = 0;
533 var->blue.msb_right = 0;
534 break;
535 default:
536 pr_debug("%s: depth not supported: %u BPP\n", __func__,
537 var->bits_per_pixel);
538 return -EINVAL;
539 }
540
541 if (info->var.xres != var->xres ||
542 info->var.yres != var->yres ||
543 info->var.xres_virtual != var->xres_virtual ||
544 info->var.yres_virtual != var->yres_virtual) {
545 pr_debug("%s: Resolution not supported: X%u x Y%u\n",
546 __func__, var->xres, var->yres);
547 return -EINVAL;
548 }
549
550 /*
551 * Memory limit
552 */
553
554 if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
555 pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
556 __func__, var->yres_virtual);
557 return -ENOMEM;
558 }
559
560 return 0;
561}
562
563/* fb_rotate
564 * Rotate the display of this angle. This doesn't seems to be used by the core,
565 * but as our hardware supports it, so why not implementing it...
566 */
567static void bfin_lq035_fb_rotate(struct fb_info *fbi, int angle)
568{
569 pr_debug("%s: %p %d", __func__, fbi, angle);
570#if (defined(UD) && defined(LBR))
571 switch (angle) {
572
573 case 180:
574 gpio_set_value(LBR, 0);
575 gpio_set_value(UD, 1);
576 break;
577 default:
578 gpio_set_value(LBR, 1);
579 gpio_set_value(UD, 0);
580 break;
581 }
582#endif
583}
584
585static int bfin_lq035_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
586{
587 if (nocursor)
588 return 0;
589 else
590 return -EINVAL; /* just to force soft_cursor() call */
591}
592
593static int bfin_lq035_fb_setcolreg(u_int regno, u_int red, u_int green,
594 u_int blue, u_int transp,
595 struct fb_info *info)
596{
597 if (regno >= NBR_PALETTE)
598 return -EINVAL;
599
600 if (info->var.grayscale)
601 /* grayscale = 0.30*R + 0.59*G + 0.11*B */
602 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
603
604 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
605
606 u32 value;
607 /* Place color in the pseudopalette */
608 if (regno > 16)
609 return -EINVAL;
610
611 red >>= (16 - info->var.red.length);
612 green >>= (16 - info->var.green.length);
613 blue >>= (16 - info->var.blue.length);
614
615 value = (red << info->var.red.offset) |
616 (green << info->var.green.offset)|
617 (blue << info->var.blue.offset);
618 value &= 0xFFFF;
619
620 ((u32 *) (info->pseudo_palette))[regno] = value;
621
622 }
623
624 return 0;
625}
626
627static struct fb_ops bfin_lq035_fb_ops = {
628 .owner = THIS_MODULE,
629 .fb_open = bfin_lq035_fb_open,
630 .fb_release = bfin_lq035_fb_release,
631 .fb_check_var = bfin_lq035_fb_check_var,
632 .fb_rotate = bfin_lq035_fb_rotate,
633 .fb_fillrect = cfb_fillrect,
634 .fb_copyarea = cfb_copyarea,
635 .fb_imageblit = cfb_imageblit,
636 .fb_cursor = bfin_lq035_fb_cursor,
637 .fb_setcolreg = bfin_lq035_fb_setcolreg,
638};
639
640static int bl_get_brightness(struct backlight_device *bd)
641{
642 return current_brightness;
643}
644
645static const struct backlight_ops bfin_lq035fb_bl_ops = {
646 .get_brightness = bl_get_brightness,
647};
648
649static struct backlight_device *bl_dev;
650
651static int bfin_lcd_get_power(struct lcd_device *dev)
652{
653 return 0;
654}
655
656static int bfin_lcd_set_power(struct lcd_device *dev, int power)
657{
658 return 0;
659}
660
661static int bfin_lcd_get_contrast(struct lcd_device *dev)
662{
663 return (int)vcomm_value;
664}
665
666static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
667{
668 if (contrast > 255)
669 contrast = 255;
670 if (contrast < 0)
671 contrast = 0;
672
673 vcomm_value = (unsigned char)contrast;
674 set_vcomm();
675 return 0;
676}
677
678static int bfin_lcd_check_fb(struct lcd_device *lcd, struct fb_info *fi)
679{
680 if (!fi || (fi == &bfin_lq035_fb))
681 return 1;
682 return 0;
683}
684
685static struct lcd_ops bfin_lcd_ops = {
686 .get_power = bfin_lcd_get_power,
687 .set_power = bfin_lcd_set_power,
688 .get_contrast = bfin_lcd_get_contrast,
689 .set_contrast = bfin_lcd_set_contrast,
690 .check_fb = bfin_lcd_check_fb,
691};
692
693static struct lcd_device *lcd_dev;
694
695static int __devinit bfin_lq035_probe(struct platform_device *pdev)
696{
697 struct backlight_properties props;
698 dma_addr_t dma_handle;
699
700 if (request_dma(CH_PPI, KBUILD_MODNAME)) {
701 pr_err("couldn't request PPI DMA\n");
702 return -EFAULT;
703 }
704
705 if (request_ports()) {
706 pr_err("couldn't request gpio port\n");
707 free_dma(CH_PPI);
708 return -EFAULT;
709 }
710
711 fb_buffer = dma_alloc_coherent(NULL, TOTAL_VIDEO_MEM_SIZE,
712 &dma_handle, GFP_KERNEL);
713 if (fb_buffer == NULL) {
714 pr_err("couldn't allocate dma buffer\n");
715 free_dma(CH_PPI);
716 free_ports();
717 return -ENOMEM;
718 }
719
720 if (L1_DATA_A_LENGTH)
721 dma_desc_table = l1_data_sram_zalloc(TOTAL_DMA_DESC_SIZE);
722 else
723 dma_desc_table = dma_alloc_coherent(NULL, TOTAL_DMA_DESC_SIZE,
724 &dma_handle, 0);
725
726 if (dma_desc_table == NULL) {
727 pr_err("couldn't allocate dma descriptor\n");
728 free_dma(CH_PPI);
729 free_ports();
730 dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
731 return -ENOMEM;
732 }
733
734 bfin_lq035_fb.screen_base = (void *)fb_buffer;
735 bfin_lq035_fb_fix.smem_start = (int)fb_buffer;
736 if (landscape) {
737 bfin_lq035_fb_defined.xres = LCD_Y_RES;
738 bfin_lq035_fb_defined.yres = LCD_X_RES;
739 bfin_lq035_fb_defined.xres_virtual = LCD_Y_RES;
740 bfin_lq035_fb_defined.yres_virtual = LCD_X_RES;
741
742 bfin_lq035_fb_fix.line_length = LCD_Y_RES*(LCD_BBP/8);
743 } else {
744 bfin_lq035_fb.screen_base += ACTIVE_VIDEO_MEM_OFFSET;
745 bfin_lq035_fb_fix.smem_start += ACTIVE_VIDEO_MEM_OFFSET;
746 }
747
748 bfin_lq035_fb_defined.green.msb_right = 0;
749 bfin_lq035_fb_defined.red.msb_right = 0;
750 bfin_lq035_fb_defined.blue.msb_right = 0;
751 bfin_lq035_fb_defined.green.offset = 5;
752 bfin_lq035_fb_defined.green.length = 6;
753 bfin_lq035_fb_defined.red.length = 5;
754 bfin_lq035_fb_defined.blue.length = 5;
755
756 if (bgr) {
757 bfin_lq035_fb_defined.red.offset = 0;
758 bfin_lq035_fb_defined.blue.offset = 11;
759 } else {
760 bfin_lq035_fb_defined.red.offset = 11;
761 bfin_lq035_fb_defined.blue.offset = 0;
762 }
763
764 bfin_lq035_fb.fbops = &bfin_lq035_fb_ops;
765 bfin_lq035_fb.var = bfin_lq035_fb_defined;
766
767 bfin_lq035_fb.fix = bfin_lq035_fb_fix;
768 bfin_lq035_fb.flags = FBINFO_DEFAULT;
769
770
771 bfin_lq035_fb.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
772 if (bfin_lq035_fb.pseudo_palette == NULL) {
773 pr_err("failed to allocate pseudo_palette\n");
774 free_dma(CH_PPI);
775 free_ports();
776 dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
777 return -ENOMEM;
778 }
779
780 if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) {
781 pr_err("failed to allocate colormap (%d entries)\n",
782 NBR_PALETTE);
783 free_dma(CH_PPI);
784 free_ports();
785 dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
786 kfree(bfin_lq035_fb.pseudo_palette);
787 return -EFAULT;
788 }
789
790 if (register_framebuffer(&bfin_lq035_fb) < 0) {
791 pr_err("unable to register framebuffer\n");
792 free_dma(CH_PPI);
793 free_ports();
794 dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
795 fb_buffer = NULL;
796 kfree(bfin_lq035_fb.pseudo_palette);
797 fb_dealloc_cmap(&bfin_lq035_fb.cmap);
798 return -EINVAL;
799 }
800
801 i2c_add_driver(&ad5280_driver);
802
803 memset(&props, 0, sizeof(props));
804 props.max_brightness = MAX_BRIGHENESS;
805 bl_dev = backlight_device_register("bf537-bl", NULL, NULL,
806 &bfin_lq035fb_bl_ops, &props);
807
808 lcd_dev = lcd_device_register(KBUILD_MODNAME, &pdev->dev, NULL,
809 &bfin_lcd_ops);
810 lcd_dev->props.max_contrast = 255,
811
812 pr_info("initialized");
813
814 return 0;
815}
816
817static int __devexit bfin_lq035_remove(struct platform_device *pdev)
818{
819 if (fb_buffer != NULL)
820 dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
821
822 if (L1_DATA_A_LENGTH)
823 l1_data_sram_free(dma_desc_table);
824 else
825 dma_free_coherent(NULL, TOTAL_DMA_DESC_SIZE, NULL, 0);
826
827 bfin_write_TIMER_DISABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS|
828 TIMEN_LP|TIMEN_REV);
829 t_conf_done = 0;
830
831 free_dma(CH_PPI);
832
833
834 kfree(bfin_lq035_fb.pseudo_palette);
835 fb_dealloc_cmap(&bfin_lq035_fb.cmap);
836
837
838 lcd_device_unregister(lcd_dev);
839 backlight_device_unregister(bl_dev);
840
841 unregister_framebuffer(&bfin_lq035_fb);
842 i2c_del_driver(&ad5280_driver);
843
844 free_ports();
845
846 pr_info("unregistered LCD driver\n");
847
848 return 0;
849}
850
851#ifdef CONFIG_PM
852static int bfin_lq035_suspend(struct platform_device *pdev, pm_message_t state)
853{
854 if (lq035_open_cnt > 0) {
855 bfin_write_PPI_CONTROL(0);
856 SSYNC();
857 disable_dma(CH_PPI);
858 }
859
860 return 0;
861}
862
863static int bfin_lq035_resume(struct platform_device *pdev)
864{
865 if (lq035_open_cnt > 0) {
866 bfin_write_PPI_CONTROL(0);
867 SSYNC();
868
869 config_dma();
870 config_ppi();
871
872 enable_dma(CH_PPI);
873 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
874 SSYNC();
875
876 config_timers();
877 start_timers();
878 } else {
879 t_conf_done = 0;
880 }
881
882 return 0;
883}
884#else
885# define bfin_lq035_suspend NULL
886# define bfin_lq035_resume NULL
887#endif
888
889static struct platform_driver bfin_lq035_driver = {
890 .probe = bfin_lq035_probe,
891 .remove = __devexit_p(bfin_lq035_remove),
892 .suspend = bfin_lq035_suspend,
893 .resume = bfin_lq035_resume,
894 .driver = {
895 .name = KBUILD_MODNAME,
896 .owner = THIS_MODULE,
897 },
898};
899
900static int __init bfin_lq035_driver_init(void)
901{
902 request_module("i2c-bfin-twi");
903 return platform_driver_register(&bfin_lq035_driver);
904}
905module_init(bfin_lq035_driver_init);
906
907static void __exit bfin_lq035_driver_cleanup(void)
908{
909 platform_driver_unregister(&bfin_lq035_driver);
910}
911module_exit(bfin_lq035_driver_cleanup);
912
913MODULE_DESCRIPTION("SHARP LQ035Q7DB03 TFT LCD Driver");
914MODULE_LICENSE("GPL");
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c
new file mode 100644
index 000000000000..8486f541156b
--- /dev/null
+++ b/drivers/video/bfin_adv7393fb.c
@@ -0,0 +1,832 @@
1/*
2 * Frame buffer driver for ADV7393/2 video encoder
3 *
4 * Copyright 2006-2009 Analog Devices Inc.
5 * Licensed under the GPL-2 or late.
6 */
7
8/*
9 * TODO: Remove Globals
10 * TODO: Code Cleanup
11 */
12
13#define pr_fmt(fmt) DRIVER_NAME ": " fmt
14
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/string.h>
19#include <linux/mm.h>
20#include <linux/tty.h>
21#include <linux/slab.h>
22#include <linux/delay.h>
23#include <linux/fb.h>
24#include <linux/ioport.h>
25#include <linux/init.h>
26#include <linux/types.h>
27#include <linux/interrupt.h>
28#include <linux/sched.h>
29#include <asm/blackfin.h>
30#include <asm/irq.h>
31#include <asm/dma.h>
32#include <linux/uaccess.h>
33#include <linux/gpio.h>
34#include <asm/portmux.h>
35
36#include <linux/dma-mapping.h>
37#include <linux/proc_fs.h>
38#include <linux/platform_device.h>
39
40#include <linux/i2c.h>
41#include <linux/i2c-dev.h>
42
43#include "bfin_adv7393fb.h"
44
45static int mode = VMODE;
46static int mem = VMEM;
47static int nocursor = 1;
48
49static const unsigned short ppi_pins[] = {
50 P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
51 P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
52 P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
53 P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
54 P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
55 0
56};
57
58/*
59 * card parameters
60 */
61
62static struct bfin_adv7393_fb_par {
63 /* structure holding blackfin / adv7393 paramters when
64 screen is blanked */
65 struct {
66 u8 Mode; /* ntsc/pal/? */
67 } vga_state;
68 atomic_t ref_count;
69} bfin_par;
70
71/* --------------------------------------------------------------------- */
72
73static struct fb_var_screeninfo bfin_adv7393_fb_defined = {
74 .xres = 720,
75 .yres = 480,
76 .xres_virtual = 720,
77 .yres_virtual = 480,
78 .bits_per_pixel = 16,
79 .activate = FB_ACTIVATE_TEST,
80 .height = -1,
81 .width = -1,
82 .left_margin = 0,
83 .right_margin = 0,
84 .upper_margin = 0,
85 .lower_margin = 0,
86 .vmode = FB_VMODE_INTERLACED,
87 .red = {11, 5, 0},
88 .green = {5, 6, 0},
89 .blue = {0, 5, 0},
90 .transp = {0, 0, 0},
91};
92
93static struct fb_fix_screeninfo bfin_adv7393_fb_fix __devinitdata = {
94 .id = "BFIN ADV7393",
95 .smem_len = 720 * 480 * 2,
96 .type = FB_TYPE_PACKED_PIXELS,
97 .visual = FB_VISUAL_TRUECOLOR,
98 .xpanstep = 0,
99 .ypanstep = 0,
100 .line_length = 720 * 2,
101 .accel = FB_ACCEL_NONE
102};
103
104static struct fb_ops bfin_adv7393_fb_ops = {
105 .owner = THIS_MODULE,
106 .fb_open = bfin_adv7393_fb_open,
107 .fb_release = bfin_adv7393_fb_release,
108 .fb_check_var = bfin_adv7393_fb_check_var,
109 .fb_pan_display = bfin_adv7393_fb_pan_display,
110 .fb_blank = bfin_adv7393_fb_blank,
111 .fb_fillrect = cfb_fillrect,
112 .fb_copyarea = cfb_copyarea,
113 .fb_imageblit = cfb_imageblit,
114 .fb_cursor = bfin_adv7393_fb_cursor,
115 .fb_setcolreg = bfin_adv7393_fb_setcolreg,
116};
117
118static int dma_desc_list(struct adv7393fb_device *fbdev, u16 arg)
119{
120 if (arg == BUILD) { /* Build */
121 fbdev->vb1 = l1_data_sram_zalloc(sizeof(struct dmasg));
122 if (fbdev->vb1 == NULL)
123 goto error;
124
125 fbdev->av1 = l1_data_sram_zalloc(sizeof(struct dmasg));
126 if (fbdev->av1 == NULL)
127 goto error;
128
129 fbdev->vb2 = l1_data_sram_zalloc(sizeof(struct dmasg));
130 if (fbdev->vb2 == NULL)
131 goto error;
132
133 fbdev->av2 = l1_data_sram_zalloc(sizeof(struct dmasg));
134 if (fbdev->av2 == NULL)
135 goto error;
136
137 /* Build linked DMA descriptor list */
138 fbdev->vb1->next_desc_addr = fbdev->av1;
139 fbdev->av1->next_desc_addr = fbdev->vb2;
140 fbdev->vb2->next_desc_addr = fbdev->av2;
141 fbdev->av2->next_desc_addr = fbdev->vb1;
142
143 /* Save list head */
144 fbdev->descriptor_list_head = fbdev->av2;
145
146 /* Vertical Blanking Field 1 */
147 fbdev->vb1->start_addr = VB_DUMMY_MEMORY_SOURCE;
148 fbdev->vb1->cfg = DMA_CFG_VAL;
149
150 fbdev->vb1->x_count =
151 fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
152
153 fbdev->vb1->x_modify = 0;
154 fbdev->vb1->y_count = fbdev->modes[mode].vb1_lines;
155 fbdev->vb1->y_modify = 0;
156
157 /* Active Video Field 1 */
158
159 fbdev->av1->start_addr = (unsigned long)fbdev->fb_mem;
160 fbdev->av1->cfg = DMA_CFG_VAL;
161 fbdev->av1->x_count =
162 fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
163 fbdev->av1->x_modify = fbdev->modes[mode].bpp / 8;
164 fbdev->av1->y_count = fbdev->modes[mode].a_lines;
165 fbdev->av1->y_modify =
166 (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank +
167 1) * (fbdev->modes[mode].bpp / 8);
168
169 /* Vertical Blanking Field 2 */
170
171 fbdev->vb2->start_addr = VB_DUMMY_MEMORY_SOURCE;
172 fbdev->vb2->cfg = DMA_CFG_VAL;
173 fbdev->vb2->x_count =
174 fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
175
176 fbdev->vb2->x_modify = 0;
177 fbdev->vb2->y_count = fbdev->modes[mode].vb2_lines;
178 fbdev->vb2->y_modify = 0;
179
180 /* Active Video Field 2 */
181
182 fbdev->av2->start_addr =
183 (unsigned long)fbdev->fb_mem + fbdev->line_len;
184
185 fbdev->av2->cfg = DMA_CFG_VAL;
186
187 fbdev->av2->x_count =
188 fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank;
189
190 fbdev->av2->x_modify = (fbdev->modes[mode].bpp / 8);
191 fbdev->av2->y_count = fbdev->modes[mode].a_lines;
192
193 fbdev->av2->y_modify =
194 (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank +
195 1) * (fbdev->modes[mode].bpp / 8);
196
197 return 1;
198 }
199
200error:
201 l1_data_sram_free(fbdev->vb1);
202 l1_data_sram_free(fbdev->av1);
203 l1_data_sram_free(fbdev->vb2);
204 l1_data_sram_free(fbdev->av2);
205
206 return 0;
207}
208
209static int bfin_config_dma(struct adv7393fb_device *fbdev)
210{
211 BUG_ON(!(fbdev->fb_mem));
212
213 set_dma_x_count(CH_PPI, fbdev->descriptor_list_head->x_count);
214 set_dma_x_modify(CH_PPI, fbdev->descriptor_list_head->x_modify);
215 set_dma_y_count(CH_PPI, fbdev->descriptor_list_head->y_count);
216 set_dma_y_modify(CH_PPI, fbdev->descriptor_list_head->y_modify);
217 set_dma_start_addr(CH_PPI, fbdev->descriptor_list_head->start_addr);
218 set_dma_next_desc_addr(CH_PPI,
219 fbdev->descriptor_list_head->next_desc_addr);
220 set_dma_config(CH_PPI, fbdev->descriptor_list_head->cfg);
221
222 return 1;
223}
224
225static void bfin_disable_dma(void)
226{
227 bfin_write_DMA0_CONFIG(bfin_read_DMA0_CONFIG() & ~DMAEN);
228}
229
230static void bfin_config_ppi(struct adv7393fb_device *fbdev)
231{
232 if (ANOMALY_05000183) {
233 bfin_write_TIMER2_CONFIG(WDTH_CAP);
234 bfin_write_TIMER_ENABLE(TIMEN2);
235 }
236
237 bfin_write_PPI_CONTROL(0x381E);
238 bfin_write_PPI_FRAME(fbdev->modes[mode].tot_lines);
239 bfin_write_PPI_COUNT(fbdev->modes[mode].xres +
240 fbdev->modes[mode].boeft_blank - 1);
241 bfin_write_PPI_DELAY(fbdev->modes[mode].aoeft_blank - 1);
242}
243
244static void bfin_enable_ppi(void)
245{
246 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
247}
248
249static void bfin_disable_ppi(void)
250{
251 bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
252}
253
254static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value)
255{
256 return i2c_smbus_write_byte_data(client, reg, value);
257}
258
259static inline int adv7393_read(struct i2c_client *client, u8 reg)
260{
261 return i2c_smbus_read_byte_data(client, reg);
262}
263
264static int
265adv7393_write_block(struct i2c_client *client,
266 const u8 *data, unsigned int len)
267{
268 int ret = -1;
269 u8 reg;
270
271 while (len >= 2) {
272 reg = *data++;
273 ret = adv7393_write(client, reg, *data++);
274 if (ret < 0)
275 break;
276 len -= 2;
277 }
278
279 return ret;
280}
281
282static int adv7393_mode(struct i2c_client *client, u16 mode)
283{
284 switch (mode) {
285 case POWER_ON: /* ADV7393 Sleep mode OFF */
286 adv7393_write(client, 0x00, 0x1E);
287 break;
288 case POWER_DOWN: /* ADV7393 Sleep mode ON */
289 adv7393_write(client, 0x00, 0x1F);
290 break;
291 case BLANK_OFF: /* Pixel Data Valid */
292 adv7393_write(client, 0x82, 0xCB);
293 break;
294 case BLANK_ON: /* Pixel Data Invalid */
295 adv7393_write(client, 0x82, 0x8B);
296 break;
297 default:
298 return -EINVAL;
299 break;
300 }
301 return 0;
302}
303
304static irqreturn_t ppi_irq_error(int irq, void *dev_id)
305{
306
307 struct adv7393fb_device *fbdev = (struct adv7393fb_device *)dev_id;
308
309 u16 status = bfin_read_PPI_STATUS();
310
311 pr_debug("%s: PPI Status = 0x%X\n", __func__, status);
312
313 if (status) {
314 bfin_disable_dma(); /* TODO: Check Sequence */
315 bfin_disable_ppi();
316 bfin_clear_PPI_STATUS();
317 bfin_config_dma(fbdev);
318 bfin_enable_ppi();
319 }
320
321 return IRQ_HANDLED;
322
323}
324
325static int proc_output(char *buf)
326{
327 char *p = buf;
328
329 p += sprintf(p,
330 "Usage:\n"
331 "echo 0x[REG][Value] > adv7393\n"
332 "example: echo 0x1234 >adv7393\n"
333 "writes 0x34 into Register 0x12\n");
334
335 return p - buf;
336}
337
338static int
339adv7393_read_proc(char *page, char **start, off_t off,
340 int count, int *eof, void *data)
341{
342 int len;
343
344 len = proc_output(page);
345 if (len <= off + count)
346 *eof = 1;
347 *start = page + off;
348 len -= off;
349 if (len > count)
350 len = count;
351 if (len < 0)
352 len = 0;
353 return len;
354}
355
356static int
357adv7393_write_proc(struct file *file, const char __user * buffer,
358 unsigned long count, void *data)
359{
360 struct adv7393fb_device *fbdev = data;
361 char line[8];
362 unsigned int val;
363 int ret;
364
365 ret = copy_from_user(line, buffer, count);
366 if (ret)
367 return -EFAULT;
368
369 val = simple_strtoul(line, NULL, 0);
370 adv7393_write(fbdev->client, val >> 8, val & 0xff);
371
372 return count;
373}
374
375static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
376 const struct i2c_device_id *id)
377{
378 int ret = 0;
379 struct proc_dir_entry *entry;
380 int num_modes = ARRAY_SIZE(known_modes);
381
382 struct adv7393fb_device *fbdev = NULL;
383
384 if (mem > 2) {
385 dev_err(&client->dev, "mem out of allowed range [1;2]\n");
386 return -EINVAL;
387 }
388
389 if (mode > num_modes) {
390 dev_err(&client->dev, "mode %d: not supported", mode);
391 return -EFAULT;
392 }
393
394 fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
395 if (!fbdev) {
396 dev_err(&client->dev, "failed to allocate device private record");
397 return -ENOMEM;
398 }
399
400 i2c_set_clientdata(client, fbdev);
401
402 fbdev->modes = known_modes;
403 fbdev->client = client;
404
405 fbdev->fb_len =
406 mem * fbdev->modes[mode].xres * fbdev->modes[mode].xres *
407 (fbdev->modes[mode].bpp / 8);
408
409 fbdev->line_len =
410 fbdev->modes[mode].xres * (fbdev->modes[mode].bpp / 8);
411
412 /* Workaround "PPI Does Not Start Properly In Specific Mode" */
413 if (ANOMALY_05000400) {
414 if (gpio_request(P_IDENT(P_PPI0_FS3), "PPI0_FS3")) {
415 dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n");
416 ret = -EBUSY;
417 goto out_8;
418 }
419 gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
420 }
421
422 if (peripheral_request_list(ppi_pins, DRIVER_NAME)) {
423 dev_err(&client->dev, "requesting PPI peripheral failed\n");
424 ret = -EFAULT;
425 goto out_8;
426 }
427
428 fbdev->fb_mem =
429 dma_alloc_coherent(NULL, fbdev->fb_len, &fbdev->dma_handle,
430 GFP_KERNEL);
431
432 if (NULL == fbdev->fb_mem) {
433 dev_err(&client->dev, "couldn't allocate dma buffer (%d bytes)\n",
434 (u32) fbdev->fb_len);
435 ret = -ENOMEM;
436 goto out_7;
437 }
438
439 fbdev->info.screen_base = (void *)fbdev->fb_mem;
440 bfin_adv7393_fb_fix.smem_start = (int)fbdev->fb_mem;
441
442 bfin_adv7393_fb_fix.smem_len = fbdev->fb_len;
443 bfin_adv7393_fb_fix.line_length = fbdev->line_len;
444
445 if (mem > 1)
446 bfin_adv7393_fb_fix.ypanstep = 1;
447
448 bfin_adv7393_fb_defined.red.length = 5;
449 bfin_adv7393_fb_defined.green.length = 6;
450 bfin_adv7393_fb_defined.blue.length = 5;
451
452 bfin_adv7393_fb_defined.xres = fbdev->modes[mode].xres;
453 bfin_adv7393_fb_defined.yres = fbdev->modes[mode].yres;
454 bfin_adv7393_fb_defined.xres_virtual = fbdev->modes[mode].xres;
455 bfin_adv7393_fb_defined.yres_virtual = mem * fbdev->modes[mode].yres;
456 bfin_adv7393_fb_defined.bits_per_pixel = fbdev->modes[mode].bpp;
457
458 fbdev->info.fbops = &bfin_adv7393_fb_ops;
459 fbdev->info.var = bfin_adv7393_fb_defined;
460 fbdev->info.fix = bfin_adv7393_fb_fix;
461 fbdev->info.par = &bfin_par;
462 fbdev->info.flags = FBINFO_DEFAULT;
463
464 fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
465 if (!fbdev->info.pseudo_palette) {
466 dev_err(&client->dev, "failed to allocate pseudo_palette\n");
467 ret = -ENOMEM;
468 goto out_6;
469 }
470
471 if (fb_alloc_cmap(&fbdev->info.cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
472 dev_err(&client->dev, "failed to allocate colormap (%d entries)\n",
473 BFIN_LCD_NBR_PALETTE_ENTRIES);
474 ret = -EFAULT;
475 goto out_5;
476 }
477
478 if (request_dma(CH_PPI, "BF5xx_PPI_DMA") < 0) {
479 dev_err(&client->dev, "unable to request PPI DMA\n");
480 ret = -EFAULT;
481 goto out_4;
482 }
483
484 if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, IRQF_DISABLED,
485 "PPI ERROR", fbdev) < 0) {
486 dev_err(&client->dev, "unable to request PPI ERROR IRQ\n");
487 ret = -EFAULT;
488 goto out_3;
489 }
490
491 fbdev->open = 0;
492
493 ret = adv7393_write_block(client, fbdev->modes[mode].adv7393_i2c_initd,
494 fbdev->modes[mode].adv7393_i2c_initd_len);
495
496 if (ret) {
497 dev_err(&client->dev, "i2c attach: init error\n");
498 goto out_1;
499 }
500
501
502 if (register_framebuffer(&fbdev->info) < 0) {
503 dev_err(&client->dev, "unable to register framebuffer\n");
504 ret = -EFAULT;
505 goto out_1;
506 }
507
508 dev_info(&client->dev, "fb%d: %s frame buffer device\n",
509 fbdev->info.node, fbdev->info.fix.id);
510 dev_info(&client->dev, "fb memory address : 0x%p\n", fbdev->fb_mem);
511
512 entry = create_proc_entry("driver/adv7393", 0, NULL);
513 if (!entry) {
514 dev_err(&client->dev, "unable to create /proc entry\n");
515 ret = -EFAULT;
516 goto out_0;
517 }
518
519 entry->read_proc = adv7393_read_proc;
520 entry->write_proc = adv7393_write_proc;
521 entry->data = fbdev;
522
523 return 0;
524
525 out_0:
526 unregister_framebuffer(&fbdev->info);
527 out_1:
528 free_irq(IRQ_PPI_ERROR, fbdev);
529 out_3:
530 free_dma(CH_PPI);
531 out_4:
532 dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem,
533 fbdev->dma_handle);
534 out_5:
535 fb_dealloc_cmap(&fbdev->info.cmap);
536 out_6:
537 kfree(fbdev->info.pseudo_palette);
538 out_7:
539 peripheral_free_list(ppi_pins);
540 out_8:
541 kfree(fbdev);
542
543 return ret;
544}
545
546static int bfin_adv7393_fb_open(struct fb_info *info, int user)
547{
548 struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
549
550 fbdev->info.screen_base = (void *)fbdev->fb_mem;
551 if (!fbdev->info.screen_base) {
552 dev_err(&fbdev->client->dev, "unable to map device\n");
553 return -ENOMEM;
554 }
555
556 fbdev->open = 1;
557 dma_desc_list(fbdev, BUILD);
558 adv7393_mode(fbdev->client, BLANK_OFF);
559 bfin_config_ppi(fbdev);
560 bfin_config_dma(fbdev);
561 bfin_enable_ppi();
562
563 return 0;
564}
565
566static int bfin_adv7393_fb_release(struct fb_info *info, int user)
567{
568 struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
569
570 adv7393_mode(fbdev->client, BLANK_ON);
571 bfin_disable_dma();
572 bfin_disable_ppi();
573 dma_desc_list(fbdev, DESTRUCT);
574 fbdev->open = 0;
575 return 0;
576}
577
578static int
579bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
580{
581
582 switch (var->bits_per_pixel) {
583 case 16:/* DIRECTCOLOUR, 64k */
584 var->red.offset = info->var.red.offset;
585 var->green.offset = info->var.green.offset;
586 var->blue.offset = info->var.blue.offset;
587 var->red.length = info->var.red.length;
588 var->green.length = info->var.green.length;
589 var->blue.length = info->var.blue.length;
590 var->transp.offset = 0;
591 var->transp.length = 0;
592 var->transp.msb_right = 0;
593 var->red.msb_right = 0;
594 var->green.msb_right = 0;
595 var->blue.msb_right = 0;
596 break;
597 default:
598 pr_debug("%s: depth not supported: %u BPP\n", __func__,
599 var->bits_per_pixel);
600 return -EINVAL;
601 }
602
603 if (info->var.xres != var->xres ||
604 info->var.yres != var->yres ||
605 info->var.xres_virtual != var->xres_virtual ||
606 info->var.yres_virtual != var->yres_virtual) {
607 pr_debug("%s: Resolution not supported: X%u x Y%u\n",
608 __func__, var->xres, var->yres);
609 return -EINVAL;
610 }
611
612 /*
613 * Memory limit
614 */
615
616 if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
617 pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
618 __func__, var->yres_virtual);
619 return -ENOMEM;
620 }
621
622 return 0;
623}
624
625static int
626bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
627{
628 int dy;
629 u32 dmaaddr;
630 struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
631
632 if (!var || !info)
633 return -EINVAL;
634
635 if (var->xoffset - info->var.xoffset) {
636 /* No support for X panning for now! */
637 return -EINVAL;
638 }
639 dy = var->yoffset - info->var.yoffset;
640
641 if (dy) {
642 pr_debug("%s: Panning screen of %d lines\n", __func__, dy);
643
644 dmaaddr = fbdev->av1->start_addr;
645 dmaaddr += (info->fix.line_length * dy);
646 /* TODO: Wait for current frame to finished */
647
648 fbdev->av1->start_addr = (unsigned long)dmaaddr;
649 fbdev->av2->start_addr = (unsigned long)dmaaddr + fbdev->line_len;
650 }
651
652 return 0;
653
654}
655
656/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
657static int bfin_adv7393_fb_blank(int blank, struct fb_info *info)
658{
659 struct adv7393fb_device *fbdev = to_adv7393fb_device(info);
660
661 switch (blank) {
662
663 case VESA_NO_BLANKING:
664 /* Turn on panel */
665 adv7393_mode(fbdev->client, BLANK_OFF);
666 break;
667
668 case VESA_VSYNC_SUSPEND:
669 case VESA_HSYNC_SUSPEND:
670 case VESA_POWERDOWN:
671 /* Turn off panel */
672 adv7393_mode(fbdev->client, BLANK_ON);
673 break;
674
675 default:
676 return -EINVAL;
677 break;
678 }
679 return 0;
680}
681
682int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
683{
684 if (nocursor)
685 return 0;
686 else
687 return -EINVAL; /* just to force soft_cursor() call */
688}
689
690static int bfin_adv7393_fb_setcolreg(u_int regno, u_int red, u_int green,
691 u_int blue, u_int transp,
692 struct fb_info *info)
693{
694 if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
695 return -EINVAL;
696
697 if (info->var.grayscale)
698 /* grayscale = 0.30*R + 0.59*G + 0.11*B */
699 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
700
701 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
702 u32 value;
703 /* Place color in the pseudopalette */
704 if (regno > 16)
705 return -EINVAL;
706
707 red >>= (16 - info->var.red.length);
708 green >>= (16 - info->var.green.length);
709 blue >>= (16 - info->var.blue.length);
710
711 value = (red << info->var.red.offset) |
712 (green << info->var.green.offset)|
713 (blue << info->var.blue.offset);
714 value &= 0xFFFF;
715
716 ((u32 *) (info->pseudo_palette))[regno] = value;
717 }
718
719 return 0;
720}
721
722static int __devexit bfin_adv7393_fb_remove(struct i2c_client *client)
723{
724 struct adv7393fb_device *fbdev = i2c_get_clientdata(client);
725
726 adv7393_mode(client, POWER_DOWN);
727
728 if (fbdev->fb_mem)
729 dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem, fbdev->dma_handle);
730 free_dma(CH_PPI);
731 free_irq(IRQ_PPI_ERROR, fbdev);
732 unregister_framebuffer(&fbdev->info);
733 remove_proc_entry("driver/adv7393", NULL);
734 fb_dealloc_cmap(&fbdev->info.cmap);
735 kfree(fbdev->info.pseudo_palette);
736
737 if (ANOMALY_05000400)
738 gpio_free(P_IDENT(P_PPI0_FS3)); /* FS3 */
739 peripheral_free_list(ppi_pins);
740 kfree(fbdev);
741
742 return 0;
743}
744
745#ifdef CONFIG_PM
746static int bfin_adv7393_fb_suspend(struct device *dev)
747{
748 struct adv7393fb_device *fbdev = dev_get_drvdata(dev);
749
750 if (fbdev->open) {
751 bfin_disable_dma();
752 bfin_disable_ppi();
753 dma_desc_list(fbdev, DESTRUCT);
754 }
755 adv7393_mode(fbdev->client, POWER_DOWN);
756
757 return 0;
758}
759
760static int bfin_adv7393_fb_resume(struct device *dev)
761{
762 struct adv7393fb_device *fbdev = dev_get_drvdata(dev);
763
764 adv7393_mode(fbdev->client, POWER_ON);
765
766 if (fbdev->open) {
767 dma_desc_list(fbdev, BUILD);
768 bfin_config_ppi(fbdev);
769 bfin_config_dma(fbdev);
770 bfin_enable_ppi();
771 }
772
773 return 0;
774}
775
776static const struct dev_pm_ops bfin_adv7393_dev_pm_ops = {
777 .suspend = bfin_adv7393_fb_suspend,
778 .resume = bfin_adv7393_fb_resume,
779};
780#endif
781
782static const struct i2c_device_id bfin_adv7393_id[] = {
783 {DRIVER_NAME, 0},
784 {}
785};
786
787MODULE_DEVICE_TABLE(i2c, bfin_adv7393_id);
788
789static struct i2c_driver bfin_adv7393_fb_driver = {
790 .driver = {
791 .name = DRIVER_NAME,
792#ifdef CONFIG_PM
793 .pm = &bfin_adv7393_dev_pm_ops,
794#endif
795 },
796 .probe = bfin_adv7393_fb_probe,
797 .remove = __devexit_p(bfin_adv7393_fb_remove),
798 .id_table = bfin_adv7393_id,
799};
800
801static int __init bfin_adv7393_fb_driver_init(void)
802{
803#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
804 request_module("i2c-bfin-twi");
805#else
806 request_module("i2c-gpio");
807#endif
808
809 return i2c_add_driver(&bfin_adv7393_fb_driver);
810}
811module_init(bfin_adv7393_fb_driver_init);
812
813static void __exit bfin_adv7393_fb_driver_cleanup(void)
814{
815 i2c_del_driver(&bfin_adv7393_fb_driver);
816}
817module_exit(bfin_adv7393_fb_driver_cleanup);
818
819MODULE_LICENSE("GPL");
820MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
821MODULE_DESCRIPTION("Frame buffer driver for ADV7393/2 Video Encoder");
822
823module_param(mode, int, 0);
824MODULE_PARM_DESC(mode,
825 "Video Mode (0=NTSC,1=PAL,2=NTSC 640x480,3=PAL 640x480,4=NTSC YCbCr input,5=PAL YCbCr input)");
826
827module_param(mem, int, 0);
828MODULE_PARM_DESC(mem,
829 "Size of frame buffer memory 1=Single 2=Double Size (allows y-panning / frame stacking)");
830
831module_param(nocursor, int, 0644);
832MODULE_PARM_DESC(nocursor, "cursor enable/disable");
diff --git a/drivers/video/bfin_adv7393fb.h b/drivers/video/bfin_adv7393fb.h
new file mode 100644
index 000000000000..8c7f9e4fc6eb
--- /dev/null
+++ b/drivers/video/bfin_adv7393fb.h
@@ -0,0 +1,321 @@
1/*
2 * Frame buffer driver for ADV7393/2 video encoder
3 *
4 * Copyright 2006-2009 Analog Devices Inc.
5 * Licensed under the GPL-2 or late.
6 */
7
8#ifndef __BFIN_ADV7393FB_H__
9#define __BFIN_ADV7393FB_H__
10
11#define BFIN_LCD_NBR_PALETTE_ENTRIES 256
12
13#ifdef CONFIG_NTSC
14# define VMODE 0
15#endif
16#ifdef CONFIG_PAL
17# define VMODE 1
18#endif
19#ifdef CONFIG_NTSC_640x480
20# define VMODE 2
21#endif
22#ifdef CONFIG_PAL_640x480
23# define VMODE 3
24#endif
25#ifdef CONFIG_NTSC_YCBCR
26# define VMODE 4
27#endif
28#ifdef CONFIG_PAL_YCBCR
29# define VMODE 5
30#endif
31
32#ifndef VMODE
33# define VMODE 1
34#endif
35
36#ifdef CONFIG_ADV7393_2XMEM
37# define VMEM 2
38#else
39# define VMEM 1
40#endif
41
42#if defined(CONFIG_BF537) || defined(CONFIG_BF536) || defined(CONFIG_BF534)
43# define DMA_CFG_VAL 0x7935 /* Set Sync Bit */
44# define VB_DUMMY_MEMORY_SOURCE L1_DATA_B_START
45#else
46# define DMA_CFG_VAL 0x7915
47# define VB_DUMMY_MEMORY_SOURCE BOOT_ROM_START
48#endif
49
50enum {
51 DESTRUCT,
52 BUILD,
53};
54
55enum {
56 POWER_ON,
57 POWER_DOWN,
58 BLANK_ON,
59 BLANK_OFF,
60};
61
62#define DRIVER_NAME "bfin-adv7393"
63
64struct adv7393fb_modes {
65 const s8 name[25]; /* Full name */
66 u16 xres; /* Active Horizonzal Pixels */
67 u16 yres; /* Active Vertical Pixels */
68 u16 bpp;
69 u16 vmode;
70 u16 a_lines; /* Active Lines per Field */
71 u16 vb1_lines; /* Vertical Blanking Field 1 Lines */
72 u16 vb2_lines; /* Vertical Blanking Field 2 Lines */
73 u16 tot_lines; /* Total Lines per Frame */
74 u16 boeft_blank; /* Before Odd/Even Field Transition No. of Blank Pixels */
75 u16 aoeft_blank; /* After Odd/Even Field Transition No. of Blank Pixels */
76 const s8 *adv7393_i2c_initd;
77 u16 adv7393_i2c_initd_len;
78};
79
80static const u8 init_NTSC_TESTPATTERN[] = {
81 0x00, 0x1E, /* Power up all DACs and PLL */
82 0x01, 0x00, /* SD-Only Mode */
83 0x80, 0x10, /* SSAF Luma Filter Enabled, NTSC Mode */
84 0x82, 0xCB, /* Step control on, pixel data valid, pedestal on, PrPb SSAF on, CVBS/YC output */
85 0x84, 0x40, /* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
86};
87
88static const u8 init_NTSC[] = {
89 0x00, 0x1E, /* Power up all DACs and PLL */
90 0xC3, 0x26, /* Program RGB->YCrCb Color Space convertion matrix */
91 0xC5, 0x12, /* Program RGB->YCrCb Color Space convertion matrix */
92 0xC2, 0x4A, /* Program RGB->YCrCb Color Space convertion matrix */
93 0xC6, 0x5E, /* Program RGB->YCrCb Color Space convertion matrix */
94 0xBD, 0x19, /* Program RGB->YCrCb Color Space convertion matrix */
95 0xBF, 0x42, /* Program RGB->YCrCb Color Space convertion matrix */
96 0x8C, 0x1F, /* NTSC Subcarrier Frequency */
97 0x8D, 0x7C, /* NTSC Subcarrier Frequency */
98 0x8E, 0xF0, /* NTSC Subcarrier Frequency */
99 0x8F, 0x21, /* NTSC Subcarrier Frequency */
100 0x01, 0x00, /* SD-Only Mode */
101 0x80, 0x30, /* SSAF Luma Filter Enabled, NTSC Mode */
102 0x82, 0x8B, /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
103 0x87, 0x80, /* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
104 0x86, 0x82,
105 0x8B, 0x11,
106 0x88, 0x20,
107 0x8A, 0x0d,
108};
109
110static const u8 init_PAL[] = {
111 0x00, 0x1E, /* Power up all DACs and PLL */
112 0xC3, 0x26, /* Program RGB->YCrCb Color Space convertion matrix */
113 0xC5, 0x12, /* Program RGB->YCrCb Color Space convertion matrix */
114 0xC2, 0x4A, /* Program RGB->YCrCb Color Space convertion matrix */
115 0xC6, 0x5E, /* Program RGB->YCrCb Color Space convertion matrix */
116 0xBD, 0x19, /* Program RGB->YCrCb Color Space convertion matrix */
117 0xBF, 0x42, /* Program RGB->YCrCb Color Space convertion matrix */
118 0x8C, 0xCB, /* PAL Subcarrier Frequency */
119 0x8D, 0x8A, /* PAL Subcarrier Frequency */
120 0x8E, 0x09, /* PAL Subcarrier Frequency */
121 0x8F, 0x2A, /* PAL Subcarrier Frequency */
122 0x01, 0x00, /* SD-Only Mode */
123 0x80, 0x11, /* SSAF Luma Filter Enabled, PAL Mode */
124 0x82, 0x8B, /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
125 0x87, 0x80, /* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
126 0x86, 0x82,
127 0x8B, 0x11,
128 0x88, 0x20,
129 0x8A, 0x0d,
130};
131
132static const u8 init_NTSC_YCbCr[] = {
133 0x00, 0x1E, /* Power up all DACs and PLL */
134 0x8C, 0x1F, /* NTSC Subcarrier Frequency */
135 0x8D, 0x7C, /* NTSC Subcarrier Frequency */
136 0x8E, 0xF0, /* NTSC Subcarrier Frequency */
137 0x8F, 0x21, /* NTSC Subcarrier Frequency */
138 0x01, 0x00, /* SD-Only Mode */
139 0x80, 0x30, /* SSAF Luma Filter Enabled, NTSC Mode */
140 0x82, 0x8B, /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
141 0x87, 0x00, /* DAC 2 = Luma, DAC 3 = Chroma */
142 0x86, 0x82,
143 0x8B, 0x11,
144 0x88, 0x08,
145 0x8A, 0x0d,
146};
147
148static const u8 init_PAL_YCbCr[] = {
149 0x00, 0x1E, /* Power up all DACs and PLL */
150 0x8C, 0xCB, /* PAL Subcarrier Frequency */
151 0x8D, 0x8A, /* PAL Subcarrier Frequency */
152 0x8E, 0x09, /* PAL Subcarrier Frequency */
153 0x8F, 0x2A, /* PAL Subcarrier Frequency */
154 0x01, 0x00, /* SD-Only Mode */
155 0x80, 0x11, /* SSAF Luma Filter Enabled, PAL Mode */
156 0x82, 0x8B, /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
157 0x87, 0x00, /* DAC 2 = Luma, DAC 3 = Chroma */
158 0x86, 0x82,
159 0x8B, 0x11,
160 0x88, 0x08,
161 0x8A, 0x0d,
162};
163
164static struct adv7393fb_modes known_modes[] = {
165 /* NTSC 720x480 CRT */
166 {
167 .name = "NTSC 720x480",
168 .xres = 720,
169 .yres = 480,
170 .bpp = 16,
171 .vmode = FB_VMODE_INTERLACED,
172 .a_lines = 240,
173 .vb1_lines = 22,
174 .vb2_lines = 23,
175 .tot_lines = 525,
176 .boeft_blank = 16,
177 .aoeft_blank = 122,
178 .adv7393_i2c_initd = init_NTSC,
179 .adv7393_i2c_initd_len = sizeof(init_NTSC)
180 },
181 /* PAL 720x480 CRT */
182 {
183 .name = "PAL 720x576",
184 .xres = 720,
185 .yres = 576,
186 .bpp = 16,
187 .vmode = FB_VMODE_INTERLACED,
188 .a_lines = 288,
189 .vb1_lines = 24,
190 .vb2_lines = 25,
191 .tot_lines = 625,
192 .boeft_blank = 12,
193 .aoeft_blank = 132,
194 .adv7393_i2c_initd = init_PAL,
195 .adv7393_i2c_initd_len = sizeof(init_PAL)
196 },
197 /* NTSC 640x480 CRT Experimental */
198 {
199 .name = "NTSC 640x480",
200 .xres = 640,
201 .yres = 480,
202 .bpp = 16,
203 .vmode = FB_VMODE_INTERLACED,
204 .a_lines = 240,
205 .vb1_lines = 22,
206 .vb2_lines = 23,
207 .tot_lines = 525,
208 .boeft_blank = 16 + 40,
209 .aoeft_blank = 122 + 40,
210 .adv7393_i2c_initd = init_NTSC,
211 .adv7393_i2c_initd_len = sizeof(init_NTSC)
212 },
213 /* PAL 640x480 CRT Experimental */
214 {
215 .name = "PAL 640x480",
216 .xres = 640,
217 .yres = 480,
218 .bpp = 16,
219 .vmode = FB_VMODE_INTERLACED,
220 .a_lines = 288 - 20,
221 .vb1_lines = 24 + 20,
222 .vb2_lines = 25 + 20,
223 .tot_lines = 625,
224 .boeft_blank = 12 + 40,
225 .aoeft_blank = 132 + 40,
226 .adv7393_i2c_initd = init_PAL,
227 .adv7393_i2c_initd_len = sizeof(init_PAL)
228 },
229 /* NTSC 720x480 YCbCR */
230 {
231 .name = "NTSC 720x480 YCbCR",
232 .xres = 720,
233 .yres = 480,
234 .bpp = 16,
235 .vmode = FB_VMODE_INTERLACED,
236 .a_lines = 240,
237 .vb1_lines = 22,
238 .vb2_lines = 23,
239 .tot_lines = 525,
240 .boeft_blank = 16,
241 .aoeft_blank = 122,
242 .adv7393_i2c_initd = init_NTSC_YCbCr,
243 .adv7393_i2c_initd_len = sizeof(init_NTSC_YCbCr)
244 },
245 /* PAL 720x480 CRT */
246 {
247 .name = "PAL 720x576 YCbCR",
248 .xres = 720,
249 .yres = 576,
250 .bpp = 16,
251 .vmode = FB_VMODE_INTERLACED,
252 .a_lines = 288,
253 .vb1_lines = 24,
254 .vb2_lines = 25,
255 .tot_lines = 625,
256 .boeft_blank = 12,
257 .aoeft_blank = 132,
258 .adv7393_i2c_initd = init_PAL_YCbCr,
259 .adv7393_i2c_initd_len = sizeof(init_PAL_YCbCr)
260 }
261};
262
263struct adv7393fb_regs {
264
265};
266
267struct adv7393fb_device {
268 struct fb_info info; /* FB driver info record */
269
270 struct i2c_client *client;
271
272 struct dmasg *descriptor_list_head;
273 struct dmasg *vb1;
274 struct dmasg *av1;
275 struct dmasg *vb2;
276 struct dmasg *av2;
277
278 dma_addr_t dma_handle;
279
280 struct fb_info bfin_adv7393_fb;
281
282 struct adv7393fb_modes *modes;
283
284 struct adv7393fb_regs *regs; /* Registers memory map */
285 size_t regs_len;
286 size_t fb_len;
287 size_t line_len;
288 u16 open;
289 u16 *fb_mem; /* RGB Buffer */
290
291};
292
293#define to_adv7393fb_device(_info) \
294 (_info ? container_of(_info, struct adv7393fb_device, info) : NULL);
295
296static int bfin_adv7393_fb_open(struct fb_info *info, int user);
297static int bfin_adv7393_fb_release(struct fb_info *info, int user);
298static int bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var,
299 struct fb_info *info);
300
301static int bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var,
302 struct fb_info *info);
303
304static int bfin_adv7393_fb_blank(int blank, struct fb_info *info);
305
306static void bfin_config_ppi(struct adv7393fb_device *fbdev);
307static int bfin_config_dma(struct adv7393fb_device *fbdev);
308static void bfin_disable_dma(void);
309static void bfin_enable_ppi(void);
310static void bfin_disable_ppi(void);
311
312static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value);
313static inline int adv7393_read(struct i2c_client *client, u8 reg);
314static int adv7393_write_block(struct i2c_client *client, const u8 *data,
315 unsigned int len);
316
317int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
318static int bfin_adv7393_fb_setcolreg(u_int, u_int, u_int, u_int,
319 u_int, struct fb_info *info);
320
321#endif
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 563a98b88e9b..4f57485f8c54 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -973,6 +973,90 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
973 DPRINTK("========================================\n"); 973 DPRINTK("========================================\n");
974} 974}
975 975
976/**
977 * fb_edid_add_monspecs() - add monitor video modes from E-EDID data
978 * @edid: 128 byte array with an E-EDID block
979 * @spacs: monitor specs to be extended
980 */
981void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
982{
983 unsigned char *block;
984 struct fb_videomode *m;
985 int num = 0, i;
986 u8 svd[64], edt[(128 - 4) / DETAILED_TIMING_DESCRIPTION_SIZE];
987 u8 pos = 4, svd_n = 0;
988
989 if (!edid)
990 return;
991
992 if (!edid_checksum(edid))
993 return;
994
995 if (edid[0] != 0x2 ||
996 edid[2] < 4 || edid[2] > 128 - DETAILED_TIMING_DESCRIPTION_SIZE)
997 return;
998
999 DPRINTK(" Short Video Descriptors\n");
1000
1001 while (pos < edid[2]) {
1002 u8 len = edid[pos] & 0x1f, type = (edid[pos] >> 5) & 7;
1003 pr_debug("Data block %u of %u bytes\n", type, len);
1004 if (type == 2)
1005 for (i = pos; i < pos + len; i++) {
1006 u8 idx = edid[pos + i] & 0x7f;
1007 svd[svd_n++] = idx;
1008 pr_debug("N%sative mode #%d\n",
1009 edid[pos + i] & 0x80 ? "" : "on-n", idx);
1010 }
1011 pos += len + 1;
1012 }
1013
1014 block = edid + edid[2];
1015
1016 DPRINTK(" Extended Detailed Timings\n");
1017
1018 for (i = 0; i < (128 - edid[2]) / DETAILED_TIMING_DESCRIPTION_SIZE;
1019 i++, block += DETAILED_TIMING_DESCRIPTION_SIZE)
1020 if (PIXEL_CLOCK)
1021 edt[num++] = block - edid;
1022
1023 /* Yikes, EDID data is totally useless */
1024 if (!(num + svd_n))
1025 return;
1026
1027 m = kzalloc((specs->modedb_len + num + svd_n) *
1028 sizeof(struct fb_videomode), GFP_KERNEL);
1029
1030 if (!m)
1031 return;
1032
1033 memcpy(m, specs->modedb, specs->modedb_len * sizeof(struct fb_videomode));
1034
1035 for (i = specs->modedb_len; i < specs->modedb_len + num; i++) {
1036 get_detailed_timing(edid + edt[i - specs->modedb_len], &m[i]);
1037 if (i == specs->modedb_len)
1038 m[i].flag |= FB_MODE_IS_FIRST;
1039 pr_debug("Adding %ux%u@%u\n", m[i].xres, m[i].yres, m[i].refresh);
1040 }
1041
1042 for (i = specs->modedb_len + num; i < specs->modedb_len + num + svd_n; i++) {
1043 int idx = svd[i - specs->modedb_len - num];
1044 if (!idx || idx > 63) {
1045 pr_warning("Reserved SVD code %d\n", idx);
1046 } else if (idx > ARRAY_SIZE(cea_modes) || !cea_modes[idx].xres) {
1047 pr_warning("Unimplemented SVD code %d\n", idx);
1048 } else {
1049 memcpy(&m[i], cea_modes + idx, sizeof(m[i]));
1050 pr_debug("Adding SVD #%d: %ux%u@%u\n", idx,
1051 m[i].xres, m[i].yres, m[i].refresh);
1052 }
1053 }
1054
1055 kfree(specs->modedb);
1056 specs->modedb = m;
1057 specs->modedb_len = specs->modedb_len + num + svd_n;
1058}
1059
976/* 1060/*
977 * VESA Generalized Timing Formula (GTF) 1061 * VESA Generalized Timing Formula (GTF)
978 */ 1062 */
@@ -1289,6 +1373,9 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
1289{ 1373{
1290 specs = NULL; 1374 specs = NULL;
1291} 1375}
1376void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
1377{
1378}
1292void fb_destroy_modedb(struct fb_videomode *modedb) 1379void fb_destroy_modedb(struct fb_videomode *modedb)
1293{ 1380{
1294} 1381}
@@ -1396,6 +1483,7 @@ EXPORT_SYMBOL(fb_firmware_edid);
1396 1483
1397EXPORT_SYMBOL(fb_parse_edid); 1484EXPORT_SYMBOL(fb_parse_edid);
1398EXPORT_SYMBOL(fb_edid_to_monspecs); 1485EXPORT_SYMBOL(fb_edid_to_monspecs);
1486EXPORT_SYMBOL(fb_edid_add_monspecs);
1399EXPORT_SYMBOL(fb_get_mode); 1487EXPORT_SYMBOL(fb_get_mode);
1400EXPORT_SYMBOL(fb_validate_mode); 1488EXPORT_SYMBOL(fb_validate_mode);
1401EXPORT_SYMBOL(fb_destroy_modedb); 1489EXPORT_SYMBOL(fb_destroy_modedb);
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index de450c1fb869..7a61ba6a4850 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -278,6 +278,53 @@ static const struct fb_videomode modedb[] = {
278}; 278};
279 279
280#ifdef CONFIG_FB_MODE_HELPERS 280#ifdef CONFIG_FB_MODE_HELPERS
281const struct fb_videomode cea_modes[64] = {
282 /* #1: 640x480p@59.94/60Hz */
283 [1] = {
284 NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED, 0,
285 },
286 /* #3: 720x480p@59.94/60Hz */
287 [3] = {
288 NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0, FB_VMODE_NONINTERLACED, 0,
289 },
290 /* #5: 1920x1080i@59.94/60Hz */
291 [5] = {
292 NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5,
293 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED, 0,
294 },
295 /* #7: 720(1440)x480iH@59.94/60Hz */
296 [7] = {
297 NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0, FB_VMODE_INTERLACED, 0,
298 },
299 /* #9: 720(1440)x240pH@59.94/60Hz */
300 [9] = {
301 NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0, FB_VMODE_NONINTERLACED, 0,
302 },
303 /* #18: 720x576pH@50Hz */
304 [18] = {
305 NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0, FB_VMODE_NONINTERLACED, 0,
306 },
307 /* #19: 1280x720p@50Hz */
308 [19] = {
309 NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5,
310 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0,
311 },
312 /* #20: 1920x1080i@50Hz */
313 [20] = {
314 NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5,
315 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED, 0,
316 },
317 /* #32: 1920x1080p@23.98/24Hz */
318 [32] = {
319 NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5,
320 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0,
321 },
322 /* #35: (2880)x480p4x@59.94/60Hz */
323 [35] = {
324 NULL, 60, 2880, 480, 9250, 240, 64, 30, 9, 248, 6, 0, FB_VMODE_NONINTERLACED, 0,
325 },
326};
327
281const struct fb_videomode vesa_modes[] = { 328const struct fb_videomode vesa_modes[] = {
282 /* 0 640x350-85 VESA */ 329 /* 0 640x350-85 VESA */
283 { NULL, 85, 640, 350, 31746, 96, 32, 60, 32, 64, 3, 330 { NULL, 85, 640, 350, 31746, 96, 32, 60, 32, 64, 3,
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index ca0f6be9d12e..cb013919e9ce 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -1474,8 +1474,7 @@ static int mx3fb_probe(struct platform_device *pdev)
1474 goto eremap; 1474 goto eremap;
1475 } 1475 }
1476 1476
1477 pr_debug("Remapped %x to %x at %p\n", sdc_reg->start, sdc_reg->end, 1477 pr_debug("Remapped %pR at %p\n", sdc_reg, mx3fb->reg_base);
1478 mx3fb->reg_base);
1479 1478
1480 /* IDMAC interface */ 1479 /* IDMAC interface */
1481 dmaengine_get(); 1480 dmaengine_get();
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index a6247fc081ab..28b1c6c3d8ac 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -410,28 +410,6 @@ s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
410 ************************************************************/ 410 ************************************************************/
411 411
412/** 412/**
413 * bltbit_wait_bitset - waits for change in register value
414 * @info : framebuffer structure
415 * @bit : value expected in register
416 * @timeout : ...
417 *
418 * waits until value changes INTO bit
419 */
420static u8
421bltbit_wait_bitset(struct fb_info *info, u8 bit, int timeout)
422{
423 while (!(s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0) & bit)) {
424 udelay(10);
425 if (!--timeout) {
426 dbg_blit("wait_bitset timeout\n");
427 break;
428 }
429 }
430
431 return timeout;
432}
433
434/**
435 * bltbit_wait_bitclear - waits for change in register value 413 * bltbit_wait_bitclear - waits for change in register value
436 * @info : frambuffer structure 414 * @info : frambuffer structure
437 * @bit : value currently in register 415 * @bit : value currently in register
@@ -454,34 +432,6 @@ bltbit_wait_bitclear(struct fb_info *info, u8 bit, int timeout)
454 return timeout; 432 return timeout;
455} 433}
456 434
457/**
458 * bltbit_fifo_status - checks the current status of the fifo
459 * @info : framebuffer structure
460 *
461 * returns number of free words in buffer
462 */
463static u8
464bltbit_fifo_status(struct fb_info *info)
465{
466 u8 status;
467
468 status = s1d13xxxfb_readreg(info->par, S1DREG_BBLT_CTL0);
469
470 /* its empty so room for 16 words */
471 if (status & BBLT_FIFO_EMPTY)
472 return 16;
473
474 /* its full so we dont want to add */
475 if (status & BBLT_FIFO_FULL)
476 return 0;
477
478 /* its atleast half full but we can add one atleast */
479 if (status & BBLT_FIFO_NOT_FULL)
480 return 1;
481
482 return 0;
483}
484
485/* 435/*
486 * s1d13xxxfb_bitblt_copyarea - accelerated copyarea function 436 * s1d13xxxfb_bitblt_copyarea - accelerated copyarea function
487 * @info : framebuffer structure 437 * @info : framebuffer structure
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index f9aca9d13d1b..83ce9a04d872 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -23,6 +23,7 @@
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/uaccess.h> 24#include <linux/uaccess.h>
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/pm_runtime.h>
26 27
27#include <mach/map.h> 28#include <mach/map.h>
28#include <plat/regs-fb-v4.h> 29#include <plat/regs-fb-v4.h>
@@ -1013,8 +1014,30 @@ static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
1013 return ret; 1014 return ret;
1014} 1015}
1015 1016
1017static int s3c_fb_open(struct fb_info *info, int user)
1018{
1019 struct s3c_fb_win *win = info->par;
1020 struct s3c_fb *sfb = win->parent;
1021
1022 pm_runtime_get_sync(sfb->dev);
1023
1024 return 0;
1025}
1026
1027static int s3c_fb_release(struct fb_info *info, int user)
1028{
1029 struct s3c_fb_win *win = info->par;
1030 struct s3c_fb *sfb = win->parent;
1031
1032 pm_runtime_put_sync(sfb->dev);
1033
1034 return 0;
1035}
1036
1016static struct fb_ops s3c_fb_ops = { 1037static struct fb_ops s3c_fb_ops = {
1017 .owner = THIS_MODULE, 1038 .owner = THIS_MODULE,
1039 .fb_open = s3c_fb_open,
1040 .fb_release = s3c_fb_release,
1018 .fb_check_var = s3c_fb_check_var, 1041 .fb_check_var = s3c_fb_check_var,
1019 .fb_set_par = s3c_fb_set_par, 1042 .fb_set_par = s3c_fb_set_par,
1020 .fb_blank = s3c_fb_blank, 1043 .fb_blank = s3c_fb_blank,
@@ -1322,6 +1345,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1322 1345
1323 clk_enable(sfb->bus_clk); 1346 clk_enable(sfb->bus_clk);
1324 1347
1348 pm_runtime_enable(sfb->dev);
1349
1325 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1350 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1326 if (!res) { 1351 if (!res) {
1327 dev_err(dev, "failed to find registers\n"); 1352 dev_err(dev, "failed to find registers\n");
@@ -1360,6 +1385,9 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1360 1385
1361 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs); 1386 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
1362 1387
1388 platform_set_drvdata(pdev, sfb);
1389 pm_runtime_get_sync(sfb->dev);
1390
1363 /* setup gpio and output polarity controls */ 1391 /* setup gpio and output polarity controls */
1364 1392
1365 pd->setup_gpio(); 1393 pd->setup_gpio();
@@ -1400,6 +1428,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1400 } 1428 }
1401 1429
1402 platform_set_drvdata(pdev, sfb); 1430 platform_set_drvdata(pdev, sfb);
1431 pm_runtime_put_sync(sfb->dev);
1403 1432
1404 return 0; 1433 return 0;
1405 1434
@@ -1434,6 +1463,8 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1434 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1463 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1435 int win; 1464 int win;
1436 1465
1466 pm_runtime_get_sync(sfb->dev);
1467
1437 for (win = 0; win < S3C_FB_MAX_WIN; win++) 1468 for (win = 0; win < S3C_FB_MAX_WIN; win++)
1438 if (sfb->windows[win]) 1469 if (sfb->windows[win])
1439 s3c_fb_release_win(sfb, sfb->windows[win]); 1470 s3c_fb_release_win(sfb, sfb->windows[win]);
@@ -1450,12 +1481,74 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1450 1481
1451 kfree(sfb); 1482 kfree(sfb);
1452 1483
1484 pm_runtime_put_sync(sfb->dev);
1485 pm_runtime_disable(sfb->dev);
1486
1453 return 0; 1487 return 0;
1454} 1488}
1455 1489
1456#ifdef CONFIG_PM 1490#ifdef CONFIG_PM
1457static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state) 1491static int s3c_fb_suspend(struct device *dev)
1492{
1493 struct platform_device *pdev = to_platform_device(dev);
1494 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1495 struct s3c_fb_win *win;
1496 int win_no;
1497
1498 for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
1499 win = sfb->windows[win_no];
1500 if (!win)
1501 continue;
1502
1503 /* use the blank function to push into power-down */
1504 s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
1505 }
1506
1507 clk_disable(sfb->bus_clk);
1508 return 0;
1509}
1510
1511static int s3c_fb_resume(struct device *dev)
1512{
1513 struct platform_device *pdev = to_platform_device(dev);
1514 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1515 struct s3c_fb_platdata *pd = sfb->pdata;
1516 struct s3c_fb_win *win;
1517 int win_no;
1518
1519 clk_enable(sfb->bus_clk);
1520
1521 /* setup registers */
1522 writel(pd->vidcon1, sfb->regs + VIDCON1);
1523
1524 /* zero all windows before we do anything */
1525 for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
1526 s3c_fb_clear_win(sfb, win_no);
1527
1528 for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
1529 void __iomem *regs = sfb->regs + sfb->variant.keycon;
1530
1531 regs += (win_no * 8);
1532 writel(0xffffff, regs + WKEYCON0);
1533 writel(0xffffff, regs + WKEYCON1);
1534 }
1535
1536 /* restore framebuffers */
1537 for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
1538 win = sfb->windows[win_no];
1539 if (!win)
1540 continue;
1541
1542 dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
1543 s3c_fb_set_par(win->fbinfo);
1544 }
1545
1546 return 0;
1547}
1548
1549int s3c_fb_runtime_suspend(struct device *dev)
1458{ 1550{
1551 struct platform_device *pdev = to_platform_device(dev);
1459 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1552 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1460 struct s3c_fb_win *win; 1553 struct s3c_fb_win *win;
1461 int win_no; 1554 int win_no;
@@ -1473,8 +1566,9 @@ static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state)
1473 return 0; 1566 return 0;
1474} 1567}
1475 1568
1476static int s3c_fb_resume(struct platform_device *pdev) 1569int s3c_fb_runtime_resume(struct device *dev)
1477{ 1570{
1571 struct platform_device *pdev = to_platform_device(dev);
1478 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1572 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1479 struct s3c_fb_platdata *pd = sfb->pdata; 1573 struct s3c_fb_platdata *pd = sfb->pdata;
1480 struct s3c_fb_win *win; 1574 struct s3c_fb_win *win;
@@ -1509,9 +1603,12 @@ static int s3c_fb_resume(struct platform_device *pdev)
1509 1603
1510 return 0; 1604 return 0;
1511} 1605}
1606
1512#else 1607#else
1513#define s3c_fb_suspend NULL 1608#define s3c_fb_suspend NULL
1514#define s3c_fb_resume NULL 1609#define s3c_fb_resume NULL
1610#define s3c_fb_runtime_suspend NULL
1611#define s3c_fb_runtime_resume NULL
1515#endif 1612#endif
1516 1613
1517 1614
@@ -1710,15 +1807,21 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
1710}; 1807};
1711MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids); 1808MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
1712 1809
1810static const struct dev_pm_ops s3cfb_pm_ops = {
1811 .suspend = s3c_fb_suspend,
1812 .resume = s3c_fb_resume,
1813 .runtime_suspend = s3c_fb_runtime_suspend,
1814 .runtime_resume = s3c_fb_runtime_resume,
1815};
1816
1713static struct platform_driver s3c_fb_driver = { 1817static struct platform_driver s3c_fb_driver = {
1714 .probe = s3c_fb_probe, 1818 .probe = s3c_fb_probe,
1715 .remove = __devexit_p(s3c_fb_remove), 1819 .remove = __devexit_p(s3c_fb_remove),
1716 .suspend = s3c_fb_suspend,
1717 .resume = s3c_fb_resume,
1718 .id_table = s3c_fb_driver_ids, 1820 .id_table = s3c_fb_driver_ids,
1719 .driver = { 1821 .driver = {
1720 .name = "s3c-fb", 1822 .name = "s3c-fb",
1721 .owner = THIS_MODULE, 1823 .owner = THIS_MODULE,
1824 .pm = &s3cfb_pm_ops,
1722 }, 1825 },
1723}; 1826};
1724 1827
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 3f3d431033ca..b40dc423cbdf 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -21,18 +21,38 @@
21#include <video/sh_mipi_dsi.h> 21#include <video/sh_mipi_dsi.h>
22#include <video/sh_mobile_lcdc.h> 22#include <video/sh_mobile_lcdc.h>
23 23
24#define CMTSRTCTR 0x80d0 24#define SYSCTRL 0x0000
25#define CMTSRTREQ 0x8070 25#define SYSCONF 0x0004
26 26#define TIMSET 0x0008
27#define RESREQSET0 0x0018
28#define RESREQSET1 0x001c
29#define HSTTOVSET 0x0020
30#define LPRTOVSET 0x0024
31#define TATOVSET 0x0028
32#define PRTOVSET 0x002c
33#define DSICTRL 0x0030
27#define DSIINTE 0x0060 34#define DSIINTE 0x0060
35#define PHYCTRL 0x0070
36
37/* relative to linkbase */
38#define DTCTR 0x0000
39#define VMCTR1 0x0020
40#define VMCTR2 0x0024
41#define VMLEN1 0x0028
42#define CMTSRTREQ 0x0070
43#define CMTSRTCTR 0x00d0
28 44
29/* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */ 45/* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */
30#define MAX_SH_MIPI_DSI 2 46#define MAX_SH_MIPI_DSI 2
31 47
32struct sh_mipi { 48struct sh_mipi {
33 void __iomem *base; 49 void __iomem *base;
50 void __iomem *linkbase;
34 struct clk *dsit_clk; 51 struct clk *dsit_clk;
35 struct clk *dsip_clk; 52 struct clk *dsip_clk;
53 void *next_board_data;
54 void (*next_display_on)(void *board_data, struct fb_info *info);
55 void (*next_display_off)(void *board_data);
36}; 56};
37 57
38static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI]; 58static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI];
@@ -55,10 +75,10 @@ static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd,
55 int cnt = 100; 75 int cnt = 100;
56 76
57 /* transmit a short packet to LCD panel */ 77 /* transmit a short packet to LCD panel */
58 iowrite32(1 | data, mipi->base + 0x80d0); /* CMTSRTCTR */ 78 iowrite32(1 | data, mipi->linkbase + CMTSRTCTR);
59 iowrite32(1, mipi->base + 0x8070); /* CMTSRTREQ */ 79 iowrite32(1, mipi->linkbase + CMTSRTREQ);
60 80
61 while ((ioread32(mipi->base + 0x8070) & 1) && --cnt) 81 while ((ioread32(mipi->linkbase + CMTSRTREQ) & 1) && --cnt)
62 udelay(1); 82 udelay(1);
63 83
64 return cnt ? 0 : -ETIMEDOUT; 84 return cnt ? 0 : -ETIMEDOUT;
@@ -90,7 +110,7 @@ static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable)
90 * enable LCDC data tx, transition to LPS after completion of each HS 110 * enable LCDC data tx, transition to LPS after completion of each HS
91 * packet 111 * packet
92 */ 112 */
93 iowrite32(0x00000002 | enable, mipi->base + 0x8000); /* DTCTR */ 113 iowrite32(0x00000002 | enable, mipi->linkbase + DTCTR);
94} 114}
95 115
96static void sh_mipi_shutdown(struct platform_device *pdev) 116static void sh_mipi_shutdown(struct platform_device *pdev)
@@ -105,12 +125,18 @@ static void mipi_display_on(void *arg, struct fb_info *info)
105 struct sh_mipi *mipi = arg; 125 struct sh_mipi *mipi = arg;
106 126
107 sh_mipi_dsi_enable(mipi, true); 127 sh_mipi_dsi_enable(mipi, true);
128
129 if (mipi->next_display_on)
130 mipi->next_display_on(mipi->next_board_data, info);
108} 131}
109 132
110static void mipi_display_off(void *arg) 133static void mipi_display_off(void *arg)
111{ 134{
112 struct sh_mipi *mipi = arg; 135 struct sh_mipi *mipi = arg;
113 136
137 if (mipi->next_display_off)
138 mipi->next_display_off(mipi->next_board_data);
139
114 sh_mipi_dsi_enable(mipi, false); 140 sh_mipi_dsi_enable(mipi, false);
115} 141}
116 142
@@ -223,10 +249,10 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
223 return -EINVAL; 249 return -EINVAL;
224 250
225 /* reset DSI link */ 251 /* reset DSI link */
226 iowrite32(0x00000001, base); /* SYSCTRL */ 252 iowrite32(0x00000001, base + SYSCTRL);
227 /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */ 253 /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
228 udelay(50); 254 udelay(50);
229 iowrite32(0x00000000, base); /* SYSCTRL */ 255 iowrite32(0x00000000, base + SYSCTRL);
230 256
231 /* setup DSI link */ 257 /* setup DSI link */
232 258
@@ -238,7 +264,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
238 * ECC check enable 264 * ECC check enable
239 * additionally enable first two lanes 265 * additionally enable first two lanes
240 */ 266 */
241 iowrite32(0x00003703, base + 0x04); /* SYSCONF */ 267 iowrite32(0x00003703, base + SYSCONF);
242 /* 268 /*
243 * T_wakeup = 0x7000 269 * T_wakeup = 0x7000
244 * T_hs-trail = 3 270 * T_hs-trail = 3
@@ -246,28 +272,28 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
246 * T_clk-trail = 3 272 * T_clk-trail = 3
247 * T_clk-prepare = 2 273 * T_clk-prepare = 2
248 */ 274 */
249 iowrite32(0x70003332, base + 0x08); /* TIMSET */ 275 iowrite32(0x70003332, base + TIMSET);
250 /* no responses requested */ 276 /* no responses requested */
251 iowrite32(0x00000000, base + 0x18); /* RESREQSET0 */ 277 iowrite32(0x00000000, base + RESREQSET0);
252 /* request response to packets of type 0x28 */ 278 /* request response to packets of type 0x28 */
253 iowrite32(0x00000100, base + 0x1c); /* RESREQSET1 */ 279 iowrite32(0x00000100, base + RESREQSET1);
254 /* High-speed transmission timeout, default 0xffffffff */ 280 /* High-speed transmission timeout, default 0xffffffff */
255 iowrite32(0x0fffffff, base + 0x20); /* HSTTOVSET */ 281 iowrite32(0x0fffffff, base + HSTTOVSET);
256 /* LP reception timeout, default 0xffffffff */ 282 /* LP reception timeout, default 0xffffffff */
257 iowrite32(0x0fffffff, base + 0x24); /* LPRTOVSET */ 283 iowrite32(0x0fffffff, base + LPRTOVSET);
258 /* Turn-around timeout, default 0xffffffff */ 284 /* Turn-around timeout, default 0xffffffff */
259 iowrite32(0x0fffffff, base + 0x28); /* TATOVSET */ 285 iowrite32(0x0fffffff, base + TATOVSET);
260 /* Peripheral reset timeout, default 0xffffffff */ 286 /* Peripheral reset timeout, default 0xffffffff */
261 iowrite32(0x0fffffff, base + 0x2c); /* PRTOVSET */ 287 iowrite32(0x0fffffff, base + PRTOVSET);
262 /* Enable timeout counters */ 288 /* Enable timeout counters */
263 iowrite32(0x00000f00, base + 0x30); /* DSICTRL */ 289 iowrite32(0x00000f00, base + DSICTRL);
264 /* Interrupts not used, disable all */ 290 /* Interrupts not used, disable all */
265 iowrite32(0, base + DSIINTE); 291 iowrite32(0, base + DSIINTE);
266 /* DSI-Tx bias on */ 292 /* DSI-Tx bias on */
267 iowrite32(0x00000001, base + 0x70); /* PHYCTRL */ 293 iowrite32(0x00000001, base + PHYCTRL);
268 udelay(200); 294 udelay(200);
269 /* Deassert resets, power on, set multiplier */ 295 /* Deassert resets, power on, set multiplier */
270 iowrite32(0x03070b01, base + 0x70); /* PHYCTRL */ 296 iowrite32(0x03070b01, base + PHYCTRL);
271 297
272 /* setup l-bridge */ 298 /* setup l-bridge */
273 299
@@ -275,20 +301,21 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
275 * Enable transmission of all packets, 301 * Enable transmission of all packets,
276 * transmit LPS after each HS packet completion 302 * transmit LPS after each HS packet completion
277 */ 303 */
278 iowrite32(0x00000006, base + 0x8000); /* DTCTR */ 304 iowrite32(0x00000006, mipi->linkbase + DTCTR);
279 /* VSYNC width = 2 (<< 17) */ 305 /* VSYNC width = 2 (<< 17) */
280 iowrite32(0x00040000 | (pctype << 12) | datatype, base + 0x8020); /* VMCTR1 */ 306 iowrite32(0x00040000 | (pctype << 12) | datatype,
307 mipi->linkbase + VMCTR1);
281 /* 308 /*
282 * Non-burst mode with sync pulses: VSE and HSE are output, 309 * Non-burst mode with sync pulses: VSE and HSE are output,
283 * HSA period allowed, no commands in LP 310 * HSA period allowed, no commands in LP
284 */ 311 */
285 iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */ 312 iowrite32(0x00e00000, mipi->linkbase + VMCTR2);
286 /* 313 /*
287 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see 314 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see
288 * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default 315 * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default
289 * (unused, since VMCTR2[HSABM] = 0) 316 * (unused, since VMCTR2[HSABM] = 0)
290 */ 317 */
291 iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */ 318 iowrite32(1 | (linelength << 16), mipi->linkbase + VMLEN1);
292 319
293 msleep(5); 320 msleep(5);
294 321
@@ -321,11 +348,12 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
321 struct sh_mipi *mipi; 348 struct sh_mipi *mipi;
322 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; 349 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
323 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 350 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
351 struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
324 unsigned long rate, f_current; 352 unsigned long rate, f_current;
325 int idx = pdev->id, ret; 353 int idx = pdev->id, ret;
326 char dsip_clk[] = "dsi.p_clk"; 354 char dsip_clk[] = "dsi.p_clk";
327 355
328 if (!res || idx >= ARRAY_SIZE(mipi_dsi) || !pdata) 356 if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
329 return -ENODEV; 357 return -ENODEV;
330 358
331 mutex_lock(&array_lock); 359 mutex_lock(&array_lock);
@@ -356,6 +384,18 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
356 goto emap; 384 goto emap;
357 } 385 }
358 386
387 if (!request_mem_region(res2->start, resource_size(res2), pdev->name)) {
388 dev_err(&pdev->dev, "MIPI register region 2 already claimed\n");
389 ret = -EBUSY;
390 goto ereqreg2;
391 }
392
393 mipi->linkbase = ioremap(res2->start, resource_size(res2));
394 if (!mipi->linkbase) {
395 ret = -ENOMEM;
396 goto emap2;
397 }
398
359 mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk"); 399 mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
360 if (IS_ERR(mipi->dsit_clk)) { 400 if (IS_ERR(mipi->dsit_clk)) {
361 ret = PTR_ERR(mipi->dsit_clk); 401 ret = PTR_ERR(mipi->dsit_clk);
@@ -412,6 +452,11 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
412 mutex_unlock(&array_lock); 452 mutex_unlock(&array_lock);
413 platform_set_drvdata(pdev, mipi); 453 platform_set_drvdata(pdev, mipi);
414 454
455 /* Save original LCDC callbacks */
456 mipi->next_board_data = pdata->lcd_chan->board_cfg.board_data;
457 mipi->next_display_on = pdata->lcd_chan->board_cfg.display_on;
458 mipi->next_display_off = pdata->lcd_chan->board_cfg.display_off;
459
415 /* Set up LCDC callbacks */ 460 /* Set up LCDC callbacks */
416 pdata->lcd_chan->board_cfg.board_data = mipi; 461 pdata->lcd_chan->board_cfg.board_data = mipi;
417 pdata->lcd_chan->board_cfg.display_on = mipi_display_on; 462 pdata->lcd_chan->board_cfg.display_on = mipi_display_on;
@@ -431,6 +476,10 @@ eclkpget:
431esettrate: 476esettrate:
432 clk_put(mipi->dsit_clk); 477 clk_put(mipi->dsit_clk);
433eclktget: 478eclktget:
479 iounmap(mipi->linkbase);
480emap2:
481 release_mem_region(res2->start, resource_size(res2));
482ereqreg2:
434 iounmap(mipi->base); 483 iounmap(mipi->base);
435emap: 484emap:
436 release_mem_region(res->start, resource_size(res)); 485 release_mem_region(res->start, resource_size(res));
@@ -447,6 +496,7 @@ static int __exit sh_mipi_remove(struct platform_device *pdev)
447{ 496{
448 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; 497 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
449 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 498 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
499 struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
450 struct sh_mipi *mipi = platform_get_drvdata(pdev); 500 struct sh_mipi *mipi = platform_get_drvdata(pdev);
451 int i, ret; 501 int i, ret;
452 502
@@ -475,6 +525,9 @@ static int __exit sh_mipi_remove(struct platform_device *pdev)
475 clk_disable(mipi->dsit_clk); 525 clk_disable(mipi->dsit_clk);
476 clk_put(mipi->dsit_clk); 526 clk_put(mipi->dsit_clk);
477 clk_put(mipi->dsip_clk); 527 clk_put(mipi->dsip_clk);
528 iounmap(mipi->linkbase);
529 if (res2)
530 release_mem_region(res2->start, resource_size(res2));
478 iounmap(mipi->base); 531 iounmap(mipi->base);
479 if (res) 532 if (res)
480 release_mem_region(res->start, resource_size(res)); 533 release_mem_region(res->start, resource_size(res));
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index d7df10315d8d..76f9fac9020f 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -209,7 +209,11 @@ enum hotplug_state {
209struct sh_hdmi { 209struct sh_hdmi {
210 void __iomem *base; 210 void __iomem *base;
211 enum hotplug_state hp_state; /* hot-plug status */ 211 enum hotplug_state hp_state; /* hot-plug status */
212 bool preprogrammed_mode; /* use a pre-programmed VIC or the external mode */ 212 u8 preprogrammed_vic; /* use a pre-programmed VIC or
213 the external mode */
214 u8 edid_block_addr;
215 u8 edid_segment_nr;
216 u8 edid_blocks;
213 struct clk *hdmi_clk; 217 struct clk *hdmi_clk;
214 struct device *dev; 218 struct device *dev;
215 struct fb_info *info; 219 struct fb_info *info;
@@ -342,7 +346,7 @@ static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
342 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION); 346 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION);
343 347
344 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */ 348 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */
345 if (!hdmi->preprogrammed_mode) 349 if (!hdmi->preprogrammed_vic)
346 hdmi_write(hdmi, sync | 1 | (voffset << 4), 350 hdmi_write(hdmi, sync | 1 | (voffset << 4),
347 HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); 351 HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
348} 352}
@@ -466,7 +470,18 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
466 */ 470 */
467static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) 471static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
468{ 472{
469 if (hdmi->var.yres > 480) { 473 if (hdmi->var.pixclock < 10000) {
474 /* for 1080p8bit 148MHz */
475 hdmi_write(hdmi, 0x1d, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
476 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
477 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
478 hdmi_write(hdmi, 0x4c, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
479 hdmi_write(hdmi, 0x1e, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
480 hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
481 hdmi_write(hdmi, 0x0e, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
482 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
483 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
484 } else if (hdmi->var.pixclock < 30000) {
470 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */ 485 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
471 /* 486 /*
472 * [1:0] Speed_A 487 * [1:0] Speed_A
@@ -565,13 +580,11 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
565 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3); 580 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB3);
566 581
567 /* 582 /*
568 * VIC = 1280 x 720p: ignored if external config is used 583 * VIC should be ignored if external config is used, so, we could just use 0,
569 * Send 2 for 720 x 480p, 16 for 1080p, ignored in external mode 584 * but play safe and use a valid value in any case just in case
570 */ 585 */
571 if (hdmi->var.yres == 1080 && hdmi->var.xres == 1920) 586 if (hdmi->preprogrammed_vic)
572 vic = 16; 587 vic = hdmi->preprogrammed_vic;
573 else if (hdmi->var.yres == 480 && hdmi->var.xres == 720)
574 vic = 2;
575 else 588 else
576 vic = 4; 589 vic = 4;
577 hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4); 590 hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
@@ -685,11 +698,21 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
685} 698}
686 699
687static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi, 700static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
688 const struct fb_videomode *mode) 701 const struct fb_videomode *mode,
702 unsigned long *hdmi_rate, unsigned long *parent_rate)
689{ 703{
690 long target = PICOS2KHZ(mode->pixclock) * 1000, 704 unsigned long target = PICOS2KHZ(mode->pixclock) * 1000, rate_error;
691 rate = clk_round_rate(hdmi->hdmi_clk, target); 705 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
692 unsigned long rate_error = rate > 0 ? abs(rate - target) : ULONG_MAX; 706
707 *hdmi_rate = clk_round_rate(hdmi->hdmi_clk, target);
708 if ((long)*hdmi_rate < 0)
709 *hdmi_rate = clk_get_rate(hdmi->hdmi_clk);
710
711 rate_error = (long)*hdmi_rate > 0 ? abs(*hdmi_rate - target) : ULONG_MAX;
712 if (rate_error && pdata->clk_optimize_parent)
713 rate_error = pdata->clk_optimize_parent(target, hdmi_rate, parent_rate);
714 else if (clk_get_parent(hdmi->hdmi_clk))
715 *parent_rate = clk_get_rate(clk_get_parent(hdmi->hdmi_clk));
693 716
694 dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n", 717 dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n",
695 mode->left_margin, mode->xres, 718 mode->left_margin, mode->xres,
@@ -697,14 +720,15 @@ static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
697 mode->upper_margin, mode->yres, 720 mode->upper_margin, mode->yres,
698 mode->lower_margin, mode->vsync_len); 721 mode->lower_margin, mode->vsync_len);
699 722
700 dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz\n", target, 723 dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz, p=%luHz\n", target,
701 rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0, 724 rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
702 mode->refresh); 725 mode->refresh, *parent_rate);
703 726
704 return rate_error; 727 return rate_error;
705} 728}
706 729
707static int sh_hdmi_read_edid(struct sh_hdmi *hdmi) 730static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
731 unsigned long *parent_rate)
708{ 732{
709 struct fb_var_screeninfo tmpvar; 733 struct fb_var_screeninfo tmpvar;
710 struct fb_var_screeninfo *var = &tmpvar; 734 struct fb_var_screeninfo *var = &tmpvar;
@@ -735,7 +759,38 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
735 printk(KERN_CONT "\n"); 759 printk(KERN_CONT "\n");
736#endif 760#endif
737 761
738 fb_edid_to_monspecs(edid, &hdmi->monspec); 762 if (!hdmi->edid_blocks) {
763 fb_edid_to_monspecs(edid, &hdmi->monspec);
764 hdmi->edid_blocks = edid[126] + 1;
765
766 dev_dbg(hdmi->dev, "%d main modes, %d extension blocks\n",
767 hdmi->monspec.modedb_len, hdmi->edid_blocks - 1);
768 } else {
769 dev_dbg(hdmi->dev, "Extension %u detected, DTD start %u\n",
770 edid[0], edid[2]);
771 fb_edid_add_monspecs(edid, &hdmi->monspec);
772 }
773
774 if (hdmi->edid_blocks > hdmi->edid_segment_nr * 2 +
775 (hdmi->edid_block_addr >> 7) + 1) {
776 /* More blocks to read */
777 if (hdmi->edid_block_addr) {
778 hdmi->edid_block_addr = 0;
779 hdmi->edid_segment_nr++;
780 } else {
781 hdmi->edid_block_addr = 0x80;
782 }
783 /* Set EDID word address */
784 hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS);
785 /* Enable EDID interrupt */
786 hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
787 /* Set EDID segment pointer - starts reading EDID */
788 hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER);
789 return -EAGAIN;
790 }
791
792 /* All E-EDID blocks ready */
793 dev_dbg(hdmi->dev, "%d main and extended modes\n", hdmi->monspec.modedb_len);
739 794
740 fb_get_options("sh_mobile_lcdc", &forced); 795 fb_get_options("sh_mobile_lcdc", &forced);
741 if (forced && *forced) { 796 if (forced && *forced) {
@@ -754,11 +809,14 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
754 for (i = 0, mode = hdmi->monspec.modedb; 809 for (i = 0, mode = hdmi->monspec.modedb;
755 f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match; 810 f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match;
756 i++, mode++) { 811 i++, mode++) {
757 unsigned long rate_error = sh_hdmi_rate_error(hdmi, mode); 812 unsigned long rate_error;
758 813
759 /* No interest in unmatching modes */ 814 /* No interest in unmatching modes */
760 if (f_width != mode->xres || f_height != mode->yres) 815 if (f_width != mode->xres || f_height != mode->yres)
761 continue; 816 continue;
817
818 rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate);
819
762 if (f_refresh == mode->refresh || (!f_refresh && !rate_error)) 820 if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
763 /* 821 /*
764 * Exact match if either the refresh rate matches or it 822 * Exact match if either the refresh rate matches or it
@@ -802,7 +860,7 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
802 860
803 if (modelist) { 861 if (modelist) {
804 found = &modelist->mode; 862 found = &modelist->mode;
805 found_rate_error = sh_hdmi_rate_error(hdmi, found); 863 found_rate_error = sh_hdmi_rate_error(hdmi, found, hdmi_rate, parent_rate);
806 } 864 }
807 } 865 }
808 866
@@ -810,16 +868,27 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
810 if (!found) 868 if (!found)
811 return -ENXIO; 869 return -ENXIO;
812 870
813 dev_info(hdmi->dev, "Using %s mode %ux%u@%uHz (%luHz), clock error %luHz\n", 871 if (found->xres == 640 && found->yres == 480 && found->refresh == 60)
814 modelist ? "default" : "EDID", found->xres, found->yres, 872 hdmi->preprogrammed_vic = 1;
815 found->refresh, PICOS2KHZ(found->pixclock) * 1000, found_rate_error); 873 else if (found->xres == 720 && found->yres == 480 && found->refresh == 60)
816 874 hdmi->preprogrammed_vic = 2;
817 if ((found->xres == 720 && found->yres == 480) || 875 else if (found->xres == 720 && found->yres == 576 && found->refresh == 50)
818 (found->xres == 1280 && found->yres == 720) || 876 hdmi->preprogrammed_vic = 17;
819 (found->xres == 1920 && found->yres == 1080)) 877 else if (found->xres == 1280 && found->yres == 720 && found->refresh == 60)
820 hdmi->preprogrammed_mode = true; 878 hdmi->preprogrammed_vic = 4;
879 else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 24)
880 hdmi->preprogrammed_vic = 32;
881 else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 50)
882 hdmi->preprogrammed_vic = 31;
883 else if (found->xres == 1920 && found->yres == 1080 && found->refresh == 60)
884 hdmi->preprogrammed_vic = 16;
821 else 885 else
822 hdmi->preprogrammed_mode = false; 886 hdmi->preprogrammed_vic = 0;
887
888 dev_dbg(hdmi->dev, "Using %s %s mode %ux%u@%uHz (%luHz), clock error %luHz\n",
889 modelist ? "default" : "EDID", hdmi->preprogrammed_vic ? "VIC" : "external",
890 found->xres, found->yres, found->refresh,
891 PICOS2KHZ(found->pixclock) * 1000, found_rate_error);
823 892
824 fb_videomode_to_var(&hdmi->var, found); 893 fb_videomode_to_var(&hdmi->var, found);
825 sh_hdmi_external_video_param(hdmi); 894 sh_hdmi_external_video_param(hdmi);
@@ -868,32 +937,34 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
868 /* Check, if hot plug & MSENS pin status are both high */ 937 /* Check, if hot plug & MSENS pin status are both high */
869 if ((msens & 0xC0) == 0xC0) { 938 if ((msens & 0xC0) == 0xC0) {
870 /* Display plug in */ 939 /* Display plug in */
940 hdmi->edid_segment_nr = 0;
941 hdmi->edid_block_addr = 0;
942 hdmi->edid_blocks = 0;
871 hdmi->hp_state = HDMI_HOTPLUG_CONNECTED; 943 hdmi->hp_state = HDMI_HOTPLUG_CONNECTED;
872 944
873 /* Set EDID word address */ 945 /* Set EDID word address */
874 hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS); 946 hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS);
875 /* Set EDID segment pointer */
876 hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
877 /* Enable EDID interrupt */ 947 /* Enable EDID interrupt */
878 hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1); 948 hdmi_write(hdmi, 0xC6, HDMI_INTERRUPT_MASK_1);
949 /* Set EDID segment pointer - starts reading EDID */
950 hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER);
879 } else if (!(status1 & 0x80)) { 951 } else if (!(status1 & 0x80)) {
880 /* Display unplug, beware multiple interrupts */ 952 /* Display unplug, beware multiple interrupts */
881 if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED) 953 if (hdmi->hp_state != HDMI_HOTPLUG_DISCONNECTED) {
954 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
882 schedule_delayed_work(&hdmi->edid_work, 0); 955 schedule_delayed_work(&hdmi->edid_work, 0);
883 956 }
884 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
885 /* display_off will switch back to mode_a */ 957 /* display_off will switch back to mode_a */
886 } 958 }
887 } else if (status1 & 2) { 959 } else if (status1 & 2) {
888 /* EDID error interrupt: retry */ 960 /* EDID error interrupt: retry */
889 /* Set EDID word address */ 961 /* Set EDID word address */
890 hdmi_write(hdmi, 0x00, HDMI_EDID_WORD_ADDRESS); 962 hdmi_write(hdmi, hdmi->edid_block_addr, HDMI_EDID_WORD_ADDRESS);
891 /* Set EDID segment pointer */ 963 /* Set EDID segment pointer */
892 hdmi_write(hdmi, 0x00, HDMI_EDID_SEGMENT_POINTER); 964 hdmi_write(hdmi, hdmi->edid_segment_nr, HDMI_EDID_SEGMENT_POINTER);
893 } else if (status1 & 4) { 965 } else if (status1 & 4) {
894 /* Disable EDID interrupt */ 966 /* Disable EDID interrupt */
895 hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1); 967 hdmi_write(hdmi, 0xC0, HDMI_INTERRUPT_MASK_1);
896 hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
897 schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10)); 968 schedule_delayed_work(&hdmi->edid_work, msecs_to_jiffies(10));
898 } 969 }
899 970
@@ -972,39 +1043,37 @@ static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi)
972 1043
973/** 1044/**
974 * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock 1045 * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock
975 * @hdmi: driver context 1046 * @hdmi: driver context
976 * @pixclock: pixel clock period in picoseconds 1047 * @hdmi_rate: HDMI clock frequency in Hz
977 * return: configured positive rate if successful 1048 * @parent_rate: if != 0 - set parent clock rate for optimal precision
978 * 0 if couldn't set the rate, but managed to enable the clock 1049 * return: configured positive rate if successful
979 * negative error, if couldn't enable the clock 1050 * 0 if couldn't set the rate, but managed to enable the
1051 * clock, negative error, if couldn't enable the clock
980 */ 1052 */
981static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long pixclock) 1053static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate,
1054 unsigned long parent_rate)
982{ 1055{
983 long rate;
984 int ret; 1056 int ret;
985 1057
986 rate = PICOS2KHZ(pixclock) * 1000; 1058 if (parent_rate && clk_get_parent(hdmi->hdmi_clk)) {
987 rate = clk_round_rate(hdmi->hdmi_clk, rate); 1059 ret = clk_set_rate(clk_get_parent(hdmi->hdmi_clk), parent_rate);
988 if (rate > 0) {
989 ret = clk_set_rate(hdmi->hdmi_clk, rate);
990 if (ret < 0) { 1060 if (ret < 0) {
991 dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", rate, ret); 1061 dev_warn(hdmi->dev, "Cannot set parent rate %ld: %d\n", parent_rate, ret);
992 rate = 0; 1062 hdmi_rate = clk_round_rate(hdmi->hdmi_clk, hdmi_rate);
993 } else { 1063 } else {
994 dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", rate); 1064 dev_dbg(hdmi->dev, "HDMI set parent frequency %lu\n", parent_rate);
995 } 1065 }
996 } else {
997 rate = 0;
998 dev_warn(hdmi->dev, "Cannot get suitable rate: %ld\n", rate);
999 } 1066 }
1000 1067
1001 ret = clk_enable(hdmi->hdmi_clk); 1068 ret = clk_set_rate(hdmi->hdmi_clk, hdmi_rate);
1002 if (ret < 0) { 1069 if (ret < 0) {
1003 dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret); 1070 dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", hdmi_rate, ret);
1004 return ret; 1071 hdmi_rate = 0;
1072 } else {
1073 dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", hdmi_rate);
1005 } 1074 }
1006 1075
1007 return rate; 1076 return hdmi_rate;
1008} 1077}
1009 1078
1010/* Hotplug interrupt occurred, read EDID */ 1079/* Hotplug interrupt occurred, read EDID */
@@ -1023,17 +1092,20 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
1023 1092
1024 mutex_lock(&hdmi->mutex); 1093 mutex_lock(&hdmi->mutex);
1025 1094
1026 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { 1095 if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
1096 unsigned long parent_rate = 0, hdmi_rate;
1097
1027 /* A device has been plugged in */ 1098 /* A device has been plugged in */
1028 pm_runtime_get_sync(hdmi->dev); 1099 pm_runtime_get_sync(hdmi->dev);
1029 1100
1030 ret = sh_hdmi_read_edid(hdmi); 1101 ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate);
1031 if (ret < 0) 1102 if (ret < 0)
1032 goto out; 1103 goto out;
1033 1104
1105 hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
1106
1034 /* Reconfigure the clock */ 1107 /* Reconfigure the clock */
1035 clk_disable(hdmi->hdmi_clk); 1108 ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate);
1036 ret = sh_hdmi_clk_configure(hdmi, hdmi->var.pixclock);
1037 if (ret < 0) 1109 if (ret < 0)
1038 goto out; 1110 goto out;
1039 1111
@@ -1085,7 +1157,7 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
1085 } 1157 }
1086 1158
1087out: 1159out:
1088 if (ret < 0) 1160 if (ret < 0 && ret != -EAGAIN)
1089 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED; 1161 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
1090 mutex_unlock(&hdmi->mutex); 1162 mutex_unlock(&hdmi->mutex);
1091 1163
@@ -1166,13 +1238,22 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1166 goto egetclk; 1238 goto egetclk;
1167 } 1239 }
1168 1240
1169 /* Some arbitrary relaxed pixclock just to get things started */ 1241 /* An arbitrary relaxed pixclock just to get things started: from standard 480p */
1170 rate = sh_hdmi_clk_configure(hdmi, 37037); 1242 rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037));
1243 if (rate > 0)
1244 rate = sh_hdmi_clk_configure(hdmi, rate, 0);
1245
1171 if (rate < 0) { 1246 if (rate < 0) {
1172 ret = rate; 1247 ret = rate;
1173 goto erate; 1248 goto erate;
1174 } 1249 }
1175 1250
1251 ret = clk_enable(hdmi->hdmi_clk);
1252 if (ret < 0) {
1253 dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret);
1254 goto erate;
1255 }
1256
1176 dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate); 1257 dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
1177 1258
1178 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) { 1259 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
@@ -1190,10 +1271,6 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1190 1271
1191 platform_set_drvdata(pdev, hdmi); 1272 platform_set_drvdata(pdev, hdmi);
1192 1273
1193 /* Product and revision IDs are 0 in sh-mobile version */
1194 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
1195 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
1196
1197 /* Set up LCDC callbacks */ 1274 /* Set up LCDC callbacks */
1198 board_cfg = &pdata->lcd_chan->board_cfg; 1275 board_cfg = &pdata->lcd_chan->board_cfg;
1199 board_cfg->owner = THIS_MODULE; 1276 board_cfg->owner = THIS_MODULE;
@@ -1206,6 +1283,10 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1206 pm_runtime_enable(&pdev->dev); 1283 pm_runtime_enable(&pdev->dev);
1207 pm_runtime_resume(&pdev->dev); 1284 pm_runtime_resume(&pdev->dev);
1208 1285
1286 /* Product and revision IDs are 0 in sh-mobile version */
1287 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
1288 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
1289
1209 ret = request_irq(irq, sh_hdmi_hotplug, 0, 1290 ret = request_irq(irq, sh_hdmi_hotplug, 0,
1210 dev_name(&pdev->dev), hdmi); 1291 dev_name(&pdev->dev), hdmi);
1211 if (ret < 0) { 1292 if (ret < 0) {
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index b02d97a879d6..778bffbbdbb7 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -54,8 +54,8 @@ static int lcdc_shared_regs[] = {
54}; 54};
55#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) 55#define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
56 56
57#define DEFAULT_XRES 1280 57#define MAX_XRES 1920
58#define DEFAULT_YRES 1024 58#define MAX_YRES 1080
59 59
60static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { 60static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
61 [LDDCKPAT1R] = 0x400, 61 [LDDCKPAT1R] = 0x400,
@@ -914,22 +914,12 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
914{ 914{
915 struct sh_mobile_lcdc_chan *ch = info->par; 915 struct sh_mobile_lcdc_chan *ch = info->par;
916 916
917 if (var->xres < 160 || var->xres > 1920 || 917 if (var->xres > MAX_XRES || var->yres > MAX_YRES ||
918 var->yres < 120 || var->yres > 1080 ||
919 var->left_margin < 32 || var->left_margin > 320 ||
920 var->right_margin < 12 || var->right_margin > 240 ||
921 var->upper_margin < 12 || var->upper_margin > 120 ||
922 var->lower_margin < 1 || var->lower_margin > 64 ||
923 var->hsync_len < 32 || var->hsync_len > 240 ||
924 var->vsync_len < 2 || var->vsync_len > 64 ||
925 var->pixclock < 6000 || var->pixclock > 40000 ||
926 var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) { 918 var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) {
927 dev_warn(info->dev, "Invalid info: %u %u %u %u %u %u %u %u %u!\n", 919 dev_warn(info->dev, "Invalid info: %u-%u-%u-%u x %u-%u-%u-%u @ %lukHz!\n",
928 var->xres, var->yres, 920 var->left_margin, var->xres, var->right_margin, var->hsync_len,
929 var->left_margin, var->right_margin, 921 var->upper_margin, var->yres, var->lower_margin, var->vsync_len,
930 var->upper_margin, var->lower_margin, 922 PICOS2KHZ(var->pixclock));
931 var->hsync_len, var->vsync_len,
932 var->pixclock);
933 return -EINVAL; 923 return -EINVAL;
934 } 924 }
935 return 0; 925 return 0;
@@ -1226,7 +1216,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1226 } 1216 }
1227 1217
1228 if (!mode) 1218 if (!mode)
1229 max_size = DEFAULT_XRES * DEFAULT_YRES; 1219 max_size = MAX_XRES * MAX_YRES;
1230 else if (max_cfg) 1220 else if (max_cfg)
1231 dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n", 1221 dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n",
1232 max_cfg->xres, max_cfg->yres); 1222 max_cfg->xres, max_cfg->yres);
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c
index a3aa91709503..6723d6910cde 100644
--- a/drivers/video/via/via-core.c
+++ b/drivers/video/via/via-core.c
@@ -15,6 +15,9 @@
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/list.h>
19#include <linux/pm.h>
20#include <asm/olpc.h>
18 21
19/* 22/*
20 * The default port config. 23 * The default port config.
@@ -29,6 +32,19 @@ static struct via_port_cfg adap_configs[] = {
29}; 32};
30 33
31/* 34/*
35 * The OLPC XO-1.5 puts the camera power and reset lines onto
36 * GPIO 2C.
37 */
38static const struct via_port_cfg olpc_adap_configs[] = {
39 [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 },
40 [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 },
41 [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
42 [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x2c },
43 [VIA_PORT_3D] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
44 { 0, 0, 0, 0 }
45};
46
47/*
32 * We currently only support one viafb device (will there ever be 48 * We currently only support one viafb device (will there ever be
33 * more than one?), so just declare it globally here. 49 * more than one?), so just declare it globally here.
34 */ 50 */
@@ -575,6 +591,78 @@ static void via_teardown_subdevs(void)
575 } 591 }
576} 592}
577 593
594/*
595 * Power management functions
596 */
597#ifdef CONFIG_PM
598static LIST_HEAD(viafb_pm_hooks);
599static DEFINE_MUTEX(viafb_pm_hooks_lock);
600
601void viafb_pm_register(struct viafb_pm_hooks *hooks)
602{
603 INIT_LIST_HEAD(&hooks->list);
604
605 mutex_lock(&viafb_pm_hooks_lock);
606 list_add_tail(&hooks->list, &viafb_pm_hooks);
607 mutex_unlock(&viafb_pm_hooks_lock);
608}
609EXPORT_SYMBOL_GPL(viafb_pm_register);
610
611void viafb_pm_unregister(struct viafb_pm_hooks *hooks)
612{
613 mutex_lock(&viafb_pm_hooks_lock);
614 list_del(&hooks->list);
615 mutex_unlock(&viafb_pm_hooks_lock);
616}
617EXPORT_SYMBOL_GPL(viafb_pm_unregister);
618
619static int via_suspend(struct pci_dev *pdev, pm_message_t state)
620{
621 struct viafb_pm_hooks *hooks;
622
623 if (state.event != PM_EVENT_SUSPEND)
624 return 0;
625 /*
626 * "I've occasionally hit a few drivers that caused suspend
627 * failures, and each and every time it was a driver bug, and
628 * the right thing to do was to just ignore the error and suspend
629 * anyway - returning an error code and trying to undo the suspend
630 * is not what anybody ever really wants, even if our model
631 *_allows_ for it."
632 * -- Linus Torvalds, Dec. 7, 2009
633 */
634 mutex_lock(&viafb_pm_hooks_lock);
635 list_for_each_entry_reverse(hooks, &viafb_pm_hooks, list)
636 hooks->suspend(hooks->private);
637 mutex_unlock(&viafb_pm_hooks_lock);
638
639 pci_save_state(pdev);
640 pci_disable_device(pdev);
641 pci_set_power_state(pdev, pci_choose_state(pdev, state));
642 return 0;
643}
644
645static int via_resume(struct pci_dev *pdev)
646{
647 struct viafb_pm_hooks *hooks;
648
649 /* Get the bus side powered up */
650 pci_set_power_state(pdev, PCI_D0);
651 pci_restore_state(pdev);
652 if (pci_enable_device(pdev))
653 return 0;
654
655 pci_set_master(pdev);
656
657 /* Now bring back any subdevs */
658 mutex_lock(&viafb_pm_hooks_lock);
659 list_for_each_entry(hooks, &viafb_pm_hooks, list)
660 hooks->resume(hooks->private);
661 mutex_unlock(&viafb_pm_hooks_lock);
662
663 return 0;
664}
665#endif /* CONFIG_PM */
578 666
579static int __devinit via_pci_probe(struct pci_dev *pdev, 667static int __devinit via_pci_probe(struct pci_dev *pdev,
580 const struct pci_device_id *ent) 668 const struct pci_device_id *ent)
@@ -584,6 +672,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
584 ret = pci_enable_device(pdev); 672 ret = pci_enable_device(pdev);
585 if (ret) 673 if (ret)
586 return ret; 674 return ret;
675
587 /* 676 /*
588 * Global device initialization. 677 * Global device initialization.
589 */ 678 */
@@ -591,6 +680,9 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
591 global_dev.pdev = pdev; 680 global_dev.pdev = pdev;
592 global_dev.chip_type = ent->driver_data; 681 global_dev.chip_type = ent->driver_data;
593 global_dev.port_cfg = adap_configs; 682 global_dev.port_cfg = adap_configs;
683 if (machine_is_olpc())
684 global_dev.port_cfg = olpc_adap_configs;
685
594 spin_lock_init(&global_dev.reg_lock); 686 spin_lock_init(&global_dev.reg_lock);
595 ret = via_pci_setup_mmio(&global_dev); 687 ret = via_pci_setup_mmio(&global_dev);
596 if (ret) 688 if (ret)
@@ -663,8 +755,8 @@ static struct pci_driver via_driver = {
663 .probe = via_pci_probe, 755 .probe = via_pci_probe,
664 .remove = __devexit_p(via_pci_remove), 756 .remove = __devexit_p(via_pci_remove),
665#ifdef CONFIG_PM 757#ifdef CONFIG_PM
666 .suspend = viafb_suspend, 758 .suspend = via_suspend,
667 .resume = viafb_resume, 759 .resume = via_resume,
668#endif 760#endif
669}; 761};
670 762
diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c
index 39acb37e7a1d..c2a0a1cfd3b3 100644
--- a/drivers/video/via/via-gpio.c
+++ b/drivers/video/via/via-gpio.c
@@ -172,6 +172,28 @@ static void viafb_gpio_disable(struct viafb_gpio *gpio)
172 via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02); 172 via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02);
173} 173}
174 174
175#ifdef CONFIG_PM
176
177static int viafb_gpio_suspend(void *private)
178{
179 return 0;
180}
181
182static int viafb_gpio_resume(void *private)
183{
184 int i;
185
186 for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2)
187 viafb_gpio_enable(gpio_config.active_gpios[i]);
188 return 0;
189}
190
191static struct viafb_pm_hooks viafb_gpio_pm_hooks = {
192 .suspend = viafb_gpio_suspend,
193 .resume = viafb_gpio_resume
194};
195#endif /* CONFIG_PM */
196
175/* 197/*
176 * Look up a specific gpio and return the number it was assigned. 198 * Look up a specific gpio and return the number it was assigned.
177 */ 199 */
@@ -236,6 +258,9 @@ static __devinit int viafb_gpio_probe(struct platform_device *platdev)
236 printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret); 258 printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret);
237 gpio_config.gpio_chip.ngpio = 0; 259 gpio_config.gpio_chip.ngpio = 0;
238 } 260 }
261#ifdef CONFIG_PM
262 viafb_pm_register(&viafb_gpio_pm_hooks);
263#endif
239 return ret; 264 return ret;
240} 265}
241 266
@@ -245,6 +270,10 @@ static int viafb_gpio_remove(struct platform_device *platdev)
245 unsigned long flags; 270 unsigned long flags;
246 int ret = 0, i; 271 int ret = 0, i;
247 272
273#ifdef CONFIG_PM
274 viafb_pm_unregister(&viafb_gpio_pm_hooks);
275#endif
276
248 /* 277 /*
249 * Get unregistered. 278 * Get unregistered.
250 */ 279 */
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index d298cfccd6fc..289edd519527 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -1672,31 +1672,19 @@ static int parse_mode(const char *str, u32 *xres, u32 *yres)
1672 1672
1673 1673
1674#ifdef CONFIG_PM 1674#ifdef CONFIG_PM
1675int viafb_suspend(struct pci_dev *pdev, pm_message_t state) 1675static int viafb_suspend(void *unused)
1676{ 1676{
1677 if (state.event == PM_EVENT_SUSPEND) { 1677 acquire_console_sem();
1678 acquire_console_sem(); 1678 fb_set_suspend(viafbinfo, 1);
1679 fb_set_suspend(viafbinfo, 1); 1679 viafb_sync(viafbinfo);
1680 1680 release_console_sem();
1681 viafb_sync(viafbinfo);
1682
1683 pci_save_state(pdev);
1684 pci_disable_device(pdev);
1685 pci_set_power_state(pdev, pci_choose_state(pdev, state));
1686 release_console_sem();
1687 }
1688 1681
1689 return 0; 1682 return 0;
1690} 1683}
1691 1684
1692int viafb_resume(struct pci_dev *pdev) 1685static int viafb_resume(void *unused)
1693{ 1686{
1694 acquire_console_sem(); 1687 acquire_console_sem();
1695 pci_set_power_state(pdev, PCI_D0);
1696 pci_restore_state(pdev);
1697 if (pci_enable_device(pdev))
1698 goto fail;
1699 pci_set_master(pdev);
1700 if (viaparinfo->shared->vdev->engine_mmio) 1688 if (viaparinfo->shared->vdev->engine_mmio)
1701 viafb_reset_engine(viaparinfo); 1689 viafb_reset_engine(viaparinfo);
1702 viafb_set_par(viafbinfo); 1690 viafb_set_par(viafbinfo);
@@ -1704,11 +1692,15 @@ int viafb_resume(struct pci_dev *pdev)
1704 viafb_set_par(viafbinfo1); 1692 viafb_set_par(viafbinfo1);
1705 fb_set_suspend(viafbinfo, 0); 1693 fb_set_suspend(viafbinfo, 0);
1706 1694
1707fail:
1708 release_console_sem(); 1695 release_console_sem();
1709 return 0; 1696 return 0;
1710} 1697}
1711 1698
1699static struct viafb_pm_hooks viafb_fb_pm_hooks = {
1700 .suspend = viafb_suspend,
1701 .resume = viafb_resume
1702};
1703
1712#endif 1704#endif
1713 1705
1714 1706
@@ -1899,6 +1891,10 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1899 1891
1900 viafb_init_proc(viaparinfo->shared); 1892 viafb_init_proc(viaparinfo->shared);
1901 viafb_init_dac(IGA2); 1893 viafb_init_dac(IGA2);
1894
1895#ifdef CONFIG_PM
1896 viafb_pm_register(&viafb_fb_pm_hooks);
1897#endif
1902 return 0; 1898 return 0;
1903 1899
1904out_fb_unreg: 1900out_fb_unreg:
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index 4960e3da6645..d66f963e930e 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -108,6 +108,4 @@ void via_fb_pci_remove(struct pci_dev *pdev);
108/* Temporary */ 108/* Temporary */
109int viafb_init(void); 109int viafb_init(void);
110void viafb_exit(void); 110void viafb_exit(void);
111int viafb_suspend(struct pci_dev *pdev, pm_message_t state);
112int viafb_resume(struct pci_dev *pdev);
113#endif /* __VIAFBDEV_H__ */ 111#endif /* __VIAFBDEV_H__ */
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
new file mode 100644
index 000000000000..7617f12e4fd7
--- /dev/null
+++ b/drivers/video/vt8500lcdfb.c
@@ -0,0 +1,447 @@
1/*
2 * linux/drivers/video/vt8500lcdfb.c
3 *
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 *
6 * Based on skeletonfb.c and pxafb.c
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/string.h>
22#include <linux/mm.h>
23#include <linux/slab.h>
24#include <linux/delay.h>
25#include <linux/fb.h>
26#include <linux/init.h>
27#include <linux/interrupt.h>
28#include <linux/io.h>
29#include <linux/dma-mapping.h>
30#include <linux/platform_device.h>
31#include <linux/wait.h>
32
33#include <mach/vt8500fb.h>
34
35#include "vt8500lcdfb.h"
36#include "wmt_ge_rops.h"
37
38#define to_vt8500lcd_info(__info) container_of(__info, \
39 struct vt8500lcd_info, fb)
40
41static int vt8500lcd_set_par(struct fb_info *info)
42{
43 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
44 int reg_bpp = 5; /* 16bpp */
45 int i;
46 unsigned long control0;
47
48 if (!fbi)
49 return -EINVAL;
50
51 if (info->var.bits_per_pixel <= 8) {
52 /* palettized */
53 info->var.red.offset = 0;
54 info->var.red.length = info->var.bits_per_pixel;
55 info->var.red.msb_right = 0;
56
57 info->var.green.offset = 0;
58 info->var.green.length = info->var.bits_per_pixel;
59 info->var.green.msb_right = 0;
60
61 info->var.blue.offset = 0;
62 info->var.blue.length = info->var.bits_per_pixel;
63 info->var.blue.msb_right = 0;
64
65 info->var.transp.offset = 0;
66 info->var.transp.length = 0;
67 info->var.transp.msb_right = 0;
68
69 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
70 info->fix.line_length = info->var.xres_virtual /
71 (8/info->var.bits_per_pixel);
72 } else {
73 /* non-palettized */
74 info->var.transp.offset = 0;
75 info->var.transp.length = 0;
76 info->var.transp.msb_right = 0;
77
78 if (info->var.bits_per_pixel == 16) {
79 /* RGB565 */
80 info->var.red.offset = 11;
81 info->var.red.length = 5;
82 info->var.red.msb_right = 0;
83 info->var.green.offset = 5;
84 info->var.green.length = 6;
85 info->var.green.msb_right = 0;
86 info->var.blue.offset = 0;
87 info->var.blue.length = 5;
88 info->var.blue.msb_right = 0;
89 } else {
90 /* Equal depths per channel */
91 info->var.red.offset = info->var.bits_per_pixel
92 * 2 / 3;
93 info->var.red.length = info->var.bits_per_pixel / 3;
94 info->var.red.msb_right = 0;
95 info->var.green.offset = info->var.bits_per_pixel / 3;
96 info->var.green.length = info->var.bits_per_pixel / 3;
97 info->var.green.msb_right = 0;
98 info->var.blue.offset = 0;
99 info->var.blue.length = info->var.bits_per_pixel / 3;
100 info->var.blue.msb_right = 0;
101 }
102
103 info->fix.visual = FB_VISUAL_TRUECOLOR;
104 info->fix.line_length = info->var.bits_per_pixel > 16 ?
105 info->var.xres_virtual << 2 :
106 info->var.xres_virtual << 1;
107 }
108
109 for (i = 0; i < 8; i++) {
110 if (bpp_values[i] == info->var.bits_per_pixel) {
111 reg_bpp = i;
112 continue;
113 }
114 }
115
116 control0 = readl(fbi->regbase) & ~0xf;
117 writel(0, fbi->regbase);
118 while (readl(fbi->regbase + 0x38) & 0x10)
119 /* wait */;
120 writel((((info->var.hsync_len - 1) & 0x3f) << 26)
121 | ((info->var.left_margin & 0xff) << 18)
122 | (((info->var.xres - 1) & 0x3ff) << 8)
123 | (info->var.right_margin & 0xff), fbi->regbase + 0x4);
124 writel((((info->var.vsync_len - 1) & 0x3f) << 26)
125 | ((info->var.upper_margin & 0xff) << 18)
126 | (((info->var.yres - 1) & 0x3ff) << 8)
127 | (info->var.lower_margin & 0xff), fbi->regbase + 0x8);
128 writel((((info->var.yres - 1) & 0x400) << 2)
129 | ((info->var.xres - 1) & 0x400), fbi->regbase + 0x10);
130 writel(0x80000000, fbi->regbase + 0x20);
131 writel(control0 | (reg_bpp << 1) | 0x100, fbi->regbase);
132
133 return 0;
134}
135
136static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
137{
138 chan &= 0xffff;
139 chan >>= 16 - bf->length;
140 return chan << bf->offset;
141}
142
143static int vt8500lcd_setcolreg(unsigned regno, unsigned red, unsigned green,
144 unsigned blue, unsigned transp,
145 struct fb_info *info) {
146 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
147 int ret = 1;
148 unsigned int val;
149 if (regno >= 256)
150 return -EINVAL;
151
152 if (info->var.grayscale)
153 red = green = blue =
154 (19595 * red + 38470 * green + 7471 * blue) >> 16;
155
156 switch (fbi->fb.fix.visual) {
157 case FB_VISUAL_TRUECOLOR:
158 if (regno < 16) {
159 u32 *pal = fbi->fb.pseudo_palette;
160
161 val = chan_to_field(red, &fbi->fb.var.red);
162 val |= chan_to_field(green, &fbi->fb.var.green);
163 val |= chan_to_field(blue, &fbi->fb.var.blue);
164
165 pal[regno] = val;
166 ret = 0;
167 }
168 break;
169
170 case FB_VISUAL_STATIC_PSEUDOCOLOR:
171 case FB_VISUAL_PSEUDOCOLOR:
172 writew((red & 0xf800)
173 | ((green >> 5) & 0x7e0)
174 | ((blue >> 11) & 0x1f),
175 fbi->palette_cpu + sizeof(u16) * regno);
176 break;
177 }
178
179 return ret;
180}
181
182static int vt8500lcd_ioctl(struct fb_info *info, unsigned int cmd,
183 unsigned long arg)
184{
185 int ret = 0;
186 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
187
188 if (cmd == FBIO_WAITFORVSYNC) {
189 /* Unmask End of Frame interrupt */
190 writel(0xffffffff ^ (1 << 3), fbi->regbase + 0x3c);
191 ret = wait_event_interruptible_timeout(fbi->wait,
192 readl(fbi->regbase + 0x38) & (1 << 3), HZ / 10);
193 /* Mask back to reduce unwanted interrupt traffic */
194 writel(0xffffffff, fbi->regbase + 0x3c);
195 if (ret < 0)
196 return ret;
197 if (ret == 0)
198 return -ETIMEDOUT;
199 }
200
201 return ret;
202}
203
204static int vt8500lcd_pan_display(struct fb_var_screeninfo *var,
205 struct fb_info *info)
206{
207 unsigned pixlen = info->fix.line_length / info->var.xres_virtual;
208 unsigned off = pixlen * var->xoffset
209 + info->fix.line_length * var->yoffset;
210 struct vt8500lcd_info *fbi = to_vt8500lcd_info(info);
211
212 writel((1 << 31)
213 | (((var->xres_virtual - var->xres) * pixlen / 4) << 20)
214 | (off >> 2), fbi->regbase + 0x20);
215 return 0;
216}
217
218static struct fb_ops vt8500lcd_ops = {
219 .owner = THIS_MODULE,
220 .fb_set_par = vt8500lcd_set_par,
221 .fb_setcolreg = vt8500lcd_setcolreg,
222 .fb_fillrect = wmt_ge_fillrect,
223 .fb_copyarea = wmt_ge_copyarea,
224 .fb_imageblit = sys_imageblit,
225 .fb_sync = wmt_ge_sync,
226 .fb_ioctl = vt8500lcd_ioctl,
227 .fb_pan_display = vt8500lcd_pan_display,
228};
229
230static irqreturn_t vt8500lcd_handle_irq(int irq, void *dev_id)
231{
232 struct vt8500lcd_info *fbi = dev_id;
233
234 if (readl(fbi->regbase + 0x38) & (1 << 3))
235 wake_up_interruptible(&fbi->wait);
236
237 writel(0xffffffff, fbi->regbase + 0x38);
238 return IRQ_HANDLED;
239}
240
241static int __devinit vt8500lcd_probe(struct platform_device *pdev)
242{
243 struct vt8500lcd_info *fbi;
244 struct resource *res;
245 struct vt8500fb_platform_data *pdata = pdev->dev.platform_data;
246 void *addr;
247 int irq, ret;
248
249 ret = -ENOMEM;
250 fbi = NULL;
251
252 fbi = kzalloc(sizeof(struct vt8500lcd_info) + sizeof(u32) * 16,
253 GFP_KERNEL);
254 if (!fbi) {
255 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
256 ret = -ENOMEM;
257 goto failed;
258 }
259
260 strcpy(fbi->fb.fix.id, "VT8500 LCD");
261
262 fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
263 fbi->fb.fix.xpanstep = 0;
264 fbi->fb.fix.ypanstep = 1;
265 fbi->fb.fix.ywrapstep = 0;
266 fbi->fb.fix.accel = FB_ACCEL_NONE;
267
268 fbi->fb.var.nonstd = 0;
269 fbi->fb.var.activate = FB_ACTIVATE_NOW;
270 fbi->fb.var.height = -1;
271 fbi->fb.var.width = -1;
272 fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
273
274 fbi->fb.fbops = &vt8500lcd_ops;
275 fbi->fb.flags = FBINFO_DEFAULT
276 | FBINFO_HWACCEL_COPYAREA
277 | FBINFO_HWACCEL_FILLRECT
278 | FBINFO_HWACCEL_YPAN
279 | FBINFO_VIRTFB
280 | FBINFO_PARTIAL_PAN_OK;
281 fbi->fb.node = -1;
282
283 addr = fbi;
284 addr = addr + sizeof(struct vt8500lcd_info);
285 fbi->fb.pseudo_palette = addr;
286
287 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
288 if (res == NULL) {
289 dev_err(&pdev->dev, "no I/O memory resource defined\n");
290 ret = -ENODEV;
291 goto failed_fbi;
292 }
293
294 res = request_mem_region(res->start, resource_size(res), "vt8500lcd");
295 if (res == NULL) {
296 dev_err(&pdev->dev, "failed to request I/O memory\n");
297 ret = -EBUSY;
298 goto failed_fbi;
299 }
300
301 fbi->regbase = ioremap(res->start, resource_size(res));
302 if (fbi->regbase == NULL) {
303 dev_err(&pdev->dev, "failed to map I/O memory\n");
304 ret = -EBUSY;
305 goto failed_free_res;
306 }
307
308 fbi->fb.fix.smem_start = pdata->video_mem_phys;
309 fbi->fb.fix.smem_len = pdata->video_mem_len;
310 fbi->fb.screen_base = pdata->video_mem_virt;
311
312 fbi->palette_size = PAGE_ALIGN(512);
313 fbi->palette_cpu = dma_alloc_coherent(&pdev->dev,
314 fbi->palette_size,
315 &fbi->palette_phys,
316 GFP_KERNEL);
317 if (fbi->palette_cpu == NULL) {
318 dev_err(&pdev->dev, "Failed to allocate palette buffer\n");
319 ret = -ENOMEM;
320 goto failed_free_io;
321 }
322
323 irq = platform_get_irq(pdev, 0);
324 if (irq < 0) {
325 dev_err(&pdev->dev, "no IRQ defined\n");
326 ret = -ENODEV;
327 goto failed_free_palette;
328 }
329
330 ret = request_irq(irq, vt8500lcd_handle_irq, IRQF_DISABLED, "LCD", fbi);
331 if (ret) {
332 dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
333 ret = -EBUSY;
334 goto failed_free_palette;
335 }
336
337 init_waitqueue_head(&fbi->wait);
338
339 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
340 dev_err(&pdev->dev, "Failed to allocate color map\n");
341 ret = -ENOMEM;
342 goto failed_free_irq;
343 }
344
345 fb_videomode_to_var(&fbi->fb.var, &pdata->mode);
346 fbi->fb.var.bits_per_pixel = pdata->bpp;
347 fbi->fb.var.xres_virtual = pdata->xres_virtual;
348 fbi->fb.var.yres_virtual = pdata->yres_virtual;
349
350 ret = vt8500lcd_set_par(&fbi->fb);
351 if (ret) {
352 dev_err(&pdev->dev, "Failed to set parameters\n");
353 goto failed_free_cmap;
354 }
355
356 writel(fbi->fb.fix.smem_start >> 22, fbi->regbase + 0x1c);
357 writel((fbi->palette_phys & 0xfffffe00) | 1, fbi->regbase + 0x18);
358
359 platform_set_drvdata(pdev, fbi);
360
361 ret = register_framebuffer(&fbi->fb);
362 if (ret < 0) {
363 dev_err(&pdev->dev,
364 "Failed to register framebuffer device: %d\n", ret);
365 goto failed_free_cmap;
366 }
367
368 /*
369 * Ok, now enable the LCD controller
370 */
371 writel(readl(fbi->regbase) | 1, fbi->regbase);
372
373 return 0;
374
375failed_free_cmap:
376 if (fbi->fb.cmap.len)
377 fb_dealloc_cmap(&fbi->fb.cmap);
378failed_free_irq:
379 free_irq(irq, fbi);
380failed_free_palette:
381 dma_free_coherent(&pdev->dev, fbi->palette_size,
382 fbi->palette_cpu, fbi->palette_phys);
383failed_free_io:
384 iounmap(fbi->regbase);
385failed_free_res:
386 release_mem_region(res->start, resource_size(res));
387failed_fbi:
388 platform_set_drvdata(pdev, NULL);
389 kfree(fbi);
390failed:
391 return ret;
392}
393
394static int __devexit vt8500lcd_remove(struct platform_device *pdev)
395{
396 struct vt8500lcd_info *fbi = platform_get_drvdata(pdev);
397 struct resource *res;
398 int irq;
399
400 unregister_framebuffer(&fbi->fb);
401
402 writel(0, fbi->regbase);
403
404 if (fbi->fb.cmap.len)
405 fb_dealloc_cmap(&fbi->fb.cmap);
406
407 irq = platform_get_irq(pdev, 0);
408 free_irq(irq, fbi);
409
410 dma_free_coherent(&pdev->dev, fbi->palette_size,
411 fbi->palette_cpu, fbi->palette_phys);
412
413 iounmap(fbi->regbase);
414
415 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
416 release_mem_region(res->start, resource_size(res));
417
418 kfree(fbi);
419
420 return 0;
421}
422
423static struct platform_driver vt8500lcd_driver = {
424 .probe = vt8500lcd_probe,
425 .remove = __devexit_p(vt8500lcd_remove),
426 .driver = {
427 .owner = THIS_MODULE,
428 .name = "vt8500-lcd",
429 },
430};
431
432static int __init vt8500lcd_init(void)
433{
434 return platform_driver_register(&vt8500lcd_driver);
435}
436
437static void __exit vt8500lcd_exit(void)
438{
439 platform_driver_unregister(&vt8500lcd_driver);
440}
441
442module_init(vt8500lcd_init);
443module_exit(vt8500lcd_exit);
444
445MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
446MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
447MODULE_LICENSE("GPL");
diff --git a/drivers/video/vt8500lcdfb.h b/drivers/video/vt8500lcdfb.h
new file mode 100644
index 000000000000..36ca3ca09d83
--- /dev/null
+++ b/drivers/video/vt8500lcdfb.h
@@ -0,0 +1,34 @@
1/*
2 * linux/drivers/video/vt8500lcdfb.h
3 *
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16struct vt8500lcd_info {
17 struct fb_info fb;
18 void __iomem *regbase;
19 void __iomem *palette_cpu;
20 dma_addr_t palette_phys;
21 size_t palette_size;
22 wait_queue_head_t wait;
23};
24
25static int bpp_values[] = {
26 1,
27 2,
28 4,
29 8,
30 12,
31 16,
32 18,
33 24,
34};
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
new file mode 100644
index 000000000000..96e34a569169
--- /dev/null
+++ b/drivers/video/wm8505fb.c
@@ -0,0 +1,422 @@
1/*
2 * WonderMedia WM8505 Frame Buffer device driver
3 *
4 * Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
5 * Based on vt8500lcdfb.c
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/errno.h>
20#include <linux/string.h>
21#include <linux/mm.h>
22#include <linux/slab.h>
23#include <linux/delay.h>
24#include <linux/fb.h>
25#include <linux/init.h>
26#include <linux/interrupt.h>
27#include <linux/io.h>
28#include <linux/dma-mapping.h>
29#include <linux/platform_device.h>
30#include <linux/wait.h>
31
32#include <mach/vt8500fb.h>
33
34#include "wm8505fb_regs.h"
35#include "wmt_ge_rops.h"
36
37#define DRIVER_NAME "wm8505-fb"
38
39#define to_wm8505fb_info(__info) container_of(__info, \
40 struct wm8505fb_info, fb)
41struct wm8505fb_info {
42 struct fb_info fb;
43 void __iomem *regbase;
44 unsigned int contrast;
45};
46
47
48static int wm8505fb_init_hw(struct fb_info *info)
49{
50 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
51
52 int i;
53
54 /* I know the purpose only of few registers, so clear unknown */
55 for (i = 0; i < 0x200; i += 4)
56 writel(0, fbi->regbase + i);
57
58 /* Set frame buffer address */
59 writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR);
60 writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR1);
61
62 /* Set in-memory picture format to RGB 32bpp */
63 writel(0x1c, fbi->regbase + WMT_GOVR_COLORSPACE);
64 writel(1, fbi->regbase + WMT_GOVR_COLORSPACE1);
65
66 /* Virtual buffer size */
67 writel(info->var.xres, fbi->regbase + WMT_GOVR_XRES);
68 writel(info->var.xres_virtual, fbi->regbase + WMT_GOVR_XRES_VIRTUAL);
69
70 /* black magic ;) */
71 writel(0xf, fbi->regbase + WMT_GOVR_FHI);
72 writel(4, fbi->regbase + WMT_GOVR_DVO_SET);
73 writel(1, fbi->regbase + WMT_GOVR_MIF_ENABLE);
74 writel(1, fbi->regbase + WMT_GOVR_REG_UPDATE);
75
76 return 0;
77}
78
79static int wm8505fb_set_timing(struct fb_info *info)
80{
81 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
82
83 int h_start = info->var.left_margin;
84 int h_end = h_start + info->var.xres;
85 int h_all = h_end + info->var.right_margin;
86 int h_sync = info->var.hsync_len;
87
88 int v_start = info->var.upper_margin;
89 int v_end = v_start + info->var.yres;
90 int v_all = v_end + info->var.lower_margin;
91 int v_sync = info->var.vsync_len;
92
93 writel(0, fbi->regbase + WMT_GOVR_TG);
94
95 writel(h_start, fbi->regbase + WMT_GOVR_TIMING_H_START);
96 writel(h_end, fbi->regbase + WMT_GOVR_TIMING_H_END);
97 writel(h_all, fbi->regbase + WMT_GOVR_TIMING_H_ALL);
98 writel(h_sync, fbi->regbase + WMT_GOVR_TIMING_H_SYNC);
99
100 writel(v_start, fbi->regbase + WMT_GOVR_TIMING_V_START);
101 writel(v_end, fbi->regbase + WMT_GOVR_TIMING_V_END);
102 writel(v_all, fbi->regbase + WMT_GOVR_TIMING_V_ALL);
103 writel(v_sync, fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
104
105 writel(1, fbi->regbase + WMT_GOVR_TG);
106
107 return 0;
108}
109
110
111static int wm8505fb_set_par(struct fb_info *info)
112{
113 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
114
115 if (!fbi)
116 return -EINVAL;
117
118 if (info->var.bits_per_pixel == 32) {
119 info->var.red.offset = 16;
120 info->var.red.length = 8;
121 info->var.red.msb_right = 0;
122 info->var.green.offset = 8;
123 info->var.green.length = 8;
124 info->var.green.msb_right = 0;
125 info->var.blue.offset = 0;
126 info->var.blue.length = 8;
127 info->var.blue.msb_right = 0;
128 info->fix.visual = FB_VISUAL_TRUECOLOR;
129 info->fix.line_length = info->var.xres_virtual << 2;
130 }
131
132 wm8505fb_set_timing(info);
133
134 writel(fbi->contrast<<16 | fbi->contrast<<8 | fbi->contrast,
135 fbi->regbase + WMT_GOVR_CONTRAST);
136
137 return 0;
138}
139
140static ssize_t contrast_show(struct device *dev,
141 struct device_attribute *attr, char *buf)
142{
143 struct fb_info *info = dev_get_drvdata(dev);
144 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
145
146 return sprintf(buf, "%d\n", fbi->contrast);
147}
148
149static ssize_t contrast_store(struct device *dev,
150 struct device_attribute *attr,
151 const char *buf, size_t count)
152{
153 struct fb_info *info = dev_get_drvdata(dev);
154 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
155 unsigned long tmp;
156
157 if (strict_strtoul(buf, 10, &tmp) || (tmp > 0xff))
158 return -EINVAL;
159 fbi->contrast = tmp;
160
161 wm8505fb_set_par(info);
162
163 return count;
164}
165
166static DEVICE_ATTR(contrast, 0644, contrast_show, contrast_store);
167
168static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
169{
170 chan &= 0xffff;
171 chan >>= 16 - bf->length;
172 return chan << bf->offset;
173}
174
175static int wm8505fb_setcolreg(unsigned regno, unsigned red, unsigned green,
176 unsigned blue, unsigned transp,
177 struct fb_info *info) {
178 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
179 int ret = 1;
180 unsigned int val;
181 if (regno >= 256)
182 return -EINVAL;
183
184 if (info->var.grayscale)
185 red = green = blue =
186 (19595 * red + 38470 * green + 7471 * blue) >> 16;
187
188 switch (fbi->fb.fix.visual) {
189 case FB_VISUAL_TRUECOLOR:
190 if (regno < 16) {
191 u32 *pal = info->pseudo_palette;
192
193 val = chan_to_field(red, &fbi->fb.var.red);
194 val |= chan_to_field(green, &fbi->fb.var.green);
195 val |= chan_to_field(blue, &fbi->fb.var.blue);
196
197 pal[regno] = val;
198 ret = 0;
199 }
200 break;
201 }
202
203 return ret;
204}
205
206static int wm8505fb_pan_display(struct fb_var_screeninfo *var,
207 struct fb_info *info)
208{
209 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
210
211 writel(var->xoffset, fbi->regbase + WMT_GOVR_XPAN);
212 writel(var->yoffset, fbi->regbase + WMT_GOVR_YPAN);
213 return 0;
214}
215
216static int wm8505fb_blank(int blank, struct fb_info *info)
217{
218 struct wm8505fb_info *fbi = to_wm8505fb_info(info);
219
220 switch (blank) {
221 case FB_BLANK_UNBLANK:
222 wm8505fb_set_timing(info);
223 break;
224 default:
225 writel(0, fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
226 break;
227 }
228
229 return 0;
230}
231
232static struct fb_ops wm8505fb_ops = {
233 .owner = THIS_MODULE,
234 .fb_set_par = wm8505fb_set_par,
235 .fb_setcolreg = wm8505fb_setcolreg,
236 .fb_fillrect = wmt_ge_fillrect,
237 .fb_copyarea = wmt_ge_copyarea,
238 .fb_imageblit = sys_imageblit,
239 .fb_sync = wmt_ge_sync,
240 .fb_pan_display = wm8505fb_pan_display,
241 .fb_blank = wm8505fb_blank,
242};
243
244static int __devinit wm8505fb_probe(struct platform_device *pdev)
245{
246 struct wm8505fb_info *fbi;
247 struct resource *res;
248 void *addr;
249 struct vt8500fb_platform_data *pdata;
250 int ret;
251
252 pdata = pdev->dev.platform_data;
253
254 ret = -ENOMEM;
255 fbi = NULL;
256
257 fbi = kzalloc(sizeof(struct wm8505fb_info) + sizeof(u32) * 16,
258 GFP_KERNEL);
259 if (!fbi) {
260 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
261 ret = -ENOMEM;
262 goto failed;
263 }
264
265 strcpy(fbi->fb.fix.id, DRIVER_NAME);
266
267 fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
268 fbi->fb.fix.xpanstep = 1;
269 fbi->fb.fix.ypanstep = 1;
270 fbi->fb.fix.ywrapstep = 0;
271 fbi->fb.fix.accel = FB_ACCEL_NONE;
272
273 fbi->fb.fbops = &wm8505fb_ops;
274 fbi->fb.flags = FBINFO_DEFAULT
275 | FBINFO_HWACCEL_COPYAREA
276 | FBINFO_HWACCEL_FILLRECT
277 | FBINFO_HWACCEL_XPAN
278 | FBINFO_HWACCEL_YPAN
279 | FBINFO_VIRTFB
280 | FBINFO_PARTIAL_PAN_OK;
281 fbi->fb.node = -1;
282
283 addr = fbi;
284 addr = addr + sizeof(struct wm8505fb_info);
285 fbi->fb.pseudo_palette = addr;
286
287 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
288 if (res == NULL) {
289 dev_err(&pdev->dev, "no I/O memory resource defined\n");
290 ret = -ENODEV;
291 goto failed_fbi;
292 }
293
294 res = request_mem_region(res->start, resource_size(res), DRIVER_NAME);
295 if (res == NULL) {
296 dev_err(&pdev->dev, "failed to request I/O memory\n");
297 ret = -EBUSY;
298 goto failed_fbi;
299 }
300
301 fbi->regbase = ioremap(res->start, resource_size(res));
302 if (fbi->regbase == NULL) {
303 dev_err(&pdev->dev, "failed to map I/O memory\n");
304 ret = -EBUSY;
305 goto failed_free_res;
306 }
307
308 fb_videomode_to_var(&fbi->fb.var, &pdata->mode);
309
310 fbi->fb.var.nonstd = 0;
311 fbi->fb.var.activate = FB_ACTIVATE_NOW;
312
313 fbi->fb.var.height = -1;
314 fbi->fb.var.width = -1;
315 fbi->fb.var.xres_virtual = pdata->xres_virtual;
316 fbi->fb.var.yres_virtual = pdata->yres_virtual;
317 fbi->fb.var.bits_per_pixel = pdata->bpp;
318
319 fbi->fb.fix.smem_start = pdata->video_mem_phys;
320 fbi->fb.fix.smem_len = pdata->video_mem_len;
321 fbi->fb.screen_base = pdata->video_mem_virt;
322 fbi->fb.screen_size = pdata->video_mem_len;
323
324 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
325 dev_err(&pdev->dev, "Failed to allocate color map\n");
326 ret = -ENOMEM;
327 goto failed_free_io;
328 }
329
330 wm8505fb_init_hw(&fbi->fb);
331
332 fbi->contrast = 0x80;
333 ret = wm8505fb_set_par(&fbi->fb);
334 if (ret) {
335 dev_err(&pdev->dev, "Failed to set parameters\n");
336 goto failed_free_cmap;
337 }
338
339 platform_set_drvdata(pdev, fbi);
340
341 ret = register_framebuffer(&fbi->fb);
342 if (ret < 0) {
343 dev_err(&pdev->dev,
344 "Failed to register framebuffer device: %d\n", ret);
345 goto failed_free_cmap;
346 }
347
348 ret = device_create_file(&pdev->dev, &dev_attr_contrast);
349 if (ret < 0) {
350 printk(KERN_WARNING "fb%d: failed to register attributes (%d)\n",
351 fbi->fb.node, ret);
352 }
353
354 printk(KERN_INFO "fb%d: %s frame buffer at 0x%lx-0x%lx\n",
355 fbi->fb.node, fbi->fb.fix.id, fbi->fb.fix.smem_start,
356 fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
357
358 return 0;
359
360failed_free_cmap:
361 if (fbi->fb.cmap.len)
362 fb_dealloc_cmap(&fbi->fb.cmap);
363failed_free_io:
364 iounmap(fbi->regbase);
365failed_free_res:
366 release_mem_region(res->start, resource_size(res));
367failed_fbi:
368 platform_set_drvdata(pdev, NULL);
369 kfree(fbi);
370failed:
371 return ret;
372}
373
374static int __devexit wm8505fb_remove(struct platform_device *pdev)
375{
376 struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
377 struct resource *res;
378
379 device_remove_file(&pdev->dev, &dev_attr_contrast);
380
381 unregister_framebuffer(&fbi->fb);
382
383 writel(0, fbi->regbase);
384
385 if (fbi->fb.cmap.len)
386 fb_dealloc_cmap(&fbi->fb.cmap);
387
388 iounmap(fbi->regbase);
389
390 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
391 release_mem_region(res->start, resource_size(res));
392
393 kfree(fbi);
394
395 return 0;
396}
397
398static struct platform_driver wm8505fb_driver = {
399 .probe = wm8505fb_probe,
400 .remove = __devexit_p(wm8505fb_remove),
401 .driver = {
402 .owner = THIS_MODULE,
403 .name = DRIVER_NAME,
404 },
405};
406
407static int __init wm8505fb_init(void)
408{
409 return platform_driver_register(&wm8505fb_driver);
410}
411
412static void __exit wm8505fb_exit(void)
413{
414 platform_driver_unregister(&wm8505fb_driver);
415}
416
417module_init(wm8505fb_init);
418module_exit(wm8505fb_exit);
419
420MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>");
421MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
422MODULE_LICENSE("GPL");
diff --git a/drivers/video/wm8505fb_regs.h b/drivers/video/wm8505fb_regs.h
new file mode 100644
index 000000000000..4dd41668c6d1
--- /dev/null
+++ b/drivers/video/wm8505fb_regs.h
@@ -0,0 +1,76 @@
1/*
2 * GOVR registers list for WM8505 chips
3 *
4 * Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
5 * Based on VIA/WonderMedia wm8510-govrh-reg.h
6 * http://github.com/projectgus/kernel_wm8505/blob/wm8505_2.6.29/
7 * drivers/video/wmt/register/wm8510/wm8510-govrh-reg.h
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#ifndef _WM8505FB_REGS_H
20#define _WM8505FB_REGS_H
21
22/*
23 * Color space select register, default value 0x1c
24 * BIT0 GOVRH_DVO_YUV2RGB_ENABLE
25 * BIT1 GOVRH_VGA_YUV2RGB_ENABLE
26 * BIT2 GOVRH_RGB_MODE
27 * BIT3 GOVRH_DAC_CLKINV
28 * BIT4 GOVRH_BLANK_ZERO
29 */
30#define WMT_GOVR_COLORSPACE 0x1e4
31/*
32 * Another colorspace select register, default value 1
33 * BIT0 GOVRH_DVO_RGB
34 * BIT1 GOVRH_DVO_YUV422
35 */
36#define WMT_GOVR_COLORSPACE1 0x30
37
38#define WMT_GOVR_CONTRAST 0x1b8
39#define WMT_GOVR_BRGHTNESS 0x1bc /* incompatible with RGB? */
40
41/* Framubeffer address */
42#define WMT_GOVR_FBADDR 0x90
43#define WMT_GOVR_FBADDR1 0x94 /* UV offset in YUV mode */
44
45/* Offset of visible window */
46#define WMT_GOVR_XPAN 0xa4
47#define WMT_GOVR_YPAN 0xa0
48
49#define WMT_GOVR_XRES 0x98
50#define WMT_GOVR_XRES_VIRTUAL 0x9c
51
52#define WMT_GOVR_MIF_ENABLE 0x80
53#define WMT_GOVR_FHI 0xa8
54#define WMT_GOVR_REG_UPDATE 0xe4
55
56/*
57 * BIT0 GOVRH_DVO_OUTWIDTH
58 * BIT1 GOVRH_DVO_SYNC_POLAR
59 * BIT2 GOVRH_DVO_ENABLE
60 */
61#define WMT_GOVR_DVO_SET 0x148
62
63/* Timing generator? */
64#define WMT_GOVR_TG 0x100
65
66/* Timings */
67#define WMT_GOVR_TIMING_H_ALL 0x108
68#define WMT_GOVR_TIMING_V_ALL 0x10c
69#define WMT_GOVR_TIMING_V_START 0x110
70#define WMT_GOVR_TIMING_V_END 0x114
71#define WMT_GOVR_TIMING_H_START 0x118
72#define WMT_GOVR_TIMING_H_END 0x11c
73#define WMT_GOVR_TIMING_V_SYNC 0x128
74#define WMT_GOVR_TIMING_H_SYNC 0x12c
75
76#endif /* _WM8505FB_REGS_H */
diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/wmt_ge_rops.c
new file mode 100644
index 000000000000..45832b7ef7d2
--- /dev/null
+++ b/drivers/video/wmt_ge_rops.c
@@ -0,0 +1,186 @@
1/*
2 * linux/drivers/video/wmt_ge_rops.c
3 *
4 * Accelerators for raster operations using WonderMedia Graphics Engine
5 *
6 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/fb.h>
20#include <linux/platform_device.h>
21#include "fb_draw.h"
22
23#define GE_COMMAND_OFF 0x00
24#define GE_DEPTH_OFF 0x04
25#define GE_HIGHCOLOR_OFF 0x08
26#define GE_ROPCODE_OFF 0x14
27#define GE_FIRE_OFF 0x18
28#define GE_SRCBASE_OFF 0x20
29#define GE_SRCDISPW_OFF 0x24
30#define GE_SRCDISPH_OFF 0x28
31#define GE_SRCAREAX_OFF 0x2c
32#define GE_SRCAREAY_OFF 0x30
33#define GE_SRCAREAW_OFF 0x34
34#define GE_SRCAREAH_OFF 0x38
35#define GE_DESTBASE_OFF 0x3c
36#define GE_DESTDISPW_OFF 0x40
37#define GE_DESTDISPH_OFF 0x44
38#define GE_DESTAREAX_OFF 0x48
39#define GE_DESTAREAY_OFF 0x4c
40#define GE_DESTAREAW_OFF 0x50
41#define GE_DESTAREAH_OFF 0x54
42#define GE_PAT0C_OFF 0x88 /* Pattern 0 color */
43#define GE_ENABLE_OFF 0xec
44#define GE_INTEN_OFF 0xf0
45#define GE_STATUS_OFF 0xf8
46
47static void __iomem *regbase;
48
49void wmt_ge_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
50{
51 unsigned long fg, pat;
52
53 if (p->state != FBINFO_STATE_RUNNING)
54 return;
55
56 if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
57 p->fix.visual == FB_VISUAL_DIRECTCOLOR)
58 fg = ((u32 *) (p->pseudo_palette))[rect->color];
59 else
60 fg = rect->color;
61
62 pat = pixel_to_pat(p->var.bits_per_pixel, fg);
63
64 if (p->fbops->fb_sync)
65 p->fbops->fb_sync(p);
66
67 writel(p->var.bits_per_pixel == 32 ? 3 :
68 (p->var.bits_per_pixel == 8 ? 0 : 1), regbase + GE_DEPTH_OFF);
69 writel(p->var.bits_per_pixel == 15 ? 1 : 0, regbase + GE_HIGHCOLOR_OFF);
70 writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
71 writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
72 writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
73 writel(rect->dx, regbase + GE_DESTAREAX_OFF);
74 writel(rect->dy, regbase + GE_DESTAREAY_OFF);
75 writel(rect->width - 1, regbase + GE_DESTAREAW_OFF);
76 writel(rect->height - 1, regbase + GE_DESTAREAH_OFF);
77
78 writel(pat, regbase + GE_PAT0C_OFF);
79 writel(1, regbase + GE_COMMAND_OFF);
80 writel(rect->rop == ROP_XOR ? 0x5a : 0xf0, regbase + GE_ROPCODE_OFF);
81 writel(1, regbase + GE_FIRE_OFF);
82}
83EXPORT_SYMBOL_GPL(wmt_ge_fillrect);
84
85void wmt_ge_copyarea(struct fb_info *p, const struct fb_copyarea *area)
86{
87 if (p->state != FBINFO_STATE_RUNNING)
88 return;
89
90 if (p->fbops->fb_sync)
91 p->fbops->fb_sync(p);
92
93 writel(p->var.bits_per_pixel > 16 ? 3 :
94 (p->var.bits_per_pixel > 8 ? 1 : 0), regbase + GE_DEPTH_OFF);
95
96 writel(p->fix.smem_start, regbase + GE_SRCBASE_OFF);
97 writel(p->var.xres_virtual - 1, regbase + GE_SRCDISPW_OFF);
98 writel(p->var.yres_virtual - 1, regbase + GE_SRCDISPH_OFF);
99 writel(area->sx, regbase + GE_SRCAREAX_OFF);
100 writel(area->sy, regbase + GE_SRCAREAY_OFF);
101 writel(area->width - 1, regbase + GE_SRCAREAW_OFF);
102 writel(area->height - 1, regbase + GE_SRCAREAH_OFF);
103
104 writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
105 writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
106 writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
107 writel(area->dx, regbase + GE_DESTAREAX_OFF);
108 writel(area->dy, regbase + GE_DESTAREAY_OFF);
109 writel(area->width - 1, regbase + GE_DESTAREAW_OFF);
110 writel(area->height - 1, regbase + GE_DESTAREAH_OFF);
111
112 writel(0xcc, regbase + GE_ROPCODE_OFF);
113 writel(1, regbase + GE_COMMAND_OFF);
114 writel(1, regbase + GE_FIRE_OFF);
115}
116EXPORT_SYMBOL_GPL(wmt_ge_copyarea);
117
118int wmt_ge_sync(struct fb_info *p)
119{
120 int loops = 5000000;
121 while ((readl(regbase + GE_STATUS_OFF) & 4) && --loops)
122 cpu_relax();
123 return loops > 0 ? 0 : -EBUSY;
124}
125EXPORT_SYMBOL_GPL(wmt_ge_sync);
126
127static int __devinit wmt_ge_rops_probe(struct platform_device *pdev)
128{
129 struct resource *res;
130
131 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
132 if (res == NULL) {
133 dev_err(&pdev->dev, "no I/O memory resource defined\n");
134 return -ENODEV;
135 }
136
137 /* Only one ROP engine is presently supported. */
138 if (unlikely(regbase)) {
139 WARN_ON(1);
140 return -EBUSY;
141 }
142
143 regbase = ioremap(res->start, resource_size(res));
144 if (regbase == NULL) {
145 dev_err(&pdev->dev, "failed to map I/O memory\n");
146 return -EBUSY;
147 }
148
149 writel(1, regbase + GE_ENABLE_OFF);
150 printk(KERN_INFO "Enabled support for WMT GE raster acceleration\n");
151
152 return 0;
153}
154
155static int __devexit wmt_ge_rops_remove(struct platform_device *pdev)
156{
157 iounmap(regbase);
158 return 0;
159}
160
161static struct platform_driver wmt_ge_rops_driver = {
162 .probe = wmt_ge_rops_probe,
163 .remove = __devexit_p(wmt_ge_rops_remove),
164 .driver = {
165 .owner = THIS_MODULE,
166 .name = "wmt_ge_rops",
167 },
168};
169
170static int __init wmt_ge_rops_init(void)
171{
172 return platform_driver_register(&wmt_ge_rops_driver);
173}
174
175static void __exit wmt_ge_rops_exit(void)
176{
177 platform_driver_unregister(&wmt_ge_rops_driver);
178}
179
180module_init(wmt_ge_rops_init);
181module_exit(wmt_ge_rops_exit);
182
183MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com");
184MODULE_DESCRIPTION("Accelerators for raster operations using "
185 "WonderMedia Graphics Engine");
186MODULE_LICENSE("GPL");
diff --git a/drivers/video/wmt_ge_rops.h b/drivers/video/wmt_ge_rops.h
new file mode 100644
index 000000000000..87380751a443
--- /dev/null
+++ b/drivers/video/wmt_ge_rops.h
@@ -0,0 +1,5 @@
1extern void wmt_ge_fillrect(struct fb_info *info,
2 const struct fb_fillrect *rect);
3extern void wmt_ge_copyarea(struct fb_info *info,
4 const struct fb_copyarea *area);
5extern int wmt_ge_sync(struct fb_info *info);
diff --git a/include/linux/fb.h b/include/linux/fb.h
index d1631d37e9e0..68ba85a00c06 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -1092,6 +1092,8 @@ extern int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var);
1092extern const unsigned char *fb_firmware_edid(struct device *device); 1092extern const unsigned char *fb_firmware_edid(struct device *device);
1093extern void fb_edid_to_monspecs(unsigned char *edid, 1093extern void fb_edid_to_monspecs(unsigned char *edid,
1094 struct fb_monspecs *specs); 1094 struct fb_monspecs *specs);
1095extern void fb_edid_add_monspecs(unsigned char *edid,
1096 struct fb_monspecs *specs);
1095extern void fb_destroy_modedb(struct fb_videomode *modedb); 1097extern void fb_destroy_modedb(struct fb_videomode *modedb);
1096extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb); 1098extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
1097extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter); 1099extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
@@ -1150,6 +1152,7 @@ struct fb_videomode {
1150 1152
1151extern const char *fb_mode_option; 1153extern const char *fb_mode_option;
1152extern const struct fb_videomode vesa_modes[]; 1154extern const struct fb_videomode vesa_modes[];
1155extern const struct fb_videomode cea_modes[64];
1153 1156
1154struct fb_modelist { 1157struct fb_modelist {
1155 struct list_head list; 1158 struct list_head list;
diff --git a/include/linux/via-core.h b/include/linux/via-core.h
index 38bffd8ccca5..9c21cdf3e3b3 100644
--- a/include/linux/via-core.h
+++ b/include/linux/via-core.h
@@ -60,6 +60,21 @@ struct via_port_cfg {
60}; 60};
61 61
62/* 62/*
63 * Allow subdevs to register suspend/resume hooks.
64 */
65#ifdef CONFIG_PM
66struct viafb_pm_hooks {
67 struct list_head list;
68 int (*suspend)(void *private);
69 int (*resume)(void *private);
70 void *private;
71};
72
73void viafb_pm_register(struct viafb_pm_hooks *hooks);
74void viafb_pm_unregister(struct viafb_pm_hooks *hooks);
75#endif /* CONFIG_PM */
76
77/*
63 * This is the global viafb "device" containing stuff needed by 78 * This is the global viafb "device" containing stuff needed by
64 * all subdevs. 79 * all subdevs.
65 */ 80 */
diff --git a/include/video/s1d13xxxfb.h b/include/video/s1d13xxxfb.h
index f0736cff2ca3..55f534491a3d 100644
--- a/include/video/s1d13xxxfb.h
+++ b/include/video/s1d13xxxfb.h
@@ -136,12 +136,6 @@
136#define S1DREG_DELAYOFF 0xFFFE 136#define S1DREG_DELAYOFF 0xFFFE
137#define S1DREG_DELAYON 0xFFFF 137#define S1DREG_DELAYON 0xFFFF
138 138
139#define BBLT_FIFO_EMPTY 0x00
140#define BBLT_FIFO_NOT_EMPTY 0x40
141#define BBLT_FIFO_NOT_FULL 0x30
142#define BBLT_FIFO_HALF_FULL 0x20
143#define BBLT_FIFO_FULL 0x10
144
145#define BBLT_SOLID_FILL 0x0c 139#define BBLT_SOLID_FILL 0x0c
146 140
147 141
diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h
index 1e1aa54ab2e4..b56932927d0a 100644
--- a/include/video/sh_mobile_hdmi.h
+++ b/include/video/sh_mobile_hdmi.h
@@ -13,6 +13,7 @@
13 13
14struct sh_mobile_lcdc_chan_cfg; 14struct sh_mobile_lcdc_chan_cfg;
15struct device; 15struct device;
16struct clk;
16 17
17/* 18/*
18 * flags format 19 * flags format
@@ -33,6 +34,8 @@ struct sh_mobile_hdmi_info {
33 struct sh_mobile_lcdc_chan_cfg *lcd_chan; 34 struct sh_mobile_lcdc_chan_cfg *lcd_chan;
34 struct device *lcd_dev; 35 struct device *lcd_dev;
35 unsigned int flags; 36 unsigned int flags;
37 long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq,
38 unsigned long *parent_freq);
36}; 39};
37 40
38#endif 41#endif