aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-22 23:43:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-22 23:43:40 -0400
commit437538267b672f9320833907f1b5acbb2605f4be (patch)
treed10173b35a5b86bc037bb2ece1b406d5575a2094
parent9586c959bfc917695893bef0102433a7d0675691 (diff)
parent6bff98b455cf3e666fd0e3d0d908eba874de0eee (diff)
Merge tag 'fbdev-updates-for-3.4' of git://github.com/schandinat/linux-2.6
Pull fbdev updates for 3.4 from Florian Tobias Schandinat: - drivers for Samsung Exynos MIPI DSI and display port - i740fb to support those old Intel chips - large updates to OMAP, viafb and sh_mobile_lcdcfb - some updates to s3c-fb and udlfb, few patches to others Fix up conflicts in drivers/video/udlfb.c due to Key Sievers' fix making it in twice. * tag 'fbdev-updates-for-3.4' of git://github.com/schandinat/linux-2.6: (156 commits) Revert "video:uvesafb: Fix oops that uvesafb try to execute NX-protected page" OMAPDSS: register dss drivers in module init video: pxafb: add clk_prepare/clk_unprepare calls fbdev: bfin_adv7393fb: Drop needless include fbdev: sh_mipi_dsi: add extra phyctrl for sh_mipi_dsi_info fbdev: remove dependency of FB_SH_MOBILE_MERAM from FB_SH_MOBILE_LCDC Revert "MAINTAINERS: add entry for exynos mipi display drivers" fbdev: da8xx: add support for SP10Q010 display fbdev: da8xx:: fix reporting of the display timing info drivers/video/pvr2fb.c: ensure arguments to request_irq and free_irq are compatible OMAPDSS: APPLY: fix clearing shadow dirty flag with manual update fbdev: sh_mobile_meram: Implement system suspend/resume fbdev: sh_mobile_meram: Remove unneeded sanity checks fbdev: sh_mobile_meram: Don't perform update in register operation arm: mach-shmobile: Constify sh_mobile_meram_cfg structures fbdev: sh_mobile_lcdc: Don't store copy of platform data fbdev: sh_mobile_meram: Remove unused sh_mobile_meram_icb_cfg fields arm: mach-shmobile: Don't set MERAM ICB numbers in platform data fbdev: sh_mobile_meram: Allocate ICBs automatically fbdev: sh_mobile_meram: Use genalloc to manage MERAM allocation ...
-rw-r--r--MAINTAINERS33
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c9
-rw-r--r--arch/arm/mach-omap1/board-fsample.c15
-rw-r--r--arch/arm/mach-omap1/board-h2.c15
-rw-r--r--arch/arm/mach-omap1/board-h3.c9
-rw-r--r--arch/arm/mach-omap1/board-htcherald.c9
-rw-r--r--arch/arm/mach-omap1/board-innovator.c11
-rw-r--r--arch/arm/mach-omap1/board-nokia770.c19
-rw-r--r--arch/arm/mach-omap1/board-osk.c14
-rw-r--r--arch/arm/mach-omap1/board-palmte.c10
-rw-r--r--arch/arm/mach-omap1/board-palmtt.c10
-rw-r--r--arch/arm/mach-omap1/board-palmz71.c10
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c15
-rw-r--r--arch/arm/mach-omap1/board-sx1.c16
-rw-r--r--arch/arm/mach-omap2/io.c1
-rw-r--r--arch/arm/mach-shmobile/board-ag5evm.c24
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c302
-rw-r--r--arch/arm/mach-shmobile/board-bonito.c6
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c106
-rw-r--r--arch/arm/plat-omap/common.c2
-rw-r--r--arch/arm/plat-omap/fb.c334
-rw-r--r--arch/arm/plat-omap/fb.h10
-rw-r--r--arch/arm/plat-omap/include/plat/blizzard.h12
-rw-r--r--arch/arm/plat-omap/include/plat/board.h2
-rw-r--r--arch/arm/plat-omap/include/plat/hwa742.h8
-rw-r--r--arch/arm/plat-omap/include/plat/vram.h21
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-fb.h33
-rw-r--r--arch/sh/boards/mach-ap325rxa/setup.c22
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c20
-rw-r--r--arch/sh/boards/mach-kfr2r09/lcd_wqvga.c10
-rw-r--r--arch/sh/boards/mach-kfr2r09/setup.c8
-rw-r--r--arch/sh/boards/mach-migor/lcd_qvga.c3
-rw-r--r--arch/sh/boards/mach-migor/setup.c16
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c12
-rw-r--r--arch/sh/include/mach-kfr2r09/mach/kfr2r09.h16
-rw-r--r--arch/sh/include/mach-migor/mach/migor.h2
-rw-r--r--drivers/video/Kconfig39
-rw-r--r--drivers/video/Makefile3
-rw-r--r--drivers/video/atmel_lcdfb.c12
-rw-r--r--drivers/video/au1100fb.c32
-rw-r--r--drivers/video/au1200fb.c9
-rw-r--r--drivers/video/bf537-lq035.c12
-rw-r--r--drivers/video/bf54x-lq043fb.c4
-rw-r--r--drivers/video/bfin-lq035q1-fb.c8
-rw-r--r--drivers/video/bfin_adv7393fb.c7
-rw-r--r--drivers/video/da8xx-fb.c79
-rw-r--r--drivers/video/exynos/Kconfig37
-rw-r--r--drivers/video/exynos/Makefile8
-rw-r--r--drivers/video/exynos/exynos_dp_core.c1058
-rw-r--r--drivers/video/exynos/exynos_dp_core.h206
-rw-r--r--drivers/video/exynos/exynos_dp_reg.c1173
-rw-r--r--drivers/video/exynos/exynos_dp_reg.h335
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi.c600
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi_common.c896
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi_common.h46
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi_lowlevel.c618
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi_lowlevel.h112
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi_regs.h149
-rw-r--r--drivers/video/exynos/s6e8ax0.c898
-rw-r--r--drivers/video/exynos/s6e8ax0.h21
-rw-r--r--drivers/video/i740_reg.h309
-rw-r--r--drivers/video/i740fb.c1337
-rw-r--r--drivers/video/msm/mddi_client_nt35399.c7
-rw-r--r--drivers/video/msm/mddi_client_toshiba.c7
-rw-r--r--drivers/video/omap/Kconfig16
-rw-r--r--drivers/video/omap/Makefile12
-rw-r--r--drivers/video/omap/blizzard.c1648
-rw-r--r--drivers/video/omap/dispc.c1547
-rw-r--r--drivers/video/omap/dispc.h46
-rw-r--r--drivers/video/omap/hwa742.c21
-rw-r--r--drivers/video/omap/lcd_inn1610.c10
-rw-r--r--drivers/video/omap/lcd_mipid.c14
-rw-r--r--drivers/video/omap/omapfb.h25
-rw-r--r--drivers/video/omap/omapfb_main.c30
-rw-r--r--drivers/video/omap/rfbi.c598
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c13
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c23
-rw-r--r--drivers/video/omap2/displays/panel-lgphilips-lb035q02.c12
-rw-r--r--drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c12
-rw-r--r--drivers/video/omap2/displays/panel-taal.c4
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c177
-rw-r--r--drivers/video/omap2/dss/apply.c275
-rw-r--r--drivers/video/omap2/dss/core.c135
-rw-r--r--drivers/video/omap2/dss/dispc.c121
-rw-r--r--drivers/video/omap2/dss/dispc_coefs.c9
-rw-r--r--drivers/video/omap2/dss/display.c10
-rw-r--r--drivers/video/omap2/dss/dsi.c65
-rw-r--r--drivers/video/omap2/dss/dss.c17
-rw-r--r--drivers/video/omap2/dss/dss.h10
-rw-r--r--drivers/video/omap2/dss/dss_features.c181
-rw-r--r--drivers/video/omap2/dss/dss_features.h54
-rw-r--r--drivers/video/omap2/dss/hdmi.c278
-rw-r--r--drivers/video/omap2/dss/manager.c12
-rw-r--r--drivers/video/omap2/dss/rfbi.c36
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h56
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c94
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h47
-rw-r--r--drivers/video/omap2/dss/venc.c32
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c101
-rw-r--r--drivers/video/omap2/vram.c99
-rw-r--r--drivers/video/pvr2fb.c4
-rw-r--r--drivers/video/pxa168fb.c15
-rw-r--r--drivers/video/pxafb.c10
-rw-r--r--drivers/video/riva/fbdev.c5
-rw-r--r--drivers/video/s3c-fb.c133
-rw-r--r--drivers/video/sh_mipi_dsi.c99
-rw-r--r--drivers/video/sh_mobile_hdmi.c297
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c1280
-rw-r--r--drivers/video/sh_mobile_lcdcfb.h84
-rw-r--r--drivers/video/sh_mobile_meram.c690
-rw-r--r--drivers/video/udlfb.c178
-rw-r--r--drivers/video/uvesafb.c14
-rw-r--r--drivers/video/via/Makefile5
-rw-r--r--drivers/video/via/chip.h3
-rw-r--r--drivers/video/via/dvi.c7
-rw-r--r--drivers/video/via/dvi.h3
-rw-r--r--drivers/video/via/hw.c130
-rw-r--r--drivers/video/via/hw.h9
-rw-r--r--drivers/video/via/lcd.c82
-rw-r--r--drivers/video/via/lcd.h3
-rw-r--r--drivers/video/via/share.h331
-rw-r--r--drivers/video/via/via_aux.c88
-rw-r--r--drivers/video/via/via_aux.h93
-rw-r--r--drivers/video/via/via_aux_ch7301.c50
-rw-r--r--drivers/video/via/via_aux_edid.c100
-rw-r--r--drivers/video/via/via_aux_sii164.c54
-rw-r--r--drivers/video/via/via_aux_vt1621.c44
-rw-r--r--drivers/video/via/via_aux_vt1622.c50
-rw-r--r--drivers/video/via/via_aux_vt1625.c50
-rw-r--r--drivers/video/via/via_aux_vt1631.c46
-rw-r--r--drivers/video/via/via_aux_vt1632.c54
-rw-r--r--drivers/video/via/via_aux_vt1636.c46
-rw-r--r--drivers/video/via/via_i2c.c10
-rw-r--r--drivers/video/via/viafbdev.c87
-rw-r--r--drivers/video/via/viafbdev.h6
-rw-r--r--drivers/video/via/viamode.c713
-rw-r--r--drivers/video/via/viamode.h11
-rw-r--r--include/linux/omapfb.h32
-rw-r--r--include/video/exynos_dp.h131
-rw-r--r--include/video/exynos_mipi_dsim.h359
-rw-r--r--include/video/sh_mipi_dsi.h1
-rw-r--r--include/video/sh_mobile_hdmi.h2
-rw-r--r--include/video/sh_mobile_lcdc.h35
-rw-r--r--include/video/sh_mobile_meram.h45
-rw-r--r--include/video/udlfb.h1
146 files changed, 12319 insertions, 8200 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 83753d04f82b..95eba3135018 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2257,6 +2257,15 @@ F: Documentation/filesystems/quota.txt
2257F: fs/quota/ 2257F: fs/quota/
2258F: include/linux/quota*.h 2258F: include/linux/quota*.h
2259 2259
2260DISPLAYLINK USB 2.0 FRAMEBUFFER DRIVER (UDLFB)
2261M: Bernie Thompson <bernie@plugable.com>
2262L: linux-fbdev@vger.kernel.org
2263S: Maintained
2264W: http://plugable.com/category/projects/udlfb/
2265F: drivers/video/udlfb.c
2266F: include/video/udlfb.h
2267F: Documentation/fb/udlfb.txt
2268
2260DISTRIBUTED LOCK MANAGER (DLM) 2269DISTRIBUTED LOCK MANAGER (DLM)
2261M: Christine Caulfield <ccaulfie@redhat.com> 2270M: Christine Caulfield <ccaulfie@redhat.com>
2262M: David Teigland <teigland@redhat.com> 2271M: David Teigland <teigland@redhat.com>
@@ -2378,15 +2387,6 @@ S: Supported
2378F: drivers/gpu/drm/exynos 2387F: drivers/gpu/drm/exynos
2379F: include/drm/exynos* 2388F: include/drm/exynos*
2380 2389
2381EXYNOS MIPI DISPLAY DRIVERS
2382M: Inki Dae <inki.dae@samsung.com>
2383M: Donghwa Lee <dh09.lee@samsung.com>
2384M: Kyungmin Park <kyungmin.park@samsung.com>
2385L: linux-fbdev@vger.kernel.org
2386S: Maintained
2387F: drivers/video/exynos/exynos_mipi*
2388F: include/video/exynos_mipi*
2389
2390DSCC4 DRIVER 2390DSCC4 DRIVER
2391M: Francois Romieu <romieu@fr.zoreil.com> 2391M: Francois Romieu <romieu@fr.zoreil.com>
2392L: netdev@vger.kernel.org 2392L: netdev@vger.kernel.org
@@ -2667,6 +2667,21 @@ M: Mimi Zohar <zohar@us.ibm.com>
2667S: Supported 2667S: Supported
2668F: security/integrity/evm/ 2668F: security/integrity/evm/
2669 2669
2670EXYNOS DP DRIVER
2671M: Jingoo Han <jg1.han@samsung.com>
2672L: linux-fbdev@vger.kernel.org
2673S: Maintained
2674F: drivers/video/exynos/exynos_dp*
2675
2676EXYNOS MIPI DISPLAY DRIVERS
2677M: Inki Dae <inki.dae@samsung.com>
2678M: Donghwa Lee <dh09.lee@samsung.com>
2679M: Kyungmin Park <kyungmin.park@samsung.com>
2680L: linux-fbdev@vger.kernel.org
2681S: Maintained
2682F: drivers/video/exynos/exynos_mipi*
2683F: include/video/exynos_mipi*
2684
2670F71805F HARDWARE MONITORING DRIVER 2685F71805F HARDWARE MONITORING DRIVER
2671M: Jean Delvare <khali@linux-fr.org> 2686M: Jean Delvare <khali@linux-fr.org>
2672L: lm-sensors@lm-sensors.org 2687L: lm-sensors@lm-sensors.org
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 88909cc0b254..e0e8245f3c9f 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -20,6 +20,7 @@
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/serial_8250.h> 21#include <linux/serial_8250.h>
22#include <linux/export.h> 22#include <linux/export.h>
23#include <linux/omapfb.h>
23 24
24#include <media/soc_camera.h> 25#include <media/soc_camera.h>
25 26
@@ -169,10 +170,6 @@ static struct omap_usb_config ams_delta_usb_config __initdata = {
169 .pins[0] = 2, 170 .pins[0] = 2,
170}; 171};
171 172
172static struct omap_board_config_kernel ams_delta_config[] __initdata = {
173 { OMAP_TAG_LCD, &ams_delta_lcd_config },
174};
175
176static struct resource ams_delta_nand_resources[] = { 173static struct resource ams_delta_nand_resources[] = {
177 [0] = { 174 [0] = {
178 .start = OMAP1_MPUIO_BASE, 175 .start = OMAP1_MPUIO_BASE,
@@ -302,8 +299,6 @@ static void __init ams_delta_init(void)
302 omap_cfg_reg(J19_1610_CAM_D6); 299 omap_cfg_reg(J19_1610_CAM_D6);
303 omap_cfg_reg(J18_1610_CAM_D7); 300 omap_cfg_reg(J18_1610_CAM_D7);
304 301
305 omap_board_config = ams_delta_config;
306 omap_board_config_size = ARRAY_SIZE(ams_delta_config);
307 omap_serial_init(); 302 omap_serial_init();
308 omap_register_i2c_bus(1, 100, NULL, 0); 303 omap_register_i2c_bus(1, 100, NULL, 0);
309 304
@@ -321,6 +316,8 @@ static void __init ams_delta_init(void)
321 ams_delta_init_fiq(); 316 ams_delta_init_fiq();
322 317
323 omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1); 318 omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);
319
320 omapfb_set_lcd_config(&ams_delta_lcd_config);
324} 321}
325 322
326static struct plat_serial8250_port ams_delta_modem_ports[] = { 323static struct plat_serial8250_port ams_delta_modem_ports[] = {
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 0b9464b41212..7afaf3c5bdc6 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -21,6 +21,7 @@
21#include <linux/mtd/physmap.h> 21#include <linux/mtd/physmap.h>
22#include <linux/input.h> 22#include <linux/input.h>
23#include <linux/smc91x.h> 23#include <linux/smc91x.h>
24#include <linux/omapfb.h>
24 25
25#include <mach/hardware.h> 26#include <mach/hardware.h>
26#include <asm/mach-types.h> 27#include <asm/mach-types.h>
@@ -273,27 +274,17 @@ static struct platform_device kp_device = {
273 .resource = kp_resources, 274 .resource = kp_resources,
274}; 275};
275 276
276static struct platform_device lcd_device = {
277 .name = "lcd_p2",
278 .id = -1,
279};
280
281static struct platform_device *devices[] __initdata = { 277static struct platform_device *devices[] __initdata = {
282 &nor_device, 278 &nor_device,
283 &nand_device, 279 &nand_device,
284 &smc91x_device, 280 &smc91x_device,
285 &kp_device, 281 &kp_device,
286 &lcd_device,
287}; 282};
288 283
289static struct omap_lcd_config fsample_lcd_config = { 284static struct omap_lcd_config fsample_lcd_config = {
290 .ctrl_name = "internal", 285 .ctrl_name = "internal",
291}; 286};
292 287
293static struct omap_board_config_kernel fsample_config[] __initdata = {
294 { OMAP_TAG_LCD, &fsample_lcd_config },
295};
296
297static void __init omap_fsample_init(void) 288static void __init omap_fsample_init(void)
298{ 289{
299 /* Early, board-dependent init */ 290 /* Early, board-dependent init */
@@ -352,10 +343,10 @@ static void __init omap_fsample_init(void)
352 343
353 platform_add_devices(devices, ARRAY_SIZE(devices)); 344 platform_add_devices(devices, ARRAY_SIZE(devices));
354 345
355 omap_board_config = fsample_config;
356 omap_board_config_size = ARRAY_SIZE(fsample_config);
357 omap_serial_init(); 346 omap_serial_init();
358 omap_register_i2c_bus(1, 100, NULL, 0); 347 omap_register_i2c_bus(1, 100, NULL, 0);
348
349 omapfb_set_lcd_config(&fsample_lcd_config);
359} 350}
360 351
361/* Only FPGA needs to be mapped here. All others are done with ioremap */ 352/* Only FPGA needs to be mapped here. All others are done with ioremap */
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 00ad6b22d60a..af2be8c12c07 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -30,6 +30,7 @@
30#include <linux/input.h> 30#include <linux/input.h>
31#include <linux/i2c/tps65010.h> 31#include <linux/i2c/tps65010.h>
32#include <linux/smc91x.h> 32#include <linux/smc91x.h>
33#include <linux/omapfb.h>
33 34
34#include <mach/hardware.h> 35#include <mach/hardware.h>
35 36
@@ -325,18 +326,12 @@ static struct platform_device h2_irda_device = {
325 .resource = h2_irda_resources, 326 .resource = h2_irda_resources,
326}; 327};
327 328
328static struct platform_device h2_lcd_device = {
329 .name = "lcd_h2",
330 .id = -1,
331};
332
333static struct platform_device *h2_devices[] __initdata = { 329static struct platform_device *h2_devices[] __initdata = {
334 &h2_nor_device, 330 &h2_nor_device,
335 &h2_nand_device, 331 &h2_nand_device,
336 &h2_smc91x_device, 332 &h2_smc91x_device,
337 &h2_irda_device, 333 &h2_irda_device,
338 &h2_kp_device, 334 &h2_kp_device,
339 &h2_lcd_device,
340}; 335};
341 336
342static void __init h2_init_smc91x(void) 337static void __init h2_init_smc91x(void)
@@ -391,10 +386,6 @@ static struct omap_lcd_config h2_lcd_config __initdata = {
391 .ctrl_name = "internal", 386 .ctrl_name = "internal",
392}; 387};
393 388
394static struct omap_board_config_kernel h2_config[] __initdata = {
395 { OMAP_TAG_LCD, &h2_lcd_config },
396};
397
398static void __init h2_init(void) 389static void __init h2_init(void)
399{ 390{
400 h2_init_smc91x(); 391 h2_init_smc91x();
@@ -438,13 +429,13 @@ static void __init h2_init(void)
438 omap_cfg_reg(N19_1610_KBR5); 429 omap_cfg_reg(N19_1610_KBR5);
439 430
440 platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices)); 431 platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices));
441 omap_board_config = h2_config;
442 omap_board_config_size = ARRAY_SIZE(h2_config);
443 omap_serial_init(); 432 omap_serial_init();
444 omap_register_i2c_bus(1, 100, h2_i2c_board_info, 433 omap_register_i2c_bus(1, 100, h2_i2c_board_info,
445 ARRAY_SIZE(h2_i2c_board_info)); 434 ARRAY_SIZE(h2_i2c_board_info));
446 omap1_usb_init(&h2_usb_config); 435 omap1_usb_init(&h2_usb_config);
447 h2_mmc_init(); 436 h2_mmc_init();
437
438 omapfb_set_lcd_config(&h2_lcd_config);
448} 439}
449 440
450MACHINE_START(OMAP_H2, "TI-H2") 441MACHINE_START(OMAP_H2, "TI-H2")
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 4a7f25149703..7cfd25b90735 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -30,6 +30,7 @@
30#include <linux/spi/spi.h> 30#include <linux/spi/spi.h>
31#include <linux/i2c/tps65010.h> 31#include <linux/i2c/tps65010.h>
32#include <linux/smc91x.h> 32#include <linux/smc91x.h>
33#include <linux/omapfb.h>
33 34
34#include <asm/setup.h> 35#include <asm/setup.h>
35#include <asm/page.h> 36#include <asm/page.h>
@@ -370,10 +371,6 @@ static struct omap_lcd_config h3_lcd_config __initdata = {
370 .ctrl_name = "internal", 371 .ctrl_name = "internal",
371}; 372};
372 373
373static struct omap_board_config_kernel h3_config[] __initdata = {
374 { OMAP_TAG_LCD, &h3_lcd_config },
375};
376
377static struct i2c_board_info __initdata h3_i2c_board_info[] = { 374static struct i2c_board_info __initdata h3_i2c_board_info[] = {
378 { 375 {
379 I2C_BOARD_INFO("tps65013", 0x48), 376 I2C_BOARD_INFO("tps65013", 0x48),
@@ -426,13 +423,13 @@ static void __init h3_init(void)
426 platform_add_devices(devices, ARRAY_SIZE(devices)); 423 platform_add_devices(devices, ARRAY_SIZE(devices));
427 spi_register_board_info(h3_spi_board_info, 424 spi_register_board_info(h3_spi_board_info,
428 ARRAY_SIZE(h3_spi_board_info)); 425 ARRAY_SIZE(h3_spi_board_info));
429 omap_board_config = h3_config;
430 omap_board_config_size = ARRAY_SIZE(h3_config);
431 omap_serial_init(); 426 omap_serial_init();
432 omap_register_i2c_bus(1, 100, h3_i2c_board_info, 427 omap_register_i2c_bus(1, 100, h3_i2c_board_info,
433 ARRAY_SIZE(h3_i2c_board_info)); 428 ARRAY_SIZE(h3_i2c_board_info));
434 omap1_usb_init(&h3_usb_config); 429 omap1_usb_init(&h3_usb_config);
435 h3_mmc_init(); 430 h3_mmc_init();
431
432 omapfb_set_lcd_config(&h3_lcd_config);
436} 433}
437 434
438MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board") 435MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index 731cc3db7ab3..af2afcf24f75 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -36,6 +36,7 @@
36#include <linux/leds.h> 36#include <linux/leds.h>
37#include <linux/spi/spi.h> 37#include <linux/spi/spi.h>
38#include <linux/spi/ads7846.h> 38#include <linux/spi/ads7846.h>
39#include <linux/omapfb.h>
39 40
40#include <asm/mach-types.h> 41#include <asm/mach-types.h>
41#include <asm/mach/arch.h> 42#include <asm/mach/arch.h>
@@ -398,10 +399,6 @@ static struct omap_lcd_config htcherald_lcd_config __initdata = {
398 .ctrl_name = "internal", 399 .ctrl_name = "internal",
399}; 400};
400 401
401static struct omap_board_config_kernel htcherald_config[] __initdata = {
402 { OMAP_TAG_LCD, &htcherald_lcd_config },
403};
404
405static struct platform_device lcd_device = { 402static struct platform_device lcd_device = {
406 .name = "lcd_htcherald", 403 .name = "lcd_htcherald",
407 .id = -1, 404 .id = -1,
@@ -580,8 +577,6 @@ static void __init htcherald_init(void)
580 printk(KERN_INFO "HTC Herald init.\n"); 577 printk(KERN_INFO "HTC Herald init.\n");
581 578
582 /* Do board initialization before we register all the devices */ 579 /* Do board initialization before we register all the devices */
583 omap_board_config = htcherald_config;
584 omap_board_config_size = ARRAY_SIZE(htcherald_config);
585 platform_add_devices(devices, ARRAY_SIZE(devices)); 580 platform_add_devices(devices, ARRAY_SIZE(devices));
586 581
587 htcherald_disable_watchdog(); 582 htcherald_disable_watchdog();
@@ -598,6 +593,8 @@ static void __init htcherald_init(void)
598 htc_mmc_data[0] = &htc_mmc1_data; 593 htc_mmc_data[0] = &htc_mmc1_data;
599 omap1_init_mmc(htc_mmc_data, 1); 594 omap1_init_mmc(htc_mmc_data, 1);
600#endif 595#endif
596
597 omapfb_set_lcd_config(&htcherald_lcd_config);
601} 598}
602 599
603MACHINE_START(HERALD, "HTC Herald") 600MACHINE_START(HERALD, "HTC Herald")
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index be2002f42dea..1d5ab6606b9f 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -25,6 +25,7 @@
25#include <linux/mtd/physmap.h> 25#include <linux/mtd/physmap.h>
26#include <linux/input.h> 26#include <linux/input.h>
27#include <linux/smc91x.h> 27#include <linux/smc91x.h>
28#include <linux/omapfb.h>
28 29
29#include <mach/hardware.h> 30#include <mach/hardware.h>
30#include <asm/mach-types.h> 31#include <asm/mach-types.h>
@@ -370,10 +371,6 @@ static inline void innovator_mmc_init(void)
370} 371}
371#endif 372#endif
372 373
373static struct omap_board_config_kernel innovator_config[] = {
374 { OMAP_TAG_LCD, NULL },
375};
376
377static void __init innovator_init(void) 374static void __init innovator_init(void)
378{ 375{
379 if (cpu_is_omap1510()) 376 if (cpu_is_omap1510())
@@ -416,17 +413,15 @@ static void __init innovator_init(void)
416#ifdef CONFIG_ARCH_OMAP15XX 413#ifdef CONFIG_ARCH_OMAP15XX
417 if (cpu_is_omap1510()) { 414 if (cpu_is_omap1510()) {
418 omap1_usb_init(&innovator1510_usb_config); 415 omap1_usb_init(&innovator1510_usb_config);
419 innovator_config[0].data = &innovator1510_lcd_config; 416 omapfb_set_lcd_config(&innovator1510_lcd_config);
420 } 417 }
421#endif 418#endif
422#ifdef CONFIG_ARCH_OMAP16XX 419#ifdef CONFIG_ARCH_OMAP16XX
423 if (cpu_is_omap1610()) { 420 if (cpu_is_omap1610()) {
424 omap1_usb_init(&h2_usb_config); 421 omap1_usb_init(&h2_usb_config);
425 innovator_config[0].data = &innovator1610_lcd_config; 422 omapfb_set_lcd_config(&innovator1610_lcd_config);
426 } 423 }
427#endif 424#endif
428 omap_board_config = innovator_config;
429 omap_board_config_size = ARRAY_SIZE(innovator_config);
430 omap_serial_init(); 425 omap_serial_init();
431 omap_register_i2c_bus(1, 100, NULL, 0); 426 omap_register_i2c_bus(1, 100, NULL, 0);
432 innovator_mmc_init(); 427 innovator_mmc_init();
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index f9efc036ba96..9b6332a31fb6 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -31,7 +31,6 @@
31#include <plat/board.h> 31#include <plat/board.h>
32#include <plat/keypad.h> 32#include <plat/keypad.h>
33#include "common.h" 33#include "common.h"
34#include <plat/hwa742.h>
35#include <plat/lcd_mipid.h> 34#include <plat/lcd_mipid.h>
36#include <plat/mmc.h> 35#include <plat/mmc.h>
37#include <plat/clock.h> 36#include <plat/clock.h>
@@ -99,15 +98,16 @@ static struct mipid_platform_data nokia770_mipid_platform_data = {
99 .shutdown = mipid_shutdown, 98 .shutdown = mipid_shutdown,
100}; 99};
101 100
101static struct omap_lcd_config nokia770_lcd_config __initdata = {
102 .ctrl_name = "hwa742",
103};
104
102static void __init mipid_dev_init(void) 105static void __init mipid_dev_init(void)
103{ 106{
104 const struct omap_lcd_config *conf; 107 nokia770_mipid_platform_data.nreset_gpio = 13;
108 nokia770_mipid_platform_data.data_lines = 16;
105 109
106 conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); 110 omapfb_set_lcd_config(&nokia770_lcd_config);
107 if (conf != NULL) {
108 nokia770_mipid_platform_data.nreset_gpio = conf->nreset_gpio;
109 nokia770_mipid_platform_data.data_lines = conf->data_lines;
110 }
111} 111}
112 112
113static void __init ads7846_dev_init(void) 113static void __init ads7846_dev_init(void)
@@ -150,14 +150,9 @@ static struct spi_board_info nokia770_spi_board_info[] __initdata = {
150 }, 150 },
151}; 151};
152 152
153static struct hwa742_platform_data nokia770_hwa742_platform_data = {
154 .te_connected = 1,
155};
156
157static void __init hwa742_dev_init(void) 153static void __init hwa742_dev_init(void)
158{ 154{
159 clk_add_alias("hwa_sys_ck", NULL, "bclk", NULL); 155 clk_add_alias("hwa_sys_ck", NULL, "bclk", NULL);
160 omapfb_set_ctrl_platform_data(&nokia770_hwa742_platform_data);
161} 156}
162 157
163/* assume no Mini-AB port */ 158/* assume no Mini-AB port */
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 675de06557aa..ef874655fbd3 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -34,6 +34,7 @@
34#include <linux/i2c.h> 34#include <linux/i2c.h>
35#include <linux/leds.h> 35#include <linux/leds.h>
36#include <linux/smc91x.h> 36#include <linux/smc91x.h>
37#include <linux/omapfb.h>
37 38
38#include <linux/mtd/mtd.h> 39#include <linux/mtd/mtd.h>
39#include <linux/mtd/partitions.h> 40#include <linux/mtd/partitions.h>
@@ -300,12 +301,6 @@ static struct omap_lcd_config osk_lcd_config __initdata = {
300}; 301};
301#endif 302#endif
302 303
303static struct omap_board_config_kernel osk_config[] __initdata = {
304#ifdef CONFIG_OMAP_OSK_MISTRAL
305 { OMAP_TAG_LCD, &osk_lcd_config },
306#endif
307};
308
309#ifdef CONFIG_OMAP_OSK_MISTRAL 304#ifdef CONFIG_OMAP_OSK_MISTRAL
310 305
311#include <linux/input.h> 306#include <linux/input.h>
@@ -549,8 +544,6 @@ static void __init osk_init(void)
549 osk_flash_resource.end = osk_flash_resource.start = omap_cs3_phys(); 544 osk_flash_resource.end = osk_flash_resource.start = omap_cs3_phys();
550 osk_flash_resource.end += SZ_32M - 1; 545 osk_flash_resource.end += SZ_32M - 1;
551 platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices)); 546 platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices));
552 omap_board_config = osk_config;
553 omap_board_config_size = ARRAY_SIZE(osk_config);
554 547
555 l = omap_readl(USB_TRANSCEIVER_CTRL); 548 l = omap_readl(USB_TRANSCEIVER_CTRL);
556 l |= (3 << 1); 549 l |= (3 << 1);
@@ -567,6 +560,11 @@ static void __init osk_init(void)
567 omap_register_i2c_bus(1, 400, osk_i2c_board_info, 560 omap_register_i2c_bus(1, 400, osk_i2c_board_info,
568 ARRAY_SIZE(osk_i2c_board_info)); 561 ARRAY_SIZE(osk_i2c_board_info));
569 osk_mistral_init(); 562 osk_mistral_init();
563
564#ifdef CONFIG_OMAP_OSK_MISTRAL
565 omapfb_set_lcd_config(&osk_lcd_config);
566#endif
567
570} 568}
571 569
572MACHINE_START(OMAP_OSK, "TI-OSK") 570MACHINE_START(OMAP_OSK, "TI-OSK")
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 81fa27f88369..612342cb2a2d 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -27,6 +27,7 @@
27#include <linux/spi/spi.h> 27#include <linux/spi/spi.h>
28#include <linux/interrupt.h> 28#include <linux/interrupt.h>
29#include <linux/apm-emulation.h> 29#include <linux/apm-emulation.h>
30#include <linux/omapfb.h>
30 31
31#include <mach/hardware.h> 32#include <mach/hardware.h>
32#include <asm/mach-types.h> 33#include <asm/mach-types.h>
@@ -209,10 +210,6 @@ static struct omap_lcd_config palmte_lcd_config __initdata = {
209 .ctrl_name = "internal", 210 .ctrl_name = "internal",
210}; 211};
211 212
212static struct omap_board_config_kernel palmte_config[] __initdata = {
213 { OMAP_TAG_LCD, &palmte_lcd_config },
214};
215
216static struct spi_board_info palmte_spi_info[] __initdata = { 213static struct spi_board_info palmte_spi_info[] __initdata = {
217 { 214 {
218 .modalias = "tsc2102", 215 .modalias = "tsc2102",
@@ -250,9 +247,6 @@ static void __init omap_palmte_init(void)
250 omap_cfg_reg(UART3_TX); 247 omap_cfg_reg(UART3_TX);
251 omap_cfg_reg(UART3_RX); 248 omap_cfg_reg(UART3_RX);
252 249
253 omap_board_config = palmte_config;
254 omap_board_config_size = ARRAY_SIZE(palmte_config);
255
256 platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices)); 250 platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices));
257 251
258 spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info)); 252 spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
@@ -260,6 +254,8 @@ static void __init omap_palmte_init(void)
260 omap_serial_init(); 254 omap_serial_init();
261 omap1_usb_init(&palmte_usb_config); 255 omap1_usb_init(&palmte_usb_config);
262 omap_register_i2c_bus(1, 100, NULL, 0); 256 omap_register_i2c_bus(1, 100, NULL, 0);
257
258 omapfb_set_lcd_config(&palmte_lcd_config);
263} 259}
264 260
265MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E") 261MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index 81cb82178388..b63350bc88fd 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -24,6 +24,7 @@
24#include <linux/mtd/partitions.h> 24#include <linux/mtd/partitions.h>
25#include <linux/mtd/physmap.h> 25#include <linux/mtd/physmap.h>
26#include <linux/leds.h> 26#include <linux/leds.h>
27#include <linux/omapfb.h>
27 28
28#include <mach/hardware.h> 29#include <mach/hardware.h>
29#include <asm/mach-types.h> 30#include <asm/mach-types.h>
@@ -273,10 +274,6 @@ static struct omap_lcd_config palmtt_lcd_config __initdata = {
273 .ctrl_name = "internal", 274 .ctrl_name = "internal",
274}; 275};
275 276
276static struct omap_board_config_kernel palmtt_config[] __initdata = {
277 { OMAP_TAG_LCD, &palmtt_lcd_config },
278};
279
280static void __init omap_mpu_wdt_mode(int mode) { 277static void __init omap_mpu_wdt_mode(int mode) {
281 if (mode) 278 if (mode)
282 omap_writew(0x8000, OMAP_WDT_TIMER_MODE); 279 omap_writew(0x8000, OMAP_WDT_TIMER_MODE);
@@ -298,15 +295,14 @@ static void __init omap_palmtt_init(void)
298 295
299 omap_mpu_wdt_mode(0); 296 omap_mpu_wdt_mode(0);
300 297
301 omap_board_config = palmtt_config;
302 omap_board_config_size = ARRAY_SIZE(palmtt_config);
303
304 platform_add_devices(palmtt_devices, ARRAY_SIZE(palmtt_devices)); 298 platform_add_devices(palmtt_devices, ARRAY_SIZE(palmtt_devices));
305 299
306 spi_register_board_info(palmtt_boardinfo,ARRAY_SIZE(palmtt_boardinfo)); 300 spi_register_board_info(palmtt_boardinfo,ARRAY_SIZE(palmtt_boardinfo));
307 omap_serial_init(); 301 omap_serial_init();
308 omap1_usb_init(&palmtt_usb_config); 302 omap1_usb_init(&palmtt_usb_config);
309 omap_register_i2c_bus(1, 100, NULL, 0); 303 omap_register_i2c_bus(1, 100, NULL, 0);
304
305 omapfb_set_lcd_config(&palmtt_lcd_config);
310} 306}
311 307
312MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T") 308MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index e881945ce8ec..9924c70af09f 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -27,6 +27,7 @@
27#include <linux/mtd/mtd.h> 27#include <linux/mtd/mtd.h>
28#include <linux/mtd/partitions.h> 28#include <linux/mtd/partitions.h>
29#include <linux/mtd/physmap.h> 29#include <linux/mtd/physmap.h>
30#include <linux/omapfb.h>
30 31
31#include <mach/hardware.h> 32#include <mach/hardware.h>
32#include <asm/mach-types.h> 33#include <asm/mach-types.h>
@@ -239,10 +240,6 @@ static struct omap_lcd_config palmz71_lcd_config __initdata = {
239 .ctrl_name = "internal", 240 .ctrl_name = "internal",
240}; 241};
241 242
242static struct omap_board_config_kernel palmz71_config[] __initdata = {
243 {OMAP_TAG_LCD, &palmz71_lcd_config},
244};
245
246static irqreturn_t 243static irqreturn_t
247palmz71_powercable(int irq, void *dev_id) 244palmz71_powercable(int irq, void *dev_id)
248{ 245{
@@ -313,9 +310,6 @@ omap_palmz71_init(void)
313 palmz71_gpio_setup(1); 310 palmz71_gpio_setup(1);
314 omap_mpu_wdt_mode(0); 311 omap_mpu_wdt_mode(0);
315 312
316 omap_board_config = palmz71_config;
317 omap_board_config_size = ARRAY_SIZE(palmz71_config);
318
319 platform_add_devices(devices, ARRAY_SIZE(devices)); 313 platform_add_devices(devices, ARRAY_SIZE(devices));
320 314
321 spi_register_board_info(palmz71_boardinfo, 315 spi_register_board_info(palmz71_boardinfo,
@@ -324,6 +318,8 @@ omap_palmz71_init(void)
324 omap_serial_init(); 318 omap_serial_init();
325 omap_register_i2c_bus(1, 100, NULL, 0); 319 omap_register_i2c_bus(1, 100, NULL, 0);
326 palmz71_gpio_setup(0); 320 palmz71_gpio_setup(0);
321
322 omapfb_set_lcd_config(&palmz71_lcd_config);
327} 323}
328 324
329MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71") 325MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index c000bed76276..8e0153447c6d 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -21,6 +21,7 @@
21#include <linux/mtd/physmap.h> 21#include <linux/mtd/physmap.h>
22#include <linux/input.h> 22#include <linux/input.h>
23#include <linux/smc91x.h> 23#include <linux/smc91x.h>
24#include <linux/omapfb.h>
24 25
25#include <mach/hardware.h> 26#include <mach/hardware.h>
26#include <asm/mach-types.h> 27#include <asm/mach-types.h>
@@ -232,27 +233,17 @@ static struct platform_device kp_device = {
232 .resource = kp_resources, 233 .resource = kp_resources,
233}; 234};
234 235
235static struct platform_device lcd_device = {
236 .name = "lcd_p2",
237 .id = -1,
238};
239
240static struct platform_device *devices[] __initdata = { 236static struct platform_device *devices[] __initdata = {
241 &nor_device, 237 &nor_device,
242 &nand_device, 238 &nand_device,
243 &smc91x_device, 239 &smc91x_device,
244 &kp_device, 240 &kp_device,
245 &lcd_device,
246}; 241};
247 242
248static struct omap_lcd_config perseus2_lcd_config __initdata = { 243static struct omap_lcd_config perseus2_lcd_config __initdata = {
249 .ctrl_name = "internal", 244 .ctrl_name = "internal",
250}; 245};
251 246
252static struct omap_board_config_kernel perseus2_config[] __initdata = {
253 { OMAP_TAG_LCD, &perseus2_lcd_config },
254};
255
256static void __init perseus2_init_smc91x(void) 247static void __init perseus2_init_smc91x(void)
257{ 248{
258 fpga_write(1, H2P2_DBG_FPGA_LAN_RESET); 249 fpga_write(1, H2P2_DBG_FPGA_LAN_RESET);
@@ -320,10 +311,10 @@ static void __init omap_perseus2_init(void)
320 311
321 platform_add_devices(devices, ARRAY_SIZE(devices)); 312 platform_add_devices(devices, ARRAY_SIZE(devices));
322 313
323 omap_board_config = perseus2_config;
324 omap_board_config_size = ARRAY_SIZE(perseus2_config);
325 omap_serial_init(); 314 omap_serial_init();
326 omap_register_i2c_bus(1, 100, NULL, 0); 315 omap_register_i2c_bus(1, 100, NULL, 0);
316
317 omapfb_set_lcd_config(&perseus2_lcd_config);
327} 318}
328 319
329/* Only FPGA needs to be mapped here. All others are done with ioremap */ 320/* Only FPGA needs to be mapped here. All others are done with ioremap */
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 7bcd82ab0fd0..0c76e12337d9 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -27,6 +27,7 @@
27#include <linux/i2c.h> 27#include <linux/i2c.h>
28#include <linux/errno.h> 28#include <linux/errno.h>
29#include <linux/export.h> 29#include <linux/export.h>
30#include <linux/omapfb.h>
30 31
31#include <mach/hardware.h> 32#include <mach/hardware.h>
32#include <asm/mach-types.h> 33#include <asm/mach-types.h>
@@ -355,11 +356,6 @@ static struct omap_usb_config sx1_usb_config __initdata = {
355 356
356/*----------- LCD -------------------------*/ 357/*----------- LCD -------------------------*/
357 358
358static struct platform_device sx1_lcd_device = {
359 .name = "lcd_sx1",
360 .id = -1,
361};
362
363static struct omap_lcd_config sx1_lcd_config __initdata = { 359static struct omap_lcd_config sx1_lcd_config __initdata = {
364 .ctrl_name = "internal", 360 .ctrl_name = "internal",
365}; 361};
@@ -368,14 +364,8 @@ static struct omap_lcd_config sx1_lcd_config __initdata = {
368static struct platform_device *sx1_devices[] __initdata = { 364static struct platform_device *sx1_devices[] __initdata = {
369 &sx1_flash_device, 365 &sx1_flash_device,
370 &sx1_kp_device, 366 &sx1_kp_device,
371 &sx1_lcd_device,
372 &sx1_irda_device, 367 &sx1_irda_device,
373}; 368};
374/*-----------------------------------------*/
375
376static struct omap_board_config_kernel sx1_config[] __initdata = {
377 { OMAP_TAG_LCD, &sx1_lcd_config },
378};
379 369
380/*-----------------------------------------*/ 370/*-----------------------------------------*/
381 371
@@ -391,8 +381,6 @@ static void __init omap_sx1_init(void)
391 381
392 platform_add_devices(sx1_devices, ARRAY_SIZE(sx1_devices)); 382 platform_add_devices(sx1_devices, ARRAY_SIZE(sx1_devices));
393 383
394 omap_board_config = sx1_config;
395 omap_board_config_size = ARRAY_SIZE(sx1_config);
396 omap_serial_init(); 384 omap_serial_init();
397 omap_register_i2c_bus(1, 100, NULL, 0); 385 omap_register_i2c_bus(1, 100, NULL, 0);
398 omap1_usb_init(&sx1_usb_config); 386 omap1_usb_init(&sx1_usb_config);
@@ -406,6 +394,8 @@ static void __init omap_sx1_init(void)
406 gpio_direction_output(1, 1); /*A_IRDA_OFF = 1 */ 394 gpio_direction_output(1, 1); /*A_IRDA_OFF = 1 */
407 gpio_direction_output(11, 0); /*A_SWITCH = 0 */ 395 gpio_direction_output(11, 0); /*A_SWITCH = 0 */
408 gpio_direction_output(15, 0); /*A_USB_ON = 0 */ 396 gpio_direction_output(15, 0); /*A_USB_ON = 0 */
397
398 omapfb_set_lcd_config(&sx1_lcd_config);
409} 399}
410 400
411MACHINE_START(SX1, "OMAP310 based Siemens SX1") 401MACHINE_START(SX1, "OMAP310 based Siemens SX1")
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index fb11b44fbdec..e501b4972a64 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -21,7 +21,6 @@
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/clk.h> 23#include <linux/clk.h>
24#include <linux/omapfb.h>
25 24
26#include <asm/tlb.h> 25#include <asm/tlb.h>
27 26
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
index 8aea3a2dd889..12c431f3443f 100644
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
@@ -230,16 +230,6 @@ static void lcd_backlight_reset(void)
230 gpio_set_value(GPIO_PORT235, 1); 230 gpio_set_value(GPIO_PORT235, 1);
231} 231}
232 232
233static void lcd_on(void *board_data, struct fb_info *info)
234{
235 lcd_backlight_on();
236}
237
238static void lcd_off(void *board_data)
239{
240 lcd_backlight_reset();
241}
242
243/* LCDC0 */ 233/* LCDC0 */
244static const struct fb_videomode lcdc0_modes[] = { 234static const struct fb_videomode lcdc0_modes[] = {
245 { 235 {
@@ -263,14 +253,14 @@ static struct sh_mobile_lcdc_info lcdc0_info = {
263 .interface_type = RGB24, 253 .interface_type = RGB24,
264 .clock_divider = 1, 254 .clock_divider = 1,
265 .flags = LCDC_FLAGS_DWPOL, 255 .flags = LCDC_FLAGS_DWPOL,
266 .lcd_size_cfg.width = 44,
267 .lcd_size_cfg.height = 79,
268 .fourcc = V4L2_PIX_FMT_RGB565, 256 .fourcc = V4L2_PIX_FMT_RGB565,
269 .lcd_cfg = lcdc0_modes, 257 .lcd_modes = lcdc0_modes,
270 .num_cfg = ARRAY_SIZE(lcdc0_modes), 258 .num_modes = ARRAY_SIZE(lcdc0_modes),
271 .board_cfg = { 259 .panel_cfg = {
272 .display_on = lcd_on, 260 .width = 44,
273 .display_off = lcd_off, 261 .height = 79,
262 .display_on = lcd_backlight_on,
263 .display_off = lcd_backlight_reset,
274 }, 264 },
275 } 265 }
276}; 266};
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 8f6da7f134b3..f90ba5b850a3 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -258,10 +258,16 @@ static struct sh_mobile_meram_info meram_info = {
258 258
259static struct resource meram_resources[] = { 259static struct resource meram_resources[] = {
260 [0] = { 260 [0] = {
261 .name = "MERAM", 261 .name = "regs",
262 .start = 0xe8000000, 262 .start = 0xe8000000,
263 .end = 0xe81fffff, 263 .end = 0xe807ffff,
264 .flags = IORESOURCE_MEM, 264 .flags = IORESOURCE_MEM,
265 },
266 [1] = {
267 .name = "meram",
268 .start = 0xe8080000,
269 .end = 0xe81fffff,
270 .flags = IORESOURCE_MEM,
265 }, 271 },
266}; 272};
267 273
@@ -437,82 +443,6 @@ static struct platform_device usb1_host_device = {
437 .resource = usb1_host_resources, 443 .resource = usb1_host_resources,
438}; 444};
439 445
440static const struct fb_videomode ap4evb_lcdc_modes[] = {
441 {
442#ifdef CONFIG_AP4EVB_QHD
443 .name = "R63302(QHD)",
444 .xres = 544,
445 .yres = 961,
446 .left_margin = 72,
447 .right_margin = 600,
448 .hsync_len = 16,
449 .upper_margin = 8,
450 .lower_margin = 8,
451 .vsync_len = 2,
452 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
453#else
454 .name = "WVGA Panel",
455 .xres = 800,
456 .yres = 480,
457 .left_margin = 220,
458 .right_margin = 110,
459 .hsync_len = 70,
460 .upper_margin = 20,
461 .lower_margin = 5,
462 .vsync_len = 5,
463 .sync = 0,
464#endif
465 },
466};
467static struct sh_mobile_meram_cfg lcd_meram_cfg = {
468 .icb[0] = {
469 .marker_icb = 28,
470 .cache_icb = 24,
471 .meram_offset = 0x0,
472 .meram_size = 0x40,
473 },
474 .icb[1] = {
475 .marker_icb = 29,
476 .cache_icb = 25,
477 .meram_offset = 0x40,
478 .meram_size = 0x40,
479 },
480};
481
482static struct sh_mobile_lcdc_info lcdc_info = {
483 .meram_dev = &meram_info,
484 .ch[0] = {
485 .chan = LCDC_CHAN_MAINLCD,
486 .fourcc = V4L2_PIX_FMT_RGB565,
487 .lcd_cfg = ap4evb_lcdc_modes,
488 .num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes),
489 .meram_cfg = &lcd_meram_cfg,
490 }
491};
492
493static struct resource lcdc_resources[] = {
494 [0] = {
495 .name = "LCDC",
496 .start = 0xfe940000, /* P4-only space */
497 .end = 0xfe943fff,
498 .flags = IORESOURCE_MEM,
499 },
500 [1] = {
501 .start = intcs_evt2irq(0x580),
502 .flags = IORESOURCE_IRQ,
503 },
504};
505
506static struct platform_device lcdc_device = {
507 .name = "sh_mobile_lcdc_fb",
508 .num_resources = ARRAY_SIZE(lcdc_resources),
509 .resource = lcdc_resources,
510 .dev = {
511 .platform_data = &lcdc_info,
512 .coherent_dma_mask = ~0,
513 },
514};
515
516/* 446/*
517 * QHD display 447 * QHD display
518 */ 448 */
@@ -556,20 +486,25 @@ static struct platform_device keysc_device = {
556}; 486};
557 487
558/* MIPI-DSI */ 488/* MIPI-DSI */
559#define PHYCTRL 0x0070
560static int sh_mipi_set_dot_clock(struct platform_device *pdev, 489static int sh_mipi_set_dot_clock(struct platform_device *pdev,
561 void __iomem *base, 490 void __iomem *base,
562 int enable) 491 int enable)
563{ 492{
564 struct clk *pck = clk_get(&pdev->dev, "dsip_clk"); 493 struct clk *pck = clk_get(&pdev->dev, "dsip_clk");
565 void __iomem *phy = base + PHYCTRL;
566 494
567 if (IS_ERR(pck)) 495 if (IS_ERR(pck))
568 return PTR_ERR(pck); 496 return PTR_ERR(pck);
569 497
570 if (enable) { 498 if (enable) {
499 /*
500 * DSIPCLK = 24MHz
501 * D-PHY = DSIPCLK * ((0x6*2)+1) = 312MHz (see .phyctrl)
502 * HsByteCLK = D-PHY/8 = 39MHz
503 *
504 * X * Y * FPS =
505 * (544+72+600+16) * (961+8+8+2) * 30 = 36.1MHz
506 */
571 clk_set_rate(pck, clk_round_rate(pck, 24000000)); 507 clk_set_rate(pck, clk_round_rate(pck, 24000000));
572 iowrite32(ioread32(phy) | (0xb << 8), phy);
573 clk_enable(pck); 508 clk_enable(pck);
574 } else { 509 } else {
575 clk_disable(pck); 510 clk_disable(pck);
@@ -593,11 +528,14 @@ static struct resource mipidsi0_resources[] = {
593 }, 528 },
594}; 529};
595 530
531static struct sh_mobile_lcdc_info lcdc_info;
532
596static struct sh_mipi_dsi_info mipidsi0_info = { 533static struct sh_mipi_dsi_info mipidsi0_info = {
597 .data_format = MIPI_RGB888, 534 .data_format = MIPI_RGB888,
598 .lcd_chan = &lcdc_info.ch[0], 535 .lcd_chan = &lcdc_info.ch[0],
599 .lane = 2, 536 .lane = 2,
600 .vsynw_offset = 17, 537 .vsynw_offset = 17,
538 .phyctrl = 0x6 << 8,
601 .flags = SH_MIPI_DSI_SYNC_PULSES_MODE | 539 .flags = SH_MIPI_DSI_SYNC_PULSES_MODE |
602 SH_MIPI_DSI_HSbyteCLK, 540 SH_MIPI_DSI_HSbyteCLK,
603 .set_dot_clock = sh_mipi_set_dot_clock, 541 .set_dot_clock = sh_mipi_set_dot_clock,
@@ -619,6 +557,81 @@ static struct platform_device *qhd_devices[] __initdata = {
619}; 557};
620#endif /* CONFIG_AP4EVB_QHD */ 558#endif /* CONFIG_AP4EVB_QHD */
621 559
560/* LCDC0 */
561static const struct fb_videomode ap4evb_lcdc_modes[] = {
562 {
563#ifdef CONFIG_AP4EVB_QHD
564 .name = "R63302(QHD)",
565 .xres = 544,
566 .yres = 961,
567 .left_margin = 72,
568 .right_margin = 600,
569 .hsync_len = 16,
570 .upper_margin = 8,
571 .lower_margin = 8,
572 .vsync_len = 2,
573 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
574#else
575 .name = "WVGA Panel",
576 .xres = 800,
577 .yres = 480,
578 .left_margin = 220,
579 .right_margin = 110,
580 .hsync_len = 70,
581 .upper_margin = 20,
582 .lower_margin = 5,
583 .vsync_len = 5,
584 .sync = 0,
585#endif
586 },
587};
588
589static const struct sh_mobile_meram_cfg lcd_meram_cfg = {
590 .icb[0] = {
591 .meram_size = 0x40,
592 },
593 .icb[1] = {
594 .meram_size = 0x40,
595 },
596};
597
598static struct sh_mobile_lcdc_info lcdc_info = {
599 .meram_dev = &meram_info,
600 .ch[0] = {
601 .chan = LCDC_CHAN_MAINLCD,
602 .fourcc = V4L2_PIX_FMT_RGB565,
603 .lcd_modes = ap4evb_lcdc_modes,
604 .num_modes = ARRAY_SIZE(ap4evb_lcdc_modes),
605 .meram_cfg = &lcd_meram_cfg,
606#ifdef CONFIG_AP4EVB_QHD
607 .tx_dev = &mipidsi0_device,
608#endif
609 }
610};
611
612static struct resource lcdc_resources[] = {
613 [0] = {
614 .name = "LCDC",
615 .start = 0xfe940000, /* P4-only space */
616 .end = 0xfe943fff,
617 .flags = IORESOURCE_MEM,
618 },
619 [1] = {
620 .start = intcs_evt2irq(0x580),
621 .flags = IORESOURCE_IRQ,
622 },
623};
624
625static struct platform_device lcdc_device = {
626 .name = "sh_mobile_lcdc_fb",
627 .num_resources = ARRAY_SIZE(lcdc_resources),
628 .resource = lcdc_resources,
629 .dev = {
630 .platform_data = &lcdc_info,
631 .coherent_dma_mask = ~0,
632 },
633};
634
622/* FSI */ 635/* FSI */
623#define IRQ_FSI evt2irq(0x1840) 636#define IRQ_FSI evt2irq(0x1840)
624static int __fsi_set_rate(struct clk *clk, long rate, int enable) 637static int __fsi_set_rate(struct clk *clk, long rate, int enable)
@@ -790,65 +803,11 @@ static struct platform_device fsi_ak4643_device = {
790 }, 803 },
791}; 804};
792 805
793static struct sh_mobile_meram_cfg hdmi_meram_cfg = { 806/* LCDC1 */
794 .icb[0] = {
795 .marker_icb = 30,
796 .cache_icb = 26,
797 .meram_offset = 0x80,
798 .meram_size = 0x100,
799 },
800 .icb[1] = {
801 .marker_icb = 31,
802 .cache_icb = 27,
803 .meram_offset = 0x180,
804 .meram_size = 0x100,
805 },
806};
807
808static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
809 .clock_source = LCDC_CLK_EXTERNAL,
810 .meram_dev = &meram_info,
811 .ch[0] = {
812 .chan = LCDC_CHAN_MAINLCD,
813 .fourcc = V4L2_PIX_FMT_RGB565,
814 .interface_type = RGB24,
815 .clock_divider = 1,
816 .flags = LCDC_FLAGS_DWPOL,
817 .meram_cfg = &hdmi_meram_cfg,
818 }
819};
820
821static struct resource lcdc1_resources[] = {
822 [0] = {
823 .name = "LCDC1",
824 .start = 0xfe944000,
825 .end = 0xfe947fff,
826 .flags = IORESOURCE_MEM,
827 },
828 [1] = {
829 .start = intcs_evt2irq(0x1780),
830 .flags = IORESOURCE_IRQ,
831 },
832};
833
834static struct platform_device lcdc1_device = {
835 .name = "sh_mobile_lcdc_fb",
836 .num_resources = ARRAY_SIZE(lcdc1_resources),
837 .resource = lcdc1_resources,
838 .id = 1,
839 .dev = {
840 .platform_data = &sh_mobile_lcdc1_info,
841 .coherent_dma_mask = ~0,
842 },
843};
844
845static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq, 807static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
846 unsigned long *parent_freq); 808 unsigned long *parent_freq);
847 809
848
849static struct sh_mobile_hdmi_info hdmi_info = { 810static struct sh_mobile_hdmi_info hdmi_info = {
850 .lcd_chan = &sh_mobile_lcdc1_info.ch[0],
851 .lcd_dev = &lcdc1_device.dev,
852 .flags = HDMI_SND_SRC_SPDIF, 811 .flags = HDMI_SND_SRC_SPDIF,
853 .clk_optimize_parent = ap4evb_clk_optimize, 812 .clk_optimize_parent = ap4evb_clk_optimize,
854}; 813};
@@ -877,10 +836,6 @@ static struct platform_device hdmi_device = {
877 }, 836 },
878}; 837};
879 838
880static struct platform_device fsi_hdmi_device = {
881 .name = "sh_fsi2_b_hdmi",
882};
883
884static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq, 839static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
885 unsigned long *parent_freq) 840 unsigned long *parent_freq)
886{ 841{
@@ -900,6 +855,57 @@ static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
900 return error; 855 return error;
901} 856}
902 857
858static const struct sh_mobile_meram_cfg hdmi_meram_cfg = {
859 .icb[0] = {
860 .meram_size = 0x100,
861 },
862 .icb[1] = {
863 .meram_size = 0x100,
864 },
865};
866
867static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
868 .clock_source = LCDC_CLK_EXTERNAL,
869 .meram_dev = &meram_info,
870 .ch[0] = {
871 .chan = LCDC_CHAN_MAINLCD,
872 .fourcc = V4L2_PIX_FMT_RGB565,
873 .interface_type = RGB24,
874 .clock_divider = 1,
875 .flags = LCDC_FLAGS_DWPOL,
876 .meram_cfg = &hdmi_meram_cfg,
877 .tx_dev = &hdmi_device,
878 }
879};
880
881static struct resource lcdc1_resources[] = {
882 [0] = {
883 .name = "LCDC1",
884 .start = 0xfe944000,
885 .end = 0xfe947fff,
886 .flags = IORESOURCE_MEM,
887 },
888 [1] = {
889 .start = intcs_evt2irq(0x1780),
890 .flags = IORESOURCE_IRQ,
891 },
892};
893
894static struct platform_device lcdc1_device = {
895 .name = "sh_mobile_lcdc_fb",
896 .num_resources = ARRAY_SIZE(lcdc1_resources),
897 .resource = lcdc1_resources,
898 .id = 1,
899 .dev = {
900 .platform_data = &sh_mobile_lcdc1_info,
901 .coherent_dma_mask = ~0,
902 },
903};
904
905static struct platform_device fsi_hdmi_device = {
906 .name = "sh_fsi2_b_hdmi",
907};
908
903static struct gpio_led ap4evb_leds[] = { 909static struct gpio_led ap4evb_leds[] = {
904 { 910 {
905 .name = "led4", 911 .name = "led4",
@@ -1034,9 +1040,9 @@ static struct platform_device *ap4evb_devices[] __initdata = {
1034 &fsi_ak4643_device, 1040 &fsi_ak4643_device,
1035 &fsi_hdmi_device, 1041 &fsi_hdmi_device,
1036 &sh_mmcif_device, 1042 &sh_mmcif_device,
1037 &lcdc1_device,
1038 &lcdc_device,
1039 &hdmi_device, 1043 &hdmi_device,
1044 &lcdc_device,
1045 &lcdc1_device,
1040 &ceu_device, 1046 &ceu_device,
1041 &ap4evb_camera, 1047 &ap4evb_camera,
1042 &meram_device, 1048 &meram_device,
@@ -1347,8 +1353,8 @@ static void __init ap4evb_init(void)
1347 lcdc_info.ch[0].interface_type = RGB24; 1353 lcdc_info.ch[0].interface_type = RGB24;
1348 lcdc_info.ch[0].clock_divider = 1; 1354 lcdc_info.ch[0].clock_divider = 1;
1349 lcdc_info.ch[0].flags = LCDC_FLAGS_DWPOL; 1355 lcdc_info.ch[0].flags = LCDC_FLAGS_DWPOL;
1350 lcdc_info.ch[0].lcd_size_cfg.width = 44; 1356 lcdc_info.ch[0].panel_cfg.width = 44;
1351 lcdc_info.ch[0].lcd_size_cfg.height = 79; 1357 lcdc_info.ch[0].panel_cfg.height = 79;
1352 1358
1353 platform_add_devices(qhd_devices, ARRAY_SIZE(qhd_devices)); 1359 platform_add_devices(qhd_devices, ARRAY_SIZE(qhd_devices));
1354 1360
@@ -1389,8 +1395,8 @@ static void __init ap4evb_init(void)
1389 lcdc_info.ch[0].interface_type = RGB18; 1395 lcdc_info.ch[0].interface_type = RGB18;
1390 lcdc_info.ch[0].clock_divider = 3; 1396 lcdc_info.ch[0].clock_divider = 3;
1391 lcdc_info.ch[0].flags = 0; 1397 lcdc_info.ch[0].flags = 0;
1392 lcdc_info.ch[0].lcd_size_cfg.width = 152; 1398 lcdc_info.ch[0].panel_cfg.width = 152;
1393 lcdc_info.ch[0].lcd_size_cfg.height = 91; 1399 lcdc_info.ch[0].panel_cfg.height = 91;
1394 1400
1395 /* enable TouchScreen */ 1401 /* enable TouchScreen */
1396 irq_set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW); 1402 irq_set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
diff --git a/arch/arm/mach-shmobile/board-bonito.c b/arch/arm/mach-shmobile/board-bonito.c
index 4bd1162ce0df..c79baa9ef61b 100644
--- a/arch/arm/mach-shmobile/board-bonito.c
+++ b/arch/arm/mach-shmobile/board-bonito.c
@@ -246,9 +246,9 @@ static struct sh_mobile_lcdc_info lcdc0_info = {
246 .interface_type = RGB24, 246 .interface_type = RGB24,
247 .clock_divider = 5, 247 .clock_divider = 5,
248 .flags = 0, 248 .flags = 0,
249 .lcd_cfg = &lcdc0_mode, 249 .lcd_modes = &lcdc0_mode,
250 .num_cfg = 1, 250 .num_modes = 1,
251 .lcd_size_cfg = { 251 .panel_cfg = {
252 .width = 152, 252 .width = 152,
253 .height = 91, 253 .height = 91,
254 }, 254 },
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index d99e780dffca..865d56d96299 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -318,8 +318,14 @@ static struct sh_mobile_meram_info mackerel_meram_info = {
318 318
319static struct resource meram_resources[] = { 319static struct resource meram_resources[] = {
320 [0] = { 320 [0] = {
321 .name = "MERAM", 321 .name = "regs",
322 .start = 0xe8000000, 322 .start = 0xe8000000,
323 .end = 0xe807ffff,
324 .flags = IORESOURCE_MEM,
325 },
326 [1] = {
327 .name = "meram",
328 .start = 0xe8080000,
323 .end = 0xe81fffff, 329 .end = 0xe81fffff,
324 .flags = IORESOURCE_MEM, 330 .flags = IORESOURCE_MEM,
325 }, 331 },
@@ -351,29 +357,23 @@ static struct fb_videomode mackerel_lcdc_modes[] = {
351 }, 357 },
352}; 358};
353 359
354static int mackerel_set_brightness(void *board_data, int brightness) 360static int mackerel_set_brightness(int brightness)
355{ 361{
356 gpio_set_value(GPIO_PORT31, brightness); 362 gpio_set_value(GPIO_PORT31, brightness);
357 363
358 return 0; 364 return 0;
359} 365}
360 366
361static int mackerel_get_brightness(void *board_data) 367static int mackerel_get_brightness(void)
362{ 368{
363 return gpio_get_value(GPIO_PORT31); 369 return gpio_get_value(GPIO_PORT31);
364} 370}
365 371
366static struct sh_mobile_meram_cfg lcd_meram_cfg = { 372static const struct sh_mobile_meram_cfg lcd_meram_cfg = {
367 .icb[0] = { 373 .icb[0] = {
368 .marker_icb = 28,
369 .cache_icb = 24,
370 .meram_offset = 0x0,
371 .meram_size = 0x40, 374 .meram_size = 0x40,
372 }, 375 },
373 .icb[1] = { 376 .icb[1] = {
374 .marker_icb = 29,
375 .cache_icb = 25,
376 .meram_offset = 0x40,
377 .meram_size = 0x40, 377 .meram_size = 0x40,
378 }, 378 },
379}; 379};
@@ -384,20 +384,20 @@ static struct sh_mobile_lcdc_info lcdc_info = {
384 .ch[0] = { 384 .ch[0] = {
385 .chan = LCDC_CHAN_MAINLCD, 385 .chan = LCDC_CHAN_MAINLCD,
386 .fourcc = V4L2_PIX_FMT_RGB565, 386 .fourcc = V4L2_PIX_FMT_RGB565,
387 .lcd_cfg = mackerel_lcdc_modes, 387 .lcd_modes = mackerel_lcdc_modes,
388 .num_cfg = ARRAY_SIZE(mackerel_lcdc_modes), 388 .num_modes = ARRAY_SIZE(mackerel_lcdc_modes),
389 .interface_type = RGB24, 389 .interface_type = RGB24,
390 .clock_divider = 3, 390 .clock_divider = 3,
391 .flags = 0, 391 .flags = 0,
392 .lcd_size_cfg.width = 152, 392 .panel_cfg = {
393 .lcd_size_cfg.height = 91, 393 .width = 152,
394 .board_cfg = { 394 .height = 91,
395 .set_brightness = mackerel_set_brightness,
396 .get_brightness = mackerel_get_brightness,
397 }, 395 },
398 .bl_info = { 396 .bl_info = {
399 .name = "sh_mobile_lcdc_bl", 397 .name = "sh_mobile_lcdc_bl",
400 .max_brightness = 1, 398 .max_brightness = 1,
399 .set_brightness = mackerel_set_brightness,
400 .get_brightness = mackerel_get_brightness,
401 }, 401 },
402 .meram_cfg = &lcd_meram_cfg, 402 .meram_cfg = &lcd_meram_cfg,
403 } 403 }
@@ -426,21 +426,44 @@ static struct platform_device lcdc_device = {
426 }, 426 },
427}; 427};
428 428
429static struct sh_mobile_meram_cfg hdmi_meram_cfg = { 429/* HDMI */
430static struct sh_mobile_hdmi_info hdmi_info = {
431 .flags = HDMI_SND_SRC_SPDIF,
432};
433
434static struct resource hdmi_resources[] = {
435 [0] = {
436 .name = "HDMI",
437 .start = 0xe6be0000,
438 .end = 0xe6be00ff,
439 .flags = IORESOURCE_MEM,
440 },
441 [1] = {
442 /* There's also an HDMI interrupt on INTCS @ 0x18e0 */
443 .start = evt2irq(0x17e0),
444 .flags = IORESOURCE_IRQ,
445 },
446};
447
448static struct platform_device hdmi_device = {
449 .name = "sh-mobile-hdmi",
450 .num_resources = ARRAY_SIZE(hdmi_resources),
451 .resource = hdmi_resources,
452 .id = -1,
453 .dev = {
454 .platform_data = &hdmi_info,
455 },
456};
457
458static const struct sh_mobile_meram_cfg hdmi_meram_cfg = {
430 .icb[0] = { 459 .icb[0] = {
431 .marker_icb = 30,
432 .cache_icb = 26,
433 .meram_offset = 0x80,
434 .meram_size = 0x100, 460 .meram_size = 0x100,
435 }, 461 },
436 .icb[1] = { 462 .icb[1] = {
437 .marker_icb = 31,
438 .cache_icb = 27,
439 .meram_offset = 0x180,
440 .meram_size = 0x100, 463 .meram_size = 0x100,
441 }, 464 },
442}; 465};
443/* HDMI */ 466
444static struct sh_mobile_lcdc_info hdmi_lcdc_info = { 467static struct sh_mobile_lcdc_info hdmi_lcdc_info = {
445 .meram_dev = &mackerel_meram_info, 468 .meram_dev = &mackerel_meram_info,
446 .clock_source = LCDC_CLK_EXTERNAL, 469 .clock_source = LCDC_CLK_EXTERNAL,
@@ -451,6 +474,7 @@ static struct sh_mobile_lcdc_info hdmi_lcdc_info = {
451 .clock_divider = 1, 474 .clock_divider = 1,
452 .flags = LCDC_FLAGS_DWPOL, 475 .flags = LCDC_FLAGS_DWPOL,
453 .meram_cfg = &hdmi_meram_cfg, 476 .meram_cfg = &hdmi_meram_cfg,
477 .tx_dev = &hdmi_device,
454 } 478 }
455}; 479};
456 480
@@ -478,36 +502,6 @@ static struct platform_device hdmi_lcdc_device = {
478 }, 502 },
479}; 503};
480 504
481static struct sh_mobile_hdmi_info hdmi_info = {
482 .lcd_chan = &hdmi_lcdc_info.ch[0],
483 .lcd_dev = &hdmi_lcdc_device.dev,
484 .flags = HDMI_SND_SRC_SPDIF,
485};
486
487static struct resource hdmi_resources[] = {
488 [0] = {
489 .name = "HDMI",
490 .start = 0xe6be0000,
491 .end = 0xe6be00ff,
492 .flags = IORESOURCE_MEM,
493 },
494 [1] = {
495 /* There's also an HDMI interrupt on INTCS @ 0x18e0 */
496 .start = evt2irq(0x17e0),
497 .flags = IORESOURCE_IRQ,
498 },
499};
500
501static struct platform_device hdmi_device = {
502 .name = "sh-mobile-hdmi",
503 .num_resources = ARRAY_SIZE(hdmi_resources),
504 .resource = hdmi_resources,
505 .id = -1,
506 .dev = {
507 .platform_data = &hdmi_info,
508 },
509};
510
511static struct platform_device fsi_hdmi_device = { 505static struct platform_device fsi_hdmi_device = {
512 .name = "sh_fsi2_b_hdmi", 506 .name = "sh_fsi2_b_hdmi",
513}; 507};
@@ -1274,8 +1268,8 @@ static struct platform_device *mackerel_devices[] __initdata = {
1274 &sh_mmcif_device, 1268 &sh_mmcif_device,
1275 &ceu_device, 1269 &ceu_device,
1276 &mackerel_camera, 1270 &mackerel_camera,
1277 &hdmi_lcdc_device,
1278 &hdmi_device, 1271 &hdmi_device,
1272 &hdmi_lcdc_device,
1279 &meram_device, 1273 &meram_device,
1280}; 1274};
1281 1275
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index 4de7d1e79e73..f1e46ea6b81d 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -15,7 +15,6 @@
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/dma-mapping.h> 17#include <linux/dma-mapping.h>
18#include <linux/omapfb.h>
19 18
20#include <plat/common.h> 19#include <plat/common.h>
21#include <plat/board.h> 20#include <plat/board.h>
@@ -65,7 +64,6 @@ const void *__init omap_get_var_config(u16 tag, size_t *len)
65 64
66void __init omap_reserve(void) 65void __init omap_reserve(void)
67{ 66{
68 omapfb_reserve_sdram_memblock();
69 omap_vram_reserve_sdram_memblock(); 67 omap_vram_reserve_sdram_memblock();
70 omap_dsp_reserve_sdram_memblock(); 68 omap_dsp_reserve_sdram_memblock();
71 omap_secure_ram_reserve_memblock(); 69 omap_secure_ram_reserve_memblock();
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index c9e5d7298c40..dd6f92c99e56 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -34,15 +34,11 @@
34#include <asm/mach/map.h> 34#include <asm/mach/map.h>
35 35
36#include <plat/board.h> 36#include <plat/board.h>
37#include <plat/sram.h>
38
39#include "fb.h"
40 37
41#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) 38#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
42 39
40static bool omapfb_lcd_configured;
43static struct omapfb_platform_data omapfb_config; 41static struct omapfb_platform_data omapfb_config;
44static int config_invalid;
45static int configured_regions;
46 42
47static u64 omap_fb_dma_mask = ~(u32)0; 43static u64 omap_fb_dma_mask = ~(u32)0;
48 44
@@ -57,302 +53,21 @@ static struct platform_device omap_fb_device = {
57 .num_resources = 0, 53 .num_resources = 0,
58}; 54};
59 55
60void omapfb_set_platform_data(struct omapfb_platform_data *data) 56void __init omapfb_set_lcd_config(const struct omap_lcd_config *config)
61{
62}
63
64static inline int ranges_overlap(unsigned long start1, unsigned long size1,
65 unsigned long start2, unsigned long size2)
66{
67 return (start1 >= start2 && start1 < start2 + size2) ||
68 (start2 >= start1 && start2 < start1 + size1);
69}
70
71static inline int range_included(unsigned long start1, unsigned long size1,
72 unsigned long start2, unsigned long size2)
73{
74 return start1 >= start2 && start1 + size1 <= start2 + size2;
75}
76
77
78/* Check if there is an overlapping region. */
79static int fbmem_region_reserved(unsigned long start, size_t size)
80{
81 struct omapfb_mem_region *rg;
82 int i;
83
84 rg = &omapfb_config.mem_desc.region[0];
85 for (i = 0; i < OMAPFB_PLANE_NUM; i++, rg++) {
86 if (!rg->paddr)
87 /* Empty slot. */
88 continue;
89 if (ranges_overlap(start, size, rg->paddr, rg->size))
90 return 1;
91 }
92 return 0;
93}
94
95/*
96 * Get the region_idx`th region from board config/ATAG and convert it to
97 * our internal format.
98 */
99static int __init get_fbmem_region(int region_idx, struct omapfb_mem_region *rg)
100{ 57{
101 const struct omap_fbmem_config *conf; 58 omapfb_config.lcd = *config;
102 u32 paddr; 59 omapfb_lcd_configured = true;
103
104 conf = omap_get_nr_config(OMAP_TAG_FBMEM,
105 struct omap_fbmem_config, region_idx);
106 if (conf == NULL)
107 return -ENOENT;
108
109 paddr = conf->start;
110 /*
111 * Low bits encode the page allocation mode, if high bits
112 * are zero. Otherwise we need a page aligned fixed
113 * address.
114 */
115 memset(rg, 0, sizeof(*rg));
116 rg->type = paddr & ~PAGE_MASK;
117 rg->paddr = paddr & PAGE_MASK;
118 rg->size = PAGE_ALIGN(conf->size);
119 return 0;
120} 60}
121 61
122static int set_fbmem_region_type(struct omapfb_mem_region *rg, int mem_type, 62static int __init omap_init_fb(void)
123 unsigned long mem_start,
124 unsigned long mem_size)
125{
126 /*
127 * Check if the configuration specifies the type explicitly.
128 * type = 0 && paddr = 0, a default don't care case maps to
129 * the SDRAM type.
130 */
131 if (rg->type || !rg->paddr)
132 return 0;
133 if (ranges_overlap(rg->paddr, rg->size, mem_start, mem_size)) {
134 rg->type = mem_type;
135 return 0;
136 }
137 /* Can't determine it. */
138 return -1;
139}
140
141static int check_fbmem_region(int region_idx, struct omapfb_mem_region *rg,
142 unsigned long start_avail, unsigned size_avail)
143{ 63{
144 unsigned long paddr = rg->paddr;
145 size_t size = rg->size;
146
147 if (rg->type > OMAPFB_MEMTYPE_MAX) {
148 printk(KERN_ERR
149 "Invalid start address for FB region %d\n", region_idx);
150 return -EINVAL;
151 }
152
153 if (!rg->size) {
154 printk(KERN_ERR "Zero size for FB region %d\n", region_idx);
155 return -EINVAL;
156 }
157
158 if (!paddr)
159 /* Allocate this dynamically, leave paddr 0 for now. */
160 return 0;
161
162 /* 64 /*
163 * Fixed region for the given RAM range. Check if it's already 65 * If the board file has not set the lcd config with
164 * reserved by the FB code or someone else. 66 * omapfb_set_lcd_config(), don't bother registering the omapfb device
165 */ 67 */
166 if (fbmem_region_reserved(paddr, size) || 68 if (!omapfb_lcd_configured)
167 !range_included(paddr, size, start_avail, size_avail)) {
168 printk(KERN_ERR "Trying to use reserved memory "
169 "for FB region %d\n", region_idx);
170 return -EINVAL;
171 }
172
173 return 0;
174}
175
176static int valid_sdram(unsigned long addr, unsigned long size)
177{
178 return memblock_is_region_memory(addr, size);
179}
180
181static int reserve_sdram(unsigned long addr, unsigned long size)
182{
183 if (memblock_is_region_reserved(addr, size))
184 return -EBUSY;
185 if (memblock_reserve(addr, size))
186 return -ENOMEM;
187 return 0;
188}
189
190/*
191 * Called from map_io. We need to call to this early enough so that we
192 * can reserve the fixed SDRAM regions before VM could get hold of them.
193 */
194void __init omapfb_reserve_sdram_memblock(void)
195{
196 unsigned long reserved = 0;
197 int i;
198
199 if (config_invalid)
200 return;
201
202 for (i = 0; ; i++) {
203 struct omapfb_mem_region rg;
204
205 if (get_fbmem_region(i, &rg) < 0)
206 break;
207
208 if (i == OMAPFB_PLANE_NUM) {
209 pr_err("Extraneous FB mem configuration entries\n");
210 config_invalid = 1;
211 return;
212 }
213
214 /* Check if it's our memory type. */
215 if (rg.type != OMAPFB_MEMTYPE_SDRAM)
216 continue;
217
218 /* Check if the region falls within SDRAM */
219 if (rg.paddr && !valid_sdram(rg.paddr, rg.size))
220 continue;
221
222 if (rg.size == 0) {
223 pr_err("Zero size for FB region %d\n", i);
224 config_invalid = 1;
225 return;
226 }
227
228 if (rg.paddr) {
229 if (reserve_sdram(rg.paddr, rg.size)) {
230 pr_err("Trying to use reserved memory for FB region %d\n",
231 i);
232 config_invalid = 1;
233 return;
234 }
235 reserved += rg.size;
236 }
237
238 if (omapfb_config.mem_desc.region[i].size) {
239 pr_err("FB region %d already set\n", i);
240 config_invalid = 1;
241 return;
242 }
243
244 omapfb_config.mem_desc.region[i] = rg;
245 configured_regions++;
246 }
247 omapfb_config.mem_desc.region_cnt = i;
248 if (reserved)
249 pr_info("Reserving %lu bytes SDRAM for frame buffer\n",
250 reserved);
251}
252
253/*
254 * Called at sram init time, before anything is pushed to the SRAM stack.
255 * Because of the stack scheme, we will allocate everything from the
256 * start of the lowest address region to the end of SRAM. This will also
257 * include padding for page alignment and possible holes between regions.
258 *
259 * As opposed to the SDRAM case, we'll also do any dynamic allocations at
260 * this point, since the driver built as a module would have problem with
261 * freeing / reallocating the regions.
262 */
263unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
264 unsigned long sram_vstart,
265 unsigned long sram_size,
266 unsigned long pstart_avail,
267 unsigned long size_avail)
268{
269 struct omapfb_mem_region rg;
270 unsigned long pend_avail;
271 unsigned long reserved;
272 int i;
273
274 if (config_invalid)
275 return 0; 69 return 0;
276 70
277 reserved = 0;
278 pend_avail = pstart_avail + size_avail;
279 for (i = 0; ; i++) {
280 if (get_fbmem_region(i, &rg) < 0)
281 break;
282 if (i == OMAPFB_PLANE_NUM) {
283 printk(KERN_ERR
284 "Extraneous FB mem configuration entries\n");
285 config_invalid = 1;
286 return 0;
287 }
288
289 /* Check if it's our memory type. */
290 if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SRAM,
291 sram_pstart, sram_size) < 0 ||
292 (rg.type != OMAPFB_MEMTYPE_SRAM))
293 continue;
294 BUG_ON(omapfb_config.mem_desc.region[i].size);
295
296 if (check_fbmem_region(i, &rg, pstart_avail, size_avail) < 0) {
297 config_invalid = 1;
298 return 0;
299 }
300
301 if (!rg.paddr) {
302 /* Dynamic allocation */
303 if ((size_avail & PAGE_MASK) < rg.size) {
304 printk("Not enough SRAM for FB region %d\n",
305 i);
306 config_invalid = 1;
307 return 0;
308 }
309 size_avail = (size_avail - rg.size) & PAGE_MASK;
310 rg.paddr = pstart_avail + size_avail;
311 }
312 /* Reserve everything above the start of the region. */
313 if (pend_avail - rg.paddr > reserved)
314 reserved = pend_avail - rg.paddr;
315 size_avail = pend_avail - reserved - pstart_avail;
316
317 /*
318 * We have a kernel mapping for this already, so the
319 * driver won't have to make one.
320 */
321 rg.vaddr = (void *)(sram_vstart + rg.paddr - sram_pstart);
322 omapfb_config.mem_desc.region[i] = rg;
323 configured_regions++;
324 }
325 omapfb_config.mem_desc.region_cnt = i;
326 if (reserved)
327 pr_info("Reserving %lu bytes SRAM for frame buffer\n",
328 reserved);
329 return reserved;
330}
331
332void omapfb_set_ctrl_platform_data(void *data)
333{
334 omapfb_config.ctrl_platform_data = data;
335}
336
337static int __init omap_init_fb(void)
338{
339 const struct omap_lcd_config *conf;
340
341 if (config_invalid)
342 return 0;
343 if (configured_regions != omapfb_config.mem_desc.region_cnt) {
344 printk(KERN_ERR "Invalid FB mem configuration entries\n");
345 return 0;
346 }
347 conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
348 if (conf == NULL) {
349 if (configured_regions)
350 /* FB mem config, but no LCD config? */
351 printk(KERN_ERR "Missing LCD configuration\n");
352 return 0;
353 }
354 omapfb_config.lcd = *conf;
355
356 return platform_device_register(&omap_fb_device); 71 return platform_device_register(&omap_fb_device);
357} 72}
358 73
@@ -374,11 +89,6 @@ static struct platform_device omap_fb_device = {
374 .num_resources = 0, 89 .num_resources = 0,
375}; 90};
376 91
377void omapfb_set_platform_data(struct omapfb_platform_data *data)
378{
379 omapfb_config = *data;
380}
381
382static int __init omap_init_fb(void) 92static int __init omap_init_fb(void)
383{ 93{
384 return platform_device_register(&omap_fb_device); 94 return platform_device_register(&omap_fb_device);
@@ -386,36 +96,10 @@ static int __init omap_init_fb(void)
386 96
387arch_initcall(omap_init_fb); 97arch_initcall(omap_init_fb);
388 98
389void omapfb_reserve_sdram_memblock(void)
390{
391}
392
393unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
394 unsigned long sram_vstart,
395 unsigned long sram_size,
396 unsigned long start_avail,
397 unsigned long size_avail)
398{
399 return 0;
400}
401
402#else 99#else
403 100
404void omapfb_set_platform_data(struct omapfb_platform_data *data) 101void __init omapfb_set_lcd_config(const struct omap_lcd_config *config)
405{
406}
407
408void omapfb_reserve_sdram_memblock(void)
409{
410}
411
412unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
413 unsigned long sram_vstart,
414 unsigned long sram_size,
415 unsigned long start_avail,
416 unsigned long size_avail)
417{ 102{
418 return 0;
419} 103}
420 104
421#endif 105#endif
diff --git a/arch/arm/plat-omap/fb.h b/arch/arm/plat-omap/fb.h
deleted file mode 100644
index d765d0bd8520..000000000000
--- a/arch/arm/plat-omap/fb.h
+++ /dev/null
@@ -1,10 +0,0 @@
1#ifndef __PLAT_OMAP_FB_H__
2#define __PLAT_OMAP_FB_H__
3
4extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
5 unsigned long sram_vstart,
6 unsigned long sram_size,
7 unsigned long pstart_avail,
8 unsigned long size_avail);
9
10#endif /* __PLAT_OMAP_FB_H__ */
diff --git a/arch/arm/plat-omap/include/plat/blizzard.h b/arch/arm/plat-omap/include/plat/blizzard.h
deleted file mode 100644
index 56e7f2e7d12f..000000000000
--- a/arch/arm/plat-omap/include/plat/blizzard.h
+++ /dev/null
@@ -1,12 +0,0 @@
1#ifndef _BLIZZARD_H
2#define _BLIZZARD_H
3
4struct blizzard_platform_data {
5 void (*power_up)(struct device *dev);
6 void (*power_down)(struct device *dev);
7 unsigned long (*get_clock_rate)(struct device *dev);
8
9 unsigned te_connected:1;
10};
11
12#endif
diff --git a/arch/arm/plat-omap/include/plat/board.h b/arch/arm/plat-omap/include/plat/board.h
index 97126dfd2888..d5eb4c87db9d 100644
--- a/arch/arm/plat-omap/include/plat/board.h
+++ b/arch/arm/plat-omap/include/plat/board.h
@@ -28,9 +28,7 @@ enum {
28 28
29/* Different peripheral ids */ 29/* Different peripheral ids */
30#define OMAP_TAG_CLOCK 0x4f01 30#define OMAP_TAG_CLOCK 0x4f01
31#define OMAP_TAG_LCD 0x4f05
32#define OMAP_TAG_GPIO_SWITCH 0x4f06 31#define OMAP_TAG_GPIO_SWITCH 0x4f06
33#define OMAP_TAG_FBMEM 0x4f08
34#define OMAP_TAG_STI_CONSOLE 0x4f09 32#define OMAP_TAG_STI_CONSOLE 0x4f09
35#define OMAP_TAG_CAMERA_SENSOR 0x4f0a 33#define OMAP_TAG_CAMERA_SENSOR 0x4f0a
36 34
diff --git a/arch/arm/plat-omap/include/plat/hwa742.h b/arch/arm/plat-omap/include/plat/hwa742.h
deleted file mode 100644
index 886248d32b49..000000000000
--- a/arch/arm/plat-omap/include/plat/hwa742.h
+++ /dev/null
@@ -1,8 +0,0 @@
1#ifndef _HWA742_H
2#define _HWA742_H
3
4struct hwa742_platform_data {
5 unsigned te_connected:1;
6};
7
8#endif
diff --git a/arch/arm/plat-omap/include/plat/vram.h b/arch/arm/plat-omap/include/plat/vram.h
index 0aa4ecd12c7d..4d65b7d06e6c 100644
--- a/arch/arm/plat-omap/include/plat/vram.h
+++ b/arch/arm/plat-omap/include/plat/vram.h
@@ -23,40 +23,21 @@
23 23
24#include <linux/types.h> 24#include <linux/types.h>
25 25
26#define OMAP_VRAM_MEMTYPE_SDRAM 0
27#define OMAP_VRAM_MEMTYPE_SRAM 1
28#define OMAP_VRAM_MEMTYPE_MAX 1
29
30extern int omap_vram_add_region(unsigned long paddr, size_t size); 26extern int omap_vram_add_region(unsigned long paddr, size_t size);
31extern int omap_vram_free(unsigned long paddr, size_t size); 27extern int omap_vram_free(unsigned long paddr, size_t size);
32extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr); 28extern int omap_vram_alloc(size_t size, unsigned long *paddr);
33extern int omap_vram_reserve(unsigned long paddr, size_t size); 29extern int omap_vram_reserve(unsigned long paddr, size_t size);
34extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram, 30extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram,
35 unsigned long *largest_free_block); 31 unsigned long *largest_free_block);
36 32
37#ifdef CONFIG_OMAP2_VRAM 33#ifdef CONFIG_OMAP2_VRAM
38extern void omap_vram_set_sdram_vram(u32 size, u32 start); 34extern void omap_vram_set_sdram_vram(u32 size, u32 start);
39extern void omap_vram_set_sram_vram(u32 size, u32 start);
40 35
41extern void omap_vram_reserve_sdram_memblock(void); 36extern void omap_vram_reserve_sdram_memblock(void);
42extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
43 unsigned long sram_vstart,
44 unsigned long sram_size,
45 unsigned long pstart_avail,
46 unsigned long size_avail);
47#else 37#else
48static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { } 38static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { }
49static inline void omap_vram_set_sram_vram(u32 size, u32 start) { }
50 39
51static inline void omap_vram_reserve_sdram_memblock(void) { } 40static inline void omap_vram_reserve_sdram_memblock(void) { }
52static inline unsigned long omap_vram_reserve_sram(unsigned long sram_pstart,
53 unsigned long sram_vstart,
54 unsigned long sram_size,
55 unsigned long pstart_avail,
56 unsigned long size_avail)
57{
58 return 0;
59}
60#endif 41#endif
61 42
62#endif 43#endif
diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h
index 8f39aa5b26ea..9a78012d6f43 100644
--- a/arch/arm/plat-samsung/include/plat/regs-fb.h
+++ b/arch/arm/plat-samsung/include/plat/regs-fb.h
@@ -91,6 +91,9 @@
91#define VIDCON1_VSTATUS_BACKPORCH (0x1 << 13) 91#define VIDCON1_VSTATUS_BACKPORCH (0x1 << 13)
92#define VIDCON1_VSTATUS_ACTIVE (0x2 << 13) 92#define VIDCON1_VSTATUS_ACTIVE (0x2 << 13)
93#define VIDCON1_VSTATUS_FRONTPORCH (0x0 << 13) 93#define VIDCON1_VSTATUS_FRONTPORCH (0x0 << 13)
94#define VIDCON1_VCLK_MASK (0x3 << 9)
95#define VIDCON1_VCLK_HOLD (0x0 << 9)
96#define VIDCON1_VCLK_RUN (0x1 << 9)
94 97
95#define VIDCON1_INV_VCLK (1 << 7) 98#define VIDCON1_INV_VCLK (1 << 7)
96#define VIDCON1_INV_HSYNC (1 << 6) 99#define VIDCON1_INV_HSYNC (1 << 6)
@@ -164,15 +167,17 @@
164#define VIDTCON1_HSPW(_x) ((_x) << 0) 167#define VIDTCON1_HSPW(_x) ((_x) << 0)
165 168
166#define VIDTCON2 (0x18) 169#define VIDTCON2 (0x18)
170#define VIDTCON2_LINEVAL_E(_x) ((((_x) & 0x800) >> 11) << 23)
167#define VIDTCON2_LINEVAL_MASK (0x7ff << 11) 171#define VIDTCON2_LINEVAL_MASK (0x7ff << 11)
168#define VIDTCON2_LINEVAL_SHIFT (11) 172#define VIDTCON2_LINEVAL_SHIFT (11)
169#define VIDTCON2_LINEVAL_LIMIT (0x7ff) 173#define VIDTCON2_LINEVAL_LIMIT (0x7ff)
170#define VIDTCON2_LINEVAL(_x) ((_x) << 11) 174#define VIDTCON2_LINEVAL(_x) (((_x) & 0x7ff) << 11)
171 175
176#define VIDTCON2_HOZVAL_E(_x) ((((_x) & 0x800) >> 11) << 22)
172#define VIDTCON2_HOZVAL_MASK (0x7ff << 0) 177#define VIDTCON2_HOZVAL_MASK (0x7ff << 0)
173#define VIDTCON2_HOZVAL_SHIFT (0) 178#define VIDTCON2_HOZVAL_SHIFT (0)
174#define VIDTCON2_HOZVAL_LIMIT (0x7ff) 179#define VIDTCON2_HOZVAL_LIMIT (0x7ff)
175#define VIDTCON2_HOZVAL(_x) ((_x) << 0) 180#define VIDTCON2_HOZVAL(_x) (((_x) & 0x7ff) << 0)
176 181
177/* WINCONx */ 182/* WINCONx */
178 183
@@ -228,25 +233,29 @@
228/* Local input channels (windows 0-2) */ 233/* Local input channels (windows 0-2) */
229#define SHADOWCON_CHx_LOCAL_ENABLE(_win) (1 << (5 + (_win))) 234#define SHADOWCON_CHx_LOCAL_ENABLE(_win) (1 << (5 + (_win)))
230 235
236#define VIDOSDxA_TOPLEFT_X_E(_x) ((((_x) & 0x800) >> 11) << 23)
231#define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11) 237#define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11)
232#define VIDOSDxA_TOPLEFT_X_SHIFT (11) 238#define VIDOSDxA_TOPLEFT_X_SHIFT (11)
233#define VIDOSDxA_TOPLEFT_X_LIMIT (0x7ff) 239#define VIDOSDxA_TOPLEFT_X_LIMIT (0x7ff)
234#define VIDOSDxA_TOPLEFT_X(_x) ((_x) << 11) 240#define VIDOSDxA_TOPLEFT_X(_x) (((_x) & 0x7ff) << 11)
235 241
242#define VIDOSDxA_TOPLEFT_Y_E(_x) ((((_x) & 0x800) >> 11) << 22)
236#define VIDOSDxA_TOPLEFT_Y_MASK (0x7ff << 0) 243#define VIDOSDxA_TOPLEFT_Y_MASK (0x7ff << 0)
237#define VIDOSDxA_TOPLEFT_Y_SHIFT (0) 244#define VIDOSDxA_TOPLEFT_Y_SHIFT (0)
238#define VIDOSDxA_TOPLEFT_Y_LIMIT (0x7ff) 245#define VIDOSDxA_TOPLEFT_Y_LIMIT (0x7ff)
239#define VIDOSDxA_TOPLEFT_Y(_x) ((_x) << 0) 246#define VIDOSDxA_TOPLEFT_Y(_x) (((_x) & 0x7ff) << 0)
240 247
248#define VIDOSDxB_BOTRIGHT_X_E(_x) ((((_x) & 0x800) >> 11) << 23)
241#define VIDOSDxB_BOTRIGHT_X_MASK (0x7ff << 11) 249#define VIDOSDxB_BOTRIGHT_X_MASK (0x7ff << 11)
242#define VIDOSDxB_BOTRIGHT_X_SHIFT (11) 250#define VIDOSDxB_BOTRIGHT_X_SHIFT (11)
243#define VIDOSDxB_BOTRIGHT_X_LIMIT (0x7ff) 251#define VIDOSDxB_BOTRIGHT_X_LIMIT (0x7ff)
244#define VIDOSDxB_BOTRIGHT_X(_x) ((_x) << 11) 252#define VIDOSDxB_BOTRIGHT_X(_x) (((_x) & 0x7ff) << 11)
245 253
254#define VIDOSDxB_BOTRIGHT_Y_E(_x) ((((_x) & 0x800) >> 11) << 22)
246#define VIDOSDxB_BOTRIGHT_Y_MASK (0x7ff << 0) 255#define VIDOSDxB_BOTRIGHT_Y_MASK (0x7ff << 0)
247#define VIDOSDxB_BOTRIGHT_Y_SHIFT (0) 256#define VIDOSDxB_BOTRIGHT_Y_SHIFT (0)
248#define VIDOSDxB_BOTRIGHT_Y_LIMIT (0x7ff) 257#define VIDOSDxB_BOTRIGHT_Y_LIMIT (0x7ff)
249#define VIDOSDxB_BOTRIGHT_Y(_x) ((_x) << 0) 258#define VIDOSDxB_BOTRIGHT_Y(_x) (((_x) & 0x7ff) << 0)
250 259
251/* For VIDOSD[1..4]C */ 260/* For VIDOSD[1..4]C */
252#define VIDISD14C_ALPHA0_R(_x) ((_x) << 20) 261#define VIDISD14C_ALPHA0_R(_x) ((_x) << 20)
@@ -278,15 +287,17 @@
278#define VIDW_BUF_END1(_buff) (0xD4 + ((_buff) * 8)) 287#define VIDW_BUF_END1(_buff) (0xD4 + ((_buff) * 8))
279#define VIDW_BUF_SIZE(_buff) (0x100 + ((_buff) * 4)) 288#define VIDW_BUF_SIZE(_buff) (0x100 + ((_buff) * 4))
280 289
290#define VIDW_BUF_SIZE_OFFSET_E(_x) ((((_x) & 0x2000) >> 13) << 27)
281#define VIDW_BUF_SIZE_OFFSET_MASK (0x1fff << 13) 291#define VIDW_BUF_SIZE_OFFSET_MASK (0x1fff << 13)
282#define VIDW_BUF_SIZE_OFFSET_SHIFT (13) 292#define VIDW_BUF_SIZE_OFFSET_SHIFT (13)
283#define VIDW_BUF_SIZE_OFFSET_LIMIT (0x1fff) 293#define VIDW_BUF_SIZE_OFFSET_LIMIT (0x1fff)
284#define VIDW_BUF_SIZE_OFFSET(_x) ((_x) << 13) 294#define VIDW_BUF_SIZE_OFFSET(_x) (((_x) & 0x1fff) << 13)
285 295
296#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x) ((((_x) & 0x2000) >> 13) << 26)
286#define VIDW_BUF_SIZE_PAGEWIDTH_MASK (0x1fff << 0) 297#define VIDW_BUF_SIZE_PAGEWIDTH_MASK (0x1fff << 0)
287#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT (0) 298#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT (0)
288#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT (0x1fff) 299#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT (0x1fff)
289#define VIDW_BUF_SIZE_PAGEWIDTH(_x) ((_x) << 0) 300#define VIDW_BUF_SIZE_PAGEWIDTH(_x) (((_x) & 0x1fff) << 0)
290 301
291/* Interrupt controls and status */ 302/* Interrupt controls and status */
292 303
@@ -384,3 +395,9 @@
384#define WPALCON_W0PAL_16BPP_A555 (0x5 << 0) 395#define WPALCON_W0PAL_16BPP_A555 (0x5 << 0)
385#define WPALCON_W0PAL_16BPP_565 (0x6 << 0) 396#define WPALCON_W0PAL_16BPP_565 (0x6 << 0)
386 397
398/* Blending equation control */
399#define BLENDCON (0x260)
400#define BLENDCON_NEW_MASK (1 << 0)
401#define BLENDCON_NEW_8BIT_ALPHA_VALUE (1 << 0)
402#define BLENDCON_NEW_4BIT_ALPHA_VALUE (0 << 0)
403
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c
index ebd0f818a25f..8cf02e343333 100644
--- a/arch/sh/boards/mach-ap325rxa/setup.c
+++ b/arch/sh/boards/mach-ap325rxa/setup.c
@@ -157,7 +157,7 @@ static struct platform_device nand_flash_device = {
157#define PORT_DRVCRA 0xA405018A 157#define PORT_DRVCRA 0xA405018A
158#define PORT_DRVCRB 0xA405018C 158#define PORT_DRVCRB 0xA405018C
159 159
160static int ap320_wvga_set_brightness(void *board_data, int brightness) 160static int ap320_wvga_set_brightness(int brightness)
161{ 161{
162 if (brightness) { 162 if (brightness) {
163 gpio_set_value(GPIO_PTS3, 0); 163 gpio_set_value(GPIO_PTS3, 0);
@@ -170,12 +170,12 @@ static int ap320_wvga_set_brightness(void *board_data, int brightness)
170 return 0; 170 return 0;
171} 171}
172 172
173static int ap320_wvga_get_brightness(void *board_data) 173static int ap320_wvga_get_brightness(void)
174{ 174{
175 return gpio_get_value(GPIO_PTS3); 175 return gpio_get_value(GPIO_PTS3);
176} 176}
177 177
178static void ap320_wvga_power_on(void *board_data, struct fb_info *info) 178static void ap320_wvga_power_on(void)
179{ 179{
180 msleep(100); 180 msleep(100);
181 181
@@ -183,7 +183,7 @@ static void ap320_wvga_power_on(void *board_data, struct fb_info *info)
183 __raw_writew(FPGA_LCDREG_VAL, FPGA_LCDREG); 183 __raw_writew(FPGA_LCDREG_VAL, FPGA_LCDREG);
184} 184}
185 185
186static void ap320_wvga_power_off(void *board_data) 186static void ap320_wvga_power_off(void)
187{ 187{
188 /* ASD AP-320/325 LCD OFF */ 188 /* ASD AP-320/325 LCD OFF */
189 __raw_writew(0, FPGA_LCDREG); 189 __raw_writew(0, FPGA_LCDREG);
@@ -211,21 +211,19 @@ static struct sh_mobile_lcdc_info lcdc_info = {
211 .fourcc = V4L2_PIX_FMT_RGB565, 211 .fourcc = V4L2_PIX_FMT_RGB565,
212 .interface_type = RGB18, 212 .interface_type = RGB18,
213 .clock_divider = 1, 213 .clock_divider = 1,
214 .lcd_cfg = ap325rxa_lcdc_modes, 214 .lcd_modes = ap325rxa_lcdc_modes,
215 .num_cfg = ARRAY_SIZE(ap325rxa_lcdc_modes), 215 .num_modes = ARRAY_SIZE(ap325rxa_lcdc_modes),
216 .lcd_size_cfg = { /* 7.0 inch */ 216 .panel_cfg = {
217 .width = 152, 217 .width = 152, /* 7.0 inch */
218 .height = 91, 218 .height = 91,
219 },
220 .board_cfg = {
221 .display_on = ap320_wvga_power_on, 219 .display_on = ap320_wvga_power_on,
222 .display_off = ap320_wvga_power_off, 220 .display_off = ap320_wvga_power_off,
223 .set_brightness = ap320_wvga_set_brightness,
224 .get_brightness = ap320_wvga_get_brightness,
225 }, 221 },
226 .bl_info = { 222 .bl_info = {
227 .name = "sh_mobile_lcdc_bl", 223 .name = "sh_mobile_lcdc_bl",
228 .max_brightness = 1, 224 .max_brightness = 1,
225 .set_brightness = ap320_wvga_set_brightness,
226 .get_brightness = ap320_wvga_get_brightness,
229 }, 227 },
230 } 228 }
231}; 229};
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 59daae2f29db..e5ac12b2ce65 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -310,14 +310,14 @@ static const struct fb_videomode ecovec_dvi_modes[] = {
310 }, 310 },
311}; 311};
312 312
313static int ecovec24_set_brightness(void *board_data, int brightness) 313static int ecovec24_set_brightness(int brightness)
314{ 314{
315 gpio_set_value(GPIO_PTR1, brightness); 315 gpio_set_value(GPIO_PTR1, brightness);
316 316
317 return 0; 317 return 0;
318} 318}
319 319
320static int ecovec24_get_brightness(void *board_data) 320static int ecovec24_get_brightness(void)
321{ 321{
322 return gpio_get_value(GPIO_PTR1); 322 return gpio_get_value(GPIO_PTR1);
323} 323}
@@ -327,17 +327,15 @@ static struct sh_mobile_lcdc_info lcdc_info = {
327 .interface_type = RGB18, 327 .interface_type = RGB18,
328 .chan = LCDC_CHAN_MAINLCD, 328 .chan = LCDC_CHAN_MAINLCD,
329 .fourcc = V4L2_PIX_FMT_RGB565, 329 .fourcc = V4L2_PIX_FMT_RGB565,
330 .lcd_size_cfg = { /* 7.0 inch */ 330 .panel_cfg = { /* 7.0 inch */
331 .width = 152, 331 .width = 152,
332 .height = 91, 332 .height = 91,
333 }, 333 },
334 .board_cfg = {
335 .set_brightness = ecovec24_set_brightness,
336 .get_brightness = ecovec24_get_brightness,
337 },
338 .bl_info = { 334 .bl_info = {
339 .name = "sh_mobile_lcdc_bl", 335 .name = "sh_mobile_lcdc_bl",
340 .max_brightness = 1, 336 .max_brightness = 1,
337 .set_brightness = ecovec24_set_brightness,
338 .get_brightness = ecovec24_get_brightness,
341 }, 339 },
342 } 340 }
343}; 341};
@@ -1118,8 +1116,8 @@ static int __init arch_setup(void)
1118 /* DVI */ 1116 /* DVI */
1119 lcdc_info.clock_source = LCDC_CLK_EXTERNAL; 1117 lcdc_info.clock_source = LCDC_CLK_EXTERNAL;
1120 lcdc_info.ch[0].clock_divider = 1; 1118 lcdc_info.ch[0].clock_divider = 1;
1121 lcdc_info.ch[0].lcd_cfg = ecovec_dvi_modes; 1119 lcdc_info.ch[0].lcd_modes = ecovec_dvi_modes;
1122 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(ecovec_dvi_modes); 1120 lcdc_info.ch[0].num_modes = ARRAY_SIZE(ecovec_dvi_modes);
1123 1121
1124 gpio_set_value(GPIO_PTA2, 1); 1122 gpio_set_value(GPIO_PTA2, 1);
1125 gpio_set_value(GPIO_PTU1, 1); 1123 gpio_set_value(GPIO_PTU1, 1);
@@ -1127,8 +1125,8 @@ static int __init arch_setup(void)
1127 /* Panel */ 1125 /* Panel */
1128 lcdc_info.clock_source = LCDC_CLK_PERIPHERAL; 1126 lcdc_info.clock_source = LCDC_CLK_PERIPHERAL;
1129 lcdc_info.ch[0].clock_divider = 2; 1127 lcdc_info.ch[0].clock_divider = 2;
1130 lcdc_info.ch[0].lcd_cfg = ecovec_lcd_modes; 1128 lcdc_info.ch[0].lcd_modes = ecovec_lcd_modes;
1131 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(ecovec_lcd_modes); 1129 lcdc_info.ch[0].num_modes = ARRAY_SIZE(ecovec_lcd_modes);
1132 1130
1133 gpio_set_value(GPIO_PTR1, 1); 1131 gpio_set_value(GPIO_PTR1, 1);
1134 1132
diff --git a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
index 25e145fb7087..c148b36ecb65 100644
--- a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
+++ b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
@@ -251,8 +251,7 @@ static void display_on(void *sohandle,
251 write_memory_start(sohandle, so); 251 write_memory_start(sohandle, so);
252} 252}
253 253
254int kfr2r09_lcd_setup(void *board_data, void *sohandle, 254int kfr2r09_lcd_setup(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so)
255 struct sh_mobile_lcdc_sys_bus_ops *so)
256{ 255{
257 /* power on */ 256 /* power on */
258 gpio_set_value(GPIO_PTF4, 0); /* PROTECT/ -> L */ 257 gpio_set_value(GPIO_PTF4, 0); /* PROTECT/ -> L */
@@ -273,8 +272,7 @@ int kfr2r09_lcd_setup(void *board_data, void *sohandle,
273 return 0; 272 return 0;
274} 273}
275 274
276void kfr2r09_lcd_start(void *board_data, void *sohandle, 275void kfr2r09_lcd_start(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so)
277 struct sh_mobile_lcdc_sys_bus_ops *so)
278{ 276{
279 write_memory_start(sohandle, so); 277 write_memory_start(sohandle, so);
280} 278}
@@ -327,12 +325,12 @@ static int kfr2r09_lcd_backlight(int on)
327 return 0; 325 return 0;
328} 326}
329 327
330void kfr2r09_lcd_on(void *board_data, struct fb_info *info) 328void kfr2r09_lcd_on(void)
331{ 329{
332 kfr2r09_lcd_backlight(1); 330 kfr2r09_lcd_backlight(1);
333} 331}
334 332
335void kfr2r09_lcd_off(void *board_data) 333void kfr2r09_lcd_off(void)
336{ 334{
337 kfr2r09_lcd_backlight(0); 335 kfr2r09_lcd_backlight(0);
338} 336}
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
index 5b382e1afaea..d04a55d3b877 100644
--- a/arch/sh/boards/mach-kfr2r09/setup.c
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -148,13 +148,11 @@ static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
148 .interface_type = SYS18, 148 .interface_type = SYS18,
149 .clock_divider = 6, 149 .clock_divider = 6,
150 .flags = LCDC_FLAGS_DWPOL, 150 .flags = LCDC_FLAGS_DWPOL,
151 .lcd_cfg = kfr2r09_lcdc_modes, 151 .lcd_modes = kfr2r09_lcdc_modes,
152 .num_cfg = ARRAY_SIZE(kfr2r09_lcdc_modes), 152 .num_modes = ARRAY_SIZE(kfr2r09_lcdc_modes),
153 .lcd_size_cfg = { 153 .panel_cfg = {
154 .width = 35, 154 .width = 35,
155 .height = 58, 155 .height = 58,
156 },
157 .board_cfg = {
158 .setup_sys = kfr2r09_lcd_setup, 156 .setup_sys = kfr2r09_lcd_setup,
159 .start_transfer = kfr2r09_lcd_start, 157 .start_transfer = kfr2r09_lcd_start,
160 .display_on = kfr2r09_lcd_on, 158 .display_on = kfr2r09_lcd_on,
diff --git a/arch/sh/boards/mach-migor/lcd_qvga.c b/arch/sh/boards/mach-migor/lcd_qvga.c
index de9014a8a93e..8bccd345b69c 100644
--- a/arch/sh/boards/mach-migor/lcd_qvga.c
+++ b/arch/sh/boards/mach-migor/lcd_qvga.c
@@ -113,8 +113,7 @@ static const unsigned short magic3_data[] = {
113 0x0010, 0x16B0, 0x0011, 0x0111, 0x0007, 0x0061, 113 0x0010, 0x16B0, 0x0011, 0x0111, 0x0007, 0x0061,
114}; 114};
115 115
116int migor_lcd_qvga_setup(void *board_data, void *sohandle, 116int migor_lcd_qvga_setup(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so)
117 struct sh_mobile_lcdc_sys_bus_ops *so)
118{ 117{
119 unsigned long xres = 320; 118 unsigned long xres = 320;
120 unsigned long yres = 240; 119 unsigned long yres = 240;
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index d37ba2720527..ff6f69c6906e 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -246,9 +246,9 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
246 .fourcc = V4L2_PIX_FMT_RGB565, 246 .fourcc = V4L2_PIX_FMT_RGB565,
247 .interface_type = RGB16, 247 .interface_type = RGB16,
248 .clock_divider = 2, 248 .clock_divider = 2,
249 .lcd_cfg = migor_lcd_modes, 249 .lcd_modes = migor_lcd_modes,
250 .num_cfg = ARRAY_SIZE(migor_lcd_modes), 250 .num_modes = ARRAY_SIZE(migor_lcd_modes),
251 .lcd_size_cfg = { /* 7.0 inch */ 251 .panel_cfg = { /* 7.0 inch */
252 .width = 152, 252 .width = 152,
253 .height = 91, 253 .height = 91,
254 }, 254 },
@@ -260,13 +260,11 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
260 .fourcc = V4L2_PIX_FMT_RGB565, 260 .fourcc = V4L2_PIX_FMT_RGB565,
261 .interface_type = SYS16A, 261 .interface_type = SYS16A,
262 .clock_divider = 10, 262 .clock_divider = 10,
263 .lcd_cfg = migor_lcd_modes, 263 .lcd_modes = migor_lcd_modes,
264 .num_cfg = ARRAY_SIZE(migor_lcd_modes), 264 .num_modes = ARRAY_SIZE(migor_lcd_modes),
265 .lcd_size_cfg = { /* 2.4 inch */ 265 .panel_cfg = {
266 .width = 49, 266 .width = 49, /* 2.4 inch */
267 .height = 37, 267 .height = 37,
268 },
269 .board_cfg = {
270 .setup_sys = migor_lcd_qvga_setup, 268 .setup_sys = migor_lcd_qvga_setup,
271 }, 269 },
272 .sys_bus_cfg = { 270 .sys_bus_cfg = {
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 59f4db829e91..c540b16547c3 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -182,12 +182,10 @@ static struct sh_mobile_lcdc_info lcdc_info = {
182 .chan = LCDC_CHAN_MAINLCD, 182 .chan = LCDC_CHAN_MAINLCD,
183 .fourcc = V4L2_PIX_FMT_RGB565, 183 .fourcc = V4L2_PIX_FMT_RGB565,
184 .clock_divider = 1, 184 .clock_divider = 1,
185 .lcd_size_cfg = { /* 7.0 inch */ 185 .panel_cfg = { /* 7.0 inch */
186 .width = 152, 186 .width = 152,
187 .height = 91, 187 .height = 91,
188 }, 188 },
189 .board_cfg = {
190 },
191 } 189 }
192}; 190};
193 191
@@ -890,12 +888,12 @@ static int __init devices_setup(void)
890 888
891 if (sw & SW41_B) { 889 if (sw & SW41_B) {
892 /* 720p */ 890 /* 720p */
893 lcdc_info.ch[0].lcd_cfg = lcdc_720p_modes; 891 lcdc_info.ch[0].lcd_modes = lcdc_720p_modes;
894 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(lcdc_720p_modes); 892 lcdc_info.ch[0].num_modes = ARRAY_SIZE(lcdc_720p_modes);
895 } else { 893 } else {
896 /* VGA */ 894 /* VGA */
897 lcdc_info.ch[0].lcd_cfg = lcdc_vga_modes; 895 lcdc_info.ch[0].lcd_modes = lcdc_vga_modes;
898 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(lcdc_vga_modes); 896 lcdc_info.ch[0].num_modes = ARRAY_SIZE(lcdc_vga_modes);
899 } 897 }
900 898
901 if (sw & SW41_A) { 899 if (sw & SW41_A) {
diff --git a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
index 07e635b0e04c..ba3d93d333f8 100644
--- a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
+++ b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
@@ -4,21 +4,21 @@
4#include <video/sh_mobile_lcdc.h> 4#include <video/sh_mobile_lcdc.h>
5 5
6#if defined(CONFIG_FB_SH_MOBILE_LCDC) || defined(CONFIG_FB_SH_MOBILE_LCDC_MODULE) 6#if defined(CONFIG_FB_SH_MOBILE_LCDC) || defined(CONFIG_FB_SH_MOBILE_LCDC_MODULE)
7void kfr2r09_lcd_on(void *board_data, struct fb_info *info); 7void kfr2r09_lcd_on(void);
8void kfr2r09_lcd_off(void *board_data); 8void kfr2r09_lcd_off(void);
9int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle, 9int kfr2r09_lcd_setup(void *sys_ops_handle,
10 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 10 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
11void kfr2r09_lcd_start(void *board_data, void *sys_ops_handle, 11void kfr2r09_lcd_start(void *sys_ops_handle,
12 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 12 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
13#else 13#else
14static void kfr2r09_lcd_on(void *board_data) {} 14static void kfr2r09_lcd_on(void) {}
15static void kfr2r09_lcd_off(void *board_data) {} 15static void kfr2r09_lcd_off(void) {}
16static int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle, 16static int kfr2r09_lcd_setup(void *sys_ops_handle,
17 struct sh_mobile_lcdc_sys_bus_ops *sys_ops) 17 struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
18{ 18{
19 return -ENODEV; 19 return -ENODEV;
20} 20}
21static void kfr2r09_lcd_start(void *board_data, void *sys_ops_handle, 21static void kfr2r09_lcd_start(void *sys_ops_handle,
22 struct sh_mobile_lcdc_sys_bus_ops *sys_ops) 22 struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
23{ 23{
24} 24}
diff --git a/arch/sh/include/mach-migor/mach/migor.h b/arch/sh/include/mach-migor/mach/migor.h
index 42fccf93412e..7de7bb74c290 100644
--- a/arch/sh/include/mach-migor/mach/migor.h
+++ b/arch/sh/include/mach-migor/mach/migor.h
@@ -9,7 +9,7 @@
9 9
10#include <video/sh_mobile_lcdc.h> 10#include <video/sh_mobile_lcdc.h>
11 11
12int migor_lcd_qvga_setup(void *board_data, void *sys_ops_handle, 12int migor_lcd_qvga_setup(void *sys_ops_handle,
13 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 13 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
14 14
15#endif /* __ASM_SH_MIGOR_H */ 15#endif /* __ASM_SH_MIGOR_H */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index eca60c73ef1f..a8a897ac5446 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1123,6 +1123,18 @@ config FB_RIVA_BACKLIGHT
1123 help 1123 help
1124 Say Y here if you want to control the backlight of your display. 1124 Say Y here if you want to control the backlight of your display.
1125 1125
1126config FB_I740
1127 tristate "Intel740 support (EXPERIMENTAL)"
1128 depends on EXPERIMENTAL && FB && PCI
1129 select FB_MODE_HELPERS
1130 select FB_CFB_FILLRECT
1131 select FB_CFB_COPYAREA
1132 select FB_CFB_IMAGEBLIT
1133 select VGASTATE
1134 select FB_DDC
1135 help
1136 This driver supports graphics cards based on Intel740 chip.
1137
1126config FB_I810 1138config FB_I810
1127 tristate "Intel 810/815 support (EXPERIMENTAL)" 1139 tristate "Intel 810/815 support (EXPERIMENTAL)"
1128 depends on EXPERIMENTAL && FB && PCI && X86_32 && AGP_INTEL 1140 depends on EXPERIMENTAL && FB && PCI && X86_32 && AGP_INTEL
@@ -2001,18 +2013,6 @@ config FB_SH_MOBILE_HDMI
2001 ---help--- 2013 ---help---
2002 Driver for the on-chip SH-Mobile HDMI controller. 2014 Driver for the on-chip SH-Mobile HDMI controller.
2003 2015
2004config FB_SH_MOBILE_MERAM
2005 tristate "SuperH Mobile MERAM read ahead support for LCDC"
2006 depends on FB_SH_MOBILE_LCDC
2007 default y
2008 ---help---
2009 Enable MERAM support for the SH-Mobile LCD controller.
2010
2011 This will allow for caching of the framebuffer to provide more
2012 reliable access under heavy main memory bus traffic situations.
2013 Up to 4 memory channels can be configured, allowing 4 RGB or
2014 2 YCbCr framebuffers to be configured.
2015
2016config FB_TMIO 2016config FB_TMIO
2017 tristate "Toshiba Mobile IO FrameBuffer support" 2017 tristate "Toshiba Mobile IO FrameBuffer support"
2018 depends on FB && MFD_CORE 2018 depends on FB && MFD_CORE
@@ -2233,6 +2233,7 @@ config FB_DA8XX
2233 select FB_CFB_FILLRECT 2233 select FB_CFB_FILLRECT
2234 select FB_CFB_COPYAREA 2234 select FB_CFB_COPYAREA
2235 select FB_CFB_IMAGEBLIT 2235 select FB_CFB_IMAGEBLIT
2236 select FB_CFB_REV_PIXELS_IN_BYTE
2236 ---help--- 2237 ---help---
2237 This is the frame buffer device driver for the TI LCD controller 2238 This is the frame buffer device driver for the TI LCD controller
2238 found on DA8xx/OMAP-L1xx SoCs. 2239 found on DA8xx/OMAP-L1xx SoCs.
@@ -2412,7 +2413,7 @@ config FB_PUV3_UNIGFX
2412 2413
2413source "drivers/video/omap/Kconfig" 2414source "drivers/video/omap/Kconfig"
2414source "drivers/video/omap2/Kconfig" 2415source "drivers/video/omap2/Kconfig"
2415 2416source "drivers/video/exynos/Kconfig"
2416source "drivers/video/backlight/Kconfig" 2417source "drivers/video/backlight/Kconfig"
2417 2418
2418if VT 2419if VT
@@ -2423,4 +2424,16 @@ if FB || SGI_NEWPORT_CONSOLE
2423 source "drivers/video/logo/Kconfig" 2424 source "drivers/video/logo/Kconfig"
2424endif 2425endif
2425 2426
2427config FB_SH_MOBILE_MERAM
2428 tristate "SuperH Mobile MERAM read ahead support"
2429 depends on (SUPERH || ARCH_SHMOBILE)
2430 select GENERIC_ALLOCATOR
2431 ---help---
2432 Enable MERAM support for the SuperH controller.
2433
2434 This will allow for caching of the framebuffer to provide more
2435 reliable access under heavy main memory bus traffic situations.
2436 Up to 4 memory channels can be configured, allowing 4 RGB or
2437 2 YCbCr framebuffers to be configured.
2438
2426endmenu 2439endmenu
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 142606814d98..9356add945b3 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -15,6 +15,8 @@ obj-$(CONFIG_VT) += console/
15obj-$(CONFIG_LOGO) += logo/ 15obj-$(CONFIG_LOGO) += logo/
16obj-y += backlight/ 16obj-y += backlight/
17 17
18obj-$(CONFIG_EXYNOS_VIDEO) += exynos/
19
18obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o 20obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
19obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o 21obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
20obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o 22obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
@@ -37,6 +39,7 @@ obj-$(CONFIG_FB_GRVGA) += grvga.o
37obj-$(CONFIG_FB_PM2) += pm2fb.o 39obj-$(CONFIG_FB_PM2) += pm2fb.o
38obj-$(CONFIG_FB_PM3) += pm3fb.o 40obj-$(CONFIG_FB_PM3) += pm3fb.o
39 41
42obj-$(CONFIG_FB_I740) += i740fb.o
40obj-$(CONFIG_FB_MATROX) += matrox/ 43obj-$(CONFIG_FB_MATROX) += matrox/
41obj-$(CONFIG_FB_RIVA) += riva/ 44obj-$(CONFIG_FB_RIVA) += riva/
42obj-$(CONFIG_FB_NVIDIA) += nvidia/ 45obj-$(CONFIG_FB_NVIDIA) += nvidia/
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index e40c00f2c2ba..d99505b16374 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -421,24 +421,18 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
421 var->red.length = var->green.length = var->blue.length 421 var->red.length = var->green.length = var->blue.length
422 = var->bits_per_pixel; 422 = var->bits_per_pixel;
423 break; 423 break;
424 case 15:
425 case 16: 424 case 16:
426 if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { 425 if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
427 /* RGB:565 mode */ 426 /* RGB:565 mode */
428 var->red.offset = 11; 427 var->red.offset = 11;
429 var->blue.offset = 0; 428 var->blue.offset = 0;
430 var->green.length = 6;
431 } else if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB555) {
432 var->red.offset = 10;
433 var->blue.offset = 0;
434 var->green.length = 5;
435 } else { 429 } else {
436 /* BGR:555 mode */ 430 /* BGR:565 mode */
437 var->red.offset = 0; 431 var->red.offset = 0;
438 var->blue.offset = 10; 432 var->blue.offset = 11;
439 var->green.length = 5;
440 } 433 }
441 var->green.offset = 5; 434 var->green.offset = 5;
435 var->green.length = 6;
442 var->red.length = var->blue.length = 5; 436 var->red.length = var->blue.length = 5;
443 break; 437 break;
444 case 32: 438 case 32:
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index de9da6774fd9..befcbd8ef019 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -477,7 +477,8 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
477 u32 sys_clksrc; 477 u32 sys_clksrc;
478 478
479 /* Allocate new device private */ 479 /* Allocate new device private */
480 fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL); 480 fbdev = devm_kzalloc(&dev->dev, sizeof(struct au1100fb_device),
481 GFP_KERNEL);
481 if (!fbdev) { 482 if (!fbdev) {
482 print_err("fail to allocate device private record"); 483 print_err("fail to allocate device private record");
483 return -ENOMEM; 484 return -ENOMEM;
@@ -498,8 +499,9 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
498 au1100fb_fix.mmio_start = regs_res->start; 499 au1100fb_fix.mmio_start = regs_res->start;
499 au1100fb_fix.mmio_len = resource_size(regs_res); 500 au1100fb_fix.mmio_len = resource_size(regs_res);
500 501
501 if (!request_mem_region(au1100fb_fix.mmio_start, au1100fb_fix.mmio_len, 502 if (!devm_request_mem_region(au1100fb_fix.mmio_start,
502 DRIVER_NAME)) { 503 au1100fb_fix.mmio_len,
504 DRIVER_NAME)) {
503 print_err("fail to lock memory region at 0x%08lx", 505 print_err("fail to lock memory region at 0x%08lx",
504 au1100fb_fix.mmio_start); 506 au1100fb_fix.mmio_start);
505 return -EBUSY; 507 return -EBUSY;
@@ -514,8 +516,9 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
514 fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * 516 fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
515 (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; 517 (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
516 518
517 fbdev->fb_mem = dma_alloc_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), 519 fbdev->fb_mem = dmam_alloc_coherent(&dev->dev, &dev->dev,
518 &fbdev->fb_phys, GFP_KERNEL); 520 PAGE_ALIGN(fbdev->fb_len),
521 &fbdev->fb_phys, GFP_KERNEL);
519 if (!fbdev->fb_mem) { 522 if (!fbdev->fb_mem) {
520 print_err("fail to allocate frambuffer (size: %dK))", 523 print_err("fail to allocate frambuffer (size: %dK))",
521 fbdev->fb_len / 1024); 524 fbdev->fb_len / 1024);
@@ -557,14 +560,14 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
557 fbdev->info.fbops = &au1100fb_ops; 560 fbdev->info.fbops = &au1100fb_ops;
558 fbdev->info.fix = au1100fb_fix; 561 fbdev->info.fix = au1100fb_fix;
559 562
560 if (!(fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL))) { 563 fbdev->info.pseudo_palette =
564 devm_kzalloc(&dev->dev, sizeof(u32) * 16, GFP_KERNEL);
565 if (!fbdev->info.pseudo_palette)
561 return -ENOMEM; 566 return -ENOMEM;
562 }
563 567
564 if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { 568 if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
565 print_err("Fail to allocate colormap (%d entries)", 569 print_err("Fail to allocate colormap (%d entries)",
566 AU1100_LCD_NBR_PALETTE_ENTRIES); 570 AU1100_LCD_NBR_PALETTE_ENTRIES);
567 kfree(fbdev->info.pseudo_palette);
568 return -EFAULT; 571 return -EFAULT;
569 } 572 }
570 573
@@ -582,9 +585,6 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
582 return 0; 585 return 0;
583 586
584failed: 587failed:
585 if (fbdev->regs) {
586 release_mem_region(fbdev->regs_phys, fbdev->regs_len);
587 }
588 if (fbdev->fb_mem) { 588 if (fbdev->fb_mem) {
589 dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem, 589 dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem,
590 fbdev->fb_phys); 590 fbdev->fb_phys);
@@ -592,10 +592,9 @@ failed:
592 if (fbdev->info.cmap.len != 0) { 592 if (fbdev->info.cmap.len != 0) {
593 fb_dealloc_cmap(&fbdev->info.cmap); 593 fb_dealloc_cmap(&fbdev->info.cmap);
594 } 594 }
595 kfree(fbdev);
596 platform_set_drvdata(dev, NULL); 595 platform_set_drvdata(dev, NULL);
597 596
598 return 0; 597 return -ENODEV;
599} 598}
600 599
601int au1100fb_drv_remove(struct platform_device *dev) 600int au1100fb_drv_remove(struct platform_device *dev)
@@ -615,14 +614,7 @@ int au1100fb_drv_remove(struct platform_device *dev)
615 /* Clean up all probe data */ 614 /* Clean up all probe data */
616 unregister_framebuffer(&fbdev->info); 615 unregister_framebuffer(&fbdev->info);
617 616
618 release_mem_region(fbdev->regs_phys, fbdev->regs_len);
619
620 dma_free_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem,
621 fbdev->fb_phys);
622
623 fb_dealloc_cmap(&fbdev->info.cmap); 617 fb_dealloc_cmap(&fbdev->info.cmap);
624 kfree(fbdev->info.pseudo_palette);
625 kfree((void*)fbdev);
626 618
627 return 0; 619 return 0;
628} 620}
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index 04e4479d5afd..3e9a773db09f 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -1724,7 +1724,7 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev)
1724 /* Allocate the framebuffer to the maximum screen size */ 1724 /* Allocate the framebuffer to the maximum screen size */
1725 fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8; 1725 fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;
1726 1726
1727 fbdev->fb_mem = dma_alloc_noncoherent(&dev->dev, 1727 fbdev->fb_mem = dmam_alloc_noncoherent(&dev->dev, &dev->dev,
1728 PAGE_ALIGN(fbdev->fb_len), 1728 PAGE_ALIGN(fbdev->fb_len),
1729 &fbdev->fb_phys, GFP_KERNEL); 1729 &fbdev->fb_phys, GFP_KERNEL);
1730 if (!fbdev->fb_mem) { 1730 if (!fbdev->fb_mem) {
@@ -1788,9 +1788,6 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev)
1788 1788
1789failed: 1789failed:
1790 /* NOTE: This only does the current plane/window that failed; others are still active */ 1790 /* NOTE: This only does the current plane/window that failed; others are still active */
1791 if (fbdev->fb_mem)
1792 dma_free_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len),
1793 fbdev->fb_mem, fbdev->fb_phys);
1794 if (fbi) { 1791 if (fbi) {
1795 if (fbi->cmap.len != 0) 1792 if (fbi->cmap.len != 0)
1796 fb_dealloc_cmap(&fbi->cmap); 1793 fb_dealloc_cmap(&fbi->cmap);
@@ -1817,10 +1814,6 @@ static int __devexit au1200fb_drv_remove(struct platform_device *dev)
1817 1814
1818 /* Clean up all probe data */ 1815 /* Clean up all probe data */
1819 unregister_framebuffer(fbi); 1816 unregister_framebuffer(fbi);
1820 if (fbdev->fb_mem)
1821 dma_free_noncoherent(&dev->dev,
1822 PAGE_ALIGN(fbdev->fb_len),
1823 fbdev->fb_mem, fbdev->fb_phys);
1824 if (fbi->cmap.len != 0) 1817 if (fbi->cmap.len != 0)
1825 fb_dealloc_cmap(&fbi->cmap); 1818 fb_dealloc_cmap(&fbi->cmap);
1826 kfree(fbi->pseudo_palette); 1819 kfree(fbi->pseudo_palette);
diff --git a/drivers/video/bf537-lq035.c b/drivers/video/bf537-lq035.c
index bea53c1a4950..befbc80d11fc 100644
--- a/drivers/video/bf537-lq035.c
+++ b/drivers/video/bf537-lq035.c
@@ -383,23 +383,19 @@ static int __devinit request_ports(void)
383 } 383 }
384 384
385#if (defined(UD) && defined(LBR)) 385#if (defined(UD) && defined(LBR))
386 if (gpio_request(UD, KBUILD_MODNAME)) { 386 if (gpio_request_one(UD, GPIOF_OUT_INIT_LOW, KBUILD_MODNAME)) {
387 pr_err("requesting GPIO %d failed\n", UD); 387 pr_err("requesting GPIO %d failed\n", UD);
388 return -EBUSY; 388 return -EBUSY;
389 } 389 }
390 390
391 if (gpio_request(LBR, KBUILD_MODNAME)) { 391 if (gpio_request_one(LBR, GPIOF_OUT_INIT_HIGH, KBUILD_MODNAME)) {
392 pr_err("requesting GPIO %d failed\n", LBR); 392 pr_err("requesting GPIO %d failed\n", LBR);
393 gpio_free(UD); 393 gpio_free(UD);
394 return -EBUSY; 394 return -EBUSY;
395 } 395 }
396
397 gpio_direction_output(UD, 0);
398 gpio_direction_output(LBR, 1);
399
400#endif 396#endif
401 397
402 if (gpio_request(MOD, KBUILD_MODNAME)) { 398 if (gpio_request_one(MOD, GPIOF_OUT_INIT_HIGH, KBUILD_MODNAME)) {
403 pr_err("requesting GPIO %d failed\n", MOD); 399 pr_err("requesting GPIO %d failed\n", MOD);
404#if (defined(UD) && defined(LBR)) 400#if (defined(UD) && defined(LBR))
405 gpio_free(LBR); 401 gpio_free(LBR);
@@ -408,8 +404,6 @@ static int __devinit request_ports(void)
408 return -EBUSY; 404 return -EBUSY;
409 } 405 }
410 406
411 gpio_direction_output(MOD, 1);
412
413 SSYNC(); 407 SSYNC();
414 return 0; 408 return 0;
415} 409}
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index 46b03f53985f..dc2f0047769b 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -240,7 +240,7 @@ static int request_ports(struct bfin_bf54xfb_info *fbi)
240 u16 eppi_req_18[] = EPPI0_18; 240 u16 eppi_req_18[] = EPPI0_18;
241 u16 disp = fbi->mach_info->disp; 241 u16 disp = fbi->mach_info->disp;
242 242
243 if (gpio_request(disp, DRIVER_NAME)) { 243 if (gpio_request_one(disp, GPIOF_OUT_INIT_HIGH, DRIVER_NAME)) {
244 printk(KERN_ERR "Requesting GPIO %d failed\n", disp); 244 printk(KERN_ERR "Requesting GPIO %d failed\n", disp);
245 return -EFAULT; 245 return -EFAULT;
246 } 246 }
@@ -263,8 +263,6 @@ static int request_ports(struct bfin_bf54xfb_info *fbi)
263 } 263 }
264 } 264 }
265 265
266 gpio_direction_output(disp, 1);
267
268 return 0; 266 return 0;
269} 267}
270 268
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c
index c633068372c9..86922ac84412 100644
--- a/drivers/video/bfin-lq035q1-fb.c
+++ b/drivers/video/bfin-lq035q1-fb.c
@@ -365,10 +365,10 @@ static int __devinit bfin_lq035q1_request_ports(struct platform_device *pdev,
365 * Drive PPI_FS3 Low 365 * Drive PPI_FS3 Low
366 */ 366 */
367 if (ANOMALY_05000400) { 367 if (ANOMALY_05000400) {
368 int ret = gpio_request(P_IDENT(P_PPI0_FS3), "PPI_FS3"); 368 int ret = gpio_request_one(P_IDENT(P_PPI0_FS3),
369 GPIOF_OUT_INIT_LOW, "PPI_FS3");
369 if (ret) 370 if (ret)
370 return ret; 371 return ret;
371 gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
372 } 372 }
373 373
374 if (ppi16) 374 if (ppi16)
@@ -716,14 +716,14 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
716 } 716 }
717 717
718 if (info->disp_info->use_bl) { 718 if (info->disp_info->use_bl) {
719 ret = gpio_request(info->disp_info->gpio_bl, "LQ035 Backlight"); 719 ret = gpio_request_one(info->disp_info->gpio_bl,
720 GPIOF_OUT_INIT_LOW, "LQ035 Backlight");
720 721
721 if (ret) { 722 if (ret) {
722 dev_err(&pdev->dev, "failed to request GPIO %d\n", 723 dev_err(&pdev->dev, "failed to request GPIO %d\n",
723 info->disp_info->gpio_bl); 724 info->disp_info->gpio_bl);
724 goto out9; 725 goto out9;
725 } 726 }
726 gpio_direction_output(info->disp_info->gpio_bl, 0);
727 } 727 }
728 728
729 ret = register_framebuffer(fbinfo); 729 ret = register_framebuffer(fbinfo);
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c
index 811dd7f6aa41..1a268a294478 100644
--- a/drivers/video/bfin_adv7393fb.c
+++ b/drivers/video/bfin_adv7393fb.c
@@ -36,9 +36,7 @@
36#include <linux/dma-mapping.h> 36#include <linux/dma-mapping.h>
37#include <linux/proc_fs.h> 37#include <linux/proc_fs.h>
38#include <linux/platform_device.h> 38#include <linux/platform_device.h>
39
40#include <linux/i2c.h> 39#include <linux/i2c.h>
41#include <linux/i2c-dev.h>
42 40
43#include "bfin_adv7393fb.h" 41#include "bfin_adv7393fb.h"
44 42
@@ -411,12 +409,13 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
411 409
412 /* Workaround "PPI Does Not Start Properly In Specific Mode" */ 410 /* Workaround "PPI Does Not Start Properly In Specific Mode" */
413 if (ANOMALY_05000400) { 411 if (ANOMALY_05000400) {
414 if (gpio_request(P_IDENT(P_PPI0_FS3), "PPI0_FS3")) { 412 ret = gpio_request_one(P_IDENT(P_PPI0_FS3), GPIOF_OUT_INIT_LOW,
413 "PPI0_FS3")
414 if (ret) {
415 dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n"); 415 dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n");
416 ret = -EBUSY; 416 ret = -EBUSY;
417 goto out_8; 417 goto out_8;
418 } 418 }
419 gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
420 } 419 }
421 420
422 if (peripheral_request_list(ppi_pins, DRIVER_NAME)) { 421 if (peripheral_request_list(ppi_pins, DRIVER_NAME)) {
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 29577bf1f559..47118c75a4c0 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -32,6 +32,7 @@
32#include <linux/console.h> 32#include <linux/console.h>
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <video/da8xx-fb.h> 34#include <video/da8xx-fb.h>
35#include <asm/div64.h>
35 36
36#define DRIVER_NAME "da8xx_lcdc" 37#define DRIVER_NAME "da8xx_lcdc"
37 38
@@ -161,6 +162,7 @@ struct da8xx_fb_par {
161 int vsync_timeout; 162 int vsync_timeout;
162#ifdef CONFIG_CPU_FREQ 163#ifdef CONFIG_CPU_FREQ
163 struct notifier_block freq_transition; 164 struct notifier_block freq_transition;
165 unsigned int lcd_fck_rate;
164#endif 166#endif
165 void (*panel_power_ctrl)(int); 167 void (*panel_power_ctrl)(int);
166}; 168};
@@ -174,7 +176,6 @@ static struct fb_var_screeninfo da8xx_fb_var __devinitdata = {
174 .activate = 0, 176 .activate = 0,
175 .height = -1, 177 .height = -1,
176 .width = -1, 178 .width = -1,
177 .pixclock = 46666, /* 46us - AUO display */
178 .accel_flags = 0, 179 .accel_flags = 0,
179 .left_margin = LEFT_MARGIN, 180 .left_margin = LEFT_MARGIN,
180 .right_margin = RIGHT_MARGIN, 181 .right_margin = RIGHT_MARGIN,
@@ -238,6 +239,20 @@ static struct da8xx_panel known_lcd_panels[] = {
238 .pxl_clk = 7833600, 239 .pxl_clk = 7833600,
239 .invert_pxl_clk = 0, 240 .invert_pxl_clk = 0,
240 }, 241 },
242 [2] = {
243 /* Hitachi SP10Q010 */
244 .name = "SP10Q010",
245 .width = 320,
246 .height = 240,
247 .hfp = 10,
248 .hbp = 10,
249 .hsw = 10,
250 .vfp = 10,
251 .vbp = 10,
252 .vsw = 10,
253 .pxl_clk = 7833600,
254 .invert_pxl_clk = 0,
255 },
241}; 256};
242 257
243/* Enable the Raster Engine of the LCD Controller */ 258/* Enable the Raster Engine of the LCD Controller */
@@ -546,7 +561,26 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
546 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) 561 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
547 return 1; 562 return 1;
548 563
549 if (info->var.bits_per_pixel == 8) { 564 if (info->var.bits_per_pixel == 4) {
565 if (regno > 15)
566 return 1;
567
568 if (info->var.grayscale) {
569 pal = regno;
570 } else {
571 red >>= 4;
572 green >>= 8;
573 blue >>= 12;
574
575 pal = (red & 0x0f00);
576 pal |= (green & 0x00f0);
577 pal |= (blue & 0x000f);
578 }
579 if (regno == 0)
580 pal |= 0x2000;
581 palette[regno] = pal;
582
583 } else if (info->var.bits_per_pixel == 8) {
550 red >>= 4; 584 red >>= 4;
551 green >>= 8; 585 green >>= 8;
552 blue >>= 12; 586 blue >>= 12;
@@ -801,6 +835,7 @@ static int fb_check_var(struct fb_var_screeninfo *var,
801 var->blue.length = 8; 835 var->blue.length = 8;
802 var->transp.offset = 0; 836 var->transp.offset = 0;
803 var->transp.length = 0; 837 var->transp.length = 0;
838 var->nonstd = 0;
804 break; 839 break;
805 case 4: 840 case 4:
806 var->red.offset = 0; 841 var->red.offset = 0;
@@ -811,6 +846,7 @@ static int fb_check_var(struct fb_var_screeninfo *var,
811 var->blue.length = 4; 846 var->blue.length = 4;
812 var->transp.offset = 0; 847 var->transp.offset = 0;
813 var->transp.length = 0; 848 var->transp.length = 0;
849 var->nonstd = FB_NONSTD_REV_PIX_IN_B;
814 break; 850 break;
815 case 16: /* RGB 565 */ 851 case 16: /* RGB 565 */
816 var->red.offset = 11; 852 var->red.offset = 11;
@@ -821,6 +857,7 @@ static int fb_check_var(struct fb_var_screeninfo *var,
821 var->blue.length = 5; 857 var->blue.length = 5;
822 var->transp.offset = 0; 858 var->transp.offset = 0;
823 var->transp.length = 0; 859 var->transp.length = 0;
860 var->nonstd = 0;
824 break; 861 break;
825 default: 862 default:
826 err = -EINVAL; 863 err = -EINVAL;
@@ -840,11 +877,13 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
840 struct da8xx_fb_par *par; 877 struct da8xx_fb_par *par;
841 878
842 par = container_of(nb, struct da8xx_fb_par, freq_transition); 879 par = container_of(nb, struct da8xx_fb_par, freq_transition);
843 if (val == CPUFREQ_PRECHANGE) { 880 if (val == CPUFREQ_POSTCHANGE) {
844 lcd_disable_raster(); 881 if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) {
845 } else if (val == CPUFREQ_POSTCHANGE) { 882 par->lcd_fck_rate = clk_get_rate(par->lcdc_clk);
846 lcd_calc_clk_divider(par); 883 lcd_disable_raster();
847 lcd_enable_raster(); 884 lcd_calc_clk_divider(par);
885 lcd_enable_raster();
886 }
848 } 887 }
849 888
850 return 0; 889 return 0;
@@ -1048,6 +1087,22 @@ static struct fb_ops da8xx_fb_ops = {
1048 .fb_blank = cfb_blank, 1087 .fb_blank = cfb_blank,
1049}; 1088};
1050 1089
1090/* Calculate and return pixel clock period in pico seconds */
1091static unsigned int da8xxfb_pixel_clk_period(struct da8xx_fb_par *par)
1092{
1093 unsigned int lcd_clk, div;
1094 unsigned int configured_pix_clk;
1095 unsigned long long pix_clk_period_picosec = 1000000000000ULL;
1096
1097 lcd_clk = clk_get_rate(par->lcdc_clk);
1098 div = lcd_clk / par->pxl_clk;
1099 configured_pix_clk = (lcd_clk / div);
1100
1101 do_div(pix_clk_period_picosec, configured_pix_clk);
1102
1103 return pix_clk_period_picosec;
1104}
1105
1051static int __devinit fb_probe(struct platform_device *device) 1106static int __devinit fb_probe(struct platform_device *device)
1052{ 1107{
1053 struct da8xx_lcdc_platform_data *fb_pdata = 1108 struct da8xx_lcdc_platform_data *fb_pdata =
@@ -1137,6 +1192,9 @@ static int __devinit fb_probe(struct platform_device *device)
1137 1192
1138 par = da8xx_fb_info->par; 1193 par = da8xx_fb_info->par;
1139 par->lcdc_clk = fb_clk; 1194 par->lcdc_clk = fb_clk;
1195#ifdef CONFIG_CPU_FREQ
1196 par->lcd_fck_rate = clk_get_rate(fb_clk);
1197#endif
1140 par->pxl_clk = lcdc_info->pxl_clk; 1198 par->pxl_clk = lcdc_info->pxl_clk;
1141 if (fb_pdata->panel_power_ctrl) { 1199 if (fb_pdata->panel_power_ctrl) {
1142 par->panel_power_ctrl = fb_pdata->panel_power_ctrl; 1200 par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
@@ -1209,6 +1267,11 @@ static int __devinit fb_probe(struct platform_device *device)
1209 1267
1210 da8xx_fb_var.hsync_len = lcdc_info->hsw; 1268 da8xx_fb_var.hsync_len = lcdc_info->hsw;
1211 da8xx_fb_var.vsync_len = lcdc_info->vsw; 1269 da8xx_fb_var.vsync_len = lcdc_info->vsw;
1270 da8xx_fb_var.right_margin = lcdc_info->hfp;
1271 da8xx_fb_var.left_margin = lcdc_info->hbp;
1272 da8xx_fb_var.lower_margin = lcdc_info->vfp;
1273 da8xx_fb_var.upper_margin = lcdc_info->vbp;
1274 da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par);
1212 1275
1213 /* Initialize fbinfo */ 1276 /* Initialize fbinfo */
1214 da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT; 1277 da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
@@ -1264,8 +1327,8 @@ static int __devinit fb_probe(struct platform_device *device)
1264irq_freq: 1327irq_freq:
1265#ifdef CONFIG_CPU_FREQ 1328#ifdef CONFIG_CPU_FREQ
1266 lcd_da8xx_cpufreq_deregister(par); 1329 lcd_da8xx_cpufreq_deregister(par);
1267#endif
1268err_cpu_freq: 1330err_cpu_freq:
1331#endif
1269 unregister_framebuffer(da8xx_fb_info); 1332 unregister_framebuffer(da8xx_fb_info);
1270 1333
1271err_dealloc_cmap: 1334err_dealloc_cmap:
diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig
new file mode 100644
index 000000000000..1b035b2eb6b6
--- /dev/null
+++ b/drivers/video/exynos/Kconfig
@@ -0,0 +1,37 @@
1#
2# Exynos Video configuration
3#
4
5menuconfig EXYNOS_VIDEO
6 bool "Exynos Video driver support"
7 help
8 This enables support for EXYNOS Video device.
9
10if EXYNOS_VIDEO
11
12#
13# MIPI DSI driver
14#
15
16config EXYNOS_MIPI_DSI
17 bool "EXYNOS MIPI DSI driver support."
18 depends on ARCH_S5PV210 || ARCH_EXYNOS
19 help
20 This enables support for MIPI-DSI device.
21
22config EXYNOS_LCD_S6E8AX0
23 bool "S6E8AX0 MIPI AMOLED LCD Driver"
24 depends on (EXYNOS_MIPI_DSI && BACKLIGHT_CLASS_DEVICE && LCD_CLASS_DEVICE)
25 default n
26 help
27 If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its
28 LCD control driver.
29
30config EXYNOS_DP
31 bool "EXYNOS DP driver support"
32 depends on ARCH_EXYNOS
33 default n
34 help
35 This enables support for DP device.
36
37endif # EXYNOS_VIDEO
diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile
new file mode 100644
index 000000000000..ec7772e452a9
--- /dev/null
+++ b/drivers/video/exynos/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for the exynos video drivers.
3#
4
5obj-$(CONFIG_EXYNOS_MIPI_DSI) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \
6 exynos_mipi_dsi_lowlevel.o
7obj-$(CONFIG_EXYNOS_LCD_S6E8AX0) += s6e8ax0.o
8obj-$(CONFIG_EXYNOS_DP) += exynos_dp_core.o exynos_dp_reg.o
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
new file mode 100644
index 000000000000..2a4481cf260c
--- /dev/null
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -0,0 +1,1058 @@
1/*
2 * Samsung SoC DP (Display Port) interface driver.
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/slab.h>
16#include <linux/err.h>
17#include <linux/clk.h>
18#include <linux/io.h>
19#include <linux/interrupt.h>
20#include <linux/delay.h>
21
22#include <video/exynos_dp.h>
23
24#include <plat/cpu.h>
25
26#include "exynos_dp_core.h"
27
28static int exynos_dp_init_dp(struct exynos_dp_device *dp)
29{
30 exynos_dp_reset(dp);
31
32 /* SW defined function Normal operation */
33 exynos_dp_enable_sw_function(dp);
34
35 exynos_dp_config_interrupt(dp);
36 exynos_dp_init_analog_func(dp);
37
38 exynos_dp_init_hpd(dp);
39 exynos_dp_init_aux(dp);
40
41 return 0;
42}
43
44static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
45{
46 int timeout_loop = 0;
47
48 exynos_dp_init_hpd(dp);
49
50 udelay(200);
51
52 while (exynos_dp_get_plug_in_status(dp) != 0) {
53 timeout_loop++;
54 if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
55 dev_err(dp->dev, "failed to get hpd plug status\n");
56 return -ETIMEDOUT;
57 }
58 udelay(10);
59 }
60
61 return 0;
62}
63
64static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data)
65{
66 int i;
67 unsigned char sum = 0;
68
69 for (i = 0; i < EDID_BLOCK_LENGTH; i++)
70 sum = sum + edid_data[i];
71
72 return sum;
73}
74
75static int exynos_dp_read_edid(struct exynos_dp_device *dp)
76{
77 unsigned char edid[EDID_BLOCK_LENGTH * 2];
78 unsigned int extend_block = 0;
79 unsigned char sum;
80 unsigned char test_vector;
81 int retval;
82
83 /*
84 * EDID device address is 0x50.
85 * However, if necessary, you must have set upper address
86 * into E-EDID in I2C device, 0x30.
87 */
88
89 /* Read Extension Flag, Number of 128-byte EDID extension blocks */
90 exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
91 EDID_EXTENSION_FLAG,
92 &extend_block);
93
94 if (extend_block > 0) {
95 dev_dbg(dp->dev, "EDID data includes a single extension!\n");
96
97 /* Read EDID data */
98 retval = exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
99 EDID_HEADER_PATTERN,
100 EDID_BLOCK_LENGTH,
101 &edid[EDID_HEADER_PATTERN]);
102 if (retval != 0) {
103 dev_err(dp->dev, "EDID Read failed!\n");
104 return -EIO;
105 }
106 sum = exynos_dp_calc_edid_check_sum(edid);
107 if (sum != 0) {
108 dev_err(dp->dev, "EDID bad checksum!\n");
109 return -EIO;
110 }
111
112 /* Read additional EDID data */
113 retval = exynos_dp_read_bytes_from_i2c(dp,
114 I2C_EDID_DEVICE_ADDR,
115 EDID_BLOCK_LENGTH,
116 EDID_BLOCK_LENGTH,
117 &edid[EDID_BLOCK_LENGTH]);
118 if (retval != 0) {
119 dev_err(dp->dev, "EDID Read failed!\n");
120 return -EIO;
121 }
122 sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
123 if (sum != 0) {
124 dev_err(dp->dev, "EDID bad checksum!\n");
125 return -EIO;
126 }
127
128 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TEST_REQUEST,
129 &test_vector);
130 if (test_vector & DPCD_TEST_EDID_READ) {
131 exynos_dp_write_byte_to_dpcd(dp,
132 DPCD_ADDR_TEST_EDID_CHECKSUM,
133 edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
134 exynos_dp_write_byte_to_dpcd(dp,
135 DPCD_ADDR_TEST_RESPONSE,
136 DPCD_TEST_EDID_CHECKSUM_WRITE);
137 }
138 } else {
139 dev_info(dp->dev, "EDID data does not include any extensions.\n");
140
141 /* Read EDID data */
142 retval = exynos_dp_read_bytes_from_i2c(dp,
143 I2C_EDID_DEVICE_ADDR,
144 EDID_HEADER_PATTERN,
145 EDID_BLOCK_LENGTH,
146 &edid[EDID_HEADER_PATTERN]);
147 if (retval != 0) {
148 dev_err(dp->dev, "EDID Read failed!\n");
149 return -EIO;
150 }
151 sum = exynos_dp_calc_edid_check_sum(edid);
152 if (sum != 0) {
153 dev_err(dp->dev, "EDID bad checksum!\n");
154 return -EIO;
155 }
156
157 exynos_dp_read_byte_from_dpcd(dp,
158 DPCD_ADDR_TEST_REQUEST,
159 &test_vector);
160 if (test_vector & DPCD_TEST_EDID_READ) {
161 exynos_dp_write_byte_to_dpcd(dp,
162 DPCD_ADDR_TEST_EDID_CHECKSUM,
163 edid[EDID_CHECKSUM]);
164 exynos_dp_write_byte_to_dpcd(dp,
165 DPCD_ADDR_TEST_RESPONSE,
166 DPCD_TEST_EDID_CHECKSUM_WRITE);
167 }
168 }
169
170 dev_err(dp->dev, "EDID Read success!\n");
171 return 0;
172}
173
174static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
175{
176 u8 buf[12];
177 int i;
178 int retval;
179
180 /* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
181 exynos_dp_read_bytes_from_dpcd(dp,
182 DPCD_ADDR_DPCD_REV,
183 12, buf);
184
185 /* Read EDID */
186 for (i = 0; i < 3; i++) {
187 retval = exynos_dp_read_edid(dp);
188 if (retval == 0)
189 break;
190 }
191
192 return retval;
193}
194
195static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp,
196 bool enable)
197{
198 u8 data;
199
200 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data);
201
202 if (enable)
203 exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
204 DPCD_ENHANCED_FRAME_EN |
205 DPCD_LANE_COUNT_SET(data));
206 else
207 exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
208 DPCD_LANE_COUNT_SET(data));
209}
210
211static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp)
212{
213 u8 data;
214 int retval;
215
216 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
217 retval = DPCD_ENHANCED_FRAME_CAP(data);
218
219 return retval;
220}
221
222static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
223{
224 u8 data;
225
226 data = exynos_dp_is_enhanced_mode_available(dp);
227 exynos_dp_enable_rx_to_enhanced_mode(dp, data);
228 exynos_dp_enable_enhanced_mode(dp, data);
229}
230
231static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
232{
233 exynos_dp_set_training_pattern(dp, DP_NONE);
234
235 exynos_dp_write_byte_to_dpcd(dp,
236 DPCD_ADDR_TRAINING_PATTERN_SET,
237 DPCD_TRAINING_PATTERN_DISABLED);
238}
239
240static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
241 int pre_emphasis, int lane)
242{
243 switch (lane) {
244 case 0:
245 exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
246 break;
247 case 1:
248 exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
249 break;
250
251 case 2:
252 exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
253 break;
254
255 case 3:
256 exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
257 break;
258 }
259}
260
261static void exynos_dp_link_start(struct exynos_dp_device *dp)
262{
263 u8 buf[5];
264 int lane;
265 int lane_count;
266
267 lane_count = dp->link_train.lane_count;
268
269 dp->link_train.lt_state = CLOCK_RECOVERY;
270 dp->link_train.eq_loop = 0;
271
272 for (lane = 0; lane < lane_count; lane++)
273 dp->link_train.cr_loop[lane] = 0;
274
275 /* Set sink to D0 (Sink Not Ready) mode. */
276 exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
277 DPCD_SET_POWER_STATE_D0);
278
279 /* Set link rate and count as you want to establish*/
280 exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
281 exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
282
283 /* Setup RX configuration */
284 buf[0] = dp->link_train.link_rate;
285 buf[1] = dp->link_train.lane_count;
286 exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
287 2, buf);
288
289 /* Set TX pre-emphasis to minimum */
290 for (lane = 0; lane < lane_count; lane++)
291 exynos_dp_set_lane_lane_pre_emphasis(dp,
292 PRE_EMPHASIS_LEVEL_0, lane);
293
294 /* Set training pattern 1 */
295 exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
296
297 /* Set RX training pattern */
298 buf[0] = DPCD_SCRAMBLING_DISABLED |
299 DPCD_TRAINING_PATTERN_1;
300 exynos_dp_write_byte_to_dpcd(dp,
301 DPCD_ADDR_TRAINING_PATTERN_SET, buf[0]);
302
303 for (lane = 0; lane < lane_count; lane++)
304 buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
305 DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
306 exynos_dp_write_bytes_to_dpcd(dp,
307 DPCD_ADDR_TRAINING_PATTERN_SET,
308 lane_count, buf);
309}
310
311static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
312{
313 int shift = (lane & 1) * 4;
314 u8 link_value = link_status[lane>>1];
315
316 return (link_value >> shift) & 0xf;
317}
318
319static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
320{
321 int lane;
322 u8 lane_status;
323
324 for (lane = 0; lane < lane_count; lane++) {
325 lane_status = exynos_dp_get_lane_status(link_status, lane);
326 if ((lane_status & DPCD_LANE_CR_DONE) == 0)
327 return -EINVAL;
328 }
329 return 0;
330}
331
332static int exynos_dp_channel_eq_ok(u8 link_status[6], int lane_count)
333{
334 int lane;
335 u8 lane_align;
336 u8 lane_status;
337
338 lane_align = link_status[2];
339 if ((lane_align == DPCD_INTERLANE_ALIGN_DONE) == 0)
340 return -EINVAL;
341
342 for (lane = 0; lane < lane_count; lane++) {
343 lane_status = exynos_dp_get_lane_status(link_status, lane);
344 lane_status &= DPCD_CHANNEL_EQ_BITS;
345 if (lane_status != DPCD_CHANNEL_EQ_BITS)
346 return -EINVAL;
347 }
348 return 0;
349}
350
351static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2],
352 int lane)
353{
354 int shift = (lane & 1) * 4;
355 u8 link_value = adjust_request[lane>>1];
356
357 return (link_value >> shift) & 0x3;
358}
359
360static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
361 u8 adjust_request[2],
362 int lane)
363{
364 int shift = (lane & 1) * 4;
365 u8 link_value = adjust_request[lane>>1];
366
367 return ((link_value >> shift) & 0xc) >> 2;
368}
369
370static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
371 u8 training_lane_set, int lane)
372{
373 switch (lane) {
374 case 0:
375 exynos_dp_set_lane0_link_training(dp, training_lane_set);
376 break;
377 case 1:
378 exynos_dp_set_lane1_link_training(dp, training_lane_set);
379 break;
380
381 case 2:
382 exynos_dp_set_lane2_link_training(dp, training_lane_set);
383 break;
384
385 case 3:
386 exynos_dp_set_lane3_link_training(dp, training_lane_set);
387 break;
388 }
389}
390
391static unsigned int exynos_dp_get_lane_link_training(
392 struct exynos_dp_device *dp,
393 int lane)
394{
395 u32 reg;
396
397 switch (lane) {
398 case 0:
399 reg = exynos_dp_get_lane0_link_training(dp);
400 break;
401 case 1:
402 reg = exynos_dp_get_lane1_link_training(dp);
403 break;
404 case 2:
405 reg = exynos_dp_get_lane2_link_training(dp);
406 break;
407 case 3:
408 reg = exynos_dp_get_lane3_link_training(dp);
409 break;
410 }
411
412 return reg;
413}
414
415static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
416{
417 if (dp->link_train.link_rate == LINK_RATE_2_70GBPS) {
418 /* set to reduced bit rate */
419 dp->link_train.link_rate = LINK_RATE_1_62GBPS;
420 dev_err(dp->dev, "set to bandwidth %.2x\n",
421 dp->link_train.link_rate);
422 dp->link_train.lt_state = START;
423 } else {
424 exynos_dp_training_pattern_dis(dp);
425 /* set enhanced mode if available */
426 exynos_dp_set_enhanced_mode(dp);
427 dp->link_train.lt_state = FAILED;
428 }
429}
430
431static void exynos_dp_get_adjust_train(struct exynos_dp_device *dp,
432 u8 adjust_request[2])
433{
434 int lane;
435 int lane_count;
436 u8 voltage_swing;
437 u8 pre_emphasis;
438 u8 training_lane;
439
440 lane_count = dp->link_train.lane_count;
441 for (lane = 0; lane < lane_count; lane++) {
442 voltage_swing = exynos_dp_get_adjust_request_voltage(
443 adjust_request, lane);
444 pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
445 adjust_request, lane);
446 training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
447 DPCD_PRE_EMPHASIS_SET(pre_emphasis);
448
449 if (voltage_swing == VOLTAGE_LEVEL_3 ||
450 pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
451 training_lane |= DPCD_MAX_SWING_REACHED;
452 training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
453 }
454 dp->link_train.training_lane[lane] = training_lane;
455 }
456}
457
458static int exynos_dp_check_max_cr_loop(struct exynos_dp_device *dp,
459 u8 voltage_swing)
460{
461 int lane;
462 int lane_count;
463
464 lane_count = dp->link_train.lane_count;
465 for (lane = 0; lane < lane_count; lane++) {
466 if (voltage_swing == VOLTAGE_LEVEL_3 ||
467 dp->link_train.cr_loop[lane] == MAX_CR_LOOP)
468 return -EINVAL;
469 }
470 return 0;
471}
472
473static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
474{
475 u8 data;
476 u8 link_status[6];
477 int lane;
478 int lane_count;
479 u8 buf[5];
480
481 u8 *adjust_request;
482 u8 voltage_swing;
483 u8 pre_emphasis;
484 u8 training_lane;
485
486 udelay(100);
487
488 exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
489 6, link_status);
490 lane_count = dp->link_train.lane_count;
491
492 if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
493 /* set training pattern 2 for EQ */
494 exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
495
496 adjust_request = link_status + (DPCD_ADDR_ADJUST_REQUEST_LANE0_1
497 - DPCD_ADDR_LANE0_1_STATUS);
498
499 exynos_dp_get_adjust_train(dp, adjust_request);
500
501 buf[0] = DPCD_SCRAMBLING_DISABLED |
502 DPCD_TRAINING_PATTERN_2;
503 exynos_dp_write_byte_to_dpcd(dp,
504 DPCD_ADDR_TRAINING_LANE0_SET,
505 buf[0]);
506
507 for (lane = 0; lane < lane_count; lane++) {
508 exynos_dp_set_lane_link_training(dp,
509 dp->link_train.training_lane[lane],
510 lane);
511 buf[lane] = dp->link_train.training_lane[lane];
512 exynos_dp_write_byte_to_dpcd(dp,
513 DPCD_ADDR_TRAINING_LANE0_SET + lane,
514 buf[lane]);
515 }
516 dp->link_train.lt_state = EQUALIZER_TRAINING;
517 } else {
518 exynos_dp_read_byte_from_dpcd(dp,
519 DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
520 &data);
521 adjust_request[0] = data;
522
523 exynos_dp_read_byte_from_dpcd(dp,
524 DPCD_ADDR_ADJUST_REQUEST_LANE2_3,
525 &data);
526 adjust_request[1] = data;
527
528 for (lane = 0; lane < lane_count; lane++) {
529 training_lane = exynos_dp_get_lane_link_training(
530 dp, lane);
531 voltage_swing = exynos_dp_get_adjust_request_voltage(
532 adjust_request, lane);
533 pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
534 adjust_request, lane);
535 if ((DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing) &&
536 (DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis))
537 dp->link_train.cr_loop[lane]++;
538 dp->link_train.training_lane[lane] = training_lane;
539 }
540
541 if (exynos_dp_check_max_cr_loop(dp, voltage_swing) != 0) {
542 exynos_dp_reduce_link_rate(dp);
543 } else {
544 exynos_dp_get_adjust_train(dp, adjust_request);
545
546 for (lane = 0; lane < lane_count; lane++) {
547 exynos_dp_set_lane_link_training(dp,
548 dp->link_train.training_lane[lane],
549 lane);
550 buf[lane] = dp->link_train.training_lane[lane];
551 exynos_dp_write_byte_to_dpcd(dp,
552 DPCD_ADDR_TRAINING_LANE0_SET + lane,
553 buf[lane]);
554 }
555 }
556 }
557
558 return 0;
559}
560
561static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
562{
563 u8 link_status[6];
564 int lane;
565 int lane_count;
566 u8 buf[5];
567 u32 reg;
568
569 u8 *adjust_request;
570
571 udelay(400);
572
573 exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
574 6, link_status);
575 lane_count = dp->link_train.lane_count;
576
577 if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
578 adjust_request = link_status + (DPCD_ADDR_ADJUST_REQUEST_LANE0_1
579 - DPCD_ADDR_LANE0_1_STATUS);
580
581 if (exynos_dp_channel_eq_ok(link_status, lane_count) == 0) {
582 /* traing pattern Set to Normal */
583 exynos_dp_training_pattern_dis(dp);
584
585 dev_info(dp->dev, "Link Training success!\n");
586
587 exynos_dp_get_link_bandwidth(dp, &reg);
588 dp->link_train.link_rate = reg;
589 dev_dbg(dp->dev, "final bandwidth = %.2x\n",
590 dp->link_train.link_rate);
591
592 exynos_dp_get_lane_count(dp, &reg);
593 dp->link_train.lane_count = reg;
594 dev_dbg(dp->dev, "final lane count = %.2x\n",
595 dp->link_train.lane_count);
596 /* set enhanced mode if available */
597 exynos_dp_set_enhanced_mode(dp);
598
599 dp->link_train.lt_state = FINISHED;
600 } else {
601 /* not all locked */
602 dp->link_train.eq_loop++;
603
604 if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
605 exynos_dp_reduce_link_rate(dp);
606 } else {
607 exynos_dp_get_adjust_train(dp, adjust_request);
608
609 for (lane = 0; lane < lane_count; lane++) {
610 exynos_dp_set_lane_link_training(dp,
611 dp->link_train.training_lane[lane],
612 lane);
613 buf[lane] = dp->link_train.training_lane[lane];
614 exynos_dp_write_byte_to_dpcd(dp,
615 DPCD_ADDR_TRAINING_LANE0_SET + lane,
616 buf[lane]);
617 }
618 }
619 }
620 } else {
621 exynos_dp_reduce_link_rate(dp);
622 }
623
624 return 0;
625}
626
627static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
628 u8 *bandwidth)
629{
630 u8 data;
631
632 /*
633 * For DP rev.1.1, Maximum link rate of Main Link lanes
634 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
635 */
636 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
637 *bandwidth = data;
638}
639
640static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
641 u8 *lane_count)
642{
643 u8 data;
644
645 /*
646 * For DP rev.1.1, Maximum number of Main Link lanes
647 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
648 */
649 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
650 *lane_count = DPCD_MAX_LANE_COUNT(data);
651}
652
653static void exynos_dp_init_training(struct exynos_dp_device *dp,
654 enum link_lane_count_type max_lane,
655 enum link_rate_type max_rate)
656{
657 /*
658 * MACRO_RST must be applied after the PLL_LOCK to avoid
659 * the DP inter pair skew issue for at least 10 us
660 */
661 exynos_dp_reset_macro(dp);
662
663 /* Initialize by reading RX's DPCD */
664 exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
665 exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
666
667 if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
668 (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
669 dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
670 dp->link_train.link_rate);
671 dp->link_train.link_rate = LINK_RATE_1_62GBPS;
672 }
673
674 if (dp->link_train.lane_count == 0) {
675 dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
676 dp->link_train.lane_count);
677 dp->link_train.lane_count = (u8)LANE_COUNT1;
678 }
679
680 /* Setup TX lane count & rate */
681 if (dp->link_train.lane_count > max_lane)
682 dp->link_train.lane_count = max_lane;
683 if (dp->link_train.link_rate > max_rate)
684 dp->link_train.link_rate = max_rate;
685
686 /* All DP analog module power up */
687 exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
688}
689
690static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
691{
692 int retval = 0;
693 int training_finished;
694
695 /* Turn off unnecessary lane */
696 if (dp->link_train.lane_count == 1)
697 exynos_dp_set_analog_power_down(dp, CH1_BLOCK, 1);
698
699 training_finished = 0;
700
701 dp->link_train.lt_state = START;
702
703 /* Process here */
704 while (!training_finished) {
705 switch (dp->link_train.lt_state) {
706 case START:
707 exynos_dp_link_start(dp);
708 break;
709 case CLOCK_RECOVERY:
710 exynos_dp_process_clock_recovery(dp);
711 break;
712 case EQUALIZER_TRAINING:
713 exynos_dp_process_equalizer_training(dp);
714 break;
715 case FINISHED:
716 training_finished = 1;
717 break;
718 case FAILED:
719 return -EREMOTEIO;
720 }
721 }
722
723 return retval;
724}
725
726static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
727 u32 count,
728 u32 bwtype)
729{
730 int i;
731 int retval;
732
733 for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
734 exynos_dp_init_training(dp, count, bwtype);
735 retval = exynos_dp_sw_link_training(dp);
736 if (retval == 0)
737 break;
738
739 udelay(100);
740 }
741
742 return retval;
743}
744
745static int exynos_dp_config_video(struct exynos_dp_device *dp,
746 struct video_info *video_info)
747{
748 int retval = 0;
749 int timeout_loop = 0;
750 int done_count = 0;
751
752 exynos_dp_config_video_slave_mode(dp, video_info);
753
754 exynos_dp_set_video_color_format(dp, video_info->color_depth,
755 video_info->color_space,
756 video_info->dynamic_range,
757 video_info->ycbcr_coeff);
758
759 if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
760 dev_err(dp->dev, "PLL is not locked yet.\n");
761 return -EINVAL;
762 }
763
764 for (;;) {
765 timeout_loop++;
766 if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
767 break;
768 if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
769 dev_err(dp->dev, "Timeout of video streamclk ok\n");
770 return -ETIMEDOUT;
771 }
772
773 mdelay(100);
774 }
775
776 /* Set to use the register calculated M/N video */
777 exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
778
779 /* For video bist, Video timing must be generated by register */
780 exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
781
782 /* Disable video mute */
783 exynos_dp_enable_video_mute(dp, 0);
784
785 /* Configure video slave mode */
786 exynos_dp_enable_video_master(dp, 0);
787
788 /* Enable video */
789 exynos_dp_start_video(dp);
790
791 timeout_loop = 0;
792
793 for (;;) {
794 timeout_loop++;
795 if (exynos_dp_is_video_stream_on(dp) == 0) {
796 done_count++;
797 if (done_count > 10)
798 break;
799 } else if (done_count) {
800 done_count = 0;
801 }
802 if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
803 dev_err(dp->dev, "Timeout of video streamclk ok\n");
804 return -ETIMEDOUT;
805 }
806
807 mdelay(100);
808 }
809
810 if (retval != 0)
811 dev_err(dp->dev, "Video stream is not detected!\n");
812
813 return retval;
814}
815
816static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable)
817{
818 u8 data;
819
820 if (enable) {
821 exynos_dp_enable_scrambling(dp);
822
823 exynos_dp_read_byte_from_dpcd(dp,
824 DPCD_ADDR_TRAINING_PATTERN_SET,
825 &data);
826 exynos_dp_write_byte_to_dpcd(dp,
827 DPCD_ADDR_TRAINING_PATTERN_SET,
828 (u8)(data & ~DPCD_SCRAMBLING_DISABLED));
829 } else {
830 exynos_dp_disable_scrambling(dp);
831
832 exynos_dp_read_byte_from_dpcd(dp,
833 DPCD_ADDR_TRAINING_PATTERN_SET,
834 &data);
835 exynos_dp_write_byte_to_dpcd(dp,
836 DPCD_ADDR_TRAINING_PATTERN_SET,
837 (u8)(data | DPCD_SCRAMBLING_DISABLED));
838 }
839}
840
841static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
842{
843 struct exynos_dp_device *dp = arg;
844
845 dev_err(dp->dev, "exynos_dp_irq_handler\n");
846 return IRQ_HANDLED;
847}
848
849static int __devinit exynos_dp_probe(struct platform_device *pdev)
850{
851 struct resource *res;
852 struct exynos_dp_device *dp;
853 struct exynos_dp_platdata *pdata;
854
855 int ret = 0;
856
857 pdata = pdev->dev.platform_data;
858 if (!pdata) {
859 dev_err(&pdev->dev, "no platform data\n");
860 return -EINVAL;
861 }
862
863 dp = kzalloc(sizeof(struct exynos_dp_device), GFP_KERNEL);
864 if (!dp) {
865 dev_err(&pdev->dev, "no memory for device data\n");
866 return -ENOMEM;
867 }
868
869 dp->dev = &pdev->dev;
870
871 dp->clock = clk_get(&pdev->dev, "dp");
872 if (IS_ERR(dp->clock)) {
873 dev_err(&pdev->dev, "failed to get clock\n");
874 ret = PTR_ERR(dp->clock);
875 goto err_dp;
876 }
877
878 clk_enable(dp->clock);
879
880 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
881 if (!res) {
882 dev_err(&pdev->dev, "failed to get registers\n");
883 ret = -EINVAL;
884 goto err_clock;
885 }
886
887 res = request_mem_region(res->start, resource_size(res),
888 dev_name(&pdev->dev));
889 if (!res) {
890 dev_err(&pdev->dev, "failed to request registers region\n");
891 ret = -EINVAL;
892 goto err_clock;
893 }
894
895 dp->res = res;
896
897 dp->reg_base = ioremap(res->start, resource_size(res));
898 if (!dp->reg_base) {
899 dev_err(&pdev->dev, "failed to ioremap\n");
900 ret = -ENOMEM;
901 goto err_req_region;
902 }
903
904 dp->irq = platform_get_irq(pdev, 0);
905 if (!dp->irq) {
906 dev_err(&pdev->dev, "failed to get irq\n");
907 ret = -ENODEV;
908 goto err_ioremap;
909 }
910
911 ret = request_irq(dp->irq, exynos_dp_irq_handler, 0,
912 "exynos-dp", dp);
913 if (ret) {
914 dev_err(&pdev->dev, "failed to request irq\n");
915 goto err_ioremap;
916 }
917
918 dp->video_info = pdata->video_info;
919 if (pdata->phy_init)
920 pdata->phy_init();
921
922 exynos_dp_init_dp(dp);
923
924 ret = exynos_dp_detect_hpd(dp);
925 if (ret) {
926 dev_err(&pdev->dev, "unable to detect hpd\n");
927 goto err_irq;
928 }
929
930 exynos_dp_handle_edid(dp);
931
932 ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
933 dp->video_info->link_rate);
934 if (ret) {
935 dev_err(&pdev->dev, "unable to do link train\n");
936 goto err_irq;
937 }
938
939 exynos_dp_enable_scramble(dp, 1);
940 exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
941 exynos_dp_enable_enhanced_mode(dp, 1);
942
943 exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
944 exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
945
946 exynos_dp_init_video(dp);
947 ret = exynos_dp_config_video(dp, dp->video_info);
948 if (ret) {
949 dev_err(&pdev->dev, "unable to config video\n");
950 goto err_irq;
951 }
952
953 platform_set_drvdata(pdev, dp);
954
955 return 0;
956
957err_irq:
958 free_irq(dp->irq, dp);
959err_ioremap:
960 iounmap(dp->reg_base);
961err_req_region:
962 release_mem_region(res->start, resource_size(res));
963err_clock:
964 clk_put(dp->clock);
965err_dp:
966 kfree(dp);
967
968 return ret;
969}
970
971static int __devexit exynos_dp_remove(struct platform_device *pdev)
972{
973 struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
974 struct exynos_dp_device *dp = platform_get_drvdata(pdev);
975
976 if (pdata && pdata->phy_exit)
977 pdata->phy_exit();
978
979 free_irq(dp->irq, dp);
980 iounmap(dp->reg_base);
981
982 clk_disable(dp->clock);
983 clk_put(dp->clock);
984
985 release_mem_region(dp->res->start, resource_size(dp->res));
986
987 kfree(dp);
988
989 return 0;
990}
991
992#ifdef CONFIG_PM_SLEEP
993static int exynos_dp_suspend(struct device *dev)
994{
995 struct platform_device *pdev = to_platform_device(dev);
996 struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
997 struct exynos_dp_device *dp = platform_get_drvdata(pdev);
998
999 if (pdata && pdata->phy_exit)
1000 pdata->phy_exit();
1001
1002 clk_disable(dp->clock);
1003
1004 return 0;
1005}
1006
1007static int exynos_dp_resume(struct device *dev)
1008{
1009 struct platform_device *pdev = to_platform_device(dev);
1010 struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
1011 struct exynos_dp_device *dp = platform_get_drvdata(pdev);
1012
1013 if (pdata && pdata->phy_init)
1014 pdata->phy_init();
1015
1016 clk_enable(dp->clock);
1017
1018 exynos_dp_init_dp(dp);
1019
1020 exynos_dp_detect_hpd(dp);
1021 exynos_dp_handle_edid(dp);
1022
1023 exynos_dp_set_link_train(dp, dp->video_info->lane_count,
1024 dp->video_info->link_rate);
1025
1026 exynos_dp_enable_scramble(dp, 1);
1027 exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
1028 exynos_dp_enable_enhanced_mode(dp, 1);
1029
1030 exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
1031 exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
1032
1033 exynos_dp_init_video(dp);
1034 exynos_dp_config_video(dp, dp->video_info);
1035
1036 return 0;
1037}
1038#endif
1039
1040static const struct dev_pm_ops exynos_dp_pm_ops = {
1041 SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
1042};
1043
1044static struct platform_driver exynos_dp_driver = {
1045 .probe = exynos_dp_probe,
1046 .remove = __devexit_p(exynos_dp_remove),
1047 .driver = {
1048 .name = "exynos-dp",
1049 .owner = THIS_MODULE,
1050 .pm = &exynos_dp_pm_ops,
1051 },
1052};
1053
1054module_platform_driver(exynos_dp_driver);
1055
1056MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
1057MODULE_DESCRIPTION("Samsung SoC DP Driver");
1058MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
new file mode 100644
index 000000000000..90ceaca0fa24
--- /dev/null
+++ b/drivers/video/exynos/exynos_dp_core.h
@@ -0,0 +1,206 @@
1/*
2 * Header file for Samsung DP (Display Port) interface driver.
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#ifndef _EXYNOS_DP_CORE_H
14#define _EXYNOS_DP_CORE_H
15
16struct link_train {
17 int eq_loop;
18 int cr_loop[4];
19
20 u8 link_rate;
21 u8 lane_count;
22 u8 training_lane[4];
23
24 enum link_training_state lt_state;
25};
26
27struct exynos_dp_device {
28 struct device *dev;
29 struct resource *res;
30 struct clk *clock;
31 unsigned int irq;
32 void __iomem *reg_base;
33
34 struct video_info *video_info;
35 struct link_train link_train;
36};
37
38/* exynos_dp_reg.c */
39void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable);
40void exynos_dp_stop_video(struct exynos_dp_device *dp);
41void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
42void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
43void exynos_dp_reset(struct exynos_dp_device *dp);
44void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
45u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
46void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
47void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
48 enum analog_power_block block,
49 bool enable);
50void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
51void exynos_dp_init_hpd(struct exynos_dp_device *dp);
52void exynos_dp_reset_aux(struct exynos_dp_device *dp);
53void exynos_dp_init_aux(struct exynos_dp_device *dp);
54int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
55void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
56int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
57int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
58 unsigned int reg_addr,
59 unsigned char data);
60int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
61 unsigned int reg_addr,
62 unsigned char *data);
63int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
64 unsigned int reg_addr,
65 unsigned int count,
66 unsigned char data[]);
67int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
68 unsigned int reg_addr,
69 unsigned int count,
70 unsigned char data[]);
71int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
72 unsigned int device_addr,
73 unsigned int reg_addr);
74int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
75 unsigned int device_addr,
76 unsigned int reg_addr,
77 unsigned int *data);
78int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
79 unsigned int device_addr,
80 unsigned int reg_addr,
81 unsigned int count,
82 unsigned char edid[]);
83void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
84void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
85void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
86void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
87void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
88void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
89void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
90void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
91void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable);
92void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
93 enum pattern_set pattern);
94void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level);
95void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level);
96void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level);
97void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level);
98void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
99 u32 training_lane);
100void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
101 u32 training_lane);
102void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
103 u32 training_lane);
104void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
105 u32 training_lane);
106u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
107u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
108u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
109u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
110void exynos_dp_reset_macro(struct exynos_dp_device *dp);
111int exynos_dp_init_video(struct exynos_dp_device *dp);
112
113void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
114 u32 color_depth,
115 u32 color_space,
116 u32 dynamic_range,
117 u32 ycbcr_coeff);
118int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
119void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
120 enum clock_recovery_m_value_type type,
121 u32 m_value,
122 u32 n_value);
123void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
124void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
125void exynos_dp_start_video(struct exynos_dp_device *dp);
126int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
127void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
128 struct video_info *video_info);
129void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
130void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
131
132/* I2C EDID Chip ID, Slave Address */
133#define I2C_EDID_DEVICE_ADDR 0x50
134#define I2C_E_EDID_DEVICE_ADDR 0x30
135
136#define EDID_BLOCK_LENGTH 0x80
137#define EDID_HEADER_PATTERN 0x00
138#define EDID_EXTENSION_FLAG 0x7e
139#define EDID_CHECKSUM 0x7f
140
141/* Definition for DPCD Register */
142#define DPCD_ADDR_DPCD_REV 0x0000
143#define DPCD_ADDR_MAX_LINK_RATE 0x0001
144#define DPCD_ADDR_MAX_LANE_COUNT 0x0002
145#define DPCD_ADDR_LINK_BW_SET 0x0100
146#define DPCD_ADDR_LANE_COUNT_SET 0x0101
147#define DPCD_ADDR_TRAINING_PATTERN_SET 0x0102
148#define DPCD_ADDR_TRAINING_LANE0_SET 0x0103
149#define DPCD_ADDR_LANE0_1_STATUS 0x0202
150#define DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED 0x0204
151#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1 0x0206
152#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3 0x0207
153#define DPCD_ADDR_TEST_REQUEST 0x0218
154#define DPCD_ADDR_TEST_RESPONSE 0x0260
155#define DPCD_ADDR_TEST_EDID_CHECKSUM 0x0261
156#define DPCD_ADDR_SINK_POWER_STATE 0x0600
157
158/* DPCD_ADDR_MAX_LANE_COUNT */
159#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1)
160#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f)
161
162/* DPCD_ADDR_LANE_COUNT_SET */
163#define DPCD_ENHANCED_FRAME_EN (0x1 << 7)
164#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f)
165
166/* DPCD_ADDR_TRAINING_PATTERN_SET */
167#define DPCD_SCRAMBLING_DISABLED (0x1 << 5)
168#define DPCD_SCRAMBLING_ENABLED (0x0 << 5)
169#define DPCD_TRAINING_PATTERN_2 (0x2 << 0)
170#define DPCD_TRAINING_PATTERN_1 (0x1 << 0)
171#define DPCD_TRAINING_PATTERN_DISABLED (0x0 << 0)
172
173/* DPCD_ADDR_TRAINING_LANE0_SET */
174#define DPCD_MAX_PRE_EMPHASIS_REACHED (0x1 << 5)
175#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3)
176#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3)
177#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 (0x0 << 3)
178#define DPCD_MAX_SWING_REACHED (0x1 << 2)
179#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0)
180#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3)
181#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0 (0x0 << 0)
182
183/* DPCD_ADDR_LANE0_1_STATUS */
184#define DPCD_LANE_SYMBOL_LOCKED (0x1 << 2)
185#define DPCD_LANE_CHANNEL_EQ_DONE (0x1 << 1)
186#define DPCD_LANE_CR_DONE (0x1 << 0)
187#define DPCD_CHANNEL_EQ_BITS (DPCD_LANE_CR_DONE| \
188 DPCD_LANE_CHANNEL_EQ_DONE|\
189 DPCD_LANE_SYMBOL_LOCKED)
190
191/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
192#define DPCD_LINK_STATUS_UPDATED (0x1 << 7)
193#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED (0x1 << 6)
194#define DPCD_INTERLANE_ALIGN_DONE (0x1 << 0)
195
196/* DPCD_ADDR_TEST_REQUEST */
197#define DPCD_TEST_EDID_READ (0x1 << 2)
198
199/* DPCD_ADDR_TEST_RESPONSE */
200#define DPCD_TEST_EDID_CHECKSUM_WRITE (0x1 << 2)
201
202/* DPCD_ADDR_SINK_POWER_STATE */
203#define DPCD_SET_POWER_STATE_D0 (0x1 << 0)
204#define DPCD_SET_POWER_STATE_D4 (0x2 << 0)
205
206#endif /* _EXYNOS_DP_CORE_H */
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c
new file mode 100644
index 000000000000..6548afa0e3d2
--- /dev/null
+++ b/drivers/video/exynos/exynos_dp_reg.c
@@ -0,0 +1,1173 @@
1/*
2 * Samsung DP (Display port) register interface driver.
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/device.h>
14#include <linux/io.h>
15#include <linux/delay.h>
16
17#include <video/exynos_dp.h>
18
19#include <plat/cpu.h>
20
21#include "exynos_dp_core.h"
22#include "exynos_dp_reg.h"
23
24#define COMMON_INT_MASK_1 (0)
25#define COMMON_INT_MASK_2 (0)
26#define COMMON_INT_MASK_3 (0)
27#define COMMON_INT_MASK_4 (0)
28#define INT_STA_MASK (0)
29
30void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
31{
32 u32 reg;
33
34 if (enable) {
35 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
36 reg |= HDCP_VIDEO_MUTE;
37 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
38 } else {
39 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
40 reg &= ~HDCP_VIDEO_MUTE;
41 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
42 }
43}
44
45void exynos_dp_stop_video(struct exynos_dp_device *dp)
46{
47 u32 reg;
48
49 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
50 reg &= ~VIDEO_EN;
51 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
52}
53
54void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
55{
56 u32 reg;
57
58 if (enable)
59 reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
60 LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
61 else
62 reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
63 LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
64
65 writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
66}
67
68void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
69{
70 /* Set interrupt pin assertion polarity as high */
71 writel(INT_POL, dp->reg_base + EXYNOS_DP_INT_CTL);
72
73 /* Clear pending regisers */
74 writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
75 writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
76 writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
77 writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
78 writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
79
80 /* 0:mask,1: unmask */
81 writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
82 writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
83 writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
84 writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
85 writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
86}
87
88void exynos_dp_reset(struct exynos_dp_device *dp)
89{
90 u32 reg;
91
92 writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
93
94 exynos_dp_stop_video(dp);
95 exynos_dp_enable_video_mute(dp, 0);
96
97 reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
98 AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
99 HDCP_FUNC_EN_N | SW_FUNC_EN_N;
100 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
101
102 reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
103 SERDES_FIFO_FUNC_EN_N |
104 LS_CLK_DOMAIN_FUNC_EN_N;
105 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
106
107 udelay(20);
108
109 exynos_dp_lane_swap(dp, 0);
110
111 writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
112 writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
113 writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
114 writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
115
116 writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
117 writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
118
119 writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
120 writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
121
122 writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
123
124 writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
125
126 writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
127 writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
128
129 writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
130 writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
131
132 writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
133
134 exynos_dp_init_interrupt(dp);
135}
136
137void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
138{
139 u32 reg;
140
141 /* 0: mask, 1: unmask */
142 reg = COMMON_INT_MASK_1;
143 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
144
145 reg = COMMON_INT_MASK_2;
146 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
147
148 reg = COMMON_INT_MASK_3;
149 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
150
151 reg = COMMON_INT_MASK_4;
152 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
153
154 reg = INT_STA_MASK;
155 writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
156}
157
158u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
159{
160 u32 reg;
161
162 reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
163 if (reg & PLL_LOCK)
164 return PLL_LOCKED;
165 else
166 return PLL_UNLOCKED;
167}
168
169void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable)
170{
171 u32 reg;
172
173 if (enable) {
174 reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
175 reg |= DP_PLL_PD;
176 writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
177 } else {
178 reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
179 reg &= ~DP_PLL_PD;
180 writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
181 }
182}
183
184void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
185 enum analog_power_block block,
186 bool enable)
187{
188 u32 reg;
189
190 switch (block) {
191 case AUX_BLOCK:
192 if (enable) {
193 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
194 reg |= AUX_PD;
195 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
196 } else {
197 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
198 reg &= ~AUX_PD;
199 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
200 }
201 break;
202 case CH0_BLOCK:
203 if (enable) {
204 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
205 reg |= CH0_PD;
206 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
207 } else {
208 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
209 reg &= ~CH0_PD;
210 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
211 }
212 break;
213 case CH1_BLOCK:
214 if (enable) {
215 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
216 reg |= CH1_PD;
217 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
218 } else {
219 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
220 reg &= ~CH1_PD;
221 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
222 }
223 break;
224 case CH2_BLOCK:
225 if (enable) {
226 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
227 reg |= CH2_PD;
228 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
229 } else {
230 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
231 reg &= ~CH2_PD;
232 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
233 }
234 break;
235 case CH3_BLOCK:
236 if (enable) {
237 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
238 reg |= CH3_PD;
239 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
240 } else {
241 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
242 reg &= ~CH3_PD;
243 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
244 }
245 break;
246 case ANALOG_TOTAL:
247 if (enable) {
248 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
249 reg |= DP_PHY_PD;
250 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
251 } else {
252 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
253 reg &= ~DP_PHY_PD;
254 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
255 }
256 break;
257 case POWER_ALL:
258 if (enable) {
259 reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
260 CH1_PD | CH0_PD;
261 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
262 } else {
263 writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
264 }
265 break;
266 default:
267 break;
268 }
269}
270
271void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
272{
273 u32 reg;
274
275 exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
276
277 reg = PLL_LOCK_CHG;
278 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
279
280 reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
281 reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
282 writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
283
284 /* Power up PLL */
285 if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED)
286 exynos_dp_set_pll_power_down(dp, 0);
287
288 /* Enable Serdes FIFO function and Link symbol clock domain module */
289 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
290 reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
291 | AUX_FUNC_EN_N);
292 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
293}
294
295void exynos_dp_init_hpd(struct exynos_dp_device *dp)
296{
297 u32 reg;
298
299 reg = HOTPLUG_CHG | HPD_LOST | PLUG;
300 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
301
302 reg = INT_HPD;
303 writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
304
305 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
306 reg &= ~(F_HPD | HPD_CTRL);
307 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
308}
309
310void exynos_dp_reset_aux(struct exynos_dp_device *dp)
311{
312 u32 reg;
313
314 /* Disable AUX channel module */
315 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
316 reg |= AUX_FUNC_EN_N;
317 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
318}
319
320void exynos_dp_init_aux(struct exynos_dp_device *dp)
321{
322 u32 reg;
323
324 /* Clear inerrupts related to AUX channel */
325 reg = RPLY_RECEIV | AUX_ERR;
326 writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
327
328 exynos_dp_reset_aux(dp);
329
330 /* Disable AUX transaction H/W retry */
331 reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
332 AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
333 writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL) ;
334
335 /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
336 reg = DEFER_CTRL_EN | DEFER_COUNT(1);
337 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
338
339 /* Enable AUX channel module */
340 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
341 reg &= ~AUX_FUNC_EN_N;
342 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
343}
344
345int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
346{
347 u32 reg;
348
349 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
350 if (reg & HPD_STATUS)
351 return 0;
352
353 return -EINVAL;
354}
355
356void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
357{
358 u32 reg;
359
360 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
361 reg &= ~SW_FUNC_EN_N;
362 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
363}
364
365int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
366{
367 int reg;
368 int retval = 0;
369
370 /* Enable AUX CH operation */
371 reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
372 reg |= AUX_EN;
373 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
374
375 /* Is AUX CH command reply received? */
376 reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
377 while (!(reg & RPLY_RECEIV))
378 reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
379
380 /* Clear interrupt source for AUX CH command reply */
381 writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
382
383 /* Clear interrupt source for AUX CH access error */
384 reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
385 if (reg & AUX_ERR) {
386 writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
387 return -EREMOTEIO;
388 }
389
390 /* Check AUX CH error access status */
391 reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
392 if ((reg & AUX_STATUS_MASK) != 0) {
393 dev_err(dp->dev, "AUX CH error happens: %d\n\n",
394 reg & AUX_STATUS_MASK);
395 return -EREMOTEIO;
396 }
397
398 return retval;
399}
400
401int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
402 unsigned int reg_addr,
403 unsigned char data)
404{
405 u32 reg;
406 int i;
407 int retval;
408
409 for (i = 0; i < 3; i++) {
410 /* Clear AUX CH data buffer */
411 reg = BUF_CLR;
412 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
413
414 /* Select DPCD device address */
415 reg = AUX_ADDR_7_0(reg_addr);
416 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
417 reg = AUX_ADDR_15_8(reg_addr);
418 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
419 reg = AUX_ADDR_19_16(reg_addr);
420 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
421
422 /* Write data buffer */
423 reg = (unsigned int)data;
424 writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
425
426 /*
427 * Set DisplayPort transaction and write 1 byte
428 * If bit 3 is 1, DisplayPort transaction.
429 * If Bit 3 is 0, I2C transaction.
430 */
431 reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
432 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
433
434 /* Start AUX transaction */
435 retval = exynos_dp_start_aux_transaction(dp);
436 if (retval == 0)
437 break;
438 else
439 dev_err(dp->dev, "Aux Transaction fail!\n");
440 }
441
442 return retval;
443}
444
445int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
446 unsigned int reg_addr,
447 unsigned char *data)
448{
449 u32 reg;
450 int i;
451 int retval;
452
453 for (i = 0; i < 10; i++) {
454 /* Clear AUX CH data buffer */
455 reg = BUF_CLR;
456 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
457
458 /* Select DPCD device address */
459 reg = AUX_ADDR_7_0(reg_addr);
460 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
461 reg = AUX_ADDR_15_8(reg_addr);
462 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
463 reg = AUX_ADDR_19_16(reg_addr);
464 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
465
466 /*
467 * Set DisplayPort transaction and read 1 byte
468 * If bit 3 is 1, DisplayPort transaction.
469 * If Bit 3 is 0, I2C transaction.
470 */
471 reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
472 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
473
474 /* Start AUX transaction */
475 retval = exynos_dp_start_aux_transaction(dp);
476 if (retval == 0)
477 break;
478 else
479 dev_err(dp->dev, "Aux Transaction fail!\n");
480 }
481
482 /* Read data buffer */
483 reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
484 *data = (unsigned char)(reg & 0xff);
485
486 return retval;
487}
488
489int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
490 unsigned int reg_addr,
491 unsigned int count,
492 unsigned char data[])
493{
494 u32 reg;
495 unsigned int start_offset;
496 unsigned int cur_data_count;
497 unsigned int cur_data_idx;
498 int i;
499 int retval = 0;
500
501 /* Clear AUX CH data buffer */
502 reg = BUF_CLR;
503 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
504
505 start_offset = 0;
506 while (start_offset < count) {
507 /* Buffer size of AUX CH is 16 * 4bytes */
508 if ((count - start_offset) > 16)
509 cur_data_count = 16;
510 else
511 cur_data_count = count - start_offset;
512
513 for (i = 0; i < 10; i++) {
514 /* Select DPCD device address */
515 reg = AUX_ADDR_7_0(reg_addr + start_offset);
516 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
517 reg = AUX_ADDR_15_8(reg_addr + start_offset);
518 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
519 reg = AUX_ADDR_19_16(reg_addr + start_offset);
520 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
521
522 for (cur_data_idx = 0; cur_data_idx < cur_data_count;
523 cur_data_idx++) {
524 reg = data[start_offset + cur_data_idx];
525 writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0
526 + 4 * cur_data_idx);
527 }
528
529 /*
530 * Set DisplayPort transaction and write
531 * If bit 3 is 1, DisplayPort transaction.
532 * If Bit 3 is 0, I2C transaction.
533 */
534 reg = AUX_LENGTH(cur_data_count) |
535 AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
536 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
537
538 /* Start AUX transaction */
539 retval = exynos_dp_start_aux_transaction(dp);
540 if (retval == 0)
541 break;
542 else
543 dev_err(dp->dev, "Aux Transaction fail!\n");
544 }
545
546 start_offset += cur_data_count;
547 }
548
549 return retval;
550}
551
552int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
553 unsigned int reg_addr,
554 unsigned int count,
555 unsigned char data[])
556{
557 u32 reg;
558 unsigned int start_offset;
559 unsigned int cur_data_count;
560 unsigned int cur_data_idx;
561 int i;
562 int retval = 0;
563
564 /* Clear AUX CH data buffer */
565 reg = BUF_CLR;
566 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
567
568 start_offset = 0;
569 while (start_offset < count) {
570 /* Buffer size of AUX CH is 16 * 4bytes */
571 if ((count - start_offset) > 16)
572 cur_data_count = 16;
573 else
574 cur_data_count = count - start_offset;
575
576 /* AUX CH Request Transaction process */
577 for (i = 0; i < 10; i++) {
578 /* Select DPCD device address */
579 reg = AUX_ADDR_7_0(reg_addr + start_offset);
580 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
581 reg = AUX_ADDR_15_8(reg_addr + start_offset);
582 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
583 reg = AUX_ADDR_19_16(reg_addr + start_offset);
584 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
585
586 /*
587 * Set DisplayPort transaction and read
588 * If bit 3 is 1, DisplayPort transaction.
589 * If Bit 3 is 0, I2C transaction.
590 */
591 reg = AUX_LENGTH(cur_data_count) |
592 AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
593 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
594
595 /* Start AUX transaction */
596 retval = exynos_dp_start_aux_transaction(dp);
597 if (retval == 0)
598 break;
599 else
600 dev_err(dp->dev, "Aux Transaction fail!\n");
601 }
602
603 for (cur_data_idx = 0; cur_data_idx < cur_data_count;
604 cur_data_idx++) {
605 reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
606 + 4 * cur_data_idx);
607 data[start_offset + cur_data_idx] =
608 (unsigned char)reg;
609 }
610
611 start_offset += cur_data_count;
612 }
613
614 return retval;
615}
616
617int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
618 unsigned int device_addr,
619 unsigned int reg_addr)
620{
621 u32 reg;
622 int retval;
623
624 /* Set EDID device address */
625 reg = device_addr;
626 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
627 writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
628 writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
629
630 /* Set offset from base address of EDID device */
631 writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
632
633 /*
634 * Set I2C transaction and write address
635 * If bit 3 is 1, DisplayPort transaction.
636 * If Bit 3 is 0, I2C transaction.
637 */
638 reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
639 AUX_TX_COMM_WRITE;
640 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
641
642 /* Start AUX transaction */
643 retval = exynos_dp_start_aux_transaction(dp);
644 if (retval != 0)
645 dev_err(dp->dev, "Aux Transaction fail!\n");
646
647 return retval;
648}
649
650int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
651 unsigned int device_addr,
652 unsigned int reg_addr,
653 unsigned int *data)
654{
655 u32 reg;
656 int i;
657 int retval;
658
659 for (i = 0; i < 10; i++) {
660 /* Clear AUX CH data buffer */
661 reg = BUF_CLR;
662 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
663
664 /* Select EDID device */
665 retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
666 if (retval != 0) {
667 dev_err(dp->dev, "Select EDID device fail!\n");
668 continue;
669 }
670
671 /*
672 * Set I2C transaction and read data
673 * If bit 3 is 1, DisplayPort transaction.
674 * If Bit 3 is 0, I2C transaction.
675 */
676 reg = AUX_TX_COMM_I2C_TRANSACTION |
677 AUX_TX_COMM_READ;
678 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
679
680 /* Start AUX transaction */
681 retval = exynos_dp_start_aux_transaction(dp);
682 if (retval == 0)
683 break;
684 else
685 dev_err(dp->dev, "Aux Transaction fail!\n");
686 }
687
688 /* Read data */
689 if (retval == 0)
690 *data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
691
692 return retval;
693}
694
695int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
696 unsigned int device_addr,
697 unsigned int reg_addr,
698 unsigned int count,
699 unsigned char edid[])
700{
701 u32 reg;
702 unsigned int i, j;
703 unsigned int cur_data_idx;
704 unsigned int defer = 0;
705 int retval = 0;
706
707 for (i = 0; i < count; i += 16) {
708 for (j = 0; j < 100; j++) {
709 /* Clear AUX CH data buffer */
710 reg = BUF_CLR;
711 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
712
713 /* Set normal AUX CH command */
714 reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
715 reg &= ~ADDR_ONLY;
716 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
717
718 /*
719 * If Rx sends defer, Tx sends only reads
720 * request without sending addres
721 */
722 if (!defer)
723 retval = exynos_dp_select_i2c_device(dp,
724 device_addr, reg_addr + i);
725 else
726 defer = 0;
727
728 if (retval == 0) {
729 /*
730 * Set I2C transaction and write data
731 * If bit 3 is 1, DisplayPort transaction.
732 * If Bit 3 is 0, I2C transaction.
733 */
734 reg = AUX_LENGTH(16) |
735 AUX_TX_COMM_I2C_TRANSACTION |
736 AUX_TX_COMM_READ;
737 writel(reg, dp->reg_base +
738 EXYNOS_DP_AUX_CH_CTL_1);
739
740 /* Start AUX transaction */
741 retval = exynos_dp_start_aux_transaction(dp);
742 if (retval == 0)
743 break;
744 else
745 dev_err(dp->dev, "Aux Transaction fail!\n");
746 }
747 /* Check if Rx sends defer */
748 reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
749 if (reg == AUX_RX_COMM_AUX_DEFER ||
750 reg == AUX_RX_COMM_I2C_DEFER) {
751 dev_err(dp->dev, "Defer: %d\n\n", reg);
752 defer = 1;
753 }
754 }
755
756 for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
757 reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
758 + 4 * cur_data_idx);
759 edid[i + cur_data_idx] = (unsigned char)reg;
760 }
761 }
762
763 return retval;
764}
765
766void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype)
767{
768 u32 reg;
769
770 reg = bwtype;
771 if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS))
772 writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
773}
774
775void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype)
776{
777 u32 reg;
778
779 reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
780 *bwtype = reg;
781}
782
783void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
784{
785 u32 reg;
786
787 reg = count;
788 writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
789}
790
791void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
792{
793 u32 reg;
794
795 reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
796 *count = reg;
797}
798
799void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable)
800{
801 u32 reg;
802
803 if (enable) {
804 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
805 reg |= ENHANCED;
806 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
807 } else {
808 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
809 reg &= ~ENHANCED;
810 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
811 }
812}
813
814void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
815 enum pattern_set pattern)
816{
817 u32 reg;
818
819 switch (pattern) {
820 case PRBS7:
821 reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
822 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
823 break;
824 case D10_2:
825 reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
826 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
827 break;
828 case TRAINING_PTN1:
829 reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
830 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
831 break;
832 case TRAINING_PTN2:
833 reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
834 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
835 break;
836 case DP_NONE:
837 reg = SCRAMBLING_ENABLE |
838 LINK_QUAL_PATTERN_SET_DISABLE |
839 SW_TRAINING_PATTERN_SET_NORMAL;
840 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
841 break;
842 default:
843 break;
844 }
845}
846
847void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
848{
849 u32 reg;
850
851 reg = level << PRE_EMPHASIS_SET_SHIFT;
852 writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
853}
854
855void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
856{
857 u32 reg;
858
859 reg = level << PRE_EMPHASIS_SET_SHIFT;
860 writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
861}
862
863void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
864{
865 u32 reg;
866
867 reg = level << PRE_EMPHASIS_SET_SHIFT;
868 writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
869}
870
871void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
872{
873 u32 reg;
874
875 reg = level << PRE_EMPHASIS_SET_SHIFT;
876 writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
877}
878
879void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
880 u32 training_lane)
881{
882 u32 reg;
883
884 reg = training_lane;
885 writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
886}
887
888void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
889 u32 training_lane)
890{
891 u32 reg;
892
893 reg = training_lane;
894 writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
895}
896
897void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
898 u32 training_lane)
899{
900 u32 reg;
901
902 reg = training_lane;
903 writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
904}
905
906void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
907 u32 training_lane)
908{
909 u32 reg;
910
911 reg = training_lane;
912 writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
913}
914
915u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
916{
917 u32 reg;
918
919 reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
920 return reg;
921}
922
923u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
924{
925 u32 reg;
926
927 reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
928 return reg;
929}
930
931u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
932{
933 u32 reg;
934
935 reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
936 return reg;
937}
938
939u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
940{
941 u32 reg;
942
943 reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
944 return reg;
945}
946
947void exynos_dp_reset_macro(struct exynos_dp_device *dp)
948{
949 u32 reg;
950
951 reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
952 reg |= MACRO_RST;
953 writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
954
955 /* 10 us is the minimum reset time. */
956 udelay(10);
957
958 reg &= ~MACRO_RST;
959 writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
960}
961
962int exynos_dp_init_video(struct exynos_dp_device *dp)
963{
964 u32 reg;
965
966 reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
967 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
968
969 reg = 0x0;
970 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
971
972 reg = CHA_CRI(4) | CHA_CTRL;
973 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
974
975 reg = 0x0;
976 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
977
978 reg = VID_HRES_TH(2) | VID_VRES_TH(0);
979 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
980
981 return 0;
982}
983
984void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
985 u32 color_depth,
986 u32 color_space,
987 u32 dynamic_range,
988 u32 ycbcr_coeff)
989{
990 u32 reg;
991
992 /* Configure the input color depth, color space, dynamic range */
993 reg = (dynamic_range << IN_D_RANGE_SHIFT) |
994 (color_depth << IN_BPC_SHIFT) |
995 (color_space << IN_COLOR_F_SHIFT);
996 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
997
998 /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
999 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
1000 reg &= ~IN_YC_COEFFI_MASK;
1001 if (ycbcr_coeff)
1002 reg |= IN_YC_COEFFI_ITU709;
1003 else
1004 reg |= IN_YC_COEFFI_ITU601;
1005 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
1006}
1007
1008int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
1009{
1010 u32 reg;
1011
1012 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
1013 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
1014
1015 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
1016
1017 if (!(reg & DET_STA)) {
1018 dev_dbg(dp->dev, "Input stream clock not detected.\n");
1019 return -EINVAL;
1020 }
1021
1022 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
1023 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
1024
1025 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
1026 dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
1027
1028 if (reg & CHA_STA) {
1029 dev_dbg(dp->dev, "Input stream clk is changing\n");
1030 return -EINVAL;
1031 }
1032
1033 return 0;
1034}
1035
1036void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
1037 enum clock_recovery_m_value_type type,
1038 u32 m_value,
1039 u32 n_value)
1040{
1041 u32 reg;
1042
1043 if (type == REGISTER_M) {
1044 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1045 reg |= FIX_M_VID;
1046 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1047 reg = m_value & 0xff;
1048 writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
1049 reg = (m_value >> 8) & 0xff;
1050 writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
1051 reg = (m_value >> 16) & 0xff;
1052 writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
1053
1054 reg = n_value & 0xff;
1055 writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
1056 reg = (n_value >> 8) & 0xff;
1057 writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
1058 reg = (n_value >> 16) & 0xff;
1059 writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
1060 } else {
1061 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1062 reg &= ~FIX_M_VID;
1063 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1064
1065 writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
1066 writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
1067 writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
1068 }
1069}
1070
1071void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type)
1072{
1073 u32 reg;
1074
1075 if (type == VIDEO_TIMING_FROM_CAPTURE) {
1076 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1077 reg &= ~FORMAT_SEL;
1078 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1079 } else {
1080 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1081 reg |= FORMAT_SEL;
1082 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1083 }
1084}
1085
1086void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable)
1087{
1088 u32 reg;
1089
1090 if (enable) {
1091 reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1092 reg &= ~VIDEO_MODE_MASK;
1093 reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
1094 writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1095 } else {
1096 reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1097 reg &= ~VIDEO_MODE_MASK;
1098 reg |= VIDEO_MODE_SLAVE_MODE;
1099 writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1100 }
1101}
1102
1103void exynos_dp_start_video(struct exynos_dp_device *dp)
1104{
1105 u32 reg;
1106
1107 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
1108 reg |= VIDEO_EN;
1109 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
1110}
1111
1112int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
1113{
1114 u32 reg;
1115
1116 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
1117 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
1118
1119 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
1120 if (!(reg & STRM_VALID)) {
1121 dev_dbg(dp->dev, "Input video stream is not detected.\n");
1122 return -EINVAL;
1123 }
1124
1125 return 0;
1126}
1127
1128void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
1129 struct video_info *video_info)
1130{
1131 u32 reg;
1132
1133 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
1134 reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
1135 reg |= MASTER_VID_FUNC_EN_N;
1136 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
1137
1138 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1139 reg &= ~INTERACE_SCAN_CFG;
1140 reg |= (video_info->interlaced << 2);
1141 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1142
1143 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1144 reg &= ~VSYNC_POLARITY_CFG;
1145 reg |= (video_info->v_sync_polarity << 1);
1146 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1147
1148 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1149 reg &= ~HSYNC_POLARITY_CFG;
1150 reg |= (video_info->h_sync_polarity << 0);
1151 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1152
1153 reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
1154 writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1155}
1156
1157void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
1158{
1159 u32 reg;
1160
1161 reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1162 reg &= ~SCRAMBLING_DISABLE;
1163 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1164}
1165
1166void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
1167{
1168 u32 reg;
1169
1170 reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1171 reg |= SCRAMBLING_DISABLE;
1172 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1173}
diff --git a/drivers/video/exynos/exynos_dp_reg.h b/drivers/video/exynos/exynos_dp_reg.h
new file mode 100644
index 000000000000..42f608e2a43e
--- /dev/null
+++ b/drivers/video/exynos/exynos_dp_reg.h
@@ -0,0 +1,335 @@
1/*
2 * Register definition file for Samsung DP driver
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _EXYNOS_DP_REG_H
13#define _EXYNOS_DP_REG_H
14
15#define EXYNOS_DP_TX_SW_RESET 0x14
16#define EXYNOS_DP_FUNC_EN_1 0x18
17#define EXYNOS_DP_FUNC_EN_2 0x1C
18#define EXYNOS_DP_VIDEO_CTL_1 0x20
19#define EXYNOS_DP_VIDEO_CTL_2 0x24
20#define EXYNOS_DP_VIDEO_CTL_3 0x28
21
22#define EXYNOS_DP_VIDEO_CTL_8 0x3C
23#define EXYNOS_DP_VIDEO_CTL_10 0x44
24
25#define EXYNOS_DP_LANE_MAP 0x35C
26
27#define EXYNOS_DP_AUX_HW_RETRY_CTL 0x390
28
29#define EXYNOS_DP_COMMON_INT_STA_1 0x3C4
30#define EXYNOS_DP_COMMON_INT_STA_2 0x3C8
31#define EXYNOS_DP_COMMON_INT_STA_3 0x3CC
32#define EXYNOS_DP_COMMON_INT_STA_4 0x3D0
33#define EXYNOS_DP_INT_STA 0x3DC
34#define EXYNOS_DP_COMMON_INT_MASK_1 0x3E0
35#define EXYNOS_DP_COMMON_INT_MASK_2 0x3E4
36#define EXYNOS_DP_COMMON_INT_MASK_3 0x3E8
37#define EXYNOS_DP_COMMON_INT_MASK_4 0x3EC
38#define EXYNOS_DP_INT_STA_MASK 0x3F8
39#define EXYNOS_DP_INT_CTL 0x3FC
40
41#define EXYNOS_DP_SYS_CTL_1 0x600
42#define EXYNOS_DP_SYS_CTL_2 0x604
43#define EXYNOS_DP_SYS_CTL_3 0x608
44#define EXYNOS_DP_SYS_CTL_4 0x60C
45
46#define EXYNOS_DP_PKT_SEND_CTL 0x640
47#define EXYNOS_DP_HDCP_CTL 0x648
48
49#define EXYNOS_DP_LINK_BW_SET 0x680
50#define EXYNOS_DP_LANE_COUNT_SET 0x684
51#define EXYNOS_DP_TRAINING_PTN_SET 0x688
52#define EXYNOS_DP_LN0_LINK_TRAINING_CTL 0x68C
53#define EXYNOS_DP_LN1_LINK_TRAINING_CTL 0x690
54#define EXYNOS_DP_LN2_LINK_TRAINING_CTL 0x694
55#define EXYNOS_DP_LN3_LINK_TRAINING_CTL 0x698
56
57#define EXYNOS_DP_DEBUG_CTL 0x6C0
58#define EXYNOS_DP_HPD_DEGLITCH_L 0x6C4
59#define EXYNOS_DP_HPD_DEGLITCH_H 0x6C8
60#define EXYNOS_DP_LINK_DEBUG_CTL 0x6E0
61
62#define EXYNOS_DP_M_VID_0 0x700
63#define EXYNOS_DP_M_VID_1 0x704
64#define EXYNOS_DP_M_VID_2 0x708
65#define EXYNOS_DP_N_VID_0 0x70C
66#define EXYNOS_DP_N_VID_1 0x710
67#define EXYNOS_DP_N_VID_2 0x714
68
69#define EXYNOS_DP_PLL_CTL 0x71C
70#define EXYNOS_DP_PHY_PD 0x720
71#define EXYNOS_DP_PHY_TEST 0x724
72
73#define EXYNOS_DP_VIDEO_FIFO_THRD 0x730
74#define EXYNOS_DP_AUDIO_MARGIN 0x73C
75
76#define EXYNOS_DP_M_VID_GEN_FILTER_TH 0x764
77#define EXYNOS_DP_M_AUD_GEN_FILTER_TH 0x778
78#define EXYNOS_DP_AUX_CH_STA 0x780
79#define EXYNOS_DP_AUX_CH_DEFER_CTL 0x788
80#define EXYNOS_DP_AUX_RX_COMM 0x78C
81#define EXYNOS_DP_BUFFER_DATA_CTL 0x790
82#define EXYNOS_DP_AUX_CH_CTL_1 0x794
83#define EXYNOS_DP_AUX_ADDR_7_0 0x798
84#define EXYNOS_DP_AUX_ADDR_15_8 0x79C
85#define EXYNOS_DP_AUX_ADDR_19_16 0x7A0
86#define EXYNOS_DP_AUX_CH_CTL_2 0x7A4
87
88#define EXYNOS_DP_BUF_DATA_0 0x7C0
89
90#define EXYNOS_DP_SOC_GENERAL_CTL 0x800
91
92/* EXYNOS_DP_TX_SW_RESET */
93#define RESET_DP_TX (0x1 << 0)
94
95/* EXYNOS_DP_FUNC_EN_1 */
96#define MASTER_VID_FUNC_EN_N (0x1 << 7)
97#define SLAVE_VID_FUNC_EN_N (0x1 << 5)
98#define AUD_FIFO_FUNC_EN_N (0x1 << 4)
99#define AUD_FUNC_EN_N (0x1 << 3)
100#define HDCP_FUNC_EN_N (0x1 << 2)
101#define CRC_FUNC_EN_N (0x1 << 1)
102#define SW_FUNC_EN_N (0x1 << 0)
103
104/* EXYNOS_DP_FUNC_EN_2 */
105#define SSC_FUNC_EN_N (0x1 << 7)
106#define AUX_FUNC_EN_N (0x1 << 2)
107#define SERDES_FIFO_FUNC_EN_N (0x1 << 1)
108#define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0)
109
110/* EXYNOS_DP_VIDEO_CTL_1 */
111#define VIDEO_EN (0x1 << 7)
112#define HDCP_VIDEO_MUTE (0x1 << 6)
113
114/* EXYNOS_DP_VIDEO_CTL_1 */
115#define IN_D_RANGE_MASK (0x1 << 7)
116#define IN_D_RANGE_SHIFT (7)
117#define IN_D_RANGE_CEA (0x1 << 7)
118#define IN_D_RANGE_VESA (0x0 << 7)
119#define IN_BPC_MASK (0x7 << 4)
120#define IN_BPC_SHIFT (4)
121#define IN_BPC_12_BITS (0x3 << 4)
122#define IN_BPC_10_BITS (0x2 << 4)
123#define IN_BPC_8_BITS (0x1 << 4)
124#define IN_BPC_6_BITS (0x0 << 4)
125#define IN_COLOR_F_MASK (0x3 << 0)
126#define IN_COLOR_F_SHIFT (0)
127#define IN_COLOR_F_YCBCR444 (0x2 << 0)
128#define IN_COLOR_F_YCBCR422 (0x1 << 0)
129#define IN_COLOR_F_RGB (0x0 << 0)
130
131/* EXYNOS_DP_VIDEO_CTL_3 */
132#define IN_YC_COEFFI_MASK (0x1 << 7)
133#define IN_YC_COEFFI_SHIFT (7)
134#define IN_YC_COEFFI_ITU709 (0x1 << 7)
135#define IN_YC_COEFFI_ITU601 (0x0 << 7)
136#define VID_CHK_UPDATE_TYPE_MASK (0x1 << 4)
137#define VID_CHK_UPDATE_TYPE_SHIFT (4)
138#define VID_CHK_UPDATE_TYPE_1 (0x1 << 4)
139#define VID_CHK_UPDATE_TYPE_0 (0x0 << 4)
140
141/* EXYNOS_DP_VIDEO_CTL_8 */
142#define VID_HRES_TH(x) (((x) & 0xf) << 4)
143#define VID_VRES_TH(x) (((x) & 0xf) << 0)
144
145/* EXYNOS_DP_VIDEO_CTL_10 */
146#define FORMAT_SEL (0x1 << 4)
147#define INTERACE_SCAN_CFG (0x1 << 2)
148#define VSYNC_POLARITY_CFG (0x1 << 1)
149#define HSYNC_POLARITY_CFG (0x1 << 0)
150
151/* EXYNOS_DP_LANE_MAP */
152#define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6)
153#define LANE3_MAP_LOGIC_LANE_1 (0x1 << 6)
154#define LANE3_MAP_LOGIC_LANE_2 (0x2 << 6)
155#define LANE3_MAP_LOGIC_LANE_3 (0x3 << 6)
156#define LANE2_MAP_LOGIC_LANE_0 (0x0 << 4)
157#define LANE2_MAP_LOGIC_LANE_1 (0x1 << 4)
158#define LANE2_MAP_LOGIC_LANE_2 (0x2 << 4)
159#define LANE2_MAP_LOGIC_LANE_3 (0x3 << 4)
160#define LANE1_MAP_LOGIC_LANE_0 (0x0 << 2)
161#define LANE1_MAP_LOGIC_LANE_1 (0x1 << 2)
162#define LANE1_MAP_LOGIC_LANE_2 (0x2 << 2)
163#define LANE1_MAP_LOGIC_LANE_3 (0x3 << 2)
164#define LANE0_MAP_LOGIC_LANE_0 (0x0 << 0)
165#define LANE0_MAP_LOGIC_LANE_1 (0x1 << 0)
166#define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0)
167#define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0)
168
169/* EXYNOS_DP_AUX_HW_RETRY_CTL */
170#define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8)
171#define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3)
172#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS (0x0 << 3)
173#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS (0x1 << 3)
174#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS (0x2 << 3)
175#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS (0x3 << 3)
176#define AUX_HW_RETRY_COUNT_SEL(x) (((x) & 0x7) << 0)
177
178/* EXYNOS_DP_COMMON_INT_STA_1 */
179#define VSYNC_DET (0x1 << 7)
180#define PLL_LOCK_CHG (0x1 << 6)
181#define SPDIF_ERR (0x1 << 5)
182#define SPDIF_UNSTBL (0x1 << 4)
183#define VID_FORMAT_CHG (0x1 << 3)
184#define AUD_CLK_CHG (0x1 << 2)
185#define VID_CLK_CHG (0x1 << 1)
186#define SW_INT (0x1 << 0)
187
188/* EXYNOS_DP_COMMON_INT_STA_2 */
189#define ENC_EN_CHG (0x1 << 6)
190#define HW_BKSV_RDY (0x1 << 3)
191#define HW_SHA_DONE (0x1 << 2)
192#define HW_AUTH_STATE_CHG (0x1 << 1)
193#define HW_AUTH_DONE (0x1 << 0)
194
195/* EXYNOS_DP_COMMON_INT_STA_3 */
196#define AFIFO_UNDER (0x1 << 7)
197#define AFIFO_OVER (0x1 << 6)
198#define R0_CHK_FLAG (0x1 << 5)
199
200/* EXYNOS_DP_COMMON_INT_STA_4 */
201#define PSR_ACTIVE (0x1 << 7)
202#define PSR_INACTIVE (0x1 << 6)
203#define SPDIF_BI_PHASE_ERR (0x1 << 5)
204#define HOTPLUG_CHG (0x1 << 2)
205#define HPD_LOST (0x1 << 1)
206#define PLUG (0x1 << 0)
207
208/* EXYNOS_DP_INT_STA */
209#define INT_HPD (0x1 << 6)
210#define HW_TRAINING_FINISH (0x1 << 5)
211#define RPLY_RECEIV (0x1 << 1)
212#define AUX_ERR (0x1 << 0)
213
214/* EXYNOS_DP_INT_CTL */
215#define SOFT_INT_CTRL (0x1 << 2)
216#define INT_POL (0x1 << 0)
217
218/* EXYNOS_DP_SYS_CTL_1 */
219#define DET_STA (0x1 << 2)
220#define FORCE_DET (0x1 << 1)
221#define DET_CTRL (0x1 << 0)
222
223/* EXYNOS_DP_SYS_CTL_2 */
224#define CHA_CRI(x) (((x) & 0xf) << 4)
225#define CHA_STA (0x1 << 2)
226#define FORCE_CHA (0x1 << 1)
227#define CHA_CTRL (0x1 << 0)
228
229/* EXYNOS_DP_SYS_CTL_3 */
230#define HPD_STATUS (0x1 << 6)
231#define F_HPD (0x1 << 5)
232#define HPD_CTRL (0x1 << 4)
233#define HDCP_RDY (0x1 << 3)
234#define STRM_VALID (0x1 << 2)
235#define F_VALID (0x1 << 1)
236#define VALID_CTRL (0x1 << 0)
237
238/* EXYNOS_DP_SYS_CTL_4 */
239#define FIX_M_AUD (0x1 << 4)
240#define ENHANCED (0x1 << 3)
241#define FIX_M_VID (0x1 << 2)
242#define M_VID_UPDATE_CTRL (0x3 << 0)
243
244/* EXYNOS_DP_TRAINING_PTN_SET */
245#define SCRAMBLER_TYPE (0x1 << 9)
246#define HW_LINK_TRAINING_PATTERN (0x1 << 8)
247#define SCRAMBLING_DISABLE (0x1 << 5)
248#define SCRAMBLING_ENABLE (0x0 << 5)
249#define LINK_QUAL_PATTERN_SET_MASK (0x3 << 2)
250#define LINK_QUAL_PATTERN_SET_PRBS7 (0x3 << 2)
251#define LINK_QUAL_PATTERN_SET_D10_2 (0x1 << 2)
252#define LINK_QUAL_PATTERN_SET_DISABLE (0x0 << 2)
253#define SW_TRAINING_PATTERN_SET_MASK (0x3 << 0)
254#define SW_TRAINING_PATTERN_SET_PTN2 (0x2 << 0)
255#define SW_TRAINING_PATTERN_SET_PTN1 (0x1 << 0)
256#define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0)
257
258/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
259#define PRE_EMPHASIS_SET_SHIFT (3)
260
261/* EXYNOS_DP_DEBUG_CTL */
262#define PLL_LOCK (0x1 << 4)
263#define F_PLL_LOCK (0x1 << 3)
264#define PLL_LOCK_CTRL (0x1 << 2)
265#define PN_INV (0x1 << 0)
266
267/* EXYNOS_DP_PLL_CTL */
268#define DP_PLL_PD (0x1 << 7)
269#define DP_PLL_RESET (0x1 << 6)
270#define DP_PLL_LOOP_BIT_DEFAULT (0x1 << 4)
271#define DP_PLL_REF_BIT_1_1250V (0x5 << 0)
272#define DP_PLL_REF_BIT_1_2500V (0x7 << 0)
273
274/* EXYNOS_DP_PHY_PD */
275#define DP_PHY_PD (0x1 << 5)
276#define AUX_PD (0x1 << 4)
277#define CH3_PD (0x1 << 3)
278#define CH2_PD (0x1 << 2)
279#define CH1_PD (0x1 << 1)
280#define CH0_PD (0x1 << 0)
281
282/* EXYNOS_DP_PHY_TEST */
283#define MACRO_RST (0x1 << 5)
284#define CH1_TEST (0x1 << 1)
285#define CH0_TEST (0x1 << 0)
286
287/* EXYNOS_DP_AUX_CH_STA */
288#define AUX_BUSY (0x1 << 4)
289#define AUX_STATUS_MASK (0xf << 0)
290
291/* EXYNOS_DP_AUX_CH_DEFER_CTL */
292#define DEFER_CTRL_EN (0x1 << 7)
293#define DEFER_COUNT(x) (((x) & 0x7f) << 0)
294
295/* EXYNOS_DP_AUX_RX_COMM */
296#define AUX_RX_COMM_I2C_DEFER (0x2 << 2)
297#define AUX_RX_COMM_AUX_DEFER (0x2 << 0)
298
299/* EXYNOS_DP_BUFFER_DATA_CTL */
300#define BUF_CLR (0x1 << 7)
301#define BUF_DATA_COUNT(x) (((x) & 0x1f) << 0)
302
303/* EXYNOS_DP_AUX_CH_CTL_1 */
304#define AUX_LENGTH(x) (((x - 1) & 0xf) << 4)
305#define AUX_TX_COMM_MASK (0xf << 0)
306#define AUX_TX_COMM_DP_TRANSACTION (0x1 << 3)
307#define AUX_TX_COMM_I2C_TRANSACTION (0x0 << 3)
308#define AUX_TX_COMM_MOT (0x1 << 2)
309#define AUX_TX_COMM_WRITE (0x0 << 0)
310#define AUX_TX_COMM_READ (0x1 << 0)
311
312/* EXYNOS_DP_AUX_ADDR_7_0 */
313#define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff)
314
315/* EXYNOS_DP_AUX_ADDR_15_8 */
316#define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff)
317
318/* EXYNOS_DP_AUX_ADDR_19_16 */
319#define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f)
320
321/* EXYNOS_DP_AUX_CH_CTL_2 */
322#define ADDR_ONLY (0x1 << 1)
323#define AUX_EN (0x1 << 0)
324
325/* EXYNOS_DP_SOC_GENERAL_CTL */
326#define AUDIO_MODE_SPDIF_MODE (0x1 << 8)
327#define AUDIO_MODE_MASTER_MODE (0x0 << 8)
328#define MASTER_VIDEO_INTERLACE_EN (0x1 << 4)
329#define VIDEO_MASTER_CLK_SEL (0x1 << 2)
330#define VIDEO_MASTER_MODE_EN (0x1 << 1)
331#define VIDEO_MODE_MASK (0x1 << 0)
332#define VIDEO_MODE_SLAVE_MODE (0x1 << 0)
333#define VIDEO_MODE_MASTER_MODE (0x0 << 0)
334
335#endif /* _EXYNOS_DP_REG_H */
diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c
new file mode 100644
index 000000000000..557091dc0e97
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi.c
@@ -0,0 +1,600 @@
1/* linux/drivers/video/exynos/exynos_mipi_dsi.c
2 *
3 * Samsung SoC MIPI-DSIM driver.
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae, <inki.dae@samsung.com>
8 * Donghwa Lee, <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/clk.h>
19#include <linux/mutex.h>
20#include <linux/wait.h>
21#include <linux/fs.h>
22#include <linux/mm.h>
23#include <linux/fb.h>
24#include <linux/ctype.h>
25#include <linux/platform_device.h>
26#include <linux/io.h>
27#include <linux/irq.h>
28#include <linux/memory.h>
29#include <linux/delay.h>
30#include <linux/interrupt.h>
31#include <linux/kthread.h>
32#include <linux/notifier.h>
33#include <linux/regulator/consumer.h>
34#include <linux/pm_runtime.h>
35
36#include <video/exynos_mipi_dsim.h>
37
38#include <plat/fb.h>
39
40#include "exynos_mipi_dsi_common.h"
41#include "exynos_mipi_dsi_lowlevel.h"
42
43struct mipi_dsim_ddi {
44 int bus_id;
45 struct list_head list;
46 struct mipi_dsim_lcd_device *dsim_lcd_dev;
47 struct mipi_dsim_lcd_driver *dsim_lcd_drv;
48};
49
50static LIST_HEAD(dsim_ddi_list);
51
52static DEFINE_MUTEX(mipi_dsim_lock);
53
54static struct mipi_dsim_platform_data *to_dsim_plat(struct platform_device
55 *pdev)
56{
57 return pdev->dev.platform_data;
58}
59
60static struct regulator_bulk_data supplies[] = {
61 { .supply = "vdd10", },
62 { .supply = "vdd18", },
63};
64
65static int exynos_mipi_regulator_enable(struct mipi_dsim_device *dsim)
66{
67 int ret;
68
69 mutex_lock(&dsim->lock);
70 ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
71 mutex_unlock(&dsim->lock);
72
73 return ret;
74}
75
76static int exynos_mipi_regulator_disable(struct mipi_dsim_device *dsim)
77{
78 int ret;
79
80 mutex_lock(&dsim->lock);
81 ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
82 mutex_unlock(&dsim->lock);
83
84 return ret;
85}
86
87/* update all register settings to MIPI DSI controller. */
88static void exynos_mipi_update_cfg(struct mipi_dsim_device *dsim)
89{
90 /*
91 * data from Display controller(FIMD) is not transferred in video mode
92 * but in case of command mode, all settings is not updated to
93 * registers.
94 */
95 exynos_mipi_dsi_stand_by(dsim, 0);
96
97 exynos_mipi_dsi_init_dsim(dsim);
98 exynos_mipi_dsi_init_link(dsim);
99
100 exynos_mipi_dsi_set_hs_enable(dsim);
101
102 /* set display timing. */
103 exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
104
105 /*
106 * data from Display controller(FIMD) is transferred in video mode
107 * but in case of command mode, all settigs is updated to registers.
108 */
109 exynos_mipi_dsi_stand_by(dsim, 1);
110}
111
112static int exynos_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim,
113 int power)
114{
115 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
116 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
117
118 switch (power) {
119 case FB_BLANK_POWERDOWN:
120 if (dsim->suspended)
121 return 0;
122
123 if (client_drv && client_drv->suspend)
124 client_drv->suspend(client_dev);
125
126 clk_disable(dsim->clock);
127
128 exynos_mipi_regulator_disable(dsim);
129
130 dsim->suspended = true;
131
132 break;
133 default:
134 break;
135 }
136
137 return 0;
138}
139
140static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power)
141{
142 struct platform_device *pdev = to_platform_device(dsim->dev);
143 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
144 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
145
146 switch (power) {
147 case FB_BLANK_UNBLANK:
148 if (!dsim->suspended)
149 return 0;
150
151 /* lcd panel power on. */
152 if (client_drv && client_drv->power_on)
153 client_drv->power_on(client_dev, 1);
154
155 exynos_mipi_regulator_disable(dsim);
156
157 /* enable MIPI-DSI PHY. */
158 if (dsim->pd->phy_enable)
159 dsim->pd->phy_enable(pdev, true);
160
161 clk_enable(dsim->clock);
162
163 exynos_mipi_update_cfg(dsim);
164
165 /* set lcd panel sequence commands. */
166 if (client_drv && client_drv->set_sequence)
167 client_drv->set_sequence(client_dev);
168
169 dsim->suspended = false;
170
171 break;
172 case FB_BLANK_NORMAL:
173 /* TODO. */
174 break;
175 default:
176 break;
177 }
178
179 return 0;
180}
181
182int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
183{
184 struct mipi_dsim_ddi *dsim_ddi;
185
186 if (!lcd_dev->name) {
187 pr_err("dsim_lcd_device name is NULL.\n");
188 return -EFAULT;
189 }
190
191 dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
192 if (!dsim_ddi) {
193 pr_err("failed to allocate dsim_ddi object.\n");
194 return -ENOMEM;
195 }
196
197 dsim_ddi->dsim_lcd_dev = lcd_dev;
198
199 mutex_lock(&mipi_dsim_lock);
200 list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
201 mutex_unlock(&mipi_dsim_lock);
202
203 return 0;
204}
205
206struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv)
207{
208 struct mipi_dsim_ddi *dsim_ddi, *next;
209 struct mipi_dsim_lcd_device *lcd_dev;
210
211 mutex_lock(&mipi_dsim_lock);
212
213 list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
214 if (!dsim_ddi)
215 goto out;
216
217 lcd_dev = dsim_ddi->dsim_lcd_dev;
218 if (!lcd_dev)
219 continue;
220
221 if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) {
222 /**
223 * bus_id would be used to identify
224 * connected bus.
225 */
226 dsim_ddi->bus_id = lcd_dev->bus_id;
227 mutex_unlock(&mipi_dsim_lock);
228
229 return dsim_ddi;
230 }
231
232 list_del(&dsim_ddi->list);
233 kfree(dsim_ddi);
234 }
235
236out:
237 mutex_unlock(&mipi_dsim_lock);
238
239 return NULL;
240}
241
242int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
243{
244 struct mipi_dsim_ddi *dsim_ddi;
245
246 if (!lcd_drv->name) {
247 pr_err("dsim_lcd_driver name is NULL.\n");
248 return -EFAULT;
249 }
250
251 dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv);
252 if (!dsim_ddi) {
253 pr_err("mipi_dsim_ddi object not found.\n");
254 return -EFAULT;
255 }
256
257 dsim_ddi->dsim_lcd_drv = lcd_drv;
258
259 pr_info("registered panel driver(%s) to mipi-dsi driver.\n",
260 lcd_drv->name);
261
262 return 0;
263
264}
265
266struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim,
267 const char *name)
268{
269 struct mipi_dsim_ddi *dsim_ddi, *next;
270 struct mipi_dsim_lcd_driver *lcd_drv;
271 struct mipi_dsim_lcd_device *lcd_dev;
272 int ret;
273
274 mutex_lock(&dsim->lock);
275
276 list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
277 lcd_drv = dsim_ddi->dsim_lcd_drv;
278 lcd_dev = dsim_ddi->dsim_lcd_dev;
279 if (!lcd_drv || !lcd_dev ||
280 (dsim->id != dsim_ddi->bus_id))
281 continue;
282
283 dev_dbg(dsim->dev, "lcd_drv->id = %d, lcd_dev->id = %d\n",
284 lcd_drv->id, lcd_dev->id);
285 dev_dbg(dsim->dev, "lcd_dev->bus_id = %d, dsim->id = %d\n",
286 lcd_dev->bus_id, dsim->id);
287
288 if ((strcmp(lcd_drv->name, name) == 0)) {
289 lcd_dev->master = dsim;
290
291 lcd_dev->dev.parent = dsim->dev;
292 dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name);
293
294 ret = device_register(&lcd_dev->dev);
295 if (ret < 0) {
296 dev_err(dsim->dev,
297 "can't register %s, status %d\n",
298 dev_name(&lcd_dev->dev), ret);
299 mutex_unlock(&dsim->lock);
300
301 return NULL;
302 }
303
304 dsim->dsim_lcd_dev = lcd_dev;
305 dsim->dsim_lcd_drv = lcd_drv;
306
307 mutex_unlock(&dsim->lock);
308
309 return dsim_ddi;
310 }
311 }
312
313 mutex_unlock(&dsim->lock);
314
315 return NULL;
316}
317
318/* define MIPI-DSI Master operations. */
319static struct mipi_dsim_master_ops master_ops = {
320 .cmd_read = exynos_mipi_dsi_rd_data,
321 .cmd_write = exynos_mipi_dsi_wr_data,
322 .get_dsim_frame_done = exynos_mipi_dsi_get_frame_done_status,
323 .clear_dsim_frame_done = exynos_mipi_dsi_clear_frame_done,
324 .set_early_blank_mode = exynos_mipi_dsi_early_blank_mode,
325 .set_blank_mode = exynos_mipi_dsi_blank_mode,
326};
327
328static int exynos_mipi_dsi_probe(struct platform_device *pdev)
329{
330 struct resource *res;
331 struct mipi_dsim_device *dsim;
332 struct mipi_dsim_config *dsim_config;
333 struct mipi_dsim_platform_data *dsim_pd;
334 struct mipi_dsim_ddi *dsim_ddi;
335 int ret = -EINVAL;
336
337 dsim = kzalloc(sizeof(struct mipi_dsim_device), GFP_KERNEL);
338 if (!dsim) {
339 dev_err(&pdev->dev, "failed to allocate dsim object.\n");
340 return -ENOMEM;
341 }
342
343 dsim->pd = to_dsim_plat(pdev);
344 dsim->dev = &pdev->dev;
345 dsim->id = pdev->id;
346
347 /* get mipi_dsim_platform_data. */
348 dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
349 if (dsim_pd == NULL) {
350 dev_err(&pdev->dev, "failed to get platform data for dsim.\n");
351 goto err_clock_get;
352 }
353 /* get mipi_dsim_config. */
354 dsim_config = dsim_pd->dsim_config;
355 if (dsim_config == NULL) {
356 dev_err(&pdev->dev, "failed to get dsim config data.\n");
357 goto err_clock_get;
358 }
359
360 dsim->dsim_config = dsim_config;
361 dsim->master_ops = &master_ops;
362
363 mutex_init(&dsim->lock);
364
365 ret = regulator_bulk_get(&pdev->dev, ARRAY_SIZE(supplies), supplies);
366 if (ret) {
367 dev_err(&pdev->dev, "Failed to get regulators: %d\n", ret);
368 goto err_clock_get;
369 }
370
371 dsim->clock = clk_get(&pdev->dev, "dsim0");
372 if (IS_ERR(dsim->clock)) {
373 dev_err(&pdev->dev, "failed to get dsim clock source\n");
374 goto err_clock_get;
375 }
376
377 clk_enable(dsim->clock);
378
379 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
380 if (!res) {
381 dev_err(&pdev->dev, "failed to get io memory region\n");
382 goto err_platform_get;
383 }
384
385 dsim->res = request_mem_region(res->start, resource_size(res),
386 dev_name(&pdev->dev));
387 if (!dsim->res) {
388 dev_err(&pdev->dev, "failed to request io memory region\n");
389 ret = -ENOMEM;
390 goto err_mem_region;
391 }
392
393 dsim->reg_base = ioremap(res->start, resource_size(res));
394 if (!dsim->reg_base) {
395 dev_err(&pdev->dev, "failed to remap io region\n");
396 ret = -ENOMEM;
397 goto err_ioremap;
398 }
399
400 mutex_init(&dsim->lock);
401
402 /* bind lcd ddi matched with panel name. */
403 dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
404 if (!dsim_ddi) {
405 dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
406 goto err_bind;
407 }
408
409 dsim->irq = platform_get_irq(pdev, 0);
410 if (dsim->irq < 0) {
411 dev_err(&pdev->dev, "failed to request dsim irq resource\n");
412 ret = -EINVAL;
413 goto err_platform_get_irq;
414 }
415
416 ret = request_irq(dsim->irq, exynos_mipi_dsi_interrupt_handler,
417 IRQF_SHARED, pdev->name, dsim);
418 if (ret != 0) {
419 dev_err(&pdev->dev, "failed to request dsim irq\n");
420 ret = -EINVAL;
421 goto err_bind;
422 }
423
424 init_completion(&dsim_wr_comp);
425 init_completion(&dsim_rd_comp);
426
427 /* enable interrupt */
428 exynos_mipi_dsi_init_interrupt(dsim);
429
430 /* initialize mipi-dsi client(lcd panel). */
431 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe)
432 dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev);
433
434 /* in case that mipi got enabled at bootloader. */
435 if (dsim_pd->enabled)
436 goto out;
437
438 /* lcd panel power on. */
439 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on)
440 dsim_ddi->dsim_lcd_drv->power_on(dsim_ddi->dsim_lcd_dev, 1);
441
442 exynos_mipi_regulator_enable(dsim);
443
444 /* enable MIPI-DSI PHY. */
445 if (dsim->pd->phy_enable)
446 dsim->pd->phy_enable(pdev, true);
447
448 exynos_mipi_update_cfg(dsim);
449
450 /* set lcd panel sequence commands. */
451 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->set_sequence)
452 dsim_ddi->dsim_lcd_drv->set_sequence(dsim_ddi->dsim_lcd_dev);
453
454 dsim->suspended = false;
455
456out:
457 platform_set_drvdata(pdev, dsim);
458
459 dev_dbg(&pdev->dev, "mipi-dsi driver(%s mode) has been probed.\n",
460 (dsim_config->e_interface == DSIM_COMMAND) ?
461 "CPU" : "RGB");
462
463 return 0;
464
465err_bind:
466 iounmap(dsim->reg_base);
467
468err_ioremap:
469 release_mem_region(dsim->res->start, resource_size(dsim->res));
470
471err_mem_region:
472 release_resource(dsim->res);
473
474err_platform_get:
475 clk_disable(dsim->clock);
476 clk_put(dsim->clock);
477err_clock_get:
478 kfree(dsim);
479
480err_platform_get_irq:
481 return ret;
482}
483
484static int __devexit exynos_mipi_dsi_remove(struct platform_device *pdev)
485{
486 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
487 struct mipi_dsim_ddi *dsim_ddi, *next;
488 struct mipi_dsim_lcd_driver *dsim_lcd_drv;
489
490 iounmap(dsim->reg_base);
491
492 clk_disable(dsim->clock);
493 clk_put(dsim->clock);
494
495 release_resource(dsim->res);
496 release_mem_region(dsim->res->start, resource_size(dsim->res));
497
498 list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
499 if (dsim_ddi) {
500 if (dsim->id != dsim_ddi->bus_id)
501 continue;
502
503 dsim_lcd_drv = dsim_ddi->dsim_lcd_drv;
504
505 if (dsim_lcd_drv->remove)
506 dsim_lcd_drv->remove(dsim_ddi->dsim_lcd_dev);
507
508 kfree(dsim_ddi);
509 }
510 }
511
512 regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
513 kfree(dsim);
514
515 return 0;
516}
517
518#ifdef CONFIG_PM
519static int exynos_mipi_dsi_suspend(struct platform_device *pdev,
520 pm_message_t state)
521{
522 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
523 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
524 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
525
526 disable_irq(dsim->irq);
527
528 if (dsim->suspended)
529 return 0;
530
531 if (client_drv && client_drv->suspend)
532 client_drv->suspend(client_dev);
533
534 /* enable MIPI-DSI PHY. */
535 if (dsim->pd->phy_enable)
536 dsim->pd->phy_enable(pdev, false);
537
538 clk_disable(dsim->clock);
539
540 exynos_mipi_regulator_disable(dsim);
541
542 dsim->suspended = true;
543
544 return 0;
545}
546
547static int exynos_mipi_dsi_resume(struct platform_device *pdev)
548{
549 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
550 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
551 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
552
553 enable_irq(dsim->irq);
554
555 if (!dsim->suspended)
556 return 0;
557
558 /* lcd panel power on. */
559 if (client_drv && client_drv->power_on)
560 client_drv->power_on(client_dev, 1);
561
562 exynos_mipi_regulator_enable(dsim);
563
564 /* enable MIPI-DSI PHY. */
565 if (dsim->pd->phy_enable)
566 dsim->pd->phy_enable(pdev, true);
567
568 clk_enable(dsim->clock);
569
570 exynos_mipi_update_cfg(dsim);
571
572 /* set lcd panel sequence commands. */
573 if (client_drv && client_drv->set_sequence)
574 client_drv->set_sequence(client_dev);
575
576 dsim->suspended = false;
577
578 return 0;
579}
580#else
581#define exynos_mipi_dsi_suspend NULL
582#define exynos_mipi_dsi_resume NULL
583#endif
584
585static struct platform_driver exynos_mipi_dsi_driver = {
586 .probe = exynos_mipi_dsi_probe,
587 .remove = __devexit_p(exynos_mipi_dsi_remove),
588 .suspend = exynos_mipi_dsi_suspend,
589 .resume = exynos_mipi_dsi_resume,
590 .driver = {
591 .name = "exynos-mipi-dsim",
592 .owner = THIS_MODULE,
593 },
594};
595
596module_platform_driver(exynos_mipi_dsi_driver);
597
598MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
599MODULE_DESCRIPTION("Samusung SoC MIPI-DSI driver");
600MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c
new file mode 100644
index 000000000000..14909c1d3832
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_common.c
@@ -0,0 +1,896 @@
1/* linux/drivers/video/exynos/exynos_mipi_dsi_common.c
2 *
3 * Samsung SoC MIPI-DSI common driver.
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae, <inki.dae@samsung.com>
8 * Donghwa Lee, <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/mutex.h>
19#include <linux/wait.h>
20#include <linux/fs.h>
21#include <linux/mm.h>
22#include <linux/fb.h>
23#include <linux/ctype.h>
24#include <linux/platform_device.h>
25#include <linux/io.h>
26#include <linux/memory.h>
27#include <linux/delay.h>
28#include <linux/kthread.h>
29
30#include <video/mipi_display.h>
31#include <video/exynos_mipi_dsim.h>
32
33#include <mach/map.h>
34
35#include "exynos_mipi_dsi_regs.h"
36#include "exynos_mipi_dsi_lowlevel.h"
37#include "exynos_mipi_dsi_common.h"
38
39#define MIPI_FIFO_TIMEOUT msecs_to_jiffies(250)
40#define MIPI_RX_FIFO_READ_DONE 0x30800002
41#define MIPI_MAX_RX_FIFO 20
42#define MHZ (1000 * 1000)
43#define FIN_HZ (24 * MHZ)
44
45#define DFIN_PLL_MIN_HZ (6 * MHZ)
46#define DFIN_PLL_MAX_HZ (12 * MHZ)
47
48#define DFVCO_MIN_HZ (500 * MHZ)
49#define DFVCO_MAX_HZ (1000 * MHZ)
50
51#define TRY_GET_FIFO_TIMEOUT (5000 * 2)
52#define TRY_FIFO_CLEAR (10)
53
54/* MIPI-DSIM status types. */
55enum {
56 DSIM_STATE_INIT, /* should be initialized. */
57 DSIM_STATE_STOP, /* CPU and LCDC are LP mode. */
58 DSIM_STATE_HSCLKEN, /* HS clock was enabled. */
59 DSIM_STATE_ULPS
60};
61
62/* define DSI lane types. */
63enum {
64 DSIM_LANE_CLOCK = (1 << 0),
65 DSIM_LANE_DATA0 = (1 << 1),
66 DSIM_LANE_DATA1 = (1 << 2),
67 DSIM_LANE_DATA2 = (1 << 3),
68 DSIM_LANE_DATA3 = (1 << 4)
69};
70
71static unsigned int dpll_table[15] = {
72 100, 120, 170, 220, 270,
73 320, 390, 450, 510, 560,
74 640, 690, 770, 870, 950
75};
76
77irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id)
78{
79 unsigned int intsrc = 0;
80 unsigned int intmsk = 0;
81 struct mipi_dsim_device *dsim = NULL;
82
83 dsim = dev_id;
84 if (!dsim) {
85 dev_dbg(dsim->dev, KERN_ERR "%s:error: wrong parameter\n",
86 __func__);
87 return IRQ_HANDLED;
88 }
89
90 intsrc = exynos_mipi_dsi_read_interrupt(dsim);
91 intmsk = exynos_mipi_dsi_read_interrupt_mask(dsim);
92
93 intmsk = ~(intmsk) & intsrc;
94
95 switch (intmsk) {
96 case INTMSK_RX_DONE:
97 complete(&dsim_rd_comp);
98 dev_dbg(dsim->dev, "MIPI INTMSK_RX_DONE\n");
99 break;
100 case INTMSK_FIFO_EMPTY:
101 complete(&dsim_wr_comp);
102 dev_dbg(dsim->dev, "MIPI INTMSK_FIFO_EMPTY\n");
103 break;
104 default:
105 break;
106 }
107
108 exynos_mipi_dsi_clear_interrupt(dsim, intmsk);
109
110 return IRQ_HANDLED;
111}
112
113/*
114 * write long packet to mipi dsi slave
115 * @dsim: mipi dsim device structure.
116 * @data0: packet data to send.
117 * @data1: size of packet data
118 */
119static void exynos_mipi_dsi_long_data_wr(struct mipi_dsim_device *dsim,
120 const unsigned char *data0, unsigned int data_size)
121{
122 unsigned int data_cnt = 0, payload = 0;
123
124 /* in case that data count is more then 4 */
125 for (data_cnt = 0; data_cnt < data_size; data_cnt += 4) {
126 /*
127 * after sending 4bytes per one time,
128 * send remainder data less then 4.
129 */
130 if ((data_size - data_cnt) < 4) {
131 if ((data_size - data_cnt) == 3) {
132 payload = data0[data_cnt] |
133 data0[data_cnt + 1] << 8 |
134 data0[data_cnt + 2] << 16;
135 dev_dbg(dsim->dev, "count = 3 payload = %x, %x %x %x\n",
136 payload, data0[data_cnt],
137 data0[data_cnt + 1],
138 data0[data_cnt + 2]);
139 } else if ((data_size - data_cnt) == 2) {
140 payload = data0[data_cnt] |
141 data0[data_cnt + 1] << 8;
142 dev_dbg(dsim->dev,
143 "count = 2 payload = %x, %x %x\n", payload,
144 data0[data_cnt],
145 data0[data_cnt + 1]);
146 } else if ((data_size - data_cnt) == 1) {
147 payload = data0[data_cnt];
148 }
149
150 exynos_mipi_dsi_wr_tx_data(dsim, payload);
151 /* send 4bytes per one time. */
152 } else {
153 payload = data0[data_cnt] |
154 data0[data_cnt + 1] << 8 |
155 data0[data_cnt + 2] << 16 |
156 data0[data_cnt + 3] << 24;
157
158 dev_dbg(dsim->dev,
159 "count = 4 payload = %x, %x %x %x %x\n",
160 payload, *(u8 *)(data0 + data_cnt),
161 data0[data_cnt + 1],
162 data0[data_cnt + 2],
163 data0[data_cnt + 3]);
164
165 exynos_mipi_dsi_wr_tx_data(dsim, payload);
166 }
167 }
168}
169
170int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
171 const unsigned char *data0, unsigned int data_size)
172{
173 unsigned int check_rx_ack = 0;
174
175 if (dsim->state == DSIM_STATE_ULPS) {
176 dev_err(dsim->dev, "state is ULPS.\n");
177
178 return -EINVAL;
179 }
180
181 /* FIXME!!! why does it need this delay? */
182 msleep(20);
183
184 mutex_lock(&dsim->lock);
185
186 switch (data_id) {
187 /* short packet types of packet types for command. */
188 case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
189 case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
190 case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
191 case MIPI_DSI_DCS_SHORT_WRITE:
192 case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
193 case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
194 exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]);
195 if (check_rx_ack) {
196 /* process response func should be implemented */
197 mutex_unlock(&dsim->lock);
198 return 0;
199 } else {
200 mutex_unlock(&dsim->lock);
201 return -EINVAL;
202 }
203
204 /* general command */
205 case MIPI_DSI_COLOR_MODE_OFF:
206 case MIPI_DSI_COLOR_MODE_ON:
207 case MIPI_DSI_SHUTDOWN_PERIPHERAL:
208 case MIPI_DSI_TURN_ON_PERIPHERAL:
209 exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]);
210 if (check_rx_ack) {
211 /* process response func should be implemented. */
212 mutex_unlock(&dsim->lock);
213 return 0;
214 } else {
215 mutex_unlock(&dsim->lock);
216 return -EINVAL;
217 }
218
219 /* packet types for video data */
220 case MIPI_DSI_V_SYNC_START:
221 case MIPI_DSI_V_SYNC_END:
222 case MIPI_DSI_H_SYNC_START:
223 case MIPI_DSI_H_SYNC_END:
224 case MIPI_DSI_END_OF_TRANSMISSION:
225 mutex_unlock(&dsim->lock);
226 return 0;
227
228 /* long packet type and null packet */
229 case MIPI_DSI_NULL_PACKET:
230 case MIPI_DSI_BLANKING_PACKET:
231 mutex_unlock(&dsim->lock);
232 return 0;
233 case MIPI_DSI_GENERIC_LONG_WRITE:
234 case MIPI_DSI_DCS_LONG_WRITE:
235 {
236 unsigned int size, payload = 0;
237 INIT_COMPLETION(dsim_wr_comp);
238
239 size = data_size * 4;
240
241 /* if data count is less then 4, then send 3bytes data. */
242 if (data_size < 4) {
243 payload = data0[0] |
244 data0[1] << 8 |
245 data0[2] << 16;
246
247 exynos_mipi_dsi_wr_tx_data(dsim, payload);
248
249 dev_dbg(dsim->dev, "count = %d payload = %x,%x %x %x\n",
250 data_size, payload, data0[0],
251 data0[1], data0[2]);
252
253 /* in case that data count is more then 4 */
254 } else
255 exynos_mipi_dsi_long_data_wr(dsim, data0, data_size);
256
257 /* put data into header fifo */
258 exynos_mipi_dsi_wr_tx_header(dsim, data_id, data_size & 0xff,
259 (data_size & 0xff00) >> 8);
260
261 if (!wait_for_completion_interruptible_timeout(&dsim_wr_comp,
262 MIPI_FIFO_TIMEOUT)) {
263 dev_warn(dsim->dev, "command write timeout.\n");
264 mutex_unlock(&dsim->lock);
265 return -EAGAIN;
266 }
267
268 if (check_rx_ack) {
269 /* process response func should be implemented. */
270 mutex_unlock(&dsim->lock);
271 return 0;
272 } else {
273 mutex_unlock(&dsim->lock);
274 return -EINVAL;
275 }
276 }
277
278 /* packet typo for video data */
279 case MIPI_DSI_PACKED_PIXEL_STREAM_16:
280 case MIPI_DSI_PACKED_PIXEL_STREAM_18:
281 case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
282 case MIPI_DSI_PACKED_PIXEL_STREAM_24:
283 if (check_rx_ack) {
284 /* process response func should be implemented. */
285 mutex_unlock(&dsim->lock);
286 return 0;
287 } else {
288 mutex_unlock(&dsim->lock);
289 return -EINVAL;
290 }
291 default:
292 dev_warn(dsim->dev,
293 "data id %x is not supported current DSI spec.\n",
294 data_id);
295
296 mutex_unlock(&dsim->lock);
297 return -EINVAL;
298 }
299
300 mutex_unlock(&dsim->lock);
301 return 0;
302}
303
304static unsigned int exynos_mipi_dsi_long_data_rd(struct mipi_dsim_device *dsim,
305 unsigned int req_size, unsigned int rx_data, u8 *rx_buf)
306{
307 unsigned int rcv_pkt, i, j;
308 u16 rxsize;
309
310 /* for long packet */
311 rxsize = (u16)((rx_data & 0x00ffff00) >> 8);
312 dev_dbg(dsim->dev, "mipi dsi rx size : %d\n", rxsize);
313 if (rxsize != req_size) {
314 dev_dbg(dsim->dev,
315 "received size mismatch received: %d, requested: %d\n",
316 rxsize, req_size);
317 goto err;
318 }
319
320 for (i = 0; i < (rxsize >> 2); i++) {
321 rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
322 dev_dbg(dsim->dev, "received pkt : %08x\n", rcv_pkt);
323 for (j = 0; j < 4; j++) {
324 rx_buf[(i * 4) + j] =
325 (u8)(rcv_pkt >> (j * 8)) & 0xff;
326 dev_dbg(dsim->dev, "received value : %02x\n",
327 (rcv_pkt >> (j * 8)) & 0xff);
328 }
329 }
330 if (rxsize % 4) {
331 rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
332 dev_dbg(dsim->dev, "received pkt : %08x\n", rcv_pkt);
333 for (j = 0; j < (rxsize % 4); j++) {
334 rx_buf[(i * 4) + j] =
335 (u8)(rcv_pkt >> (j * 8)) & 0xff;
336 dev_dbg(dsim->dev, "received value : %02x\n",
337 (rcv_pkt >> (j * 8)) & 0xff);
338 }
339 }
340
341 return rxsize;
342
343err:
344 return -EINVAL;
345}
346
347static unsigned int exynos_mipi_dsi_response_size(unsigned int req_size)
348{
349 switch (req_size) {
350 case 1:
351 return MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE;
352 case 2:
353 return MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE;
354 default:
355 return MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE;
356 }
357}
358
359int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id,
360 unsigned int data0, unsigned int req_size, u8 *rx_buf)
361{
362 unsigned int rx_data, rcv_pkt, i;
363 u8 response = 0;
364 u16 rxsize;
365
366 if (dsim->state == DSIM_STATE_ULPS) {
367 dev_err(dsim->dev, "state is ULPS.\n");
368
369 return -EINVAL;
370 }
371
372 /* FIXME!!! */
373 msleep(20);
374
375 mutex_lock(&dsim->lock);
376 INIT_COMPLETION(dsim_rd_comp);
377 exynos_mipi_dsi_rd_tx_header(dsim,
378 MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, req_size);
379
380 response = exynos_mipi_dsi_response_size(req_size);
381
382 switch (data_id) {
383 case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
384 case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
385 case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
386 case MIPI_DSI_DCS_READ:
387 exynos_mipi_dsi_rd_tx_header(dsim,
388 data_id, data0);
389 /* process response func should be implemented. */
390 break;
391 default:
392 dev_warn(dsim->dev,
393 "data id %x is not supported current DSI spec.\n",
394 data_id);
395
396 return -EINVAL;
397 }
398
399 if (!wait_for_completion_interruptible_timeout(&dsim_rd_comp,
400 MIPI_FIFO_TIMEOUT)) {
401 pr_err("RX done interrupt timeout\n");
402 mutex_unlock(&dsim->lock);
403 return 0;
404 }
405
406 msleep(20);
407
408 rx_data = exynos_mipi_dsi_rd_rx_fifo(dsim);
409
410 if ((u8)(rx_data & 0xff) != response) {
411 printk(KERN_ERR
412 "mipi dsi wrong response rx_data : %x, response:%x\n",
413 rx_data, response);
414 goto clear_rx_fifo;
415 }
416
417 if (req_size <= 2) {
418 /* for short packet */
419 for (i = 0; i < req_size; i++)
420 rx_buf[i] = (rx_data >> (8 + (i * 8))) & 0xff;
421 rxsize = req_size;
422 } else {
423 /* for long packet */
424 rxsize = exynos_mipi_dsi_long_data_rd(dsim, req_size, rx_data,
425 rx_buf);
426 if (rxsize != req_size)
427 goto clear_rx_fifo;
428 }
429
430 rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
431
432 msleep(20);
433
434 if (rcv_pkt != MIPI_RX_FIFO_READ_DONE) {
435 dev_info(dsim->dev,
436 "Can't found RX FIFO READ DONE FLAG : %x\n", rcv_pkt);
437 goto clear_rx_fifo;
438 }
439
440 mutex_unlock(&dsim->lock);
441
442 return rxsize;
443
444clear_rx_fifo:
445 i = 0;
446 while (1) {
447 rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
448 if ((rcv_pkt == MIPI_RX_FIFO_READ_DONE)
449 || (i > MIPI_MAX_RX_FIFO))
450 break;
451 dev_dbg(dsim->dev,
452 "mipi dsi clear rx fifo : %08x\n", rcv_pkt);
453 i++;
454 }
455 dev_info(dsim->dev,
456 "mipi dsi rx done count : %d, rcv_pkt : %08x\n", i, rcv_pkt);
457
458 mutex_unlock(&dsim->lock);
459
460 return 0;
461}
462
463static int exynos_mipi_dsi_pll_on(struct mipi_dsim_device *dsim,
464 unsigned int enable)
465{
466 int sw_timeout;
467
468 if (enable) {
469 sw_timeout = 1000;
470
471 exynos_mipi_dsi_enable_pll(dsim, 1);
472 while (1) {
473 sw_timeout--;
474 if (exynos_mipi_dsi_is_pll_stable(dsim))
475 return 0;
476 if (sw_timeout == 0)
477 return -EINVAL;
478 }
479 } else
480 exynos_mipi_dsi_enable_pll(dsim, 0);
481
482 return 0;
483}
484
485static unsigned long exynos_mipi_dsi_change_pll(struct mipi_dsim_device *dsim,
486 unsigned int pre_divider, unsigned int main_divider,
487 unsigned int scaler)
488{
489 unsigned long dfin_pll, dfvco, dpll_out;
490 unsigned int i, freq_band = 0xf;
491
492 dfin_pll = (FIN_HZ / pre_divider);
493
494 /******************************************************
495 * Serial Clock(=ByteClk X 8) FreqBand[3:0] *
496 ******************************************************
497 * ~ 99.99 MHz 0000
498 * 100 ~ 119.99 MHz 0001
499 * 120 ~ 159.99 MHz 0010
500 * 160 ~ 199.99 MHz 0011
501 * 200 ~ 239.99 MHz 0100
502 * 140 ~ 319.99 MHz 0101
503 * 320 ~ 389.99 MHz 0110
504 * 390 ~ 449.99 MHz 0111
505 * 450 ~ 509.99 MHz 1000
506 * 510 ~ 559.99 MHz 1001
507 * 560 ~ 639.99 MHz 1010
508 * 640 ~ 689.99 MHz 1011
509 * 690 ~ 769.99 MHz 1100
510 * 770 ~ 869.99 MHz 1101
511 * 870 ~ 949.99 MHz 1110
512 * 950 ~ 1000 MHz 1111
513 ******************************************************/
514 if (dfin_pll < DFIN_PLL_MIN_HZ || dfin_pll > DFIN_PLL_MAX_HZ) {
515 dev_warn(dsim->dev, "fin_pll range should be 6MHz ~ 12MHz\n");
516 exynos_mipi_dsi_enable_afc(dsim, 0, 0);
517 } else {
518 if (dfin_pll < 7 * MHZ)
519 exynos_mipi_dsi_enable_afc(dsim, 1, 0x1);
520 else if (dfin_pll < 8 * MHZ)
521 exynos_mipi_dsi_enable_afc(dsim, 1, 0x0);
522 else if (dfin_pll < 9 * MHZ)
523 exynos_mipi_dsi_enable_afc(dsim, 1, 0x3);
524 else if (dfin_pll < 10 * MHZ)
525 exynos_mipi_dsi_enable_afc(dsim, 1, 0x2);
526 else if (dfin_pll < 11 * MHZ)
527 exynos_mipi_dsi_enable_afc(dsim, 1, 0x5);
528 else
529 exynos_mipi_dsi_enable_afc(dsim, 1, 0x4);
530 }
531
532 dfvco = dfin_pll * main_divider;
533 dev_dbg(dsim->dev, "dfvco = %lu, dfin_pll = %lu, main_divider = %d\n",
534 dfvco, dfin_pll, main_divider);
535 if (dfvco < DFVCO_MIN_HZ || dfvco > DFVCO_MAX_HZ)
536 dev_warn(dsim->dev, "fvco range should be 500MHz ~ 1000MHz\n");
537
538 dpll_out = dfvco / (1 << scaler);
539 dev_dbg(dsim->dev, "dpll_out = %lu, dfvco = %lu, scaler = %d\n",
540 dpll_out, dfvco, scaler);
541
542 for (i = 0; i < ARRAY_SIZE(dpll_table); i++) {
543 if (dpll_out < dpll_table[i] * MHZ) {
544 freq_band = i;
545 break;
546 }
547 }
548
549 dev_dbg(dsim->dev, "freq_band = %d\n", freq_band);
550
551 exynos_mipi_dsi_pll_freq(dsim, pre_divider, main_divider, scaler);
552
553 exynos_mipi_dsi_hs_zero_ctrl(dsim, 0);
554 exynos_mipi_dsi_prep_ctrl(dsim, 0);
555
556 /* Freq Band */
557 exynos_mipi_dsi_pll_freq_band(dsim, freq_band);
558
559 /* Stable time */
560 exynos_mipi_dsi_pll_stable_time(dsim, dsim->dsim_config->pll_stable_time);
561
562 /* Enable PLL */
563 dev_dbg(dsim->dev, "FOUT of mipi dphy pll is %luMHz\n",
564 (dpll_out / MHZ));
565
566 return dpll_out;
567}
568
569static int exynos_mipi_dsi_set_clock(struct mipi_dsim_device *dsim,
570 unsigned int byte_clk_sel, unsigned int enable)
571{
572 unsigned int esc_div;
573 unsigned long esc_clk_error_rate;
574 unsigned long hs_clk = 0, byte_clk = 0, escape_clk = 0;
575
576 if (enable) {
577 dsim->e_clk_src = byte_clk_sel;
578
579 /* Escape mode clock and byte clock source */
580 exynos_mipi_dsi_set_byte_clock_src(dsim, byte_clk_sel);
581
582 /* DPHY, DSIM Link : D-PHY clock out */
583 if (byte_clk_sel == DSIM_PLL_OUT_DIV8) {
584 hs_clk = exynos_mipi_dsi_change_pll(dsim,
585 dsim->dsim_config->p, dsim->dsim_config->m,
586 dsim->dsim_config->s);
587 if (hs_clk == 0) {
588 dev_err(dsim->dev,
589 "failed to get hs clock.\n");
590 return -EINVAL;
591 }
592
593 byte_clk = hs_clk / 8;
594 exynos_mipi_dsi_enable_pll_bypass(dsim, 0);
595 exynos_mipi_dsi_pll_on(dsim, 1);
596 /* DPHY : D-PHY clock out, DSIM link : external clock out */
597 } else if (byte_clk_sel == DSIM_EXT_CLK_DIV8) {
598 dev_warn(dsim->dev, "this project is not support\n");
599 dev_warn(dsim->dev,
600 "external clock source for MIPI DSIM.\n");
601 } else if (byte_clk_sel == DSIM_EXT_CLK_BYPASS) {
602 dev_warn(dsim->dev, "this project is not support\n");
603 dev_warn(dsim->dev,
604 "external clock source for MIPI DSIM\n");
605 }
606
607 /* escape clock divider */
608 esc_div = byte_clk / (dsim->dsim_config->esc_clk);
609 dev_dbg(dsim->dev,
610 "esc_div = %d, byte_clk = %lu, esc_clk = %lu\n",
611 esc_div, byte_clk, dsim->dsim_config->esc_clk);
612 if ((byte_clk / esc_div) >= (20 * MHZ) ||
613 (byte_clk / esc_div) >
614 dsim->dsim_config->esc_clk)
615 esc_div += 1;
616
617 escape_clk = byte_clk / esc_div;
618 dev_dbg(dsim->dev,
619 "escape_clk = %lu, byte_clk = %lu, esc_div = %d\n",
620 escape_clk, byte_clk, esc_div);
621
622 /* enable escape clock. */
623 exynos_mipi_dsi_enable_byte_clock(dsim, 1);
624
625 /* enable byte clk and escape clock */
626 exynos_mipi_dsi_set_esc_clk_prs(dsim, 1, esc_div);
627 /* escape clock on lane */
628 exynos_mipi_dsi_enable_esc_clk_on_lane(dsim,
629 (DSIM_LANE_CLOCK | dsim->data_lane), 1);
630
631 dev_dbg(dsim->dev, "byte clock is %luMHz\n",
632 (byte_clk / MHZ));
633 dev_dbg(dsim->dev, "escape clock that user's need is %lu\n",
634 (dsim->dsim_config->esc_clk / MHZ));
635 dev_dbg(dsim->dev, "escape clock divider is %x\n", esc_div);
636 dev_dbg(dsim->dev, "escape clock is %luMHz\n",
637 ((byte_clk / esc_div) / MHZ));
638
639 if ((byte_clk / esc_div) > escape_clk) {
640 esc_clk_error_rate = escape_clk /
641 (byte_clk / esc_div);
642 dev_warn(dsim->dev, "error rate is %lu over.\n",
643 (esc_clk_error_rate / 100));
644 } else if ((byte_clk / esc_div) < (escape_clk)) {
645 esc_clk_error_rate = (byte_clk / esc_div) /
646 escape_clk;
647 dev_warn(dsim->dev, "error rate is %lu under.\n",
648 (esc_clk_error_rate / 100));
649 }
650 } else {
651 exynos_mipi_dsi_enable_esc_clk_on_lane(dsim,
652 (DSIM_LANE_CLOCK | dsim->data_lane), 0);
653 exynos_mipi_dsi_set_esc_clk_prs(dsim, 0, 0);
654
655 /* disable escape clock. */
656 exynos_mipi_dsi_enable_byte_clock(dsim, 0);
657
658 if (byte_clk_sel == DSIM_PLL_OUT_DIV8)
659 exynos_mipi_dsi_pll_on(dsim, 0);
660 }
661
662 return 0;
663}
664
665int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim)
666{
667 dsim->state = DSIM_STATE_INIT;
668
669 switch (dsim->dsim_config->e_no_data_lane) {
670 case DSIM_DATA_LANE_1:
671 dsim->data_lane = DSIM_LANE_DATA0;
672 break;
673 case DSIM_DATA_LANE_2:
674 dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1;
675 break;
676 case DSIM_DATA_LANE_3:
677 dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
678 DSIM_LANE_DATA2;
679 break;
680 case DSIM_DATA_LANE_4:
681 dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
682 DSIM_LANE_DATA2 | DSIM_LANE_DATA3;
683 break;
684 default:
685 dev_info(dsim->dev, "data lane is invalid.\n");
686 return -EINVAL;
687 };
688
689 exynos_mipi_dsi_sw_reset(dsim);
690 exynos_mipi_dsi_func_reset(dsim);
691
692 exynos_mipi_dsi_dp_dn_swap(dsim, 0);
693
694 return 0;
695}
696
697void exynos_mipi_dsi_init_interrupt(struct mipi_dsim_device *dsim)
698{
699 unsigned int src = 0;
700
701 src = (INTSRC_SFR_FIFO_EMPTY | INTSRC_RX_DATA_DONE);
702 exynos_mipi_dsi_set_interrupt(dsim, src, 1);
703
704 src = 0;
705 src = ~(INTMSK_RX_DONE | INTMSK_FIFO_EMPTY);
706 exynos_mipi_dsi_set_interrupt_mask(dsim, src, 1);
707}
708
709int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim,
710 unsigned int enable)
711{
712 /* enable only frame done interrupt */
713 exynos_mipi_dsi_set_interrupt_mask(dsim, INTMSK_FRAME_DONE, enable);
714
715 return 0;
716}
717
718void exynos_mipi_dsi_stand_by(struct mipi_dsim_device *dsim,
719 unsigned int enable)
720{
721
722 /* consider Main display and Sub display. */
723
724 exynos_mipi_dsi_set_main_stand_by(dsim, enable);
725}
726
727int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim,
728 struct mipi_dsim_config *dsim_config)
729{
730 struct mipi_dsim_platform_data *dsim_pd;
731 struct fb_videomode *timing;
732
733 dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
734 timing = (struct fb_videomode *)dsim_pd->lcd_panel_info;
735
736 /* in case of VIDEO MODE (RGB INTERFACE), it sets polarities. */
737 if (dsim_config->e_interface == (u32) DSIM_VIDEO) {
738 if (dsim_config->auto_vertical_cnt == 0) {
739 exynos_mipi_dsi_set_main_disp_vporch(dsim,
740 dsim_config->cmd_allow,
741 timing->upper_margin,
742 timing->lower_margin);
743 exynos_mipi_dsi_set_main_disp_hporch(dsim,
744 timing->left_margin,
745 timing->right_margin);
746 exynos_mipi_dsi_set_main_disp_sync_area(dsim,
747 timing->vsync_len,
748 timing->hsync_len);
749 }
750 }
751
752 exynos_mipi_dsi_set_main_disp_resol(dsim, timing->xres,
753 timing->yres);
754
755 exynos_mipi_dsi_display_config(dsim, dsim_config);
756
757 dev_info(dsim->dev, "lcd panel ==> width = %d, height = %d\n",
758 timing->xres, timing->yres);
759
760 return 0;
761}
762
763int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim)
764{
765 unsigned int time_out = 100;
766
767 switch (dsim->state) {
768 case DSIM_STATE_INIT:
769 exynos_mipi_dsi_init_fifo_pointer(dsim, 0x1f);
770
771 /* dsi configuration */
772 exynos_mipi_dsi_init_config(dsim);
773 exynos_mipi_dsi_enable_lane(dsim, DSIM_LANE_CLOCK, 1);
774 exynos_mipi_dsi_enable_lane(dsim, dsim->data_lane, 1);
775
776 /* set clock configuration */
777 exynos_mipi_dsi_set_clock(dsim, dsim->dsim_config->e_byte_clk, 1);
778
779 /* check clock and data lane state are stop state */
780 while (!(exynos_mipi_dsi_is_lane_state(dsim))) {
781 time_out--;
782 if (time_out == 0) {
783 dev_err(dsim->dev,
784 "DSI Master is not stop state.\n");
785 dev_err(dsim->dev,
786 "Check initialization process\n");
787
788 return -EINVAL;
789 }
790 }
791 if (time_out != 0) {
792 dev_info(dsim->dev,
793 "DSI Master driver has been completed.\n");
794 dev_info(dsim->dev, "DSI Master state is stop state\n");
795 }
796
797 dsim->state = DSIM_STATE_STOP;
798
799 /* BTA sequence counters */
800 exynos_mipi_dsi_set_stop_state_counter(dsim,
801 dsim->dsim_config->stop_holding_cnt);
802 exynos_mipi_dsi_set_bta_timeout(dsim,
803 dsim->dsim_config->bta_timeout);
804 exynos_mipi_dsi_set_lpdr_timeout(dsim,
805 dsim->dsim_config->rx_timeout);
806
807 return 0;
808 default:
809 dev_info(dsim->dev, "DSI Master is already init.\n");
810 return 0;
811 }
812
813 return 0;
814}
815
816int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim)
817{
818 if (dsim->state != DSIM_STATE_STOP) {
819 dev_warn(dsim->dev, "DSIM is not in stop state.\n");
820 return 0;
821 }
822
823 if (dsim->e_clk_src == DSIM_EXT_CLK_BYPASS) {
824 dev_warn(dsim->dev, "clock source is external bypass.\n");
825 return 0;
826 }
827
828 dsim->state = DSIM_STATE_HSCLKEN;
829
830 /* set LCDC and CPU transfer mode to HS. */
831 exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0);
832 exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0);
833 exynos_mipi_dsi_enable_hs_clock(dsim, 1);
834
835 return 0;
836}
837
838int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim,
839 unsigned int mode)
840{
841 if (mode) {
842 if (dsim->state != DSIM_STATE_HSCLKEN) {
843 dev_err(dsim->dev, "HS Clock lane is not enabled.\n");
844 return -EINVAL;
845 }
846
847 exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0);
848 } else {
849 if (dsim->state == DSIM_STATE_INIT || dsim->state ==
850 DSIM_STATE_ULPS) {
851 dev_err(dsim->dev,
852 "DSI Master is not STOP or HSDT state.\n");
853 return -EINVAL;
854 }
855
856 exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0);
857 }
858
859 return 0;
860}
861
862int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim)
863{
864 return _exynos_mipi_dsi_get_frame_done_status(dsim);
865}
866
867int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim)
868{
869 _exynos_mipi_dsi_clear_frame_done(dsim);
870
871 return 0;
872}
873
874int exynos_mipi_dsi_fifo_clear(struct mipi_dsim_device *dsim,
875 unsigned int val)
876{
877 int try = TRY_FIFO_CLEAR;
878
879 exynos_mipi_dsi_sw_reset_release(dsim);
880 exynos_mipi_dsi_func_reset(dsim);
881
882 do {
883 if (exynos_mipi_dsi_get_sw_reset_release(dsim)) {
884 exynos_mipi_dsi_init_interrupt(dsim);
885 dev_dbg(dsim->dev, "reset release done.\n");
886 return 0;
887 }
888 } while (--try);
889
890 dev_err(dsim->dev, "failed to clear dsim fifo.\n");
891 return -EAGAIN;
892}
893
894MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
895MODULE_DESCRIPTION("Samusung SoC MIPI-DSI common driver");
896MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.h b/drivers/video/exynos/exynos_mipi_dsi_common.h
new file mode 100644
index 000000000000..412552274df3
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_common.h
@@ -0,0 +1,46 @@
1/* linux/drivers/video/exynos_mipi_dsi_common.h
2 *
3 * Header file for Samsung SoC MIPI-DSI common driver.
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae <inki.dae@samsung.com>
8 * Donghwa Lee <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#ifndef _EXYNOS_MIPI_DSI_COMMON_H
16#define _EXYNOS_MIPI_DSI_COMMON_H
17
18static DECLARE_COMPLETION(dsim_rd_comp);
19static DECLARE_COMPLETION(dsim_wr_comp);
20
21int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
22 const unsigned char *data0, unsigned int data_size);
23int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id,
24 unsigned int data0, unsigned int req_size, u8 *rx_buf);
25irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id);
26void exynos_mipi_dsi_init_interrupt(struct mipi_dsim_device *dsim);
27int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim);
28void exynos_mipi_dsi_stand_by(struct mipi_dsim_device *dsim,
29 unsigned int enable);
30int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim,
31 struct mipi_dsim_config *dsim_info);
32int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim);
33int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim);
34int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim,
35 unsigned int mode);
36int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim,
37 unsigned int enable);
38int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim);
39int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim);
40
41extern struct fb_info *registered_fb[FB_MAX] __read_mostly;
42
43int exynos_mipi_dsi_fifo_clear(struct mipi_dsim_device *dsim,
44 unsigned int val);
45
46#endif /* _EXYNOS_MIPI_DSI_COMMON_H */
diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
new file mode 100644
index 000000000000..0ef38ce72af6
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
@@ -0,0 +1,618 @@
1/* linux/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
2 *
3 * Samsung SoC MIPI-DSI lowlevel driver.
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae, <inki.dae@samsung.com>
8 * Donghwa Lee, <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/mutex.h>
19#include <linux/wait.h>
20#include <linux/delay.h>
21#include <linux/fs.h>
22#include <linux/mm.h>
23#include <linux/ctype.h>
24#include <linux/io.h>
25
26#include <video/exynos_mipi_dsim.h>
27
28#include <mach/map.h>
29
30#include "exynos_mipi_dsi_regs.h"
31
32void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim)
33{
34 unsigned int reg;
35
36 reg = readl(dsim->reg_base + EXYNOS_DSIM_SWRST);
37
38 reg |= DSIM_FUNCRST;
39
40 writel(reg, dsim->reg_base + EXYNOS_DSIM_SWRST);
41}
42
43void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim)
44{
45 unsigned int reg;
46
47 reg = readl(dsim->reg_base + EXYNOS_DSIM_SWRST);
48
49 reg |= DSIM_SWRST;
50
51 writel(reg, dsim->reg_base + EXYNOS_DSIM_SWRST);
52}
53
54void exynos_mipi_dsi_sw_reset_release(struct mipi_dsim_device *dsim)
55{
56 unsigned int reg;
57
58 reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
59
60 reg |= INTSRC_SW_RST_RELEASE;
61
62 writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
63}
64
65int exynos_mipi_dsi_get_sw_reset_release(struct mipi_dsim_device *dsim)
66{
67 return (readl(dsim->reg_base + EXYNOS_DSIM_INTSRC)) &
68 INTSRC_SW_RST_RELEASE;
69}
70
71unsigned int exynos_mipi_dsi_read_interrupt_mask(struct mipi_dsim_device *dsim)
72{
73 unsigned int reg;
74
75 reg = readl(dsim->reg_base + EXYNOS_DSIM_INTMSK);
76
77 return reg;
78}
79
80void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim,
81 unsigned int mode, unsigned int mask)
82{
83 unsigned int reg = 0;
84
85 if (mask)
86 reg |= mode;
87 else
88 reg &= ~mode;
89
90 writel(reg, dsim->reg_base + EXYNOS_DSIM_INTMSK);
91}
92
93void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim,
94 unsigned int cfg)
95{
96 unsigned int reg;
97
98 reg = readl(dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
99
100 writel(reg & ~(cfg), dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
101 mdelay(10);
102 reg |= cfg;
103
104 writel(reg, dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
105}
106
107/*
108 * this function set PLL P, M and S value in D-PHY
109 */
110void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
111 unsigned int value)
112{
113 writel(DSIM_AFC_CTL(value), dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
114}
115
116void exynos_mipi_dsi_set_main_stand_by(struct mipi_dsim_device *dsim,
117 unsigned int enable)
118{
119 unsigned int reg;
120
121 reg = readl(dsim->reg_base + EXYNOS_DSIM_MDRESOL);
122
123 reg &= ~DSIM_MAIN_STAND_BY;
124
125 if (enable)
126 reg |= DSIM_MAIN_STAND_BY;
127
128 writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
129}
130
131void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim,
132 unsigned int width_resol, unsigned int height_resol)
133{
134 unsigned int reg;
135
136 /* standby should be set after configuration so set to not ready*/
137 reg = (readl(dsim->reg_base + EXYNOS_DSIM_MDRESOL)) &
138 ~(DSIM_MAIN_STAND_BY);
139 writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
140
141 reg &= ~((0x7ff << 16) | (0x7ff << 0));
142 reg |= DSIM_MAIN_VRESOL(height_resol) | DSIM_MAIN_HRESOL(width_resol);
143
144 reg |= DSIM_MAIN_STAND_BY;
145 writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
146}
147
148void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim,
149 unsigned int cmd_allow, unsigned int vfront, unsigned int vback)
150{
151 unsigned int reg;
152
153 reg = (readl(dsim->reg_base + EXYNOS_DSIM_MVPORCH)) &
154 ~((DSIM_CMD_ALLOW_MASK) | (DSIM_STABLE_VFP_MASK) |
155 (DSIM_MAIN_VBP_MASK));
156
157 reg |= (DSIM_CMD_ALLOW_SHIFT(cmd_allow & 0xf) |
158 DSIM_STABLE_VFP_SHIFT(vfront & 0x7ff) |
159 DSIM_MAIN_VBP_SHIFT(vback & 0x7ff));
160
161 writel(reg, dsim->reg_base + EXYNOS_DSIM_MVPORCH);
162}
163
164void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim,
165 unsigned int front, unsigned int back)
166{
167 unsigned int reg;
168
169 reg = (readl(dsim->reg_base + EXYNOS_DSIM_MHPORCH)) &
170 ~((DSIM_MAIN_HFP_MASK) | (DSIM_MAIN_HBP_MASK));
171
172 reg |= DSIM_MAIN_HFP_SHIFT(front) | DSIM_MAIN_HBP_SHIFT(back);
173
174 writel(reg, dsim->reg_base + EXYNOS_DSIM_MHPORCH);
175}
176
177void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim,
178 unsigned int vert, unsigned int hori)
179{
180 unsigned int reg;
181
182 reg = (readl(dsim->reg_base + EXYNOS_DSIM_MSYNC)) &
183 ~((DSIM_MAIN_VSA_MASK) | (DSIM_MAIN_HSA_MASK));
184
185 reg |= (DSIM_MAIN_VSA_SHIFT(vert & 0x3ff) |
186 DSIM_MAIN_HSA_SHIFT(hori));
187
188 writel(reg, dsim->reg_base + EXYNOS_DSIM_MSYNC);
189}
190
191void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim,
192 unsigned int vert, unsigned int hori)
193{
194 unsigned int reg;
195
196 reg = (readl(dsim->reg_base + EXYNOS_DSIM_SDRESOL)) &
197 ~(DSIM_SUB_STANDY_MASK);
198
199 writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
200
201 reg &= ~(DSIM_SUB_VRESOL_MASK) | ~(DSIM_SUB_HRESOL_MASK);
202 reg |= (DSIM_SUB_VRESOL_SHIFT(vert & 0x7ff) |
203 DSIM_SUB_HRESOL_SHIFT(hori & 0x7ff));
204 writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
205
206 reg |= DSIM_SUB_STANDY_SHIFT(1);
207 writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
208}
209
210void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim)
211{
212 struct mipi_dsim_config *dsim_config = dsim->dsim_config;
213
214 unsigned int cfg = (readl(dsim->reg_base + EXYNOS_DSIM_CONFIG)) &
215 ~((1 << 28) | (0x1f << 20) | (0x3 << 5));
216
217 cfg = ((DSIM_AUTO_FLUSH(dsim_config->auto_flush)) |
218 (DSIM_EOT_DISABLE(dsim_config->eot_disable)) |
219 (DSIM_AUTO_MODE_SHIFT(dsim_config->auto_vertical_cnt)) |
220 (DSIM_HSE_MODE_SHIFT(dsim_config->hse)) |
221 (DSIM_HFP_MODE_SHIFT(dsim_config->hfp)) |
222 (DSIM_HBP_MODE_SHIFT(dsim_config->hbp)) |
223 (DSIM_HSA_MODE_SHIFT(dsim_config->hsa)) |
224 (DSIM_NUM_OF_DATALANE_SHIFT(dsim_config->e_no_data_lane)));
225
226 writel(cfg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
227}
228
229void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim,
230 struct mipi_dsim_config *dsim_config)
231{
232 u32 reg = (readl(dsim->reg_base + EXYNOS_DSIM_CONFIG)) &
233 ~((0x3 << 26) | (1 << 25) | (0x3 << 18) | (0x7 << 12) |
234 (0x3 << 16) | (0x7 << 8));
235
236 if (dsim_config->e_interface == DSIM_VIDEO)
237 reg |= (1 << 25);
238 else if (dsim_config->e_interface == DSIM_COMMAND)
239 reg &= ~(1 << 25);
240 else {
241 dev_err(dsim->dev, "unknown lcd type.\n");
242 return;
243 }
244
245 /* main lcd */
246 reg |= ((u8) (dsim_config->e_burst_mode) & 0x3) << 26 |
247 ((u8) (dsim_config->e_virtual_ch) & 0x3) << 18 |
248 ((u8) (dsim_config->e_pixel_format) & 0x7) << 12;
249
250 writel(reg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
251}
252
253void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, unsigned int lane,
254 unsigned int enable)
255{
256 unsigned int reg;
257
258 reg = readl(dsim->reg_base + EXYNOS_DSIM_CONFIG);
259
260 if (enable)
261 reg |= DSIM_LANE_ENx(lane);
262 else
263 reg &= ~DSIM_LANE_ENx(lane);
264
265 writel(reg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
266}
267
268
269void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
270 unsigned int count)
271{
272 unsigned int cfg;
273
274 /* get the data lane number. */
275 cfg = DSIM_NUM_OF_DATALANE_SHIFT(count);
276
277 writel(cfg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
278}
279
280void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, unsigned int enable,
281 unsigned int afc_code)
282{
283 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
284
285 if (enable) {
286 reg |= (1 << 14);
287 reg &= ~(0x7 << 5);
288 reg |= (afc_code & 0x7) << 5;
289 } else
290 reg &= ~(1 << 14);
291
292 writel(reg, dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
293}
294
295void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim,
296 unsigned int enable)
297{
298 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
299 ~(DSIM_PLL_BYPASS_SHIFT(0x1));
300
301 reg |= DSIM_PLL_BYPASS_SHIFT(enable);
302
303 writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
304}
305
306void exynos_mipi_dsi_set_pll_pms(struct mipi_dsim_device *dsim, unsigned int p,
307 unsigned int m, unsigned int s)
308{
309 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
310
311 reg |= ((p & 0x3f) << 13) | ((m & 0x1ff) << 4) | ((s & 0x7) << 1);
312
313 writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
314}
315
316void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim,
317 unsigned int freq_band)
318{
319 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
320 ~(DSIM_FREQ_BAND_SHIFT(0x1f));
321
322 reg |= DSIM_FREQ_BAND_SHIFT(freq_band & 0x1f);
323
324 writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
325}
326
327void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim,
328 unsigned int pre_divider, unsigned int main_divider,
329 unsigned int scaler)
330{
331 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
332 ~(0x7ffff << 1);
333
334 reg |= (pre_divider & 0x3f) << 13 | (main_divider & 0x1ff) << 4 |
335 (scaler & 0x7) << 1;
336
337 writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
338}
339
340void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim,
341 unsigned int lock_time)
342{
343 writel(lock_time, dsim->reg_base + EXYNOS_DSIM_PLLTMR);
344}
345
346void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim, unsigned int enable)
347{
348 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
349 ~(DSIM_PLL_EN_SHIFT(0x1));
350
351 reg |= DSIM_PLL_EN_SHIFT(enable & 0x1);
352
353 writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
354}
355
356void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim,
357 unsigned int src)
358{
359 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
360 ~(DSIM_BYTE_CLK_SRC_SHIFT(0x3));
361
362 reg |= (DSIM_BYTE_CLK_SRC_SHIFT(src));
363
364 writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
365}
366
367void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim,
368 unsigned int enable)
369{
370 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
371 ~(DSIM_BYTE_CLKEN_SHIFT(0x1));
372
373 reg |= DSIM_BYTE_CLKEN_SHIFT(enable);
374
375 writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
376}
377
378void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim,
379 unsigned int enable, unsigned int prs_val)
380{
381 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
382 ~(DSIM_ESC_CLKEN_SHIFT(0x1) | 0xffff);
383
384 reg |= DSIM_ESC_CLKEN_SHIFT(enable);
385 if (enable)
386 reg |= prs_val;
387
388 writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
389}
390
391void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim,
392 unsigned int lane_sel, unsigned int enable)
393{
394 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
395
396 if (enable)
397 reg |= DSIM_LANE_ESC_CLKEN(lane_sel);
398 else
399
400 reg &= ~DSIM_LANE_ESC_CLKEN(lane_sel);
401
402 writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
403}
404
405void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim,
406 unsigned int enable)
407{
408 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE)) &
409 ~(DSIM_FORCE_STOP_STATE_SHIFT(0x1));
410
411 reg |= (DSIM_FORCE_STOP_STATE_SHIFT(enable & 0x1));
412
413 writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
414}
415
416unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim)
417{
418 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_STATUS);
419
420 /**
421 * check clock and data lane states.
422 * if MIPI-DSI controller was enabled at bootloader then
423 * TX_READY_HS_CLK is enabled otherwise STOP_STATE_CLK.
424 * so it should be checked for two case.
425 */
426 if ((reg & DSIM_STOP_STATE_DAT(0xf)) &&
427 ((reg & DSIM_STOP_STATE_CLK) ||
428 (reg & DSIM_TX_READY_HS_CLK)))
429 return 1;
430
431 return 0;
432}
433
434void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim,
435 unsigned int cnt_val)
436{
437 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE)) &
438 ~(DSIM_STOP_STATE_CNT_SHIFT(0x7ff));
439
440 reg |= (DSIM_STOP_STATE_CNT_SHIFT(cnt_val & 0x7ff));
441
442 writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
443}
444
445void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim,
446 unsigned int timeout)
447{
448 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_TIMEOUT)) &
449 ~(DSIM_BTA_TOUT_SHIFT(0xff));
450
451 reg |= (DSIM_BTA_TOUT_SHIFT(timeout));
452
453 writel(reg, dsim->reg_base + EXYNOS_DSIM_TIMEOUT);
454}
455
456void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim,
457 unsigned int timeout)
458{
459 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_TIMEOUT)) &
460 ~(DSIM_LPDR_TOUT_SHIFT(0xffff));
461
462 reg |= (DSIM_LPDR_TOUT_SHIFT(timeout));
463
464 writel(reg, dsim->reg_base + EXYNOS_DSIM_TIMEOUT);
465}
466
467void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim,
468 unsigned int lp)
469{
470 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE);
471
472 reg &= ~DSIM_CMD_LPDT_LP;
473
474 if (lp)
475 reg |= DSIM_CMD_LPDT_LP;
476
477 writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
478}
479
480void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim,
481 unsigned int lp)
482{
483 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE);
484
485 reg &= ~DSIM_TX_LPDT_LP;
486
487 if (lp)
488 reg |= DSIM_TX_LPDT_LP;
489
490 writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
491}
492
493void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim,
494 unsigned int enable)
495{
496 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
497 ~(DSIM_TX_REQUEST_HSCLK_SHIFT(0x1));
498
499 reg |= DSIM_TX_REQUEST_HSCLK_SHIFT(enable);
500
501 writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
502}
503
504void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim,
505 unsigned int swap_en)
506{
507 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PHYACCHR1);
508
509 reg &= ~(0x3 << 0);
510 reg |= (swap_en & 0x3) << 0;
511
512 writel(reg, dsim->reg_base + EXYNOS_DSIM_PHYACCHR1);
513}
514
515void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim,
516 unsigned int hs_zero)
517{
518 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
519 ~(0xf << 28);
520
521 reg |= ((hs_zero & 0xf) << 28);
522
523 writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
524}
525
526void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep)
527{
528 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
529 ~(0x7 << 20);
530
531 reg |= ((prep & 0x7) << 20);
532
533 writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
534}
535
536unsigned int exynos_mipi_dsi_read_interrupt(struct mipi_dsim_device *dsim)
537{
538 return readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
539}
540
541void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim,
542 unsigned int src)
543{
544 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
545
546 reg |= src;
547
548 writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
549}
550
551void exynos_mipi_dsi_set_interrupt(struct mipi_dsim_device *dsim,
552 unsigned int src, unsigned int enable)
553{
554 unsigned int reg = 0;
555
556 if (enable)
557 reg |= src;
558 else
559 reg &= ~src;
560
561 writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
562}
563
564unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim)
565{
566 unsigned int reg;
567
568 reg = readl(dsim->reg_base + EXYNOS_DSIM_STATUS);
569
570 return reg & (1 << 31) ? 1 : 0;
571}
572
573unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim)
574{
575 return readl(dsim->reg_base + EXYNOS_DSIM_FIFOCTRL) & ~(0x1f);
576}
577
578void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim,
579 unsigned int di, unsigned int data0, unsigned int data1)
580{
581 unsigned int reg = (data1 << 16) | (data0 << 8) | ((di & 0x3f) << 0);
582
583 writel(reg, dsim->reg_base + EXYNOS_DSIM_PKTHDR);
584}
585
586void exynos_mipi_dsi_rd_tx_header(struct mipi_dsim_device *dsim,
587 unsigned int di, unsigned int data0)
588{
589 unsigned int reg = (data0 << 8) | (di << 0);
590
591 writel(reg, dsim->reg_base + EXYNOS_DSIM_PKTHDR);
592}
593
594unsigned int exynos_mipi_dsi_rd_rx_fifo(struct mipi_dsim_device *dsim)
595{
596 return readl(dsim->reg_base + EXYNOS_DSIM_RXFIFO);
597}
598
599unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim)
600{
601 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
602
603 return (reg & INTSRC_FRAME_DONE) ? 1 : 0;
604}
605
606void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim)
607{
608 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
609
610 writel(reg | INTSRC_FRAME_DONE, dsim->reg_base +
611 EXYNOS_DSIM_INTSRC);
612}
613
614void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim,
615 unsigned int tx_data)
616{
617 writel(tx_data, dsim->reg_base + EXYNOS_DSIM_PAYLOAD);
618}
diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
new file mode 100644
index 000000000000..85460701c7ea
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
@@ -0,0 +1,112 @@
1/* linux/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
2 *
3 * Header file for Samsung SoC MIPI-DSI lowlevel driver.
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae <inki.dae@samsung.com>
8 * Donghwa Lee <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#ifndef _EXYNOS_MIPI_DSI_LOWLEVEL_H
16#define _EXYNOS_MIPI_DSI_LOWLEVEL_H
17
18void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim);
19void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim);
20void exynos_mipi_dsi_sw_reset_release(struct mipi_dsim_device *dsim);
21int exynos_mipi_dsi_get_sw_reset_release(struct mipi_dsim_device *dsim);
22void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim,
23 unsigned int mode, unsigned int mask);
24void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
25 unsigned int count);
26void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim,
27 unsigned int cfg);
28void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
29 unsigned int value);
30void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
31 unsigned int value);
32void exynos_mipi_dsi_set_main_stand_by(struct mipi_dsim_device *dsim,
33 unsigned int enable);
34void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim,
35 unsigned int width_resol, unsigned int height_resol);
36void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim,
37 unsigned int cmd_allow, unsigned int vfront, unsigned int vback);
38void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim,
39 unsigned int front, unsigned int back);
40void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim,
41 unsigned int vert, unsigned int hori);
42void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim,
43 unsigned int vert, unsigned int hori);
44void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim);
45void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim,
46 struct mipi_dsim_config *dsim_config);
47void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
48 unsigned int count);
49void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, unsigned int lane,
50 unsigned int enable);
51void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, unsigned int enable,
52 unsigned int afc_code);
53void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim,
54 unsigned int enable);
55void exynos_mipi_dsi_set_pll_pms(struct mipi_dsim_device *dsim, unsigned int p,
56 unsigned int m, unsigned int s);
57void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim,
58 unsigned int freq_band);
59void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim,
60 unsigned int pre_divider, unsigned int main_divider,
61 unsigned int scaler);
62void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim,
63 unsigned int lock_time);
64void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim,
65 unsigned int enable);
66void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim,
67 unsigned int src);
68void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim,
69 unsigned int enable);
70void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim,
71 unsigned int enable, unsigned int prs_val);
72void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim,
73 unsigned int lane_sel, unsigned int enable);
74void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim,
75 unsigned int enable);
76unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim);
77void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim,
78 unsigned int cnt_val);
79void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim,
80 unsigned int timeout);
81void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim,
82 unsigned int timeout);
83void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim,
84 unsigned int lp);
85void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim,
86 unsigned int lp);
87void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim,
88 unsigned int enable);
89void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim,
90 unsigned int swap_en);
91void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim,
92 unsigned int hs_zero);
93void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep);
94unsigned int exynos_mipi_dsi_read_interrupt(struct mipi_dsim_device *dsim);
95unsigned int exynos_mipi_dsi_read_interrupt_mask(struct mipi_dsim_device *dsim);
96void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim,
97 unsigned int src);
98void exynos_mipi_dsi_set_interrupt(struct mipi_dsim_device *dsim,
99 unsigned int src, unsigned int enable);
100unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim);
101unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim);
102unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim);
103void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim);
104void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim, unsigned int di,
105 unsigned int data0, unsigned int data1);
106void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim,
107 unsigned int tx_data);
108void exynos_mipi_dsi_rd_tx_header(struct mipi_dsim_device *dsim,
109 unsigned int data0, unsigned int data1);
110unsigned int exynos_mipi_dsi_rd_rx_fifo(struct mipi_dsim_device *dsim);
111
112#endif /* _EXYNOS_MIPI_DSI_LOWLEVEL_H */
diff --git a/drivers/video/exynos/exynos_mipi_dsi_regs.h b/drivers/video/exynos/exynos_mipi_dsi_regs.h
new file mode 100644
index 000000000000..4227106d3fd0
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_regs.h
@@ -0,0 +1,149 @@
1/* linux/driver/video/exynos/exynos_mipi_dsi_regs.h
2 *
3 * Register definition file for Samsung MIPI-DSIM driver
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae <inki.dae@samsung.com>
8 * Donghwa Lee <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#ifndef _EXYNOS_MIPI_DSI_REGS_H
16#define _EXYNOS_MIPI_DSI_REGS_H
17
18#define EXYNOS_DSIM_STATUS 0x0 /* Status register */
19#define EXYNOS_DSIM_SWRST 0x4 /* Software reset register */
20#define EXYNOS_DSIM_CLKCTRL 0x8 /* Clock control register */
21#define EXYNOS_DSIM_TIMEOUT 0xc /* Time out register */
22#define EXYNOS_DSIM_CONFIG 0x10 /* Configuration register */
23#define EXYNOS_DSIM_ESCMODE 0x14 /* Escape mode register */
24
25/* Main display image resolution register */
26#define EXYNOS_DSIM_MDRESOL 0x18
27#define EXYNOS_DSIM_MVPORCH 0x1c /* Main display Vporch register */
28#define EXYNOS_DSIM_MHPORCH 0x20 /* Main display Hporch register */
29#define EXYNOS_DSIM_MSYNC 0x24 /* Main display sync area register */
30
31/* Sub display image resolution register */
32#define EXYNOS_DSIM_SDRESOL 0x28
33#define EXYNOS_DSIM_INTSRC 0x2c /* Interrupt source register */
34#define EXYNOS_DSIM_INTMSK 0x30 /* Interrupt mask register */
35#define EXYNOS_DSIM_PKTHDR 0x34 /* Packet Header FIFO register */
36#define EXYNOS_DSIM_PAYLOAD 0x38 /* Payload FIFO register */
37#define EXYNOS_DSIM_RXFIFO 0x3c /* Read FIFO register */
38#define EXYNOS_DSIM_FIFOTHLD 0x40 /* FIFO threshold level register */
39#define EXYNOS_DSIM_FIFOCTRL 0x44 /* FIFO status and control register */
40
41/* FIFO memory AC characteristic register */
42#define EXYNOS_DSIM_PLLCTRL 0x4c /* PLL control register */
43#define EXYNOS_DSIM_PLLTMR 0x50 /* PLL timer register */
44#define EXYNOS_DSIM_PHYACCHR 0x54 /* D-PHY AC characteristic register */
45#define EXYNOS_DSIM_PHYACCHR1 0x58 /* D-PHY AC characteristic register1 */
46
47/* DSIM_STATUS */
48#define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0)
49#define DSIM_STOP_STATE_CLK (1 << 8)
50#define DSIM_TX_READY_HS_CLK (1 << 10)
51
52/* DSIM_SWRST */
53#define DSIM_FUNCRST (1 << 16)
54#define DSIM_SWRST (1 << 0)
55
56/* EXYNOS_DSIM_TIMEOUT */
57#define DSIM_LPDR_TOUT_SHIFT(x) ((x) << 0)
58#define DSIM_BTA_TOUT_SHIFT(x) ((x) << 16)
59
60/* EXYNOS_DSIM_CLKCTRL */
61#define DSIM_LANE_ESC_CLKEN(x) (((x) & 0x1f) << 19)
62#define DSIM_BYTE_CLKEN_SHIFT(x) ((x) << 24)
63#define DSIM_BYTE_CLK_SRC_SHIFT(x) ((x) << 25)
64#define DSIM_PLL_BYPASS_SHIFT(x) ((x) << 27)
65#define DSIM_ESC_CLKEN_SHIFT(x) ((x) << 28)
66#define DSIM_TX_REQUEST_HSCLK_SHIFT(x) ((x) << 31)
67
68/* EXYNOS_DSIM_CONFIG */
69#define DSIM_LANE_ENx(x) (((x) & 0x1f) << 0)
70#define DSIM_NUM_OF_DATALANE_SHIFT(x) ((x) << 5)
71#define DSIM_HSA_MODE_SHIFT(x) ((x) << 20)
72#define DSIM_HBP_MODE_SHIFT(x) ((x) << 21)
73#define DSIM_HFP_MODE_SHIFT(x) ((x) << 22)
74#define DSIM_HSE_MODE_SHIFT(x) ((x) << 23)
75#define DSIM_AUTO_MODE_SHIFT(x) ((x) << 24)
76#define DSIM_EOT_DISABLE(x) ((x) << 28)
77#define DSIM_AUTO_FLUSH(x) ((x) << 29)
78
79#define DSIM_NUM_OF_DATA_LANE(x) ((x) << DSIM_NUM_OF_DATALANE_SHIFT)
80
81/* EXYNOS_DSIM_ESCMODE */
82#define DSIM_TX_LPDT_LP (1 << 6)
83#define DSIM_CMD_LPDT_LP (1 << 7)
84#define DSIM_FORCE_STOP_STATE_SHIFT(x) ((x) << 20)
85#define DSIM_STOP_STATE_CNT_SHIFT(x) ((x) << 21)
86
87/* EXYNOS_DSIM_MDRESOL */
88#define DSIM_MAIN_STAND_BY (1 << 31)
89#define DSIM_MAIN_VRESOL(x) (((x) & 0x7ff) << 16)
90#define DSIM_MAIN_HRESOL(x) (((x) & 0X7ff) << 0)
91
92/* EXYNOS_DSIM_MVPORCH */
93#define DSIM_CMD_ALLOW_SHIFT(x) ((x) << 28)
94#define DSIM_STABLE_VFP_SHIFT(x) ((x) << 16)
95#define DSIM_MAIN_VBP_SHIFT(x) ((x) << 0)
96#define DSIM_CMD_ALLOW_MASK (0xf << 28)
97#define DSIM_STABLE_VFP_MASK (0x7ff << 16)
98#define DSIM_MAIN_VBP_MASK (0x7ff << 0)
99
100/* EXYNOS_DSIM_MHPORCH */
101#define DSIM_MAIN_HFP_SHIFT(x) ((x) << 16)
102#define DSIM_MAIN_HBP_SHIFT(x) ((x) << 0)
103#define DSIM_MAIN_HFP_MASK ((0xffff) << 16)
104#define DSIM_MAIN_HBP_MASK ((0xffff) << 0)
105
106/* EXYNOS_DSIM_MSYNC */
107#define DSIM_MAIN_VSA_SHIFT(x) ((x) << 22)
108#define DSIM_MAIN_HSA_SHIFT(x) ((x) << 0)
109#define DSIM_MAIN_VSA_MASK ((0x3ff) << 22)
110#define DSIM_MAIN_HSA_MASK ((0xffff) << 0)
111
112/* EXYNOS_DSIM_SDRESOL */
113#define DSIM_SUB_STANDY_SHIFT(x) ((x) << 31)
114#define DSIM_SUB_VRESOL_SHIFT(x) ((x) << 16)
115#define DSIM_SUB_HRESOL_SHIFT(x) ((x) << 0)
116#define DSIM_SUB_STANDY_MASK ((0x1) << 31)
117#define DSIM_SUB_VRESOL_MASK ((0x7ff) << 16)
118#define DSIM_SUB_HRESOL_MASK ((0x7ff) << 0)
119
120/* EXYNOS_DSIM_INTSRC */
121#define INTSRC_PLL_STABLE (1 << 31)
122#define INTSRC_SW_RST_RELEASE (1 << 30)
123#define INTSRC_SFR_FIFO_EMPTY (1 << 29)
124#define INTSRC_FRAME_DONE (1 << 24)
125#define INTSRC_RX_DATA_DONE (1 << 18)
126
127/* EXYNOS_DSIM_INTMSK */
128#define INTMSK_FIFO_EMPTY (1 << 29)
129#define INTMSK_BTA (1 << 25)
130#define INTMSK_FRAME_DONE (1 << 24)
131#define INTMSK_RX_TIMEOUT (1 << 21)
132#define INTMSK_BTA_TIMEOUT (1 << 20)
133#define INTMSK_RX_DONE (1 << 18)
134#define INTMSK_RX_TE (1 << 17)
135#define INTMSK_RX_ACK (1 << 16)
136#define INTMSK_RX_ECC_ERR (1 << 15)
137#define INTMSK_RX_CRC_ERR (1 << 14)
138
139/* EXYNOS_DSIM_FIFOCTRL */
140#define SFR_HEADER_EMPTY (1 << 22)
141
142/* EXYNOS_DSIM_PHYACCHR */
143#define DSIM_AFC_CTL(x) (((x) & 0x7) << 5)
144
145/* EXYNOS_DSIM_PLLCTRL */
146#define DSIM_PLL_EN_SHIFT(x) ((x) << 23)
147#define DSIM_FREQ_BAND_SHIFT(x) ((x) << 24)
148
149#endif /* _EXYNOS_MIPI_DSI_REGS_H */
diff --git a/drivers/video/exynos/s6e8ax0.c b/drivers/video/exynos/s6e8ax0.c
new file mode 100644
index 000000000000..4aa9ac6218bf
--- /dev/null
+++ b/drivers/video/exynos/s6e8ax0.c
@@ -0,0 +1,898 @@
1/* linux/drivers/video/exynos/s6e8ax0.c
2 *
3 * MIPI-DSI based s6e8ax0 AMOLED lcd 4.65 inch panel driver.
4 *
5 * Inki Dae, <inki.dae@samsung.com>
6 * Donghwa Lee, <dh09.lee@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/errno.h>
16#include <linux/mutex.h>
17#include <linux/wait.h>
18#include <linux/ctype.h>
19#include <linux/io.h>
20#include <linux/delay.h>
21#include <linux/irq.h>
22#include <linux/interrupt.h>
23#include <linux/lcd.h>
24#include <linux/fb.h>
25#include <linux/backlight.h>
26#include <linux/regulator/consumer.h>
27
28#include <video/mipi_display.h>
29#include <video/exynos_mipi_dsim.h>
30
31#define LDI_MTP_LENGTH 24
32#define DSIM_PM_STABLE_TIME 10
33#define MIN_BRIGHTNESS 0
34#define MAX_BRIGHTNESS 24
35#define GAMMA_TABLE_COUNT 26
36
37#define POWER_IS_ON(pwr) ((pwr) == FB_BLANK_UNBLANK)
38#define POWER_IS_OFF(pwr) ((pwr) == FB_BLANK_POWERDOWN)
39#define POWER_IS_NRM(pwr) ((pwr) == FB_BLANK_NORMAL)
40
41#define lcd_to_master(a) (a->dsim_dev->master)
42#define lcd_to_master_ops(a) ((lcd_to_master(a))->master_ops)
43
44enum {
45 DSIM_NONE_STATE = 0,
46 DSIM_RESUME_COMPLETE = 1,
47 DSIM_FRAME_DONE = 2,
48};
49
50struct s6e8ax0 {
51 struct device *dev;
52 unsigned int power;
53 unsigned int id;
54 unsigned int gamma;
55 unsigned int acl_enable;
56 unsigned int cur_acl;
57
58 struct lcd_device *ld;
59 struct backlight_device *bd;
60
61 struct mipi_dsim_lcd_device *dsim_dev;
62 struct lcd_platform_data *ddi_pd;
63 struct mutex lock;
64 bool enabled;
65};
66
67
68static struct regulator_bulk_data supplies[] = {
69 { .supply = "vdd3", },
70 { .supply = "vci", },
71};
72
73static void s6e8ax0_regulator_enable(struct s6e8ax0 *lcd)
74{
75 int ret = 0;
76 struct lcd_platform_data *pd = NULL;
77
78 pd = lcd->ddi_pd;
79 mutex_lock(&lcd->lock);
80 if (!lcd->enabled) {
81 ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
82 if (ret)
83 goto out;
84
85 lcd->enabled = true;
86 }
87 msleep(pd->power_on_delay);
88out:
89 mutex_unlock(&lcd->lock);
90}
91
92static void s6e8ax0_regulator_disable(struct s6e8ax0 *lcd)
93{
94 int ret = 0;
95
96 mutex_lock(&lcd->lock);
97 if (lcd->enabled) {
98 ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
99 if (ret)
100 goto out;
101
102 lcd->enabled = false;
103 }
104out:
105 mutex_unlock(&lcd->lock);
106}
107
108static const unsigned char s6e8ax0_22_gamma_30[] = {
109 0xfa, 0x01, 0x60, 0x10, 0x60, 0xf5, 0x00, 0xff, 0xad, 0xaf,
110 0xbA, 0xc3, 0xd8, 0xc5, 0x9f, 0xc6, 0x9e, 0xc1, 0xdc, 0xc0,
111 0x00, 0x61, 0x00, 0x5a, 0x00, 0x74,
112};
113
114static const unsigned char s6e8ax0_22_gamma_50[] = {
115 0xfa, 0x01, 0x60, 0x10, 0x60, 0xe8, 0x1f, 0xf7, 0xad, 0xc0,
116 0xb5, 0xc4, 0xdc, 0xc4, 0x9e, 0xc6, 0x9c, 0xbb, 0xd8, 0xbb,
117 0x00, 0x70, 0x00, 0x68, 0x00, 0x86,
118};
119
120static const unsigned char s6e8ax0_22_gamma_60[] = {
121 0xfa, 0x01, 0x60, 0x10, 0x60, 0xde, 0x1f, 0xef, 0xad, 0xc4,
122 0xb3, 0xc3, 0xdd, 0xc4, 0x9e, 0xc6, 0x9c, 0xbc, 0xd6, 0xba,
123 0x00, 0x75, 0x00, 0x6e, 0x00, 0x8d,
124};
125
126static const unsigned char s6e8ax0_22_gamma_70[] = {
127 0xfa, 0x01, 0x60, 0x10, 0x60, 0xd8, 0x1f, 0xe7, 0xaf, 0xc8,
128 0xb4, 0xc4, 0xdd, 0xc3, 0x9d, 0xc6, 0x9c, 0xbb, 0xd6, 0xb9,
129 0x00, 0x7a, 0x00, 0x72, 0x00, 0x93,
130};
131
132static const unsigned char s6e8ax0_22_gamma_80[] = {
133 0xfa, 0x01, 0x60, 0x10, 0x60, 0xc9, 0x1f, 0xde, 0xae, 0xc9,
134 0xb1, 0xc3, 0xdd, 0xc2, 0x9d, 0xc5, 0x9b, 0xbc, 0xd6, 0xbb,
135 0x00, 0x7f, 0x00, 0x77, 0x00, 0x99,
136};
137
138static const unsigned char s6e8ax0_22_gamma_90[] = {
139 0xfa, 0x01, 0x60, 0x10, 0x60, 0xc7, 0x1f, 0xd9, 0xb0, 0xcc,
140 0xb2, 0xc3, 0xdc, 0xc1, 0x9c, 0xc6, 0x9c, 0xbc, 0xd4, 0xb9,
141 0x00, 0x83, 0x00, 0x7b, 0x00, 0x9e,
142};
143
144static const unsigned char s6e8ax0_22_gamma_100[] = {
145 0xfa, 0x01, 0x60, 0x10, 0x60, 0xbd, 0x80, 0xcd, 0xba, 0xce,
146 0xb3, 0xc4, 0xde, 0xc3, 0x9c, 0xc4, 0x9, 0xb8, 0xd3, 0xb6,
147 0x00, 0x88, 0x00, 0x80, 0x00, 0xa5,
148};
149
150static const unsigned char s6e8ax0_22_gamma_120[] = {
151 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb9, 0x95, 0xc8, 0xb1, 0xcf,
152 0xb2, 0xc6, 0xdf, 0xc5, 0x9b, 0xc3, 0x99, 0xb6, 0xd2, 0xb6,
153 0x00, 0x8f, 0x00, 0x86, 0x00, 0xac,
154};
155
156static const unsigned char s6e8ax0_22_gamma_130[] = {
157 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb7, 0xa0, 0xc7, 0xb1, 0xd0,
158 0xb2, 0xc4, 0xdd, 0xc3, 0x9a, 0xc3, 0x98, 0xb6, 0xd0, 0xb4,
159 0x00, 0x92, 0x00, 0x8a, 0x00, 0xb1,
160};
161
162static const unsigned char s6e8ax0_22_gamma_140[] = {
163 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb7, 0xa0, 0xc5, 0xb2, 0xd0,
164 0xb3, 0xc3, 0xde, 0xc3, 0x9b, 0xc2, 0x98, 0xb6, 0xd0, 0xb4,
165 0x00, 0x95, 0x00, 0x8d, 0x00, 0xb5,
166};
167
168static const unsigned char s6e8ax0_22_gamma_150[] = {
169 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xa0, 0xc2, 0xb2, 0xd0,
170 0xb2, 0xc1, 0xdd, 0xc2, 0x9b, 0xc2, 0x98, 0xb4, 0xcf, 0xb1,
171 0x00, 0x99, 0x00, 0x90, 0x00, 0xba,
172};
173
174static const unsigned char s6e8ax0_22_gamma_160[] = {
175 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xa5, 0xbf, 0xb0, 0xd0,
176 0xb1, 0xc3, 0xde, 0xc2, 0x99, 0xc1, 0x97, 0xb4, 0xce, 0xb1,
177 0x00, 0x9c, 0x00, 0x93, 0x00, 0xbe,
178};
179
180static const unsigned char s6e8ax0_22_gamma_170[] = {
181 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb5, 0xbf, 0xb1, 0xd1,
182 0xb1, 0xc3, 0xde, 0xc3, 0x99, 0xc0, 0x96, 0xb4, 0xce, 0xb1,
183 0x00, 0x9f, 0x00, 0x96, 0x00, 0xc2,
184};
185
186static const unsigned char s6e8ax0_22_gamma_180[] = {
187 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb7, 0xbe, 0xb3, 0xd2,
188 0xb3, 0xc3, 0xde, 0xc2, 0x97, 0xbf, 0x95, 0xb4, 0xcd, 0xb1,
189 0x00, 0xa2, 0x00, 0x99, 0x00, 0xc5,
190};
191
192static const unsigned char s6e8ax0_22_gamma_190[] = {
193 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb9, 0xbe, 0xb2, 0xd2,
194 0xb2, 0xc3, 0xdd, 0xc3, 0x98, 0xbf, 0x95, 0xb2, 0xcc, 0xaf,
195 0x00, 0xa5, 0x00, 0x9c, 0x00, 0xc9,
196};
197
198static const unsigned char s6e8ax0_22_gamma_200[] = {
199 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb9, 0xbc, 0xb2, 0xd2,
200 0xb1, 0xc4, 0xdd, 0xc3, 0x97, 0xbe, 0x95, 0xb1, 0xcb, 0xae,
201 0x00, 0xa8, 0x00, 0x9f, 0x00, 0xcd,
202};
203
204static const unsigned char s6e8ax0_22_gamma_210[] = {
205 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc1, 0xbd, 0xb1, 0xd1,
206 0xb1, 0xc2, 0xde, 0xc2, 0x97, 0xbe, 0x94, 0xB0, 0xc9, 0xad,
207 0x00, 0xae, 0x00, 0xa4, 0x00, 0xd4,
208};
209
210static const unsigned char s6e8ax0_22_gamma_220[] = {
211 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc7, 0xbd, 0xb1, 0xd1,
212 0xb1, 0xc2, 0xdd, 0xc2, 0x97, 0xbd, 0x94, 0xb0, 0xc9, 0xad,
213 0x00, 0xad, 0x00, 0xa2, 0x00, 0xd3,
214};
215
216static const unsigned char s6e8ax0_22_gamma_230[] = {
217 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc3, 0xbd, 0xb2, 0xd1,
218 0xb1, 0xc3, 0xdd, 0xc1, 0x96, 0xbd, 0x94, 0xb0, 0xc9, 0xad,
219 0x00, 0xb0, 0x00, 0xa7, 0x00, 0xd7,
220};
221
222static const unsigned char s6e8ax0_22_gamma_240[] = {
223 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xcb, 0xbd, 0xb1, 0xd2,
224 0xb1, 0xc3, 0xdD, 0xc2, 0x95, 0xbd, 0x93, 0xaf, 0xc8, 0xab,
225 0x00, 0xb3, 0x00, 0xa9, 0x00, 0xdb,
226};
227
228static const unsigned char s6e8ax0_22_gamma_250[] = {
229 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xcc, 0xbe, 0xb0, 0xd2,
230 0xb0, 0xc3, 0xdD, 0xc2, 0x94, 0xbc, 0x92, 0xae, 0xc8, 0xab,
231 0x00, 0xb6, 0x00, 0xab, 0x00, 0xde,
232};
233
234static const unsigned char s6e8ax0_22_gamma_260[] = {
235 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xd0, 0xbe, 0xaf, 0xd1,
236 0xaf, 0xc2, 0xdd, 0xc1, 0x96, 0xbc, 0x93, 0xaf, 0xc8, 0xac,
237 0x00, 0xb7, 0x00, 0xad, 0x00, 0xe0,
238};
239
240static const unsigned char s6e8ax0_22_gamma_270[] = {
241 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb2, 0xcF, 0xbd, 0xb0, 0xd2,
242 0xaf, 0xc2, 0xdc, 0xc1, 0x95, 0xbd, 0x93, 0xae, 0xc6, 0xaa,
243 0x00, 0xba, 0x00, 0xb0, 0x00, 0xe4,
244};
245
246static const unsigned char s6e8ax0_22_gamma_280[] = {
247 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb2, 0xd0, 0xbd, 0xaf, 0xd0,
248 0xad, 0xc4, 0xdd, 0xc3, 0x95, 0xbd, 0x93, 0xac, 0xc5, 0xa9,
249 0x00, 0xbd, 0x00, 0xb2, 0x00, 0xe7,
250};
251
252static const unsigned char s6e8ax0_22_gamma_300[] = {
253 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb5, 0xd3, 0xbd, 0xb1, 0xd2,
254 0xb0, 0xc0, 0xdc, 0xc0, 0x94, 0xba, 0x91, 0xac, 0xc5, 0xa9,
255 0x00, 0xc2, 0x00, 0xb7, 0x00, 0xed,
256};
257
258static const unsigned char *s6e8ax0_22_gamma_table[] = {
259 s6e8ax0_22_gamma_30,
260 s6e8ax0_22_gamma_50,
261 s6e8ax0_22_gamma_60,
262 s6e8ax0_22_gamma_70,
263 s6e8ax0_22_gamma_80,
264 s6e8ax0_22_gamma_90,
265 s6e8ax0_22_gamma_100,
266 s6e8ax0_22_gamma_120,
267 s6e8ax0_22_gamma_130,
268 s6e8ax0_22_gamma_140,
269 s6e8ax0_22_gamma_150,
270 s6e8ax0_22_gamma_160,
271 s6e8ax0_22_gamma_170,
272 s6e8ax0_22_gamma_180,
273 s6e8ax0_22_gamma_190,
274 s6e8ax0_22_gamma_200,
275 s6e8ax0_22_gamma_210,
276 s6e8ax0_22_gamma_220,
277 s6e8ax0_22_gamma_230,
278 s6e8ax0_22_gamma_240,
279 s6e8ax0_22_gamma_250,
280 s6e8ax0_22_gamma_260,
281 s6e8ax0_22_gamma_270,
282 s6e8ax0_22_gamma_280,
283 s6e8ax0_22_gamma_300,
284};
285
286static void s6e8ax0_panel_cond(struct s6e8ax0 *lcd)
287{
288 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
289
290 static const unsigned char data_to_send[] = {
291 0xf8, 0x3d, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00, 0x3c, 0x7d,
292 0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x04, 0x08,
293 0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0,
294 0xc8, 0x08, 0x48, 0xc1, 0x00, 0xc1, 0xff, 0xff, 0xc8
295 };
296
297 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
298 data_to_send, ARRAY_SIZE(data_to_send));
299}
300
301static void s6e8ax0_display_cond(struct s6e8ax0 *lcd)
302{
303 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
304 static const unsigned char data_to_send[] = {
305 0xf2, 0x80, 0x03, 0x0d
306 };
307
308 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
309 data_to_send, ARRAY_SIZE(data_to_send));
310}
311
312/* Gamma 2.2 Setting (200cd, 7500K, 10MPCD) */
313static void s6e8ax0_gamma_cond(struct s6e8ax0 *lcd)
314{
315 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
316 unsigned int gamma = lcd->bd->props.brightness;
317
318 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
319 s6e8ax0_22_gamma_table[gamma],
320 GAMMA_TABLE_COUNT);
321}
322
323static void s6e8ax0_gamma_update(struct s6e8ax0 *lcd)
324{
325 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
326 static const unsigned char data_to_send[] = {
327 0xf7, 0x03
328 };
329
330 ops->cmd_write(lcd_to_master(lcd),
331 MIPI_DSI_DCS_SHORT_WRITE_PARAM, data_to_send,
332 ARRAY_SIZE(data_to_send));
333}
334
335static void s6e8ax0_etc_cond1(struct s6e8ax0 *lcd)
336{
337 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
338 static const unsigned char data_to_send[] = {
339 0xd1, 0xfe, 0x80, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x40,
340 0x0d, 0x00, 0x00
341 };
342
343 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
344 data_to_send, ARRAY_SIZE(data_to_send));
345}
346
347static void s6e8ax0_etc_cond2(struct s6e8ax0 *lcd)
348{
349 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
350 static const unsigned char data_to_send[] = {
351 0xb6, 0x0c, 0x02, 0x03, 0x32, 0xff, 0x44, 0x44, 0xc0,
352 0x00
353 };
354
355 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
356 data_to_send, ARRAY_SIZE(data_to_send));
357}
358
359static void s6e8ax0_etc_cond3(struct s6e8ax0 *lcd)
360{
361 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
362 static const unsigned char data_to_send[] = {
363 0xe1, 0x10, 0x1c, 0x17, 0x08, 0x1d
364 };
365
366 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
367 data_to_send, ARRAY_SIZE(data_to_send));
368}
369
370static void s6e8ax0_etc_cond4(struct s6e8ax0 *lcd)
371{
372 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
373 static const unsigned char data_to_send[] = {
374 0xe2, 0xed, 0x07, 0xc3, 0x13, 0x0d, 0x03
375 };
376
377 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
378 data_to_send, ARRAY_SIZE(data_to_send));
379}
380
381static void s6e8ax0_etc_cond5(struct s6e8ax0 *lcd)
382{
383 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
384 static const unsigned char data_to_send[] = {
385 0xf4, 0xcf, 0x0a, 0x12, 0x10, 0x19, 0x33, 0x02
386 };
387
388 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
389 data_to_send, ARRAY_SIZE(data_to_send));
390}
391static void s6e8ax0_etc_cond6(struct s6e8ax0 *lcd)
392{
393 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
394 static const unsigned char data_to_send[] = {
395 0xe3, 0x40
396 };
397
398 ops->cmd_write(lcd_to_master(lcd),
399 MIPI_DSI_DCS_SHORT_WRITE_PARAM,
400 data_to_send, ARRAY_SIZE(data_to_send));
401}
402
403static void s6e8ax0_etc_cond7(struct s6e8ax0 *lcd)
404{
405 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
406 static const unsigned char data_to_send[] = {
407 0xe4, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00
408 };
409
410 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
411 data_to_send, ARRAY_SIZE(data_to_send));
412}
413
414static void s6e8ax0_elvss_set(struct s6e8ax0 *lcd)
415{
416 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
417 static const unsigned char data_to_send[] = {
418 0xb1, 0x04, 0x00
419 };
420
421 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
422 data_to_send, ARRAY_SIZE(data_to_send));
423}
424
425static void s6e8ax0_elvss_nvm_set(struct s6e8ax0 *lcd)
426{
427 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
428 static const unsigned char data_to_send[] = {
429 0xd9, 0x5c, 0x20, 0x0c, 0x0f, 0x41, 0x00, 0x10, 0x11,
430 0x12, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcb, 0xed,
431 0x64, 0xaf
432 };
433
434 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
435 data_to_send, ARRAY_SIZE(data_to_send));
436}
437
438static void s6e8ax0_sleep_in(struct s6e8ax0 *lcd)
439{
440 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
441 static const unsigned char data_to_send[] = {
442 0x10, 0x00
443 };
444
445 ops->cmd_write(lcd_to_master(lcd),
446 MIPI_DSI_DCS_SHORT_WRITE,
447 data_to_send, ARRAY_SIZE(data_to_send));
448}
449
450static void s6e8ax0_sleep_out(struct s6e8ax0 *lcd)
451{
452 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
453 static const unsigned char data_to_send[] = {
454 0x11, 0x00
455 };
456
457 ops->cmd_write(lcd_to_master(lcd),
458 MIPI_DSI_DCS_SHORT_WRITE,
459 data_to_send, ARRAY_SIZE(data_to_send));
460}
461
462static void s6e8ax0_display_on(struct s6e8ax0 *lcd)
463{
464 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
465 static const unsigned char data_to_send[] = {
466 0x29, 0x00
467 };
468
469 ops->cmd_write(lcd_to_master(lcd),
470 MIPI_DSI_DCS_SHORT_WRITE,
471 data_to_send, ARRAY_SIZE(data_to_send));
472}
473
474static void s6e8ax0_display_off(struct s6e8ax0 *lcd)
475{
476 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
477 static const unsigned char data_to_send[] = {
478 0x28, 0x00
479 };
480
481 ops->cmd_write(lcd_to_master(lcd),
482 MIPI_DSI_DCS_SHORT_WRITE,
483 data_to_send, ARRAY_SIZE(data_to_send));
484}
485
486static void s6e8ax0_apply_level2_key(struct s6e8ax0 *lcd)
487{
488 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
489 static const unsigned char data_to_send[] = {
490 0xf0, 0x5a, 0x5a
491 };
492
493 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
494 data_to_send, ARRAY_SIZE(data_to_send));
495}
496
497static void s6e8ax0_acl_on(struct s6e8ax0 *lcd)
498{
499 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
500 static const unsigned char data_to_send[] = {
501 0xc0, 0x01
502 };
503
504 ops->cmd_write(lcd_to_master(lcd),
505 MIPI_DSI_DCS_SHORT_WRITE,
506 data_to_send, ARRAY_SIZE(data_to_send));
507}
508
509static void s6e8ax0_acl_off(struct s6e8ax0 *lcd)
510{
511 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
512 static const unsigned char data_to_send[] = {
513 0xc0, 0x00
514 };
515
516 ops->cmd_write(lcd_to_master(lcd),
517 MIPI_DSI_DCS_SHORT_WRITE,
518 data_to_send, ARRAY_SIZE(data_to_send));
519}
520
521/* Full white 50% reducing setting */
522static void s6e8ax0_acl_ctrl_set(struct s6e8ax0 *lcd)
523{
524 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
525 /* Full white 50% reducing setting */
526 static const unsigned char cutoff_50[] = {
527 0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
528 0x00, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x01, 0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2a, 0x31, 0x38,
530 0x3f, 0x46
531 };
532 /* Full white 45% reducing setting */
533 static const unsigned char cutoff_45[] = {
534 0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
535 0x00, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
536 0x01, 0x07, 0x0d, 0x13, 0x19, 0x1f, 0x25, 0x2b, 0x31,
537 0x37, 0x3d
538 };
539 /* Full white 40% reducing setting */
540 static const unsigned char cutoff_40[] = {
541 0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
542 0x00, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x01, 0x06, 0x0c, 0x11, 0x16, 0x1c, 0x21, 0x26, 0x2b,
544 0x31, 0x36
545 };
546
547 if (lcd->acl_enable) {
548 if (lcd->cur_acl == 0) {
549 if (lcd->gamma == 0 || lcd->gamma == 1) {
550 s6e8ax0_acl_off(lcd);
551 dev_dbg(&lcd->ld->dev,
552 "cur_acl=%d\n", lcd->cur_acl);
553 } else
554 s6e8ax0_acl_on(lcd);
555 }
556 switch (lcd->gamma) {
557 case 0: /* 30cd */
558 s6e8ax0_acl_off(lcd);
559 lcd->cur_acl = 0;
560 break;
561 case 1 ... 3: /* 50cd ~ 90cd */
562 ops->cmd_write(lcd_to_master(lcd),
563 MIPI_DSI_DCS_LONG_WRITE,
564 cutoff_40,
565 ARRAY_SIZE(cutoff_40));
566 lcd->cur_acl = 40;
567 break;
568 case 4 ... 7: /* 120cd ~ 210cd */
569 ops->cmd_write(lcd_to_master(lcd),
570 MIPI_DSI_DCS_LONG_WRITE,
571 cutoff_45,
572 ARRAY_SIZE(cutoff_45));
573 lcd->cur_acl = 45;
574 break;
575 case 8 ... 10: /* 220cd ~ 300cd */
576 ops->cmd_write(lcd_to_master(lcd),
577 MIPI_DSI_DCS_LONG_WRITE,
578 cutoff_50,
579 ARRAY_SIZE(cutoff_50));
580 lcd->cur_acl = 50;
581 break;
582 default:
583 break;
584 }
585 } else {
586 s6e8ax0_acl_off(lcd);
587 lcd->cur_acl = 0;
588 dev_dbg(&lcd->ld->dev, "cur_acl = %d\n", lcd->cur_acl);
589 }
590}
591
592static void s6e8ax0_read_id(struct s6e8ax0 *lcd, u8 *mtp_id)
593{
594 unsigned int ret;
595 unsigned int addr = 0xd1; /* MTP ID */
596 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
597
598 ret = ops->cmd_read(lcd_to_master(lcd),
599 MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM,
600 addr, 3, mtp_id);
601}
602
603static int s6e8ax0_panel_init(struct s6e8ax0 *lcd)
604{
605 s6e8ax0_apply_level2_key(lcd);
606 s6e8ax0_sleep_out(lcd);
607 msleep(1);
608 s6e8ax0_panel_cond(lcd);
609 s6e8ax0_display_cond(lcd);
610 s6e8ax0_gamma_cond(lcd);
611 s6e8ax0_gamma_update(lcd);
612
613 s6e8ax0_etc_cond1(lcd);
614 s6e8ax0_etc_cond2(lcd);
615 s6e8ax0_etc_cond3(lcd);
616 s6e8ax0_etc_cond4(lcd);
617 s6e8ax0_etc_cond5(lcd);
618 s6e8ax0_etc_cond6(lcd);
619 s6e8ax0_etc_cond7(lcd);
620
621 s6e8ax0_elvss_nvm_set(lcd);
622 s6e8ax0_elvss_set(lcd);
623
624 s6e8ax0_acl_ctrl_set(lcd);
625 s6e8ax0_acl_on(lcd);
626
627 /* if ID3 value is not 33h, branch private elvss mode */
628 msleep(lcd->ddi_pd->power_on_delay);
629
630 return 0;
631}
632
633static int s6e8ax0_update_gamma_ctrl(struct s6e8ax0 *lcd, int brightness)
634{
635 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
636
637 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
638 s6e8ax0_22_gamma_table[brightness],
639 ARRAY_SIZE(s6e8ax0_22_gamma_table));
640
641 /* update gamma table. */
642 s6e8ax0_gamma_update(lcd);
643 lcd->gamma = brightness;
644
645 return 0;
646}
647
648static int s6e8ax0_gamma_ctrl(struct s6e8ax0 *lcd, int gamma)
649{
650 s6e8ax0_update_gamma_ctrl(lcd, gamma);
651
652 return 0;
653}
654
655static int s6e8ax0_set_power(struct lcd_device *ld, int power)
656{
657 struct s6e8ax0 *lcd = lcd_get_data(ld);
658 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
659 int ret = 0;
660
661 if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
662 power != FB_BLANK_NORMAL) {
663 dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
664 return -EINVAL;
665 }
666
667 if ((power == FB_BLANK_UNBLANK) && ops->set_blank_mode) {
668 /* LCD power on */
669 if ((POWER_IS_ON(power) && POWER_IS_OFF(lcd->power))
670 || (POWER_IS_ON(power) && POWER_IS_NRM(lcd->power))) {
671 ret = ops->set_blank_mode(lcd_to_master(lcd), power);
672 if (!ret && lcd->power != power)
673 lcd->power = power;
674 }
675 } else if ((power == FB_BLANK_POWERDOWN) && ops->set_early_blank_mode) {
676 /* LCD power off */
677 if ((POWER_IS_OFF(power) && POWER_IS_ON(lcd->power)) ||
678 (POWER_IS_ON(lcd->power) && POWER_IS_NRM(power))) {
679 ret = ops->set_early_blank_mode(lcd_to_master(lcd),
680 power);
681 if (!ret && lcd->power != power)
682 lcd->power = power;
683 }
684 }
685
686 return ret;
687}
688
689static int s6e8ax0_get_power(struct lcd_device *ld)
690{
691 struct s6e8ax0 *lcd = lcd_get_data(ld);
692
693 return lcd->power;
694}
695
696static int s6e8ax0_get_brightness(struct backlight_device *bd)
697{
698 return bd->props.brightness;
699}
700
701static int s6e8ax0_set_brightness(struct backlight_device *bd)
702{
703 int ret = 0, brightness = bd->props.brightness;
704 struct s6e8ax0 *lcd = bl_get_data(bd);
705
706 if (brightness < MIN_BRIGHTNESS ||
707 brightness > bd->props.max_brightness) {
708 dev_err(lcd->dev, "lcd brightness should be %d to %d.\n",
709 MIN_BRIGHTNESS, MAX_BRIGHTNESS);
710 return -EINVAL;
711 }
712
713 ret = s6e8ax0_gamma_ctrl(lcd, brightness);
714 if (ret) {
715 dev_err(&bd->dev, "lcd brightness setting failed.\n");
716 return -EIO;
717 }
718
719 return ret;
720}
721
722static struct lcd_ops s6e8ax0_lcd_ops = {
723 .set_power = s6e8ax0_set_power,
724 .get_power = s6e8ax0_get_power,
725};
726
727static const struct backlight_ops s6e8ax0_backlight_ops = {
728 .get_brightness = s6e8ax0_get_brightness,
729 .update_status = s6e8ax0_set_brightness,
730};
731
732static void s6e8ax0_power_on(struct mipi_dsim_lcd_device *dsim_dev, int power)
733{
734 struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
735
736 msleep(lcd->ddi_pd->power_on_delay);
737
738 /* lcd power on */
739 if (power)
740 s6e8ax0_regulator_enable(lcd);
741 else
742 s6e8ax0_regulator_disable(lcd);
743
744 msleep(lcd->ddi_pd->reset_delay);
745
746 /* lcd reset */
747 if (lcd->ddi_pd->reset)
748 lcd->ddi_pd->reset(lcd->ld);
749 msleep(5);
750}
751
752static void s6e8ax0_set_sequence(struct mipi_dsim_lcd_device *dsim_dev)
753{
754 struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
755
756 s6e8ax0_panel_init(lcd);
757 s6e8ax0_display_on(lcd);
758
759 lcd->power = FB_BLANK_UNBLANK;
760}
761
762static int s6e8ax0_probe(struct mipi_dsim_lcd_device *dsim_dev)
763{
764 struct s6e8ax0 *lcd;
765 int ret;
766 u8 mtp_id[3] = {0, };
767
768 lcd = kzalloc(sizeof(struct s6e8ax0), GFP_KERNEL);
769 if (!lcd) {
770 dev_err(&dsim_dev->dev, "failed to allocate s6e8ax0 structure.\n");
771 return -ENOMEM;
772 }
773
774 lcd->dsim_dev = dsim_dev;
775 lcd->ddi_pd = (struct lcd_platform_data *)dsim_dev->platform_data;
776 lcd->dev = &dsim_dev->dev;
777
778 mutex_init(&lcd->lock);
779
780 ret = regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies);
781 if (ret) {
782 dev_err(lcd->dev, "Failed to get regulators: %d\n", ret);
783 goto err_lcd_register;
784 }
785
786 lcd->ld = lcd_device_register("s6e8ax0", lcd->dev, lcd,
787 &s6e8ax0_lcd_ops);
788 if (IS_ERR(lcd->ld)) {
789 dev_err(lcd->dev, "failed to register lcd ops.\n");
790 ret = PTR_ERR(lcd->ld);
791 goto err_lcd_register;
792 }
793
794 lcd->bd = backlight_device_register("s6e8ax0-bl", lcd->dev, lcd,
795 &s6e8ax0_backlight_ops, NULL);
796 if (IS_ERR(lcd->bd)) {
797 dev_err(lcd->dev, "failed to register backlight ops.\n");
798 ret = PTR_ERR(lcd->bd);
799 goto err_backlight_register;
800 }
801
802 lcd->bd->props.max_brightness = MAX_BRIGHTNESS;
803 lcd->bd->props.brightness = MAX_BRIGHTNESS;
804
805 s6e8ax0_read_id(lcd, mtp_id);
806 if (mtp_id[0] == 0x00)
807 dev_err(lcd->dev, "read id failed\n");
808
809 dev_info(lcd->dev, "Read ID : %x, %x, %x\n",
810 mtp_id[0], mtp_id[1], mtp_id[2]);
811
812 if (mtp_id[2] == 0x33)
813 dev_info(lcd->dev,
814 "ID-3 is 0xff does not support dynamic elvss\n");
815 else
816 dev_info(lcd->dev,
817 "ID-3 is 0x%x support dynamic elvss\n", mtp_id[2]);
818
819 lcd->acl_enable = 1;
820 lcd->cur_acl = 0;
821
822 dev_set_drvdata(&dsim_dev->dev, lcd);
823
824 dev_dbg(lcd->dev, "probed s6e8ax0 panel driver.\n");
825
826 return 0;
827
828err_backlight_register:
829 lcd_device_unregister(lcd->ld);
830
831err_lcd_register:
832 regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
833 kfree(lcd);
834
835 return ret;
836}
837
838#ifdef CONFIG_PM
839static int s6e8ax0_suspend(struct mipi_dsim_lcd_device *dsim_dev)
840{
841 struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
842
843 s6e8ax0_sleep_in(lcd);
844 msleep(lcd->ddi_pd->power_off_delay);
845 s6e8ax0_display_off(lcd);
846
847 s6e8ax0_regulator_disable(lcd);
848
849 return 0;
850}
851
852static int s6e8ax0_resume(struct mipi_dsim_lcd_device *dsim_dev)
853{
854 struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
855
856 s6e8ax0_sleep_out(lcd);
857 msleep(lcd->ddi_pd->power_on_delay);
858
859 s6e8ax0_regulator_enable(lcd);
860 s6e8ax0_set_sequence(dsim_dev);
861
862 return 0;
863}
864#else
865#define s6e8ax0_suspend NULL
866#define s6e8ax0_resume NULL
867#endif
868
869static struct mipi_dsim_lcd_driver s6e8ax0_dsim_ddi_driver = {
870 .name = "s6e8ax0",
871 .id = -1,
872
873 .power_on = s6e8ax0_power_on,
874 .set_sequence = s6e8ax0_set_sequence,
875 .probe = s6e8ax0_probe,
876 .suspend = s6e8ax0_suspend,
877 .resume = s6e8ax0_resume,
878};
879
880static int s6e8ax0_init(void)
881{
882 exynos_mipi_dsi_register_lcd_driver(&s6e8ax0_dsim_ddi_driver);
883
884 return 0;
885}
886
887static void s6e8ax0_exit(void)
888{
889 return;
890}
891
892module_init(s6e8ax0_init);
893module_exit(s6e8ax0_exit);
894
895MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
896MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
897MODULE_DESCRIPTION("MIPI-DSI based s6e8ax0 AMOLED LCD Panel Driver");
898MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/s6e8ax0.h b/drivers/video/exynos/s6e8ax0.h
new file mode 100644
index 000000000000..1f1b270484b0
--- /dev/null
+++ b/drivers/video/exynos/s6e8ax0.h
@@ -0,0 +1,21 @@
1/* linux/drivers/video/backlight/s6e8ax0.h
2 *
3 * MIPI-DSI based s6e8ax0 AMOLED LCD Panel definitions.
4 *
5 * Copyright (c) 2011 Samsung Electronics
6 *
7 * Inki Dae, <inki.dae@samsung.com>
8 * Donghwa Lee <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#ifndef _S6E8AX0_H
16#define _S6E8AX0_H
17
18extern void s6e8ax0_init(void);
19
20#endif
21
diff --git a/drivers/video/i740_reg.h b/drivers/video/i740_reg.h
new file mode 100644
index 000000000000..91bac76549d7
--- /dev/null
+++ b/drivers/video/i740_reg.h
@@ -0,0 +1,309 @@
1/**************************************************************************
2
3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4All Rights Reserved.
5
6Permission is hereby granted, free of charge, to any person obtaining a
7copy of this software and associated documentation files (the
8"Software"), to deal in the Software without restriction, including
9without limitation the rights to use, copy, modify, merge, publish,
10distribute, sub license, and/or sell copies of the Software, and to
11permit persons to whom the Software is furnished to do so, subject to
12the following conditions:
13
14The above copyright notice and this permission notice (including the
15next paragraph) shall be included in all copies or substantial portions
16of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26**************************************************************************/
27
28/*
29 * Authors:
30 * Kevin E. Martin <kevin@precisioninsight.com>
31 */
32
33/* I/O register offsets */
34#define SRX VGA_SEQ_I
35#define GRX VGA_GFX_I
36#define ARX VGA_ATT_IW
37#define XRX 0x3D6
38#define MRX 0x3D2
39
40/* VGA Color Palette Registers */
41#define DACMASK 0x3C6
42#define DACSTATE 0x3C7
43#define DACRX 0x3C7
44#define DACWX 0x3C8
45#define DACDATA 0x3C9
46
47/* CRT Controller Registers (CRX) */
48#define START_ADDR_HI 0x0C
49#define START_ADDR_LO 0x0D
50#define VERT_SYNC_END 0x11
51#define EXT_VERT_TOTAL 0x30
52#define EXT_VERT_DISPLAY 0x31
53#define EXT_VERT_SYNC_START 0x32
54#define EXT_VERT_BLANK_START 0x33
55#define EXT_HORIZ_TOTAL 0x35
56#define EXT_HORIZ_BLANK 0x39
57#define EXT_START_ADDR 0x40
58#define EXT_START_ADDR_ENABLE 0x80
59#define EXT_OFFSET 0x41
60#define EXT_START_ADDR_HI 0x42
61#define INTERLACE_CNTL 0x70
62#define INTERLACE_ENABLE 0x80
63#define INTERLACE_DISABLE 0x00
64
65/* Miscellaneous Output Register */
66#define MSR_R 0x3CC
67#define MSR_W 0x3C2
68#define IO_ADDR_SELECT 0x01
69
70#define MDA_BASE 0x3B0
71#define CGA_BASE 0x3D0
72
73/* System Configuration Extension Registers (XRX) */
74#define IO_CTNL 0x09
75#define EXTENDED_ATTR_CNTL 0x02
76#define EXTENDED_CRTC_CNTL 0x01
77
78#define ADDRESS_MAPPING 0x0A
79#define PACKED_MODE_ENABLE 0x04
80#define LINEAR_MODE_ENABLE 0x02
81#define PAGE_MAPPING_ENABLE 0x01
82
83#define BITBLT_CNTL 0x20
84#define COLEXP_MODE 0x30
85#define COLEXP_8BPP 0x00
86#define COLEXP_16BPP 0x10
87#define COLEXP_24BPP 0x20
88#define COLEXP_RESERVED 0x30
89#define CHIP_RESET 0x02
90#define BITBLT_STATUS 0x01
91
92#define DISPLAY_CNTL 0x40
93#define VGA_WRAP_MODE 0x02
94#define VGA_WRAP_AT_256KB 0x00
95#define VGA_NO_WRAP 0x02
96#define GUI_MODE 0x01
97#define STANDARD_VGA_MODE 0x00
98#define HIRES_MODE 0x01
99
100#define DRAM_ROW_TYPE 0x50
101#define DRAM_ROW_0 0x07
102#define DRAM_ROW_0_SDRAM 0x00
103#define DRAM_ROW_0_EMPTY 0x07
104#define DRAM_ROW_1 0x38
105#define DRAM_ROW_1_SDRAM 0x00
106#define DRAM_ROW_1_EMPTY 0x38
107#define DRAM_ROW_CNTL_LO 0x51
108#define DRAM_CAS_LATENCY 0x10
109#define DRAM_RAS_TIMING 0x08
110#define DRAM_RAS_PRECHARGE 0x04
111#define DRAM_ROW_CNTL_HI 0x52
112#define DRAM_EXT_CNTL 0x53
113#define DRAM_REFRESH_RATE 0x03
114#define DRAM_REFRESH_DISABLE 0x00
115#define DRAM_REFRESH_60HZ 0x01
116#define DRAM_REFRESH_FAST_TEST 0x02
117#define DRAM_REFRESH_RESERVED 0x03
118#define DRAM_TIMING 0x54
119#define DRAM_ROW_BNDRY_0 0x55
120#define DRAM_ROW_BNDRY_1 0x56
121
122#define DPMS_SYNC_SELECT 0x61
123#define VSYNC_CNTL 0x08
124#define VSYNC_ON 0x00
125#define VSYNC_OFF 0x08
126#define HSYNC_CNTL 0x02
127#define HSYNC_ON 0x00
128#define HSYNC_OFF 0x02
129
130#define PIXPIPE_CONFIG_0 0x80
131#define DAC_8_BIT 0x80
132#define DAC_6_BIT 0x00
133#define HW_CURSOR_ENABLE 0x10
134#define EXTENDED_PALETTE 0x01
135
136#define PIXPIPE_CONFIG_1 0x81
137#define DISPLAY_COLOR_MODE 0x0F
138#define DISPLAY_VGA_MODE 0x00
139#define DISPLAY_8BPP_MODE 0x02
140#define DISPLAY_15BPP_MODE 0x04
141#define DISPLAY_16BPP_MODE 0x05
142#define DISPLAY_24BPP_MODE 0x06
143#define DISPLAY_32BPP_MODE 0x07
144
145#define PIXPIPE_CONFIG_2 0x82
146#define DISPLAY_GAMMA_ENABLE 0x08
147#define DISPLAY_GAMMA_DISABLE 0x00
148#define OVERLAY_GAMMA_ENABLE 0x04
149#define OVERLAY_GAMMA_DISABLE 0x00
150
151#define CURSOR_CONTROL 0xA0
152#define CURSOR_ORIGIN_SCREEN 0x00
153#define CURSOR_ORIGIN_DISPLAY 0x10
154#define CURSOR_MODE 0x07
155#define CURSOR_MODE_DISABLE 0x00
156#define CURSOR_MODE_32_4C_AX 0x01
157#define CURSOR_MODE_128_2C 0x02
158#define CURSOR_MODE_128_1C 0x03
159#define CURSOR_MODE_64_3C 0x04
160#define CURSOR_MODE_64_4C_AX 0x05
161#define CURSOR_MODE_64_4C 0x06
162#define CURSOR_MODE_RESERVED 0x07
163#define CURSOR_BASEADDR_LO 0xA2
164#define CURSOR_BASEADDR_HI 0xA3
165#define CURSOR_X_LO 0xA4
166#define CURSOR_X_HI 0xA5
167#define CURSOR_X_POS 0x00
168#define CURSOR_X_NEG 0x80
169#define CURSOR_Y_LO 0xA6
170#define CURSOR_Y_HI 0xA7
171#define CURSOR_Y_POS 0x00
172#define CURSOR_Y_NEG 0x80
173
174#define VCLK2_VCO_M 0xC8
175#define VCLK2_VCO_N 0xC9
176#define VCLK2_VCO_MN_MSBS 0xCA
177#define VCO_N_MSBS 0x30
178#define VCO_M_MSBS 0x03
179#define VCLK2_VCO_DIV_SEL 0xCB
180#define POST_DIV_SELECT 0x70
181#define POST_DIV_1 0x00
182#define POST_DIV_2 0x10
183#define POST_DIV_4 0x20
184#define POST_DIV_8 0x30
185#define POST_DIV_16 0x40
186#define POST_DIV_32 0x50
187#define VCO_LOOP_DIV_BY_4M 0x00
188#define VCO_LOOP_DIV_BY_16M 0x04
189#define REF_CLK_DIV_BY_5 0x02
190#define REF_DIV_4 0x00
191#define REF_DIV_1 0x01
192
193#define PLL_CNTL 0xCE
194#define PLL_MEMCLK_SEL 0x03
195#define PLL_MEMCLK__66667KHZ 0x00
196#define PLL_MEMCLK__75000KHZ 0x01
197#define PLL_MEMCLK__88889KHZ 0x02
198#define PLL_MEMCLK_100000KHZ 0x03
199
200/* Multimedia Extension Registers (MRX) */
201#define ACQ_CNTL_1 0x02
202#define ACQ_CNTL_2 0x03
203#define FRAME_CAP_MODE 0x01
204#define CONT_CAP_MODE 0x00
205#define SINGLE_CAP_MODE 0x01
206#define ACQ_CNTL_3 0x04
207#define COL_KEY_CNTL_1 0x3C
208#define BLANK_DISP_OVERLAY 0x20
209
210/* FIFOs */
211#define LP_FIFO 0x1000
212#define HP_FIFO 0x2000
213#define INSTPNT 0x3040
214#define LP_FIFO_COUNT 0x3040
215#define HP_FIFO_COUNT 0x3041
216
217/* FIFO Commands */
218#define CLIENT 0xE0000000
219#define CLIENT_2D 0x60000000
220
221/* Command Parser Mode Register */
222#define COMPARS 0x3038
223#define TWO_D_INST_DISABLE 0x08
224#define THREE_D_INST_DISABLE 0x04
225#define STATE_VAR_UPDATE_DISABLE 0x02
226#define PAL_STIP_DISABLE 0x01
227
228/* Interrupt Control Registers */
229#define IER 0x3030
230#define IIR 0x3032
231#define IMR 0x3034
232#define ISR 0x3036
233#define VMIINTB_EVENT 0x2000
234#define GPIO4_INT 0x1000
235#define DISP_FLIP_EVENT 0x0800
236#define DVD_PORT_DMA 0x0400
237#define DISP_VBLANK 0x0200
238#define FIFO_EMPTY_DMA_DONE 0x0100
239#define INST_PARSER_ERROR 0x0080
240#define USER_DEFINED 0x0040
241#define BREAKPOINT 0x0020
242#define DISP_HORIZ_COUNT 0x0010
243#define DISP_VSYNC 0x0008
244#define CAPTURE_HORIZ_COUNT 0x0004
245#define CAPTURE_VSYNC 0x0002
246#define THREE_D_PIPE_FLUSHED 0x0001
247
248/* FIFO Watermark and Burst Length Control Register */
249#define FWATER_BLC 0x00006000
250#define LMI_BURST_LENGTH 0x7F000000
251#define LMI_FIFO_WATERMARK 0x003F0000
252#define AGP_BURST_LENGTH 0x00007F00
253#define AGP_FIFO_WATERMARK 0x0000003F
254
255/* BitBLT Registers */
256#define SRC_DST_PITCH 0x00040000
257#define DST_PITCH 0x1FFF0000
258#define SRC_PITCH 0x00001FFF
259#define COLEXP_BG_COLOR 0x00040004
260#define COLEXP_FG_COLOR 0x00040008
261#define MONO_SRC_CNTL 0x0004000C
262#define MONO_USE_COLEXP 0x00000000
263#define MONO_USE_SRCEXP 0x08000000
264#define MONO_DATA_ALIGN 0x07000000
265#define MONO_BIT_ALIGN 0x01000000
266#define MONO_BYTE_ALIGN 0x02000000
267#define MONO_WORD_ALIGN 0x03000000
268#define MONO_DWORD_ALIGN 0x04000000
269#define MONO_QWORD_ALIGN 0x05000000
270#define MONO_SRC_INIT_DSCRD 0x003F0000
271#define MONO_SRC_RIGHT_CLIP 0x00003F00
272#define MONO_SRC_LEFT_CLIP 0x0000003F
273#define BITBLT_CONTROL 0x00040010
274#define BLTR_STATUS 0x80000000
275#define DYN_DEPTH 0x03000000
276#define DYN_DEPTH_8BPP 0x00000000
277#define DYN_DEPTH_16BPP 0x01000000
278#define DYN_DEPTH_24BPP 0x02000000
279#define DYN_DEPTH_32BPP 0x03000000 /* Unimplemented on the i740 */
280#define DYN_DEPTH_ENABLE 0x00800000
281#define PAT_VERT_ALIGN 0x00700000
282#define SOLID_PAT_SELECT 0x00080000
283#define PAT_IS_IN_COLOR 0x00000000
284#define PAT_IS_MONO 0x00040000
285#define MONO_PAT_TRANSP 0x00020000
286#define COLOR_TRANSP_ROP 0x00000000
287#define COLOR_TRANSP_DST 0x00008000
288#define COLOR_TRANSP_EQ 0x00000000
289#define COLOR_TRANSP_NOT_EQ 0x00010000
290#define COLOR_TRANSP_ENABLE 0x00004000
291#define MONO_SRC_TRANSP 0x00002000
292#define SRC_IS_IN_COLOR 0x00000000
293#define SRC_IS_MONO 0x00001000
294#define SRC_USE_SRC_ADDR 0x00000000
295#define SRC_USE_BLTDATA 0x00000400
296#define BLT_TOP_TO_BOT 0x00000000
297#define BLT_BOT_TO_TOP 0x00000200
298#define BLT_LEFT_TO_RIGHT 0x00000000
299#define BLT_RIGHT_TO_LEFT 0x00000100
300#define BLT_ROP 0x000000FF
301#define BLT_PAT_ADDR 0x00040014
302#define BLT_SRC_ADDR 0x00040018
303#define BLT_DST_ADDR 0x0004001C
304#define BLT_DST_H_W 0x00040020
305#define BLT_DST_HEIGHT 0x1FFF0000
306#define BLT_DST_WIDTH 0x00001FFF
307#define SRCEXP_BG_COLOR 0x00040024
308#define SRCEXP_FG_COLOR 0x00040028
309#define BLTDATA 0x00050000
diff --git a/drivers/video/i740fb.c b/drivers/video/i740fb.c
new file mode 100644
index 000000000000..fe574d84ed99
--- /dev/null
+++ b/drivers/video/i740fb.c
@@ -0,0 +1,1337 @@
1/*
2 * i740fb - framebuffer driver for Intel740
3 * Copyright (c) 2011 Ondrej Zary
4 *
5 * Based on old i740fb driver (c) 2001-2002 Andrey Ulanov <drey@rt.mipt.ru>
6 * which was partially based on:
7 * VGA 16-color framebuffer driver (c) 1999 Ben Pfaff <pfaffben@debian.org>
8 * and Petr Vandrovec <VANDROVE@vc.cvut.cz>
9 * i740 driver from XFree86 (c) 1998-1999 Precision Insight, Inc., Cedar Park,
10 * Texas.
11 * i740fb by Patrick LERDA, v0.9
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/errno.h>
17#include <linux/string.h>
18#include <linux/mm.h>
19#include <linux/slab.h>
20#include <linux/delay.h>
21#include <linux/fb.h>
22#include <linux/init.h>
23#include <linux/pci.h>
24#include <linux/pci_ids.h>
25#include <linux/i2c.h>
26#include <linux/i2c-algo-bit.h>
27#include <linux/console.h>
28#include <video/vga.h>
29
30#ifdef CONFIG_MTRR
31#include <asm/mtrr.h>
32#endif
33
34#include "i740_reg.h"
35
36static char *mode_option __devinitdata;
37
38#ifdef CONFIG_MTRR
39static int mtrr __devinitdata = 1;
40#endif
41
42struct i740fb_par {
43 unsigned char __iomem *regs;
44 bool has_sgram;
45#ifdef CONFIG_MTRR
46 int mtrr_reg;
47#endif
48 bool ddc_registered;
49 struct i2c_adapter ddc_adapter;
50 struct i2c_algo_bit_data ddc_algo;
51 u32 pseudo_palette[16];
52 struct mutex open_lock;
53 unsigned int ref_count;
54
55 u8 crtc[VGA_CRT_C];
56 u8 atc[VGA_ATT_C];
57 u8 gdc[VGA_GFX_C];
58 u8 seq[VGA_SEQ_C];
59 u8 misc;
60 u8 vss;
61
62 /* i740 specific registers */
63 u8 display_cntl;
64 u8 pixelpipe_cfg0;
65 u8 pixelpipe_cfg1;
66 u8 pixelpipe_cfg2;
67 u8 video_clk2_m;
68 u8 video_clk2_n;
69 u8 video_clk2_mn_msbs;
70 u8 video_clk2_div_sel;
71 u8 pll_cntl;
72 u8 address_mapping;
73 u8 io_cntl;
74 u8 bitblt_cntl;
75 u8 ext_vert_total;
76 u8 ext_vert_disp_end;
77 u8 ext_vert_sync_start;
78 u8 ext_vert_blank_start;
79 u8 ext_horiz_total;
80 u8 ext_horiz_blank;
81 u8 ext_offset;
82 u8 interlace_cntl;
83 u32 lmi_fifo_watermark;
84 u8 ext_start_addr;
85 u8 ext_start_addr_hi;
86};
87
88#define DACSPEED8 203
89#define DACSPEED16 163
90#define DACSPEED24_SG 136
91#define DACSPEED24_SD 128
92#define DACSPEED32 86
93
94static struct fb_fix_screeninfo i740fb_fix __devinitdata = {
95 .id = "i740fb",
96 .type = FB_TYPE_PACKED_PIXELS,
97 .visual = FB_VISUAL_TRUECOLOR,
98 .xpanstep = 8,
99 .ypanstep = 1,
100 .accel = FB_ACCEL_NONE,
101};
102
103static inline void i740outb(struct i740fb_par *par, u16 port, u8 val)
104{
105 vga_mm_w(par->regs, port, val);
106}
107static inline u8 i740inb(struct i740fb_par *par, u16 port)
108{
109 return vga_mm_r(par->regs, port);
110}
111static inline void i740outreg(struct i740fb_par *par, u16 port, u8 reg, u8 val)
112{
113 vga_mm_w_fast(par->regs, port, reg, val);
114}
115static inline u8 i740inreg(struct i740fb_par *par, u16 port, u8 reg)
116{
117 vga_mm_w(par->regs, port, reg);
118 return vga_mm_r(par->regs, port+1);
119}
120static inline void i740outreg_mask(struct i740fb_par *par, u16 port, u8 reg,
121 u8 val, u8 mask)
122{
123 vga_mm_w_fast(par->regs, port, reg, (val & mask)
124 | (i740inreg(par, port, reg) & ~mask));
125}
126
127#define REG_DDC_DRIVE 0x62
128#define REG_DDC_STATE 0x63
129#define DDC_SCL (1 << 3)
130#define DDC_SDA (1 << 2)
131
132static void i740fb_ddc_setscl(void *data, int val)
133{
134 struct i740fb_par *par = data;
135
136 i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SCL, DDC_SCL);
137 i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SCL : 0, DDC_SCL);
138}
139
140static void i740fb_ddc_setsda(void *data, int val)
141{
142 struct i740fb_par *par = data;
143
144 i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SDA, DDC_SDA);
145 i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SDA : 0, DDC_SDA);
146}
147
148static int i740fb_ddc_getscl(void *data)
149{
150 struct i740fb_par *par = data;
151
152 i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SCL);
153
154 return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SCL);
155}
156
157static int i740fb_ddc_getsda(void *data)
158{
159 struct i740fb_par *par = data;
160
161 i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SDA);
162
163 return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SDA);
164}
165
166static int __devinit i740fb_setup_ddc_bus(struct fb_info *info)
167{
168 struct i740fb_par *par = info->par;
169
170 strlcpy(par->ddc_adapter.name, info->fix.id,
171 sizeof(par->ddc_adapter.name));
172 par->ddc_adapter.owner = THIS_MODULE;
173 par->ddc_adapter.class = I2C_CLASS_DDC;
174 par->ddc_adapter.algo_data = &par->ddc_algo;
175 par->ddc_adapter.dev.parent = info->device;
176 par->ddc_algo.setsda = i740fb_ddc_setsda;
177 par->ddc_algo.setscl = i740fb_ddc_setscl;
178 par->ddc_algo.getsda = i740fb_ddc_getsda;
179 par->ddc_algo.getscl = i740fb_ddc_getscl;
180 par->ddc_algo.udelay = 10;
181 par->ddc_algo.timeout = 20;
182 par->ddc_algo.data = par;
183
184 i2c_set_adapdata(&par->ddc_adapter, par);
185
186 return i2c_bit_add_bus(&par->ddc_adapter);
187}
188
189static int i740fb_open(struct fb_info *info, int user)
190{
191 struct i740fb_par *par = info->par;
192
193 mutex_lock(&(par->open_lock));
194 par->ref_count++;
195 mutex_unlock(&(par->open_lock));
196
197 return 0;
198}
199
200static int i740fb_release(struct fb_info *info, int user)
201{
202 struct i740fb_par *par = info->par;
203
204 mutex_lock(&(par->open_lock));
205 if (par->ref_count == 0) {
206 printk(KERN_ERR "fb%d: release called with zero refcount\n",
207 info->node);
208 mutex_unlock(&(par->open_lock));
209 return -EINVAL;
210 }
211
212 par->ref_count--;
213 mutex_unlock(&(par->open_lock));
214
215 return 0;
216}
217
218static u32 i740_calc_fifo(struct i740fb_par *par, u32 freq, int bpp)
219{
220 /*
221 * Would like to calculate these values automatically, but a generic
222 * algorithm does not seem possible. Note: These FIFO water mark
223 * values were tested on several cards and seem to eliminate the
224 * all of the snow and vertical banding, but fine adjustments will
225 * probably be required for other cards.
226 */
227
228 u32 wm;
229
230 switch (bpp) {
231 case 8:
232 if (freq > 200)
233 wm = 0x18120000;
234 else if (freq > 175)
235 wm = 0x16110000;
236 else if (freq > 135)
237 wm = 0x120E0000;
238 else
239 wm = 0x100D0000;
240 break;
241 case 15:
242 case 16:
243 if (par->has_sgram) {
244 if (freq > 140)
245 wm = 0x2C1D0000;
246 else if (freq > 120)
247 wm = 0x2C180000;
248 else if (freq > 100)
249 wm = 0x24160000;
250 else if (freq > 90)
251 wm = 0x18120000;
252 else if (freq > 50)
253 wm = 0x16110000;
254 else if (freq > 32)
255 wm = 0x13100000;
256 else
257 wm = 0x120E0000;
258 } else {
259 if (freq > 160)
260 wm = 0x28200000;
261 else if (freq > 140)
262 wm = 0x2A1E0000;
263 else if (freq > 130)
264 wm = 0x2B1A0000;
265 else if (freq > 120)
266 wm = 0x2C180000;
267 else if (freq > 100)
268 wm = 0x24180000;
269 else if (freq > 90)
270 wm = 0x18120000;
271 else if (freq > 50)
272 wm = 0x16110000;
273 else if (freq > 32)
274 wm = 0x13100000;
275 else
276 wm = 0x120E0000;
277 }
278 break;
279 case 24:
280 if (par->has_sgram) {
281 if (freq > 130)
282 wm = 0x31200000;
283 else if (freq > 120)
284 wm = 0x2E200000;
285 else if (freq > 100)
286 wm = 0x2C1D0000;
287 else if (freq > 80)
288 wm = 0x25180000;
289 else if (freq > 64)
290 wm = 0x24160000;
291 else if (freq > 49)
292 wm = 0x18120000;
293 else if (freq > 32)
294 wm = 0x16110000;
295 else
296 wm = 0x13100000;
297 } else {
298 if (freq > 120)
299 wm = 0x311F0000;
300 else if (freq > 100)
301 wm = 0x2C1D0000;
302 else if (freq > 80)
303 wm = 0x25180000;
304 else if (freq > 64)
305 wm = 0x24160000;
306 else if (freq > 49)
307 wm = 0x18120000;
308 else if (freq > 32)
309 wm = 0x16110000;
310 else
311 wm = 0x13100000;
312 }
313 break;
314 case 32:
315 if (par->has_sgram) {
316 if (freq > 80)
317 wm = 0x2A200000;
318 else if (freq > 60)
319 wm = 0x281A0000;
320 else if (freq > 49)
321 wm = 0x25180000;
322 else if (freq > 32)
323 wm = 0x18120000;
324 else
325 wm = 0x16110000;
326 } else {
327 if (freq > 80)
328 wm = 0x29200000;
329 else if (freq > 60)
330 wm = 0x281A0000;
331 else if (freq > 49)
332 wm = 0x25180000;
333 else if (freq > 32)
334 wm = 0x18120000;
335 else
336 wm = 0x16110000;
337 }
338 break;
339 }
340
341 return wm;
342}
343
344/* clock calculation from i740fb by Patrick LERDA */
345
346#define I740_RFREQ 1000000
347#define TARGET_MAX_N 30
348#define I740_FFIX (1 << 8)
349#define I740_RFREQ_FIX (I740_RFREQ / I740_FFIX)
350#define I740_REF_FREQ (6667 * I740_FFIX / 100) /* 66.67 MHz */
351#define I740_MAX_VCO_FREQ (450 * I740_FFIX) /* 450 MHz */
352
353static void i740_calc_vclk(u32 freq, struct i740fb_par *par)
354{
355 const u32 err_max = freq / (200 * I740_RFREQ / I740_FFIX);
356 const u32 err_target = freq / (1000 * I740_RFREQ / I740_FFIX);
357 u32 err_best = 512 * I740_FFIX;
358 u32 f_err, f_vco;
359 int m_best = 0, n_best = 0, p_best = 0, d_best = 0;
360 int m, n;
361
362 p_best = min(15, ilog2(I740_MAX_VCO_FREQ / (freq / I740_RFREQ_FIX)));
363 d_best = 0;
364 f_vco = (freq * (1 << p_best)) / I740_RFREQ_FIX;
365 freq = freq / I740_RFREQ_FIX;
366
367 n = 2;
368 do {
369 n++;
370 m = ((f_vco * n) / I740_REF_FREQ + 2) / 4;
371
372 if (m < 3)
373 m = 3;
374
375 {
376 u32 f_out = (((m * I740_REF_FREQ * (4 << 2 * d_best))
377 / n) + ((1 << p_best) / 2)) / (1 << p_best);
378
379 f_err = (freq - f_out);
380
381 if (abs(f_err) < err_max) {
382 m_best = m;
383 n_best = n;
384 err_best = f_err;
385 }
386 }
387 } while ((abs(f_err) >= err_target) &&
388 ((n <= TARGET_MAX_N) || (abs(err_best) > err_max)));
389
390 if (abs(f_err) < err_target) {
391 m_best = m;
392 n_best = n;
393 }
394
395 par->video_clk2_m = (m_best - 2) & 0xFF;
396 par->video_clk2_n = (n_best - 2) & 0xFF;
397 par->video_clk2_mn_msbs = ((((n_best - 2) >> 4) & VCO_N_MSBS)
398 | (((m_best - 2) >> 8) & VCO_M_MSBS));
399 par->video_clk2_div_sel =
400 ((p_best << 4) | (d_best ? 4 : 0) | REF_DIV_1);
401}
402
403static int i740fb_decode_var(const struct fb_var_screeninfo *var,
404 struct i740fb_par *par, struct fb_info *info)
405{
406 /*
407 * Get the video params out of 'var'.
408 * If a value doesn't fit, round it up, if it's too big, return -EINVAL.
409 */
410
411 u32 xres, right, hslen, left, xtotal;
412 u32 yres, lower, vslen, upper, ytotal;
413 u32 vxres, xoffset, vyres, yoffset;
414 u32 bpp, base, dacspeed24, mem;
415 u8 r7;
416 int i;
417
418 dev_dbg(info->device, "decode_var: xres: %i, yres: %i, xres_v: %i, xres_v: %i\n",
419 var->xres, var->yres, var->xres_virtual, var->xres_virtual);
420 dev_dbg(info->device, " xoff: %i, yoff: %i, bpp: %i, graysc: %i\n",
421 var->xoffset, var->yoffset, var->bits_per_pixel,
422 var->grayscale);
423 dev_dbg(info->device, " activate: %i, nonstd: %i, vmode: %i\n",
424 var->activate, var->nonstd, var->vmode);
425 dev_dbg(info->device, " pixclock: %i, hsynclen:%i, vsynclen:%i\n",
426 var->pixclock, var->hsync_len, var->vsync_len);
427 dev_dbg(info->device, " left: %i, right: %i, up:%i, lower:%i\n",
428 var->left_margin, var->right_margin, var->upper_margin,
429 var->lower_margin);
430
431
432 bpp = var->bits_per_pixel;
433 switch (bpp) {
434 case 1 ... 8:
435 bpp = 8;
436 if ((1000000 / var->pixclock) > DACSPEED8) {
437 dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 8bpp)\n",
438 1000000 / var->pixclock, DACSPEED8);
439 return -EINVAL;
440 }
441 break;
442 case 9 ... 15:
443 bpp = 15;
444 case 16:
445 if ((1000000 / var->pixclock) > DACSPEED16) {
446 dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n",
447 1000000 / var->pixclock, DACSPEED16);
448 return -EINVAL;
449 }
450 break;
451 case 17 ... 24:
452 bpp = 24;
453 dacspeed24 = par->has_sgram ? DACSPEED24_SG : DACSPEED24_SD;
454 if ((1000000 / var->pixclock) > dacspeed24) {
455 dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 24bpp)\n",
456 1000000 / var->pixclock, dacspeed24);
457 return -EINVAL;
458 }
459 break;
460 case 25 ... 32:
461 bpp = 32;
462 if ((1000000 / var->pixclock) > DACSPEED32) {
463 dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 32bpp)\n",
464 1000000 / var->pixclock, DACSPEED32);
465 return -EINVAL;
466 }
467 break;
468 default:
469 return -EINVAL;
470 }
471
472 xres = ALIGN(var->xres, 8);
473 vxres = ALIGN(var->xres_virtual, 16);
474 if (vxres < xres)
475 vxres = xres;
476
477 xoffset = ALIGN(var->xoffset, 8);
478 if (xres + xoffset > vxres)
479 xoffset = vxres - xres;
480
481 left = ALIGN(var->left_margin, 8);
482 right = ALIGN(var->right_margin, 8);
483 hslen = ALIGN(var->hsync_len, 8);
484
485 yres = var->yres;
486 vyres = var->yres_virtual;
487 if (yres > vyres)
488 vyres = yres;
489
490 yoffset = var->yoffset;
491 if (yres + yoffset > vyres)
492 yoffset = vyres - yres;
493
494 lower = var->lower_margin;
495 vslen = var->vsync_len;
496 upper = var->upper_margin;
497
498 mem = vxres * vyres * ((bpp + 1) / 8);
499 if (mem > info->screen_size) {
500 dev_err(info->device, "not enough video memory (%d KB requested, %ld KB avaliable)\n",
501 mem >> 10, info->screen_size >> 10);
502 return -ENOMEM;
503 }
504
505 if (yoffset + yres > vyres)
506 yoffset = vyres - yres;
507
508 xtotal = xres + right + hslen + left;
509 ytotal = yres + lower + vslen + upper;
510
511 par->crtc[VGA_CRTC_H_TOTAL] = (xtotal >> 3) - 5;
512 par->crtc[VGA_CRTC_H_DISP] = (xres >> 3) - 1;
513 par->crtc[VGA_CRTC_H_BLANK_START] = ((xres + right) >> 3) - 1;
514 par->crtc[VGA_CRTC_H_SYNC_START] = (xres + right) >> 3;
515 par->crtc[VGA_CRTC_H_SYNC_END] = (((xres + right + hslen) >> 3) & 0x1F)
516 | ((((xres + right + hslen) >> 3) & 0x20) << 2);
517 par->crtc[VGA_CRTC_H_BLANK_END] = ((xres + right + hslen) >> 3 & 0x1F)
518 | 0x80;
519
520 par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
521
522 r7 = 0x10; /* disable linecompare */
523 if (ytotal & 0x100)
524 r7 |= 0x01;
525 if (ytotal & 0x200)
526 r7 |= 0x20;
527
528 par->crtc[VGA_CRTC_PRESET_ROW] = 0;
529 par->crtc[VGA_CRTC_MAX_SCAN] = 0x40; /* 1 scanline, no linecmp */
530 if (var->vmode & FB_VMODE_DOUBLE)
531 par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
532 par->crtc[VGA_CRTC_CURSOR_START] = 0x00;
533 par->crtc[VGA_CRTC_CURSOR_END] = 0x00;
534 par->crtc[VGA_CRTC_CURSOR_HI] = 0x00;
535 par->crtc[VGA_CRTC_CURSOR_LO] = 0x00;
536 par->crtc[VGA_CRTC_V_DISP_END] = yres-1;
537 if ((yres-1) & 0x100)
538 r7 |= 0x02;
539 if ((yres-1) & 0x200)
540 r7 |= 0x40;
541
542 par->crtc[VGA_CRTC_V_BLANK_START] = yres + lower - 1;
543 par->crtc[VGA_CRTC_V_SYNC_START] = yres + lower - 1;
544 if ((yres + lower - 1) & 0x100)
545 r7 |= 0x0C;
546 if ((yres + lower - 1) & 0x200) {
547 par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20;
548 r7 |= 0x80;
549 }
550
551 /* disabled IRQ */
552 par->crtc[VGA_CRTC_V_SYNC_END] =
553 ((yres + lower - 1 + vslen) & 0x0F) & ~0x10;
554 /* 0x7F for VGA, but some SVGA chips require all 8 bits to be set */
555 par->crtc[VGA_CRTC_V_BLANK_END] = (yres + lower - 1 + vslen) & 0xFF;
556
557 par->crtc[VGA_CRTC_UNDERLINE] = 0x00;
558 par->crtc[VGA_CRTC_MODE] = 0xC3 ;
559 par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
560 par->crtc[VGA_CRTC_OVERFLOW] = r7;
561
562 par->vss = 0x00; /* 3DA */
563
564 for (i = 0x00; i < 0x10; i++)
565 par->atc[i] = i;
566 par->atc[VGA_ATC_MODE] = 0x81;
567 par->atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */
568 par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
569 par->atc[VGA_ATC_COLOR_PAGE] = 0x00;
570
571 par->misc = 0xC3;
572 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
573 par->misc &= ~0x40;
574 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
575 par->misc &= ~0x80;
576
577 par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;
578 par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
579 par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
580 par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;
581
582 par->gdc[VGA_GFX_SR_VALUE] = 0x00;
583 par->gdc[VGA_GFX_SR_ENABLE] = 0x00;
584 par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
585 par->gdc[VGA_GFX_DATA_ROTATE] = 0x00;
586 par->gdc[VGA_GFX_PLANE_READ] = 0;
587 par->gdc[VGA_GFX_MODE] = 0x02;
588 par->gdc[VGA_GFX_MISC] = 0x05;
589 par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
590 par->gdc[VGA_GFX_BIT_MASK] = 0xFF;
591
592 base = (yoffset * vxres + (xoffset & ~7)) >> 2;
593 switch (bpp) {
594 case 8:
595 par->crtc[VGA_CRTC_OFFSET] = vxres >> 3;
596 par->ext_offset = vxres >> 11;
597 par->pixelpipe_cfg1 = DISPLAY_8BPP_MODE;
598 par->bitblt_cntl = COLEXP_8BPP;
599 break;
600 case 15: /* 0rrrrrgg gggbbbbb */
601 case 16: /* rrrrrggg gggbbbbb */
602 par->pixelpipe_cfg1 = (var->green.length == 6) ?
603 DISPLAY_16BPP_MODE : DISPLAY_15BPP_MODE;
604 par->crtc[VGA_CRTC_OFFSET] = vxres >> 2;
605 par->ext_offset = vxres >> 10;
606 par->bitblt_cntl = COLEXP_16BPP;
607 base *= 2;
608 break;
609 case 24:
610 par->crtc[VGA_CRTC_OFFSET] = (vxres * 3) >> 3;
611 par->ext_offset = (vxres * 3) >> 11;
612 par->pixelpipe_cfg1 = DISPLAY_24BPP_MODE;
613 par->bitblt_cntl = COLEXP_24BPP;
614 base &= 0xFFFFFFFE; /* ...ignore the last bit. */
615 base *= 3;
616 break;
617 case 32:
618 par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
619 par->ext_offset = vxres >> 9;
620 par->pixelpipe_cfg1 = DISPLAY_32BPP_MODE;
621 par->bitblt_cntl = COLEXP_RESERVED; /* Unimplemented on i740 */
622 base *= 4;
623 break;
624 }
625
626 par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
627 par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
628 par->ext_start_addr =
629 ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
630 par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
631
632 par->pixelpipe_cfg0 = DAC_8_BIT;
633
634 par->pixelpipe_cfg2 = DISPLAY_GAMMA_ENABLE | OVERLAY_GAMMA_ENABLE;
635 par->io_cntl = EXTENDED_CRTC_CNTL;
636 par->address_mapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
637 par->display_cntl = HIRES_MODE;
638
639 /* Set the MCLK freq */
640 par->pll_cntl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
641
642 /* Calculate the extended CRTC regs */
643 par->ext_vert_total = (ytotal - 2) >> 8;
644 par->ext_vert_disp_end = (yres - 1) >> 8;
645 par->ext_vert_sync_start = (yres + lower) >> 8;
646 par->ext_vert_blank_start = (yres + lower) >> 8;
647 par->ext_horiz_total = ((xtotal >> 3) - 5) >> 8;
648 par->ext_horiz_blank = (((xres + right) >> 3) & 0x40) >> 6;
649
650 par->interlace_cntl = INTERLACE_DISABLE;
651
652 /* Set the overscan color to 0. (NOTE: This only affects >8bpp mode) */
653 par->atc[VGA_ATC_OVERSCAN] = 0;
654
655 /* Calculate VCLK that most closely matches the requested dot clock */
656 i740_calc_vclk((((u32)1e9) / var->pixclock) * (u32)(1e3), par);
657
658 /* Since we program the clocks ourselves, always use VCLK2. */
659 par->misc |= 0x0C;
660
661 /* Calculate the FIFO Watermark and Burst Length. */
662 par->lmi_fifo_watermark =
663 i740_calc_fifo(par, 1000000 / var->pixclock, bpp);
664
665 return 0;
666}
667
668static int i740fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
669{
670 switch (var->bits_per_pixel) {
671 case 8:
672 var->red.offset = var->green.offset = var->blue.offset = 0;
673 var->red.length = var->green.length = var->blue.length = 8;
674 break;
675 case 16:
676 switch (var->green.length) {
677 default:
678 case 5:
679 var->red.offset = 10;
680 var->green.offset = 5;
681 var->blue.offset = 0;
682 var->red.length = 5;
683 var->green.length = 5;
684 var->blue.length = 5;
685 break;
686 case 6:
687 var->red.offset = 11;
688 var->green.offset = 5;
689 var->blue.offset = 0;
690 var->red.length = var->blue.length = 5;
691 break;
692 }
693 break;
694 case 24:
695 var->red.offset = 16;
696 var->green.offset = 8;
697 var->blue.offset = 0;
698 var->red.length = var->green.length = var->blue.length = 8;
699 break;
700 case 32:
701 var->transp.offset = 24;
702 var->red.offset = 16;
703 var->green.offset = 8;
704 var->blue.offset = 0;
705 var->transp.length = 8;
706 var->red.length = var->green.length = var->blue.length = 8;
707 break;
708 default:
709 return -EINVAL;
710 }
711
712 if (var->xres > var->xres_virtual)
713 var->xres_virtual = var->xres;
714
715 if (var->yres > var->yres_virtual)
716 var->yres_virtual = var->yres;
717
718 if (info->monspecs.hfmax && info->monspecs.vfmax &&
719 info->monspecs.dclkmax && fb_validate_mode(var, info) < 0)
720 return -EINVAL;
721
722 return 0;
723}
724
725static void vga_protect(struct i740fb_par *par)
726{
727 /* disable the display */
728 i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0x20, 0x20);
729
730 i740inb(par, 0x3DA);
731 i740outb(par, VGA_ATT_W, 0x00); /* enable pallete access */
732}
733
734static void vga_unprotect(struct i740fb_par *par)
735{
736 /* reenable display */
737 i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0, 0x20);
738
739 i740inb(par, 0x3DA);
740 i740outb(par, VGA_ATT_W, 0x20); /* disable pallete access */
741}
742
743static int i740fb_set_par(struct fb_info *info)
744{
745 struct i740fb_par *par = info->par;
746 u32 itemp;
747 int i;
748
749 i = i740fb_decode_var(&info->var, par, info);
750 if (i)
751 return i;
752
753 memset(info->screen_base, 0, info->screen_size);
754
755 vga_protect(par);
756
757 i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
758
759 mdelay(1);
760
761 i740outreg(par, XRX, VCLK2_VCO_M, par->video_clk2_m);
762 i740outreg(par, XRX, VCLK2_VCO_N, par->video_clk2_n);
763 i740outreg(par, XRX, VCLK2_VCO_MN_MSBS, par->video_clk2_mn_msbs);
764 i740outreg(par, XRX, VCLK2_VCO_DIV_SEL, par->video_clk2_div_sel);
765
766 i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0,
767 par->pixelpipe_cfg0 & DAC_8_BIT, 0x80);
768
769 i740inb(par, 0x3DA);
770 i740outb(par, 0x3C0, 0x00);
771
772 /* update misc output register */
773 i740outb(par, VGA_MIS_W, par->misc | 0x01);
774
775 /* synchronous reset on */
776 i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x01);
777 /* write sequencer registers */
778 i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE,
779 par->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
780 for (i = 2; i < VGA_SEQ_C; i++)
781 i740outreg(par, VGA_SEQ_I, i, par->seq[i]);
782
783 /* synchronous reset off */
784 i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x03);
785
786 /* deprotect CRT registers 0-7 */
787 i740outreg(par, VGA_CRT_IC, VGA_CRTC_V_SYNC_END,
788 par->crtc[VGA_CRTC_V_SYNC_END]);
789
790 /* write CRT registers */
791 for (i = 0; i < VGA_CRT_C; i++)
792 i740outreg(par, VGA_CRT_IC, i, par->crtc[i]);
793
794 /* write graphics controller registers */
795 for (i = 0; i < VGA_GFX_C; i++)
796 i740outreg(par, VGA_GFX_I, i, par->gdc[i]);
797
798 /* write attribute controller registers */
799 for (i = 0; i < VGA_ATT_C; i++) {
800 i740inb(par, VGA_IS1_RC); /* reset flip-flop */
801 i740outb(par, VGA_ATT_IW, i);
802 i740outb(par, VGA_ATT_IW, par->atc[i]);
803 }
804
805 i740inb(par, VGA_IS1_RC);
806 i740outb(par, VGA_ATT_IW, 0x20);
807
808 i740outreg(par, VGA_CRT_IC, EXT_VERT_TOTAL, par->ext_vert_total);
809 i740outreg(par, VGA_CRT_IC, EXT_VERT_DISPLAY, par->ext_vert_disp_end);
810 i740outreg(par, VGA_CRT_IC, EXT_VERT_SYNC_START,
811 par->ext_vert_sync_start);
812 i740outreg(par, VGA_CRT_IC, EXT_VERT_BLANK_START,
813 par->ext_vert_blank_start);
814 i740outreg(par, VGA_CRT_IC, EXT_HORIZ_TOTAL, par->ext_horiz_total);
815 i740outreg(par, VGA_CRT_IC, EXT_HORIZ_BLANK, par->ext_horiz_blank);
816 i740outreg(par, VGA_CRT_IC, EXT_OFFSET, par->ext_offset);
817 i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, par->ext_start_addr_hi);
818 i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, par->ext_start_addr);
819
820 i740outreg_mask(par, VGA_CRT_IC, INTERLACE_CNTL,
821 par->interlace_cntl, INTERLACE_ENABLE);
822 i740outreg_mask(par, XRX, ADDRESS_MAPPING, par->address_mapping, 0x1F);
823 i740outreg_mask(par, XRX, BITBLT_CNTL, par->bitblt_cntl, COLEXP_MODE);
824 i740outreg_mask(par, XRX, DISPLAY_CNTL,
825 par->display_cntl, VGA_WRAP_MODE | GUI_MODE);
826 i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0, 0x9B);
827 i740outreg_mask(par, XRX, PIXPIPE_CONFIG_2, par->pixelpipe_cfg2, 0x0C);
828
829 i740outreg(par, XRX, PLL_CNTL, par->pll_cntl);
830
831 i740outreg_mask(par, XRX, PIXPIPE_CONFIG_1,
832 par->pixelpipe_cfg1, DISPLAY_COLOR_MODE);
833
834 itemp = readl(par->regs + FWATER_BLC);
835 itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
836 itemp |= par->lmi_fifo_watermark;
837 writel(itemp, par->regs + FWATER_BLC);
838
839 i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
840
841 i740outreg_mask(par, MRX, COL_KEY_CNTL_1, 0, BLANK_DISP_OVERLAY);
842 i740outreg_mask(par, XRX, IO_CTNL,
843 par->io_cntl, EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
844
845 if (par->pixelpipe_cfg1 != DISPLAY_8BPP_MODE) {
846 i740outb(par, VGA_PEL_MSK, 0xFF);
847 i740outb(par, VGA_PEL_IW, 0x00);
848 for (i = 0; i < 256; i++) {
849 itemp = (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2;
850 i740outb(par, VGA_PEL_D, itemp);
851 i740outb(par, VGA_PEL_D, itemp);
852 i740outb(par, VGA_PEL_D, itemp);
853 }
854 }
855
856 /* Wait for screen to stabilize. */
857 mdelay(50);
858 vga_unprotect(par);
859
860 info->fix.line_length =
861 info->var.xres_virtual * info->var.bits_per_pixel / 8;
862 if (info->var.bits_per_pixel == 8)
863 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
864 else
865 info->fix.visual = FB_VISUAL_TRUECOLOR;
866
867 return 0;
868}
869
870static int i740fb_setcolreg(unsigned regno, unsigned red, unsigned green,
871 unsigned blue, unsigned transp,
872 struct fb_info *info)
873{
874 u32 r, g, b;
875
876 dev_dbg(info->device, "setcolreg: regno: %i, red=%d, green=%d, blue=%d, transp=%d, bpp=%d\n",
877 regno, red, green, blue, transp, info->var.bits_per_pixel);
878
879 switch (info->fix.visual) {
880 case FB_VISUAL_PSEUDOCOLOR:
881 if (regno >= 256)
882 return -EINVAL;
883 i740outb(info->par, VGA_PEL_IW, regno);
884 i740outb(info->par, VGA_PEL_D, red >> 8);
885 i740outb(info->par, VGA_PEL_D, green >> 8);
886 i740outb(info->par, VGA_PEL_D, blue >> 8);
887 break;
888 case FB_VISUAL_TRUECOLOR:
889 if (regno >= 16)
890 return -EINVAL;
891 r = (red >> (16 - info->var.red.length))
892 << info->var.red.offset;
893 b = (blue >> (16 - info->var.blue.length))
894 << info->var.blue.offset;
895 g = (green >> (16 - info->var.green.length))
896 << info->var.green.offset;
897 ((u32 *) info->pseudo_palette)[regno] = r | g | b;
898 break;
899 default:
900 return -EINVAL;
901 }
902
903 return 0;
904}
905
906static int i740fb_pan_display(struct fb_var_screeninfo *var,
907 struct fb_info *info)
908{
909 struct i740fb_par *par = info->par;
910 u32 base = (var->yoffset * info->var.xres_virtual
911 + (var->xoffset & ~7)) >> 2;
912
913 dev_dbg(info->device, "pan_display: xoffset: %i yoffset: %i base: %i\n",
914 var->xoffset, var->yoffset, base);
915
916 switch (info->var.bits_per_pixel) {
917 case 8:
918 break;
919 case 15:
920 case 16:
921 base *= 2;
922 break;
923 case 24:
924 /*
925 * The last bit does not seem to have any effect on the start
926 * address register in 24bpp mode, so...
927 */
928 base &= 0xFFFFFFFE; /* ...ignore the last bit. */
929 base *= 3;
930 break;
931 case 32:
932 base *= 4;
933 break;
934 }
935
936 par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
937 par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
938 par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
939 par->ext_start_addr =
940 ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
941
942 i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_LO, base & 0x000000FF);
943 i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_HI,
944 (base & 0x0000FF00) >> 8);
945 i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI,
946 (base & 0x3FC00000) >> 22);
947 i740outreg(par, VGA_CRT_IC, EXT_START_ADDR,
948 ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE);
949
950 return 0;
951}
952
953static int i740fb_blank(int blank_mode, struct fb_info *info)
954{
955 struct i740fb_par *par = info->par;
956
957 unsigned char SEQ01;
958 int DPMSSyncSelect;
959
960 switch (blank_mode) {
961 case FB_BLANK_UNBLANK:
962 case FB_BLANK_NORMAL:
963 SEQ01 = 0x00;
964 DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
965 break;
966 case FB_BLANK_VSYNC_SUSPEND:
967 SEQ01 = 0x20;
968 DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
969 break;
970 case FB_BLANK_HSYNC_SUSPEND:
971 SEQ01 = 0x20;
972 DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
973 break;
974 case FB_BLANK_POWERDOWN:
975 SEQ01 = 0x20;
976 DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
977 break;
978 default:
979 return -EINVAL;
980 }
981 /* Turn the screen on/off */
982 i740outb(par, SRX, 0x01);
983 SEQ01 |= i740inb(par, SRX + 1) & ~0x20;
984 i740outb(par, SRX, 0x01);
985 i740outb(par, SRX + 1, SEQ01);
986
987 /* Set the DPMS mode */
988 i740outreg(par, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
989
990 /* Let fbcon do a soft blank for us */
991 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
992}
993
994static struct fb_ops i740fb_ops = {
995 .owner = THIS_MODULE,
996 .fb_open = i740fb_open,
997 .fb_release = i740fb_release,
998 .fb_check_var = i740fb_check_var,
999 .fb_set_par = i740fb_set_par,
1000 .fb_setcolreg = i740fb_setcolreg,
1001 .fb_blank = i740fb_blank,
1002 .fb_pan_display = i740fb_pan_display,
1003 .fb_fillrect = cfb_fillrect,
1004 .fb_copyarea = cfb_copyarea,
1005 .fb_imageblit = cfb_imageblit,
1006};
1007
1008/* ------------------------------------------------------------------------- */
1009
1010static int __devinit i740fb_probe(struct pci_dev *dev,
1011 const struct pci_device_id *ent)
1012{
1013 struct fb_info *info;
1014 struct i740fb_par *par;
1015 int ret, tmp;
1016 bool found = false;
1017 u8 *edid;
1018
1019 info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev));
1020 if (!info) {
1021 dev_err(&(dev->dev), "cannot allocate framebuffer\n");
1022 return -ENOMEM;
1023 }
1024
1025 par = info->par;
1026 mutex_init(&par->open_lock);
1027
1028 info->var.activate = FB_ACTIVATE_NOW;
1029 info->var.bits_per_pixel = 8;
1030 info->fbops = &i740fb_ops;
1031 info->pseudo_palette = par->pseudo_palette;
1032
1033 ret = pci_enable_device(dev);
1034 if (ret) {
1035 dev_err(info->device, "cannot enable PCI device\n");
1036 goto err_enable_device;
1037 }
1038
1039 ret = pci_request_regions(dev, info->fix.id);
1040 if (ret) {
1041 dev_err(info->device, "error requesting regions\n");
1042 goto err_request_regions;
1043 }
1044
1045 info->screen_base = pci_ioremap_bar(dev, 0);
1046 if (!info->screen_base) {
1047 dev_err(info->device, "error remapping base\n");
1048 ret = -ENOMEM;
1049 goto err_ioremap_1;
1050 }
1051
1052 par->regs = pci_ioremap_bar(dev, 1);
1053 if (!par->regs) {
1054 dev_err(info->device, "error remapping MMIO\n");
1055 ret = -ENOMEM;
1056 goto err_ioremap_2;
1057 }
1058
1059 /* detect memory size */
1060 if ((i740inreg(par, XRX, DRAM_ROW_TYPE) & DRAM_ROW_1)
1061 == DRAM_ROW_1_SDRAM)
1062 i740outb(par, XRX, DRAM_ROW_BNDRY_1);
1063 else
1064 i740outb(par, XRX, DRAM_ROW_BNDRY_0);
1065 info->screen_size = i740inb(par, XRX + 1) * 1024 * 1024;
1066 /* detect memory type */
1067 tmp = i740inreg(par, XRX, DRAM_ROW_CNTL_LO);
1068 par->has_sgram = !((tmp & DRAM_RAS_TIMING) ||
1069 (tmp & DRAM_RAS_PRECHARGE));
1070
1071 printk(KERN_INFO "fb%d: Intel740 on %s, %ld KB %s\n", info->node,
1072 pci_name(dev), info->screen_size >> 10,
1073 par->has_sgram ? "SGRAM" : "SDRAM");
1074
1075 info->fix = i740fb_fix;
1076 info->fix.mmio_start = pci_resource_start(dev, 1);
1077 info->fix.mmio_len = pci_resource_len(dev, 1);
1078 info->fix.smem_start = pci_resource_start(dev, 0);
1079 info->fix.smem_len = info->screen_size;
1080 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1081
1082 if (i740fb_setup_ddc_bus(info) == 0) {
1083 par->ddc_registered = true;
1084 edid = fb_ddc_read(&par->ddc_adapter);
1085 if (edid) {
1086 fb_edid_to_monspecs(edid, &info->monspecs);
1087 kfree(edid);
1088 if (!info->monspecs.modedb)
1089 dev_err(info->device,
1090 "error getting mode database\n");
1091 else {
1092 const struct fb_videomode *m;
1093
1094 fb_videomode_to_modelist(
1095 info->monspecs.modedb,
1096 info->monspecs.modedb_len,
1097 &info->modelist);
1098 m = fb_find_best_display(&info->monspecs,
1099 &info->modelist);
1100 if (m) {
1101 fb_videomode_to_var(&info->var, m);
1102 /* fill all other info->var's fields */
1103 if (!i740fb_check_var(&info->var, info))
1104 found = true;
1105 }
1106 }
1107 }
1108 }
1109
1110 if (!mode_option && !found)
1111 mode_option = "640x480-8@60";
1112
1113 if (mode_option) {
1114 ret = fb_find_mode(&info->var, info, mode_option,
1115 info->monspecs.modedb,
1116 info->monspecs.modedb_len,
1117 NULL, info->var.bits_per_pixel);
1118 if (!ret || ret == 4) {
1119 dev_err(info->device, "mode %s not found\n",
1120 mode_option);
1121 ret = -EINVAL;
1122 }
1123 }
1124
1125 fb_destroy_modedb(info->monspecs.modedb);
1126 info->monspecs.modedb = NULL;
1127
1128 /* maximize virtual vertical size for fast scrolling */
1129 info->var.yres_virtual = info->fix.smem_len * 8 /
1130 (info->var.bits_per_pixel * info->var.xres_virtual);
1131
1132 if (ret == -EINVAL)
1133 goto err_find_mode;
1134
1135 ret = fb_alloc_cmap(&info->cmap, 256, 0);
1136 if (ret) {
1137 dev_err(info->device, "cannot allocate colormap\n");
1138 goto err_alloc_cmap;
1139 }
1140
1141 ret = register_framebuffer(info);
1142 if (ret) {
1143 dev_err(info->device, "error registering framebuffer\n");
1144 goto err_reg_framebuffer;
1145 }
1146
1147 printk(KERN_INFO "fb%d: %s frame buffer device\n",
1148 info->node, info->fix.id);
1149 pci_set_drvdata(dev, info);
1150#ifdef CONFIG_MTRR
1151 if (mtrr) {
1152 par->mtrr_reg = -1;
1153 par->mtrr_reg = mtrr_add(info->fix.smem_start,
1154 info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
1155 }
1156#endif
1157 return 0;
1158
1159err_reg_framebuffer:
1160 fb_dealloc_cmap(&info->cmap);
1161err_alloc_cmap:
1162err_find_mode:
1163 if (par->ddc_registered)
1164 i2c_del_adapter(&par->ddc_adapter);
1165 pci_iounmap(dev, par->regs);
1166err_ioremap_2:
1167 pci_iounmap(dev, info->screen_base);
1168err_ioremap_1:
1169 pci_release_regions(dev);
1170err_request_regions:
1171/* pci_disable_device(dev); */
1172err_enable_device:
1173 framebuffer_release(info);
1174 return ret;
1175}
1176
1177static void __devexit i740fb_remove(struct pci_dev *dev)
1178{
1179 struct fb_info *info = pci_get_drvdata(dev);
1180
1181 if (info) {
1182 struct i740fb_par *par = info->par;
1183
1184#ifdef CONFIG_MTRR
1185 if (par->mtrr_reg >= 0) {
1186 mtrr_del(par->mtrr_reg, 0, 0);
1187 par->mtrr_reg = -1;
1188 }
1189#endif
1190 unregister_framebuffer(info);
1191 fb_dealloc_cmap(&info->cmap);
1192 if (par->ddc_registered)
1193 i2c_del_adapter(&par->ddc_adapter);
1194 pci_iounmap(dev, par->regs);
1195 pci_iounmap(dev, info->screen_base);
1196 pci_release_regions(dev);
1197/* pci_disable_device(dev); */
1198 pci_set_drvdata(dev, NULL);
1199 framebuffer_release(info);
1200 }
1201}
1202
1203#ifdef CONFIG_PM
1204static int i740fb_suspend(struct pci_dev *dev, pm_message_t state)
1205{
1206 struct fb_info *info = pci_get_drvdata(dev);
1207 struct i740fb_par *par = info->par;
1208
1209 /* don't disable console during hibernation and wakeup from it */
1210 if (state.event == PM_EVENT_FREEZE || state.event == PM_EVENT_PRETHAW)
1211 return 0;
1212
1213 console_lock();
1214 mutex_lock(&(par->open_lock));
1215
1216 /* do nothing if framebuffer is not active */
1217 if (par->ref_count == 0) {
1218 mutex_unlock(&(par->open_lock));
1219 console_unlock();
1220 return 0;
1221 }
1222
1223 fb_set_suspend(info, 1);
1224
1225 pci_save_state(dev);
1226 pci_disable_device(dev);
1227 pci_set_power_state(dev, pci_choose_state(dev, state));
1228
1229 mutex_unlock(&(par->open_lock));
1230 console_unlock();
1231
1232 return 0;
1233}
1234
1235static int i740fb_resume(struct pci_dev *dev)
1236{
1237 struct fb_info *info = pci_get_drvdata(dev);
1238 struct i740fb_par *par = info->par;
1239
1240 console_lock();
1241 mutex_lock(&(par->open_lock));
1242
1243 if (par->ref_count == 0)
1244 goto fail;
1245
1246 pci_set_power_state(dev, PCI_D0);
1247 pci_restore_state(dev);
1248 if (pci_enable_device(dev))
1249 goto fail;
1250
1251 i740fb_set_par(info);
1252 fb_set_suspend(info, 0);
1253
1254fail:
1255 mutex_unlock(&(par->open_lock));
1256 console_unlock();
1257 return 0;
1258}
1259#else
1260#define i740fb_suspend NULL
1261#define i740fb_resume NULL
1262#endif /* CONFIG_PM */
1263
1264#define I740_ID_PCI 0x00d1
1265#define I740_ID_AGP 0x7800
1266
1267static DEFINE_PCI_DEVICE_TABLE(i740fb_id_table) = {
1268 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_PCI) },
1269 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_AGP) },
1270 { 0 }
1271};
1272MODULE_DEVICE_TABLE(pci, i740fb_id_table);
1273
1274static struct pci_driver i740fb_driver = {
1275 .name = "i740fb",
1276 .id_table = i740fb_id_table,
1277 .probe = i740fb_probe,
1278 .remove = __devexit_p(i740fb_remove),
1279 .suspend = i740fb_suspend,
1280 .resume = i740fb_resume,
1281};
1282
1283#ifndef MODULE
1284static int __init i740fb_setup(char *options)
1285{
1286 char *opt;
1287
1288 if (!options || !*options)
1289 return 0;
1290
1291 while ((opt = strsep(&options, ",")) != NULL) {
1292 if (!*opt)
1293 continue;
1294#ifdef CONFIG_MTRR
1295 else if (!strncmp(opt, "mtrr:", 5))
1296 mtrr = simple_strtoul(opt + 5, NULL, 0);
1297#endif
1298 else
1299 mode_option = opt;
1300 }
1301
1302 return 0;
1303}
1304#endif
1305
1306int __init i740fb_init(void)
1307{
1308#ifndef MODULE
1309 char *option = NULL;
1310
1311 if (fb_get_options("i740fb", &option))
1312 return -ENODEV;
1313 i740fb_setup(option);
1314#endif
1315
1316 return pci_register_driver(&i740fb_driver);
1317}
1318
1319static void __exit i740fb_exit(void)
1320{
1321 pci_unregister_driver(&i740fb_driver);
1322}
1323
1324module_init(i740fb_init);
1325module_exit(i740fb_exit);
1326
1327MODULE_AUTHOR("(c) 2011 Ondrej Zary <linux@rainbow-software.org>");
1328MODULE_LICENSE("GPL");
1329MODULE_DESCRIPTION("fbdev driver for Intel740");
1330
1331module_param(mode_option, charp, 0444);
1332MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
1333
1334#ifdef CONFIG_MTRR
1335module_param(mtrr, int, 0444);
1336MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
1337#endif
diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/msm/mddi_client_nt35399.c
index f239f4a25e01..7fcd67e132bf 100644
--- a/drivers/video/msm/mddi_client_nt35399.c
+++ b/drivers/video/msm/mddi_client_nt35399.c
@@ -155,14 +155,10 @@ static int setup_vsync(struct panel_info *panel, int init)
155 ret = 0; 155 ret = 0;
156 goto uninit; 156 goto uninit;
157 } 157 }
158 ret = gpio_request(gpio, "vsync"); 158 ret = gpio_request_one(gpio, GPIOF_IN, "vsync");
159 if (ret) 159 if (ret)
160 goto err_request_gpio_failed; 160 goto err_request_gpio_failed;
161 161
162 ret = gpio_direction_input(gpio);
163 if (ret)
164 goto err_gpio_direction_input_failed;
165
166 ret = irq = gpio_to_irq(gpio); 162 ret = irq = gpio_to_irq(gpio);
167 if (ret < 0) 163 if (ret < 0)
168 goto err_get_irq_num_failed; 164 goto err_get_irq_num_failed;
@@ -180,7 +176,6 @@ uninit:
180 free_irq(gpio_to_irq(gpio), panel->client_data); 176 free_irq(gpio_to_irq(gpio), panel->client_data);
181err_request_irq_failed: 177err_request_irq_failed:
182err_get_irq_num_failed: 178err_get_irq_num_failed:
183err_gpio_direction_input_failed:
184 gpio_free(gpio); 179 gpio_free(gpio);
185err_request_gpio_failed: 180err_request_gpio_failed:
186 return ret; 181 return ret;
diff --git a/drivers/video/msm/mddi_client_toshiba.c b/drivers/video/msm/mddi_client_toshiba.c
index f9bc932ac46b..053eb6877330 100644
--- a/drivers/video/msm/mddi_client_toshiba.c
+++ b/drivers/video/msm/mddi_client_toshiba.c
@@ -186,14 +186,10 @@ static int setup_vsync(struct panel_info *panel,
186 ret = 0; 186 ret = 0;
187 goto uninit; 187 goto uninit;
188 } 188 }
189 ret = gpio_request(gpio, "vsync"); 189 ret = gpio_request_one(gpio, GPIOF_IN, "vsync");
190 if (ret) 190 if (ret)
191 goto err_request_gpio_failed; 191 goto err_request_gpio_failed;
192 192
193 ret = gpio_direction_input(gpio);
194 if (ret)
195 goto err_gpio_direction_input_failed;
196
197 ret = irq = gpio_to_irq(gpio); 193 ret = irq = gpio_to_irq(gpio);
198 if (ret < 0) 194 if (ret < 0)
199 goto err_get_irq_num_failed; 195 goto err_get_irq_num_failed;
@@ -210,7 +206,6 @@ uninit:
210 free_irq(gpio_to_irq(gpio), panel); 206 free_irq(gpio_to_irq(gpio), panel);
211err_request_irq_failed: 207err_request_irq_failed:
212err_get_irq_num_failed: 208err_get_irq_num_failed:
213err_gpio_direction_input_failed:
214 gpio_free(gpio); 209 gpio_free(gpio);
215err_request_gpio_failed: 210err_request_gpio_failed:
216 return ret; 211 return ret;
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index 84ff23208c25..1e7536d9a8fc 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -1,11 +1,10 @@
1config FB_OMAP 1config FB_OMAP
2 tristate "OMAP frame buffer support (EXPERIMENTAL)" 2 tristate "OMAP frame buffer support (EXPERIMENTAL)"
3 depends on FB && (OMAP2_DSS = "n") 3 depends on FB
4 depends on ARCH_OMAP1 || ARCH_OMAP2 || ARCH_OMAP3 4 depends on ARCH_OMAP1
5 select FB_CFB_FILLRECT 5 select FB_CFB_FILLRECT
6 select FB_CFB_COPYAREA 6 select FB_CFB_COPYAREA
7 select FB_CFB_IMAGEBLIT 7 select FB_CFB_IMAGEBLIT
8 select TWL4030_CORE if MACH_OMAP_2430SDP
9 help 8 help
10 Frame buffer driver for OMAP based boards. 9 Frame buffer driver for OMAP based boards.
11 10
@@ -23,13 +22,6 @@ config FB_OMAP_LCDC_HWA742
23 Say Y here if you want to have support for the external 22 Say Y here if you want to have support for the external
24 Epson HWA742 LCD controller. 23 Epson HWA742 LCD controller.
25 24
26config FB_OMAP_LCDC_BLIZZARD
27 bool "Epson Blizzard LCD controller support"
28 depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
29 help
30 Say Y here if you want to have support for the external
31 Epson Blizzard LCD controller.
32
33config FB_OMAP_MANUAL_UPDATE 25config FB_OMAP_MANUAL_UPDATE
34 bool "Default to manual update mode" 26 bool "Default to manual update mode"
35 depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL 27 depends on FB_OMAP && FB_OMAP_LCDC_EXTERNAL
@@ -49,7 +41,7 @@ config FB_OMAP_LCD_MIPID
49 41
50config FB_OMAP_BOOTLOADER_INIT 42config FB_OMAP_BOOTLOADER_INIT
51 bool "Check bootloader initialization" 43 bool "Check bootloader initialization"
52 depends on FB_OMAP || FB_OMAP2 44 depends on FB_OMAP
53 help 45 help
54 Say Y here if you want to enable checking if the bootloader has 46 Say Y here if you want to enable checking if the bootloader has
55 already initialized the display controller. In this case the 47 already initialized the display controller. In this case the
@@ -68,7 +60,7 @@ config FB_OMAP_CONSISTENT_DMA_SIZE
68 60
69config FB_OMAP_DMA_TUNE 61config FB_OMAP_DMA_TUNE
70 bool "Set DMA SDRAM access priority high" 62 bool "Set DMA SDRAM access priority high"
71 depends on FB_OMAP && ARCH_OMAP1 63 depends on FB_OMAP
72 help 64 help
73 On systems in which video memory is in system memory 65 On systems in which video memory is in system memory
74 (SDRAM) this will speed up graphics DMA operations. 66 (SDRAM) this will speed up graphics DMA operations.
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile
index ef78550917ff..1927faffb5bc 100644
--- a/drivers/video/omap/Makefile
+++ b/drivers/video/omap/Makefile
@@ -1,20 +1,14 @@
1# 1#
2# Makefile for the new OMAP framebuffer device driver 2# Makefile for the OMAP1 framebuffer device driver
3# 3#
4 4
5obj-$(CONFIG_FB_OMAP) += omapfb.o 5obj-$(CONFIG_FB_OMAP) += omapfb.o
6 6
7objs-yy := omapfb_main.o 7objs-yy := omapfb_main.o lcdc.o
8 8
9objs-y$(CONFIG_ARCH_OMAP1) += lcdc.o 9objs-y$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o
10objs-y$(CONFIG_ARCH_OMAP2) += dispc.o
11objs-y$(CONFIG_ARCH_OMAP3) += dispc.o
12
13objs-$(CONFIG_ARCH_OMAP1)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o
14objs-$(CONFIG_ARCH_OMAP2)$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += rfbi.o
15 10
16objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o 11objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o
17objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o
18 12
19objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o 13objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o
20objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o 14objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o
diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c
deleted file mode 100644
index c0504a8a5079..000000000000
--- a/drivers/video/omap/blizzard.c
+++ /dev/null
@@ -1,1648 +0,0 @@
1/*
2 * Epson Blizzard LCD controller driver
3 *
4 * Copyright (C) 2004-2005 Nokia Corporation
5 * Authors: Juha Yrjola <juha.yrjola@nokia.com>
6 * Imre Deak <imre.deak@nokia.com>
7 * YUV support: Jussi Laako <jussi.laako@nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23#include <linux/module.h>
24#include <linux/mm.h>
25#include <linux/fb.h>
26#include <linux/delay.h>
27#include <linux/clk.h>
28
29#include <plat/dma.h>
30#include <plat/blizzard.h>
31
32#include "omapfb.h"
33#include "dispc.h"
34
35#define MODULE_NAME "blizzard"
36
37#define BLIZZARD_REV_CODE 0x00
38#define BLIZZARD_CONFIG 0x02
39#define BLIZZARD_PLL_DIV 0x04
40#define BLIZZARD_PLL_LOCK_RANGE 0x06
41#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08
42#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a
43#define BLIZZARD_PLL_MODE 0x0c
44#define BLIZZARD_CLK_SRC 0x0e
45#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
46#define BLIZZARD_MEM_BANK0_STATUS 0x14
47#define BLIZZARD_PANEL_CONFIGURATION 0x28
48#define BLIZZARD_HDISP 0x2a
49#define BLIZZARD_HNDP 0x2c
50#define BLIZZARD_VDISP0 0x2e
51#define BLIZZARD_VDISP1 0x30
52#define BLIZZARD_VNDP 0x32
53#define BLIZZARD_HSW 0x34
54#define BLIZZARD_VSW 0x38
55#define BLIZZARD_DISPLAY_MODE 0x68
56#define BLIZZARD_INPUT_WIN_X_START_0 0x6c
57#define BLIZZARD_DATA_SOURCE_SELECT 0x8e
58#define BLIZZARD_DISP_MEM_DATA_PORT 0x90
59#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92
60#define BLIZZARD_POWER_SAVE 0xE6
61#define BLIZZARD_NDISP_CTRL_STATUS 0xE8
62
63/* Data source select */
64/* For S1D13745 */
65#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00
66#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01
67#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04
68#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05
69/* For S1D13744 */
70#define BLIZZARD_SRC_WRITE_LCD 0x00
71#define BLIZZARD_SRC_BLT_LCD 0x06
72
73#define BLIZZARD_COLOR_RGB565 0x01
74#define BLIZZARD_COLOR_YUV420 0x09
75
76#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
77#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
78
79#define BLIZZARD_AUTO_UPDATE_TIME (HZ / 20)
80
81/* Reserve 4 request slots for requests in irq context */
82#define REQ_POOL_SIZE 24
83#define IRQ_REQ_POOL_SIZE 4
84
85#define REQ_FROM_IRQ_POOL 0x01
86
87#define REQ_COMPLETE 0
88#define REQ_PENDING 1
89
90struct blizzard_reg_list {
91 int start;
92 int end;
93};
94
95/* These need to be saved / restored separately from the rest. */
96static const struct blizzard_reg_list blizzard_pll_regs[] = {
97 {
98 .start = 0x04, /* Don't save PLL ctrl (0x0C) */
99 .end = 0x0a,
100 },
101 {
102 .start = 0x0e, /* Clock configuration */
103 .end = 0x0e,
104 },
105};
106
107static const struct blizzard_reg_list blizzard_gen_regs[] = {
108 {
109 .start = 0x18, /* SDRAM control */
110 .end = 0x20,
111 },
112 {
113 .start = 0x28, /* LCD Panel configuration */
114 .end = 0x5a, /* HSSI interface, TV configuration */
115 },
116};
117
118static u8 blizzard_reg_cache[0x5a / 2];
119
120struct update_param {
121 int plane;
122 int x, y, width, height;
123 int out_x, out_y;
124 int out_width, out_height;
125 int color_mode;
126 int bpp;
127 int flags;
128};
129
130struct blizzard_request {
131 struct list_head entry;
132 unsigned int flags;
133
134 int (*handler)(struct blizzard_request *req);
135 void (*complete)(void *data);
136 void *complete_data;
137
138 union {
139 struct update_param update;
140 struct completion *sync;
141 } par;
142};
143
144struct plane_info {
145 unsigned long offset;
146 int pos_x, pos_y;
147 int width, height;
148 int out_width, out_height;
149 int scr_width;
150 int color_mode;
151 int bpp;
152};
153
154struct blizzard_struct {
155 enum omapfb_update_mode update_mode;
156 enum omapfb_update_mode update_mode_before_suspend;
157
158 struct timer_list auto_update_timer;
159 int stop_auto_update;
160 struct omapfb_update_window auto_update_window;
161 int enabled_planes;
162 int vid_nonstd_color;
163 int vid_scaled;
164 int last_color_mode;
165 int zoom_on;
166 int zoom_area_gx1;
167 int zoom_area_gx2;
168 int zoom_area_gy1;
169 int zoom_area_gy2;
170 int screen_width;
171 int screen_height;
172 unsigned te_connected:1;
173 unsigned vsync_only:1;
174
175 struct plane_info plane[OMAPFB_PLANE_NUM];
176
177 struct blizzard_request req_pool[REQ_POOL_SIZE];
178 struct list_head pending_req_list;
179 struct list_head free_req_list;
180 struct semaphore req_sema;
181 spinlock_t req_lock;
182
183 unsigned long sys_ck_rate;
184 struct extif_timings reg_timings, lut_timings;
185
186 u32 max_transmit_size;
187 u32 extif_clk_period;
188 int extif_clk_div;
189 unsigned long pix_tx_time;
190 unsigned long line_upd_time;
191
192 struct omapfb_device *fbdev;
193 struct lcd_ctrl_extif *extif;
194 const struct lcd_ctrl *int_ctrl;
195
196 void (*power_up)(struct device *dev);
197 void (*power_down)(struct device *dev);
198
199 int version;
200} blizzard;
201
202struct lcd_ctrl blizzard_ctrl;
203
204static u8 blizzard_read_reg(u8 reg)
205{
206 u8 data;
207
208 blizzard.extif->set_bits_per_cycle(8);
209 blizzard.extif->write_command(&reg, 1);
210 blizzard.extif->read_data(&data, 1);
211
212 return data;
213}
214
215static void blizzard_write_reg(u8 reg, u8 val)
216{
217 blizzard.extif->set_bits_per_cycle(8);
218 blizzard.extif->write_command(&reg, 1);
219 blizzard.extif->write_data(&val, 1);
220}
221
222static void blizzard_restart_sdram(void)
223{
224 unsigned long tmo;
225
226 blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);
227 udelay(50);
228 blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 1);
229 tmo = jiffies + msecs_to_jiffies(200);
230 while (!(blizzard_read_reg(BLIZZARD_MEM_BANK0_STATUS) & 0x01)) {
231 if (time_after(jiffies, tmo)) {
232 dev_err(blizzard.fbdev->dev,
233 "s1d1374x: SDRAM not ready\n");
234 break;
235 }
236 msleep(1);
237 }
238}
239
240static void blizzard_stop_sdram(void)
241{
242 blizzard_write_reg(BLIZZARD_MEM_BANK0_ACTIVATE, 0);
243}
244
245/* Wait until the last window was completely written into the controllers
246 * SDRAM and we can start transferring the next window.
247 */
248static void blizzard_wait_line_buffer(void)
249{
250 unsigned long tmo = jiffies + msecs_to_jiffies(30);
251
252 while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 7)) {
253 if (time_after(jiffies, tmo)) {
254 if (printk_ratelimit())
255 dev_err(blizzard.fbdev->dev,
256 "s1d1374x: line buffer not ready\n");
257 break;
258 }
259 }
260}
261
262/* Wait until the YYC color space converter is idle. */
263static void blizzard_wait_yyc(void)
264{
265 unsigned long tmo = jiffies + msecs_to_jiffies(30);
266
267 while (blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS) & (1 << 4)) {
268 if (time_after(jiffies, tmo)) {
269 if (printk_ratelimit())
270 dev_err(blizzard.fbdev->dev,
271 "s1d1374x: YYC not ready\n");
272 break;
273 }
274 }
275}
276
277static void disable_overlay(void)
278{
279 blizzard_write_reg(BLIZZARD_DATA_SOURCE_SELECT,
280 BLIZZARD_SRC_DISABLE_OVERLAY);
281}
282
283static void set_window_regs(int x_start, int y_start, int x_end, int y_end,
284 int x_out_start, int y_out_start,
285 int x_out_end, int y_out_end, int color_mode,
286 int zoom_off, int flags)
287{
288 u8 tmp[18];
289 u8 cmd;
290
291 x_end--;
292 y_end--;
293 tmp[0] = x_start;
294 tmp[1] = x_start >> 8;
295 tmp[2] = y_start;
296 tmp[3] = y_start >> 8;
297 tmp[4] = x_end;
298 tmp[5] = x_end >> 8;
299 tmp[6] = y_end;
300 tmp[7] = y_end >> 8;
301
302 x_out_end--;
303 y_out_end--;
304 tmp[8] = x_out_start;
305 tmp[9] = x_out_start >> 8;
306 tmp[10] = y_out_start;
307 tmp[11] = y_out_start >> 8;
308 tmp[12] = x_out_end;
309 tmp[13] = x_out_end >> 8;
310 tmp[14] = y_out_end;
311 tmp[15] = y_out_end >> 8;
312
313 tmp[16] = color_mode;
314 if (zoom_off && blizzard.version == BLIZZARD_VERSION_S1D13745)
315 tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
316 else if (flags & OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY)
317 tmp[17] = BLIZZARD_SRC_WRITE_OVERLAY_ENABLE;
318 else
319 tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ?
320 BLIZZARD_SRC_WRITE_LCD :
321 BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
322
323 blizzard.extif->set_bits_per_cycle(8);
324 cmd = BLIZZARD_INPUT_WIN_X_START_0;
325 blizzard.extif->write_command(&cmd, 1);
326 blizzard.extif->write_data(tmp, 18);
327}
328
329static void enable_tearsync(int y, int width, int height, int screen_height,
330 int out_height, int force_vsync)
331{
332 u8 b;
333
334 b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
335 b |= 1 << 3;
336 blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
337
338 if (likely(blizzard.vsync_only || force_vsync)) {
339 blizzard.extif->enable_tearsync(1, 0);
340 return;
341 }
342
343 if (width * blizzard.pix_tx_time < blizzard.line_upd_time) {
344 blizzard.extif->enable_tearsync(1, 0);
345 return;
346 }
347
348 if ((width * blizzard.pix_tx_time / 1000) * height <
349 (y + out_height) * (blizzard.line_upd_time / 1000)) {
350 blizzard.extif->enable_tearsync(1, 0);
351 return;
352 }
353
354 blizzard.extif->enable_tearsync(1, y + 1);
355}
356
357static void disable_tearsync(void)
358{
359 u8 b;
360
361 blizzard.extif->enable_tearsync(0, 0);
362 b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
363 b &= ~(1 << 3);
364 blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
365 b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
366}
367
368static inline void set_extif_timings(const struct extif_timings *t);
369
370static inline struct blizzard_request *alloc_req(void)
371{
372 unsigned long flags;
373 struct blizzard_request *req;
374 int req_flags = 0;
375
376 if (!in_interrupt())
377 down(&blizzard.req_sema);
378 else
379 req_flags = REQ_FROM_IRQ_POOL;
380
381 spin_lock_irqsave(&blizzard.req_lock, flags);
382 BUG_ON(list_empty(&blizzard.free_req_list));
383 req = list_entry(blizzard.free_req_list.next,
384 struct blizzard_request, entry);
385 list_del(&req->entry);
386 spin_unlock_irqrestore(&blizzard.req_lock, flags);
387
388 INIT_LIST_HEAD(&req->entry);
389 req->flags = req_flags;
390
391 return req;
392}
393
394static inline void free_req(struct blizzard_request *req)
395{
396 unsigned long flags;
397
398 spin_lock_irqsave(&blizzard.req_lock, flags);
399
400 list_move(&req->entry, &blizzard.free_req_list);
401 if (!(req->flags & REQ_FROM_IRQ_POOL))
402 up(&blizzard.req_sema);
403
404 spin_unlock_irqrestore(&blizzard.req_lock, flags);
405}
406
407static void process_pending_requests(void)
408{
409 unsigned long flags;
410
411 spin_lock_irqsave(&blizzard.req_lock, flags);
412
413 while (!list_empty(&blizzard.pending_req_list)) {
414 struct blizzard_request *req;
415 void (*complete)(void *);
416 void *complete_data;
417
418 req = list_entry(blizzard.pending_req_list.next,
419 struct blizzard_request, entry);
420 spin_unlock_irqrestore(&blizzard.req_lock, flags);
421
422 if (req->handler(req) == REQ_PENDING)
423 return;
424
425 complete = req->complete;
426 complete_data = req->complete_data;
427 free_req(req);
428
429 if (complete)
430 complete(complete_data);
431
432 spin_lock_irqsave(&blizzard.req_lock, flags);
433 }
434
435 spin_unlock_irqrestore(&blizzard.req_lock, flags);
436}
437
438static void submit_req_list(struct list_head *head)
439{
440 unsigned long flags;
441 int process = 1;
442
443 spin_lock_irqsave(&blizzard.req_lock, flags);
444 if (likely(!list_empty(&blizzard.pending_req_list)))
445 process = 0;
446 list_splice_init(head, blizzard.pending_req_list.prev);
447 spin_unlock_irqrestore(&blizzard.req_lock, flags);
448
449 if (process)
450 process_pending_requests();
451}
452
453static void request_complete(void *data)
454{
455 struct blizzard_request *req = (struct blizzard_request *)data;
456 void (*complete)(void *);
457 void *complete_data;
458
459 complete = req->complete;
460 complete_data = req->complete_data;
461
462 free_req(req);
463
464 if (complete)
465 complete(complete_data);
466
467 process_pending_requests();
468}
469
470
471static int do_full_screen_update(struct blizzard_request *req)
472{
473 int i;
474 int flags;
475
476 for (i = 0; i < 3; i++) {
477 struct plane_info *p = &blizzard.plane[i];
478 if (!(blizzard.enabled_planes & (1 << i))) {
479 blizzard.int_ctrl->enable_plane(i, 0);
480 continue;
481 }
482 dev_dbg(blizzard.fbdev->dev, "pw %d ph %d\n",
483 p->width, p->height);
484 blizzard.int_ctrl->setup_plane(i,
485 OMAPFB_CHANNEL_OUT_LCD, p->offset,
486 p->scr_width, p->pos_x, p->pos_y,
487 p->width, p->height,
488 p->color_mode);
489 blizzard.int_ctrl->enable_plane(i, 1);
490 }
491
492 dev_dbg(blizzard.fbdev->dev, "sw %d sh %d\n",
493 blizzard.screen_width, blizzard.screen_height);
494 blizzard_wait_line_buffer();
495 flags = req->par.update.flags;
496 if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
497 enable_tearsync(0, blizzard.screen_width,
498 blizzard.screen_height,
499 blizzard.screen_height,
500 blizzard.screen_height,
501 flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
502 else
503 disable_tearsync();
504
505 set_window_regs(0, 0, blizzard.screen_width, blizzard.screen_height,
506 0, 0, blizzard.screen_width, blizzard.screen_height,
507 BLIZZARD_COLOR_RGB565, blizzard.zoom_on, flags);
508 blizzard.zoom_on = 0;
509
510 blizzard.extif->set_bits_per_cycle(16);
511 /* set_window_regs has left the register index at the right
512 * place, so no need to set it here.
513 */
514 blizzard.extif->transfer_area(blizzard.screen_width,
515 blizzard.screen_height,
516 request_complete, req);
517 return REQ_PENDING;
518}
519
520static int check_1d_intersect(int a1, int a2, int b1, int b2)
521{
522 if (a2 <= b1 || b2 <= a1)
523 return 0;
524 return 1;
525}
526
527/* Setup all planes with an overlapping area with the update window. */
528static int do_partial_update(struct blizzard_request *req, int plane,
529 int x, int y, int w, int h,
530 int x_out, int y_out, int w_out, int h_out,
531 int wnd_color_mode, int bpp)
532{
533 int i;
534 int gx1, gy1, gx2, gy2;
535 int gx1_out, gy1_out, gx2_out, gy2_out;
536 int color_mode;
537 int flags;
538 int zoom_off;
539 int have_zoom_for_this_update = 0;
540
541 /* Global coordinates, relative to pixel 0,0 of the LCD */
542 gx1 = x + blizzard.plane[plane].pos_x;
543 gy1 = y + blizzard.plane[plane].pos_y;
544 gx2 = gx1 + w;
545 gy2 = gy1 + h;
546
547 flags = req->par.update.flags;
548 if (flags & OMAPFB_FORMAT_FLAG_DOUBLE) {
549 gx1_out = gx1;
550 gy1_out = gy1;
551 gx2_out = gx1 + w * 2;
552 gy2_out = gy1 + h * 2;
553 } else {
554 gx1_out = x_out + blizzard.plane[plane].pos_x;
555 gy1_out = y_out + blizzard.plane[plane].pos_y;
556 gx2_out = gx1_out + w_out;
557 gy2_out = gy1_out + h_out;
558 }
559
560 for (i = 0; i < OMAPFB_PLANE_NUM; i++) {
561 struct plane_info *p = &blizzard.plane[i];
562 int px1, py1;
563 int px2, py2;
564 int pw, ph;
565 int pposx, pposy;
566 unsigned long offset;
567
568 if (!(blizzard.enabled_planes & (1 << i)) ||
569 (wnd_color_mode && i != plane)) {
570 blizzard.int_ctrl->enable_plane(i, 0);
571 continue;
572 }
573 /* Plane coordinates */
574 if (i == plane) {
575 /* Plane in which we are doing the update.
576 * Local coordinates are the one in the update
577 * request.
578 */
579 px1 = x;
580 py1 = y;
581 px2 = x + w;
582 py2 = y + h;
583 pposx = 0;
584 pposy = 0;
585 } else {
586 /* Check if this plane has an overlapping part */
587 px1 = gx1 - p->pos_x;
588 py1 = gy1 - p->pos_y;
589 px2 = gx2 - p->pos_x;
590 py2 = gy2 - p->pos_y;
591 if (px1 >= p->width || py1 >= p->height ||
592 px2 <= 0 || py2 <= 0) {
593 blizzard.int_ctrl->enable_plane(i, 0);
594 continue;
595 }
596 /* Calculate the coordinates for the overlapping
597 * part in the plane's local coordinates.
598 */
599 pposx = -px1;
600 pposy = -py1;
601 if (px1 < 0)
602 px1 = 0;
603 if (py1 < 0)
604 py1 = 0;
605 if (px2 > p->width)
606 px2 = p->width;
607 if (py2 > p->height)
608 py2 = p->height;
609 if (pposx < 0)
610 pposx = 0;
611 if (pposy < 0)
612 pposy = 0;
613 }
614 pw = px2 - px1;
615 ph = py2 - py1;
616 offset = p->offset + (p->scr_width * py1 + px1) * p->bpp / 8;
617 if (wnd_color_mode)
618 /* Window embedded in the plane with a differing
619 * color mode / bpp. Calculate the number of DMA
620 * transfer elements in terms of the plane's bpp.
621 */
622 pw = (pw + 1) * bpp / p->bpp;
623#ifdef VERBOSE
624 dev_dbg(blizzard.fbdev->dev,
625 "plane %d offset %#08lx pposx %d pposy %d "
626 "px1 %d py1 %d pw %d ph %d\n",
627 i, offset, pposx, pposy, px1, py1, pw, ph);
628#endif
629 blizzard.int_ctrl->setup_plane(i,
630 OMAPFB_CHANNEL_OUT_LCD, offset,
631 p->scr_width,
632 pposx, pposy, pw, ph,
633 p->color_mode);
634
635 blizzard.int_ctrl->enable_plane(i, 1);
636 }
637
638 switch (wnd_color_mode) {
639 case OMAPFB_COLOR_YUV420:
640 color_mode = BLIZZARD_COLOR_YUV420;
641 /* Currently only the 16 bits/pixel cycle format is
642 * supported on the external interface. Adjust the number
643 * of transfer elements per line for 12bpp format.
644 */
645 w = (w + 1) * 3 / 4;
646 break;
647 default:
648 color_mode = BLIZZARD_COLOR_RGB565;
649 break;
650 }
651
652 blizzard_wait_line_buffer();
653 if (blizzard.last_color_mode == BLIZZARD_COLOR_YUV420)
654 blizzard_wait_yyc();
655 blizzard.last_color_mode = color_mode;
656 if (flags & OMAPFB_FORMAT_FLAG_TEARSYNC)
657 enable_tearsync(gy1, w, h,
658 blizzard.screen_height,
659 h_out,
660 flags & OMAPFB_FORMAT_FLAG_FORCE_VSYNC);
661 else
662 disable_tearsync();
663
664 if ((gx2_out - gx1_out) != (gx2 - gx1) ||
665 (gy2_out - gy1_out) != (gy2 - gy1))
666 have_zoom_for_this_update = 1;
667
668 /* 'background' type of screen update (as opposed to 'destructive')
669 can be used to disable scaling if scaling is active */
670 zoom_off = blizzard.zoom_on && !have_zoom_for_this_update &&
671 (gx1_out == 0) && (gx2_out == blizzard.screen_width) &&
672 (gy1_out == 0) && (gy2_out == blizzard.screen_height) &&
673 (gx1 == 0) && (gy1 == 0);
674
675 if (blizzard.zoom_on && !have_zoom_for_this_update && !zoom_off &&
676 check_1d_intersect(blizzard.zoom_area_gx1, blizzard.zoom_area_gx2,
677 gx1_out, gx2_out) &&
678 check_1d_intersect(blizzard.zoom_area_gy1, blizzard.zoom_area_gy2,
679 gy1_out, gy2_out)) {
680 /* Previous screen update was using scaling, current update
681 * is not using it. Additionally, current screen update is
682 * going to overlap with the scaled area. Scaling needs to be
683 * disabled in order to avoid 'magnifying glass' effect.
684 * Dummy setup of background window can be used for this.
685 */
686 set_window_regs(0, 0, blizzard.screen_width,
687 blizzard.screen_height,
688 0, 0, blizzard.screen_width,
689 blizzard.screen_height,
690 BLIZZARD_COLOR_RGB565, 1, flags);
691 blizzard.zoom_on = 0;
692 }
693
694 /* remember scaling settings if we have scaled update */
695 if (have_zoom_for_this_update) {
696 blizzard.zoom_on = 1;
697 blizzard.zoom_area_gx1 = gx1_out;
698 blizzard.zoom_area_gx2 = gx2_out;
699 blizzard.zoom_area_gy1 = gy1_out;
700 blizzard.zoom_area_gy2 = gy2_out;
701 }
702
703 set_window_regs(gx1, gy1, gx2, gy2, gx1_out, gy1_out, gx2_out, gy2_out,
704 color_mode, zoom_off, flags);
705 if (zoom_off)
706 blizzard.zoom_on = 0;
707
708 blizzard.extif->set_bits_per_cycle(16);
709 /* set_window_regs has left the register index at the right
710 * place, so no need to set it here.
711 */
712 blizzard.extif->transfer_area(w, h, request_complete, req);
713
714 return REQ_PENDING;
715}
716
717static int send_frame_handler(struct blizzard_request *req)
718{
719 struct update_param *par = &req->par.update;
720 int plane = par->plane;
721
722#ifdef VERBOSE
723 dev_dbg(blizzard.fbdev->dev,
724 "send_frame: x %d y %d w %d h %d "
725 "x_out %d y_out %d w_out %d h_out %d "
726 "color_mode %04x flags %04x planes %01x\n",
727 par->x, par->y, par->width, par->height,
728 par->out_x, par->out_y, par->out_width, par->out_height,
729 par->color_mode, par->flags, blizzard.enabled_planes);
730#endif
731 if (par->flags & OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY)
732 disable_overlay();
733
734 if ((blizzard.enabled_planes & blizzard.vid_nonstd_color) ||
735 (blizzard.enabled_planes & blizzard.vid_scaled))
736 return do_full_screen_update(req);
737
738 return do_partial_update(req, plane, par->x, par->y,
739 par->width, par->height,
740 par->out_x, par->out_y,
741 par->out_width, par->out_height,
742 par->color_mode, par->bpp);
743}
744
745static void send_frame_complete(void *data)
746{
747}
748
749#define ADD_PREQ(_x, _y, _w, _h, _x_out, _y_out, _w_out, _h_out) do { \
750 req = alloc_req(); \
751 req->handler = send_frame_handler; \
752 req->complete = send_frame_complete; \
753 req->par.update.plane = plane_idx; \
754 req->par.update.x = _x; \
755 req->par.update.y = _y; \
756 req->par.update.width = _w; \
757 req->par.update.height = _h; \
758 req->par.update.out_x = _x_out; \
759 req->par.update.out_y = _y_out; \
760 req->par.update.out_width = _w_out; \
761 req->par.update.out_height = _h_out; \
762 req->par.update.bpp = bpp; \
763 req->par.update.color_mode = color_mode;\
764 req->par.update.flags = flags; \
765 list_add_tail(&req->entry, req_head); \
766} while(0)
767
768static void create_req_list(int plane_idx,
769 struct omapfb_update_window *win,
770 struct list_head *req_head)
771{
772 struct blizzard_request *req;
773 int x = win->x;
774 int y = win->y;
775 int width = win->width;
776 int height = win->height;
777 int x_out = win->out_x;
778 int y_out = win->out_y;
779 int width_out = win->out_width;
780 int height_out = win->out_height;
781 int color_mode;
782 int bpp;
783 int flags;
784 unsigned int ystart = y;
785 unsigned int yspan = height;
786 unsigned int ystart_out = y_out;
787 unsigned int yspan_out = height_out;
788
789 flags = win->format & ~OMAPFB_FORMAT_MASK;
790 color_mode = win->format & OMAPFB_FORMAT_MASK;
791 switch (color_mode) {
792 case OMAPFB_COLOR_YUV420:
793 /* Embedded window with different color mode */
794 bpp = 12;
795 /* X, Y, height must be aligned at 2, width at 4 pixels */
796 x &= ~1;
797 y &= ~1;
798 height = yspan = height & ~1;
799 width = width & ~3;
800 break;
801 default:
802 /* Same as the plane color mode */
803 bpp = blizzard.plane[plane_idx].bpp;
804 break;
805 }
806 if (width * height * bpp / 8 > blizzard.max_transmit_size) {
807 yspan = blizzard.max_transmit_size / (width * bpp / 8);
808 yspan_out = yspan * height_out / height;
809 ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out,
810 width_out, yspan_out);
811 ystart += yspan;
812 ystart_out += yspan_out;
813 yspan = height - yspan;
814 yspan_out = height_out - yspan_out;
815 flags &= ~OMAPFB_FORMAT_FLAG_TEARSYNC;
816 }
817
818 ADD_PREQ(x, ystart, width, yspan, x_out, ystart_out,
819 width_out, yspan_out);
820}
821
822static void auto_update_complete(void *data)
823{
824 if (!blizzard.stop_auto_update)
825 mod_timer(&blizzard.auto_update_timer,
826 jiffies + BLIZZARD_AUTO_UPDATE_TIME);
827}
828
829static void blizzard_update_window_auto(unsigned long arg)
830{
831 LIST_HEAD(req_list);
832 struct blizzard_request *last;
833 struct omapfb_plane_struct *plane;
834
835 plane = blizzard.fbdev->fb_info[0]->par;
836 create_req_list(plane->idx,
837 &blizzard.auto_update_window, &req_list);
838 last = list_entry(req_list.prev, struct blizzard_request, entry);
839
840 last->complete = auto_update_complete;
841 last->complete_data = NULL;
842
843 submit_req_list(&req_list);
844}
845
846int blizzard_update_window_async(struct fb_info *fbi,
847 struct omapfb_update_window *win,
848 void (*complete_callback)(void *arg),
849 void *complete_callback_data)
850{
851 LIST_HEAD(req_list);
852 struct blizzard_request *last;
853 struct omapfb_plane_struct *plane = fbi->par;
854
855 if (unlikely(blizzard.update_mode != OMAPFB_MANUAL_UPDATE))
856 return -EINVAL;
857 if (unlikely(!blizzard.te_connected &&
858 (win->format & OMAPFB_FORMAT_FLAG_TEARSYNC)))
859 return -EINVAL;
860
861 create_req_list(plane->idx, win, &req_list);
862 last = list_entry(req_list.prev, struct blizzard_request, entry);
863
864 last->complete = complete_callback;
865 last->complete_data = (void *)complete_callback_data;
866
867 submit_req_list(&req_list);
868
869 return 0;
870}
871EXPORT_SYMBOL(blizzard_update_window_async);
872
873static int update_full_screen(void)
874{
875 return blizzard_update_window_async(blizzard.fbdev->fb_info[0],
876 &blizzard.auto_update_window, NULL, NULL);
877
878}
879
880static int blizzard_setup_plane(int plane, int channel_out,
881 unsigned long offset, int screen_width,
882 int pos_x, int pos_y, int width, int height,
883 int color_mode)
884{
885 struct plane_info *p;
886
887#ifdef VERBOSE
888 dev_dbg(blizzard.fbdev->dev,
889 "plane %d ch_out %d offset %#08lx scr_width %d "
890 "pos_x %d pos_y %d width %d height %d color_mode %d\n",
891 plane, channel_out, offset, screen_width,
892 pos_x, pos_y, width, height, color_mode);
893#endif
894 if ((unsigned)plane > OMAPFB_PLANE_NUM)
895 return -EINVAL;
896 p = &blizzard.plane[plane];
897
898 switch (color_mode) {
899 case OMAPFB_COLOR_YUV422:
900 case OMAPFB_COLOR_YUY422:
901 p->bpp = 16;
902 blizzard.vid_nonstd_color &= ~(1 << plane);
903 break;
904 case OMAPFB_COLOR_YUV420:
905 p->bpp = 12;
906 blizzard.vid_nonstd_color |= 1 << plane;
907 break;
908 case OMAPFB_COLOR_RGB565:
909 p->bpp = 16;
910 blizzard.vid_nonstd_color &= ~(1 << plane);
911 break;
912 default:
913 return -EINVAL;
914 }
915
916 p->offset = offset;
917 p->pos_x = pos_x;
918 p->pos_y = pos_y;
919 p->width = width;
920 p->height = height;
921 p->scr_width = screen_width;
922 if (!p->out_width)
923 p->out_width = width;
924 if (!p->out_height)
925 p->out_height = height;
926
927 p->color_mode = color_mode;
928
929 return 0;
930}
931
932static int blizzard_set_scale(int plane, int orig_w, int orig_h,
933 int out_w, int out_h)
934{
935 struct plane_info *p = &blizzard.plane[plane];
936 int r;
937
938 dev_dbg(blizzard.fbdev->dev,
939 "plane %d orig_w %d orig_h %d out_w %d out_h %d\n",
940 plane, orig_w, orig_h, out_w, out_h);
941 if ((unsigned)plane > OMAPFB_PLANE_NUM)
942 return -ENODEV;
943
944 r = blizzard.int_ctrl->set_scale(plane, orig_w, orig_h, out_w, out_h);
945 if (r < 0)
946 return r;
947
948 p->width = orig_w;
949 p->height = orig_h;
950 p->out_width = out_w;
951 p->out_height = out_h;
952 if (orig_w == out_w && orig_h == out_h)
953 blizzard.vid_scaled &= ~(1 << plane);
954 else
955 blizzard.vid_scaled |= 1 << plane;
956
957 return 0;
958}
959
960static int blizzard_set_rotate(int angle)
961{
962 u32 l;
963
964 l = blizzard_read_reg(BLIZZARD_PANEL_CONFIGURATION);
965 l &= ~0x03;
966
967 switch (angle) {
968 case 0:
969 l = l | 0x00;
970 break;
971 case 90:
972 l = l | 0x03;
973 break;
974 case 180:
975 l = l | 0x02;
976 break;
977 case 270:
978 l = l | 0x01;
979 break;
980 default:
981 return -EINVAL;
982 }
983
984 blizzard_write_reg(BLIZZARD_PANEL_CONFIGURATION, l);
985
986 return 0;
987}
988
989static int blizzard_enable_plane(int plane, int enable)
990{
991 if (enable)
992 blizzard.enabled_planes |= 1 << plane;
993 else
994 blizzard.enabled_planes &= ~(1 << plane);
995
996 return 0;
997}
998
999static int sync_handler(struct blizzard_request *req)
1000{
1001 complete(req->par.sync);
1002 return REQ_COMPLETE;
1003}
1004
1005static void blizzard_sync(void)
1006{
1007 LIST_HEAD(req_list);
1008 struct blizzard_request *req;
1009 struct completion comp;
1010
1011 req = alloc_req();
1012
1013 req->handler = sync_handler;
1014 req->complete = NULL;
1015 init_completion(&comp);
1016 req->par.sync = &comp;
1017
1018 list_add(&req->entry, &req_list);
1019 submit_req_list(&req_list);
1020
1021 wait_for_completion(&comp);
1022}
1023
1024
1025static void blizzard_bind_client(struct omapfb_notifier_block *nb)
1026{
1027 if (blizzard.update_mode == OMAPFB_MANUAL_UPDATE) {
1028 omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY);
1029 }
1030}
1031
1032static int blizzard_set_update_mode(enum omapfb_update_mode mode)
1033{
1034 if (unlikely(mode != OMAPFB_MANUAL_UPDATE &&
1035 mode != OMAPFB_AUTO_UPDATE &&
1036 mode != OMAPFB_UPDATE_DISABLED))
1037 return -EINVAL;
1038
1039 if (mode == blizzard.update_mode)
1040 return 0;
1041
1042 dev_info(blizzard.fbdev->dev, "s1d1374x: setting update mode to %s\n",
1043 mode == OMAPFB_UPDATE_DISABLED ? "disabled" :
1044 (mode == OMAPFB_AUTO_UPDATE ? "auto" : "manual"));
1045
1046 switch (blizzard.update_mode) {
1047 case OMAPFB_MANUAL_UPDATE:
1048 omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_DISABLED);
1049 break;
1050 case OMAPFB_AUTO_UPDATE:
1051 blizzard.stop_auto_update = 1;
1052 del_timer_sync(&blizzard.auto_update_timer);
1053 break;
1054 case OMAPFB_UPDATE_DISABLED:
1055 break;
1056 }
1057
1058 blizzard.update_mode = mode;
1059 blizzard_sync();
1060 blizzard.stop_auto_update = 0;
1061
1062 switch (mode) {
1063 case OMAPFB_MANUAL_UPDATE:
1064 omapfb_notify_clients(blizzard.fbdev, OMAPFB_EVENT_READY);
1065 break;
1066 case OMAPFB_AUTO_UPDATE:
1067 blizzard_update_window_auto(0);
1068 break;
1069 case OMAPFB_UPDATE_DISABLED:
1070 break;
1071 }
1072
1073 return 0;
1074}
1075
1076static enum omapfb_update_mode blizzard_get_update_mode(void)
1077{
1078 return blizzard.update_mode;
1079}
1080
1081static inline void set_extif_timings(const struct extif_timings *t)
1082{
1083 blizzard.extif->set_timings(t);
1084}
1085
1086static inline unsigned long round_to_extif_ticks(unsigned long ps, int div)
1087{
1088 int bus_tick = blizzard.extif_clk_period * div;
1089 return (ps + bus_tick - 1) / bus_tick * bus_tick;
1090}
1091
1092static int calc_reg_timing(unsigned long sysclk, int div)
1093{
1094 struct extif_timings *t;
1095 unsigned long systim;
1096
1097 /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
1098 * AccessTime 2 ns + 12.2 ns (regs),
1099 * WEOffTime = WEOnTime + 1 ns,
1100 * REOffTime = REOnTime + 12 ns (regs),
1101 * CSOffTime = REOffTime + 1 ns
1102 * ReadCycle = 2ns + 2*SYSCLK (regs),
1103 * WriteCycle = 2*SYSCLK + 2 ns,
1104 * CSPulseWidth = 10 ns */
1105
1106 systim = 1000000000 / (sysclk / 1000);
1107 dev_dbg(blizzard.fbdev->dev,
1108 "Blizzard systim %lu ps extif_clk_period %u div %d\n",
1109 systim, blizzard.extif_clk_period, div);
1110
1111 t = &blizzard.reg_timings;
1112 memset(t, 0, sizeof(*t));
1113
1114 t->clk_div = div;
1115
1116 t->cs_on_time = 0;
1117 t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
1118 t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
1119 t->access_time = round_to_extif_ticks(t->re_on_time + 12200, div);
1120 t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
1121 t->re_off_time = round_to_extif_ticks(t->re_on_time + 13000, div);
1122 t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
1123 t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
1124 if (t->we_cycle_time < t->we_off_time)
1125 t->we_cycle_time = t->we_off_time;
1126 t->re_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
1127 if (t->re_cycle_time < t->re_off_time)
1128 t->re_cycle_time = t->re_off_time;
1129 t->cs_pulse_width = 0;
1130
1131 dev_dbg(blizzard.fbdev->dev, "[reg]cson %d csoff %d reon %d reoff %d\n",
1132 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
1133 dev_dbg(blizzard.fbdev->dev, "[reg]weon %d weoff %d recyc %d wecyc %d\n",
1134 t->we_on_time, t->we_off_time, t->re_cycle_time,
1135 t->we_cycle_time);
1136 dev_dbg(blizzard.fbdev->dev, "[reg]rdaccess %d cspulse %d\n",
1137 t->access_time, t->cs_pulse_width);
1138
1139 return blizzard.extif->convert_timings(t);
1140}
1141
1142static int calc_lut_timing(unsigned long sysclk, int div)
1143{
1144 struct extif_timings *t;
1145 unsigned long systim;
1146
1147 /* CSOnTime 0, WEOnTime 2 ns, REOnTime 2 ns,
1148 * AccessTime 2 ns + 4 * SYSCLK + 26 (lut),
1149 * WEOffTime = WEOnTime + 1 ns,
1150 * REOffTime = REOnTime + 4*SYSCLK + 26 ns (lut),
1151 * CSOffTime = REOffTime + 1 ns
1152 * ReadCycle = 2ns + 4*SYSCLK + 26 ns (lut),
1153 * WriteCycle = 2*SYSCLK + 2 ns,
1154 * CSPulseWidth = 10 ns */
1155
1156 systim = 1000000000 / (sysclk / 1000);
1157 dev_dbg(blizzard.fbdev->dev,
1158 "Blizzard systim %lu ps extif_clk_period %u div %d\n",
1159 systim, blizzard.extif_clk_period, div);
1160
1161 t = &blizzard.lut_timings;
1162 memset(t, 0, sizeof(*t));
1163
1164 t->clk_div = div;
1165
1166 t->cs_on_time = 0;
1167 t->we_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
1168 t->re_on_time = round_to_extif_ticks(t->cs_on_time + 2000, div);
1169 t->access_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
1170 26000, div);
1171 t->we_off_time = round_to_extif_ticks(t->we_on_time + 1000, div);
1172 t->re_off_time = round_to_extif_ticks(t->re_on_time + 4 * systim +
1173 26000, div);
1174 t->cs_off_time = round_to_extif_ticks(t->re_off_time + 1000, div);
1175 t->we_cycle_time = round_to_extif_ticks(2 * systim + 2000, div);
1176 if (t->we_cycle_time < t->we_off_time)
1177 t->we_cycle_time = t->we_off_time;
1178 t->re_cycle_time = round_to_extif_ticks(2000 + 4 * systim + 26000, div);
1179 if (t->re_cycle_time < t->re_off_time)
1180 t->re_cycle_time = t->re_off_time;
1181 t->cs_pulse_width = 0;
1182
1183 dev_dbg(blizzard.fbdev->dev,
1184 "[lut]cson %d csoff %d reon %d reoff %d\n",
1185 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time);
1186 dev_dbg(blizzard.fbdev->dev,
1187 "[lut]weon %d weoff %d recyc %d wecyc %d\n",
1188 t->we_on_time, t->we_off_time, t->re_cycle_time,
1189 t->we_cycle_time);
1190 dev_dbg(blizzard.fbdev->dev, "[lut]rdaccess %d cspulse %d\n",
1191 t->access_time, t->cs_pulse_width);
1192
1193 return blizzard.extif->convert_timings(t);
1194}
1195
1196static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div)
1197{
1198 int max_clk_div;
1199 int div;
1200
1201 blizzard.extif->get_clk_info(&blizzard.extif_clk_period, &max_clk_div);
1202 for (div = 1; div <= max_clk_div; div++) {
1203 if (calc_reg_timing(sysclk, div) == 0)
1204 break;
1205 }
1206 if (div > max_clk_div) {
1207 dev_dbg(blizzard.fbdev->dev, "reg timing failed\n");
1208 goto err;
1209 }
1210 *extif_mem_div = div;
1211
1212 for (div = 1; div <= max_clk_div; div++) {
1213 if (calc_lut_timing(sysclk, div) == 0)
1214 break;
1215 }
1216
1217 if (div > max_clk_div)
1218 goto err;
1219
1220 blizzard.extif_clk_div = div;
1221
1222 return 0;
1223err:
1224 dev_err(blizzard.fbdev->dev, "can't setup timings\n");
1225 return -1;
1226}
1227
1228static void calc_blizzard_clk_rates(unsigned long ext_clk,
1229 unsigned long *sys_clk, unsigned long *pix_clk)
1230{
1231 int pix_clk_src;
1232 int sys_div = 0, sys_mul = 0;
1233 int pix_div;
1234
1235 pix_clk_src = blizzard_read_reg(BLIZZARD_CLK_SRC);
1236 pix_div = ((pix_clk_src >> 3) & 0x1f) + 1;
1237 if ((pix_clk_src & (0x3 << 1)) == 0) {
1238 /* Source is the PLL */
1239 sys_div = (blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x3f) + 1;
1240 sys_mul = blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_0);
1241 sys_mul |= ((blizzard_read_reg(BLIZZARD_PLL_CLOCK_SYNTH_1)
1242 & 0x0f) << 11);
1243 *sys_clk = ext_clk * sys_mul / sys_div;
1244 } else /* else source is ext clk, or oscillator */
1245 *sys_clk = ext_clk;
1246
1247 *pix_clk = *sys_clk / pix_div; /* HZ */
1248 dev_dbg(blizzard.fbdev->dev,
1249 "ext_clk %ld pix_src %d pix_div %d sys_div %d sys_mul %d\n",
1250 ext_clk, pix_clk_src & (0x3 << 1), pix_div, sys_div, sys_mul);
1251 dev_dbg(blizzard.fbdev->dev, "sys_clk %ld pix_clk %ld\n",
1252 *sys_clk, *pix_clk);
1253}
1254
1255static int setup_tearsync(unsigned long pix_clk, int extif_div)
1256{
1257 int hdisp, vdisp;
1258 int hndp, vndp;
1259 int hsw, vsw;
1260 int hs, vs;
1261 int hs_pol_inv, vs_pol_inv;
1262 int use_hsvs, use_ndp;
1263 u8 b;
1264
1265 hsw = blizzard_read_reg(BLIZZARD_HSW);
1266 vsw = blizzard_read_reg(BLIZZARD_VSW);
1267 hs_pol_inv = !(hsw & 0x80);
1268 vs_pol_inv = !(vsw & 0x80);
1269 hsw = hsw & 0x7f;
1270 vsw = vsw & 0x3f;
1271
1272 hdisp = blizzard_read_reg(BLIZZARD_HDISP) * 8;
1273 vdisp = blizzard_read_reg(BLIZZARD_VDISP0) +
1274 ((blizzard_read_reg(BLIZZARD_VDISP1) & 0x3) << 8);
1275
1276 hndp = blizzard_read_reg(BLIZZARD_HNDP) & 0x3f;
1277 vndp = blizzard_read_reg(BLIZZARD_VNDP);
1278
1279 /* time to transfer one pixel (16bpp) in ps */
1280 blizzard.pix_tx_time = blizzard.reg_timings.we_cycle_time;
1281 if (blizzard.extif->get_max_tx_rate != NULL) {
1282 /* The external interface might have a rate limitation,
1283 * if so, we have to maximize our transfer rate.
1284 */
1285 unsigned long min_tx_time;
1286 unsigned long max_tx_rate = blizzard.extif->get_max_tx_rate();
1287
1288 dev_dbg(blizzard.fbdev->dev, "max_tx_rate %ld HZ\n",
1289 max_tx_rate);
1290 min_tx_time = 1000000000 / (max_tx_rate / 1000); /* ps */
1291 if (blizzard.pix_tx_time < min_tx_time)
1292 blizzard.pix_tx_time = min_tx_time;
1293 }
1294
1295 /* time to update one line in ps */
1296 blizzard.line_upd_time = (hdisp + hndp) * 1000000 / (pix_clk / 1000);
1297 blizzard.line_upd_time *= 1000;
1298 if (hdisp * blizzard.pix_tx_time > blizzard.line_upd_time)
1299 /* transfer speed too low, we might have to use both
1300 * HS and VS */
1301 use_hsvs = 1;
1302 else
1303 /* decent transfer speed, we'll always use only VS */
1304 use_hsvs = 0;
1305
1306 if (use_hsvs && (hs_pol_inv || vs_pol_inv)) {
1307 /* HS or'ed with VS doesn't work, use the active high
1308 * TE signal based on HNDP / VNDP */
1309 use_ndp = 1;
1310 hs_pol_inv = 0;
1311 vs_pol_inv = 0;
1312 hs = hndp;
1313 vs = vndp;
1314 } else {
1315 /* Use HS or'ed with VS as a TE signal if both are needed
1316 * or VNDP if only vsync is needed. */
1317 use_ndp = 0;
1318 hs = hsw;
1319 vs = vsw;
1320 if (!use_hsvs) {
1321 hs_pol_inv = 0;
1322 vs_pol_inv = 0;
1323 }
1324 }
1325
1326 hs = hs * 1000000 / (pix_clk / 1000); /* ps */
1327 hs *= 1000;
1328
1329 vs = vs * (hdisp + hndp) * 1000000 / (pix_clk / 1000); /* ps */
1330 vs *= 1000;
1331
1332 if (vs <= hs)
1333 return -EDOM;
1334 /* set VS to 120% of HS to minimize VS detection time */
1335 vs = hs * 12 / 10;
1336 /* minimize HS too */
1337 if (hs > 10000)
1338 hs = 10000;
1339
1340 b = blizzard_read_reg(BLIZZARD_NDISP_CTRL_STATUS);
1341 b &= ~0x3;
1342 b |= use_hsvs ? 1 : 0;
1343 b |= (use_ndp && use_hsvs) ? 0 : 2;
1344 blizzard_write_reg(BLIZZARD_NDISP_CTRL_STATUS, b);
1345
1346 blizzard.vsync_only = !use_hsvs;
1347
1348 dev_dbg(blizzard.fbdev->dev,
1349 "pix_clk %ld HZ pix_tx_time %ld ps line_upd_time %ld ps\n",
1350 pix_clk, blizzard.pix_tx_time, blizzard.line_upd_time);
1351 dev_dbg(blizzard.fbdev->dev,
1352 "hs %d ps vs %d ps mode %d vsync_only %d\n",
1353 hs, vs, b & 0x3, !use_hsvs);
1354
1355 return blizzard.extif->setup_tearsync(1, hs, vs,
1356 hs_pol_inv, vs_pol_inv,
1357 extif_div);
1358}
1359
1360static void blizzard_get_caps(int plane, struct omapfb_caps *caps)
1361{
1362 blizzard.int_ctrl->get_caps(plane, caps);
1363 caps->ctrl |= OMAPFB_CAPS_MANUAL_UPDATE |
1364 OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE |
1365 OMAPFB_CAPS_WINDOW_SCALE |
1366 OMAPFB_CAPS_WINDOW_OVERLAY |
1367 OMAPFB_CAPS_WINDOW_ROTATE;
1368 if (blizzard.te_connected)
1369 caps->ctrl |= OMAPFB_CAPS_TEARSYNC;
1370 caps->wnd_color |= (1 << OMAPFB_COLOR_RGB565) |
1371 (1 << OMAPFB_COLOR_YUV420);
1372}
1373
1374static void _save_regs(const struct blizzard_reg_list *list, int cnt)
1375{
1376 int i;
1377
1378 for (i = 0; i < cnt; i++, list++) {
1379 int reg;
1380 for (reg = list->start; reg <= list->end; reg += 2)
1381 blizzard_reg_cache[reg / 2] = blizzard_read_reg(reg);
1382 }
1383}
1384
1385static void _restore_regs(const struct blizzard_reg_list *list, int cnt)
1386{
1387 int i;
1388
1389 for (i = 0; i < cnt; i++, list++) {
1390 int reg;
1391 for (reg = list->start; reg <= list->end; reg += 2)
1392 blizzard_write_reg(reg, blizzard_reg_cache[reg / 2]);
1393 }
1394}
1395
1396static void blizzard_save_all_regs(void)
1397{
1398 _save_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs));
1399 _save_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs));
1400}
1401
1402static void blizzard_restore_pll_regs(void)
1403{
1404 _restore_regs(blizzard_pll_regs, ARRAY_SIZE(blizzard_pll_regs));
1405}
1406
1407static void blizzard_restore_gen_regs(void)
1408{
1409 _restore_regs(blizzard_gen_regs, ARRAY_SIZE(blizzard_gen_regs));
1410}
1411
1412static void blizzard_suspend(void)
1413{
1414 u32 l;
1415 unsigned long tmo;
1416
1417 if (blizzard.last_color_mode) {
1418 update_full_screen();
1419 blizzard_sync();
1420 }
1421 blizzard.update_mode_before_suspend = blizzard.update_mode;
1422 /* the following will disable clocks as well */
1423 blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED);
1424
1425 blizzard_save_all_regs();
1426
1427 blizzard_stop_sdram();
1428
1429 l = blizzard_read_reg(BLIZZARD_POWER_SAVE);
1430 /* Standby, Sleep. We assume we use an external clock. */
1431 l |= 0x03;
1432 blizzard_write_reg(BLIZZARD_POWER_SAVE, l);
1433
1434 tmo = jiffies + msecs_to_jiffies(100);
1435 while (!(blizzard_read_reg(BLIZZARD_PLL_MODE) & (1 << 1))) {
1436 if (time_after(jiffies, tmo)) {
1437 dev_err(blizzard.fbdev->dev,
1438 "s1d1374x: sleep timeout, stopping PLL manually\n");
1439 l = blizzard_read_reg(BLIZZARD_PLL_MODE);
1440 l &= ~0x03;
1441 /* Disable PLL, counter function */
1442 l |= 0x2;
1443 blizzard_write_reg(BLIZZARD_PLL_MODE, l);
1444 break;
1445 }
1446 msleep(1);
1447 }
1448
1449 if (blizzard.power_down != NULL)
1450 blizzard.power_down(blizzard.fbdev->dev);
1451}
1452
1453static void blizzard_resume(void)
1454{
1455 u32 l;
1456
1457 if (blizzard.power_up != NULL)
1458 blizzard.power_up(blizzard.fbdev->dev);
1459
1460 l = blizzard_read_reg(BLIZZARD_POWER_SAVE);
1461 /* Standby, Sleep */
1462 l &= ~0x03;
1463 blizzard_write_reg(BLIZZARD_POWER_SAVE, l);
1464
1465 blizzard_restore_pll_regs();
1466 l = blizzard_read_reg(BLIZZARD_PLL_MODE);
1467 l &= ~0x03;
1468 /* Enable PLL, counter function */
1469 l |= 0x1;
1470 blizzard_write_reg(BLIZZARD_PLL_MODE, l);
1471
1472 while (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & (1 << 7)))
1473 msleep(1);
1474
1475 blizzard_restart_sdram();
1476
1477 blizzard_restore_gen_regs();
1478
1479 /* Enable display */
1480 blizzard_write_reg(BLIZZARD_DISPLAY_MODE, 0x01);
1481
1482 /* the following will enable clocks as necessary */
1483 blizzard_set_update_mode(blizzard.update_mode_before_suspend);
1484
1485 /* Force a background update */
1486 blizzard.zoom_on = 1;
1487 update_full_screen();
1488 blizzard_sync();
1489}
1490
1491static int blizzard_init(struct omapfb_device *fbdev, int ext_mode,
1492 struct omapfb_mem_desc *req_vram)
1493{
1494 int r = 0, i;
1495 u8 rev, conf;
1496 unsigned long ext_clk;
1497 int extif_div;
1498 unsigned long sys_clk, pix_clk;
1499 struct omapfb_platform_data *omapfb_conf;
1500 struct blizzard_platform_data *ctrl_conf;
1501
1502 blizzard.fbdev = fbdev;
1503
1504 BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
1505
1506 blizzard.fbdev = fbdev;
1507 blizzard.extif = fbdev->ext_if;
1508 blizzard.int_ctrl = fbdev->int_ctrl;
1509
1510 omapfb_conf = fbdev->dev->platform_data;
1511 ctrl_conf = omapfb_conf->ctrl_platform_data;
1512 if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) {
1513 dev_err(fbdev->dev, "s1d1374x: missing platform data\n");
1514 r = -ENOENT;
1515 goto err1;
1516 }
1517
1518 blizzard.power_down = ctrl_conf->power_down;
1519 blizzard.power_up = ctrl_conf->power_up;
1520
1521 spin_lock_init(&blizzard.req_lock);
1522
1523 if ((r = blizzard.int_ctrl->init(fbdev, 1, req_vram)) < 0)
1524 goto err1;
1525
1526 if ((r = blizzard.extif->init(fbdev)) < 0)
1527 goto err2;
1528
1529 blizzard_ctrl.set_color_key = blizzard.int_ctrl->set_color_key;
1530 blizzard_ctrl.get_color_key = blizzard.int_ctrl->get_color_key;
1531 blizzard_ctrl.setup_mem = blizzard.int_ctrl->setup_mem;
1532 blizzard_ctrl.mmap = blizzard.int_ctrl->mmap;
1533
1534 ext_clk = ctrl_conf->get_clock_rate(fbdev->dev);
1535 if ((r = calc_extif_timings(ext_clk, &extif_div)) < 0)
1536 goto err3;
1537
1538 set_extif_timings(&blizzard.reg_timings);
1539
1540 if (blizzard.power_up != NULL)
1541 blizzard.power_up(fbdev->dev);
1542
1543 calc_blizzard_clk_rates(ext_clk, &sys_clk, &pix_clk);
1544
1545 if ((r = calc_extif_timings(sys_clk, &extif_div)) < 0)
1546 goto err3;
1547 set_extif_timings(&blizzard.reg_timings);
1548
1549 if (!(blizzard_read_reg(BLIZZARD_PLL_DIV) & 0x80)) {
1550 dev_err(fbdev->dev,
1551 "controller not initialized by the bootloader\n");
1552 r = -ENODEV;
1553 goto err3;
1554 }
1555
1556 if (ctrl_conf->te_connected) {
1557 if ((r = setup_tearsync(pix_clk, extif_div)) < 0)
1558 goto err3;
1559 blizzard.te_connected = 1;
1560 }
1561
1562 rev = blizzard_read_reg(BLIZZARD_REV_CODE);
1563 conf = blizzard_read_reg(BLIZZARD_CONFIG);
1564
1565 switch (rev & 0xfc) {
1566 case 0x9c:
1567 blizzard.version = BLIZZARD_VERSION_S1D13744;
1568 pr_info("omapfb: s1d13744 LCD controller rev %d "
1569 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
1570 break;
1571 case 0xa4:
1572 blizzard.version = BLIZZARD_VERSION_S1D13745;
1573 pr_info("omapfb: s1d13745 LCD controller rev %d "
1574 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
1575 break;
1576 default:
1577 dev_err(fbdev->dev, "invalid s1d1374x revision %02x\n",
1578 rev);
1579 r = -ENODEV;
1580 goto err3;
1581 }
1582
1583 blizzard.max_transmit_size = blizzard.extif->max_transmit_size;
1584
1585 blizzard.update_mode = OMAPFB_UPDATE_DISABLED;
1586
1587 blizzard.auto_update_window.x = 0;
1588 blizzard.auto_update_window.y = 0;
1589 blizzard.auto_update_window.width = fbdev->panel->x_res;
1590 blizzard.auto_update_window.height = fbdev->panel->y_res;
1591 blizzard.auto_update_window.out_x = 0;
1592 blizzard.auto_update_window.out_y = 0;
1593 blizzard.auto_update_window.out_width = fbdev->panel->x_res;
1594 blizzard.auto_update_window.out_height = fbdev->panel->y_res;
1595 blizzard.auto_update_window.format = 0;
1596
1597 blizzard.screen_width = fbdev->panel->x_res;
1598 blizzard.screen_height = fbdev->panel->y_res;
1599
1600 init_timer(&blizzard.auto_update_timer);
1601 blizzard.auto_update_timer.function = blizzard_update_window_auto;
1602 blizzard.auto_update_timer.data = 0;
1603
1604 INIT_LIST_HEAD(&blizzard.free_req_list);
1605 INIT_LIST_HEAD(&blizzard.pending_req_list);
1606 for (i = 0; i < ARRAY_SIZE(blizzard.req_pool); i++)
1607 list_add(&blizzard.req_pool[i].entry, &blizzard.free_req_list);
1608 BUG_ON(i <= IRQ_REQ_POOL_SIZE);
1609 sema_init(&blizzard.req_sema, i - IRQ_REQ_POOL_SIZE);
1610
1611 return 0;
1612err3:
1613 if (blizzard.power_down != NULL)
1614 blizzard.power_down(fbdev->dev);
1615 blizzard.extif->cleanup();
1616err2:
1617 blizzard.int_ctrl->cleanup();
1618err1:
1619 return r;
1620}
1621
1622static void blizzard_cleanup(void)
1623{
1624 blizzard_set_update_mode(OMAPFB_UPDATE_DISABLED);
1625 blizzard.extif->cleanup();
1626 blizzard.int_ctrl->cleanup();
1627 if (blizzard.power_down != NULL)
1628 blizzard.power_down(blizzard.fbdev->dev);
1629}
1630
1631struct lcd_ctrl blizzard_ctrl = {
1632 .name = "blizzard",
1633 .init = blizzard_init,
1634 .cleanup = blizzard_cleanup,
1635 .bind_client = blizzard_bind_client,
1636 .get_caps = blizzard_get_caps,
1637 .set_update_mode = blizzard_set_update_mode,
1638 .get_update_mode = blizzard_get_update_mode,
1639 .setup_plane = blizzard_setup_plane,
1640 .set_scale = blizzard_set_scale,
1641 .enable_plane = blizzard_enable_plane,
1642 .set_rotate = blizzard_set_rotate,
1643 .update_window = blizzard_update_window_async,
1644 .sync = blizzard_sync,
1645 .suspend = blizzard_suspend,
1646 .resume = blizzard_resume,
1647};
1648
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
deleted file mode 100644
index 6f61e781f15a..000000000000
--- a/drivers/video/omap/dispc.c
+++ /dev/null
@@ -1,1547 +0,0 @@
1/*
2 * OMAP2 display controller support
3 *
4 * Copyright (C) 2005 Nokia Corporation
5 * Author: Imre Deak <imre.deak@nokia.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/dma-mapping.h>
24#include <linux/mm.h>
25#include <linux/vmalloc.h>
26#include <linux/clk.h>
27#include <linux/io.h>
28#include <linux/platform_device.h>
29#include <linux/slab.h>
30
31#include <plat/sram.h>
32#include <plat/board.h>
33
34#include "omapfb.h"
35#include "dispc.h"
36
37#define MODULE_NAME "dispc"
38
39#define DSS_BASE 0x48050000
40#define DSS_SYSCONFIG 0x0010
41
42#define DISPC_BASE 0x48050400
43
44/* DISPC common */
45#define DISPC_REVISION 0x0000
46#define DISPC_SYSCONFIG 0x0010
47#define DISPC_SYSSTATUS 0x0014
48#define DISPC_IRQSTATUS 0x0018
49#define DISPC_IRQENABLE 0x001C
50#define DISPC_CONTROL 0x0040
51#define DISPC_CONFIG 0x0044
52#define DISPC_CAPABLE 0x0048
53#define DISPC_DEFAULT_COLOR0 0x004C
54#define DISPC_DEFAULT_COLOR1 0x0050
55#define DISPC_TRANS_COLOR0 0x0054
56#define DISPC_TRANS_COLOR1 0x0058
57#define DISPC_LINE_STATUS 0x005C
58#define DISPC_LINE_NUMBER 0x0060
59#define DISPC_TIMING_H 0x0064
60#define DISPC_TIMING_V 0x0068
61#define DISPC_POL_FREQ 0x006C
62#define DISPC_DIVISOR 0x0070
63#define DISPC_SIZE_DIG 0x0078
64#define DISPC_SIZE_LCD 0x007C
65
66#define DISPC_DATA_CYCLE1 0x01D4
67#define DISPC_DATA_CYCLE2 0x01D8
68#define DISPC_DATA_CYCLE3 0x01DC
69
70/* DISPC GFX plane */
71#define DISPC_GFX_BA0 0x0080
72#define DISPC_GFX_BA1 0x0084
73#define DISPC_GFX_POSITION 0x0088
74#define DISPC_GFX_SIZE 0x008C
75#define DISPC_GFX_ATTRIBUTES 0x00A0
76#define DISPC_GFX_FIFO_THRESHOLD 0x00A4
77#define DISPC_GFX_FIFO_SIZE_STATUS 0x00A8
78#define DISPC_GFX_ROW_INC 0x00AC
79#define DISPC_GFX_PIXEL_INC 0x00B0
80#define DISPC_GFX_WINDOW_SKIP 0x00B4
81#define DISPC_GFX_TABLE_BA 0x00B8
82
83/* DISPC Video plane 1/2 */
84#define DISPC_VID1_BASE 0x00BC
85#define DISPC_VID2_BASE 0x014C
86
87/* Offsets into DISPC_VID1/2_BASE */
88#define DISPC_VID_BA0 0x0000
89#define DISPC_VID_BA1 0x0004
90#define DISPC_VID_POSITION 0x0008
91#define DISPC_VID_SIZE 0x000C
92#define DISPC_VID_ATTRIBUTES 0x0010
93#define DISPC_VID_FIFO_THRESHOLD 0x0014
94#define DISPC_VID_FIFO_SIZE_STATUS 0x0018
95#define DISPC_VID_ROW_INC 0x001C
96#define DISPC_VID_PIXEL_INC 0x0020
97#define DISPC_VID_FIR 0x0024
98#define DISPC_VID_PICTURE_SIZE 0x0028
99#define DISPC_VID_ACCU0 0x002C
100#define DISPC_VID_ACCU1 0x0030
101
102/* 8 elements in 8 byte increments */
103#define DISPC_VID_FIR_COEF_H0 0x0034
104/* 8 elements in 8 byte increments */
105#define DISPC_VID_FIR_COEF_HV0 0x0038
106/* 5 elements in 4 byte increments */
107#define DISPC_VID_CONV_COEF0 0x0074
108
109#define DISPC_IRQ_FRAMEMASK 0x0001
110#define DISPC_IRQ_VSYNC 0x0002
111#define DISPC_IRQ_EVSYNC_EVEN 0x0004
112#define DISPC_IRQ_EVSYNC_ODD 0x0008
113#define DISPC_IRQ_ACBIAS_COUNT_STAT 0x0010
114#define DISPC_IRQ_PROG_LINE_NUM 0x0020
115#define DISPC_IRQ_GFX_FIFO_UNDERFLOW 0x0040
116#define DISPC_IRQ_GFX_END_WIN 0x0080
117#define DISPC_IRQ_PAL_GAMMA_MASK 0x0100
118#define DISPC_IRQ_OCP_ERR 0x0200
119#define DISPC_IRQ_VID1_FIFO_UNDERFLOW 0x0400
120#define DISPC_IRQ_VID1_END_WIN 0x0800
121#define DISPC_IRQ_VID2_FIFO_UNDERFLOW 0x1000
122#define DISPC_IRQ_VID2_END_WIN 0x2000
123#define DISPC_IRQ_SYNC_LOST 0x4000
124
125#define DISPC_IRQ_MASK_ALL 0x7fff
126
127#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
128 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
129 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
130 DISPC_IRQ_SYNC_LOST)
131
132#define RFBI_CONTROL 0x48050040
133
134#define MAX_PALETTE_SIZE (256 * 16)
135
136#define FLD_MASK(pos, len) (((1 << len) - 1) << pos)
137
138#define MOD_REG_FLD(reg, mask, val) \
139 dispc_write_reg((reg), (dispc_read_reg(reg) & ~(mask)) | (val));
140
141#define OMAP2_SRAM_START 0x40200000
142/* Maximum size, in reality this is smaller if SRAM is partially locked. */
143#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */
144
145/* We support the SDRAM / SRAM types. See OMAPFB_PLANE_MEMTYPE_* in omapfb.h */
146#define DISPC_MEMTYPE_NUM 2
147
148#define RESMAP_SIZE(_page_cnt) \
149 ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
150#define RESMAP_PTR(_res_map, _page_nr) \
151 (((_res_map)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
152#define RESMAP_MASK(_page_nr) \
153 (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
154
155struct resmap {
156 unsigned long start;
157 unsigned page_cnt;
158 unsigned long *map;
159};
160
161#define MAX_IRQ_HANDLERS 4
162
163static struct {
164 void __iomem *base;
165
166 struct omapfb_mem_desc mem_desc;
167 struct resmap *res_map[DISPC_MEMTYPE_NUM];
168 atomic_t map_count[OMAPFB_PLANE_NUM];
169
170 dma_addr_t palette_paddr;
171 void *palette_vaddr;
172
173 int ext_mode;
174
175 struct {
176 u32 irq_mask;
177 void (*callback)(void *);
178 void *data;
179 } irq_handlers[MAX_IRQ_HANDLERS];
180 struct completion frame_done;
181
182 int fir_hinc[OMAPFB_PLANE_NUM];
183 int fir_vinc[OMAPFB_PLANE_NUM];
184
185 struct clk *dss_ick, *dss1_fck;
186 struct clk *dss_54m_fck;
187
188 enum omapfb_update_mode update_mode;
189 struct omapfb_device *fbdev;
190
191 struct omapfb_color_key color_key;
192} dispc;
193
194static void enable_lcd_clocks(int enable);
195
196static void inline dispc_write_reg(int idx, u32 val)
197{
198 __raw_writel(val, dispc.base + idx);
199}
200
201static u32 inline dispc_read_reg(int idx)
202{
203 u32 l = __raw_readl(dispc.base + idx);
204 return l;
205}
206
207/* Select RFBI or bypass mode */
208static void enable_rfbi_mode(int enable)
209{
210 void __iomem *rfbi_control;
211 u32 l;
212
213 l = dispc_read_reg(DISPC_CONTROL);
214 /* Enable RFBI, GPIO0/1 */
215 l &= ~((1 << 11) | (1 << 15) | (1 << 16));
216 l |= enable ? (1 << 11) : 0;
217 /* RFBI En: GPIO0/1=10 RFBI Dis: GPIO0/1=11 */
218 l |= 1 << 15;
219 l |= enable ? 0 : (1 << 16);
220 dispc_write_reg(DISPC_CONTROL, l);
221
222 /* Set bypass mode in RFBI module */
223 rfbi_control = ioremap(RFBI_CONTROL, SZ_1K);
224 if (!rfbi_control) {
225 pr_err("Unable to ioremap rfbi_control\n");
226 return;
227 }
228 l = __raw_readl(rfbi_control);
229 l |= enable ? 0 : (1 << 1);
230 __raw_writel(l, rfbi_control);
231 iounmap(rfbi_control);
232}
233
234static void set_lcd_data_lines(int data_lines)
235{
236 u32 l;
237 int code = 0;
238
239 switch (data_lines) {
240 case 12:
241 code = 0;
242 break;
243 case 16:
244 code = 1;
245 break;
246 case 18:
247 code = 2;
248 break;
249 case 24:
250 code = 3;
251 break;
252 default:
253 BUG();
254 }
255
256 l = dispc_read_reg(DISPC_CONTROL);
257 l &= ~(0x03 << 8);
258 l |= code << 8;
259 dispc_write_reg(DISPC_CONTROL, l);
260}
261
262static void set_load_mode(int mode)
263{
264 BUG_ON(mode & ~(DISPC_LOAD_CLUT_ONLY | DISPC_LOAD_FRAME_ONLY |
265 DISPC_LOAD_CLUT_ONCE_FRAME));
266 MOD_REG_FLD(DISPC_CONFIG, 0x03 << 1, mode << 1);
267}
268
269void omap_dispc_set_lcd_size(int x, int y)
270{
271 BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
272 enable_lcd_clocks(1);
273 MOD_REG_FLD(DISPC_SIZE_LCD, FLD_MASK(16, 11) | FLD_MASK(0, 11),
274 ((y - 1) << 16) | (x - 1));
275 enable_lcd_clocks(0);
276}
277EXPORT_SYMBOL(omap_dispc_set_lcd_size);
278
279void omap_dispc_set_digit_size(int x, int y)
280{
281 BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
282 enable_lcd_clocks(1);
283 MOD_REG_FLD(DISPC_SIZE_DIG, FLD_MASK(16, 11) | FLD_MASK(0, 11),
284 ((y - 1) << 16) | (x - 1));
285 enable_lcd_clocks(0);
286}
287EXPORT_SYMBOL(omap_dispc_set_digit_size);
288
289static void setup_plane_fifo(int plane, int ext_mode)
290{
291 const u32 ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
292 DISPC_VID1_BASE + DISPC_VID_FIFO_THRESHOLD,
293 DISPC_VID2_BASE + DISPC_VID_FIFO_THRESHOLD };
294 const u32 fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
295 DISPC_VID1_BASE + DISPC_VID_FIFO_SIZE_STATUS,
296 DISPC_VID2_BASE + DISPC_VID_FIFO_SIZE_STATUS };
297 int low, high;
298 u32 l;
299
300 BUG_ON(plane > 2);
301
302 l = dispc_read_reg(fsz_reg[plane]);
303 l &= FLD_MASK(0, 11);
304 if (ext_mode) {
305 low = l * 3 / 4;
306 high = l;
307 } else {
308 low = l / 4;
309 high = l * 3 / 4;
310 }
311 MOD_REG_FLD(ftrs_reg[plane], FLD_MASK(16, 12) | FLD_MASK(0, 12),
312 (high << 16) | low);
313}
314
315void omap_dispc_enable_lcd_out(int enable)
316{
317 enable_lcd_clocks(1);
318 MOD_REG_FLD(DISPC_CONTROL, 1, enable ? 1 : 0);
319 enable_lcd_clocks(0);
320}
321EXPORT_SYMBOL(omap_dispc_enable_lcd_out);
322
323void omap_dispc_enable_digit_out(int enable)
324{
325 enable_lcd_clocks(1);
326 MOD_REG_FLD(DISPC_CONTROL, 1 << 1, enable ? 1 << 1 : 0);
327 enable_lcd_clocks(0);
328}
329EXPORT_SYMBOL(omap_dispc_enable_digit_out);
330
331static inline int _setup_plane(int plane, int channel_out,
332 u32 paddr, int screen_width,
333 int pos_x, int pos_y, int width, int height,
334 int color_mode)
335{
336 const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
337 DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
338 DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
339 const u32 ba_reg[] = { DISPC_GFX_BA0, DISPC_VID1_BASE + DISPC_VID_BA0,
340 DISPC_VID2_BASE + DISPC_VID_BA0 };
341 const u32 ps_reg[] = { DISPC_GFX_POSITION,
342 DISPC_VID1_BASE + DISPC_VID_POSITION,
343 DISPC_VID2_BASE + DISPC_VID_POSITION };
344 const u32 sz_reg[] = { DISPC_GFX_SIZE,
345 DISPC_VID1_BASE + DISPC_VID_PICTURE_SIZE,
346 DISPC_VID2_BASE + DISPC_VID_PICTURE_SIZE };
347 const u32 ri_reg[] = { DISPC_GFX_ROW_INC,
348 DISPC_VID1_BASE + DISPC_VID_ROW_INC,
349 DISPC_VID2_BASE + DISPC_VID_ROW_INC };
350 const u32 vs_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
351 DISPC_VID2_BASE + DISPC_VID_SIZE };
352
353 int chout_shift, burst_shift;
354 int chout_val;
355 int color_code;
356 int bpp;
357 int cconv_en;
358 int set_vsize;
359 u32 l;
360
361#ifdef VERBOSE
362 dev_dbg(dispc.fbdev->dev, "plane %d channel %d paddr %#08x scr_width %d"
363 " pos_x %d pos_y %d width %d height %d color_mode %d\n",
364 plane, channel_out, paddr, screen_width, pos_x, pos_y,
365 width, height, color_mode);
366#endif
367
368 set_vsize = 0;
369 switch (plane) {
370 case OMAPFB_PLANE_GFX:
371 burst_shift = 6;
372 chout_shift = 8;
373 break;
374 case OMAPFB_PLANE_VID1:
375 case OMAPFB_PLANE_VID2:
376 burst_shift = 14;
377 chout_shift = 16;
378 set_vsize = 1;
379 break;
380 default:
381 return -EINVAL;
382 }
383
384 switch (channel_out) {
385 case OMAPFB_CHANNEL_OUT_LCD:
386 chout_val = 0;
387 break;
388 case OMAPFB_CHANNEL_OUT_DIGIT:
389 chout_val = 1;
390 break;
391 default:
392 return -EINVAL;
393 }
394
395 cconv_en = 0;
396 switch (color_mode) {
397 case OMAPFB_COLOR_RGB565:
398 color_code = DISPC_RGB_16_BPP;
399 bpp = 16;
400 break;
401 case OMAPFB_COLOR_YUV422:
402 if (plane == 0)
403 return -EINVAL;
404 color_code = DISPC_UYVY_422;
405 cconv_en = 1;
406 bpp = 16;
407 break;
408 case OMAPFB_COLOR_YUY422:
409 if (plane == 0)
410 return -EINVAL;
411 color_code = DISPC_YUV2_422;
412 cconv_en = 1;
413 bpp = 16;
414 break;
415 default:
416 return -EINVAL;
417 }
418
419 l = dispc_read_reg(at_reg[plane]);
420
421 l &= ~(0x0f << 1);
422 l |= color_code << 1;
423 l &= ~(1 << 9);
424 l |= cconv_en << 9;
425
426 l &= ~(0x03 << burst_shift);
427 l |= DISPC_BURST_8x32 << burst_shift;
428
429 l &= ~(1 << chout_shift);
430 l |= chout_val << chout_shift;
431
432 dispc_write_reg(at_reg[plane], l);
433
434 dispc_write_reg(ba_reg[plane], paddr);
435 MOD_REG_FLD(ps_reg[plane],
436 FLD_MASK(16, 11) | FLD_MASK(0, 11), (pos_y << 16) | pos_x);
437
438 MOD_REG_FLD(sz_reg[plane], FLD_MASK(16, 11) | FLD_MASK(0, 11),
439 ((height - 1) << 16) | (width - 1));
440
441 if (set_vsize) {
442 /* Set video size if set_scale hasn't set it */
443 if (!dispc.fir_vinc[plane])
444 MOD_REG_FLD(vs_reg[plane],
445 FLD_MASK(16, 11), (height - 1) << 16);
446 if (!dispc.fir_hinc[plane])
447 MOD_REG_FLD(vs_reg[plane],
448 FLD_MASK(0, 11), width - 1);
449 }
450
451 dispc_write_reg(ri_reg[plane], (screen_width - width) * bpp / 8 + 1);
452
453 return height * screen_width * bpp / 8;
454}
455
456static int omap_dispc_setup_plane(int plane, int channel_out,
457 unsigned long offset,
458 int screen_width,
459 int pos_x, int pos_y, int width, int height,
460 int color_mode)
461{
462 u32 paddr;
463 int r;
464
465 if ((unsigned)plane > dispc.mem_desc.region_cnt)
466 return -EINVAL;
467 paddr = dispc.mem_desc.region[plane].paddr + offset;
468 enable_lcd_clocks(1);
469 r = _setup_plane(plane, channel_out, paddr,
470 screen_width,
471 pos_x, pos_y, width, height, color_mode);
472 enable_lcd_clocks(0);
473 return r;
474}
475
476static void write_firh_reg(int plane, int reg, u32 value)
477{
478 u32 base;
479
480 if (plane == 1)
481 base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_H0;
482 else
483 base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_H0;
484 dispc_write_reg(base + reg * 8, value);
485}
486
487static void write_firhv_reg(int plane, int reg, u32 value)
488{
489 u32 base;
490
491 if (plane == 1)
492 base = DISPC_VID1_BASE + DISPC_VID_FIR_COEF_HV0;
493 else
494 base = DISPC_VID2_BASE + DISPC_VID_FIR_COEF_HV0;
495 dispc_write_reg(base + reg * 8, value);
496}
497
498static void set_upsampling_coef_table(int plane)
499{
500 const u32 coef[][2] = {
501 { 0x00800000, 0x00800000 },
502 { 0x0D7CF800, 0x037B02FF },
503 { 0x1E70F5FF, 0x0C6F05FE },
504 { 0x335FF5FE, 0x205907FB },
505 { 0xF74949F7, 0x00404000 },
506 { 0xF55F33FB, 0x075920FE },
507 { 0xF5701EFE, 0x056F0CFF },
508 { 0xF87C0DFF, 0x027B0300 },
509 };
510 int i;
511
512 for (i = 0; i < 8; i++) {
513 write_firh_reg(plane, i, coef[i][0]);
514 write_firhv_reg(plane, i, coef[i][1]);
515 }
516}
517
518static int omap_dispc_set_scale(int plane,
519 int orig_width, int orig_height,
520 int out_width, int out_height)
521{
522 const u32 at_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
523 DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
524 const u32 vs_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_SIZE,
525 DISPC_VID2_BASE + DISPC_VID_SIZE };
526 const u32 fir_reg[] = { 0, DISPC_VID1_BASE + DISPC_VID_FIR,
527 DISPC_VID2_BASE + DISPC_VID_FIR };
528
529 u32 l;
530 int fir_hinc;
531 int fir_vinc;
532
533 if ((unsigned)plane > OMAPFB_PLANE_NUM)
534 return -ENODEV;
535
536 if (plane == OMAPFB_PLANE_GFX &&
537 (out_width != orig_width || out_height != orig_height))
538 return -EINVAL;
539
540 enable_lcd_clocks(1);
541 if (orig_width < out_width) {
542 /*
543 * Upsampling.
544 * Currently you can only scale both dimensions in one way.
545 */
546 if (orig_height > out_height ||
547 orig_width * 8 < out_width ||
548 orig_height * 8 < out_height) {
549 enable_lcd_clocks(0);
550 return -EINVAL;
551 }
552 set_upsampling_coef_table(plane);
553 } else if (orig_width > out_width) {
554 /* Downsampling not yet supported
555 */
556
557 enable_lcd_clocks(0);
558 return -EINVAL;
559 }
560 if (!orig_width || orig_width == out_width)
561 fir_hinc = 0;
562 else
563 fir_hinc = 1024 * orig_width / out_width;
564 if (!orig_height || orig_height == out_height)
565 fir_vinc = 0;
566 else
567 fir_vinc = 1024 * orig_height / out_height;
568 dispc.fir_hinc[plane] = fir_hinc;
569 dispc.fir_vinc[plane] = fir_vinc;
570
571 MOD_REG_FLD(fir_reg[plane],
572 FLD_MASK(16, 12) | FLD_MASK(0, 12),
573 ((fir_vinc & 4095) << 16) |
574 (fir_hinc & 4095));
575
576 dev_dbg(dispc.fbdev->dev, "out_width %d out_height %d orig_width %d "
577 "orig_height %d fir_hinc %d fir_vinc %d\n",
578 out_width, out_height, orig_width, orig_height,
579 fir_hinc, fir_vinc);
580
581 MOD_REG_FLD(vs_reg[plane],
582 FLD_MASK(16, 11) | FLD_MASK(0, 11),
583 ((out_height - 1) << 16) | (out_width - 1));
584
585 l = dispc_read_reg(at_reg[plane]);
586 l &= ~(0x03 << 5);
587 l |= fir_hinc ? (1 << 5) : 0;
588 l |= fir_vinc ? (1 << 6) : 0;
589 dispc_write_reg(at_reg[plane], l);
590
591 enable_lcd_clocks(0);
592 return 0;
593}
594
595static int omap_dispc_enable_plane(int plane, int enable)
596{
597 const u32 at_reg[] = { DISPC_GFX_ATTRIBUTES,
598 DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES,
599 DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES };
600 if ((unsigned int)plane > dispc.mem_desc.region_cnt)
601 return -EINVAL;
602
603 enable_lcd_clocks(1);
604 MOD_REG_FLD(at_reg[plane], 1, enable ? 1 : 0);
605 enable_lcd_clocks(0);
606
607 return 0;
608}
609
610static int omap_dispc_set_color_key(struct omapfb_color_key *ck)
611{
612 u32 df_reg, tr_reg;
613 int shift, val;
614
615 switch (ck->channel_out) {
616 case OMAPFB_CHANNEL_OUT_LCD:
617 df_reg = DISPC_DEFAULT_COLOR0;
618 tr_reg = DISPC_TRANS_COLOR0;
619 shift = 10;
620 break;
621 case OMAPFB_CHANNEL_OUT_DIGIT:
622 df_reg = DISPC_DEFAULT_COLOR1;
623 tr_reg = DISPC_TRANS_COLOR1;
624 shift = 12;
625 break;
626 default:
627 return -EINVAL;
628 }
629 switch (ck->key_type) {
630 case OMAPFB_COLOR_KEY_DISABLED:
631 val = 0;
632 break;
633 case OMAPFB_COLOR_KEY_GFX_DST:
634 val = 1;
635 break;
636 case OMAPFB_COLOR_KEY_VID_SRC:
637 val = 3;
638 break;
639 default:
640 return -EINVAL;
641 }
642 enable_lcd_clocks(1);
643 MOD_REG_FLD(DISPC_CONFIG, FLD_MASK(shift, 2), val << shift);
644
645 if (val != 0)
646 dispc_write_reg(tr_reg, ck->trans_key);
647 dispc_write_reg(df_reg, ck->background);
648 enable_lcd_clocks(0);
649
650 dispc.color_key = *ck;
651
652 return 0;
653}
654
655static int omap_dispc_get_color_key(struct omapfb_color_key *ck)
656{
657 *ck = dispc.color_key;
658 return 0;
659}
660
661static void load_palette(void)
662{
663}
664
665static int omap_dispc_set_update_mode(enum omapfb_update_mode mode)
666{
667 int r = 0;
668
669 if (mode != dispc.update_mode) {
670 switch (mode) {
671 case OMAPFB_AUTO_UPDATE:
672 case OMAPFB_MANUAL_UPDATE:
673 enable_lcd_clocks(1);
674 omap_dispc_enable_lcd_out(1);
675 dispc.update_mode = mode;
676 break;
677 case OMAPFB_UPDATE_DISABLED:
678 init_completion(&dispc.frame_done);
679 omap_dispc_enable_lcd_out(0);
680 if (!wait_for_completion_timeout(&dispc.frame_done,
681 msecs_to_jiffies(500))) {
682 dev_err(dispc.fbdev->dev,
683 "timeout waiting for FRAME DONE\n");
684 }
685 dispc.update_mode = mode;
686 enable_lcd_clocks(0);
687 break;
688 default:
689 r = -EINVAL;
690 }
691 }
692
693 return r;
694}
695
696static void omap_dispc_get_caps(int plane, struct omapfb_caps *caps)
697{
698 caps->ctrl |= OMAPFB_CAPS_PLANE_RELOCATE_MEM;
699 if (plane > 0)
700 caps->ctrl |= OMAPFB_CAPS_PLANE_SCALE;
701 caps->plane_color |= (1 << OMAPFB_COLOR_RGB565) |
702 (1 << OMAPFB_COLOR_YUV422) |
703 (1 << OMAPFB_COLOR_YUY422);
704 if (plane == 0)
705 caps->plane_color |= (1 << OMAPFB_COLOR_CLUT_8BPP) |
706 (1 << OMAPFB_COLOR_CLUT_4BPP) |
707 (1 << OMAPFB_COLOR_CLUT_2BPP) |
708 (1 << OMAPFB_COLOR_CLUT_1BPP) |
709 (1 << OMAPFB_COLOR_RGB444);
710}
711
712static enum omapfb_update_mode omap_dispc_get_update_mode(void)
713{
714 return dispc.update_mode;
715}
716
717static void setup_color_conv_coef(void)
718{
719 u32 mask = FLD_MASK(16, 11) | FLD_MASK(0, 11);
720 int cf1_reg = DISPC_VID1_BASE + DISPC_VID_CONV_COEF0;
721 int cf2_reg = DISPC_VID2_BASE + DISPC_VID_CONV_COEF0;
722 int at1_reg = DISPC_VID1_BASE + DISPC_VID_ATTRIBUTES;
723 int at2_reg = DISPC_VID2_BASE + DISPC_VID_ATTRIBUTES;
724 const struct color_conv_coef {
725 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
726 int full_range;
727 } ctbl_bt601_5 = {
728 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
729 };
730 const struct color_conv_coef *ct;
731#define CVAL(x, y) (((x & 2047) << 16) | (y & 2047))
732
733 ct = &ctbl_bt601_5;
734
735 MOD_REG_FLD(cf1_reg, mask, CVAL(ct->rcr, ct->ry));
736 MOD_REG_FLD(cf1_reg + 4, mask, CVAL(ct->gy, ct->rcb));
737 MOD_REG_FLD(cf1_reg + 8, mask, CVAL(ct->gcb, ct->gcr));
738 MOD_REG_FLD(cf1_reg + 12, mask, CVAL(ct->bcr, ct->by));
739 MOD_REG_FLD(cf1_reg + 16, mask, CVAL(0, ct->bcb));
740
741 MOD_REG_FLD(cf2_reg, mask, CVAL(ct->rcr, ct->ry));
742 MOD_REG_FLD(cf2_reg + 4, mask, CVAL(ct->gy, ct->rcb));
743 MOD_REG_FLD(cf2_reg + 8, mask, CVAL(ct->gcb, ct->gcr));
744 MOD_REG_FLD(cf2_reg + 12, mask, CVAL(ct->bcr, ct->by));
745 MOD_REG_FLD(cf2_reg + 16, mask, CVAL(0, ct->bcb));
746#undef CVAL
747
748 MOD_REG_FLD(at1_reg, (1 << 11), ct->full_range);
749 MOD_REG_FLD(at2_reg, (1 << 11), ct->full_range);
750}
751
752static void calc_ck_div(int is_tft, int pck, int *lck_div, int *pck_div)
753{
754 unsigned long fck, lck;
755
756 *lck_div = 1;
757 pck = max(1, pck);
758 fck = clk_get_rate(dispc.dss1_fck);
759 lck = fck;
760 *pck_div = (lck + pck - 1) / pck;
761 if (is_tft)
762 *pck_div = max(2, *pck_div);
763 else
764 *pck_div = max(3, *pck_div);
765 if (*pck_div > 255) {
766 *pck_div = 255;
767 lck = pck * *pck_div;
768 *lck_div = fck / lck;
769 BUG_ON(*lck_div < 1);
770 if (*lck_div > 255) {
771 *lck_div = 255;
772 dev_warn(dispc.fbdev->dev, "pixclock %d kHz too low.\n",
773 pck / 1000);
774 }
775 }
776}
777
778static void set_lcd_tft_mode(int enable)
779{
780 u32 mask;
781
782 mask = 1 << 3;
783 MOD_REG_FLD(DISPC_CONTROL, mask, enable ? mask : 0);
784}
785
786static void set_lcd_timings(void)
787{
788 u32 l;
789 int lck_div, pck_div;
790 struct lcd_panel *panel = dispc.fbdev->panel;
791 int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;
792 unsigned long fck;
793
794 l = dispc_read_reg(DISPC_TIMING_H);
795 l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
796 l |= ( max(1, (min(64, panel->hsw))) - 1 ) << 0;
797 l |= ( max(1, (min(256, panel->hfp))) - 1 ) << 8;
798 l |= ( max(1, (min(256, panel->hbp))) - 1 ) << 20;
799 dispc_write_reg(DISPC_TIMING_H, l);
800
801 l = dispc_read_reg(DISPC_TIMING_V);
802 l &= ~(FLD_MASK(0, 6) | FLD_MASK(8, 8) | FLD_MASK(20, 8));
803 l |= ( max(1, (min(64, panel->vsw))) - 1 ) << 0;
804 l |= ( max(0, (min(255, panel->vfp))) - 0 ) << 8;
805 l |= ( max(0, (min(255, panel->vbp))) - 0 ) << 20;
806 dispc_write_reg(DISPC_TIMING_V, l);
807
808 l = dispc_read_reg(DISPC_POL_FREQ);
809 l &= ~FLD_MASK(12, 6);
810 l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 12;
811 l |= panel->acb & 0xff;
812 dispc_write_reg(DISPC_POL_FREQ, l);
813
814 calc_ck_div(is_tft, panel->pixel_clock * 1000, &lck_div, &pck_div);
815
816 l = dispc_read_reg(DISPC_DIVISOR);
817 l &= ~(FLD_MASK(16, 8) | FLD_MASK(0, 8));
818 l |= (lck_div << 16) | (pck_div << 0);
819 dispc_write_reg(DISPC_DIVISOR, l);
820
821 /* update panel info with the exact clock */
822 fck = clk_get_rate(dispc.dss1_fck);
823 panel->pixel_clock = fck / lck_div / pck_div / 1000;
824}
825
826static void recalc_irq_mask(void)
827{
828 int i;
829 unsigned long irq_mask = DISPC_IRQ_MASK_ERROR;
830
831 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
832 if (!dispc.irq_handlers[i].callback)
833 continue;
834
835 irq_mask |= dispc.irq_handlers[i].irq_mask;
836 }
837
838 enable_lcd_clocks(1);
839 MOD_REG_FLD(DISPC_IRQENABLE, 0x7fff, irq_mask);
840 enable_lcd_clocks(0);
841}
842
843int omap_dispc_request_irq(unsigned long irq_mask, void (*callback)(void *data),
844 void *data)
845{
846 int i;
847
848 BUG_ON(callback == NULL);
849
850 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
851 if (dispc.irq_handlers[i].callback)
852 continue;
853
854 dispc.irq_handlers[i].irq_mask = irq_mask;
855 dispc.irq_handlers[i].callback = callback;
856 dispc.irq_handlers[i].data = data;
857 recalc_irq_mask();
858
859 return 0;
860 }
861
862 return -EBUSY;
863}
864EXPORT_SYMBOL(omap_dispc_request_irq);
865
866void omap_dispc_free_irq(unsigned long irq_mask, void (*callback)(void *data),
867 void *data)
868{
869 int i;
870
871 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
872 if (dispc.irq_handlers[i].callback == callback &&
873 dispc.irq_handlers[i].data == data) {
874 dispc.irq_handlers[i].irq_mask = 0;
875 dispc.irq_handlers[i].callback = NULL;
876 dispc.irq_handlers[i].data = NULL;
877 recalc_irq_mask();
878 return;
879 }
880 }
881
882 BUG();
883}
884EXPORT_SYMBOL(omap_dispc_free_irq);
885
886static irqreturn_t omap_dispc_irq_handler(int irq, void *dev)
887{
888 u32 stat;
889 int i = 0;
890
891 enable_lcd_clocks(1);
892
893 stat = dispc_read_reg(DISPC_IRQSTATUS);
894 if (stat & DISPC_IRQ_FRAMEMASK)
895 complete(&dispc.frame_done);
896
897 if (stat & DISPC_IRQ_MASK_ERROR) {
898 if (printk_ratelimit()) {
899 dev_err(dispc.fbdev->dev, "irq error status %04x\n",
900 stat & 0x7fff);
901 }
902 }
903
904 for (i = 0; i < MAX_IRQ_HANDLERS; i++) {
905 if (unlikely(dispc.irq_handlers[i].callback &&
906 (stat & dispc.irq_handlers[i].irq_mask)))
907 dispc.irq_handlers[i].callback(
908 dispc.irq_handlers[i].data);
909 }
910
911 dispc_write_reg(DISPC_IRQSTATUS, stat);
912
913 enable_lcd_clocks(0);
914
915 return IRQ_HANDLED;
916}
917
918static int get_dss_clocks(void)
919{
920 dispc.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick");
921 if (IS_ERR(dispc.dss_ick)) {
922 dev_err(dispc.fbdev->dev, "can't get ick\n");
923 return PTR_ERR(dispc.dss_ick);
924 }
925
926 dispc.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "fck");
927 if (IS_ERR(dispc.dss1_fck)) {
928 dev_err(dispc.fbdev->dev, "can't get dss1_fck\n");
929 clk_put(dispc.dss_ick);
930 return PTR_ERR(dispc.dss1_fck);
931 }
932
933 dispc.dss_54m_fck = clk_get(&dispc.fbdev->dssdev->dev, "tv_clk");
934 if (IS_ERR(dispc.dss_54m_fck)) {
935 dev_err(dispc.fbdev->dev, "can't get tv_fck\n");
936 clk_put(dispc.dss_ick);
937 clk_put(dispc.dss1_fck);
938 return PTR_ERR(dispc.dss_54m_fck);
939 }
940
941 return 0;
942}
943
944static void put_dss_clocks(void)
945{
946 clk_put(dispc.dss_54m_fck);
947 clk_put(dispc.dss1_fck);
948 clk_put(dispc.dss_ick);
949}
950
951static void enable_lcd_clocks(int enable)
952{
953 if (enable) {
954 clk_enable(dispc.dss_ick);
955 clk_enable(dispc.dss1_fck);
956 } else {
957 clk_disable(dispc.dss1_fck);
958 clk_disable(dispc.dss_ick);
959 }
960}
961
962static void enable_digit_clocks(int enable)
963{
964 if (enable)
965 clk_enable(dispc.dss_54m_fck);
966 else
967 clk_disable(dispc.dss_54m_fck);
968}
969
970static void omap_dispc_suspend(void)
971{
972 if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
973 init_completion(&dispc.frame_done);
974 omap_dispc_enable_lcd_out(0);
975 if (!wait_for_completion_timeout(&dispc.frame_done,
976 msecs_to_jiffies(500))) {
977 dev_err(dispc.fbdev->dev,
978 "timeout waiting for FRAME DONE\n");
979 }
980 enable_lcd_clocks(0);
981 }
982}
983
984static void omap_dispc_resume(void)
985{
986 if (dispc.update_mode == OMAPFB_AUTO_UPDATE) {
987 enable_lcd_clocks(1);
988 if (!dispc.ext_mode) {
989 set_lcd_timings();
990 load_palette();
991 }
992 omap_dispc_enable_lcd_out(1);
993 }
994}
995
996
997static int omap_dispc_update_window(struct fb_info *fbi,
998 struct omapfb_update_window *win,
999 void (*complete_callback)(void *arg),
1000 void *complete_callback_data)
1001{
1002 return dispc.update_mode == OMAPFB_UPDATE_DISABLED ? -ENODEV : 0;
1003}
1004
1005static int mmap_kern(struct omapfb_mem_region *region)
1006{
1007 struct vm_struct *kvma;
1008 struct vm_area_struct vma;
1009 pgprot_t pgprot;
1010 unsigned long vaddr;
1011
1012 kvma = get_vm_area(region->size, VM_IOREMAP);
1013 if (kvma == NULL) {
1014 dev_err(dispc.fbdev->dev, "can't get kernel vm area\n");
1015 return -ENOMEM;
1016 }
1017 vma.vm_mm = &init_mm;
1018
1019 vaddr = (unsigned long)kvma->addr;
1020
1021 pgprot = pgprot_writecombine(pgprot_kernel);
1022 vma.vm_start = vaddr;
1023 vma.vm_end = vaddr + region->size;
1024 if (io_remap_pfn_range(&vma, vaddr, region->paddr >> PAGE_SHIFT,
1025 region->size, pgprot) < 0) {
1026 dev_err(dispc.fbdev->dev, "kernel mmap for FBMEM failed\n");
1027 return -EAGAIN;
1028 }
1029 region->vaddr = (void *)vaddr;
1030
1031 return 0;
1032}
1033
1034static void mmap_user_open(struct vm_area_struct *vma)
1035{
1036 int plane = (int)vma->vm_private_data;
1037
1038 atomic_inc(&dispc.map_count[plane]);
1039}
1040
1041static void mmap_user_close(struct vm_area_struct *vma)
1042{
1043 int plane = (int)vma->vm_private_data;
1044
1045 atomic_dec(&dispc.map_count[plane]);
1046}
1047
1048static const struct vm_operations_struct mmap_user_ops = {
1049 .open = mmap_user_open,
1050 .close = mmap_user_close,
1051};
1052
1053static int omap_dispc_mmap_user(struct fb_info *info,
1054 struct vm_area_struct *vma)
1055{
1056 struct omapfb_plane_struct *plane = info->par;
1057 unsigned long off;
1058 unsigned long start;
1059 u32 len;
1060
1061 if (vma->vm_end - vma->vm_start == 0)
1062 return 0;
1063 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1064 return -EINVAL;
1065 off = vma->vm_pgoff << PAGE_SHIFT;
1066
1067 start = info->fix.smem_start;
1068 len = info->fix.smem_len;
1069 if (off >= len)
1070 return -EINVAL;
1071 if ((vma->vm_end - vma->vm_start + off) > len)
1072 return -EINVAL;
1073 off += start;
1074 vma->vm_pgoff = off >> PAGE_SHIFT;
1075 vma->vm_flags |= VM_IO | VM_RESERVED;
1076 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1077 vma->vm_ops = &mmap_user_ops;
1078 vma->vm_private_data = (void *)plane->idx;
1079 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
1080 vma->vm_end - vma->vm_start, vma->vm_page_prot))
1081 return -EAGAIN;
1082 /* vm_ops.open won't be called for mmap itself. */
1083 atomic_inc(&dispc.map_count[plane->idx]);
1084 return 0;
1085}
1086
1087static void unmap_kern(struct omapfb_mem_region *region)
1088{
1089 vunmap(region->vaddr);
1090}
1091
1092static int alloc_palette_ram(void)
1093{
1094 dispc.palette_vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
1095 MAX_PALETTE_SIZE, &dispc.palette_paddr, GFP_KERNEL);
1096 if (dispc.palette_vaddr == NULL) {
1097 dev_err(dispc.fbdev->dev, "failed to alloc palette memory\n");
1098 return -ENOMEM;
1099 }
1100
1101 return 0;
1102}
1103
1104static void free_palette_ram(void)
1105{
1106 dma_free_writecombine(dispc.fbdev->dev, MAX_PALETTE_SIZE,
1107 dispc.palette_vaddr, dispc.palette_paddr);
1108}
1109
1110static int alloc_fbmem(struct omapfb_mem_region *region)
1111{
1112 region->vaddr = dma_alloc_writecombine(dispc.fbdev->dev,
1113 region->size, &region->paddr, GFP_KERNEL);
1114
1115 if (region->vaddr == NULL) {
1116 dev_err(dispc.fbdev->dev, "unable to allocate FB DMA memory\n");
1117 return -ENOMEM;
1118 }
1119
1120 return 0;
1121}
1122
1123static void free_fbmem(struct omapfb_mem_region *region)
1124{
1125 dma_free_writecombine(dispc.fbdev->dev, region->size,
1126 region->vaddr, region->paddr);
1127}
1128
1129static struct resmap *init_resmap(unsigned long start, size_t size)
1130{
1131 unsigned page_cnt;
1132 struct resmap *res_map;
1133
1134 page_cnt = PAGE_ALIGN(size) / PAGE_SIZE;
1135 res_map =
1136 kzalloc(sizeof(struct resmap) + RESMAP_SIZE(page_cnt), GFP_KERNEL);
1137 if (res_map == NULL)
1138 return NULL;
1139 res_map->start = start;
1140 res_map->page_cnt = page_cnt;
1141 res_map->map = (unsigned long *)(res_map + 1);
1142 return res_map;
1143}
1144
1145static void cleanup_resmap(struct resmap *res_map)
1146{
1147 kfree(res_map);
1148}
1149
1150static inline int resmap_mem_type(unsigned long start)
1151{
1152 if (start >= OMAP2_SRAM_START &&
1153 start < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
1154 return OMAPFB_MEMTYPE_SRAM;
1155 else
1156 return OMAPFB_MEMTYPE_SDRAM;
1157}
1158
1159static inline int resmap_page_reserved(struct resmap *res_map, unsigned page_nr)
1160{
1161 return *RESMAP_PTR(res_map, page_nr) & RESMAP_MASK(page_nr) ? 1 : 0;
1162}
1163
1164static inline void resmap_reserve_page(struct resmap *res_map, unsigned page_nr)
1165{
1166 BUG_ON(resmap_page_reserved(res_map, page_nr));
1167 *RESMAP_PTR(res_map, page_nr) |= RESMAP_MASK(page_nr);
1168}
1169
1170static inline void resmap_free_page(struct resmap *res_map, unsigned page_nr)
1171{
1172 BUG_ON(!resmap_page_reserved(res_map, page_nr));
1173 *RESMAP_PTR(res_map, page_nr) &= ~RESMAP_MASK(page_nr);
1174}
1175
1176static void resmap_reserve_region(unsigned long start, size_t size)
1177{
1178
1179 struct resmap *res_map;
1180 unsigned start_page;
1181 unsigned end_page;
1182 int mtype;
1183 unsigned i;
1184
1185 mtype = resmap_mem_type(start);
1186 res_map = dispc.res_map[mtype];
1187 dev_dbg(dispc.fbdev->dev, "reserve mem type %d start %08lx size %d\n",
1188 mtype, start, size);
1189 start_page = (start - res_map->start) / PAGE_SIZE;
1190 end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE;
1191 for (i = start_page; i < end_page; i++)
1192 resmap_reserve_page(res_map, i);
1193}
1194
1195static void resmap_free_region(unsigned long start, size_t size)
1196{
1197 struct resmap *res_map;
1198 unsigned start_page;
1199 unsigned end_page;
1200 unsigned i;
1201 int mtype;
1202
1203 mtype = resmap_mem_type(start);
1204 res_map = dispc.res_map[mtype];
1205 dev_dbg(dispc.fbdev->dev, "free mem type %d start %08lx size %d\n",
1206 mtype, start, size);
1207 start_page = (start - res_map->start) / PAGE_SIZE;
1208 end_page = start_page + PAGE_ALIGN(size) / PAGE_SIZE;
1209 for (i = start_page; i < end_page; i++)
1210 resmap_free_page(res_map, i);
1211}
1212
1213static unsigned long resmap_alloc_region(int mtype, size_t size)
1214{
1215 unsigned i;
1216 unsigned total;
1217 unsigned start_page;
1218 unsigned long start;
1219 struct resmap *res_map = dispc.res_map[mtype];
1220
1221 BUG_ON(mtype >= DISPC_MEMTYPE_NUM || res_map == NULL || !size);
1222
1223 size = PAGE_ALIGN(size) / PAGE_SIZE;
1224 start_page = 0;
1225 total = 0;
1226 for (i = 0; i < res_map->page_cnt; i++) {
1227 if (resmap_page_reserved(res_map, i)) {
1228 start_page = i + 1;
1229 total = 0;
1230 } else if (++total == size)
1231 break;
1232 }
1233 if (total < size)
1234 return 0;
1235
1236 start = res_map->start + start_page * PAGE_SIZE;
1237 resmap_reserve_region(start, size * PAGE_SIZE);
1238
1239 return start;
1240}
1241
1242/* Note that this will only work for user mappings, we don't deal with
1243 * kernel mappings here, so fbcon will keep using the old region.
1244 */
1245static int omap_dispc_setup_mem(int plane, size_t size, int mem_type,
1246 unsigned long *paddr)
1247{
1248 struct omapfb_mem_region *rg;
1249 unsigned long new_addr = 0;
1250
1251 if ((unsigned)plane > dispc.mem_desc.region_cnt)
1252 return -EINVAL;
1253 if (mem_type >= DISPC_MEMTYPE_NUM)
1254 return -EINVAL;
1255 if (dispc.res_map[mem_type] == NULL)
1256 return -ENOMEM;
1257 rg = &dispc.mem_desc.region[plane];
1258 if (size == rg->size && mem_type == rg->type)
1259 return 0;
1260 if (atomic_read(&dispc.map_count[plane]))
1261 return -EBUSY;
1262 if (rg->size != 0)
1263 resmap_free_region(rg->paddr, rg->size);
1264 if (size != 0) {
1265 new_addr = resmap_alloc_region(mem_type, size);
1266 if (!new_addr) {
1267 /* Reallocate old region. */
1268 resmap_reserve_region(rg->paddr, rg->size);
1269 return -ENOMEM;
1270 }
1271 }
1272 rg->paddr = new_addr;
1273 rg->size = size;
1274 rg->type = mem_type;
1275
1276 *paddr = new_addr;
1277
1278 return 0;
1279}
1280
1281static int setup_fbmem(struct omapfb_mem_desc *req_md)
1282{
1283 struct omapfb_mem_region *rg;
1284 int i;
1285 int r;
1286 unsigned long mem_start[DISPC_MEMTYPE_NUM];
1287 unsigned long mem_end[DISPC_MEMTYPE_NUM];
1288
1289 if (!req_md->region_cnt) {
1290 dev_err(dispc.fbdev->dev, "no memory regions defined\n");
1291 return -ENOENT;
1292 }
1293
1294 rg = &req_md->region[0];
1295 memset(mem_start, 0xff, sizeof(mem_start));
1296 memset(mem_end, 0, sizeof(mem_end));
1297
1298 for (i = 0; i < req_md->region_cnt; i++, rg++) {
1299 int mtype;
1300 if (rg->paddr) {
1301 rg->alloc = 0;
1302 if (rg->vaddr == NULL) {
1303 rg->map = 1;
1304 if ((r = mmap_kern(rg)) < 0)
1305 return r;
1306 }
1307 } else {
1308 if (rg->type != OMAPFB_MEMTYPE_SDRAM) {
1309 dev_err(dispc.fbdev->dev,
1310 "unsupported memory type\n");
1311 return -EINVAL;
1312 }
1313 rg->alloc = rg->map = 1;
1314 if ((r = alloc_fbmem(rg)) < 0)
1315 return r;
1316 }
1317 mtype = rg->type;
1318
1319 if (rg->paddr < mem_start[mtype])
1320 mem_start[mtype] = rg->paddr;
1321 if (rg->paddr + rg->size > mem_end[mtype])
1322 mem_end[mtype] = rg->paddr + rg->size;
1323 }
1324
1325 for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
1326 unsigned long start;
1327 size_t size;
1328 if (mem_end[i] == 0)
1329 continue;
1330 start = mem_start[i];
1331 size = mem_end[i] - start;
1332 dispc.res_map[i] = init_resmap(start, size);
1333 r = -ENOMEM;
1334 if (dispc.res_map[i] == NULL)
1335 goto fail;
1336 /* Initial state is that everything is reserved. This
1337 * includes possible holes as well, which will never be
1338 * freed.
1339 */
1340 resmap_reserve_region(start, size);
1341 }
1342
1343 dispc.mem_desc = *req_md;
1344
1345 return 0;
1346fail:
1347 for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
1348 if (dispc.res_map[i] != NULL)
1349 cleanup_resmap(dispc.res_map[i]);
1350 }
1351 return r;
1352}
1353
1354static void cleanup_fbmem(void)
1355{
1356 struct omapfb_mem_region *rg;
1357 int i;
1358
1359 for (i = 0; i < DISPC_MEMTYPE_NUM; i++) {
1360 if (dispc.res_map[i] != NULL)
1361 cleanup_resmap(dispc.res_map[i]);
1362 }
1363 rg = &dispc.mem_desc.region[0];
1364 for (i = 0; i < dispc.mem_desc.region_cnt; i++, rg++) {
1365 if (rg->alloc)
1366 free_fbmem(rg);
1367 else {
1368 if (rg->map)
1369 unmap_kern(rg);
1370 }
1371 }
1372}
1373
1374static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
1375 struct omapfb_mem_desc *req_vram)
1376{
1377 int r;
1378 u32 l;
1379 struct lcd_panel *panel = fbdev->panel;
1380 void __iomem *ram_fw_base;
1381 int tmo = 10000;
1382 int skip_init = 0;
1383 int i;
1384
1385 memset(&dispc, 0, sizeof(dispc));
1386
1387 dispc.base = ioremap(DISPC_BASE, SZ_1K);
1388 if (!dispc.base) {
1389 dev_err(fbdev->dev, "can't ioremap DISPC\n");
1390 return -ENOMEM;
1391 }
1392
1393 dispc.fbdev = fbdev;
1394 dispc.ext_mode = ext_mode;
1395
1396 init_completion(&dispc.frame_done);
1397
1398 if ((r = get_dss_clocks()) < 0)
1399 goto fail0;
1400
1401 enable_lcd_clocks(1);
1402
1403#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
1404 l = dispc_read_reg(DISPC_CONTROL);
1405 /* LCD enabled ? */
1406 if (l & 1) {
1407 pr_info("omapfb: skipping hardware initialization\n");
1408 skip_init = 1;
1409 }
1410#endif
1411
1412 if (!skip_init) {
1413 /* Reset monitoring works only w/ the 54M clk */
1414 enable_digit_clocks(1);
1415
1416 /* Soft reset */
1417 MOD_REG_FLD(DISPC_SYSCONFIG, 1 << 1, 1 << 1);
1418
1419 while (!(dispc_read_reg(DISPC_SYSSTATUS) & 1)) {
1420 if (!--tmo) {
1421 dev_err(dispc.fbdev->dev, "soft reset failed\n");
1422 r = -ENODEV;
1423 enable_digit_clocks(0);
1424 goto fail1;
1425 }
1426 }
1427
1428 enable_digit_clocks(0);
1429 }
1430
1431 /* Enable smart standby/idle, autoidle and wakeup */
1432 l = dispc_read_reg(DISPC_SYSCONFIG);
1433 l &= ~((3 << 12) | (3 << 3));
1434 l |= (2 << 12) | (2 << 3) | (1 << 2) | (1 << 0);
1435 dispc_write_reg(DISPC_SYSCONFIG, l);
1436 omap_writel(1 << 0, DSS_BASE + DSS_SYSCONFIG);
1437
1438 /* Set functional clock autogating */
1439 l = dispc_read_reg(DISPC_CONFIG);
1440 l |= 1 << 9;
1441 dispc_write_reg(DISPC_CONFIG, l);
1442
1443 l = dispc_read_reg(DISPC_IRQSTATUS);
1444 dispc_write_reg(DISPC_IRQSTATUS, l);
1445
1446 recalc_irq_mask();
1447
1448 if ((r = request_irq(INT_24XX_DSS_IRQ, omap_dispc_irq_handler,
1449 0, MODULE_NAME, fbdev)) < 0) {
1450 dev_err(dispc.fbdev->dev, "can't get DSS IRQ\n");
1451 goto fail1;
1452 }
1453
1454 /* L3 firewall setting: enable access to OCM RAM */
1455 ram_fw_base = ioremap(0x68005000, SZ_1K);
1456 if (!ram_fw_base) {
1457 dev_err(dispc.fbdev->dev, "Cannot ioremap to enable OCM RAM\n");
1458 goto fail1;
1459 }
1460 __raw_writel(0x402000b0, ram_fw_base + 0xa0);
1461 iounmap(ram_fw_base);
1462
1463 if ((r = alloc_palette_ram()) < 0)
1464 goto fail2;
1465
1466 if ((r = setup_fbmem(req_vram)) < 0)
1467 goto fail3;
1468
1469 if (!skip_init) {
1470 for (i = 0; i < dispc.mem_desc.region_cnt; i++) {
1471 memset(dispc.mem_desc.region[i].vaddr, 0,
1472 dispc.mem_desc.region[i].size);
1473 }
1474
1475 /* Set logic clock to fck, pixel clock to fck/2 for now */
1476 MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(16, 8), 1 << 16);
1477 MOD_REG_FLD(DISPC_DIVISOR, FLD_MASK(0, 8), 2 << 0);
1478
1479 setup_plane_fifo(0, ext_mode);
1480 setup_plane_fifo(1, ext_mode);
1481 setup_plane_fifo(2, ext_mode);
1482
1483 setup_color_conv_coef();
1484
1485 set_lcd_tft_mode(panel->config & OMAP_LCDC_PANEL_TFT);
1486 set_load_mode(DISPC_LOAD_FRAME_ONLY);
1487
1488 if (!ext_mode) {
1489 set_lcd_data_lines(panel->data_lines);
1490 omap_dispc_set_lcd_size(panel->x_res, panel->y_res);
1491 set_lcd_timings();
1492 } else
1493 set_lcd_data_lines(panel->bpp);
1494 enable_rfbi_mode(ext_mode);
1495 }
1496
1497 l = dispc_read_reg(DISPC_REVISION);
1498 pr_info("omapfb: DISPC version %d.%d initialized\n",
1499 l >> 4 & 0x0f, l & 0x0f);
1500 enable_lcd_clocks(0);
1501
1502 return 0;
1503fail3:
1504 free_palette_ram();
1505fail2:
1506 free_irq(INT_24XX_DSS_IRQ, fbdev);
1507fail1:
1508 enable_lcd_clocks(0);
1509 put_dss_clocks();
1510fail0:
1511 iounmap(dispc.base);
1512 return r;
1513}
1514
1515static void omap_dispc_cleanup(void)
1516{
1517 int i;
1518
1519 omap_dispc_set_update_mode(OMAPFB_UPDATE_DISABLED);
1520 /* This will also disable clocks that are on */
1521 for (i = 0; i < dispc.mem_desc.region_cnt; i++)
1522 omap_dispc_enable_plane(i, 0);
1523 cleanup_fbmem();
1524 free_palette_ram();
1525 free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
1526 put_dss_clocks();
1527 iounmap(dispc.base);
1528}
1529
1530const struct lcd_ctrl omap2_int_ctrl = {
1531 .name = "internal",
1532 .init = omap_dispc_init,
1533 .cleanup = omap_dispc_cleanup,
1534 .get_caps = omap_dispc_get_caps,
1535 .set_update_mode = omap_dispc_set_update_mode,
1536 .get_update_mode = omap_dispc_get_update_mode,
1537 .update_window = omap_dispc_update_window,
1538 .suspend = omap_dispc_suspend,
1539 .resume = omap_dispc_resume,
1540 .setup_plane = omap_dispc_setup_plane,
1541 .setup_mem = omap_dispc_setup_mem,
1542 .set_scale = omap_dispc_set_scale,
1543 .enable_plane = omap_dispc_enable_plane,
1544 .set_color_key = omap_dispc_set_color_key,
1545 .get_color_key = omap_dispc_get_color_key,
1546 .mmap = omap_dispc_mmap_user,
1547};
diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h
deleted file mode 100644
index c15ea77f0604..000000000000
--- a/drivers/video/omap/dispc.h
+++ /dev/null
@@ -1,46 +0,0 @@
1#ifndef _DISPC_H
2#define _DISPC_H
3
4#include <linux/interrupt.h>
5
6#define DISPC_PLANE_GFX 0
7#define DISPC_PLANE_VID1 1
8#define DISPC_PLANE_VID2 2
9
10#define DISPC_RGB_1_BPP 0x00
11#define DISPC_RGB_2_BPP 0x01
12#define DISPC_RGB_4_BPP 0x02
13#define DISPC_RGB_8_BPP 0x03
14#define DISPC_RGB_12_BPP 0x04
15#define DISPC_RGB_16_BPP 0x06
16#define DISPC_RGB_24_BPP 0x08
17#define DISPC_RGB_24_BPP_UNPACK_32 0x09
18#define DISPC_YUV2_422 0x0a
19#define DISPC_UYVY_422 0x0b
20
21#define DISPC_BURST_4x32 0
22#define DISPC_BURST_8x32 1
23#define DISPC_BURST_16x32 2
24
25#define DISPC_LOAD_CLUT_AND_FRAME 0x00
26#define DISPC_LOAD_CLUT_ONLY 0x01
27#define DISPC_LOAD_FRAME_ONLY 0x02
28#define DISPC_LOAD_CLUT_ONCE_FRAME 0x03
29
30#define DISPC_TFT_DATA_LINES_12 0
31#define DISPC_TFT_DATA_LINES_16 1
32#define DISPC_TFT_DATA_LINES_18 2
33#define DISPC_TFT_DATA_LINES_24 3
34
35extern void omap_dispc_set_lcd_size(int width, int height);
36
37extern void omap_dispc_enable_lcd_out(int enable);
38extern void omap_dispc_enable_digit_out(int enable);
39
40extern int omap_dispc_request_irq(unsigned long irq_mask,
41 void (*callback)(void *data), void *data);
42extern void omap_dispc_free_irq(unsigned long irq_mask,
43 void (*callback)(void *data), void *data);
44
45extern const struct lcd_ctrl omap2_int_ctrl;
46#endif
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
index 084aa0ac562b..9f1d23c319cb 100644
--- a/drivers/video/omap/hwa742.c
+++ b/drivers/video/omap/hwa742.c
@@ -28,7 +28,6 @@
28#include <linux/interrupt.h> 28#include <linux/interrupt.h>
29 29
30#include <plat/dma.h> 30#include <plat/dma.h>
31#include <plat/hwa742.h>
32#include "omapfb.h" 31#include "omapfb.h"
33 32
34#define HWA742_REV_CODE_REG 0x0 33#define HWA742_REV_CODE_REG 0x0
@@ -942,7 +941,6 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
942 unsigned long sys_clk, pix_clk; 941 unsigned long sys_clk, pix_clk;
943 int extif_mem_div; 942 int extif_mem_div;
944 struct omapfb_platform_data *omapfb_conf; 943 struct omapfb_platform_data *omapfb_conf;
945 struct hwa742_platform_data *ctrl_conf;
946 944
947 BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl); 945 BUG_ON(!fbdev->ext_if || !fbdev->int_ctrl);
948 946
@@ -951,13 +949,6 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
951 hwa742.int_ctrl = fbdev->int_ctrl; 949 hwa742.int_ctrl = fbdev->int_ctrl;
952 950
953 omapfb_conf = fbdev->dev->platform_data; 951 omapfb_conf = fbdev->dev->platform_data;
954 ctrl_conf = omapfb_conf->ctrl_platform_data;
955
956 if (ctrl_conf == NULL) {
957 dev_err(fbdev->dev, "HWA742: missing platform data\n");
958 r = -ENOENT;
959 goto err1;
960 }
961 952
962 hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck"); 953 hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck");
963 954
@@ -995,14 +986,12 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
995 goto err4; 986 goto err4;
996 } 987 }
997 988
998 if (ctrl_conf->te_connected) { 989 if ((r = setup_tearsync(pix_clk, extif_mem_div)) < 0) {
999 if ((r = setup_tearsync(pix_clk, extif_mem_div)) < 0) { 990 dev_err(hwa742.fbdev->dev,
1000 dev_err(hwa742.fbdev->dev, 991 "HWA742: can't setup tearing synchronization\n");
1001 "HWA742: can't setup tearing synchronization\n"); 992 goto err4;
1002 goto err4;
1003 }
1004 hwa742.te_connected = 1;
1005 } 993 }
994 hwa742.te_connected = 1;
1006 995
1007 hwa742.max_transmit_size = hwa742.extif->max_transmit_size; 996 hwa742.max_transmit_size = hwa742.extif->max_transmit_size;
1008 997
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
index 7e8bd8e08a98..e3d3d135aa48 100644
--- a/drivers/video/omap/lcd_inn1610.c
+++ b/drivers/video/omap/lcd_inn1610.c
@@ -22,7 +22,7 @@
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24 24
25#include <asm/gpio.h> 25#include <linux/gpio.h>
26#include "omapfb.h" 26#include "omapfb.h"
27 27
28#define MODULE_NAME "omapfb-lcd_h3" 28#define MODULE_NAME "omapfb-lcd_h3"
@@ -32,20 +32,18 @@ static int innovator1610_panel_init(struct lcd_panel *panel,
32{ 32{
33 int r = 0; 33 int r = 0;
34 34
35 if (gpio_request(14, "lcd_en0")) { 35 /* configure GPIO(14, 15) as outputs */
36 if (gpio_request_one(14, GPIOF_OUT_INIT_LOW, "lcd_en0")) {
36 pr_err(MODULE_NAME ": can't request GPIO 14\n"); 37 pr_err(MODULE_NAME ": can't request GPIO 14\n");
37 r = -1; 38 r = -1;
38 goto exit; 39 goto exit;
39 } 40 }
40 if (gpio_request(15, "lcd_en1")) { 41 if (gpio_request_one(15, GPIOF_OUT_INIT_LOW, "lcd_en1")) {
41 pr_err(MODULE_NAME ": can't request GPIO 15\n"); 42 pr_err(MODULE_NAME ": can't request GPIO 15\n");
42 gpio_free(14); 43 gpio_free(14);
43 r = -1; 44 r = -1;
44 goto exit; 45 goto exit;
45 } 46 }
46 /* configure GPIO(14, 15) as outputs */
47 gpio_direction_output(14, 0);
48 gpio_direction_output(15, 0);
49exit: 47exit:
50 return r; 48 return r;
51} 49}
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
index 8d546dd55e81..e3880c4a0bb1 100644
--- a/drivers/video/omap/lcd_mipid.c
+++ b/drivers/video/omap/lcd_mipid.c
@@ -609,19 +609,7 @@ static struct spi_driver mipid_spi_driver = {
609 .remove = __devexit_p(mipid_spi_remove), 609 .remove = __devexit_p(mipid_spi_remove),
610}; 610};
611 611
612static int __init mipid_drv_init(void) 612module_spi_driver(mipid_spi_driver);
613{
614 spi_register_driver(&mipid_spi_driver);
615
616 return 0;
617}
618module_init(mipid_drv_init);
619
620static void __exit mipid_drv_cleanup(void)
621{
622 spi_unregister_driver(&mipid_spi_driver);
623}
624module_exit(mipid_drv_cleanup);
625 613
626MODULE_DESCRIPTION("MIPI display driver"); 614MODULE_DESCRIPTION("MIPI display driver");
627MODULE_LICENSE("GPL"); 615MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap/omapfb.h b/drivers/video/omap/omapfb.h
index af3c9e571ec3..2921d20e4fba 100644
--- a/drivers/video/omap/omapfb.h
+++ b/drivers/video/omap/omapfb.h
@@ -47,6 +47,27 @@
47 47
48struct omapfb_device; 48struct omapfb_device;
49 49
50#define OMAPFB_PLANE_NUM 1
51
52struct omapfb_mem_region {
53 u32 paddr;
54 void __iomem *vaddr;
55 unsigned long size;
56 u8 type; /* OMAPFB_PLANE_MEM_* */
57 enum omapfb_color_format format;/* OMAPFB_COLOR_* */
58 unsigned format_used:1; /* Must be set when format is set.
59 * Needed b/c of the badly chosen 0
60 * base for OMAPFB_COLOR_* values
61 */
62 unsigned alloc:1; /* allocated by the driver */
63 unsigned map:1; /* kernel mapped by the driver */
64};
65
66struct omapfb_mem_desc {
67 int region_cnt;
68 struct omapfb_mem_region region[OMAPFB_PLANE_NUM];
69};
70
50struct lcd_panel { 71struct lcd_panel {
51 const char *name; 72 const char *name;
52 int config; /* TFT/STN, signal inversion */ 73 int config; /* TFT/STN, signal inversion */
@@ -207,11 +228,7 @@ struct omapfb_device {
207 struct platform_device *dssdev; /* dummy dev for clocks */ 228 struct platform_device *dssdev; /* dummy dev for clocks */
208}; 229};
209 230
210#ifdef CONFIG_ARCH_OMAP1
211extern struct lcd_ctrl omap1_lcd_ctrl; 231extern struct lcd_ctrl omap1_lcd_ctrl;
212#else
213extern struct lcd_ctrl omap2_disp_ctrl;
214#endif
215 232
216extern void omapfb_register_panel(struct lcd_panel *panel); 233extern void omapfb_register_panel(struct lcd_panel *panel);
217extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); 234extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index b291bfaac80e..f54b463709e9 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -34,7 +34,6 @@
34 34
35#include "omapfb.h" 35#include "omapfb.h"
36#include "lcdc.h" 36#include "lcdc.h"
37#include "dispc.h"
38 37
39#define MODULE_NAME "omapfb" 38#define MODULE_NAME "omapfb"
40 39
@@ -104,29 +103,17 @@ static struct platform_device omapdss_device = {
104 * --------------------------------------------------------------------------- 103 * ---------------------------------------------------------------------------
105 */ 104 */
106extern struct lcd_ctrl hwa742_ctrl; 105extern struct lcd_ctrl hwa742_ctrl;
107extern struct lcd_ctrl blizzard_ctrl;
108 106
109static const struct lcd_ctrl *ctrls[] = { 107static const struct lcd_ctrl *ctrls[] = {
110#ifdef CONFIG_ARCH_OMAP1
111 &omap1_int_ctrl, 108 &omap1_int_ctrl,
112#else
113 &omap2_int_ctrl,
114#endif
115 109
116#ifdef CONFIG_FB_OMAP_LCDC_HWA742 110#ifdef CONFIG_FB_OMAP_LCDC_HWA742
117 &hwa742_ctrl, 111 &hwa742_ctrl,
118#endif 112#endif
119#ifdef CONFIG_FB_OMAP_LCDC_BLIZZARD
120 &blizzard_ctrl,
121#endif
122}; 113};
123 114
124#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL 115#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
125#ifdef CONFIG_ARCH_OMAP1
126extern struct lcd_ctrl_extif omap1_ext_if; 116extern struct lcd_ctrl_extif omap1_ext_if;
127#else
128extern struct lcd_ctrl_extif omap2_ext_if;
129#endif
130#endif 117#endif
131 118
132static void omapfb_rqueue_lock(struct omapfb_device *fbdev) 119static void omapfb_rqueue_lock(struct omapfb_device *fbdev)
@@ -170,11 +157,6 @@ static int ctrl_init(struct omapfb_device *fbdev)
170 fbdev->mem_desc.region[i].size = 157 fbdev->mem_desc.region[i].size =
171 PAGE_ALIGN(def_vram[i]); 158 PAGE_ALIGN(def_vram[i]);
172 fbdev->mem_desc.region_cnt = i; 159 fbdev->mem_desc.region_cnt = i;
173 } else {
174 struct omapfb_platform_data *conf;
175
176 conf = fbdev->dev->platform_data;
177 fbdev->mem_desc = conf->mem_desc;
178 } 160 }
179 161
180 if (!fbdev->mem_desc.region_cnt) { 162 if (!fbdev->mem_desc.region_cnt) {
@@ -880,7 +862,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
880 862
881 if (fbdev->ctrl->setup_mem == NULL) 863 if (fbdev->ctrl->setup_mem == NULL)
882 return -ENODEV; 864 return -ENODEV;
883 if (mi->type > OMAPFB_MEMTYPE_MAX) 865 if (mi->type != OMAPFB_MEMTYPE_SDRAM)
884 return -EINVAL; 866 return -EINVAL;
885 867
886 size = PAGE_ALIGN(mi->size); 868 size = PAGE_ALIGN(mi->size);
@@ -1721,17 +1703,10 @@ static int omapfb_do_probe(struct platform_device *pdev,
1721 1703
1722 mutex_init(&fbdev->rqueue_mutex); 1704 mutex_init(&fbdev->rqueue_mutex);
1723 1705
1724#ifdef CONFIG_ARCH_OMAP1
1725 fbdev->int_ctrl = &omap1_int_ctrl; 1706 fbdev->int_ctrl = &omap1_int_ctrl;
1726#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL 1707#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
1727 fbdev->ext_if = &omap1_ext_if; 1708 fbdev->ext_if = &omap1_ext_if;
1728#endif 1709#endif
1729#else /* OMAP2 */
1730 fbdev->int_ctrl = &omap2_int_ctrl;
1731#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
1732 fbdev->ext_if = &omap2_ext_if;
1733#endif
1734#endif
1735 if (omapfb_find_ctrl(fbdev) < 0) { 1710 if (omapfb_find_ctrl(fbdev) < 0) {
1736 dev_err(fbdev->dev, 1711 dev_err(fbdev->dev,
1737 "LCD controller not found, board not supported\n"); 1712 "LCD controller not found, board not supported\n");
@@ -1766,8 +1741,7 @@ static int omapfb_do_probe(struct platform_device *pdev,
1766 1741
1767#ifdef CONFIG_FB_OMAP_DMA_TUNE 1742#ifdef CONFIG_FB_OMAP_DMA_TUNE
1768 /* Set DMA priority for EMIFF access to highest */ 1743 /* Set DMA priority for EMIFF access to highest */
1769 if (cpu_class_is_omap1()) 1744 omap_set_dma_priority(0, OMAP_DMA_PORT_EMIFF, 15);
1770 omap_set_dma_priority(0, OMAP_DMA_PORT_EMIFF, 15);
1771#endif 1745#endif
1772 1746
1773 r = ctrl_change_mode(fbdev->fb_info[0]); 1747 r = ctrl_change_mode(fbdev->fb_info[0]);
diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c
deleted file mode 100644
index 2c1a3402bef0..000000000000
--- a/drivers/video/omap/rfbi.c
+++ /dev/null
@@ -1,598 +0,0 @@
1/*
2 * OMAP2 Remote Frame Buffer Interface support
3 *
4 * Copyright (C) 2005 Nokia Corporation
5 * Author: Juha Yrjölä <juha.yrjola@nokia.com>
6 * Imre Deak <imre.deak@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22#include <linux/module.h>
23#include <linux/delay.h>
24#include <linux/i2c.h>
25#include <linux/err.h>
26#include <linux/interrupt.h>
27#include <linux/clk.h>
28#include <linux/io.h>
29#include <linux/platform_device.h>
30
31#include "omapfb.h"
32#include "dispc.h"
33
34/* To work around an RFBI transfer rate limitation */
35#define OMAP_RFBI_RATE_LIMIT 1
36
37#define RFBI_BASE 0x48050800
38#define RFBI_REVISION 0x0000
39#define RFBI_SYSCONFIG 0x0010
40#define RFBI_SYSSTATUS 0x0014
41#define RFBI_CONTROL 0x0040
42#define RFBI_PIXEL_CNT 0x0044
43#define RFBI_LINE_NUMBER 0x0048
44#define RFBI_CMD 0x004c
45#define RFBI_PARAM 0x0050
46#define RFBI_DATA 0x0054
47#define RFBI_READ 0x0058
48#define RFBI_STATUS 0x005c
49#define RFBI_CONFIG0 0x0060
50#define RFBI_ONOFF_TIME0 0x0064
51#define RFBI_CYCLE_TIME0 0x0068
52#define RFBI_DATA_CYCLE1_0 0x006c
53#define RFBI_DATA_CYCLE2_0 0x0070
54#define RFBI_DATA_CYCLE3_0 0x0074
55#define RFBI_VSYNC_WIDTH 0x0090
56#define RFBI_HSYNC_WIDTH 0x0094
57
58#define DISPC_BASE 0x48050400
59#define DISPC_CONTROL 0x0040
60#define DISPC_IRQ_FRAMEMASK 0x0001
61
62static struct {
63 void __iomem *base;
64 void (*lcdc_callback)(void *data);
65 void *lcdc_callback_data;
66 unsigned long l4_khz;
67 int bits_per_cycle;
68 struct omapfb_device *fbdev;
69 struct clk *dss_ick;
70 struct clk *dss1_fck;
71 unsigned tearsync_pin_cnt;
72 unsigned tearsync_mode;
73} rfbi;
74
75static inline void rfbi_write_reg(int idx, u32 val)
76{
77 __raw_writel(val, rfbi.base + idx);
78}
79
80static inline u32 rfbi_read_reg(int idx)
81{
82 return __raw_readl(rfbi.base + idx);
83}
84
85static int rfbi_get_clocks(void)
86{
87 rfbi.dss_ick = clk_get(&rfbi.fbdev->dssdev->dev, "ick");
88 if (IS_ERR(rfbi.dss_ick)) {
89 dev_err(rfbi.fbdev->dev, "can't get ick\n");
90 return PTR_ERR(rfbi.dss_ick);
91 }
92
93 rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "fck");
94 if (IS_ERR(rfbi.dss1_fck)) {
95 dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n");
96 clk_put(rfbi.dss_ick);
97 return PTR_ERR(rfbi.dss1_fck);
98 }
99
100 return 0;
101}
102
103static void rfbi_put_clocks(void)
104{
105 clk_put(rfbi.dss1_fck);
106 clk_put(rfbi.dss_ick);
107}
108
109static void rfbi_enable_clocks(int enable)
110{
111 if (enable) {
112 clk_enable(rfbi.dss_ick);
113 clk_enable(rfbi.dss1_fck);
114 } else {
115 clk_disable(rfbi.dss1_fck);
116 clk_disable(rfbi.dss_ick);
117 }
118}
119
120
121#ifdef VERBOSE
122static void rfbi_print_timings(void)
123{
124 u32 l;
125 u32 time;
126
127 l = rfbi_read_reg(RFBI_CONFIG0);
128 time = 1000000000 / rfbi.l4_khz;
129 if (l & (1 << 4))
130 time *= 2;
131
132 dev_dbg(rfbi.fbdev->dev, "Tick time %u ps\n", time);
133 l = rfbi_read_reg(RFBI_ONOFF_TIME0);
134 dev_dbg(rfbi.fbdev->dev,
135 "CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, "
136 "REONTIME %d, REOFFTIME %d\n",
137 l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f,
138 (l >> 20) & 0x0f, (l >> 24) & 0x3f);
139
140 l = rfbi_read_reg(RFBI_CYCLE_TIME0);
141 dev_dbg(rfbi.fbdev->dev,
142 "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, "
143 "ACCESSTIME %d\n",
144 (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f,
145 (l >> 22) & 0x3f);
146}
147#else
148static void rfbi_print_timings(void) {}
149#endif
150
151static void rfbi_set_timings(const struct extif_timings *t)
152{
153 u32 l;
154
155 BUG_ON(!t->converted);
156
157 rfbi_enable_clocks(1);
158 rfbi_write_reg(RFBI_ONOFF_TIME0, t->tim[0]);
159 rfbi_write_reg(RFBI_CYCLE_TIME0, t->tim[1]);
160
161 l = rfbi_read_reg(RFBI_CONFIG0);
162 l &= ~(1 << 4);
163 l |= (t->tim[2] ? 1 : 0) << 4;
164 rfbi_write_reg(RFBI_CONFIG0, l);
165
166 rfbi_print_timings();
167 rfbi_enable_clocks(0);
168}
169
170static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
171{
172 *clk_period = 1000000000 / rfbi.l4_khz;
173 *max_clk_div = 2;
174}
175
176static int ps_to_rfbi_ticks(int time, int div)
177{
178 unsigned long tick_ps;
179 int ret;
180
181 /* Calculate in picosecs to yield more exact results */
182 tick_ps = 1000000000 / (rfbi.l4_khz) * div;
183
184 ret = (time + tick_ps - 1) / tick_ps;
185
186 return ret;
187}
188
189#ifdef OMAP_RFBI_RATE_LIMIT
190static unsigned long rfbi_get_max_tx_rate(void)
191{
192 unsigned long l4_rate, dss1_rate;
193 int min_l4_ticks = 0;
194 int i;
195
196 /* According to TI this can't be calculated so make the
197 * adjustments for a couple of known frequencies and warn for
198 * others.
199 */
200 static const struct {
201 unsigned long l4_clk; /* HZ */
202 unsigned long dss1_clk; /* HZ */
203 unsigned long min_l4_ticks;
204 } ftab[] = {
205 { 55, 132, 7, }, /* 7.86 MPix/s */
206 { 110, 110, 12, }, /* 9.16 MPix/s */
207 { 110, 132, 10, }, /* 11 Mpix/s */
208 { 120, 120, 10, }, /* 12 Mpix/s */
209 { 133, 133, 10, }, /* 13.3 Mpix/s */
210 };
211
212 l4_rate = rfbi.l4_khz / 1000;
213 dss1_rate = clk_get_rate(rfbi.dss1_fck) / 1000000;
214
215 for (i = 0; i < ARRAY_SIZE(ftab); i++) {
216 /* Use a window instead of an exact match, to account
217 * for different DPLL multiplier / divider pairs.
218 */
219 if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
220 abs(ftab[i].dss1_clk - dss1_rate) < 3) {
221 min_l4_ticks = ftab[i].min_l4_ticks;
222 break;
223 }
224 }
225 if (i == ARRAY_SIZE(ftab)) {
226 /* Can't be sure, return anyway the maximum not
227 * rate-limited. This might cause a problem only for the
228 * tearing synchronisation.
229 */
230 dev_err(rfbi.fbdev->dev,
231 "can't determine maximum RFBI transfer rate\n");
232 return rfbi.l4_khz * 1000;
233 }
234 return rfbi.l4_khz * 1000 / min_l4_ticks;
235}
236#else
237static int rfbi_get_max_tx_rate(void)
238{
239 return rfbi.l4_khz * 1000;
240}
241#endif
242
243
244static int rfbi_convert_timings(struct extif_timings *t)
245{
246 u32 l;
247 int reon, reoff, weon, weoff, cson, csoff, cs_pulse;
248 int actim, recyc, wecyc;
249 int div = t->clk_div;
250
251 if (div <= 0 || div > 2)
252 return -1;
253
254 /* Make sure that after conversion it still holds that:
255 * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff,
256 * csoff > cson, csoff >= max(weoff, reoff), actim > reon
257 */
258 weon = ps_to_rfbi_ticks(t->we_on_time, div);
259 weoff = ps_to_rfbi_ticks(t->we_off_time, div);
260 if (weoff <= weon)
261 weoff = weon + 1;
262 if (weon > 0x0f)
263 return -1;
264 if (weoff > 0x3f)
265 return -1;
266
267 reon = ps_to_rfbi_ticks(t->re_on_time, div);
268 reoff = ps_to_rfbi_ticks(t->re_off_time, div);
269 if (reoff <= reon)
270 reoff = reon + 1;
271 if (reon > 0x0f)
272 return -1;
273 if (reoff > 0x3f)
274 return -1;
275
276 cson = ps_to_rfbi_ticks(t->cs_on_time, div);
277 csoff = ps_to_rfbi_ticks(t->cs_off_time, div);
278 if (csoff <= cson)
279 csoff = cson + 1;
280 if (csoff < max(weoff, reoff))
281 csoff = max(weoff, reoff);
282 if (cson > 0x0f)
283 return -1;
284 if (csoff > 0x3f)
285 return -1;
286
287 l = cson;
288 l |= csoff << 4;
289 l |= weon << 10;
290 l |= weoff << 14;
291 l |= reon << 20;
292 l |= reoff << 24;
293
294 t->tim[0] = l;
295
296 actim = ps_to_rfbi_ticks(t->access_time, div);
297 if (actim <= reon)
298 actim = reon + 1;
299 if (actim > 0x3f)
300 return -1;
301
302 wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div);
303 if (wecyc < weoff)
304 wecyc = weoff;
305 if (wecyc > 0x3f)
306 return -1;
307
308 recyc = ps_to_rfbi_ticks(t->re_cycle_time, div);
309 if (recyc < reoff)
310 recyc = reoff;
311 if (recyc > 0x3f)
312 return -1;
313
314 cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div);
315 if (cs_pulse > 0x3f)
316 return -1;
317
318 l = wecyc;
319 l |= recyc << 6;
320 l |= cs_pulse << 12;
321 l |= actim << 22;
322
323 t->tim[1] = l;
324
325 t->tim[2] = div - 1;
326
327 t->converted = 1;
328
329 return 0;
330}
331
332static int rfbi_setup_tearsync(unsigned pin_cnt,
333 unsigned hs_pulse_time, unsigned vs_pulse_time,
334 int hs_pol_inv, int vs_pol_inv, int extif_div)
335{
336 int hs, vs;
337 int min;
338 u32 l;
339
340 if (pin_cnt != 1 && pin_cnt != 2)
341 return -EINVAL;
342
343 hs = ps_to_rfbi_ticks(hs_pulse_time, 1);
344 vs = ps_to_rfbi_ticks(vs_pulse_time, 1);
345 if (hs < 2)
346 return -EDOM;
347 if (pin_cnt == 2)
348 min = 2;
349 else
350 min = 4;
351 if (vs < min)
352 return -EDOM;
353 if (vs == hs)
354 return -EINVAL;
355 rfbi.tearsync_pin_cnt = pin_cnt;
356 dev_dbg(rfbi.fbdev->dev,
357 "setup_tearsync: pins %d hs %d vs %d hs_inv %d vs_inv %d\n",
358 pin_cnt, hs, vs, hs_pol_inv, vs_pol_inv);
359
360 rfbi_enable_clocks(1);
361 rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
362 rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
363
364 l = rfbi_read_reg(RFBI_CONFIG0);
365 if (hs_pol_inv)
366 l &= ~(1 << 21);
367 else
368 l |= 1 << 21;
369 if (vs_pol_inv)
370 l &= ~(1 << 20);
371 else
372 l |= 1 << 20;
373 rfbi_enable_clocks(0);
374
375 return 0;
376}
377
378static int rfbi_enable_tearsync(int enable, unsigned line)
379{
380 u32 l;
381
382 dev_dbg(rfbi.fbdev->dev, "tearsync %d line %d mode %d\n",
383 enable, line, rfbi.tearsync_mode);
384 if (line > (1 << 11) - 1)
385 return -EINVAL;
386
387 rfbi_enable_clocks(1);
388 l = rfbi_read_reg(RFBI_CONFIG0);
389 l &= ~(0x3 << 2);
390 if (enable) {
391 rfbi.tearsync_mode = rfbi.tearsync_pin_cnt;
392 l |= rfbi.tearsync_mode << 2;
393 } else
394 rfbi.tearsync_mode = 0;
395 rfbi_write_reg(RFBI_CONFIG0, l);
396 rfbi_write_reg(RFBI_LINE_NUMBER, line);
397 rfbi_enable_clocks(0);
398
399 return 0;
400}
401
402static void rfbi_write_command(const void *buf, unsigned int len)
403{
404 rfbi_enable_clocks(1);
405 if (rfbi.bits_per_cycle == 16) {
406 const u16 *w = buf;
407 BUG_ON(len & 1);
408 for (; len; len -= 2)
409 rfbi_write_reg(RFBI_CMD, *w++);
410 } else {
411 const u8 *b = buf;
412 BUG_ON(rfbi.bits_per_cycle != 8);
413 for (; len; len--)
414 rfbi_write_reg(RFBI_CMD, *b++);
415 }
416 rfbi_enable_clocks(0);
417}
418
419static void rfbi_read_data(void *buf, unsigned int len)
420{
421 rfbi_enable_clocks(1);
422 if (rfbi.bits_per_cycle == 16) {
423 u16 *w = buf;
424 BUG_ON(len & ~1);
425 for (; len; len -= 2) {
426 rfbi_write_reg(RFBI_READ, 0);
427 *w++ = rfbi_read_reg(RFBI_READ);
428 }
429 } else {
430 u8 *b = buf;
431 BUG_ON(rfbi.bits_per_cycle != 8);
432 for (; len; len--) {
433 rfbi_write_reg(RFBI_READ, 0);
434 *b++ = rfbi_read_reg(RFBI_READ);
435 }
436 }
437 rfbi_enable_clocks(0);
438}
439
440static void rfbi_write_data(const void *buf, unsigned int len)
441{
442 rfbi_enable_clocks(1);
443 if (rfbi.bits_per_cycle == 16) {
444 const u16 *w = buf;
445 BUG_ON(len & 1);
446 for (; len; len -= 2)
447 rfbi_write_reg(RFBI_PARAM, *w++);
448 } else {
449 const u8 *b = buf;
450 BUG_ON(rfbi.bits_per_cycle != 8);
451 for (; len; len--)
452 rfbi_write_reg(RFBI_PARAM, *b++);
453 }
454 rfbi_enable_clocks(0);
455}
456
457static void rfbi_transfer_area(int width, int height,
458 void (callback)(void * data), void *data)
459{
460 u32 w;
461
462 BUG_ON(callback == NULL);
463
464 rfbi_enable_clocks(1);
465 omap_dispc_set_lcd_size(width, height);
466
467 rfbi.lcdc_callback = callback;
468 rfbi.lcdc_callback_data = data;
469
470 rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
471
472 w = rfbi_read_reg(RFBI_CONTROL);
473 w |= 1; /* enable */
474 if (!rfbi.tearsync_mode)
475 w |= 1 << 4; /* internal trigger, reset by HW */
476 rfbi_write_reg(RFBI_CONTROL, w);
477
478 omap_dispc_enable_lcd_out(1);
479}
480
481static inline void _stop_transfer(void)
482{
483 u32 w;
484
485 w = rfbi_read_reg(RFBI_CONTROL);
486 rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0));
487 rfbi_enable_clocks(0);
488}
489
490static void rfbi_dma_callback(void *data)
491{
492 _stop_transfer();
493 rfbi.lcdc_callback(rfbi.lcdc_callback_data);
494}
495
496static void rfbi_set_bits_per_cycle(int bpc)
497{
498 u32 l;
499
500 rfbi_enable_clocks(1);
501 l = rfbi_read_reg(RFBI_CONFIG0);
502 l &= ~(0x03 << 0);
503
504 switch (bpc) {
505 case 8:
506 break;
507 case 16:
508 l |= 3;
509 break;
510 default:
511 BUG();
512 }
513 rfbi_write_reg(RFBI_CONFIG0, l);
514 rfbi.bits_per_cycle = bpc;
515 rfbi_enable_clocks(0);
516}
517
518static int rfbi_init(struct omapfb_device *fbdev)
519{
520 u32 l;
521 int r;
522
523 rfbi.fbdev = fbdev;
524 rfbi.base = ioremap(RFBI_BASE, SZ_1K);
525 if (!rfbi.base) {
526 dev_err(fbdev->dev, "can't ioremap RFBI\n");
527 return -ENOMEM;
528 }
529
530 if ((r = rfbi_get_clocks()) < 0)
531 return r;
532 rfbi_enable_clocks(1);
533
534 rfbi.l4_khz = clk_get_rate(rfbi.dss_ick) / 1000;
535
536 /* Reset */
537 rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1);
538 while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0)));
539
540 l = rfbi_read_reg(RFBI_SYSCONFIG);
541 /* Enable autoidle and smart-idle */
542 l |= (1 << 0) | (2 << 3);
543 rfbi_write_reg(RFBI_SYSCONFIG, l);
544
545 /* 16-bit interface, ITE trigger mode, 16-bit data */
546 l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7);
547 l |= (0 << 9) | (1 << 20) | (1 << 21);
548 rfbi_write_reg(RFBI_CONFIG0, l);
549
550 rfbi_write_reg(RFBI_DATA_CYCLE1_0, 0x00000010);
551
552 l = rfbi_read_reg(RFBI_CONTROL);
553 /* Select CS0, clear bypass mode */
554 l = (0x01 << 2);
555 rfbi_write_reg(RFBI_CONTROL, l);
556
557 r = omap_dispc_request_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback,
558 NULL);
559 if (r < 0) {
560 dev_err(fbdev->dev, "can't get DISPC irq\n");
561 rfbi_enable_clocks(0);
562 return r;
563 }
564
565 l = rfbi_read_reg(RFBI_REVISION);
566 pr_info("omapfb: RFBI version %d.%d initialized\n",
567 (l >> 4) & 0x0f, l & 0x0f);
568
569 rfbi_enable_clocks(0);
570
571 return 0;
572}
573
574static void rfbi_cleanup(void)
575{
576 omap_dispc_free_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, NULL);
577 rfbi_put_clocks();
578 iounmap(rfbi.base);
579}
580
581const struct lcd_ctrl_extif omap2_ext_if = {
582 .init = rfbi_init,
583 .cleanup = rfbi_cleanup,
584 .get_clk_info = rfbi_get_clk_info,
585 .get_max_tx_rate = rfbi_get_max_tx_rate,
586 .set_bits_per_cycle = rfbi_set_bits_per_cycle,
587 .convert_timings = rfbi_convert_timings,
588 .set_timings = rfbi_set_timings,
589 .write_command = rfbi_write_command,
590 .read_data = rfbi_read_data,
591 .write_data = rfbi_write_data,
592 .transfer_area = rfbi_transfer_area,
593 .setup_tearsync = rfbi_setup_tearsync,
594 .enable_tearsync = rfbi_enable_tearsync,
595
596 .max_transmit_size = (u32) ~0,
597};
598
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index 51a87e149e24..d26f37ac69d8 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -809,18 +809,7 @@ static struct spi_driver acx565akm_spi_driver = {
809 .remove = __devexit_p(acx565akm_spi_remove), 809 .remove = __devexit_p(acx565akm_spi_remove),
810}; 810};
811 811
812static int __init acx565akm_init(void) 812module_spi_driver(acx565akm_spi_driver);
813{
814 return spi_register_driver(&acx565akm_spi_driver);
815}
816
817static void __exit acx565akm_exit(void)
818{
819 spi_unregister_driver(&acx565akm_spi_driver);
820}
821
822module_init(acx565akm_init);
823module_exit(acx565akm_exit);
824 813
825MODULE_AUTHOR("Nokia Corporation"); 814MODULE_AUTHOR("Nokia Corporation");
826MODULE_DESCRIPTION("acx565akm LCD Driver"); 815MODULE_DESCRIPTION("acx565akm LCD Driver");
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 28b9a6d61b0f..30fe4dfeb227 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -363,6 +363,29 @@ static struct panel_config generic_dpi_panels[] = {
363 363
364 .name = "ortustech_com43h4m10xtc", 364 .name = "ortustech_com43h4m10xtc",
365 }, 365 },
366
367 /* Innolux AT080TN52 */
368 {
369 {
370 .x_res = 800,
371 .y_res = 600,
372
373 .pixel_clock = 41142,
374
375 .hsw = 20,
376 .hfp = 210,
377 .hbp = 46,
378
379 .vsw = 10,
380 .vfp = 12,
381 .vbp = 23,
382 },
383 .acb = 0x0,
384 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
385 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO,
386
387 .name = "innolux_at080tn52",
388 },
366}; 389};
367 390
368struct panel_drv_data { 391struct panel_drv_data {
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
index e0eb35be303e..0841cc2b3f77 100644
--- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -264,16 +264,6 @@ static struct spi_driver lb035q02_spi_driver = {
264 .remove = __devexit_p(lb035q02_panel_spi_remove), 264 .remove = __devexit_p(lb035q02_panel_spi_remove),
265}; 265};
266 266
267static int __init lb035q02_panel_drv_init(void) 267module_spi_driver(lb035q02_spi_driver);
268{
269 return spi_register_driver(&lb035q02_spi_driver);
270}
271
272static void __exit lb035q02_panel_drv_exit(void)
273{
274 spi_unregister_driver(&lb035q02_spi_driver);
275}
276 268
277module_init(lb035q02_panel_drv_init);
278module_exit(lb035q02_panel_drv_exit);
279MODULE_LICENSE("GPL"); 269MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index 0eb31caddca8..8b38b39213f4 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -350,18 +350,8 @@ static struct spi_driver nec_8048_spi_driver = {
350 }, 350 },
351}; 351};
352 352
353static int __init nec_8048_lcd_init(void) 353module_spi_driver(nec_8048_spi_driver);
354{
355 return spi_register_driver(&nec_8048_spi_driver);
356}
357
358static void __exit nec_8048_lcd_exit(void)
359{
360 return spi_unregister_driver(&nec_8048_spi_driver);
361}
362 354
363module_init(nec_8048_lcd_init);
364module_exit(nec_8048_lcd_exit);
365MODULE_AUTHOR("Erik Gilling <konkers@android.com>"); 355MODULE_AUTHOR("Erik Gilling <konkers@android.com>");
366MODULE_DESCRIPTION("NEC-nl8048hl11-01b Driver"); 356MODULE_DESCRIPTION("NEC-nl8048hl11-01b Driver");
367MODULE_LICENSE("GPL"); 357MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 00c5c615585f..0f21fa5a16ae 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -1019,14 +1019,12 @@ static int taal_probe(struct omap_dss_device *dssdev)
1019 if (panel_data->use_ext_te) { 1019 if (panel_data->use_ext_te) {
1020 int gpio = panel_data->ext_te_gpio; 1020 int gpio = panel_data->ext_te_gpio;
1021 1021
1022 r = gpio_request(gpio, "taal irq"); 1022 r = gpio_request_one(gpio, GPIOF_IN, "taal irq");
1023 if (r) { 1023 if (r) {
1024 dev_err(&dssdev->dev, "GPIO request failed\n"); 1024 dev_err(&dssdev->dev, "GPIO request failed\n");
1025 goto err_gpio; 1025 goto err_gpio;
1026 } 1026 }
1027 1027
1028 gpio_direction_input(gpio);
1029
1030 r = request_irq(gpio_to_irq(gpio), taal_te_isr, 1028 r = request_irq(gpio_to_irq(gpio), taal_te_isr,
1031 IRQF_TRIGGER_RISING, 1029 IRQF_TRIGGER_RISING,
1032 "taal vsync", dssdev); 1030 "taal vsync", dssdev);
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index e6649aa89591..32f3fcd7f0f0 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -47,16 +47,20 @@
47 TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL) 47 TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL)
48 48
49static const u16 tpo_td043_def_gamma[12] = { 49static const u16 tpo_td043_def_gamma[12] = {
50 106, 200, 289, 375, 460, 543, 625, 705, 785, 864, 942, 1020 50 105, 315, 381, 431, 490, 537, 579, 686, 780, 837, 880, 1023
51}; 51};
52 52
53struct tpo_td043_device { 53struct tpo_td043_device {
54 struct spi_device *spi; 54 struct spi_device *spi;
55 struct regulator *vcc_reg; 55 struct regulator *vcc_reg;
56 int nreset_gpio;
56 u16 gamma[12]; 57 u16 gamma[12];
57 u32 mode; 58 u32 mode;
58 u32 hmirror:1; 59 u32 hmirror:1;
59 u32 vmirror:1; 60 u32 vmirror:1;
61 u32 powered_on:1;
62 u32 spi_suspended:1;
63 u32 power_on_resume:1;
60}; 64};
61 65
62static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data) 66static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
@@ -265,28 +269,16 @@ static const struct omap_video_timings tpo_td043_timings = {
265 .vbp = 34, 269 .vbp = 34,
266}; 270};
267 271
268static int tpo_td043_power_on(struct omap_dss_device *dssdev) 272static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
269{ 273{
270 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); 274 int nreset_gpio = tpo_td043->nreset_gpio;
271 int nreset_gpio = dssdev->reset_gpio;
272 int r;
273 275
274 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 276 if (tpo_td043->powered_on)
275 return 0; 277 return 0;
276 278
277 r = omapdss_dpi_display_enable(dssdev);
278 if (r)
279 goto err0;
280
281 if (dssdev->platform_enable) {
282 r = dssdev->platform_enable(dssdev);
283 if (r)
284 goto err1;
285 }
286
287 regulator_enable(tpo_td043->vcc_reg); 279 regulator_enable(tpo_td043->vcc_reg);
288 280
289 /* wait for power up */ 281 /* wait for regulator to stabilize */
290 msleep(160); 282 msleep(160);
291 283
292 if (gpio_is_valid(nreset_gpio)) 284 if (gpio_is_valid(nreset_gpio))
@@ -301,19 +293,15 @@ static int tpo_td043_power_on(struct omap_dss_device *dssdev)
301 tpo_td043->vmirror); 293 tpo_td043->vmirror);
302 tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma); 294 tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma);
303 295
296 tpo_td043->powered_on = 1;
304 return 0; 297 return 0;
305err1:
306 omapdss_dpi_display_disable(dssdev);
307err0:
308 return r;
309} 298}
310 299
311static void tpo_td043_power_off(struct omap_dss_device *dssdev) 300static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043)
312{ 301{
313 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); 302 int nreset_gpio = tpo_td043->nreset_gpio;
314 int nreset_gpio = dssdev->reset_gpio;
315 303
316 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 304 if (!tpo_td043->powered_on)
317 return; 305 return;
318 306
319 tpo_td043_write(tpo_td043->spi, 3, 307 tpo_td043_write(tpo_td043->spi, 3,
@@ -329,54 +317,94 @@ static void tpo_td043_power_off(struct omap_dss_device *dssdev)
329 317
330 regulator_disable(tpo_td043->vcc_reg); 318 regulator_disable(tpo_td043->vcc_reg);
331 319
320 tpo_td043->powered_on = 0;
321}
322
323static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
324{
325 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
326 int r;
327
328 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
329 return 0;
330
331 r = omapdss_dpi_display_enable(dssdev);
332 if (r)
333 goto err0;
334
335 if (dssdev->platform_enable) {
336 r = dssdev->platform_enable(dssdev);
337 if (r)
338 goto err1;
339 }
340
341 /*
342 * If we are resuming from system suspend, SPI clocks might not be
343 * enabled yet, so we'll program the LCD from SPI PM resume callback.
344 */
345 if (!tpo_td043->spi_suspended) {
346 r = tpo_td043_power_on(tpo_td043);
347 if (r)
348 goto err1;
349 }
350
351 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
352
353 return 0;
354err1:
355 omapdss_dpi_display_disable(dssdev);
356err0:
357 return r;
358}
359
360static void tpo_td043_disable_dss(struct omap_dss_device *dssdev)
361{
362 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
363
364 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
365 return;
366
332 if (dssdev->platform_disable) 367 if (dssdev->platform_disable)
333 dssdev->platform_disable(dssdev); 368 dssdev->platform_disable(dssdev);
334 369
335 omapdss_dpi_display_disable(dssdev); 370 omapdss_dpi_display_disable(dssdev);
371
372 if (!tpo_td043->spi_suspended)
373 tpo_td043_power_off(tpo_td043);
336} 374}
337 375
338static int tpo_td043_enable(struct omap_dss_device *dssdev) 376static int tpo_td043_enable(struct omap_dss_device *dssdev)
339{ 377{
340 int ret;
341
342 dev_dbg(&dssdev->dev, "enable\n"); 378 dev_dbg(&dssdev->dev, "enable\n");
343 379
344 ret = tpo_td043_power_on(dssdev); 380 return tpo_td043_enable_dss(dssdev);
345 if (ret)
346 return ret;
347
348 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
349
350 return 0;
351} 381}
352 382
353static void tpo_td043_disable(struct omap_dss_device *dssdev) 383static void tpo_td043_disable(struct omap_dss_device *dssdev)
354{ 384{
355 dev_dbg(&dssdev->dev, "disable\n"); 385 dev_dbg(&dssdev->dev, "disable\n");
356 386
357 tpo_td043_power_off(dssdev); 387 tpo_td043_disable_dss(dssdev);
358 388
359 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 389 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
360} 390}
361 391
362static int tpo_td043_suspend(struct omap_dss_device *dssdev) 392static int tpo_td043_suspend(struct omap_dss_device *dssdev)
363{ 393{
364 tpo_td043_power_off(dssdev); 394 dev_dbg(&dssdev->dev, "suspend\n");
395
396 tpo_td043_disable_dss(dssdev);
397
365 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; 398 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
399
366 return 0; 400 return 0;
367} 401}
368 402
369static int tpo_td043_resume(struct omap_dss_device *dssdev) 403static int tpo_td043_resume(struct omap_dss_device *dssdev)
370{ 404{
371 int r = 0; 405 dev_dbg(&dssdev->dev, "resume\n");
372
373 r = tpo_td043_power_on(dssdev);
374 if (r)
375 return r;
376 406
377 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 407 return tpo_td043_enable_dss(dssdev);
378
379 return 0;
380} 408}
381 409
382static int tpo_td043_probe(struct omap_dss_device *dssdev) 410static int tpo_td043_probe(struct omap_dss_device *dssdev)
@@ -408,17 +436,12 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
408 } 436 }
409 437
410 if (gpio_is_valid(nreset_gpio)) { 438 if (gpio_is_valid(nreset_gpio)) {
411 ret = gpio_request(nreset_gpio, "lcd reset"); 439 ret = gpio_request_one(nreset_gpio, GPIOF_OUT_INIT_LOW,
440 "lcd reset");
412 if (ret < 0) { 441 if (ret < 0) {
413 dev_err(&dssdev->dev, "couldn't request reset GPIO\n"); 442 dev_err(&dssdev->dev, "couldn't request reset GPIO\n");
414 goto fail_gpio_req; 443 goto fail_gpio_req;
415 } 444 }
416
417 ret = gpio_direction_output(nreset_gpio, 0);
418 if (ret < 0) {
419 dev_err(&dssdev->dev, "couldn't set GPIO direction\n");
420 goto fail_gpio_direction;
421 }
422 } 445 }
423 446
424 ret = sysfs_create_group(&dssdev->dev.kobj, &tpo_td043_attr_group); 447 ret = sysfs_create_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
@@ -427,8 +450,6 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
427 450
428 return 0; 451 return 0;
429 452
430fail_gpio_direction:
431 gpio_free(nreset_gpio);
432fail_gpio_req: 453fail_gpio_req:
433 regulator_put(tpo_td043->vcc_reg); 454 regulator_put(tpo_td043->vcc_reg);
434fail_regulator: 455fail_regulator:
@@ -491,6 +512,7 @@ static int tpo_td043_spi_probe(struct spi_device *spi)
491 return -ENOMEM; 512 return -ENOMEM;
492 513
493 tpo_td043->spi = spi; 514 tpo_td043->spi = spi;
515 tpo_td043->nreset_gpio = dssdev->reset_gpio;
494 dev_set_drvdata(&spi->dev, tpo_td043); 516 dev_set_drvdata(&spi->dev, tpo_td043);
495 dev_set_drvdata(&dssdev->dev, tpo_td043); 517 dev_set_drvdata(&dssdev->dev, tpo_td043);
496 518
@@ -509,27 +531,52 @@ static int __devexit tpo_td043_spi_remove(struct spi_device *spi)
509 return 0; 531 return 0;
510} 532}
511 533
534#ifdef CONFIG_PM_SLEEP
535static int tpo_td043_spi_suspend(struct device *dev)
536{
537 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
538
539 dev_dbg(dev, "tpo_td043_spi_suspend, tpo %p\n", tpo_td043);
540
541 tpo_td043->power_on_resume = tpo_td043->powered_on;
542 tpo_td043_power_off(tpo_td043);
543 tpo_td043->spi_suspended = 1;
544
545 return 0;
546}
547
548static int tpo_td043_spi_resume(struct device *dev)
549{
550 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
551 int ret;
552
553 dev_dbg(dev, "tpo_td043_spi_resume\n");
554
555 if (tpo_td043->power_on_resume) {
556 ret = tpo_td043_power_on(tpo_td043);
557 if (ret)
558 return ret;
559 }
560 tpo_td043->spi_suspended = 0;
561
562 return 0;
563}
564#endif
565
566static SIMPLE_DEV_PM_OPS(tpo_td043_spi_pm,
567 tpo_td043_spi_suspend, tpo_td043_spi_resume);
568
512static struct spi_driver tpo_td043_spi_driver = { 569static struct spi_driver tpo_td043_spi_driver = {
513 .driver = { 570 .driver = {
514 .name = "tpo_td043mtea1_panel_spi", 571 .name = "tpo_td043mtea1_panel_spi",
515 .owner = THIS_MODULE, 572 .owner = THIS_MODULE,
573 .pm = &tpo_td043_spi_pm,
516 }, 574 },
517 .probe = tpo_td043_spi_probe, 575 .probe = tpo_td043_spi_probe,
518 .remove = __devexit_p(tpo_td043_spi_remove), 576 .remove = __devexit_p(tpo_td043_spi_remove),
519}; 577};
520 578
521static int __init tpo_td043_init(void) 579module_spi_driver(tpo_td043_spi_driver);
522{
523 return spi_register_driver(&tpo_td043_spi_driver);
524}
525
526static void __exit tpo_td043_exit(void)
527{
528 spi_unregister_driver(&tpo_td043_spi_driver);
529}
530
531module_init(tpo_td043_init);
532module_exit(tpo_td043_exit);
533 580
534MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>"); 581MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
535MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver"); 582MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 87b3e25294cf..b10b3bc1931e 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -105,6 +105,9 @@ static struct {
105 struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS]; 105 struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
106 struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS]; 106 struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
107 107
108 bool fifo_merge_dirty;
109 bool fifo_merge;
110
108 bool irq_enabled; 111 bool irq_enabled;
109} dss_data; 112} dss_data;
110 113
@@ -351,6 +354,7 @@ static void wait_pending_extra_info_updates(void)
351 bool updating; 354 bool updating;
352 unsigned long flags; 355 unsigned long flags;
353 unsigned long t; 356 unsigned long t;
357 int r;
354 358
355 spin_lock_irqsave(&data_lock, flags); 359 spin_lock_irqsave(&data_lock, flags);
356 360
@@ -366,11 +370,11 @@ static void wait_pending_extra_info_updates(void)
366 spin_unlock_irqrestore(&data_lock, flags); 370 spin_unlock_irqrestore(&data_lock, flags);
367 371
368 t = msecs_to_jiffies(500); 372 t = msecs_to_jiffies(500);
369 wait_for_completion_timeout(&extra_updated_completion, t); 373 r = wait_for_completion_timeout(&extra_updated_completion, t);
370 374 if (r == 0)
371 updating = extra_info_update_ongoing(); 375 DSSWARN("timeout in wait_pending_extra_info_updates\n");
372 376 else if (r < 0)
373 WARN_ON(updating); 377 DSSERR("wait_pending_extra_info_updates failed: %d\n", r);
374} 378}
375 379
376int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) 380int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
@@ -388,6 +392,10 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
388 if (mgr_manual_update(mgr)) 392 if (mgr_manual_update(mgr))
389 return 0; 393 return 0;
390 394
395 r = dispc_runtime_get();
396 if (r)
397 return r;
398
391 irq = dispc_mgr_get_vsync_irq(mgr->id); 399 irq = dispc_mgr_get_vsync_irq(mgr->id);
392 400
393 mp = get_mgr_priv(mgr); 401 mp = get_mgr_priv(mgr);
@@ -428,6 +436,8 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
428 } 436 }
429 } 437 }
430 438
439 dispc_runtime_put();
440
431 return r; 441 return r;
432} 442}
433 443
@@ -451,6 +461,10 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
451 if (ovl_manual_update(ovl)) 461 if (ovl_manual_update(ovl))
452 return 0; 462 return 0;
453 463
464 r = dispc_runtime_get();
465 if (r)
466 return r;
467
454 irq = dispc_mgr_get_vsync_irq(ovl->manager->id); 468 irq = dispc_mgr_get_vsync_irq(ovl->manager->id);
455 469
456 op = get_ovl_priv(ovl); 470 op = get_ovl_priv(ovl);
@@ -491,6 +505,8 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
491 } 505 }
492 } 506 }
493 507
508 dispc_runtime_put();
509
494 return r; 510 return r;
495} 511}
496 512
@@ -585,11 +601,40 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
585 } 601 }
586} 602}
587 603
604static void dss_write_regs_common(void)
605{
606 const int num_mgrs = omap_dss_get_num_overlay_managers();
607 int i;
608
609 if (!dss_data.fifo_merge_dirty)
610 return;
611
612 for (i = 0; i < num_mgrs; ++i) {
613 struct omap_overlay_manager *mgr;
614 struct mgr_priv_data *mp;
615
616 mgr = omap_dss_get_overlay_manager(i);
617 mp = get_mgr_priv(mgr);
618
619 if (mp->enabled) {
620 if (dss_data.fifo_merge_dirty) {
621 dispc_enable_fifomerge(dss_data.fifo_merge);
622 dss_data.fifo_merge_dirty = false;
623 }
624
625 if (mp->updating)
626 mp->shadow_info_dirty = true;
627 }
628 }
629}
630
588static void dss_write_regs(void) 631static void dss_write_regs(void)
589{ 632{
590 const int num_mgrs = omap_dss_get_num_overlay_managers(); 633 const int num_mgrs = omap_dss_get_num_overlay_managers();
591 int i; 634 int i;
592 635
636 dss_write_regs_common();
637
593 for (i = 0; i < num_mgrs; ++i) { 638 for (i = 0; i < num_mgrs; ++i) {
594 struct omap_overlay_manager *mgr; 639 struct omap_overlay_manager *mgr;
595 struct mgr_priv_data *mp; 640 struct mgr_priv_data *mp;
@@ -640,6 +685,22 @@ static void dss_set_go_bits(void)
640 685
641} 686}
642 687
688static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
689{
690 struct omap_overlay *ovl;
691 struct mgr_priv_data *mp;
692 struct ovl_priv_data *op;
693
694 mp = get_mgr_priv(mgr);
695 mp->shadow_info_dirty = false;
696
697 list_for_each_entry(ovl, &mgr->overlays, list) {
698 op = get_ovl_priv(ovl);
699 op->shadow_info_dirty = false;
700 op->shadow_extra_info_dirty = false;
701 }
702}
703
643void dss_mgr_start_update(struct omap_overlay_manager *mgr) 704void dss_mgr_start_update(struct omap_overlay_manager *mgr)
644{ 705{
645 struct mgr_priv_data *mp = get_mgr_priv(mgr); 706 struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -659,6 +720,8 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
659 720
660 dss_mgr_write_regs(mgr); 721 dss_mgr_write_regs(mgr);
661 722
723 dss_write_regs_common();
724
662 mp->updating = true; 725 mp->updating = true;
663 726
664 if (!dss_data.irq_enabled && need_isr()) 727 if (!dss_data.irq_enabled && need_isr())
@@ -666,6 +729,8 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
666 729
667 dispc_mgr_enable(mgr->id, true); 730 dispc_mgr_enable(mgr->id, true);
668 731
732 mgr_clear_shadow_dirty(mgr);
733
669 spin_unlock_irqrestore(&data_lock, flags); 734 spin_unlock_irqrestore(&data_lock, flags);
670} 735}
671 736
@@ -709,22 +774,6 @@ static void dss_unregister_vsync_isr(void)
709 dss_data.irq_enabled = false; 774 dss_data.irq_enabled = false;
710} 775}
711 776
712static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
713{
714 struct omap_overlay *ovl;
715 struct mgr_priv_data *mp;
716 struct ovl_priv_data *op;
717
718 mp = get_mgr_priv(mgr);
719 mp->shadow_info_dirty = false;
720
721 list_for_each_entry(ovl, &mgr->overlays, list) {
722 op = get_ovl_priv(ovl);
723 op->shadow_info_dirty = false;
724 op->shadow_extra_info_dirty = false;
725 }
726}
727
728static void dss_apply_irq_handler(void *data, u32 mask) 777static void dss_apply_irq_handler(void *data, u32 mask)
729{ 778{
730 const int num_mgrs = dss_feat_get_num_mgrs(); 779 const int num_mgrs = dss_feat_get_num_mgrs();
@@ -754,9 +803,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
754 803
755 if (was_busy && !mp->busy) 804 if (was_busy && !mp->busy)
756 mgr_clear_shadow_dirty(mgr); 805 mgr_clear_shadow_dirty(mgr);
757 } else {
758 if (was_updating && !mp->updating)
759 mgr_clear_shadow_dirty(mgr);
760 } 806 }
761 } 807 }
762 808
@@ -859,11 +905,20 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
859 op->extra_info_dirty = true; 905 op->extra_info_dirty = true;
860} 906}
861 907
862static void dss_ovl_setup_fifo(struct omap_overlay *ovl) 908static void dss_apply_fifo_merge(bool use_fifo_merge)
909{
910 if (dss_data.fifo_merge == use_fifo_merge)
911 return;
912
913 dss_data.fifo_merge = use_fifo_merge;
914 dss_data.fifo_merge_dirty = true;
915}
916
917static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
918 bool use_fifo_merge)
863{ 919{
864 struct ovl_priv_data *op = get_ovl_priv(ovl); 920 struct ovl_priv_data *op = get_ovl_priv(ovl);
865 struct omap_dss_device *dssdev; 921 struct omap_dss_device *dssdev;
866 u32 size, burst_size;
867 u32 fifo_low, fifo_high; 922 u32 fifo_low, fifo_high;
868 923
869 if (!op->enabled && !op->enabling) 924 if (!op->enabled && !op->enabling)
@@ -871,33 +926,14 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
871 926
872 dssdev = ovl->manager->device; 927 dssdev = ovl->manager->device;
873 928
874 size = dispc_ovl_get_fifo_size(ovl->id); 929 dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
875 930 use_fifo_merge);
876 burst_size = dispc_ovl_get_burst_size(ovl->id);
877
878 switch (dssdev->type) {
879 case OMAP_DISPLAY_TYPE_DPI:
880 case OMAP_DISPLAY_TYPE_DBI:
881 case OMAP_DISPLAY_TYPE_SDI:
882 case OMAP_DISPLAY_TYPE_VENC:
883 case OMAP_DISPLAY_TYPE_HDMI:
884 default_get_overlay_fifo_thresholds(ovl->id, size,
885 burst_size, &fifo_low, &fifo_high);
886 break;
887#ifdef CONFIG_OMAP2_DSS_DSI
888 case OMAP_DISPLAY_TYPE_DSI:
889 dsi_get_overlay_fifo_thresholds(ovl->id, size,
890 burst_size, &fifo_low, &fifo_high);
891 break;
892#endif
893 default:
894 BUG();
895 }
896 931
897 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); 932 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
898} 933}
899 934
900static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr) 935static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
936 bool use_fifo_merge)
901{ 937{
902 struct omap_overlay *ovl; 938 struct omap_overlay *ovl;
903 struct mgr_priv_data *mp; 939 struct mgr_priv_data *mp;
@@ -908,19 +944,94 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
908 return; 944 return;
909 945
910 list_for_each_entry(ovl, &mgr->overlays, list) 946 list_for_each_entry(ovl, &mgr->overlays, list)
911 dss_ovl_setup_fifo(ovl); 947 dss_ovl_setup_fifo(ovl, use_fifo_merge);
948}
949
950static void dss_setup_fifos(bool use_fifo_merge)
951{
952 const int num_mgrs = omap_dss_get_num_overlay_managers();
953 struct omap_overlay_manager *mgr;
954 int i;
955
956 for (i = 0; i < num_mgrs; ++i) {
957 mgr = omap_dss_get_overlay_manager(i);
958 dss_mgr_setup_fifos(mgr, use_fifo_merge);
959 }
912} 960}
913 961
914static void dss_setup_fifos(void) 962static int get_num_used_managers(void)
915{ 963{
916 const int num_mgrs = omap_dss_get_num_overlay_managers(); 964 const int num_mgrs = omap_dss_get_num_overlay_managers();
917 struct omap_overlay_manager *mgr; 965 struct omap_overlay_manager *mgr;
966 struct mgr_priv_data *mp;
918 int i; 967 int i;
968 int enabled_mgrs;
969
970 enabled_mgrs = 0;
919 971
920 for (i = 0; i < num_mgrs; ++i) { 972 for (i = 0; i < num_mgrs; ++i) {
921 mgr = omap_dss_get_overlay_manager(i); 973 mgr = omap_dss_get_overlay_manager(i);
922 dss_mgr_setup_fifos(mgr); 974 mp = get_mgr_priv(mgr);
975
976 if (!mp->enabled)
977 continue;
978
979 enabled_mgrs++;
980 }
981
982 return enabled_mgrs;
983}
984
985static int get_num_used_overlays(void)
986{
987 const int num_ovls = omap_dss_get_num_overlays();
988 struct omap_overlay *ovl;
989 struct ovl_priv_data *op;
990 struct mgr_priv_data *mp;
991 int i;
992 int enabled_ovls;
993
994 enabled_ovls = 0;
995
996 for (i = 0; i < num_ovls; ++i) {
997 ovl = omap_dss_get_overlay(i);
998 op = get_ovl_priv(ovl);
999
1000 if (!op->enabled && !op->enabling)
1001 continue;
1002
1003 mp = get_mgr_priv(ovl->manager);
1004
1005 if (!mp->enabled)
1006 continue;
1007
1008 enabled_ovls++;
923 } 1009 }
1010
1011 return enabled_ovls;
1012}
1013
1014static bool get_use_fifo_merge(void)
1015{
1016 int enabled_mgrs = get_num_used_managers();
1017 int enabled_ovls = get_num_used_overlays();
1018
1019 if (!dss_has_feature(FEAT_FIFO_MERGE))
1020 return false;
1021
1022 /*
1023 * In theory the only requirement for fifomerge is enabled_ovls <= 1.
1024 * However, if we have two managers enabled and set/unset the fifomerge,
1025 * we need to set the GO bits in particular sequence for the managers,
1026 * and wait in between.
1027 *
1028 * This is rather difficult as new apply calls can happen at any time,
1029 * so we simplify the problem by requiring also that enabled_mgrs <= 1.
1030 * In practice this shouldn't matter, because when only one overlay is
1031 * enabled, most likely only one output is enabled.
1032 */
1033
1034 return enabled_mgrs <= 1 && enabled_ovls <= 1;
924} 1035}
925 1036
926int dss_mgr_enable(struct omap_overlay_manager *mgr) 1037int dss_mgr_enable(struct omap_overlay_manager *mgr)
@@ -928,6 +1039,7 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
928 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1039 struct mgr_priv_data *mp = get_mgr_priv(mgr);
929 unsigned long flags; 1040 unsigned long flags;
930 int r; 1041 int r;
1042 bool fifo_merge;
931 1043
932 mutex_lock(&apply_lock); 1044 mutex_lock(&apply_lock);
933 1045
@@ -945,11 +1057,23 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
945 goto err; 1057 goto err;
946 } 1058 }
947 1059
948 dss_setup_fifos(); 1060 /* step 1: setup fifos/fifomerge before enabling the manager */
1061
1062 fifo_merge = get_use_fifo_merge();
1063 dss_setup_fifos(fifo_merge);
1064 dss_apply_fifo_merge(fifo_merge);
949 1065
950 dss_write_regs(); 1066 dss_write_regs();
951 dss_set_go_bits(); 1067 dss_set_go_bits();
952 1068
1069 spin_unlock_irqrestore(&data_lock, flags);
1070
1071 /* wait until fifo config is in */
1072 wait_pending_extra_info_updates();
1073
1074 /* step 2: enable the manager */
1075 spin_lock_irqsave(&data_lock, flags);
1076
953 if (!mgr_manual_update(mgr)) 1077 if (!mgr_manual_update(mgr))
954 mp->updating = true; 1078 mp->updating = true;
955 1079
@@ -974,6 +1098,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
974{ 1098{
975 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1099 struct mgr_priv_data *mp = get_mgr_priv(mgr);
976 unsigned long flags; 1100 unsigned long flags;
1101 bool fifo_merge;
977 1102
978 mutex_lock(&apply_lock); 1103 mutex_lock(&apply_lock);
979 1104
@@ -988,8 +1113,16 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
988 mp->updating = false; 1113 mp->updating = false;
989 mp->enabled = false; 1114 mp->enabled = false;
990 1115
1116 fifo_merge = get_use_fifo_merge();
1117 dss_setup_fifos(fifo_merge);
1118 dss_apply_fifo_merge(fifo_merge);
1119
1120 dss_write_regs();
1121 dss_set_go_bits();
1122
991 spin_unlock_irqrestore(&data_lock, flags); 1123 spin_unlock_irqrestore(&data_lock, flags);
992 1124
1125 wait_pending_extra_info_updates();
993out: 1126out:
994 mutex_unlock(&apply_lock); 1127 mutex_unlock(&apply_lock);
995} 1128}
@@ -1241,6 +1374,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1241{ 1374{
1242 struct ovl_priv_data *op = get_ovl_priv(ovl); 1375 struct ovl_priv_data *op = get_ovl_priv(ovl);
1243 unsigned long flags; 1376 unsigned long flags;
1377 bool fifo_merge;
1244 int r; 1378 int r;
1245 1379
1246 mutex_lock(&apply_lock); 1380 mutex_lock(&apply_lock);
@@ -1266,7 +1400,22 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1266 goto err2; 1400 goto err2;
1267 } 1401 }
1268 1402
1269 dss_setup_fifos(); 1403 /* step 1: configure fifos/fifomerge for currently enabled ovls */
1404
1405 fifo_merge = get_use_fifo_merge();
1406 dss_setup_fifos(fifo_merge);
1407 dss_apply_fifo_merge(fifo_merge);
1408
1409 dss_write_regs();
1410 dss_set_go_bits();
1411
1412 spin_unlock_irqrestore(&data_lock, flags);
1413
1414 /* wait for fifo configs to go in */
1415 wait_pending_extra_info_updates();
1416
1417 /* step 2: enable the overlay */
1418 spin_lock_irqsave(&data_lock, flags);
1270 1419
1271 op->enabling = false; 1420 op->enabling = false;
1272 dss_apply_ovl_enable(ovl, true); 1421 dss_apply_ovl_enable(ovl, true);
@@ -1294,6 +1443,7 @@ int dss_ovl_disable(struct omap_overlay *ovl)
1294{ 1443{
1295 struct ovl_priv_data *op = get_ovl_priv(ovl); 1444 struct ovl_priv_data *op = get_ovl_priv(ovl);
1296 unsigned long flags; 1445 unsigned long flags;
1446 bool fifo_merge;
1297 int r; 1447 int r;
1298 1448
1299 mutex_lock(&apply_lock); 1449 mutex_lock(&apply_lock);
@@ -1308,9 +1458,11 @@ int dss_ovl_disable(struct omap_overlay *ovl)
1308 goto err; 1458 goto err;
1309 } 1459 }
1310 1460
1461 /* step 1: disable the overlay */
1311 spin_lock_irqsave(&data_lock, flags); 1462 spin_lock_irqsave(&data_lock, flags);
1312 1463
1313 dss_apply_ovl_enable(ovl, false); 1464 dss_apply_ovl_enable(ovl, false);
1465
1314 dss_write_regs(); 1466 dss_write_regs();
1315 dss_set_go_bits(); 1467 dss_set_go_bits();
1316 1468
@@ -1319,6 +1471,21 @@ int dss_ovl_disable(struct omap_overlay *ovl)
1319 /* wait for the overlay to be disabled */ 1471 /* wait for the overlay to be disabled */
1320 wait_pending_extra_info_updates(); 1472 wait_pending_extra_info_updates();
1321 1473
1474 /* step 2: configure fifos/fifomerge */
1475 spin_lock_irqsave(&data_lock, flags);
1476
1477 fifo_merge = get_use_fifo_merge();
1478 dss_setup_fifos(fifo_merge);
1479 dss_apply_fifo_merge(fifo_merge);
1480
1481 dss_write_regs();
1482 dss_set_go_bits();
1483
1484 spin_unlock_irqrestore(&data_lock, flags);
1485
1486 /* wait for fifo config to go in */
1487 wait_pending_extra_info_updates();
1488
1322 mutex_unlock(&apply_lock); 1489 mutex_unlock(&apply_lock);
1323 1490
1324 return 0; 1491 return 0;
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 8613f86fb56d..e8a120771ac6 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -183,42 +183,6 @@ static int omap_dss_probe(struct platform_device *pdev)
183 dss_init_overlay_managers(pdev); 183 dss_init_overlay_managers(pdev);
184 dss_init_overlays(pdev); 184 dss_init_overlays(pdev);
185 185
186 r = dss_init_platform_driver();
187 if (r) {
188 DSSERR("Failed to initialize DSS platform driver\n");
189 goto err_dss;
190 }
191
192 r = dispc_init_platform_driver();
193 if (r) {
194 DSSERR("Failed to initialize dispc platform driver\n");
195 goto err_dispc;
196 }
197
198 r = rfbi_init_platform_driver();
199 if (r) {
200 DSSERR("Failed to initialize rfbi platform driver\n");
201 goto err_rfbi;
202 }
203
204 r = venc_init_platform_driver();
205 if (r) {
206 DSSERR("Failed to initialize venc platform driver\n");
207 goto err_venc;
208 }
209
210 r = dsi_init_platform_driver();
211 if (r) {
212 DSSERR("Failed to initialize DSI platform driver\n");
213 goto err_dsi;
214 }
215
216 r = hdmi_init_platform_driver();
217 if (r) {
218 DSSERR("Failed to initialize hdmi\n");
219 goto err_hdmi;
220 }
221
222 r = dss_initialize_debugfs(); 186 r = dss_initialize_debugfs();
223 if (r) 187 if (r)
224 goto err_debugfs; 188 goto err_debugfs;
@@ -246,18 +210,6 @@ static int omap_dss_probe(struct platform_device *pdev)
246err_register: 210err_register:
247 dss_uninitialize_debugfs(); 211 dss_uninitialize_debugfs();
248err_debugfs: 212err_debugfs:
249 hdmi_uninit_platform_driver();
250err_hdmi:
251 dsi_uninit_platform_driver();
252err_dsi:
253 venc_uninit_platform_driver();
254err_venc:
255 dispc_uninit_platform_driver();
256err_dispc:
257 rfbi_uninit_platform_driver();
258err_rfbi:
259 dss_uninit_platform_driver();
260err_dss:
261 213
262 return r; 214 return r;
263} 215}
@@ -269,13 +221,6 @@ static int omap_dss_remove(struct platform_device *pdev)
269 221
270 dss_uninitialize_debugfs(); 222 dss_uninitialize_debugfs();
271 223
272 hdmi_uninit_platform_driver();
273 dsi_uninit_platform_driver();
274 venc_uninit_platform_driver();
275 rfbi_uninit_platform_driver();
276 dispc_uninit_platform_driver();
277 dss_uninit_platform_driver();
278
279 dss_uninit_overlays(pdev); 224 dss_uninit_overlays(pdev);
280 dss_uninit_overlay_managers(pdev); 225 dss_uninit_overlay_managers(pdev);
281 226
@@ -525,6 +470,80 @@ static int omap_dss_bus_register(void)
525 470
526/* INIT */ 471/* INIT */
527 472
473static int __init omap_dss_register_drivers(void)
474{
475 int r;
476
477 r = platform_driver_register(&omap_dss_driver);
478 if (r)
479 return r;
480
481 r = dss_init_platform_driver();
482 if (r) {
483 DSSERR("Failed to initialize DSS platform driver\n");
484 goto err_dss;
485 }
486
487 r = dispc_init_platform_driver();
488 if (r) {
489 DSSERR("Failed to initialize dispc platform driver\n");
490 goto err_dispc;
491 }
492
493 r = rfbi_init_platform_driver();
494 if (r) {
495 DSSERR("Failed to initialize rfbi platform driver\n");
496 goto err_rfbi;
497 }
498
499 r = venc_init_platform_driver();
500 if (r) {
501 DSSERR("Failed to initialize venc platform driver\n");
502 goto err_venc;
503 }
504
505 r = dsi_init_platform_driver();
506 if (r) {
507 DSSERR("Failed to initialize DSI platform driver\n");
508 goto err_dsi;
509 }
510
511 r = hdmi_init_platform_driver();
512 if (r) {
513 DSSERR("Failed to initialize hdmi\n");
514 goto err_hdmi;
515 }
516
517 return 0;
518
519err_hdmi:
520 dsi_uninit_platform_driver();
521err_dsi:
522 venc_uninit_platform_driver();
523err_venc:
524 rfbi_uninit_platform_driver();
525err_rfbi:
526 dispc_uninit_platform_driver();
527err_dispc:
528 dss_uninit_platform_driver();
529err_dss:
530 platform_driver_unregister(&omap_dss_driver);
531
532 return r;
533}
534
535static void __exit omap_dss_unregister_drivers(void)
536{
537 hdmi_uninit_platform_driver();
538 dsi_uninit_platform_driver();
539 venc_uninit_platform_driver();
540 rfbi_uninit_platform_driver();
541 dispc_uninit_platform_driver();
542 dss_uninit_platform_driver();
543
544 platform_driver_unregister(&omap_dss_driver);
545}
546
528#ifdef CONFIG_OMAP2_DSS_MODULE 547#ifdef CONFIG_OMAP2_DSS_MODULE
529static void omap_dss_bus_unregister(void) 548static void omap_dss_bus_unregister(void)
530{ 549{
@@ -541,7 +560,7 @@ static int __init omap_dss_init(void)
541 if (r) 560 if (r)
542 return r; 561 return r;
543 562
544 r = platform_driver_register(&omap_dss_driver); 563 r = omap_dss_register_drivers();
545 if (r) { 564 if (r) {
546 omap_dss_bus_unregister(); 565 omap_dss_bus_unregister();
547 return r; 566 return r;
@@ -562,7 +581,7 @@ static void __exit omap_dss_exit(void)
562 core.vdds_sdi_reg = NULL; 581 core.vdds_sdi_reg = NULL;
563 } 582 }
564 583
565 platform_driver_unregister(&omap_dss_driver); 584 omap_dss_unregister_drivers();
566 585
567 omap_dss_bus_unregister(); 586 omap_dss_bus_unregister();
568} 587}
@@ -577,7 +596,7 @@ static int __init omap_dss_init(void)
577 596
578static int __init omap_dss_init2(void) 597static int __init omap_dss_init2(void)
579{ 598{
580 return platform_driver_register(&omap_dss_driver); 599 return omap_dss_register_drivers();
581} 600}
582 601
583core_initcall(omap_dss_init); 602core_initcall(omap_dss_init);
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index e1626a1d5c45..bddd64b435b9 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -37,7 +37,6 @@
37#include <linux/platform_device.h> 37#include <linux/platform_device.h>
38#include <linux/pm_runtime.h> 38#include <linux/pm_runtime.h>
39 39
40#include <plat/sram.h>
41#include <plat/clock.h> 40#include <plat/clock.h>
42 41
43#include <video/omapdss.h> 42#include <video/omapdss.h>
@@ -736,11 +735,11 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
736 switch (color_mode) { 735 switch (color_mode) {
737 case OMAP_DSS_COLOR_NV12: 736 case OMAP_DSS_COLOR_NV12:
738 m = 0x0; break; 737 m = 0x0; break;
739 case OMAP_DSS_COLOR_RGB12U: 738 case OMAP_DSS_COLOR_RGBX16:
740 m = 0x1; break; 739 m = 0x1; break;
741 case OMAP_DSS_COLOR_RGBA16: 740 case OMAP_DSS_COLOR_RGBA16:
742 m = 0x2; break; 741 m = 0x2; break;
743 case OMAP_DSS_COLOR_RGBX16: 742 case OMAP_DSS_COLOR_RGB12U:
744 m = 0x4; break; 743 m = 0x4; break;
745 case OMAP_DSS_COLOR_ARGB16: 744 case OMAP_DSS_COLOR_ARGB16:
746 m = 0x5; break; 745 m = 0x5; break;
@@ -789,9 +788,9 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
789 m = 0x8; break; 788 m = 0x8; break;
790 case OMAP_DSS_COLOR_RGB24P: 789 case OMAP_DSS_COLOR_RGB24P:
791 m = 0x9; break; 790 m = 0x9; break;
792 case OMAP_DSS_COLOR_YUV2: 791 case OMAP_DSS_COLOR_RGBX16:
793 m = 0xa; break; 792 m = 0xa; break;
794 case OMAP_DSS_COLOR_UYVY: 793 case OMAP_DSS_COLOR_RGBA16:
795 m = 0xb; break; 794 m = 0xb; break;
796 case OMAP_DSS_COLOR_ARGB32: 795 case OMAP_DSS_COLOR_ARGB32:
797 m = 0xc; break; 796 m = 0xc; break;
@@ -909,7 +908,7 @@ static void dispc_configure_burst_sizes(void)
909 dispc_ovl_set_burst_size(i, burst_size); 908 dispc_ovl_set_burst_size(i, burst_size);
910} 909}
911 910
912u32 dispc_ovl_get_burst_size(enum omap_plane plane) 911static u32 dispc_ovl_get_burst_size(enum omap_plane plane)
913{ 912{
914 unsigned unit = dss_feat_get_burst_size_unit(); 913 unsigned unit = dss_feat_get_burst_size_unit();
915 /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ 914 /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
@@ -1018,7 +1017,7 @@ static void dispc_read_plane_fifo_sizes(void)
1018 } 1017 }
1019} 1018}
1020 1019
1021u32 dispc_ovl_get_fifo_size(enum omap_plane plane) 1020static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
1022{ 1021{
1023 return dispc.fifo_size[plane]; 1022 return dispc.fifo_size[plane];
1024} 1023}
@@ -1039,13 +1038,13 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
1039 dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); 1038 dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
1040 dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); 1039 dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
1041 1040
1042 DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", 1041 DSSDBG("fifo(%d) threshold (bytes), old %u/%u, new %u/%u\n",
1043 plane, 1042 plane,
1044 REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), 1043 REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
1045 lo_start, lo_end), 1044 lo_start, lo_end) * unit,
1046 REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), 1045 REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
1047 hi_start, hi_end), 1046 hi_start, hi_end) * unit,
1048 low, high); 1047 low * unit, high * unit);
1049 1048
1050 dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane), 1049 dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
1051 FLD_VAL(high, hi_start, hi_end) | 1050 FLD_VAL(high, hi_start, hi_end) |
@@ -1054,10 +1053,53 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
1054 1053
1055void dispc_enable_fifomerge(bool enable) 1054void dispc_enable_fifomerge(bool enable)
1056{ 1055{
1056 if (!dss_has_feature(FEAT_FIFO_MERGE)) {
1057 WARN_ON(enable);
1058 return;
1059 }
1060
1057 DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled"); 1061 DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
1058 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); 1062 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
1059} 1063}
1060 1064
1065void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
1066 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge)
1067{
1068 /*
1069 * All sizes are in bytes. Both the buffer and burst are made of
1070 * buffer_units, and the fifo thresholds must be buffer_unit aligned.
1071 */
1072
1073 unsigned buf_unit = dss_feat_get_buffer_size_unit();
1074 unsigned ovl_fifo_size, total_fifo_size, burst_size;
1075 int i;
1076
1077 burst_size = dispc_ovl_get_burst_size(plane);
1078 ovl_fifo_size = dispc_ovl_get_fifo_size(plane);
1079
1080 if (use_fifomerge) {
1081 total_fifo_size = 0;
1082 for (i = 0; i < omap_dss_get_num_overlays(); ++i)
1083 total_fifo_size += dispc_ovl_get_fifo_size(i);
1084 } else {
1085 total_fifo_size = ovl_fifo_size;
1086 }
1087
1088 /*
1089 * We use the same low threshold for both fifomerge and non-fifomerge
1090 * cases, but for fifomerge we calculate the high threshold using the
1091 * combined fifo size
1092 */
1093
1094 if (dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
1095 *fifo_low = ovl_fifo_size - burst_size * 2;
1096 *fifo_high = total_fifo_size - burst_size;
1097 } else {
1098 *fifo_low = ovl_fifo_size - burst_size;
1099 *fifo_high = total_fifo_size - buf_unit;
1100 }
1101}
1102
1061static void dispc_ovl_set_fir(enum omap_plane plane, 1103static void dispc_ovl_set_fir(enum omap_plane plane,
1062 int hinc, int vinc, 1104 int hinc, int vinc,
1063 enum omap_color_component color_comp) 1105 enum omap_color_component color_comp)
@@ -1651,6 +1693,7 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
1651 u16 height, u16 out_width, u16 out_height) 1693 u16 height, u16 out_width, u16 out_height)
1652{ 1694{
1653 unsigned int hf, vf; 1695 unsigned int hf, vf;
1696 unsigned long pclk = dispc_mgr_pclk_rate(channel);
1654 1697
1655 /* 1698 /*
1656 * FIXME how to determine the 'A' factor 1699 * FIXME how to determine the 'A' factor
@@ -1673,13 +1716,16 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
1673 1716
1674 if (cpu_is_omap24xx()) { 1717 if (cpu_is_omap24xx()) {
1675 if (vf > 1 && hf > 1) 1718 if (vf > 1 && hf > 1)
1676 return dispc_mgr_pclk_rate(channel) * 4; 1719 return pclk * 4;
1677 else 1720 else
1678 return dispc_mgr_pclk_rate(channel) * 2; 1721 return pclk * 2;
1679 } else if (cpu_is_omap34xx()) { 1722 } else if (cpu_is_omap34xx()) {
1680 return dispc_mgr_pclk_rate(channel) * vf * hf; 1723 return pclk * vf * hf;
1681 } else { 1724 } else {
1682 return dispc_mgr_pclk_rate(channel) * hf; 1725 if (hf > 1)
1726 return DIV_ROUND_UP(pclk, out_width) * width;
1727 else
1728 return pclk;
1683 } 1729 }
1684} 1730}
1685 1731
@@ -3298,15 +3344,6 @@ static int omap_dispchw_probe(struct platform_device *pdev)
3298 3344
3299 dispc.pdev = pdev; 3345 dispc.pdev = pdev;
3300 3346
3301 clk = clk_get(&pdev->dev, "fck");
3302 if (IS_ERR(clk)) {
3303 DSSERR("can't get fck\n");
3304 r = PTR_ERR(clk);
3305 goto err_get_clk;
3306 }
3307
3308 dispc.dss_clk = clk;
3309
3310 spin_lock_init(&dispc.irq_lock); 3347 spin_lock_init(&dispc.irq_lock);
3311 3348
3312#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 3349#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -3319,29 +3356,38 @@ static int omap_dispchw_probe(struct platform_device *pdev)
3319 dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); 3356 dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
3320 if (!dispc_mem) { 3357 if (!dispc_mem) {
3321 DSSERR("can't get IORESOURCE_MEM DISPC\n"); 3358 DSSERR("can't get IORESOURCE_MEM DISPC\n");
3322 r = -EINVAL; 3359 return -EINVAL;
3323 goto err_ioremap;
3324 } 3360 }
3325 dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem)); 3361
3362 dispc.base = devm_ioremap(&pdev->dev, dispc_mem->start,
3363 resource_size(dispc_mem));
3326 if (!dispc.base) { 3364 if (!dispc.base) {
3327 DSSERR("can't ioremap DISPC\n"); 3365 DSSERR("can't ioremap DISPC\n");
3328 r = -ENOMEM; 3366 return -ENOMEM;
3329 goto err_ioremap;
3330 } 3367 }
3368
3331 dispc.irq = platform_get_irq(dispc.pdev, 0); 3369 dispc.irq = platform_get_irq(dispc.pdev, 0);
3332 if (dispc.irq < 0) { 3370 if (dispc.irq < 0) {
3333 DSSERR("platform_get_irq failed\n"); 3371 DSSERR("platform_get_irq failed\n");
3334 r = -ENODEV; 3372 return -ENODEV;
3335 goto err_irq;
3336 } 3373 }
3337 3374
3338 r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED, 3375 r = devm_request_irq(&pdev->dev, dispc.irq, omap_dispc_irq_handler,
3339 "OMAP DISPC", dispc.pdev); 3376 IRQF_SHARED, "OMAP DISPC", dispc.pdev);
3340 if (r < 0) { 3377 if (r < 0) {
3341 DSSERR("request_irq failed\n"); 3378 DSSERR("request_irq failed\n");
3342 goto err_irq; 3379 return r;
3380 }
3381
3382 clk = clk_get(&pdev->dev, "fck");
3383 if (IS_ERR(clk)) {
3384 DSSERR("can't get fck\n");
3385 r = PTR_ERR(clk);
3386 return r;
3343 } 3387 }
3344 3388
3389 dispc.dss_clk = clk;
3390
3345 pm_runtime_enable(&pdev->dev); 3391 pm_runtime_enable(&pdev->dev);
3346 3392
3347 r = dispc_runtime_get(); 3393 r = dispc_runtime_get();
@@ -3362,12 +3408,7 @@ static int omap_dispchw_probe(struct platform_device *pdev)
3362 3408
3363err_runtime_get: 3409err_runtime_get:
3364 pm_runtime_disable(&pdev->dev); 3410 pm_runtime_disable(&pdev->dev);
3365 free_irq(dispc.irq, dispc.pdev);
3366err_irq:
3367 iounmap(dispc.base);
3368err_ioremap:
3369 clk_put(dispc.dss_clk); 3411 clk_put(dispc.dss_clk);
3370err_get_clk:
3371 return r; 3412 return r;
3372} 3413}
3373 3414
@@ -3377,8 +3418,6 @@ static int omap_dispchw_remove(struct platform_device *pdev)
3377 3418
3378 clk_put(dispc.dss_clk); 3419 clk_put(dispc.dss_clk);
3379 3420
3380 free_irq(dispc.irq, dispc.pdev);
3381 iounmap(dispc.base);
3382 return 0; 3421 return 0;
3383} 3422}
3384 3423
diff --git a/drivers/video/omap2/dss/dispc_coefs.c b/drivers/video/omap2/dss/dispc_coefs.c
index 069bccbb3f12..038c15b04215 100644
--- a/drivers/video/omap2/dss/dispc_coefs.c
+++ b/drivers/video/omap2/dss/dispc_coefs.c
@@ -19,14 +19,13 @@
19 19
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <video/omapdss.h> 21#include <video/omapdss.h>
22#include "dispc.h"
23 22
24#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0])) 23#include "dispc.h"
25 24
26static const struct dispc_coef coef3_M8[8] = { 25static const struct dispc_coef coef3_M8[8] = {
27 { 0, 0, 128, 0, 0 }, 26 { 0, 0, 128, 0, 0 },
28 { 0, -4, 123, 9, 0 }, 27 { 0, -4, 123, 9, 0 },
29 { 0, -4, 108, 87, 0 }, 28 { 0, -4, 108, 24, 0 },
30 { 0, -2, 87, 43, 0 }, 29 { 0, -2, 87, 43, 0 },
31 { 0, 64, 64, 0, 0 }, 30 { 0, 64, 64, 0, 0 },
32 { 0, 43, 87, -2, 0 }, 31 { 0, 43, 87, -2, 0 },
@@ -168,7 +167,7 @@ static const struct dispc_coef coef5_M8[8] = {
168 167
169static const struct dispc_coef coef5_M9[8] = { 168static const struct dispc_coef coef5_M9[8] = {
170 { -3, 10, 114, 10, -3 }, 169 { -3, 10, 114, 10, -3 },
171 { -6, 24, 110, 0, -1 }, 170 { -6, 24, 111, 0, -1 },
172 { -8, 40, 103, -7, 0 }, 171 { -8, 40, 103, -7, 0 },
173 { -11, 58, 91, -11, 1 }, 172 { -11, 58, 91, -11, 1 },
174 { 0, -12, 76, 76, -12 }, 173 { 0, -12, 76, 76, -12 },
@@ -319,7 +318,7 @@ const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps)
319 }; 318 };
320 319
321 inc /= 128; 320 inc /= 128;
322 for (i = 0; i < ARRAY_LEN(coefs); ++i) 321 for (i = 0; i < ARRAY_SIZE(coefs); ++i)
323 if (inc >= coefs[i].Mmin && inc <= coefs[i].Mmax) 322 if (inc >= coefs[i].Mmin && inc <= coefs[i].Mmax)
324 return five_taps ? coefs[i].coef_5 : coefs[i].coef_3; 323 return five_taps ? coefs[i].coef_5 : coefs[i].coef_3;
325 return NULL; 324 return NULL;
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index be331dc5a61b..4424c198dbcd 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -279,16 +279,6 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
279} 279}
280EXPORT_SYMBOL(omapdss_default_get_resolution); 280EXPORT_SYMBOL(omapdss_default_get_resolution);
281 281
282void default_get_overlay_fifo_thresholds(enum omap_plane plane,
283 u32 fifo_size, u32 burst_size,
284 u32 *fifo_low, u32 *fifo_high)
285{
286 unsigned buf_unit = dss_feat_get_buffer_size_unit();
287
288 *fifo_high = fifo_size - buf_unit;
289 *fifo_low = fifo_size - burst_size;
290}
291
292int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) 282int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
293{ 283{
294 switch (dssdev->type) { 284 switch (dssdev->type) {
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 52f36ec1c8bb..662d14f8c2c3 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4524,14 +4524,6 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
4524} 4524}
4525EXPORT_SYMBOL(omapdss_dsi_enable_te); 4525EXPORT_SYMBOL(omapdss_dsi_enable_te);
4526 4526
4527void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
4528 u32 fifo_size, u32 burst_size,
4529 u32 *fifo_low, u32 *fifo_high)
4530{
4531 *fifo_high = fifo_size - burst_size;
4532 *fifo_low = fifo_size - burst_size * 2;
4533}
4534
4535int dsi_init_display(struct omap_dss_device *dssdev) 4527int dsi_init_display(struct omap_dss_device *dssdev)
4536{ 4528{
4537 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4529 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4695,11 +4687,9 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
4695 struct resource *dsi_mem; 4687 struct resource *dsi_mem;
4696 struct dsi_data *dsi; 4688 struct dsi_data *dsi;
4697 4689
4698 dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); 4690 dsi = devm_kzalloc(&dsidev->dev, sizeof(*dsi), GFP_KERNEL);
4699 if (!dsi) { 4691 if (!dsi)
4700 r = -ENOMEM; 4692 return -ENOMEM;
4701 goto err_alloc;
4702 }
4703 4693
4704 dsi->pdev = dsidev; 4694 dsi->pdev = dsidev;
4705 dsi_pdev_map[dsi_module] = dsidev; 4695 dsi_pdev_map[dsi_module] = dsidev;
@@ -4722,12 +4712,6 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
4722 mutex_init(&dsi->lock); 4712 mutex_init(&dsi->lock);
4723 sema_init(&dsi->bus_lock, 1); 4713 sema_init(&dsi->bus_lock, 1);
4724 4714
4725 r = dsi_get_clocks(dsidev);
4726 if (r)
4727 goto err_get_clk;
4728
4729 pm_runtime_enable(&dsidev->dev);
4730
4731 INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work, 4715 INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work,
4732 dsi_framedone_timeout_work_callback); 4716 dsi_framedone_timeout_work_callback);
4733 4717
@@ -4739,27 +4723,27 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
4739 dsi_mem = platform_get_resource(dsi->pdev, IORESOURCE_MEM, 0); 4723 dsi_mem = platform_get_resource(dsi->pdev, IORESOURCE_MEM, 0);
4740 if (!dsi_mem) { 4724 if (!dsi_mem) {
4741 DSSERR("can't get IORESOURCE_MEM DSI\n"); 4725 DSSERR("can't get IORESOURCE_MEM DSI\n");
4742 r = -EINVAL; 4726 return -EINVAL;
4743 goto err_ioremap;
4744 } 4727 }
4745 dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem)); 4728
4729 dsi->base = devm_ioremap(&dsidev->dev, dsi_mem->start,
4730 resource_size(dsi_mem));
4746 if (!dsi->base) { 4731 if (!dsi->base) {
4747 DSSERR("can't ioremap DSI\n"); 4732 DSSERR("can't ioremap DSI\n");
4748 r = -ENOMEM; 4733 return -ENOMEM;
4749 goto err_ioremap;
4750 } 4734 }
4735
4751 dsi->irq = platform_get_irq(dsi->pdev, 0); 4736 dsi->irq = platform_get_irq(dsi->pdev, 0);
4752 if (dsi->irq < 0) { 4737 if (dsi->irq < 0) {
4753 DSSERR("platform_get_irq failed\n"); 4738 DSSERR("platform_get_irq failed\n");
4754 r = -ENODEV; 4739 return -ENODEV;
4755 goto err_get_irq;
4756 } 4740 }
4757 4741
4758 r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED, 4742 r = devm_request_irq(&dsidev->dev, dsi->irq, omap_dsi_irq_handler,
4759 dev_name(&dsidev->dev), dsi->pdev); 4743 IRQF_SHARED, dev_name(&dsidev->dev), dsi->pdev);
4760 if (r < 0) { 4744 if (r < 0) {
4761 DSSERR("request_irq failed\n"); 4745 DSSERR("request_irq failed\n");
4762 goto err_get_irq; 4746 return r;
4763 } 4747 }
4764 4748
4765 /* DSI VCs initialization */ 4749 /* DSI VCs initialization */
@@ -4771,9 +4755,15 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
4771 4755
4772 dsi_calc_clock_param_ranges(dsidev); 4756 dsi_calc_clock_param_ranges(dsidev);
4773 4757
4758 r = dsi_get_clocks(dsidev);
4759 if (r)
4760 return r;
4761
4762 pm_runtime_enable(&dsidev->dev);
4763
4774 r = dsi_runtime_get(dsidev); 4764 r = dsi_runtime_get(dsidev);
4775 if (r) 4765 if (r)
4776 goto err_get_dsi; 4766 goto err_runtime_get;
4777 4767
4778 rev = dsi_read_reg(dsidev, DSI_REVISION); 4768 rev = dsi_read_reg(dsidev, DSI_REVISION);
4779 dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", 4769 dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
@@ -4791,15 +4781,9 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
4791 4781
4792 return 0; 4782 return 0;
4793 4783
4794err_get_dsi: 4784err_runtime_get:
4795 free_irq(dsi->irq, dsi->pdev);
4796err_get_irq:
4797 iounmap(dsi->base);
4798err_ioremap:
4799 pm_runtime_disable(&dsidev->dev); 4785 pm_runtime_disable(&dsidev->dev);
4800err_get_clk: 4786 dsi_put_clocks(dsidev);
4801 kfree(dsi);
4802err_alloc:
4803 return r; 4787 return r;
4804} 4788}
4805 4789
@@ -4823,11 +4807,6 @@ static int omap_dsihw_remove(struct platform_device *dsidev)
4823 dsi->vdds_dsi_reg = NULL; 4807 dsi->vdds_dsi_reg = NULL;
4824 } 4808 }
4825 4809
4826 free_irq(dsi->irq, dsi->pdev);
4827 iounmap(dsi->base);
4828
4829 kfree(dsi);
4830
4831 return 0; 4810 return 0;
4832} 4811}
4833 4812
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 77c2b5a32b5d..4a6b5eeef6a7 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -748,19 +748,19 @@ static int omap_dsshw_probe(struct platform_device *pdev)
748 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); 748 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
749 if (!dss_mem) { 749 if (!dss_mem) {
750 DSSERR("can't get IORESOURCE_MEM DSS\n"); 750 DSSERR("can't get IORESOURCE_MEM DSS\n");
751 r = -EINVAL; 751 return -EINVAL;
752 goto err_ioremap;
753 } 752 }
754 dss.base = ioremap(dss_mem->start, resource_size(dss_mem)); 753
754 dss.base = devm_ioremap(&pdev->dev, dss_mem->start,
755 resource_size(dss_mem));
755 if (!dss.base) { 756 if (!dss.base) {
756 DSSERR("can't ioremap DSS\n"); 757 DSSERR("can't ioremap DSS\n");
757 r = -ENOMEM; 758 return -ENOMEM;
758 goto err_ioremap;
759 } 759 }
760 760
761 r = dss_get_clocks(); 761 r = dss_get_clocks();
762 if (r) 762 if (r)
763 goto err_clocks; 763 return r;
764 764
765 pm_runtime_enable(&pdev->dev); 765 pm_runtime_enable(&pdev->dev);
766 766
@@ -808,9 +808,6 @@ err_dpi:
808err_runtime_get: 808err_runtime_get:
809 pm_runtime_disable(&pdev->dev); 809 pm_runtime_disable(&pdev->dev);
810 dss_put_clocks(); 810 dss_put_clocks();
811err_clocks:
812 iounmap(dss.base);
813err_ioremap:
814 return r; 811 return r;
815} 812}
816 813
@@ -819,8 +816,6 @@ static int omap_dsshw_remove(struct platform_device *pdev)
819 dpi_exit(); 816 dpi_exit();
820 sdi_exit(); 817 sdi_exit();
821 818
822 iounmap(dss.base);
823
824 pm_runtime_disable(&pdev->dev); 819 pm_runtime_disable(&pdev->dev);
825 820
826 dss_put_clocks(); 821 dss_put_clocks();
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 32ff69fb3333..d4b3dff2ead3 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -202,9 +202,6 @@ void dss_uninit_device(struct platform_device *pdev,
202 struct omap_dss_device *dssdev); 202 struct omap_dss_device *dssdev);
203bool dss_use_replication(struct omap_dss_device *dssdev, 203bool dss_use_replication(struct omap_dss_device *dssdev,
204 enum omap_color_mode mode); 204 enum omap_color_mode mode);
205void default_get_overlay_fifo_thresholds(enum omap_plane plane,
206 u32 fifo_size, u32 burst_size,
207 u32 *fifo_low, u32 *fifo_high);
208 205
209/* manager */ 206/* manager */
210int dss_init_overlay_managers(struct platform_device *pdev); 207int dss_init_overlay_managers(struct platform_device *pdev);
@@ -313,9 +310,6 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
313int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, 310int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
314 bool enable_hsdiv); 311 bool enable_hsdiv);
315void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes); 312void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
316void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
317 u32 fifo_size, u32 burst_size,
318 u32 *fifo_low, u32 *fifo_high);
319void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev); 313void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
320void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev); 314void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
321struct platform_device *dsi_get_dsidev_from_id(int module); 315struct platform_device *dsi_get_dsidev_from_id(int module);
@@ -429,8 +423,8 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
429 423
430 424
431void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); 425void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
432u32 dispc_ovl_get_fifo_size(enum omap_plane plane); 426void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
433u32 dispc_ovl_get_burst_size(enum omap_plane plane); 427 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge);
434int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 428int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
435 bool ilace, bool replication); 429 bool ilace, bool replication);
436int dispc_ovl_enable(enum omap_plane plane, bool enable); 430int dispc_ovl_enable(enum omap_plane plane, bool enable);
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index afcb59301c37..ce14aa6dd672 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -41,7 +41,8 @@ struct omap_dss_features {
41 const struct dss_reg_field *reg_fields; 41 const struct dss_reg_field *reg_fields;
42 const int num_reg_fields; 42 const int num_reg_fields;
43 43
44 const u32 has_feature; 44 const enum dss_feat_id *features;
45 const int num_features;
45 46
46 const int num_mgrs; 47 const int num_mgrs;
47 const int num_ovls; 48 const int num_ovls;
@@ -189,7 +190,8 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
189 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | 190 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
190 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 | 191 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
191 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 | 192 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
192 OMAP_DSS_COLOR_ARGB16_1555, 193 OMAP_DSS_COLOR_ARGB16_1555 | OMAP_DSS_COLOR_RGBX16 |
194 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_XRGB16_1555,
193 195
194 /* OMAP_DSS_VIDEO1 */ 196 /* OMAP_DSS_VIDEO1 */
195 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U | 197 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
@@ -337,15 +339,110 @@ static const struct dss_param_range omap4_dss_param_range[] = {
337 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, 339 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
338}; 340};
339 341
342static const enum dss_feat_id omap2_dss_feat_list[] = {
343 FEAT_LCDENABLEPOL,
344 FEAT_LCDENABLESIGNAL,
345 FEAT_PCKFREEENABLE,
346 FEAT_FUNCGATED,
347 FEAT_ROWREPEATENABLE,
348 FEAT_RESIZECONF,
349};
350
351static const enum dss_feat_id omap3430_dss_feat_list[] = {
352 FEAT_LCDENABLEPOL,
353 FEAT_LCDENABLESIGNAL,
354 FEAT_PCKFREEENABLE,
355 FEAT_FUNCGATED,
356 FEAT_LINEBUFFERSPLIT,
357 FEAT_ROWREPEATENABLE,
358 FEAT_RESIZECONF,
359 FEAT_DSI_PLL_FREQSEL,
360 FEAT_DSI_REVERSE_TXCLKESC,
361 FEAT_VENC_REQUIRES_TV_DAC_CLK,
362 FEAT_CPR,
363 FEAT_PRELOAD,
364 FEAT_FIR_COEF_V,
365 FEAT_ALPHA_FIXED_ZORDER,
366 FEAT_FIFO_MERGE,
367 FEAT_OMAP3_DSI_FIFO_BUG,
368};
369
370static const enum dss_feat_id omap3630_dss_feat_list[] = {
371 FEAT_LCDENABLEPOL,
372 FEAT_LCDENABLESIGNAL,
373 FEAT_PCKFREEENABLE,
374 FEAT_FUNCGATED,
375 FEAT_LINEBUFFERSPLIT,
376 FEAT_ROWREPEATENABLE,
377 FEAT_RESIZECONF,
378 FEAT_DSI_PLL_PWR_BUG,
379 FEAT_DSI_PLL_FREQSEL,
380 FEAT_CPR,
381 FEAT_PRELOAD,
382 FEAT_FIR_COEF_V,
383 FEAT_ALPHA_FIXED_ZORDER,
384 FEAT_FIFO_MERGE,
385 FEAT_OMAP3_DSI_FIFO_BUG,
386};
387
388static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = {
389 FEAT_MGR_LCD2,
390 FEAT_CORE_CLK_DIV,
391 FEAT_LCD_CLK_SRC,
392 FEAT_DSI_DCS_CMD_CONFIG_VC,
393 FEAT_DSI_VC_OCP_WIDTH,
394 FEAT_DSI_GNQ,
395 FEAT_HANDLE_UV_SEPARATE,
396 FEAT_ATTR2,
397 FEAT_CPR,
398 FEAT_PRELOAD,
399 FEAT_FIR_COEF_V,
400 FEAT_ALPHA_FREE_ZORDER,
401 FEAT_FIFO_MERGE,
402};
403
404static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = {
405 FEAT_MGR_LCD2,
406 FEAT_CORE_CLK_DIV,
407 FEAT_LCD_CLK_SRC,
408 FEAT_DSI_DCS_CMD_CONFIG_VC,
409 FEAT_DSI_VC_OCP_WIDTH,
410 FEAT_DSI_GNQ,
411 FEAT_HDMI_CTS_SWMODE,
412 FEAT_HANDLE_UV_SEPARATE,
413 FEAT_ATTR2,
414 FEAT_CPR,
415 FEAT_PRELOAD,
416 FEAT_FIR_COEF_V,
417 FEAT_ALPHA_FREE_ZORDER,
418 FEAT_FIFO_MERGE,
419};
420
421static const enum dss_feat_id omap4_dss_feat_list[] = {
422 FEAT_MGR_LCD2,
423 FEAT_CORE_CLK_DIV,
424 FEAT_LCD_CLK_SRC,
425 FEAT_DSI_DCS_CMD_CONFIG_VC,
426 FEAT_DSI_VC_OCP_WIDTH,
427 FEAT_DSI_GNQ,
428 FEAT_HDMI_CTS_SWMODE,
429 FEAT_HDMI_AUDIO_USE_MCLK,
430 FEAT_HANDLE_UV_SEPARATE,
431 FEAT_ATTR2,
432 FEAT_CPR,
433 FEAT_PRELOAD,
434 FEAT_FIR_COEF_V,
435 FEAT_ALPHA_FREE_ZORDER,
436 FEAT_FIFO_MERGE,
437};
438
340/* OMAP2 DSS Features */ 439/* OMAP2 DSS Features */
341static const struct omap_dss_features omap2_dss_features = { 440static const struct omap_dss_features omap2_dss_features = {
342 .reg_fields = omap2_dss_reg_fields, 441 .reg_fields = omap2_dss_reg_fields,
343 .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields), 442 .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields),
344 443
345 .has_feature = 444 .features = omap2_dss_feat_list,
346 FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | 445 .num_features = ARRAY_SIZE(omap2_dss_feat_list),
347 FEAT_PCKFREEENABLE | FEAT_FUNCGATED |
348 FEAT_ROWREPEATENABLE | FEAT_RESIZECONF,
349 446
350 .num_mgrs = 2, 447 .num_mgrs = 2,
351 .num_ovls = 3, 448 .num_ovls = 3,
@@ -363,14 +460,8 @@ static const struct omap_dss_features omap3430_dss_features = {
363 .reg_fields = omap3_dss_reg_fields, 460 .reg_fields = omap3_dss_reg_fields,
364 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), 461 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
365 462
366 .has_feature = 463 .features = omap3430_dss_feat_list,
367 FEAT_LCDENABLEPOL | 464 .num_features = ARRAY_SIZE(omap3430_dss_feat_list),
368 FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
369 FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
370 FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
371 FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
372 FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
373 FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,
374 465
375 .num_mgrs = 2, 466 .num_mgrs = 2,
376 .num_ovls = 3, 467 .num_ovls = 3,
@@ -387,14 +478,8 @@ static const struct omap_dss_features omap3630_dss_features = {
387 .reg_fields = omap3_dss_reg_fields, 478 .reg_fields = omap3_dss_reg_fields,
388 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), 479 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
389 480
390 .has_feature = 481 .features = omap3630_dss_feat_list,
391 FEAT_LCDENABLEPOL | 482 .num_features = ARRAY_SIZE(omap3630_dss_feat_list),
392 FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
393 FEAT_FUNCGATED |
394 FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
395 FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
396 FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
397 FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,
398 483
399 .num_mgrs = 2, 484 .num_mgrs = 2,
400 .num_ovls = 3, 485 .num_ovls = 3,
@@ -413,13 +498,27 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
413 .reg_fields = omap4_dss_reg_fields, 498 .reg_fields = omap4_dss_reg_fields,
414 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), 499 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
415 500
416 .has_feature = 501 .features = omap4430_es1_0_dss_feat_list,
417 FEAT_MGR_LCD2 | 502 .num_features = ARRAY_SIZE(omap4430_es1_0_dss_feat_list),
418 FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | 503
419 FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | 504 .num_mgrs = 3,
420 FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | 505 .num_ovls = 4,
421 FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V | 506 .supported_displays = omap4_dss_supported_displays,
422 FEAT_ALPHA_FREE_ZORDER, 507 .supported_color_modes = omap4_dss_supported_color_modes,
508 .overlay_caps = omap4_dss_overlay_caps,
509 .clksrc_names = omap4_dss_clk_source_names,
510 .dss_params = omap4_dss_param_range,
511 .buffer_size_unit = 16,
512 .burst_size_unit = 16,
513};
514
515/* For OMAP4430 ES 2.0, 2.1 and 2.2 revisions */
516static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
517 .reg_fields = omap4_dss_reg_fields,
518 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
519
520 .features = omap4430_es2_0_1_2_dss_feat_list,
521 .num_features = ARRAY_SIZE(omap4430_es2_0_1_2_dss_feat_list),
423 522
424 .num_mgrs = 3, 523 .num_mgrs = 3,
425 .num_ovls = 4, 524 .num_ovls = 4,
@@ -437,13 +536,8 @@ static const struct omap_dss_features omap4_dss_features = {
437 .reg_fields = omap4_dss_reg_fields, 536 .reg_fields = omap4_dss_reg_fields,
438 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), 537 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
439 538
440 .has_feature = 539 .features = omap4_dss_feat_list,
441 FEAT_MGR_LCD2 | 540 .num_features = ARRAY_SIZE(omap4_dss_feat_list),
442 FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
443 FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
444 FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
445 FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
446 FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER,
447 541
448 .num_mgrs = 3, 542 .num_mgrs = 3,
449 .num_ovls = 4, 543 .num_ovls = 4,
@@ -547,7 +641,16 @@ u32 dss_feat_get_burst_size_unit(void)
547/* DSS has_feature check */ 641/* DSS has_feature check */
548bool dss_has_feature(enum dss_feat_id id) 642bool dss_has_feature(enum dss_feat_id id)
549{ 643{
550 return omap_current_dss_features->has_feature & id; 644 int i;
645 const enum dss_feat_id *features = omap_current_dss_features->features;
646 const int num_features = omap_current_dss_features->num_features;
647
648 for (i = 0; i < num_features; i++) {
649 if (features[i] == id)
650 return true;
651 }
652
653 return false;
551} 654}
552 655
553void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end) 656void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
@@ -569,6 +672,10 @@ void dss_features_init(void)
569 omap_current_dss_features = &omap3430_dss_features; 672 omap_current_dss_features = &omap3430_dss_features;
570 else if (omap_rev() == OMAP4430_REV_ES1_0) 673 else if (omap_rev() == OMAP4430_REV_ES1_0)
571 omap_current_dss_features = &omap4430_es1_0_dss_features; 674 omap_current_dss_features = &omap4430_es1_0_dss_features;
675 else if (omap_rev() == OMAP4430_REV_ES2_0 ||
676 omap_rev() == OMAP4430_REV_ES2_1 ||
677 omap_rev() == OMAP4430_REV_ES2_2)
678 omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
572 else if (cpu_is_omap44xx()) 679 else if (cpu_is_omap44xx())
573 omap_current_dss_features = &omap4_dss_features; 680 omap_current_dss_features = &omap4_dss_features;
574 else 681 else
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index cd833bbaac3d..c332e7ddfce1 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -31,33 +31,37 @@
31 31
32/* DSS has feature id */ 32/* DSS has feature id */
33enum dss_feat_id { 33enum dss_feat_id {
34 FEAT_LCDENABLEPOL = 1 << 3, 34 FEAT_LCDENABLEPOL,
35 FEAT_LCDENABLESIGNAL = 1 << 4, 35 FEAT_LCDENABLESIGNAL,
36 FEAT_PCKFREEENABLE = 1 << 5, 36 FEAT_PCKFREEENABLE,
37 FEAT_FUNCGATED = 1 << 6, 37 FEAT_FUNCGATED,
38 FEAT_MGR_LCD2 = 1 << 7, 38 FEAT_MGR_LCD2,
39 FEAT_LINEBUFFERSPLIT = 1 << 8, 39 FEAT_LINEBUFFERSPLIT,
40 FEAT_ROWREPEATENABLE = 1 << 9, 40 FEAT_ROWREPEATENABLE,
41 FEAT_RESIZECONF = 1 << 10, 41 FEAT_RESIZECONF,
42 /* Independent core clk divider */ 42 /* Independent core clk divider */
43 FEAT_CORE_CLK_DIV = 1 << 11, 43 FEAT_CORE_CLK_DIV,
44 FEAT_LCD_CLK_SRC = 1 << 12, 44 FEAT_LCD_CLK_SRC,
45 /* DSI-PLL power command 0x3 is not working */ 45 /* DSI-PLL power command 0x3 is not working */
46 FEAT_DSI_PLL_PWR_BUG = 1 << 13, 46 FEAT_DSI_PLL_PWR_BUG,
47 FEAT_DSI_PLL_FREQSEL = 1 << 14, 47 FEAT_DSI_PLL_FREQSEL,
48 FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 15, 48 FEAT_DSI_DCS_CMD_CONFIG_VC,
49 FEAT_DSI_VC_OCP_WIDTH = 1 << 16, 49 FEAT_DSI_VC_OCP_WIDTH,
50 FEAT_DSI_REVERSE_TXCLKESC = 1 << 17, 50 FEAT_DSI_REVERSE_TXCLKESC,
51 FEAT_DSI_GNQ = 1 << 18, 51 FEAT_DSI_GNQ,
52 FEAT_HDMI_CTS_SWMODE = 1 << 19, 52 FEAT_HDMI_CTS_SWMODE,
53 FEAT_HANDLE_UV_SEPARATE = 1 << 20, 53 FEAT_HDMI_AUDIO_USE_MCLK,
54 FEAT_ATTR2 = 1 << 21, 54 FEAT_HANDLE_UV_SEPARATE,
55 FEAT_VENC_REQUIRES_TV_DAC_CLK = 1 << 22, 55 FEAT_ATTR2,
56 FEAT_CPR = 1 << 23, 56 FEAT_VENC_REQUIRES_TV_DAC_CLK,
57 FEAT_PRELOAD = 1 << 24, 57 FEAT_CPR,
58 FEAT_FIR_COEF_V = 1 << 25, 58 FEAT_PRELOAD,
59 FEAT_ALPHA_FIXED_ZORDER = 1 << 26, 59 FEAT_FIR_COEF_V,
60 FEAT_ALPHA_FREE_ZORDER = 1 << 27, 60 FEAT_ALPHA_FIXED_ZORDER,
61 FEAT_ALPHA_FREE_ZORDER,
62 FEAT_FIFO_MERGE,
63 /* An unknown HW bug causing the normal FIFO thresholds not to work */
64 FEAT_OMAP3_DSI_FIFO_BUG,
61}; 65};
62 66
63/* DSS register field id */ 67/* DSS register field id */
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index a36b934b2db4..c4b4f6950a92 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -58,8 +58,6 @@
58#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 58#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
59#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 59#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
60 60
61#define OMAP_HDMI_TIMINGS_NB 34
62
63#define HDMI_DEFAULT_REGN 16 61#define HDMI_DEFAULT_REGN 16
64#define HDMI_DEFAULT_REGM2 1 62#define HDMI_DEFAULT_REGM2 1
65 63
@@ -68,8 +66,6 @@ static struct {
68 struct omap_display_platform_data *pdata; 66 struct omap_display_platform_data *pdata;
69 struct platform_device *pdev; 67 struct platform_device *pdev;
70 struct hdmi_ip_data ip_data; 68 struct hdmi_ip_data ip_data;
71 int code;
72 int mode;
73 69
74 struct clk *sys_clk; 70 struct clk *sys_clk;
75} hdmi; 71} hdmi;
@@ -88,77 +84,46 @@ static struct {
88 * map it to corresponding CEA or VESA index. 84 * map it to corresponding CEA or VESA index.
89 */ 85 */
90 86
91static const struct hdmi_timings cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { 87static const struct hdmi_config cea_timings[] = {
92 { {640, 480, 25200, 96, 16, 48, 2, 10, 33} , 0 , 0}, 88{ {640, 480, 25200, 96, 16, 48, 2, 10, 33, 0, 0, 0}, {1, HDMI_HDMI} },
93 { {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, 1, 1}, 89{ {720, 480, 27027, 62, 16, 60, 6, 9, 30, 0, 0, 0}, {2, HDMI_HDMI} },
94 { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1}, 90{ {1280, 720, 74250, 40, 110, 220, 5, 5, 20, 1, 1, 0}, {4, HDMI_HDMI} },
95 { {720, 480, 27027, 62, 16, 60, 6, 9, 30}, 0, 0}, 91{ {1920, 540, 74250, 44, 88, 148, 5, 2, 15, 1, 1, 1}, {5, HDMI_HDMI} },
96 { {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, 0, 0}, 92{ {1440, 240, 27027, 124, 38, 114, 3, 4, 15, 0, 0, 1}, {6, HDMI_HDMI} },
97 { {1440, 240, 27027, 124, 38, 114, 3, 4, 15}, 0, 0}, 93{ {1920, 1080, 148500, 44, 88, 148, 5, 4, 36, 1, 1, 0}, {16, HDMI_HDMI} },
98 { {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, 0, 0}, 94{ {720, 576, 27000, 64, 12, 68, 5, 5, 39, 0, 0, 0}, {17, HDMI_HDMI} },
99 { {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, 1, 1}, 95{ {1280, 720, 74250, 40, 440, 220, 5, 5, 20, 1, 1, 0}, {19, HDMI_HDMI} },
100 { {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, 1, 1}, 96{ {1920, 540, 74250, 44, 528, 148, 5, 2, 15, 1, 1, 1}, {20, HDMI_HDMI} },
101 { {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, 1, 1}, 97{ {1440, 288, 27000, 126, 24, 138, 3, 2, 19, 0, 0, 1}, {21, HDMI_HDMI} },
102 { {720, 576, 27000, 64, 12, 68, 5, 5, 39}, 0, 0}, 98{ {1440, 576, 54000, 128, 24, 136, 5, 5, 39, 0, 0, 0}, {29, HDMI_HDMI} },
103 { {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, 0, 0}, 99{ {1920, 1080, 148500, 44, 528, 148, 5, 4, 36, 1, 1, 0}, {31, HDMI_HDMI} },
104 { {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, 1, 1}, 100{ {1920, 1080, 74250, 44, 638, 148, 5, 4, 36, 1, 1, 0}, {32, HDMI_HDMI} },
105 { {2880, 480, 108108, 248, 64, 240, 6, 9, 30}, 0, 0}, 101{ {2880, 480, 108108, 248, 64, 240, 6, 9, 30, 0, 0, 0}, {35, HDMI_HDMI} },
106 { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, 1, 1}, 102{ {2880, 576, 108000, 256, 48, 272, 5, 5, 39, 0, 0, 0}, {37, HDMI_HDMI} },
107 /* VESA From Here */
108 { {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, 0, 0},
109 { {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, 1, 1},
110 { {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, 1, 1},
111 { {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, 1, 0},
112 { {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, 1, 0},
113 { {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, 1, 1},
114 { {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, 1, 1},
115 { {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, 1, 1},
116 { {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, 0, 0},
117 { {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, 1, 0},
118 { {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, 1, 0},
119 { {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, 1, 0},
120 { {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, 1, 1},
121 { {1920, 1080, 148500, 44, 148, 80, 5, 4, 36}, 1, 1},
122 { {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, 0, 1},
123 { {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, 0, 1},
124 { {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, 0, 1},
125 { {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, 0, 1},
126 { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1}
127};
128
129/*
130 * This is a static mapping array which maps the timing values
131 * with corresponding CEA / VESA code
132 */
133static const int code_index[OMAP_HDMI_TIMINGS_NB] = {
134 1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, 32,
135 /* <--15 CEA 17--> vesa*/
136 4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A,
137 0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B
138}; 103};
139 104static const struct hdmi_config vesa_timings[] = {
140/* 105/* VESA From Here */
141 * This is reverse static mapping which maps the CEA / VESA code 106{ {640, 480, 25175, 96, 16, 48, 2 , 11, 31, 0, 0, 0}, {4, HDMI_DVI} },
142 * to the corresponding timing values 107{ {800, 600, 40000, 128, 40, 88, 4 , 1, 23, 1, 1, 0}, {9, HDMI_DVI} },
143 */ 108{ {848, 480, 33750, 112, 16, 112, 8 , 6, 23, 1, 1, 0}, {0xE, HDMI_DVI} },
144static const int code_cea[39] = { 109{ {1280, 768, 79500, 128, 64, 192, 7 , 3, 20, 1, 0, 0}, {0x17, HDMI_DVI} },
145 -1, 0, 3, 3, 2, 8, 5, 5, -1, -1, 110{ {1280, 800, 83500, 128, 72, 200, 6 , 3, 22, 1, 0, 0}, {0x1C, HDMI_DVI} },
146 -1, -1, -1, -1, -1, -1, 9, 10, 10, 1, 111{ {1360, 768, 85500, 112, 64, 256, 6 , 3, 18, 1, 1, 0}, {0x27, HDMI_DVI} },
147 7, 6, 6, -1, -1, -1, -1, -1, -1, 11, 112{ {1280, 960, 108000, 112, 96, 312, 3 , 1, 36, 1, 1, 0}, {0x20, HDMI_DVI} },
148 11, 12, 14, -1, -1, 13, 13, 4, 4 113{ {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38, 1, 1, 0}, {0x23, HDMI_DVI} },
114{ {1024, 768, 65000, 136, 24, 160, 6, 3, 29, 0, 0, 0}, {0x10, HDMI_DVI} },
115{ {1400, 1050, 121750, 144, 88, 232, 4, 3, 32, 1, 0, 0}, {0x2A, HDMI_DVI} },
116{ {1440, 900, 106500, 152, 80, 232, 6, 3, 25, 1, 0, 0}, {0x2F, HDMI_DVI} },
117{ {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30, 1, 0, 0}, {0x3A, HDMI_DVI} },
118{ {1366, 768, 85500, 143, 70, 213, 3, 3, 24, 1, 1, 0}, {0x51, HDMI_DVI} },
119{ {1920, 1080, 148500, 44, 148, 80, 5, 4, 36, 1, 1, 0}, {0x52, HDMI_DVI} },
120{ {1280, 768, 68250, 32, 48, 80, 7, 3, 12, 0, 1, 0}, {0x16, HDMI_DVI} },
121{ {1400, 1050, 101000, 32, 48, 80, 4, 3, 23, 0, 1, 0}, {0x29, HDMI_DVI} },
122{ {1680, 1050, 119000, 32, 48, 80, 6, 3, 21, 0, 1, 0}, {0x39, HDMI_DVI} },
123{ {1280, 800, 79500, 32, 48, 80, 6, 3, 14, 0, 1, 0}, {0x1B, HDMI_DVI} },
124{ {1280, 720, 74250, 40, 110, 220, 5, 5, 20, 1, 1, 0}, {0x55, HDMI_DVI} }
149}; 125};
150 126
151static const int code_vesa[85] = {
152 -1, -1, -1, -1, 15, -1, -1, -1, -1, 16,
153 -1, -1, -1, -1, 17, -1, 23, -1, -1, -1,
154 -1, -1, 29, 18, -1, -1, -1, 32, 19, -1,
155 -1, -1, 21, -1, -1, 22, -1, -1, -1, 20,
156 -1, 30, 24, -1, -1, -1, -1, 25, -1, -1,
157 -1, -1, -1, -1, -1, -1, -1, 31, 26, -1,
158 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
159 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
160 -1, 27, 28, -1, 33};
161
162static int hdmi_runtime_get(void) 127static int hdmi_runtime_get(void)
163{ 128{
164 int r; 129 int r;
@@ -210,88 +175,89 @@ int hdmi_init_display(struct omap_dss_device *dssdev)
210 return 0; 175 return 0;
211} 176}
212 177
213static int get_timings_index(void) 178static const struct hdmi_config *hdmi_find_timing(
179 const struct hdmi_config *timings_arr,
180 int len)
214{ 181{
215 int code; 182 int i;
216 183
217 if (hdmi.mode == 0) 184 for (i = 0; i < len; i++) {
218 code = code_vesa[hdmi.code]; 185 if (timings_arr[i].cm.code == hdmi.ip_data.cfg.cm.code)
219 else 186 return &timings_arr[i];
220 code = code_cea[hdmi.code]; 187 }
188 return NULL;
189}
221 190
222 if (code == -1) { 191static const struct hdmi_config *hdmi_get_timings(void)
223 /* HDMI code 4 corresponds to 640 * 480 VGA */ 192{
224 hdmi.code = 4; 193 const struct hdmi_config *arr;
225 /* DVI mode 1 corresponds to HDMI 0 to DVI */ 194 int len;
226 hdmi.mode = HDMI_DVI; 195
196 if (hdmi.ip_data.cfg.cm.mode == HDMI_DVI) {
197 arr = vesa_timings;
198 len = ARRAY_SIZE(vesa_timings);
199 } else {
200 arr = cea_timings;
201 len = ARRAY_SIZE(cea_timings);
202 }
203
204 return hdmi_find_timing(arr, len);
205}
206
207static bool hdmi_timings_compare(struct omap_video_timings *timing1,
208 const struct hdmi_video_timings *timing2)
209{
210 int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
227 211
228 code = code_vesa[hdmi.code]; 212 if ((timing2->pixel_clock == timing1->pixel_clock) &&
213 (timing2->x_res == timing1->x_res) &&
214 (timing2->y_res == timing1->y_res)) {
215
216 timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
217 timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
218 timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
219 timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
220
221 DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
222 "timing2_hsync = %d timing2_vsync = %d\n",
223 timing1_hsync, timing1_vsync,
224 timing2_hsync, timing2_vsync);
225
226 if ((timing1_hsync == timing2_hsync) &&
227 (timing1_vsync == timing2_vsync)) {
228 return true;
229 }
229 } 230 }
230 return code; 231 return false;
231} 232}
232 233
233static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) 234static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
234{ 235{
235 int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; 236 int i;
236 int timing_vsync = 0, timing_hsync = 0;
237 struct hdmi_video_timings temp;
238 struct hdmi_cm cm = {-1}; 237 struct hdmi_cm cm = {-1};
239 DSSDBG("hdmi_get_code\n"); 238 DSSDBG("hdmi_get_code\n");
240 239
241 for (i = 0; i < OMAP_HDMI_TIMINGS_NB; i++) { 240 for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
242 temp = cea_vesa_timings[i].timings; 241 if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
243 if ((temp.pixel_clock == timing->pixel_clock) && 242 cm = cea_timings[i].cm;
244 (temp.x_res == timing->x_res) && 243 goto end;
245 (temp.y_res == timing->y_res)) { 244 }
246 245 }
247 temp_hsync = temp.hfp + temp.hsw + temp.hbp; 246 for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
248 timing_hsync = timing->hfp + timing->hsw + timing->hbp; 247 if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
249 temp_vsync = temp.vfp + temp.vsw + temp.vbp; 248 cm = vesa_timings[i].cm;
250 timing_vsync = timing->vfp + timing->vsw + timing->vbp; 249 goto end;
251
252 DSSDBG("temp_hsync = %d , temp_vsync = %d"
253 "timing_hsync = %d, timing_vsync = %d\n",
254 temp_hsync, temp_hsync,
255 timing_hsync, timing_vsync);
256
257 if ((temp_hsync == timing_hsync) &&
258 (temp_vsync == timing_vsync)) {
259 code = i;
260 cm.code = code_index[i];
261 if (code < 14)
262 cm.mode = HDMI_HDMI;
263 else
264 cm.mode = HDMI_DVI;
265 DSSDBG("Hdmi_code = %d mode = %d\n",
266 cm.code, cm.mode);
267 break;
268 }
269 } 250 }
270 } 251 }
271 252
272 return cm; 253end: return cm;
273}
274 254
275static void update_hdmi_timings(struct hdmi_config *cfg,
276 struct omap_video_timings *timings, int code)
277{
278 cfg->timings.timings.x_res = timings->x_res;
279 cfg->timings.timings.y_res = timings->y_res;
280 cfg->timings.timings.hbp = timings->hbp;
281 cfg->timings.timings.hfp = timings->hfp;
282 cfg->timings.timings.hsw = timings->hsw;
283 cfg->timings.timings.vbp = timings->vbp;
284 cfg->timings.timings.vfp = timings->vfp;
285 cfg->timings.timings.vsw = timings->vsw;
286 cfg->timings.timings.pixel_clock = timings->pixel_clock;
287 cfg->timings.vsync_pol = cea_vesa_timings[code].vsync_pol;
288 cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol;
289} 255}
290 256
291unsigned long hdmi_get_pixel_clock(void) 257unsigned long hdmi_get_pixel_clock(void)
292{ 258{
293 /* HDMI Pixel Clock in Mhz */ 259 /* HDMI Pixel Clock in Mhz */
294 return hdmi.ip_data.cfg.timings.timings.pixel_clock * 1000; 260 return hdmi.ip_data.cfg.timings.pixel_clock * 1000;
295} 261}
296 262
297static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, 263static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
@@ -312,24 +278,24 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
312 278
313 refclk = clkin / pi->regn; 279 refclk = clkin / pi->regn;
314 280
315 /*
316 * multiplier is pixel_clk/ref_clk
317 * Multiplying by 100 to avoid fractional part removal
318 */
319 pi->regm = (phy * 100 / (refclk)) / 100;
320
321 if (dssdev->clocks.hdmi.regm2 == 0) 281 if (dssdev->clocks.hdmi.regm2 == 0)
322 pi->regm2 = HDMI_DEFAULT_REGM2; 282 pi->regm2 = HDMI_DEFAULT_REGM2;
323 else 283 else
324 pi->regm2 = dssdev->clocks.hdmi.regm2; 284 pi->regm2 = dssdev->clocks.hdmi.regm2;
325 285
326 /* 286 /*
287 * multiplier is pixel_clk/ref_clk
288 * Multiplying by 100 to avoid fractional part removal
289 */
290 pi->regm = phy * pi->regm2 / refclk;
291
292 /*
327 * fractional multiplier is remainder of the difference between 293 * fractional multiplier is remainder of the difference between
328 * multiplier and actual phy(required pixel clock thus should be 294 * multiplier and actual phy(required pixel clock thus should be
329 * multiplied by 2^18(262144) divided by the reference clock 295 * multiplied by 2^18(262144) divided by the reference clock
330 */ 296 */
331 mf = (phy - pi->regm * refclk) * 262144; 297 mf = (phy - pi->regm / pi->regm2 * refclk) * 262144;
332 pi->regmf = mf / (refclk); 298 pi->regmf = pi->regm2 * mf / refclk;
333 299
334 /* 300 /*
335 * Dcofreq should be set to 1 if required pixel clock 301 * Dcofreq should be set to 1 if required pixel clock
@@ -347,7 +313,8 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
347 313
348static int hdmi_power_on(struct omap_dss_device *dssdev) 314static int hdmi_power_on(struct omap_dss_device *dssdev)
349{ 315{
350 int r, code = 0; 316 int r;
317 const struct hdmi_config *timing;
351 struct omap_video_timings *p; 318 struct omap_video_timings *p;
352 unsigned long phy; 319 unsigned long phy;
353 320
@@ -363,9 +330,16 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
363 dssdev->panel.timings.x_res, 330 dssdev->panel.timings.x_res,
364 dssdev->panel.timings.y_res); 331 dssdev->panel.timings.y_res);
365 332
366 code = get_timings_index(); 333 timing = hdmi_get_timings();
367 update_hdmi_timings(&hdmi.ip_data.cfg, p, code); 334 if (timing == NULL) {
368 335 /* HDMI code 4 corresponds to 640 * 480 VGA */
336 hdmi.ip_data.cfg.cm.code = 4;
337 /* DVI mode 1 corresponds to HDMI 0 to DVI */
338 hdmi.ip_data.cfg.cm.mode = HDMI_DVI;
339 hdmi.ip_data.cfg = vesa_timings[0];
340 } else {
341 hdmi.ip_data.cfg = *timing;
342 }
369 phy = p->pixel_clock; 343 phy = p->pixel_clock;
370 344
371 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); 345 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
@@ -385,8 +359,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
385 goto err; 359 goto err;
386 } 360 }
387 361
388 hdmi.ip_data.cfg.cm.mode = hdmi.mode;
389 hdmi.ip_data.cfg.cm.code = hdmi.code;
390 hdmi.ip_data.ops->video_configure(&hdmi.ip_data); 362 hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
391 363
392 /* Make selection of HDMI in DSS */ 364 /* Make selection of HDMI in DSS */
@@ -453,8 +425,8 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
453 struct hdmi_cm cm; 425 struct hdmi_cm cm;
454 426
455 cm = hdmi_get_code(&dssdev->panel.timings); 427 cm = hdmi_get_code(&dssdev->panel.timings);
456 hdmi.code = cm.code; 428 hdmi.ip_data.cfg.cm.code = cm.code;
457 hdmi.mode = cm.mode; 429 hdmi.ip_data.cfg.cm.mode = cm.mode;
458 430
459 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 431 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
460 int r; 432 int r;
@@ -717,13 +689,15 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
717 if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) { 689 if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
718 core_cfg.aud_par_busclk = 0; 690 core_cfg.aud_par_busclk = 0;
719 core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW; 691 core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
720 core_cfg.use_mclk = false; 692 core_cfg.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
721 } else { 693 } else {
722 core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8); 694 core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8);
723 core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW; 695 core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
724 core_cfg.use_mclk = true; 696 core_cfg.use_mclk = true;
725 core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS;
726 } 697 }
698
699 if (core_cfg.use_mclk)
700 core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS;
727 core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH; 701 core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH;
728 core_cfg.en_spdif = false; 702 core_cfg.en_spdif = false;
729 /* Use sample frequency from channel status word */ 703 /* Use sample frequency from channel status word */
@@ -756,7 +730,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
756static int hdmi_audio_startup(struct snd_pcm_substream *substream, 730static int hdmi_audio_startup(struct snd_pcm_substream *substream,
757 struct snd_soc_dai *dai) 731 struct snd_soc_dai *dai)
758{ 732{
759 if (!hdmi.mode) { 733 if (!hdmi.ip_data.cfg.cm.mode) {
760 pr_err("Current video settings do not support audio.\n"); 734 pr_err("Current video settings do not support audio.\n");
761 return -EIO; 735 return -EIO;
762 } 736 }
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index d1858e71c64e..e7364603f6a1 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -494,6 +494,11 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
494{ 494{
495 unsigned long timeout = msecs_to_jiffies(500); 495 unsigned long timeout = msecs_to_jiffies(500);
496 u32 irq; 496 u32 irq;
497 int r;
498
499 r = dispc_runtime_get();
500 if (r)
501 return r;
497 502
498 if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) { 503 if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) {
499 irq = DISPC_IRQ_EVSYNC_ODD; 504 irq = DISPC_IRQ_EVSYNC_ODD;
@@ -505,7 +510,12 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
505 else 510 else
506 irq = DISPC_IRQ_VSYNC2; 511 irq = DISPC_IRQ_VSYNC2;
507 } 512 }
508 return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); 513
514 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
515
516 dispc_runtime_put();
517
518 return r;
509} 519}
510 520
511int dss_init_overlay_managers(struct platform_device *pdev) 521int dss_init_overlay_managers(struct platform_device *pdev)
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 55f398014f33..788a0ef6323a 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -922,35 +922,34 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
922 rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); 922 rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
923 if (!rfbi_mem) { 923 if (!rfbi_mem) {
924 DSSERR("can't get IORESOURCE_MEM RFBI\n"); 924 DSSERR("can't get IORESOURCE_MEM RFBI\n");
925 r = -EINVAL; 925 return -EINVAL;
926 goto err_ioremap;
927 } 926 }
928 rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem)); 927
928 rfbi.base = devm_ioremap(&pdev->dev, rfbi_mem->start,
929 resource_size(rfbi_mem));
929 if (!rfbi.base) { 930 if (!rfbi.base) {
930 DSSERR("can't ioremap RFBI\n"); 931 DSSERR("can't ioremap RFBI\n");
931 r = -ENOMEM; 932 return -ENOMEM;
932 goto err_ioremap;
933 } 933 }
934 934
935 pm_runtime_enable(&pdev->dev);
936
937 r = rfbi_runtime_get();
938 if (r)
939 goto err_get_rfbi;
940
941 msleep(10);
942
943 clk = clk_get(&pdev->dev, "ick"); 935 clk = clk_get(&pdev->dev, "ick");
944 if (IS_ERR(clk)) { 936 if (IS_ERR(clk)) {
945 DSSERR("can't get ick\n"); 937 DSSERR("can't get ick\n");
946 r = PTR_ERR(clk); 938 return PTR_ERR(clk);
947 goto err_get_ick;
948 } 939 }
949 940
950 rfbi.l4_khz = clk_get_rate(clk) / 1000; 941 rfbi.l4_khz = clk_get_rate(clk) / 1000;
951 942
952 clk_put(clk); 943 clk_put(clk);
953 944
945 pm_runtime_enable(&pdev->dev);
946
947 r = rfbi_runtime_get();
948 if (r)
949 goto err_runtime_get;
950
951 msleep(10);
952
954 rev = rfbi_read_reg(RFBI_REVISION); 953 rev = rfbi_read_reg(RFBI_REVISION);
955 dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n", 954 dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
956 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 955 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
@@ -959,19 +958,14 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
959 958
960 return 0; 959 return 0;
961 960
962err_get_ick: 961err_runtime_get:
963 rfbi_runtime_put();
964err_get_rfbi:
965 pm_runtime_disable(&pdev->dev); 962 pm_runtime_disable(&pdev->dev);
966 iounmap(rfbi.base);
967err_ioremap:
968 return r; 963 return r;
969} 964}
970 965
971static int omap_rfbihw_remove(struct platform_device *pdev) 966static int omap_rfbihw_remove(struct platform_device *pdev)
972{ 967{
973 pm_runtime_disable(&pdev->dev); 968 pm_runtime_disable(&pdev->dev);
974 iounmap(rfbi.base);
975 return 0; 969 return 0;
976} 970}
977 971
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
index 50dadba5070a..1f58b84d6901 100644
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -42,6 +42,7 @@ enum hdmi_clk_refsel {
42 HDMI_REFSEL_SYSCLK = 3 42 HDMI_REFSEL_SYSCLK = 3
43}; 43};
44 44
45/* HDMI timing structure */
45struct hdmi_video_timings { 46struct hdmi_video_timings {
46 u16 x_res; 47 u16 x_res;
47 u16 y_res; 48 u16 y_res;
@@ -53,13 +54,9 @@ struct hdmi_video_timings {
53 u16 vsw; 54 u16 vsw;
54 u16 vfp; 55 u16 vfp;
55 u16 vbp; 56 u16 vbp;
56}; 57 bool vsync_pol;
57 58 bool hsync_pol;
58/* HDMI timing structure */ 59 bool interlace;
59struct hdmi_timings {
60 struct hdmi_video_timings timings;
61 int vsync_pol;
62 int hsync_pol;
63}; 60};
64 61
65struct hdmi_cm { 62struct hdmi_cm {
@@ -68,8 +65,7 @@ struct hdmi_cm {
68}; 65};
69 66
70struct hdmi_config { 67struct hdmi_config {
71 struct hdmi_timings timings; 68 struct hdmi_video_timings timings;
72 u16 interlace;
73 struct hdmi_cm cm; 69 struct hdmi_cm cm;
74}; 70};
75 71
@@ -117,6 +113,47 @@ struct ti_hdmi_ip_ops {
117 113
118}; 114};
119 115
116/*
117 * Refer to section 8.2 in HDMI 1.3 specification for
118 * details about infoframe databytes
119 */
120struct hdmi_core_infoframe_avi {
121 /* Y0, Y1 rgb,yCbCr */
122 u8 db1_format;
123 /* A0 Active information Present */
124 u8 db1_active_info;
125 /* B0, B1 Bar info data valid */
126 u8 db1_bar_info_dv;
127 /* S0, S1 scan information */
128 u8 db1_scan_info;
129 /* C0, C1 colorimetry */
130 u8 db2_colorimetry;
131 /* M0, M1 Aspect ratio (4:3, 16:9) */
132 u8 db2_aspect_ratio;
133 /* R0...R3 Active format aspect ratio */
134 u8 db2_active_fmt_ar;
135 /* ITC IT content. */
136 u8 db3_itc;
137 /* EC0, EC1, EC2 Extended colorimetry */
138 u8 db3_ec;
139 /* Q1, Q0 Quantization range */
140 u8 db3_q_range;
141 /* SC1, SC0 Non-uniform picture scaling */
142 u8 db3_nup_scaling;
143 /* VIC0..6 Video format identification */
144 u8 db4_videocode;
145 /* PR0..PR3 Pixel repetition factor */
146 u8 db5_pixel_repeat;
147 /* Line number end of top bar */
148 u16 db6_7_line_eoftop;
149 /* Line number start of bottom bar */
150 u16 db8_9_line_sofbottom;
151 /* Pixel number end of left bar */
152 u16 db10_11_pixel_eofleft;
153 /* Pixel number start of right bar */
154 u16 db12_13_pixel_sofright;
155};
156
120struct hdmi_ip_data { 157struct hdmi_ip_data {
121 void __iomem *base_wp; /* HDMI wrapper */ 158 void __iomem *base_wp; /* HDMI wrapper */
122 unsigned long core_sys_offset; 159 unsigned long core_sys_offset;
@@ -126,6 +163,7 @@ struct hdmi_ip_data {
126 const struct ti_hdmi_ip_ops *ops; 163 const struct ti_hdmi_ip_ops *ops;
127 struct hdmi_config cfg; 164 struct hdmi_config cfg;
128 struct hdmi_pll_info pll_data; 165 struct hdmi_pll_info pll_data;
166 struct hdmi_core_infoframe_avi avi_cfg;
129 167
130 /* ti_hdmi_4xxx_ip private data. These should be in a separate struct */ 168 /* ti_hdmi_4xxx_ip private data. These should be in a separate struct */
131 int hpd_gpio; 169 int hpd_gpio;
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
index 6847a478b459..bfe6fe65c8be 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -587,12 +587,12 @@ static void hdmi_core_video_config(struct hdmi_ip_data *ip_data,
587 HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5); 587 HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5);
588} 588}
589 589
590static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data, 590static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data)
591 struct hdmi_core_infoframe_avi info_avi)
592{ 591{
593 u32 val; 592 u32 val;
594 char sum = 0, checksum = 0; 593 char sum = 0, checksum = 0;
595 void __iomem *av_base = hdmi_av_base(ip_data); 594 void __iomem *av_base = hdmi_av_base(ip_data);
595 struct hdmi_core_infoframe_avi info_avi = ip_data->avi_cfg;
596 596
597 sum += 0x82 + 0x002 + 0x00D; 597 sum += 0x82 + 0x002 + 0x00D;
598 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082); 598 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082);
@@ -682,8 +682,7 @@ static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data,
682} 682}
683 683
684static void hdmi_wp_init(struct omap_video_timings *timings, 684static void hdmi_wp_init(struct omap_video_timings *timings,
685 struct hdmi_video_format *video_fmt, 685 struct hdmi_video_format *video_fmt)
686 struct hdmi_video_interface *video_int)
687{ 686{
688 pr_debug("Enter hdmi_wp_init\n"); 687 pr_debug("Enter hdmi_wp_init\n");
689 688
@@ -698,12 +697,6 @@ static void hdmi_wp_init(struct omap_video_timings *timings,
698 video_fmt->y_res = 0; 697 video_fmt->y_res = 0;
699 video_fmt->x_res = 0; 698 video_fmt->x_res = 0;
700 699
701 video_int->vsp = 0;
702 video_int->hsp = 0;
703
704 video_int->interlacing = 0;
705 video_int->tm = 0; /* HDMI_TIMING_SLAVE */
706
707} 700}
708 701
709void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start) 702void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start)
@@ -716,15 +709,15 @@ static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
716{ 709{
717 pr_debug("Enter hdmi_wp_video_init_format\n"); 710 pr_debug("Enter hdmi_wp_video_init_format\n");
718 711
719 video_fmt->y_res = param->timings.timings.y_res; 712 video_fmt->y_res = param->timings.y_res;
720 video_fmt->x_res = param->timings.timings.x_res; 713 video_fmt->x_res = param->timings.x_res;
721 714
722 timings->hbp = param->timings.timings.hbp; 715 timings->hbp = param->timings.hbp;
723 timings->hfp = param->timings.timings.hfp; 716 timings->hfp = param->timings.hfp;
724 timings->hsw = param->timings.timings.hsw; 717 timings->hsw = param->timings.hsw;
725 timings->vbp = param->timings.timings.vbp; 718 timings->vbp = param->timings.vbp;
726 timings->vfp = param->timings.timings.vfp; 719 timings->vfp = param->timings.vfp;
727 timings->vsw = param->timings.timings.vsw; 720 timings->vsw = param->timings.vsw;
728} 721}
729 722
730static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data, 723static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data,
@@ -740,17 +733,16 @@ static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data,
740 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l); 733 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l);
741} 734}
742 735
743static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data, 736static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data)
744 struct hdmi_video_interface *video_int)
745{ 737{
746 u32 r; 738 u32 r;
747 pr_debug("Enter hdmi_wp_video_config_interface\n"); 739 pr_debug("Enter hdmi_wp_video_config_interface\n");
748 740
749 r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG); 741 r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG);
750 r = FLD_MOD(r, video_int->vsp, 7, 7); 742 r = FLD_MOD(r, ip_data->cfg.timings.vsync_pol, 7, 7);
751 r = FLD_MOD(r, video_int->hsp, 6, 6); 743 r = FLD_MOD(r, ip_data->cfg.timings.hsync_pol, 6, 6);
752 r = FLD_MOD(r, video_int->interlacing, 3, 3); 744 r = FLD_MOD(r, ip_data->cfg.timings.interlace, 3, 3);
753 r = FLD_MOD(r, video_int->tm, 1, 0); 745 r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */
754 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r); 746 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r);
755} 747}
756 748
@@ -778,15 +770,13 @@ void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data)
778 /* HDMI */ 770 /* HDMI */
779 struct omap_video_timings video_timing; 771 struct omap_video_timings video_timing;
780 struct hdmi_video_format video_format; 772 struct hdmi_video_format video_format;
781 struct hdmi_video_interface video_interface;
782 /* HDMI core */ 773 /* HDMI core */
783 struct hdmi_core_infoframe_avi avi_cfg; 774 struct hdmi_core_infoframe_avi avi_cfg = ip_data->avi_cfg;
784 struct hdmi_core_video_config v_core_cfg; 775 struct hdmi_core_video_config v_core_cfg;
785 struct hdmi_core_packet_enable_repeat repeat_cfg; 776 struct hdmi_core_packet_enable_repeat repeat_cfg;
786 struct hdmi_config *cfg = &ip_data->cfg; 777 struct hdmi_config *cfg = &ip_data->cfg;
787 778
788 hdmi_wp_init(&video_timing, &video_format, 779 hdmi_wp_init(&video_timing, &video_format);
789 &video_interface);
790 780
791 hdmi_core_init(&v_core_cfg, 781 hdmi_core_init(&v_core_cfg,
792 &avi_cfg, 782 &avi_cfg,
@@ -801,12 +791,7 @@ void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data)
801 791
802 hdmi_wp_video_config_format(ip_data, &video_format); 792 hdmi_wp_video_config_format(ip_data, &video_format);
803 793
804 video_interface.vsp = cfg->timings.vsync_pol; 794 hdmi_wp_video_config_interface(ip_data);
805 video_interface.hsp = cfg->timings.hsync_pol;
806 video_interface.interlacing = cfg->interlace;
807 video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */
808
809 hdmi_wp_video_config_interface(ip_data, &video_interface);
810 795
811 /* 796 /*
812 * configure core video part 797 * configure core video part
@@ -848,7 +833,7 @@ void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data)
848 avi_cfg.db10_11_pixel_eofleft = 0; 833 avi_cfg.db10_11_pixel_eofleft = 0;
849 avi_cfg.db12_13_pixel_sofright = 0; 834 avi_cfg.db12_13_pixel_sofright = 0;
850 835
851 hdmi_core_aux_infoframe_avi_config(ip_data, avi_cfg); 836 hdmi_core_aux_infoframe_avi_config(ip_data);
852 837
853 /* enable/repeat the infoframe */ 838 /* enable/repeat the infoframe */
854 repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; 839 repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
@@ -1076,13 +1061,9 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
1076 u32 r; 1061 u32 r;
1077 void __iomem *av_base = hdmi_av_base(ip_data); 1062 void __iomem *av_base = hdmi_av_base(ip_data);
1078 1063
1079 /* audio clock recovery parameters */ 1064 /*
1080 r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL); 1065 * Parameters for generation of Audio Clock Recovery packets
1081 r = FLD_MOD(r, cfg->use_mclk, 2, 2); 1066 */
1082 r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
1083 r = FLD_MOD(r, cfg->cts_mode, 0, 0);
1084 hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r);
1085
1086 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0); 1067 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
1087 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0); 1068 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
1088 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0); 1069 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
@@ -1094,14 +1075,6 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
1094 REG_FLD_MOD(av_base, 1075 REG_FLD_MOD(av_base,
1095 HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0); 1076 HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
1096 } else { 1077 } else {
1097 /*
1098 * HDMI IP uses this configuration to divide the MCLK to
1099 * update CTS value.
1100 */
1101 REG_FLD_MOD(av_base,
1102 HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
1103
1104 /* Configure clock for audio packets */
1105 REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1, 1078 REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
1106 cfg->aud_par_busclk, 7, 0); 1079 cfg->aud_par_busclk, 7, 0);
1107 REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2, 1080 REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
@@ -1110,6 +1083,25 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
1110 (cfg->aud_par_busclk >> 16), 7, 0); 1083 (cfg->aud_par_busclk >> 16), 7, 0);
1111 } 1084 }
1112 1085
1086 /* Set ACR clock divisor */
1087 REG_FLD_MOD(av_base,
1088 HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
1089
1090 r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL);
1091 /*
1092 * Use TMDS clock for ACR packets. For devices that use
1093 * the MCLK, this is the first part of the MCLK initialization.
1094 */
1095 r = FLD_MOD(r, 0, 2, 2);
1096
1097 r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
1098 r = FLD_MOD(r, cfg->cts_mode, 0, 0);
1099 hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r);
1100
1101 /* For devices using MCLK, this completes its initialization. */
1102 if (cfg->use_mclk)
1103 REG_FLD_MOD(av_base, HDMI_CORE_AV_ACR_CTRL, 1, 2, 2);
1104
1113 /* Override of SPDIF sample frequency with value in I2S_CHST4 */ 1105 /* Override of SPDIF sample frequency with value in I2S_CHST4 */
1114 REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL, 1106 REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL,
1115 cfg->fs_override, 1, 1); 1107 cfg->fs_override, 1, 1);
@@ -1205,7 +1197,7 @@ int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
1205{ 1197{
1206 u32 r; 1198 u32 r;
1207 u32 deep_color = 0; 1199 u32 deep_color = 0;
1208 u32 pclk = ip_data->cfg.timings.timings.pixel_clock; 1200 u32 pclk = ip_data->cfg.timings.pixel_clock;
1209 1201
1210 if (n == NULL || cts == NULL) 1202 if (n == NULL || cts == NULL)
1211 return -EINVAL; 1203 return -EINVAL;
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
index a442998980f1..a14d1a0e6e41 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
@@ -450,46 +450,6 @@ struct hdmi_core_video_config {
450 * Refer to section 8.2 in HDMI 1.3 specification for 450 * Refer to section 8.2 in HDMI 1.3 specification for
451 * details about infoframe databytes 451 * details about infoframe databytes
452 */ 452 */
453struct hdmi_core_infoframe_avi {
454 /* Y0, Y1 rgb,yCbCr */
455 u8 db1_format;
456 /* A0 Active information Present */
457 u8 db1_active_info;
458 /* B0, B1 Bar info data valid */
459 u8 db1_bar_info_dv;
460 /* S0, S1 scan information */
461 u8 db1_scan_info;
462 /* C0, C1 colorimetry */
463 u8 db2_colorimetry;
464 /* M0, M1 Aspect ratio (4:3, 16:9) */
465 u8 db2_aspect_ratio;
466 /* R0...R3 Active format aspect ratio */
467 u8 db2_active_fmt_ar;
468 /* ITC IT content. */
469 u8 db3_itc;
470 /* EC0, EC1, EC2 Extended colorimetry */
471 u8 db3_ec;
472 /* Q1, Q0 Quantization range */
473 u8 db3_q_range;
474 /* SC1, SC0 Non-uniform picture scaling */
475 u8 db3_nup_scaling;
476 /* VIC0..6 Video format identification */
477 u8 db4_videocode;
478 /* PR0..PR3 Pixel repetition factor */
479 u8 db5_pixel_repeat;
480 /* Line number end of top bar */
481 u16 db6_7_line_eoftop;
482 /* Line number start of bottom bar */
483 u16 db8_9_line_sofbottom;
484 /* Pixel number end of left bar */
485 u16 db10_11_pixel_eofleft;
486 /* Pixel number start of right bar */
487 u16 db12_13_pixel_sofright;
488};
489/*
490 * Refer to section 8.2 in HDMI 1.3 specification for
491 * details about infoframe databytes
492 */
493struct hdmi_core_infoframe_audio { 453struct hdmi_core_infoframe_audio {
494 u8 db1_coding_type; 454 u8 db1_coding_type;
495 u8 db1_channel_count; 455 u8 db1_channel_count;
@@ -517,13 +477,6 @@ struct hdmi_video_format {
517 u32 x_res; /* pixel per line */ 477 u32 x_res; /* pixel per line */
518}; 478};
519 479
520struct hdmi_video_interface {
521 int vsp; /* Vsync polarity */
522 int hsp; /* Hsync polarity */
523 int interlacing;
524 int tm; /* Timing mode */
525};
526
527struct hdmi_audio_format { 480struct hdmi_audio_format {
528 enum hdmi_stereo_channels stereo_channels; 481 enum hdmi_stereo_channels stereo_channels;
529 u8 active_chnnls_msk; 482 u8 active_chnnls_msk;
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 5c3d0f901510..9c3daf71750c 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -699,6 +699,11 @@ void venc_dump_regs(struct seq_file *s)
699{ 699{
700#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) 700#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
701 701
702 if (cpu_is_omap44xx()) {
703 seq_printf(s, "VENC currently disabled on OMAP44xx\n");
704 return;
705 }
706
702 if (venc_runtime_get()) 707 if (venc_runtime_get())
703 return; 708 return;
704 709
@@ -790,39 +795,41 @@ static int omap_venchw_probe(struct platform_device *pdev)
790 venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0); 795 venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
791 if (!venc_mem) { 796 if (!venc_mem) {
792 DSSERR("can't get IORESOURCE_MEM VENC\n"); 797 DSSERR("can't get IORESOURCE_MEM VENC\n");
793 r = -EINVAL; 798 return -EINVAL;
794 goto err_ioremap;
795 } 799 }
796 venc.base = ioremap(venc_mem->start, resource_size(venc_mem)); 800
801 venc.base = devm_ioremap(&pdev->dev, venc_mem->start,
802 resource_size(venc_mem));
797 if (!venc.base) { 803 if (!venc.base) {
798 DSSERR("can't ioremap VENC\n"); 804 DSSERR("can't ioremap VENC\n");
799 r = -ENOMEM; 805 return -ENOMEM;
800 goto err_ioremap;
801 } 806 }
802 807
803 r = venc_get_clocks(pdev); 808 r = venc_get_clocks(pdev);
804 if (r) 809 if (r)
805 goto err_get_clk; 810 return r;
806 811
807 pm_runtime_enable(&pdev->dev); 812 pm_runtime_enable(&pdev->dev);
808 813
809 r = venc_runtime_get(); 814 r = venc_runtime_get();
810 if (r) 815 if (r)
811 goto err_get_venc; 816 goto err_runtime_get;
812 817
813 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); 818 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
814 dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); 819 dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
815 820
816 venc_runtime_put(); 821 venc_runtime_put();
817 822
818 return omap_dss_register_driver(&venc_driver); 823 r = omap_dss_register_driver(&venc_driver);
824 if (r)
825 goto err_reg_panel_driver;
826
827 return 0;
819 828
820err_get_venc: 829err_reg_panel_driver:
830err_runtime_get:
821 pm_runtime_disable(&pdev->dev); 831 pm_runtime_disable(&pdev->dev);
822 venc_put_clocks(); 832 venc_put_clocks();
823err_get_clk:
824 iounmap(venc.base);
825err_ioremap:
826 return r; 833 return r;
827} 834}
828 835
@@ -837,7 +844,6 @@ static int omap_venchw_remove(struct platform_device *pdev)
837 pm_runtime_disable(&pdev->dev); 844 pm_runtime_disable(&pdev->dev);
838 venc_put_clocks(); 845 venc_put_clocks();
839 846
840 iounmap(venc.base);
841 return 0; 847 return 0;
842} 848}
843 849
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 16ba6196f330..6a09ef87e14f 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -215,7 +215,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
215 int r = 0, i; 215 int r = 0, i;
216 size_t size; 216 size_t size;
217 217
218 if (mi->type > OMAPFB_MEMTYPE_MAX) 218 if (mi->type != OMAPFB_MEMTYPE_SDRAM)
219 return -EINVAL; 219 return -EINVAL;
220 220
221 size = PAGE_ALIGN(mi->size); 221 size = PAGE_ALIGN(mi->size);
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index ce158311ff59..b00db4068d21 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -1399,7 +1399,7 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1399 1399
1400 if (!paddr) { 1400 if (!paddr) {
1401 DBG("allocating %lu bytes for fb %d\n", size, ofbi->id); 1401 DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
1402 r = omap_vram_alloc(OMAP_VRAM_MEMTYPE_SDRAM, size, &paddr); 1402 r = omap_vram_alloc(size, &paddr);
1403 } else { 1403 } else {
1404 DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr, 1404 DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
1405 ofbi->id); 1405 ofbi->id);
@@ -1487,60 +1487,6 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
1487 return omapfb_alloc_fbmem(fbi, size, paddr); 1487 return omapfb_alloc_fbmem(fbi, size, paddr);
1488} 1488}
1489 1489
1490static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format fmt)
1491{
1492 enum omap_color_mode mode;
1493
1494 switch (fmt) {
1495 case OMAPFB_COLOR_RGB565:
1496 mode = OMAP_DSS_COLOR_RGB16;
1497 break;
1498 case OMAPFB_COLOR_YUV422:
1499 mode = OMAP_DSS_COLOR_YUV2;
1500 break;
1501 case OMAPFB_COLOR_CLUT_8BPP:
1502 mode = OMAP_DSS_COLOR_CLUT8;
1503 break;
1504 case OMAPFB_COLOR_CLUT_4BPP:
1505 mode = OMAP_DSS_COLOR_CLUT4;
1506 break;
1507 case OMAPFB_COLOR_CLUT_2BPP:
1508 mode = OMAP_DSS_COLOR_CLUT2;
1509 break;
1510 case OMAPFB_COLOR_CLUT_1BPP:
1511 mode = OMAP_DSS_COLOR_CLUT1;
1512 break;
1513 case OMAPFB_COLOR_RGB444:
1514 mode = OMAP_DSS_COLOR_RGB12U;
1515 break;
1516 case OMAPFB_COLOR_YUY422:
1517 mode = OMAP_DSS_COLOR_UYVY;
1518 break;
1519 case OMAPFB_COLOR_ARGB16:
1520 mode = OMAP_DSS_COLOR_ARGB16;
1521 break;
1522 case OMAPFB_COLOR_RGB24U:
1523 mode = OMAP_DSS_COLOR_RGB24U;
1524 break;
1525 case OMAPFB_COLOR_RGB24P:
1526 mode = OMAP_DSS_COLOR_RGB24P;
1527 break;
1528 case OMAPFB_COLOR_ARGB32:
1529 mode = OMAP_DSS_COLOR_ARGB32;
1530 break;
1531 case OMAPFB_COLOR_RGBA32:
1532 mode = OMAP_DSS_COLOR_RGBA32;
1533 break;
1534 case OMAPFB_COLOR_RGBX32:
1535 mode = OMAP_DSS_COLOR_RGBX32;
1536 break;
1537 default:
1538 mode = -EINVAL;
1539 }
1540
1541 return mode;
1542}
1543
1544static int omapfb_parse_vram_param(const char *param, int max_entries, 1490static int omapfb_parse_vram_param(const char *param, int max_entries,
1545 unsigned long *sizes, unsigned long *paddrs) 1491 unsigned long *sizes, unsigned long *paddrs)
1546{ 1492{
@@ -1614,23 +1560,6 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1614 memset(&vram_paddrs, 0, sizeof(vram_paddrs)); 1560 memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1615 } 1561 }
1616 1562
1617 if (fbdev->dev->platform_data) {
1618 struct omapfb_platform_data *opd;
1619 opd = fbdev->dev->platform_data;
1620 for (i = 0; i < opd->mem_desc.region_cnt; ++i) {
1621 if (!vram_sizes[i]) {
1622 unsigned long size;
1623 unsigned long paddr;
1624
1625 size = opd->mem_desc.region[i].size;
1626 paddr = opd->mem_desc.region[i].paddr;
1627
1628 vram_sizes[i] = size;
1629 vram_paddrs[i] = paddr;
1630 }
1631 }
1632 }
1633
1634 for (i = 0; i < fbdev->num_fbs; i++) { 1563 for (i = 0; i < fbdev->num_fbs; i++) {
1635 /* allocate memory automatically only for fb0, or if 1564 /* allocate memory automatically only for fb0, or if
1636 * excplicitly defined with vram or plat data option */ 1565 * excplicitly defined with vram or plat data option */
@@ -1669,7 +1598,7 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1669 int old_type = rg->type; 1598 int old_type = rg->type;
1670 int r; 1599 int r;
1671 1600
1672 if (type > OMAPFB_MEMTYPE_MAX) 1601 if (type != OMAPFB_MEMTYPE_SDRAM)
1673 return -EINVAL; 1602 return -EINVAL;
1674 1603
1675 size = PAGE_ALIGN(size); 1604 size = PAGE_ALIGN(size);
@@ -1828,32 +1757,6 @@ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
1828 1757
1829 var->rotate = def_rotate; 1758 var->rotate = def_rotate;
1830 1759
1831 /*
1832 * Check if there is a default color format set in the board file,
1833 * and use this format instead the default deducted from the
1834 * display bpp.
1835 */
1836 if (fbdev->dev->platform_data) {
1837 struct omapfb_platform_data *opd;
1838 int id = ofbi->id;
1839
1840 opd = fbdev->dev->platform_data;
1841 if (opd->mem_desc.region[id].format_used) {
1842 enum omap_color_mode mode;
1843 enum omapfb_color_format format;
1844
1845 format = opd->mem_desc.region[id].format;
1846 mode = fb_format_to_dss_mode(format);
1847 if (mode < 0) {
1848 r = mode;
1849 goto err;
1850 }
1851 r = dss_mode_to_fb_mode(mode, var);
1852 if (r < 0)
1853 goto err;
1854 }
1855 }
1856
1857 if (display) { 1760 if (display) {
1858 u16 w, h; 1761 u16 w, h;
1859 int rotation = (var->rotate + ofbi->rotation[0]) % 4; 1762 int rotation = (var->rotate + ofbi->rotation[0]) % 4;
diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
index 9441e2eb3dee..87e421e25afe 100644
--- a/drivers/video/omap2/vram.c
+++ b/drivers/video/omap2/vram.c
@@ -33,7 +33,6 @@
33 33
34#include <asm/setup.h> 34#include <asm/setup.h>
35 35
36#include <plat/sram.h>
37#include <plat/vram.h> 36#include <plat/vram.h>
38#include <plat/dma.h> 37#include <plat/dma.h>
39 38
@@ -43,10 +42,6 @@
43#define DBG(format, ...) 42#define DBG(format, ...)
44#endif 43#endif
45 44
46#define OMAP2_SRAM_START 0x40200000
47/* Maximum size, in reality this is smaller if SRAM is partially locked. */
48#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */
49
50/* postponed regions are used to temporarily store region information at boot 45/* postponed regions are used to temporarily store region information at boot
51 * time when we cannot yet allocate the region list */ 46 * time when we cannot yet allocate the region list */
52#define MAX_POSTPONED_REGIONS 10 47#define MAX_POSTPONED_REGIONS 10
@@ -74,15 +69,6 @@ struct vram_region {
74static DEFINE_MUTEX(region_mutex); 69static DEFINE_MUTEX(region_mutex);
75static LIST_HEAD(region_list); 70static LIST_HEAD(region_list);
76 71
77static inline int region_mem_type(unsigned long paddr)
78{
79 if (paddr >= OMAP2_SRAM_START &&
80 paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
81 return OMAP_VRAM_MEMTYPE_SRAM;
82 else
83 return OMAP_VRAM_MEMTYPE_SDRAM;
84}
85
86static struct vram_region *omap_vram_create_region(unsigned long paddr, 72static struct vram_region *omap_vram_create_region(unsigned long paddr,
87 unsigned pages) 73 unsigned pages)
88{ 74{
@@ -212,9 +198,6 @@ static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
212 198
213 DBG("checking region %lx %d\n", rm->paddr, rm->pages); 199 DBG("checking region %lx %d\n", rm->paddr, rm->pages);
214 200
215 if (region_mem_type(rm->paddr) != region_mem_type(paddr))
216 continue;
217
218 start = rm->paddr; 201 start = rm->paddr;
219 end = start + (rm->pages << PAGE_SHIFT) - 1; 202 end = start + (rm->pages << PAGE_SHIFT) - 1;
220 if (start > paddr || end < paddr + size - 1) 203 if (start > paddr || end < paddr + size - 1)
@@ -320,7 +303,7 @@ err:
320 return r; 303 return r;
321} 304}
322 305
323static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr) 306static int _omap_vram_alloc(unsigned pages, unsigned long *paddr)
324{ 307{
325 struct vram_region *rm; 308 struct vram_region *rm;
326 struct vram_alloc *alloc; 309 struct vram_alloc *alloc;
@@ -330,9 +313,6 @@ static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr)
330 313
331 DBG("checking region %lx %d\n", rm->paddr, rm->pages); 314 DBG("checking region %lx %d\n", rm->paddr, rm->pages);
332 315
333 if (region_mem_type(rm->paddr) != mtype)
334 continue;
335
336 start = rm->paddr; 316 start = rm->paddr;
337 317
338 list_for_each_entry(alloc, &rm->alloc_list, list) { 318 list_for_each_entry(alloc, &rm->alloc_list, list) {
@@ -365,21 +345,21 @@ found:
365 return -ENOMEM; 345 return -ENOMEM;
366} 346}
367 347
368int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr) 348int omap_vram_alloc(size_t size, unsigned long *paddr)
369{ 349{
370 unsigned pages; 350 unsigned pages;
371 int r; 351 int r;
372 352
373 BUG_ON(mtype > OMAP_VRAM_MEMTYPE_MAX || !size); 353 BUG_ON(!size);
374 354
375 DBG("alloc mem type %d size %d\n", mtype, size); 355 DBG("alloc mem size %d\n", size);
376 356
377 size = PAGE_ALIGN(size); 357 size = PAGE_ALIGN(size);
378 pages = size >> PAGE_SHIFT; 358 pages = size >> PAGE_SHIFT;
379 359
380 mutex_lock(&region_mutex); 360 mutex_lock(&region_mutex);
381 361
382 r = _omap_vram_alloc(mtype, pages, paddr); 362 r = _omap_vram_alloc(pages, paddr);
383 363
384 mutex_unlock(&region_mutex); 364 mutex_unlock(&region_mutex);
385 365
@@ -501,10 +481,6 @@ arch_initcall(omap_vram_init);
501/* boottime vram alloc stuff */ 481/* boottime vram alloc stuff */
502 482
503/* set from board file */ 483/* set from board file */
504static u32 omap_vram_sram_start __initdata;
505static u32 omap_vram_sram_size __initdata;
506
507/* set from board file */
508static u32 omap_vram_sdram_start __initdata; 484static u32 omap_vram_sdram_start __initdata;
509static u32 omap_vram_sdram_size __initdata; 485static u32 omap_vram_sdram_size __initdata;
510 486
@@ -587,73 +563,8 @@ void __init omap_vram_reserve_sdram_memblock(void)
587 pr_info("Reserving %u bytes SDRAM for VRAM\n", size); 563 pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
588} 564}
589 565
590/*
591 * Called at sram init time, before anything is pushed to the SRAM stack.
592 * Because of the stack scheme, we will allocate everything from the
593 * start of the lowest address region to the end of SRAM. This will also
594 * include padding for page alignment and possible holes between regions.
595 *
596 * As opposed to the SDRAM case, we'll also do any dynamic allocations at
597 * this point, since the driver built as a module would have problem with
598 * freeing / reallocating the regions.
599 */
600unsigned long __init omap_vram_reserve_sram(unsigned long sram_pstart,
601 unsigned long sram_vstart,
602 unsigned long sram_size,
603 unsigned long pstart_avail,
604 unsigned long size_avail)
605{
606 unsigned long pend_avail;
607 unsigned long reserved;
608 u32 paddr;
609 u32 size;
610
611 paddr = omap_vram_sram_start;
612 size = omap_vram_sram_size;
613
614 if (!size)
615 return 0;
616
617 reserved = 0;
618 pend_avail = pstart_avail + size_avail;
619
620 if (!paddr) {
621 /* Dynamic allocation */
622 if ((size_avail & PAGE_MASK) < size) {
623 pr_err("Not enough SRAM for VRAM\n");
624 return 0;
625 }
626 size_avail = (size_avail - size) & PAGE_MASK;
627 paddr = pstart_avail + size_avail;
628 }
629
630 if (paddr < sram_pstart ||
631 paddr + size > sram_pstart + sram_size) {
632 pr_err("Illegal SRAM region for VRAM\n");
633 return 0;
634 }
635
636 /* Reserve everything above the start of the region. */
637 if (pend_avail - paddr > reserved)
638 reserved = pend_avail - paddr;
639 size_avail = pend_avail - reserved - pstart_avail;
640
641 omap_vram_add_region(paddr, size);
642
643 if (reserved)
644 pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved);
645
646 return reserved;
647}
648
649void __init omap_vram_set_sdram_vram(u32 size, u32 start) 566void __init omap_vram_set_sdram_vram(u32 size, u32 start)
650{ 567{
651 omap_vram_sdram_start = start; 568 omap_vram_sdram_start = start;
652 omap_vram_sdram_size = size; 569 omap_vram_sdram_size = size;
653} 570}
654
655void __init omap_vram_set_sram_vram(u32 size, u32 start)
656{
657 omap_vram_sram_start = start;
658 omap_vram_sram_size = size;
659}
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 3a3fdc62c75b..bcd44c32a2ed 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -895,7 +895,7 @@ static int __init pvr2fb_dc_init(void)
895 895
896#ifdef CONFIG_PVR2_DMA 896#ifdef CONFIG_PVR2_DMA
897 if (request_dma(pvr2dma, "pvr2") != 0) { 897 if (request_dma(pvr2dma, "pvr2") != 0) {
898 free_irq(HW_EVENT_VSYNC, 0); 898 free_irq(HW_EVENT_VSYNC, fb_info);
899 return -EBUSY; 899 return -EBUSY;
900 } 900 }
901#endif 901#endif
@@ -914,7 +914,7 @@ static void __exit pvr2fb_dc_exit(void)
914 currentpar->mmio_base = 0; 914 currentpar->mmio_base = 0;
915 } 915 }
916 916
917 free_irq(HW_EVENT_VSYNC, 0); 917 free_irq(HW_EVENT_VSYNC, fb_info);
918#ifdef CONFIG_PVR2_DMA 918#ifdef CONFIG_PVR2_DMA
919 free_dma(pvr2dma); 919 free_dma(pvr2dma);
920#endif 920#endif
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index 8384b941f6ba..f146089261f4 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -21,6 +21,7 @@
21#include <linux/fb.h> 21#include <linux/fb.h>
22#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/io.h>
24#include <linux/ioport.h> 25#include <linux/ioport.h>
25#include <linux/platform_device.h> 26#include <linux/platform_device.h>
26#include <linux/dma-mapping.h> 27#include <linux/dma-mapping.h>
@@ -670,7 +671,8 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
670 /* 671 /*
671 * Map LCD controller registers. 672 * Map LCD controller registers.
672 */ 673 */
673 fbi->reg_base = ioremap_nocache(res->start, resource_size(res)); 674 fbi->reg_base = devm_ioremap_nocache(&pdev->dev, res->start,
675 resource_size(res));
674 if (fbi->reg_base == NULL) { 676 if (fbi->reg_base == NULL) {
675 ret = -ENOMEM; 677 ret = -ENOMEM;
676 goto failed_free_info; 678 goto failed_free_info;
@@ -739,8 +741,8 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
739 /* 741 /*
740 * Register irq handler. 742 * Register irq handler.
741 */ 743 */
742 ret = request_irq(irq, pxa168fb_handle_irq, IRQF_SHARED, 744 ret = devm_request_irq(&pdev->dev, irq, pxa168fb_handle_irq,
743 info->fix.id, fbi); 745 IRQF_SHARED, info->fix.id, fbi);
744 if (ret < 0) { 746 if (ret < 0) {
745 dev_err(&pdev->dev, "unable to request IRQ\n"); 747 dev_err(&pdev->dev, "unable to request IRQ\n");
746 ret = -ENXIO; 748 ret = -ENXIO;
@@ -759,14 +761,12 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
759 if (ret < 0) { 761 if (ret < 0) {
760 dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret); 762 dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret);
761 ret = -ENXIO; 763 ret = -ENXIO;
762 goto failed_free_irq; 764 goto failed_free_cmap;
763 } 765 }
764 766
765 platform_set_drvdata(pdev, fbi); 767 platform_set_drvdata(pdev, fbi);
766 return 0; 768 return 0;
767 769
768failed_free_irq:
769 free_irq(irq, fbi);
770failed_free_cmap: 770failed_free_cmap:
771 fb_dealloc_cmap(&info->cmap); 771 fb_dealloc_cmap(&info->cmap);
772failed_free_clk: 772failed_free_clk:
@@ -808,13 +808,10 @@ static int __devexit pxa168fb_remove(struct platform_device *pdev)
808 fb_dealloc_cmap(&info->cmap); 808 fb_dealloc_cmap(&info->cmap);
809 809
810 irq = platform_get_irq(pdev, 0); 810 irq = platform_get_irq(pdev, 0);
811 free_irq(irq, fbi);
812 811
813 dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len), 812 dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
814 info->screen_base, info->fix.smem_start); 813 info->screen_base, info->fix.smem_start);
815 814
816 iounmap(fbi->reg_base);
817
818 clk_disable(fbi->clk); 815 clk_disable(fbi->clk);
819 clk_put(fbi->clk); 816 clk_put(fbi->clk);
820 817
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 1d1e4f175e78..3f902557690e 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -54,6 +54,7 @@
54#include <linux/mutex.h> 54#include <linux/mutex.h>
55#include <linux/kthread.h> 55#include <linux/kthread.h>
56#include <linux/freezer.h> 56#include <linux/freezer.h>
57#include <linux/console.h>
57 58
58#include <mach/hardware.h> 59#include <mach/hardware.h>
59#include <asm/io.h> 60#include <asm/io.h>
@@ -730,9 +731,12 @@ static int overlayfb_open(struct fb_info *info, int user)
730 if (user == 0) 731 if (user == 0)
731 return -ENODEV; 732 return -ENODEV;
732 733
733 if (ofb->usage++ == 0) 734 if (ofb->usage++ == 0) {
734 /* unblank the base framebuffer */ 735 /* unblank the base framebuffer */
736 console_lock();
735 fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK); 737 fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);
738 console_unlock();
739 }
736 740
737 return 0; 741 return 0;
738} 742}
@@ -1431,7 +1435,7 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
1431 pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); 1435 pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
1432 1436
1433 /* enable LCD controller clock */ 1437 /* enable LCD controller clock */
1434 clk_enable(fbi->clk); 1438 clk_prepare_enable(fbi->clk);
1435 1439
1436 if (fbi->lccr0 & LCCR0_LCDT) 1440 if (fbi->lccr0 & LCCR0_LCDT)
1437 return; 1441 return;
@@ -1471,7 +1475,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
1471 wait_for_completion_timeout(&fbi->disable_done, 200 * HZ / 1000); 1475 wait_for_completion_timeout(&fbi->disable_done, 200 * HZ / 1000);
1472 1476
1473 /* disable LCD controller clock */ 1477 /* disable LCD controller clock */
1474 clk_disable(fbi->clk); 1478 clk_disable_unprepare(fbi->clk);
1475} 1479}
1476 1480
1477/* 1481/*
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 2f58cf9c813b..90df1a60bd16 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -1816,6 +1816,8 @@ static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
1816 specs->modedb, specs->modedb_len, 1816 specs->modedb, specs->modedb_len,
1817 NULL, 8); 1817 NULL, 8);
1818 } else if (specs->modedb != NULL) { 1818 } else if (specs->modedb != NULL) {
1819 /* get first mode in database as fallback */
1820 modedb = specs->modedb[0];
1819 /* get preferred timing */ 1821 /* get preferred timing */
1820 if (info->monspecs.misc & FB_MISC_1ST_DETAIL) { 1822 if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {
1821 int i; 1823 int i;
@@ -1826,9 +1828,6 @@ static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
1826 break; 1828 break;
1827 } 1829 }
1828 } 1830 }
1829 } else {
1830 /* otherwise, get first mode in database */
1831 modedb = specs->modedb[0];
1832 } 1831 }
1833 var->bits_per_pixel = 8; 1832 var->bits_per_pixel = 8;
1834 riva_update_var(var, &modedb); 1833 riva_update_var(var, &modedb);
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 0c63b69b6340..f3105160bf98 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -48,7 +48,8 @@
48#undef writel 48#undef writel
49#define writel(v, r) do { \ 49#define writel(v, r) do { \
50 printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \ 50 printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \
51 __raw_writel(v, r); } while (0) 51 __raw_writel(v, r); \
52} while (0)
52#endif /* FB_S3C_DEBUG_REGWRITE */ 53#endif /* FB_S3C_DEBUG_REGWRITE */
53 54
54/* irq_flags bits */ 55/* irq_flags bits */
@@ -81,12 +82,14 @@ struct s3c_fb;
81 * @palette: Address of palette memory, or 0 if none. 82 * @palette: Address of palette memory, or 0 if none.
82 * @has_prtcon: Set if has PRTCON register. 83 * @has_prtcon: Set if has PRTCON register.
83 * @has_shadowcon: Set if has SHADOWCON register. 84 * @has_shadowcon: Set if has SHADOWCON register.
85 * @has_blendcon: Set if has BLENDCON register.
84 * @has_clksel: Set if VIDCON0 register has CLKSEL bit. 86 * @has_clksel: Set if VIDCON0 register has CLKSEL bit.
87 * @has_fixvclk: Set if VIDCON1 register has FIXVCLK bits.
85 */ 88 */
86struct s3c_fb_variant { 89struct s3c_fb_variant {
87 unsigned int is_2443:1; 90 unsigned int is_2443:1;
88 unsigned short nr_windows; 91 unsigned short nr_windows;
89 unsigned short vidtcon; 92 unsigned int vidtcon;
90 unsigned short wincon; 93 unsigned short wincon;
91 unsigned short winmap; 94 unsigned short winmap;
92 unsigned short keycon; 95 unsigned short keycon;
@@ -99,7 +102,9 @@ struct s3c_fb_variant {
99 102
100 unsigned int has_prtcon:1; 103 unsigned int has_prtcon:1;
101 unsigned int has_shadowcon:1; 104 unsigned int has_shadowcon:1;
105 unsigned int has_blendcon:1;
102 unsigned int has_clksel:1; 106 unsigned int has_clksel:1;
107 unsigned int has_fixvclk:1;
103}; 108};
104 109
105/** 110/**
@@ -186,7 +191,6 @@ struct s3c_fb_vsync {
186 * struct s3c_fb - overall hardware state of the hardware 191 * struct s3c_fb - overall hardware state of the hardware
187 * @slock: The spinlock protection for this data sturcture. 192 * @slock: The spinlock protection for this data sturcture.
188 * @dev: The device that we bound to, for printing, etc. 193 * @dev: The device that we bound to, for printing, etc.
189 * @regs_res: The resource we claimed for the IO registers.
190 * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. 194 * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
191 * @lcd_clk: The clk (sclk) feeding pixclk. 195 * @lcd_clk: The clk (sclk) feeding pixclk.
192 * @regs: The mapped hardware registers. 196 * @regs: The mapped hardware registers.
@@ -202,7 +206,6 @@ struct s3c_fb_vsync {
202struct s3c_fb { 206struct s3c_fb {
203 spinlock_t slock; 207 spinlock_t slock;
204 struct device *dev; 208 struct device *dev;
205 struct resource *regs_res;
206 struct clk *bus_clk; 209 struct clk *bus_clk;
207 struct clk *lcd_clk; 210 struct clk *lcd_clk;
208 void __iomem *regs; 211 void __iomem *regs;
@@ -565,7 +568,9 @@ static int s3c_fb_set_par(struct fb_info *info)
565 writel(data, regs + sfb->variant.vidtcon + 4); 568 writel(data, regs + sfb->variant.vidtcon + 4);
566 569
567 data = VIDTCON2_LINEVAL(var->yres - 1) | 570 data = VIDTCON2_LINEVAL(var->yres - 1) |
568 VIDTCON2_HOZVAL(var->xres - 1); 571 VIDTCON2_HOZVAL(var->xres - 1) |
572 VIDTCON2_LINEVAL_E(var->yres - 1) |
573 VIDTCON2_HOZVAL_E(var->xres - 1);
569 writel(data, regs + sfb->variant.vidtcon + 8); 574 writel(data, regs + sfb->variant.vidtcon + 8);
570 } 575 }
571 576
@@ -581,17 +586,23 @@ static int s3c_fb_set_par(struct fb_info *info)
581 586
582 pagewidth = (var->xres * var->bits_per_pixel) >> 3; 587 pagewidth = (var->xres * var->bits_per_pixel) >> 3;
583 data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) | 588 data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) |
584 VIDW_BUF_SIZE_PAGEWIDTH(pagewidth); 589 VIDW_BUF_SIZE_PAGEWIDTH(pagewidth) |
590 VIDW_BUF_SIZE_OFFSET_E(info->fix.line_length - pagewidth) |
591 VIDW_BUF_SIZE_PAGEWIDTH_E(pagewidth);
585 writel(data, regs + sfb->variant.buf_size + (win_no * 4)); 592 writel(data, regs + sfb->variant.buf_size + (win_no * 4));
586 593
587 /* write 'OSD' registers to control position of framebuffer */ 594 /* write 'OSD' registers to control position of framebuffer */
588 595
589 data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0); 596 data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0) |
597 VIDOSDxA_TOPLEFT_X_E(0) | VIDOSDxA_TOPLEFT_Y_E(0);
590 writel(data, regs + VIDOSD_A(win_no, sfb->variant)); 598 writel(data, regs + VIDOSD_A(win_no, sfb->variant));
591 599
592 data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel, 600 data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel,
593 var->xres - 1)) | 601 var->xres - 1)) |
594 VIDOSDxB_BOTRIGHT_Y(var->yres - 1); 602 VIDOSDxB_BOTRIGHT_Y(var->yres - 1) |
603 VIDOSDxB_BOTRIGHT_X_E(s3c_fb_align_word(var->bits_per_pixel,
604 var->xres - 1)) |
605 VIDOSDxB_BOTRIGHT_Y_E(var->yres - 1);
595 606
596 writel(data, regs + VIDOSD_B(win_no, sfb->variant)); 607 writel(data, regs + VIDOSD_B(win_no, sfb->variant));
597 608
@@ -692,6 +703,17 @@ static int s3c_fb_set_par(struct fb_info *info)
692 writel(data, regs + sfb->variant.wincon + (win_no * 4)); 703 writel(data, regs + sfb->variant.wincon + (win_no * 4));
693 writel(0x0, regs + sfb->variant.winmap + (win_no * 4)); 704 writel(0x0, regs + sfb->variant.winmap + (win_no * 4));
694 705
706 /* Set alpha value width */
707 if (sfb->variant.has_blendcon) {
708 data = readl(sfb->regs + BLENDCON);
709 data &= ~BLENDCON_NEW_MASK;
710 if (var->transp.length > 4)
711 data |= BLENDCON_NEW_8BIT_ALPHA_VALUE;
712 else
713 data |= BLENDCON_NEW_4BIT_ALPHA_VALUE;
714 writel(data, sfb->regs + BLENDCON);
715 }
716
695 shadow_protect_win(win, 0); 717 shadow_protect_win(win, 0);
696 718
697 pm_runtime_put_sync(sfb->dev); 719 pm_runtime_put_sync(sfb->dev);
@@ -1346,6 +1368,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1346 struct resource *res; 1368 struct resource *res;
1347 int win; 1369 int win;
1348 int ret = 0; 1370 int ret = 0;
1371 u32 reg;
1349 1372
1350 platid = platform_get_device_id(pdev); 1373 platid = platform_get_device_id(pdev);
1351 fbdrv = (struct s3c_fb_driverdata *)platid->driver_data; 1374 fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
@@ -1361,7 +1384,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1361 return -EINVAL; 1384 return -EINVAL;
1362 } 1385 }
1363 1386
1364 sfb = kzalloc(sizeof(struct s3c_fb), GFP_KERNEL); 1387 sfb = devm_kzalloc(dev, sizeof(struct s3c_fb), GFP_KERNEL);
1365 if (!sfb) { 1388 if (!sfb) {
1366 dev_err(dev, "no memory for framebuffers\n"); 1389 dev_err(dev, "no memory for framebuffers\n");
1367 return -ENOMEM; 1390 return -ENOMEM;
@@ -1404,33 +1427,25 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1404 goto err_lcd_clk; 1427 goto err_lcd_clk;
1405 } 1428 }
1406 1429
1407 sfb->regs_res = request_mem_region(res->start, resource_size(res), 1430 sfb->regs = devm_request_and_ioremap(dev, res);
1408 dev_name(dev));
1409 if (!sfb->regs_res) {
1410 dev_err(dev, "failed to claim register region\n");
1411 ret = -ENOENT;
1412 goto err_lcd_clk;
1413 }
1414
1415 sfb->regs = ioremap(res->start, resource_size(res));
1416 if (!sfb->regs) { 1431 if (!sfb->regs) {
1417 dev_err(dev, "failed to map registers\n"); 1432 dev_err(dev, "failed to map registers\n");
1418 ret = -ENXIO; 1433 ret = -ENXIO;
1419 goto err_req_region; 1434 goto err_lcd_clk;
1420 } 1435 }
1421 1436
1422 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 1437 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1423 if (!res) { 1438 if (!res) {
1424 dev_err(dev, "failed to acquire irq resource\n"); 1439 dev_err(dev, "failed to acquire irq resource\n");
1425 ret = -ENOENT; 1440 ret = -ENOENT;
1426 goto err_ioremap; 1441 goto err_lcd_clk;
1427 } 1442 }
1428 sfb->irq_no = res->start; 1443 sfb->irq_no = res->start;
1429 ret = request_irq(sfb->irq_no, s3c_fb_irq, 1444 ret = devm_request_irq(dev, sfb->irq_no, s3c_fb_irq,
1430 0, "s3c_fb", sfb); 1445 0, "s3c_fb", sfb);
1431 if (ret) { 1446 if (ret) {
1432 dev_err(dev, "irq request failed\n"); 1447 dev_err(dev, "irq request failed\n");
1433 goto err_ioremap; 1448 goto err_lcd_clk;
1434 } 1449 }
1435 1450
1436 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs); 1451 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
@@ -1444,6 +1459,14 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1444 1459
1445 writel(pd->vidcon1, sfb->regs + VIDCON1); 1460 writel(pd->vidcon1, sfb->regs + VIDCON1);
1446 1461
1462 /* set video clock running at under-run */
1463 if (sfb->variant.has_fixvclk) {
1464 reg = readl(sfb->regs + VIDCON1);
1465 reg &= ~VIDCON1_VCLK_MASK;
1466 reg |= VIDCON1_VCLK_RUN;
1467 writel(reg, sfb->regs + VIDCON1);
1468 }
1469
1447 /* zero all windows before we do anything */ 1470 /* zero all windows before we do anything */
1448 1471
1449 for (win = 0; win < fbdrv->variant.nr_windows; win++) 1472 for (win = 0; win < fbdrv->variant.nr_windows; win++)
@@ -1484,13 +1507,6 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1484 1507
1485err_pm_runtime: 1508err_pm_runtime:
1486 pm_runtime_put_sync(sfb->dev); 1509 pm_runtime_put_sync(sfb->dev);
1487 free_irq(sfb->irq_no, sfb);
1488
1489err_ioremap:
1490 iounmap(sfb->regs);
1491
1492err_req_region:
1493 release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
1494 1510
1495err_lcd_clk: 1511err_lcd_clk:
1496 pm_runtime_disable(sfb->dev); 1512 pm_runtime_disable(sfb->dev);
@@ -1505,7 +1521,6 @@ err_bus_clk:
1505 clk_put(sfb->bus_clk); 1521 clk_put(sfb->bus_clk);
1506 1522
1507err_sfb: 1523err_sfb:
1508 kfree(sfb);
1509 return ret; 1524 return ret;
1510} 1525}
1511 1526
@@ -1527,10 +1542,6 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1527 if (sfb->windows[win]) 1542 if (sfb->windows[win])
1528 s3c_fb_release_win(sfb, sfb->windows[win]); 1543 s3c_fb_release_win(sfb, sfb->windows[win]);
1529 1544
1530 free_irq(sfb->irq_no, sfb);
1531
1532 iounmap(sfb->regs);
1533
1534 if (!sfb->variant.has_clksel) { 1545 if (!sfb->variant.has_clksel) {
1535 clk_disable(sfb->lcd_clk); 1546 clk_disable(sfb->lcd_clk);
1536 clk_put(sfb->lcd_clk); 1547 clk_put(sfb->lcd_clk);
@@ -1539,12 +1550,9 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1539 clk_disable(sfb->bus_clk); 1550 clk_disable(sfb->bus_clk);
1540 clk_put(sfb->bus_clk); 1551 clk_put(sfb->bus_clk);
1541 1552
1542 release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
1543
1544 pm_runtime_put_sync(sfb->dev); 1553 pm_runtime_put_sync(sfb->dev);
1545 pm_runtime_disable(sfb->dev); 1554 pm_runtime_disable(sfb->dev);
1546 1555
1547 kfree(sfb);
1548 return 0; 1556 return 0;
1549} 1557}
1550 1558
@@ -1579,6 +1587,7 @@ static int s3c_fb_resume(struct device *dev)
1579 struct s3c_fb_platdata *pd = sfb->pdata; 1587 struct s3c_fb_platdata *pd = sfb->pdata;
1580 struct s3c_fb_win *win; 1588 struct s3c_fb_win *win;
1581 int win_no; 1589 int win_no;
1590 u32 reg;
1582 1591
1583 clk_enable(sfb->bus_clk); 1592 clk_enable(sfb->bus_clk);
1584 1593
@@ -1589,6 +1598,14 @@ static int s3c_fb_resume(struct device *dev)
1589 pd->setup_gpio(); 1598 pd->setup_gpio();
1590 writel(pd->vidcon1, sfb->regs + VIDCON1); 1599 writel(pd->vidcon1, sfb->regs + VIDCON1);
1591 1600
1601 /* set video clock running at under-run */
1602 if (sfb->variant.has_fixvclk) {
1603 reg = readl(sfb->regs + VIDCON1);
1604 reg &= ~VIDCON1_VCLK_MASK;
1605 reg |= VIDCON1_VCLK_RUN;
1606 writel(reg, sfb->regs + VIDCON1);
1607 }
1608
1592 /* zero all windows before we do anything */ 1609 /* zero all windows before we do anything */
1593 for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++) 1610 for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
1594 s3c_fb_clear_win(sfb, win_no); 1611 s3c_fb_clear_win(sfb, win_no);
@@ -1819,6 +1836,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
1819 }, 1836 },
1820 1837
1821 .has_prtcon = 1, 1838 .has_prtcon = 1,
1839 .has_blendcon = 1,
1822 .has_clksel = 1, 1840 .has_clksel = 1,
1823 }, 1841 },
1824 .win[0] = &s3c_fb_data_s5p_wins[0], 1842 .win[0] = &s3c_fb_data_s5p_wins[0],
@@ -1850,7 +1868,9 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
1850 }, 1868 },
1851 1869
1852 .has_shadowcon = 1, 1870 .has_shadowcon = 1,
1871 .has_blendcon = 1,
1853 .has_clksel = 1, 1872 .has_clksel = 1,
1873 .has_fixvclk = 1,
1854 }, 1874 },
1855 .win[0] = &s3c_fb_data_s5p_wins[0], 1875 .win[0] = &s3c_fb_data_s5p_wins[0],
1856 .win[1] = &s3c_fb_data_s5p_wins[1], 1876 .win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1881,6 +1901,39 @@ static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
1881 }, 1901 },
1882 1902
1883 .has_shadowcon = 1, 1903 .has_shadowcon = 1,
1904 .has_blendcon = 1,
1905 .has_fixvclk = 1,
1906 },
1907 .win[0] = &s3c_fb_data_s5p_wins[0],
1908 .win[1] = &s3c_fb_data_s5p_wins[1],
1909 .win[2] = &s3c_fb_data_s5p_wins[2],
1910 .win[3] = &s3c_fb_data_s5p_wins[3],
1911 .win[4] = &s3c_fb_data_s5p_wins[4],
1912};
1913
1914static struct s3c_fb_driverdata s3c_fb_data_exynos5 = {
1915 .variant = {
1916 .nr_windows = 5,
1917 .vidtcon = VIDTCON0,
1918 .wincon = WINCON(0),
1919 .winmap = WINxMAP(0),
1920 .keycon = WKEYCON,
1921 .osd = VIDOSD_BASE,
1922 .osd_stride = 16,
1923 .buf_start = VIDW_BUF_START(0),
1924 .buf_size = VIDW_BUF_SIZE(0),
1925 .buf_end = VIDW_BUF_END(0),
1926
1927 .palette = {
1928 [0] = 0x2400,
1929 [1] = 0x2800,
1930 [2] = 0x2c00,
1931 [3] = 0x3000,
1932 [4] = 0x3400,
1933 },
1934 .has_shadowcon = 1,
1935 .has_blendcon = 1,
1936 .has_fixvclk = 1,
1884 }, 1937 },
1885 .win[0] = &s3c_fb_data_s5p_wins[0], 1938 .win[0] = &s3c_fb_data_s5p_wins[0],
1886 .win[1] = &s3c_fb_data_s5p_wins[1], 1939 .win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1944,6 +1997,9 @@ static struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = {
1944 [1] = 0x2800, 1997 [1] = 0x2800,
1945 [2] = 0x2c00, 1998 [2] = 0x2c00,
1946 }, 1999 },
2000
2001 .has_blendcon = 1,
2002 .has_fixvclk = 1,
1947 }, 2003 },
1948 .win[0] = &s3c_fb_data_s5p_wins[0], 2004 .win[0] = &s3c_fb_data_s5p_wins[0],
1949 .win[1] = &s3c_fb_data_s5p_wins[1], 2005 .win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1964,6 +2020,9 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
1964 .name = "exynos4-fb", 2020 .name = "exynos4-fb",
1965 .driver_data = (unsigned long)&s3c_fb_data_exynos4, 2021 .driver_data = (unsigned long)&s3c_fb_data_exynos4,
1966 }, { 2022 }, {
2023 .name = "exynos5-fb",
2024 .driver_data = (unsigned long)&s3c_fb_data_exynos5,
2025 }, {
1967 .name = "s3c2443-fb", 2026 .name = "s3c2443-fb",
1968 .driver_data = (unsigned long)&s3c_fb_data_s3c2443, 2027 .driver_data = (unsigned long)&s3c_fb_data_s3c2443,
1969 }, { 2028 }, {
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 05151b82f40f..4c6b84488561 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -24,6 +24,8 @@
24#include <video/sh_mipi_dsi.h> 24#include <video/sh_mipi_dsi.h>
25#include <video/sh_mobile_lcdc.h> 25#include <video/sh_mobile_lcdc.h>
26 26
27#include "sh_mobile_lcdcfb.h"
28
27#define SYSCTRL 0x0000 29#define SYSCTRL 0x0000
28#define SYSCONF 0x0004 30#define SYSCONF 0x0004
29#define TIMSET 0x0008 31#define TIMSET 0x0008
@@ -50,16 +52,16 @@
50#define MAX_SH_MIPI_DSI 2 52#define MAX_SH_MIPI_DSI 2
51 53
52struct sh_mipi { 54struct sh_mipi {
55 struct sh_mobile_lcdc_entity entity;
56
53 void __iomem *base; 57 void __iomem *base;
54 void __iomem *linkbase; 58 void __iomem *linkbase;
55 struct clk *dsit_clk; 59 struct clk *dsit_clk;
56 struct platform_device *pdev; 60 struct platform_device *pdev;
57
58 void *next_board_data;
59 void (*next_display_on)(void *board_data, struct fb_info *info);
60 void (*next_display_off)(void *board_data);
61}; 61};
62 62
63#define to_sh_mipi(e) container_of(e, struct sh_mipi, entity)
64
63static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI]; 65static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI];
64 66
65/* Protect the above array */ 67/* Protect the above array */
@@ -120,7 +122,7 @@ static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable)
120 122
121static void sh_mipi_shutdown(struct platform_device *pdev) 123static void sh_mipi_shutdown(struct platform_device *pdev)
122{ 124{
123 struct sh_mipi *mipi = platform_get_drvdata(pdev); 125 struct sh_mipi *mipi = to_sh_mipi(platform_get_drvdata(pdev));
124 126
125 sh_mipi_dsi_enable(mipi, false); 127 sh_mipi_dsi_enable(mipi, false);
126} 128}
@@ -145,77 +147,77 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
145 pctype = 0; 147 pctype = 0;
146 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; 148 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
147 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 149 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
148 linelength = ch->lcd_cfg[0].xres * 3; 150 linelength = ch->lcd_modes[0].xres * 3;
149 yuv = false; 151 yuv = false;
150 break; 152 break;
151 case MIPI_RGB565: 153 case MIPI_RGB565:
152 pctype = 1; 154 pctype = 1;
153 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; 155 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
154 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 156 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
155 linelength = ch->lcd_cfg[0].xres * 2; 157 linelength = ch->lcd_modes[0].xres * 2;
156 yuv = false; 158 yuv = false;
157 break; 159 break;
158 case MIPI_RGB666_LP: 160 case MIPI_RGB666_LP:
159 pctype = 2; 161 pctype = 2;
160 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 162 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
161 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 163 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
162 linelength = ch->lcd_cfg[0].xres * 3; 164 linelength = ch->lcd_modes[0].xres * 3;
163 yuv = false; 165 yuv = false;
164 break; 166 break;
165 case MIPI_RGB666: 167 case MIPI_RGB666:
166 pctype = 3; 168 pctype = 3;
167 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; 169 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
168 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; 170 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
169 linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8; 171 linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
170 yuv = false; 172 yuv = false;
171 break; 173 break;
172 case MIPI_BGR888: 174 case MIPI_BGR888:
173 pctype = 8; 175 pctype = 8;
174 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; 176 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
175 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 177 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
176 linelength = ch->lcd_cfg[0].xres * 3; 178 linelength = ch->lcd_modes[0].xres * 3;
177 yuv = false; 179 yuv = false;
178 break; 180 break;
179 case MIPI_BGR565: 181 case MIPI_BGR565:
180 pctype = 9; 182 pctype = 9;
181 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; 183 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
182 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 184 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
183 linelength = ch->lcd_cfg[0].xres * 2; 185 linelength = ch->lcd_modes[0].xres * 2;
184 yuv = false; 186 yuv = false;
185 break; 187 break;
186 case MIPI_BGR666_LP: 188 case MIPI_BGR666_LP:
187 pctype = 0xa; 189 pctype = 0xa;
188 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 190 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
189 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 191 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
190 linelength = ch->lcd_cfg[0].xres * 3; 192 linelength = ch->lcd_modes[0].xres * 3;
191 yuv = false; 193 yuv = false;
192 break; 194 break;
193 case MIPI_BGR666: 195 case MIPI_BGR666:
194 pctype = 0xb; 196 pctype = 0xb;
195 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; 197 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
196 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; 198 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
197 linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8; 199 linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
198 yuv = false; 200 yuv = false;
199 break; 201 break;
200 case MIPI_YUYV: 202 case MIPI_YUYV:
201 pctype = 4; 203 pctype = 4;
202 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; 204 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
203 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 205 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
204 linelength = ch->lcd_cfg[0].xres * 2; 206 linelength = ch->lcd_modes[0].xres * 2;
205 yuv = true; 207 yuv = true;
206 break; 208 break;
207 case MIPI_UYVY: 209 case MIPI_UYVY:
208 pctype = 5; 210 pctype = 5;
209 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; 211 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
210 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 212 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
211 linelength = ch->lcd_cfg[0].xres * 2; 213 linelength = ch->lcd_modes[0].xres * 2;
212 yuv = true; 214 yuv = true;
213 break; 215 break;
214 case MIPI_YUV420_L: 216 case MIPI_YUV420_L:
215 pctype = 6; 217 pctype = 6;
216 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; 218 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
217 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; 219 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
218 linelength = (ch->lcd_cfg[0].xres * 12 + 7) / 8; 220 linelength = (ch->lcd_modes[0].xres * 12 + 7) / 8;
219 yuv = true; 221 yuv = true;
220 break; 222 break;
221 case MIPI_YUV420: 223 case MIPI_YUV420:
@@ -223,7 +225,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
223 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; 225 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
224 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; 226 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
225 /* Length of U/V line */ 227 /* Length of U/V line */
226 linelength = (ch->lcd_cfg[0].xres + 1) / 2; 228 linelength = (ch->lcd_modes[0].xres + 1) / 2;
227 yuv = true; 229 yuv = true;
228 break; 230 break;
229 default: 231 default:
@@ -271,7 +273,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
271 iowrite32(0x00000001, base + PHYCTRL); 273 iowrite32(0x00000001, base + PHYCTRL);
272 udelay(200); 274 udelay(200);
273 /* Deassert resets, power on */ 275 /* Deassert resets, power on */
274 iowrite32(0x03070001, base + PHYCTRL); 276 iowrite32(0x03070001 | pdata->phyctrl, base + PHYCTRL);
275 277
276 /* 278 /*
277 * Default = ULPS enable | 279 * Default = ULPS enable |
@@ -292,7 +294,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
292 */ 294 */
293 iowrite32(0x00000006, mipi->linkbase + DTCTR); 295 iowrite32(0x00000006, mipi->linkbase + DTCTR);
294 /* VSYNC width = 2 (<< 17) */ 296 /* VSYNC width = 2 (<< 17) */
295 iowrite32((ch->lcd_cfg[0].vsync_len << pdata->vsynw_offset) | 297 iowrite32((ch->lcd_modes[0].vsync_len << pdata->vsynw_offset) |
296 (pdata->clksrc << 16) | (pctype << 12) | datatype, 298 (pdata->clksrc << 16) | (pctype << 12) | datatype,
297 mipi->linkbase + VMCTR1); 299 mipi->linkbase + VMCTR1);
298 300
@@ -326,7 +328,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
326 top = linelength << 16; /* RGBLEN */ 328 top = linelength << 16; /* RGBLEN */
327 bottom = 0x00000001; 329 bottom = 0x00000001;
328 if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */ 330 if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
329 bottom = (pdata->lane * ch->lcd_cfg[0].hsync_len) - 10; 331 bottom = (pdata->lane * ch->lcd_modes[0].hsync_len) - 10;
330 iowrite32(top | bottom , mipi->linkbase + VMLEN1); 332 iowrite32(top | bottom , mipi->linkbase + VMLEN1);
331 333
332 /* 334 /*
@@ -346,18 +348,18 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
346 div = 2; 348 div = 2;
347 349
348 if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */ 350 if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */
349 top = ch->lcd_cfg[0].hsync_len + ch->lcd_cfg[0].left_margin; 351 top = ch->lcd_modes[0].hsync_len + ch->lcd_modes[0].left_margin;
350 top = ((pdata->lane * top / div) - 10) << 16; 352 top = ((pdata->lane * top / div) - 10) << 16;
351 } 353 }
352 if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */ 354 if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
353 bottom = ch->lcd_cfg[0].right_margin; 355 bottom = ch->lcd_modes[0].right_margin;
354 bottom = (pdata->lane * bottom / div) - 12; 356 bottom = (pdata->lane * bottom / div) - 12;
355 } 357 }
356 358
357 bpp = linelength / ch->lcd_cfg[0].xres; /* byte / pixel */ 359 bpp = linelength / ch->lcd_modes[0].xres; /* byte / pixel */
358 if ((pdata->lane / div) > bpp) { 360 if ((pdata->lane / div) > bpp) {
359 tmp = ch->lcd_cfg[0].xres / bpp; /* output cycle */ 361 tmp = ch->lcd_modes[0].xres / bpp; /* output cycle */
360 tmp = ch->lcd_cfg[0].xres - tmp; /* (input - output) cycle */ 362 tmp = ch->lcd_modes[0].xres - tmp; /* (input - output) cycle */
361 delay = (pdata->lane * tmp); 363 delay = (pdata->lane * tmp);
362 } 364 }
363 365
@@ -392,9 +394,9 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
392 return 0; 394 return 0;
393} 395}
394 396
395static void mipi_display_on(void *arg, struct fb_info *info) 397static int mipi_display_on(struct sh_mobile_lcdc_entity *entity)
396{ 398{
397 struct sh_mipi *mipi = arg; 399 struct sh_mipi *mipi = to_sh_mipi(entity);
398 struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; 400 struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
399 int ret; 401 int ret;
400 402
@@ -410,25 +412,21 @@ static void mipi_display_on(void *arg, struct fb_info *info)
410 412
411 sh_mipi_dsi_enable(mipi, true); 413 sh_mipi_dsi_enable(mipi, true);
412 414
413 if (mipi->next_display_on) 415 return SH_MOBILE_LCDC_DISPLAY_CONNECTED;
414 mipi->next_display_on(mipi->next_board_data, info);
415
416 return;
417 416
418mipi_display_on_fail1: 417mipi_display_on_fail1:
419 pm_runtime_put_sync(&mipi->pdev->dev); 418 pm_runtime_put_sync(&mipi->pdev->dev);
420mipi_display_on_fail2: 419mipi_display_on_fail2:
421 pdata->set_dot_clock(mipi->pdev, mipi->base, 0); 420 pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
421
422 return ret;
422} 423}
423 424
424static void mipi_display_off(void *arg) 425static void mipi_display_off(struct sh_mobile_lcdc_entity *entity)
425{ 426{
426 struct sh_mipi *mipi = arg; 427 struct sh_mipi *mipi = to_sh_mipi(entity);
427 struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; 428 struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
428 429
429 if (mipi->next_display_off)
430 mipi->next_display_off(mipi->next_board_data);
431
432 sh_mipi_dsi_enable(mipi, false); 430 sh_mipi_dsi_enable(mipi, false);
433 431
434 pdata->set_dot_clock(mipi->pdev, mipi->base, 0); 432 pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
@@ -436,6 +434,11 @@ static void mipi_display_off(void *arg)
436 pm_runtime_put_sync(&mipi->pdev->dev); 434 pm_runtime_put_sync(&mipi->pdev->dev);
437} 435}
438 436
437static const struct sh_mobile_lcdc_entity_ops mipi_ops = {
438 .display_on = mipi_display_on,
439 .display_off = mipi_display_off,
440};
441
439static int __init sh_mipi_probe(struct platform_device *pdev) 442static int __init sh_mipi_probe(struct platform_device *pdev)
440{ 443{
441 struct sh_mipi *mipi; 444 struct sh_mipi *mipi;
@@ -467,6 +470,9 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
467 goto ealloc; 470 goto ealloc;
468 } 471 }
469 472
473 mipi->entity.owner = THIS_MODULE;
474 mipi->entity.ops = &mipi_ops;
475
470 if (!request_mem_region(res->start, resource_size(res), pdev->name)) { 476 if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
471 dev_err(&pdev->dev, "MIPI register region already claimed\n"); 477 dev_err(&pdev->dev, "MIPI register region already claimed\n");
472 ret = -EBUSY; 478 ret = -EBUSY;
@@ -521,18 +527,7 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
521 pm_runtime_resume(&pdev->dev); 527 pm_runtime_resume(&pdev->dev);
522 528
523 mutex_unlock(&array_lock); 529 mutex_unlock(&array_lock);
524 platform_set_drvdata(pdev, mipi); 530 platform_set_drvdata(pdev, &mipi->entity);
525
526 /* Save original LCDC callbacks */
527 mipi->next_board_data = pdata->lcd_chan->board_cfg.board_data;
528 mipi->next_display_on = pdata->lcd_chan->board_cfg.display_on;
529 mipi->next_display_off = pdata->lcd_chan->board_cfg.display_off;
530
531 /* Set up LCDC callbacks */
532 pdata->lcd_chan->board_cfg.board_data = mipi;
533 pdata->lcd_chan->board_cfg.display_on = mipi_display_on;
534 pdata->lcd_chan->board_cfg.display_off = mipi_display_off;
535 pdata->lcd_chan->board_cfg.owner = THIS_MODULE;
536 531
537 return 0; 532 return 0;
538 533
@@ -558,10 +553,9 @@ efindslot:
558 553
559static int __exit sh_mipi_remove(struct platform_device *pdev) 554static int __exit sh_mipi_remove(struct platform_device *pdev)
560{ 555{
561 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
562 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 556 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
563 struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); 557 struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
564 struct sh_mipi *mipi = platform_get_drvdata(pdev); 558 struct sh_mipi *mipi = to_sh_mipi(platform_get_drvdata(pdev));
565 int i, ret; 559 int i, ret;
566 560
567 mutex_lock(&array_lock); 561 mutex_lock(&array_lock);
@@ -581,11 +575,6 @@ static int __exit sh_mipi_remove(struct platform_device *pdev)
581 if (ret < 0) 575 if (ret < 0)
582 return ret; 576 return ret;
583 577
584 pdata->lcd_chan->board_cfg.owner = NULL;
585 pdata->lcd_chan->board_cfg.display_on = NULL;
586 pdata->lcd_chan->board_cfg.display_off = NULL;
587 pdata->lcd_chan->board_cfg.board_data = NULL;
588
589 pm_runtime_disable(&pdev->dev); 578 pm_runtime_disable(&pdev->dev);
590 clk_disable(mipi->dsit_clk); 579 clk_disable(mipi->dsit_clk);
591 clk_put(mipi->dsit_clk); 580 clk_put(mipi->dsit_clk);
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index 647ba984f00f..eafb19da2c07 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -208,6 +208,8 @@ enum hotplug_state {
208}; 208};
209 209
210struct sh_hdmi { 210struct sh_hdmi {
211 struct sh_mobile_lcdc_entity entity;
212
211 void __iomem *base; 213 void __iomem *base;
212 enum hotplug_state hp_state; /* hot-plug status */ 214 enum hotplug_state hp_state; /* hot-plug status */
213 u8 preprogrammed_vic; /* use a pre-programmed VIC or 215 u8 preprogrammed_vic; /* use a pre-programmed VIC or
@@ -217,14 +219,13 @@ struct sh_hdmi {
217 u8 edid_blocks; 219 u8 edid_blocks;
218 struct clk *hdmi_clk; 220 struct clk *hdmi_clk;
219 struct device *dev; 221 struct device *dev;
220 struct fb_info *info;
221 struct mutex mutex; /* Protect the info pointer */
222 struct delayed_work edid_work; 222 struct delayed_work edid_work;
223 struct fb_var_screeninfo var; 223 struct fb_videomode mode;
224 struct fb_monspecs monspec; 224 struct fb_monspecs monspec;
225 struct notifier_block notifier;
226}; 225};
227 226
227#define entity_to_sh_hdmi(e) container_of(e, struct sh_hdmi, entity)
228
228static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) 229static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
229{ 230{
230 iowrite8(data, hdmi->base + reg); 231 iowrite8(data, hdmi->base + reg);
@@ -290,24 +291,24 @@ static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = {
290/* External video parameter settings */ 291/* External video parameter settings */
291static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi) 292static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
292{ 293{
293 struct fb_var_screeninfo *var = &hdmi->var; 294 struct fb_videomode *mode = &hdmi->mode;
294 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset; 295 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset;
295 u8 sync = 0; 296 u8 sync = 0;
296 297
297 htotal = var->xres + var->right_margin + var->left_margin + var->hsync_len; 298 htotal = mode->xres + mode->right_margin + mode->left_margin
298 299 + mode->hsync_len;
299 hdelay = var->hsync_len + var->left_margin; 300 hdelay = mode->hsync_len + mode->left_margin;
300 hblank = var->right_margin + hdelay; 301 hblank = mode->right_margin + hdelay;
301 302
302 /* 303 /*
303 * Vertical timing looks a bit different in Figure 18, 304 * Vertical timing looks a bit different in Figure 18,
304 * but let's try the same first by setting offset = 0 305 * but let's try the same first by setting offset = 0
305 */ 306 */
306 vtotal = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; 307 vtotal = mode->yres + mode->upper_margin + mode->lower_margin
307 308 + mode->vsync_len;
308 vdelay = var->vsync_len + var->upper_margin; 309 vdelay = mode->vsync_len + mode->upper_margin;
309 vblank = var->lower_margin + vdelay; 310 vblank = mode->lower_margin + vdelay;
310 voffset = min(var->upper_margin / 2, 6U); 311 voffset = min(mode->upper_margin / 2, 6U);
311 312
312 /* 313 /*
313 * [3]: VSYNC polarity: Positive 314 * [3]: VSYNC polarity: Positive
@@ -315,14 +316,14 @@ static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
315 * [1]: Interlace/Progressive: Progressive 316 * [1]: Interlace/Progressive: Progressive
316 * [0]: External video settings enable: used. 317 * [0]: External video settings enable: used.
317 */ 318 */
318 if (var->sync & FB_SYNC_HOR_HIGH_ACT) 319 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
319 sync |= 4; 320 sync |= 4;
320 if (var->sync & FB_SYNC_VERT_HIGH_ACT) 321 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
321 sync |= 8; 322 sync |= 8;
322 323
323 dev_dbg(hdmi->dev, "H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n", 324 dev_dbg(hdmi->dev, "H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n",
324 htotal, hblank, hdelay, var->hsync_len, 325 htotal, hblank, hdelay, mode->hsync_len,
325 vtotal, vblank, vdelay, var->vsync_len, sync); 326 vtotal, vblank, vdelay, mode->vsync_len, sync);
326 327
327 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); 328 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
328 329
@@ -335,8 +336,8 @@ static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
335 hdmi_write(hdmi, hdelay, HDMI_EXTERNAL_H_DELAY_7_0); 336 hdmi_write(hdmi, hdelay, HDMI_EXTERNAL_H_DELAY_7_0);
336 hdmi_write(hdmi, hdelay >> 8, HDMI_EXTERNAL_H_DELAY_9_8); 337 hdmi_write(hdmi, hdelay >> 8, HDMI_EXTERNAL_H_DELAY_9_8);
337 338
338 hdmi_write(hdmi, var->hsync_len, HDMI_EXTERNAL_H_DURATION_7_0); 339 hdmi_write(hdmi, mode->hsync_len, HDMI_EXTERNAL_H_DURATION_7_0);
339 hdmi_write(hdmi, var->hsync_len >> 8, HDMI_EXTERNAL_H_DURATION_9_8); 340 hdmi_write(hdmi, mode->hsync_len >> 8, HDMI_EXTERNAL_H_DURATION_9_8);
340 341
341 hdmi_write(hdmi, vtotal, HDMI_EXTERNAL_V_TOTAL_7_0); 342 hdmi_write(hdmi, vtotal, HDMI_EXTERNAL_V_TOTAL_7_0);
342 hdmi_write(hdmi, vtotal >> 8, HDMI_EXTERNAL_V_TOTAL_9_8); 343 hdmi_write(hdmi, vtotal >> 8, HDMI_EXTERNAL_V_TOTAL_9_8);
@@ -345,7 +346,7 @@ static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
345 346
346 hdmi_write(hdmi, vdelay, HDMI_EXTERNAL_V_DELAY); 347 hdmi_write(hdmi, vdelay, HDMI_EXTERNAL_V_DELAY);
347 348
348 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION); 349 hdmi_write(hdmi, mode->vsync_len, HDMI_EXTERNAL_V_DURATION);
349 350
350 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */ 351 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */
351 if (!hdmi->preprogrammed_vic) 352 if (!hdmi->preprogrammed_vic)
@@ -472,7 +473,7 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
472 */ 473 */
473static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) 474static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
474{ 475{
475 if (hdmi->var.pixclock < 10000) { 476 if (hdmi->mode.pixclock < 10000) {
476 /* for 1080p8bit 148MHz */ 477 /* for 1080p8bit 148MHz */
477 hdmi_write(hdmi, 0x1d, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); 478 hdmi_write(hdmi, 0x1d, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
478 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); 479 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
@@ -483,7 +484,7 @@ static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
483 hdmi_write(hdmi, 0x0e, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); 484 hdmi_write(hdmi, 0x0e, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
484 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); 485 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
485 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); 486 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
486 } else if (hdmi->var.pixclock < 30000) { 487 } else if (hdmi->mode.pixclock < 30000) {
487 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */ 488 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
488 /* 489 /*
489 * [1:0] Speed_A 490 * [1:0] Speed_A
@@ -732,14 +733,12 @@ static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
732static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, 733static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
733 unsigned long *parent_rate) 734 unsigned long *parent_rate)
734{ 735{
735 struct fb_var_screeninfo tmpvar; 736 struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc;
736 struct fb_var_screeninfo *var = &tmpvar;
737 const struct fb_videomode *mode, *found = NULL; 737 const struct fb_videomode *mode, *found = NULL;
738 struct fb_info *info = hdmi->info;
739 struct fb_modelist *modelist = NULL;
740 unsigned int f_width = 0, f_height = 0, f_refresh = 0; 738 unsigned int f_width = 0, f_height = 0, f_refresh = 0;
741 unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */ 739 unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */
742 bool scanning = false, preferred_bad = false; 740 bool scanning = false, preferred_bad = false;
741 bool use_edid_mode = false;
743 u8 edid[128]; 742 u8 edid[128];
744 char *forced; 743 char *forced;
745 int i; 744 int i;
@@ -854,12 +853,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
854 } 853 }
855 854
856 /* Check if supported: sufficient fb memory, supported clock-rate */ 855 /* Check if supported: sufficient fb memory, supported clock-rate */
857 fb_videomode_to_var(var, mode); 856 if (ch && ch->notify &&
858 857 ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_MODE, mode,
859 var->bits_per_pixel = info->var.bits_per_pixel; 858 NULL)) {
860
861 if (info && info->fbops->fb_check_var &&
862 info->fbops->fb_check_var(var, info)) {
863 scanning = true; 859 scanning = true;
864 preferred_bad = true; 860 preferred_bad = true;
865 continue; 861 continue;
@@ -867,28 +863,19 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
867 863
868 found = mode; 864 found = mode;
869 found_rate_error = rate_error; 865 found_rate_error = rate_error;
866 use_edid_mode = true;
870 } 867 }
871 868
872 hdmi->var.width = hdmi->monspec.max_x * 10;
873 hdmi->var.height = hdmi->monspec.max_y * 10;
874
875 /* 869 /*
876 * TODO 1: if no ->info is present, postpone running the config until 870 * TODO 1: if no default mode is present, postpone running the config
877 * after ->info first gets registered. 871 * until after the LCDC channel is initialized.
878 * TODO 2: consider registering the HDMI platform device from the LCDC 872 * TODO 2: consider registering the HDMI platform device from the LCDC
879 * driver, and passing ->info with HDMI platform data. 873 * driver.
880 */ 874 */
881 if (info && !found) { 875 if (!found && hdmi->entity.def_mode.xres != 0) {
882 modelist = info->modelist.next && 876 found = &hdmi->entity.def_mode;
883 !list_empty(&info->modelist) ? 877 found_rate_error = sh_hdmi_rate_error(hdmi, found, hdmi_rate,
884 list_entry(info->modelist.next, 878 parent_rate);
885 struct fb_modelist, list) :
886 NULL;
887
888 if (modelist) {
889 found = &modelist->mode;
890 found_rate_error = sh_hdmi_rate_error(hdmi, found, hdmi_rate, parent_rate);
891 }
892 } 879 }
893 880
894 /* No cookie today */ 881 /* No cookie today */
@@ -912,12 +899,13 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
912 else 899 else
913 hdmi->preprogrammed_vic = 0; 900 hdmi->preprogrammed_vic = 0;
914 901
915 dev_dbg(hdmi->dev, "Using %s %s mode %ux%u@%uHz (%luHz), clock error %luHz\n", 902 dev_dbg(hdmi->dev, "Using %s %s mode %ux%u@%uHz (%luHz), "
916 modelist ? "default" : "EDID", hdmi->preprogrammed_vic ? "VIC" : "external", 903 "clock error %luHz\n", use_edid_mode ? "EDID" : "default",
917 found->xres, found->yres, found->refresh, 904 hdmi->preprogrammed_vic ? "VIC" : "external", found->xres,
918 PICOS2KHZ(found->pixclock) * 1000, found_rate_error); 905 found->yres, found->refresh, PICOS2KHZ(found->pixclock) * 1000,
906 found_rate_error);
919 907
920 fb_videomode_to_var(&hdmi->var, found); 908 hdmi->mode = *found;
921 sh_hdmi_external_video_param(hdmi); 909 sh_hdmi_external_video_param(hdmi);
922 910
923 return 0; 911 return 0;
@@ -998,22 +986,12 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
998 return IRQ_HANDLED; 986 return IRQ_HANDLED;
999} 987}
1000 988
1001/* locking: called with info->lock held, or before register_framebuffer() */ 989static int sh_hdmi_display_on(struct sh_mobile_lcdc_entity *entity)
1002static void sh_hdmi_display_on(void *arg, struct fb_info *info)
1003{ 990{
1004 /* 991 struct sh_hdmi *hdmi = entity_to_sh_hdmi(entity);
1005 * info is guaranteed to be valid, when we are called, because our
1006 * FB_EVENT_FB_UNBIND notify is also called with info->lock held
1007 */
1008 struct sh_hdmi *hdmi = arg;
1009 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
1010 struct sh_mobile_lcdc_chan *ch = info->par;
1011 992
1012 dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__, 993 dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__, hdmi,
1013 pdata->lcd_dev, info->state); 994 hdmi->hp_state);
1014
1015 /* No need to lock */
1016 hdmi->info = info;
1017 995
1018 /* 996 /*
1019 * hp_state can be set to 997 * hp_state can be set to
@@ -1021,56 +999,30 @@ static void sh_hdmi_display_on(void *arg, struct fb_info *info)
1021 * HDMI_HOTPLUG_CONNECTED: on monitor plug-in 999 * HDMI_HOTPLUG_CONNECTED: on monitor plug-in
1022 * HDMI_HOTPLUG_EDID_DONE: on EDID read completion 1000 * HDMI_HOTPLUG_EDID_DONE: on EDID read completion
1023 */ 1001 */
1024 switch (hdmi->hp_state) { 1002 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
1025 case HDMI_HOTPLUG_EDID_DONE:
1026 /* PS mode d->e. All functions are active */ 1003 /* PS mode d->e. All functions are active */
1027 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL); 1004 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL);
1028 dev_dbg(hdmi->dev, "HDMI running\n"); 1005 dev_dbg(hdmi->dev, "HDMI running\n");
1029 break;
1030 case HDMI_HOTPLUG_DISCONNECTED:
1031 info->state = FBINFO_STATE_SUSPENDED;
1032 default:
1033 hdmi->var = ch->display_var;
1034 } 1006 }
1007
1008 return hdmi->hp_state == HDMI_HOTPLUG_DISCONNECTED
1009 ? SH_MOBILE_LCDC_DISPLAY_DISCONNECTED
1010 : SH_MOBILE_LCDC_DISPLAY_CONNECTED;
1035} 1011}
1036 1012
1037/* locking: called with info->lock held */ 1013static void sh_hdmi_display_off(struct sh_mobile_lcdc_entity *entity)
1038static void sh_hdmi_display_off(void *arg)
1039{ 1014{
1040 struct sh_hdmi *hdmi = arg; 1015 struct sh_hdmi *hdmi = entity_to_sh_hdmi(entity);
1041 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
1042 1016
1043 dev_dbg(hdmi->dev, "%s(%p)\n", __func__, pdata->lcd_dev); 1017 dev_dbg(hdmi->dev, "%s(%p)\n", __func__, hdmi);
1044 /* PS mode e->a */ 1018 /* PS mode e->a */
1045 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL); 1019 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL);
1046} 1020}
1047 1021
1048static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi) 1022static const struct sh_mobile_lcdc_entity_ops sh_hdmi_ops = {
1049{ 1023 .display_on = sh_hdmi_display_on,
1050 struct fb_info *info = hdmi->info; 1024 .display_off = sh_hdmi_display_off,
1051 struct sh_mobile_lcdc_chan *ch = info->par; 1025};
1052 struct fb_var_screeninfo *new_var = &hdmi->var, *old_var = &ch->display_var;
1053 struct fb_videomode mode1, mode2;
1054
1055 fb_var_to_videomode(&mode1, old_var);
1056 fb_var_to_videomode(&mode2, new_var);
1057
1058 dev_dbg(info->dev, "Old %ux%u, new %ux%u\n",
1059 mode1.xres, mode1.yres, mode2.xres, mode2.yres);
1060
1061 if (fb_mode_is_equal(&mode1, &mode2)) {
1062 /* It can be a different monitor with an equal video-mode */
1063 old_var->width = new_var->width;
1064 old_var->height = new_var->height;
1065 return false;
1066 }
1067
1068 dev_dbg(info->dev, "Switching %u -> %u lines\n",
1069 mode1.yres, mode2.yres);
1070 *old_var = *new_var;
1071
1072 return true;
1073}
1074 1026
1075/** 1027/**
1076 * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock 1028 * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock
@@ -1111,20 +1063,11 @@ static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate,
1111static void sh_hdmi_edid_work_fn(struct work_struct *work) 1063static void sh_hdmi_edid_work_fn(struct work_struct *work)
1112{ 1064{
1113 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); 1065 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
1114 struct fb_info *info; 1066 struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc;
1115 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
1116 struct sh_mobile_lcdc_chan *ch;
1117 int ret; 1067 int ret;
1118 1068
1119 dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__, 1069 dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__, hdmi,
1120 pdata->lcd_dev, hdmi->hp_state); 1070 hdmi->hp_state);
1121
1122 if (!pdata->lcd_dev)
1123 return;
1124
1125 mutex_lock(&hdmi->mutex);
1126
1127 info = hdmi->info;
1128 1071
1129 if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) { 1072 if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
1130 unsigned long parent_rate = 0, hdmi_rate; 1073 unsigned long parent_rate = 0, hdmi_rate;
@@ -1145,103 +1088,32 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
1145 /* Switched to another (d) power-save mode */ 1088 /* Switched to another (d) power-save mode */
1146 msleep(10); 1089 msleep(10);
1147 1090
1148 if (!info) 1091 if (ch && ch->notify)
1149 goto out; 1092 ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT,
1150 1093 &hdmi->mode, &hdmi->monspec);
1151 ch = info->par;
1152
1153 if (lock_fb_info(info)) {
1154 console_lock();
1155
1156 /* HDMI plug in */
1157 if (!sh_hdmi_must_reconfigure(hdmi) &&
1158 info->state == FBINFO_STATE_RUNNING) {
1159 /*
1160 * First activation with the default monitor - just turn
1161 * on, if we run a resume here, the logo disappears
1162 */
1163 info->var.width = hdmi->var.width;
1164 info->var.height = hdmi->var.height;
1165 sh_hdmi_display_on(hdmi, info);
1166 } else {
1167 /* New monitor or have to wake up */
1168 fb_set_suspend(info, 0);
1169 }
1170
1171 console_unlock();
1172 unlock_fb_info(info);
1173 }
1174 } else { 1094 } else {
1175 ret = 0;
1176 if (!info)
1177 goto out;
1178
1179 hdmi->monspec.modedb_len = 0; 1095 hdmi->monspec.modedb_len = 0;
1180 fb_destroy_modedb(hdmi->monspec.modedb); 1096 fb_destroy_modedb(hdmi->monspec.modedb);
1181 hdmi->monspec.modedb = NULL; 1097 hdmi->monspec.modedb = NULL;
1182 1098
1183 if (lock_fb_info(info)) { 1099 if (ch && ch->notify)
1184 console_lock(); 1100 ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT,
1101 NULL, NULL);
1185 1102
1186 /* HDMI disconnect */ 1103 ret = 0;
1187 fb_set_suspend(info, 1);
1188
1189 console_unlock();
1190 unlock_fb_info(info);
1191 }
1192 } 1104 }
1193 1105
1194out: 1106out:
1195 if (ret < 0 && ret != -EAGAIN) 1107 if (ret < 0 && ret != -EAGAIN)
1196 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED; 1108 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
1197 mutex_unlock(&hdmi->mutex);
1198 1109
1199 dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, pdata->lcd_dev); 1110 dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, hdmi);
1200}
1201
1202static int sh_hdmi_notify(struct notifier_block *nb,
1203 unsigned long action, void *data)
1204{
1205 struct fb_event *event = data;
1206 struct fb_info *info = event->info;
1207 struct sh_mobile_lcdc_chan *ch = info->par;
1208 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
1209 struct sh_hdmi *hdmi = board_cfg->board_data;
1210
1211 if (!hdmi || nb != &hdmi->notifier || hdmi->info != info)
1212 return NOTIFY_DONE;
1213
1214 switch(action) {
1215 case FB_EVENT_FB_REGISTERED:
1216 /* Unneeded, activation taken care by sh_hdmi_display_on() */
1217 break;
1218 case FB_EVENT_FB_UNREGISTERED:
1219 /*
1220 * We are called from unregister_framebuffer() with the
1221 * info->lock held. This is bad for us, because we can race with
1222 * the scheduled work, which has to call fb_set_suspend(), which
1223 * takes info->lock internally, so, sh_hdmi_edid_work_fn()
1224 * cannot take and hold info->lock for the whole function
1225 * duration. Using an additional lock creates a classical AB-BA
1226 * lock up. Therefore, we have to release the info->lock
1227 * temporarily, synchronise with the work queue and re-acquire
1228 * the info->lock.
1229 */
1230 unlock_fb_info(info);
1231 mutex_lock(&hdmi->mutex);
1232 hdmi->info = NULL;
1233 mutex_unlock(&hdmi->mutex);
1234 lock_fb_info(info);
1235 return NOTIFY_OK;
1236 }
1237 return NOTIFY_DONE;
1238} 1111}
1239 1112
1240static int __init sh_hdmi_probe(struct platform_device *pdev) 1113static int __init sh_hdmi_probe(struct platform_device *pdev)
1241{ 1114{
1242 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1115 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
1243 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1116 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1244 struct sh_mobile_lcdc_board_cfg *board_cfg;
1245 int irq = platform_get_irq(pdev, 0), ret; 1117 int irq = platform_get_irq(pdev, 0), ret;
1246 struct sh_hdmi *hdmi; 1118 struct sh_hdmi *hdmi;
1247 long rate; 1119 long rate;
@@ -1255,9 +1127,9 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1255 return -ENOMEM; 1127 return -ENOMEM;
1256 } 1128 }
1257 1129
1258 mutex_init(&hdmi->mutex);
1259
1260 hdmi->dev = &pdev->dev; 1130 hdmi->dev = &pdev->dev;
1131 hdmi->entity.owner = THIS_MODULE;
1132 hdmi->entity.ops = &sh_hdmi_ops;
1261 1133
1262 hdmi->hdmi_clk = clk_get(&pdev->dev, "ick"); 1134 hdmi->hdmi_clk = clk_get(&pdev->dev, "ick");
1263 if (IS_ERR(hdmi->hdmi_clk)) { 1135 if (IS_ERR(hdmi->hdmi_clk)) {
@@ -1297,14 +1169,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1297 goto emap; 1169 goto emap;
1298 } 1170 }
1299 1171
1300 platform_set_drvdata(pdev, hdmi); 1172 platform_set_drvdata(pdev, &hdmi->entity);
1301
1302 /* Set up LCDC callbacks */
1303 board_cfg = &pdata->lcd_chan->board_cfg;
1304 board_cfg->owner = THIS_MODULE;
1305 board_cfg->board_data = hdmi;
1306 board_cfg->display_on = sh_hdmi_display_on;
1307 board_cfg->display_off = sh_hdmi_display_off;
1308 1173
1309 INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn); 1174 INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn);
1310 1175
@@ -1329,9 +1194,6 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1329 goto ecodec; 1194 goto ecodec;
1330 } 1195 }
1331 1196
1332 hdmi->notifier.notifier_call = sh_hdmi_notify;
1333 fb_register_client(&hdmi->notifier);
1334
1335 return 0; 1197 return 0;
1336 1198
1337ecodec: 1199ecodec:
@@ -1347,7 +1209,6 @@ ereqreg:
1347erate: 1209erate:
1348 clk_put(hdmi->hdmi_clk); 1210 clk_put(hdmi->hdmi_clk);
1349egetclk: 1211egetclk:
1350 mutex_destroy(&hdmi->mutex);
1351 kfree(hdmi); 1212 kfree(hdmi);
1352 1213
1353 return ret; 1214 return ret;
@@ -1355,21 +1216,12 @@ egetclk:
1355 1216
1356static int __exit sh_hdmi_remove(struct platform_device *pdev) 1217static int __exit sh_hdmi_remove(struct platform_device *pdev)
1357{ 1218{
1358 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1219 struct sh_hdmi *hdmi = entity_to_sh_hdmi(platform_get_drvdata(pdev));
1359 struct sh_hdmi *hdmi = platform_get_drvdata(pdev);
1360 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1220 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1361 struct sh_mobile_lcdc_board_cfg *board_cfg = &pdata->lcd_chan->board_cfg;
1362 int irq = platform_get_irq(pdev, 0); 1221 int irq = platform_get_irq(pdev, 0);
1363 1222
1364 snd_soc_unregister_codec(&pdev->dev); 1223 snd_soc_unregister_codec(&pdev->dev);
1365 1224
1366 fb_unregister_client(&hdmi->notifier);
1367
1368 board_cfg->display_on = NULL;
1369 board_cfg->display_off = NULL;
1370 board_cfg->board_data = NULL;
1371 board_cfg->owner = NULL;
1372
1373 /* No new work will be scheduled, wait for running ISR */ 1225 /* No new work will be scheduled, wait for running ISR */
1374 free_irq(irq, hdmi); 1226 free_irq(irq, hdmi);
1375 /* Wait for already scheduled work */ 1227 /* Wait for already scheduled work */
@@ -1380,7 +1232,6 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
1380 clk_put(hdmi->hdmi_clk); 1232 clk_put(hdmi->hdmi_clk);
1381 iounmap(hdmi->base); 1233 iounmap(hdmi->base);
1382 release_mem_region(res->start, resource_size(res)); 1234 release_mem_region(res->start, resource_size(res));
1383 mutex_destroy(&hdmi->mutex);
1384 kfree(hdmi); 1235 kfree(hdmi);
1385 1236
1386 return 0; 1237 return 0;
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index aac5b369d73c..7a0b301587f6 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -8,26 +8,27 @@
8 * for more details. 8 * for more details.
9 */ 9 */
10 10
11#include <linux/kernel.h> 11#include <linux/atomic.h>
12#include <linux/init.h> 12#include <linux/backlight.h>
13#include <linux/delay.h>
14#include <linux/mm.h>
15#include <linux/clk.h> 13#include <linux/clk.h>
16#include <linux/pm_runtime.h> 14#include <linux/console.h>
17#include <linux/platform_device.h>
18#include <linux/dma-mapping.h> 15#include <linux/dma-mapping.h>
16#include <linux/delay.h>
17#include <linux/gpio.h>
18#include <linux/init.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/videodev2.h>
21#include <linux/vmalloc.h>
22#include <linux/ioctl.h> 20#include <linux/ioctl.h>
23#include <linux/slab.h> 21#include <linux/kernel.h>
24#include <linux/console.h> 22#include <linux/mm.h>
25#include <linux/backlight.h>
26#include <linux/gpio.h>
27#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/pm_runtime.h>
26#include <linux/slab.h>
27#include <linux/videodev2.h>
28#include <linux/vmalloc.h>
29
28#include <video/sh_mobile_lcdc.h> 30#include <video/sh_mobile_lcdc.h>
29#include <video/sh_mobile_meram.h> 31#include <video/sh_mobile_meram.h>
30#include <linux/atomic.h>
31 32
32#include "sh_mobile_lcdcfb.h" 33#include "sh_mobile_lcdcfb.h"
33 34
@@ -37,6 +38,24 @@
37#define MAX_XRES 1920 38#define MAX_XRES 1920
38#define MAX_YRES 1080 39#define MAX_YRES 1080
39 40
41struct sh_mobile_lcdc_priv {
42 void __iomem *base;
43 int irq;
44 atomic_t hw_usecnt;
45 struct device *dev;
46 struct clk *dot_clk;
47 unsigned long lddckr;
48 struct sh_mobile_lcdc_chan ch[2];
49 struct notifier_block notifier;
50 int started;
51 int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
52 struct sh_mobile_meram_info *meram_dev;
53};
54
55/* -----------------------------------------------------------------------------
56 * Registers access
57 */
58
40static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { 59static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
41 [LDDCKPAT1R] = 0x400, 60 [LDDCKPAT1R] = 0x400,
42 [LDDCKPAT2R] = 0x404, 61 [LDDCKPAT2R] = 0x404,
@@ -75,38 +94,6 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
75 [LDPMR] = 0x63c, 94 [LDPMR] = 0x63c,
76}; 95};
77 96
78static const struct fb_videomode default_720p = {
79 .name = "HDMI 720p",
80 .xres = 1280,
81 .yres = 720,
82
83 .left_margin = 220,
84 .right_margin = 110,
85 .hsync_len = 40,
86
87 .upper_margin = 20,
88 .lower_margin = 5,
89 .vsync_len = 5,
90
91 .pixclock = 13468,
92 .refresh = 60,
93 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
94};
95
96struct sh_mobile_lcdc_priv {
97 void __iomem *base;
98 int irq;
99 atomic_t hw_usecnt;
100 struct device *dev;
101 struct clk *dot_clk;
102 unsigned long lddckr;
103 struct sh_mobile_lcdc_chan ch[2];
104 struct notifier_block notifier;
105 int started;
106 int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
107 struct sh_mobile_meram_info *meram_dev;
108};
109
110static bool banked(int reg_nr) 97static bool banked(int reg_nr)
111{ 98{
112 switch (reg_nr) { 99 switch (reg_nr) {
@@ -127,6 +114,11 @@ static bool banked(int reg_nr)
127 return false; 114 return false;
128} 115}
129 116
117static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
118{
119 return chan->cfg->chan == LCDC_CHAN_SUBLCD;
120}
121
130static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan, 122static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
131 int reg_nr, unsigned long data) 123 int reg_nr, unsigned long data)
132{ 124{
@@ -169,11 +161,72 @@ static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv,
169 cpu_relax(); 161 cpu_relax();
170} 162}
171 163
172static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan) 164/* -----------------------------------------------------------------------------
165 * Clock management
166 */
167
168static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
169{
170 if (atomic_inc_and_test(&priv->hw_usecnt)) {
171 if (priv->dot_clk)
172 clk_enable(priv->dot_clk);
173 pm_runtime_get_sync(priv->dev);
174 if (priv->meram_dev && priv->meram_dev->pdev)
175 pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
176 }
177}
178
179static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
173{ 180{
174 return chan->cfg.chan == LCDC_CHAN_SUBLCD; 181 if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
182 if (priv->meram_dev && priv->meram_dev->pdev)
183 pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
184 pm_runtime_put(priv->dev);
185 if (priv->dot_clk)
186 clk_disable(priv->dot_clk);
187 }
175} 188}
176 189
190static int sh_mobile_lcdc_setup_clocks(struct sh_mobile_lcdc_priv *priv,
191 int clock_source)
192{
193 struct clk *clk;
194 char *str;
195
196 switch (clock_source) {
197 case LCDC_CLK_BUS:
198 str = "bus_clk";
199 priv->lddckr = LDDCKR_ICKSEL_BUS;
200 break;
201 case LCDC_CLK_PERIPHERAL:
202 str = "peripheral_clk";
203 priv->lddckr = LDDCKR_ICKSEL_MIPI;
204 break;
205 case LCDC_CLK_EXTERNAL:
206 str = NULL;
207 priv->lddckr = LDDCKR_ICKSEL_HDMI;
208 break;
209 default:
210 return -EINVAL;
211 }
212
213 if (str == NULL)
214 return 0;
215
216 clk = clk_get(priv->dev, str);
217 if (IS_ERR(clk)) {
218 dev_err(priv->dev, "cannot get dot clock %s\n", str);
219 return PTR_ERR(clk);
220 }
221
222 priv->dot_clk = clk;
223 return 0;
224}
225
226/* -----------------------------------------------------------------------------
227 * Display, panel and deferred I/O
228 */
229
177static void lcdc_sys_write_index(void *handle, unsigned long data) 230static void lcdc_sys_write_index(void *handle, unsigned long data)
178{ 231{
179 struct sh_mobile_lcdc_chan *ch = handle; 232 struct sh_mobile_lcdc_chan *ch = handle;
@@ -216,74 +269,11 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
216 lcdc_sys_read_data, 269 lcdc_sys_read_data,
217}; 270};
218 271
219static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
220{
221 if (var->grayscale > 1)
222 return var->grayscale;
223
224 switch (var->bits_per_pixel) {
225 case 16:
226 return V4L2_PIX_FMT_RGB565;
227 case 24:
228 return V4L2_PIX_FMT_BGR24;
229 case 32:
230 return V4L2_PIX_FMT_BGR32;
231 default:
232 return 0;
233 }
234}
235
236static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
237{
238 return var->grayscale > 1;
239}
240
241static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var)
242{
243 if (var->grayscale <= 1)
244 return false;
245
246 switch (var->grayscale) {
247 case V4L2_PIX_FMT_NV12:
248 case V4L2_PIX_FMT_NV21:
249 case V4L2_PIX_FMT_NV16:
250 case V4L2_PIX_FMT_NV61:
251 case V4L2_PIX_FMT_NV24:
252 case V4L2_PIX_FMT_NV42:
253 return true;
254
255 default:
256 return false;
257 }
258}
259
260static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
261{
262 if (atomic_inc_and_test(&priv->hw_usecnt)) {
263 if (priv->dot_clk)
264 clk_enable(priv->dot_clk);
265 pm_runtime_get_sync(priv->dev);
266 if (priv->meram_dev && priv->meram_dev->pdev)
267 pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
268 }
269}
270
271static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
272{
273 if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
274 if (priv->meram_dev && priv->meram_dev->pdev)
275 pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
276 pm_runtime_put(priv->dev);
277 if (priv->dot_clk)
278 clk_disable(priv->dot_clk);
279 }
280}
281
282static int sh_mobile_lcdc_sginit(struct fb_info *info, 272static int sh_mobile_lcdc_sginit(struct fb_info *info,
283 struct list_head *pagelist) 273 struct list_head *pagelist)
284{ 274{
285 struct sh_mobile_lcdc_chan *ch = info->par; 275 struct sh_mobile_lcdc_chan *ch = info->par;
286 unsigned int nr_pages_max = info->fix.smem_len >> PAGE_SHIFT; 276 unsigned int nr_pages_max = ch->fb_size >> PAGE_SHIFT;
287 struct page *page; 277 struct page *page;
288 int nr_pages = 0; 278 int nr_pages = 0;
289 279
@@ -299,7 +289,7 @@ static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
299 struct list_head *pagelist) 289 struct list_head *pagelist)
300{ 290{
301 struct sh_mobile_lcdc_chan *ch = info->par; 291 struct sh_mobile_lcdc_chan *ch = info->par;
302 struct sh_mobile_lcdc_board_cfg *bcfg = &ch->cfg.board_cfg; 292 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
303 293
304 /* enable clocks before accessing hardware */ 294 /* enable clocks before accessing hardware */
305 sh_mobile_lcdc_clk_on(ch->lcdc); 295 sh_mobile_lcdc_clk_on(ch->lcdc);
@@ -323,16 +313,15 @@ static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
323 unsigned int nr_pages = sh_mobile_lcdc_sginit(info, pagelist); 313 unsigned int nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
324 314
325 /* trigger panel update */ 315 /* trigger panel update */
326 dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); 316 dma_map_sg(ch->lcdc->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
327 if (bcfg->start_transfer) 317 if (panel->start_transfer)
328 bcfg->start_transfer(bcfg->board_data, ch, 318 panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops);
329 &sh_mobile_lcdc_sys_bus_ops);
330 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG); 319 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
331 dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); 320 dma_unmap_sg(ch->lcdc->dev, ch->sglist, nr_pages,
321 DMA_TO_DEVICE);
332 } else { 322 } else {
333 if (bcfg->start_transfer) 323 if (panel->start_transfer)
334 bcfg->start_transfer(bcfg->board_data, ch, 324 panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops);
335 &sh_mobile_lcdc_sys_bus_ops);
336 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG); 325 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
337 } 326 }
338} 327}
@@ -345,6 +334,217 @@ static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
345 schedule_delayed_work(&info->deferred_work, fbdefio->delay); 334 schedule_delayed_work(&info->deferred_work, fbdefio->delay);
346} 335}
347 336
337static void sh_mobile_lcdc_display_on(struct sh_mobile_lcdc_chan *ch)
338{
339 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
340
341 if (ch->tx_dev) {
342 int ret;
343
344 ret = ch->tx_dev->ops->display_on(ch->tx_dev);
345 if (ret < 0)
346 return;
347
348 if (ret == SH_MOBILE_LCDC_DISPLAY_DISCONNECTED)
349 ch->info->state = FBINFO_STATE_SUSPENDED;
350 }
351
352 /* HDMI must be enabled before LCDC configuration */
353 if (panel->display_on)
354 panel->display_on();
355}
356
357static void sh_mobile_lcdc_display_off(struct sh_mobile_lcdc_chan *ch)
358{
359 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
360
361 if (panel->display_off)
362 panel->display_off();
363
364 if (ch->tx_dev)
365 ch->tx_dev->ops->display_off(ch->tx_dev);
366}
367
368static bool
369sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch,
370 const struct fb_videomode *new_mode)
371{
372 dev_dbg(ch->info->dev, "Old %ux%u, new %ux%u\n",
373 ch->display.mode.xres, ch->display.mode.yres,
374 new_mode->xres, new_mode->yres);
375
376 /* It can be a different monitor with an equal video-mode */
377 if (fb_mode_is_equal(&ch->display.mode, new_mode))
378 return false;
379
380 dev_dbg(ch->info->dev, "Switching %u -> %u lines\n",
381 ch->display.mode.yres, new_mode->yres);
382 ch->display.mode = *new_mode;
383
384 return true;
385}
386
387static int sh_mobile_check_var(struct fb_var_screeninfo *var,
388 struct fb_info *info);
389
390static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
391 enum sh_mobile_lcdc_entity_event event,
392 const struct fb_videomode *mode,
393 const struct fb_monspecs *monspec)
394{
395 struct fb_info *info = ch->info;
396 struct fb_var_screeninfo var;
397 int ret = 0;
398
399 switch (event) {
400 case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT:
401 /* HDMI plug in */
402 if (lock_fb_info(info)) {
403 console_lock();
404
405 ch->display.width = monspec->max_x * 10;
406 ch->display.height = monspec->max_y * 10;
407
408 if (!sh_mobile_lcdc_must_reconfigure(ch, mode) &&
409 info->state == FBINFO_STATE_RUNNING) {
410 /* First activation with the default monitor.
411 * Just turn on, if we run a resume here, the
412 * logo disappears.
413 */
414 info->var.width = monspec->max_x * 10;
415 info->var.height = monspec->max_y * 10;
416 sh_mobile_lcdc_display_on(ch);
417 } else {
418 /* New monitor or have to wake up */
419 fb_set_suspend(info, 0);
420 }
421
422 console_unlock();
423 unlock_fb_info(info);
424 }
425 break;
426
427 case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT:
428 /* HDMI disconnect */
429 if (lock_fb_info(info)) {
430 console_lock();
431 fb_set_suspend(info, 1);
432 console_unlock();
433 unlock_fb_info(info);
434 }
435 break;
436
437 case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
438 /* Validate a proposed new mode */
439 fb_videomode_to_var(&var, mode);
440 var.bits_per_pixel = info->var.bits_per_pixel;
441 var.grayscale = info->var.grayscale;
442 ret = sh_mobile_check_var(&var, info);
443 break;
444 }
445
446 return ret;
447}
448
449/* -----------------------------------------------------------------------------
450 * Format helpers
451 */
452
453struct sh_mobile_lcdc_format_info {
454 u32 fourcc;
455 unsigned int bpp;
456 bool yuv;
457 u32 lddfr;
458};
459
460static const struct sh_mobile_lcdc_format_info sh_mobile_format_infos[] = {
461 {
462 .fourcc = V4L2_PIX_FMT_RGB565,
463 .bpp = 16,
464 .yuv = false,
465 .lddfr = LDDFR_PKF_RGB16,
466 }, {
467 .fourcc = V4L2_PIX_FMT_BGR24,
468 .bpp = 24,
469 .yuv = false,
470 .lddfr = LDDFR_PKF_RGB24,
471 }, {
472 .fourcc = V4L2_PIX_FMT_BGR32,
473 .bpp = 32,
474 .yuv = false,
475 .lddfr = LDDFR_PKF_ARGB32,
476 }, {
477 .fourcc = V4L2_PIX_FMT_NV12,
478 .bpp = 12,
479 .yuv = true,
480 .lddfr = LDDFR_CC | LDDFR_YF_420,
481 }, {
482 .fourcc = V4L2_PIX_FMT_NV21,
483 .bpp = 12,
484 .yuv = true,
485 .lddfr = LDDFR_CC | LDDFR_YF_420,
486 }, {
487 .fourcc = V4L2_PIX_FMT_NV16,
488 .bpp = 16,
489 .yuv = true,
490 .lddfr = LDDFR_CC | LDDFR_YF_422,
491 }, {
492 .fourcc = V4L2_PIX_FMT_NV61,
493 .bpp = 16,
494 .yuv = true,
495 .lddfr = LDDFR_CC | LDDFR_YF_422,
496 }, {
497 .fourcc = V4L2_PIX_FMT_NV24,
498 .bpp = 24,
499 .yuv = true,
500 .lddfr = LDDFR_CC | LDDFR_YF_444,
501 }, {
502 .fourcc = V4L2_PIX_FMT_NV42,
503 .bpp = 24,
504 .yuv = true,
505 .lddfr = LDDFR_CC | LDDFR_YF_444,
506 },
507};
508
509static const struct sh_mobile_lcdc_format_info *
510sh_mobile_format_info(u32 fourcc)
511{
512 unsigned int i;
513
514 for (i = 0; i < ARRAY_SIZE(sh_mobile_format_infos); ++i) {
515 if (sh_mobile_format_infos[i].fourcc == fourcc)
516 return &sh_mobile_format_infos[i];
517 }
518
519 return NULL;
520}
521
522static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
523{
524 if (var->grayscale > 1)
525 return var->grayscale;
526
527 switch (var->bits_per_pixel) {
528 case 16:
529 return V4L2_PIX_FMT_RGB565;
530 case 24:
531 return V4L2_PIX_FMT_BGR24;
532 case 32:
533 return V4L2_PIX_FMT_BGR32;
534 default:
535 return 0;
536 }
537}
538
539static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
540{
541 return var->grayscale > 1;
542}
543
544/* -----------------------------------------------------------------------------
545 * Start, stop and IRQ
546 */
547
348static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) 548static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
349{ 549{
350 struct sh_mobile_lcdc_priv *priv = data; 550 struct sh_mobile_lcdc_priv *priv = data;
@@ -385,6 +585,26 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
385 return IRQ_HANDLED; 585 return IRQ_HANDLED;
386} 586}
387 587
588static int sh_mobile_wait_for_vsync(struct sh_mobile_lcdc_chan *ch)
589{
590 unsigned long ldintr;
591 int ret;
592
593 /* Enable VSync End interrupt and be careful not to acknowledge any
594 * pending interrupt.
595 */
596 ldintr = lcdc_read(ch->lcdc, _LDINTR);
597 ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK;
598 lcdc_write(ch->lcdc, _LDINTR, ldintr);
599
600 ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
601 msecs_to_jiffies(100));
602 if (!ret)
603 return -ETIMEDOUT;
604
605 return 0;
606}
607
388static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv, 608static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
389 int start) 609 int start)
390{ 610{
@@ -416,53 +636,52 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
416 636
417static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) 637static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
418{ 638{
419 struct fb_var_screeninfo *var = &ch->info->var, *display_var = &ch->display_var; 639 const struct fb_var_screeninfo *var = &ch->info->var;
640 const struct fb_videomode *mode = &ch->display.mode;
420 unsigned long h_total, hsync_pos, display_h_total; 641 unsigned long h_total, hsync_pos, display_h_total;
421 u32 tmp; 642 u32 tmp;
422 643
423 tmp = ch->ldmt1r_value; 644 tmp = ch->ldmt1r_value;
424 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL; 645 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL;
425 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL; 646 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL;
426 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0; 647 tmp |= (ch->cfg->flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0;
427 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0; 648 tmp |= (ch->cfg->flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0;
428 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0; 649 tmp |= (ch->cfg->flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0;
429 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0; 650 tmp |= (ch->cfg->flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0;
430 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0; 651 tmp |= (ch->cfg->flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0;
431 lcdc_write_chan(ch, LDMT1R, tmp); 652 lcdc_write_chan(ch, LDMT1R, tmp);
432 653
433 /* setup SYS bus */ 654 /* setup SYS bus */
434 lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r); 655 lcdc_write_chan(ch, LDMT2R, ch->cfg->sys_bus_cfg.ldmt2r);
435 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r); 656 lcdc_write_chan(ch, LDMT3R, ch->cfg->sys_bus_cfg.ldmt3r);
436 657
437 /* horizontal configuration */ 658 /* horizontal configuration */
438 h_total = display_var->xres + display_var->hsync_len + 659 h_total = mode->xres + mode->hsync_len + mode->left_margin
439 display_var->left_margin + display_var->right_margin; 660 + mode->right_margin;
440 tmp = h_total / 8; /* HTCN */ 661 tmp = h_total / 8; /* HTCN */
441 tmp |= (min(display_var->xres, var->xres) / 8) << 16; /* HDCN */ 662 tmp |= (min(mode->xres, ch->xres) / 8) << 16; /* HDCN */
442 lcdc_write_chan(ch, LDHCNR, tmp); 663 lcdc_write_chan(ch, LDHCNR, tmp);
443 664
444 hsync_pos = display_var->xres + display_var->right_margin; 665 hsync_pos = mode->xres + mode->right_margin;
445 tmp = hsync_pos / 8; /* HSYNP */ 666 tmp = hsync_pos / 8; /* HSYNP */
446 tmp |= (display_var->hsync_len / 8) << 16; /* HSYNW */ 667 tmp |= (mode->hsync_len / 8) << 16; /* HSYNW */
447 lcdc_write_chan(ch, LDHSYNR, tmp); 668 lcdc_write_chan(ch, LDHSYNR, tmp);
448 669
449 /* vertical configuration */ 670 /* vertical configuration */
450 tmp = display_var->yres + display_var->vsync_len + 671 tmp = mode->yres + mode->vsync_len + mode->upper_margin
451 display_var->upper_margin + display_var->lower_margin; /* VTLN */ 672 + mode->lower_margin; /* VTLN */
452 tmp |= min(display_var->yres, var->yres) << 16; /* VDLN */ 673 tmp |= min(mode->yres, ch->yres) << 16; /* VDLN */
453 lcdc_write_chan(ch, LDVLNR, tmp); 674 lcdc_write_chan(ch, LDVLNR, tmp);
454 675
455 tmp = display_var->yres + display_var->lower_margin; /* VSYNP */ 676 tmp = mode->yres + mode->lower_margin; /* VSYNP */
456 tmp |= display_var->vsync_len << 16; /* VSYNW */ 677 tmp |= mode->vsync_len << 16; /* VSYNW */
457 lcdc_write_chan(ch, LDVSYNR, tmp); 678 lcdc_write_chan(ch, LDVSYNR, tmp);
458 679
459 /* Adjust horizontal synchronisation for HDMI */ 680 /* Adjust horizontal synchronisation for HDMI */
460 display_h_total = display_var->xres + display_var->hsync_len + 681 display_h_total = mode->xres + mode->hsync_len + mode->left_margin
461 display_var->left_margin + display_var->right_margin; 682 + mode->right_margin;
462 tmp = ((display_var->xres & 7) << 24) | 683 tmp = ((mode->xres & 7) << 24) | ((display_h_total & 7) << 16)
463 ((display_h_total & 7) << 16) | 684 | ((mode->hsync_len & 7) << 8) | (hsync_pos & 7);
464 ((display_var->hsync_len & 7) << 8) |
465 (hsync_pos & 7);
466 lcdc_write_chan(ch, LDHAJR, tmp); 685 lcdc_write_chan(ch, LDHAJR, tmp);
467} 686}
468 687
@@ -498,7 +717,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
498 /* Power supply */ 717 /* Power supply */
499 lcdc_write_chan(ch, LDPMR, 0); 718 lcdc_write_chan(ch, LDPMR, 0);
500 719
501 m = ch->cfg.clock_divider; 720 m = ch->cfg->clock_divider;
502 if (!m) 721 if (!m)
503 continue; 722 continue;
504 723
@@ -525,32 +744,10 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
525 744
526 sh_mobile_lcdc_geometry(ch); 745 sh_mobile_lcdc_geometry(ch);
527 746
528 switch (sh_mobile_format_fourcc(&ch->info->var)) { 747 tmp = ch->format->lddfr;
529 case V4L2_PIX_FMT_RGB565:
530 tmp = LDDFR_PKF_RGB16;
531 break;
532 case V4L2_PIX_FMT_BGR24:
533 tmp = LDDFR_PKF_RGB24;
534 break;
535 case V4L2_PIX_FMT_BGR32:
536 tmp = LDDFR_PKF_ARGB32;
537 break;
538 case V4L2_PIX_FMT_NV12:
539 case V4L2_PIX_FMT_NV21:
540 tmp = LDDFR_CC | LDDFR_YF_420;
541 break;
542 case V4L2_PIX_FMT_NV16:
543 case V4L2_PIX_FMT_NV61:
544 tmp = LDDFR_CC | LDDFR_YF_422;
545 break;
546 case V4L2_PIX_FMT_NV24:
547 case V4L2_PIX_FMT_NV42:
548 tmp = LDDFR_CC | LDDFR_YF_444;
549 break;
550 }
551 748
552 if (sh_mobile_format_is_yuv(&ch->info->var)) { 749 if (ch->format->yuv) {
553 switch (ch->info->var.colorspace) { 750 switch (ch->colorspace) {
554 case V4L2_COLORSPACE_REC709: 751 case V4L2_COLORSPACE_REC709:
555 tmp |= LDDFR_CF1; 752 tmp |= LDDFR_CF1;
556 break; 753 break;
@@ -563,7 +760,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
563 lcdc_write_chan(ch, LDDFR, tmp); 760 lcdc_write_chan(ch, LDDFR, tmp);
564 lcdc_write_chan(ch, LDMLSR, ch->pitch); 761 lcdc_write_chan(ch, LDMLSR, ch->pitch);
565 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y); 762 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
566 if (sh_mobile_format_is_yuv(&ch->info->var)) 763 if (ch->format->yuv)
567 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c); 764 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
568 765
569 /* When using deferred I/O mode, configure the LCDC for one-shot 766 /* When using deferred I/O mode, configure the LCDC for one-shot
@@ -571,7 +768,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
571 * continuous read mode. 768 * continuous read mode.
572 */ 769 */
573 if (ch->ldmt1r_value & LDMT1R_IFM && 770 if (ch->ldmt1r_value & LDMT1R_IFM &&
574 ch->cfg.sys_bus_cfg.deferred_io_msec) { 771 ch->cfg->sys_bus_cfg.deferred_io_msec) {
575 lcdc_write_chan(ch, LDSM1R, LDSM1R_OS); 772 lcdc_write_chan(ch, LDSM1R, LDSM1R_OS);
576 lcdc_write(priv, _LDINTR, LDINTR_FE); 773 lcdc_write(priv, _LDINTR, LDINTR_FE);
577 } else { 774 } else {
@@ -580,7 +777,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
580 } 777 }
581 778
582 /* Word and long word swap. */ 779 /* Word and long word swap. */
583 switch (sh_mobile_format_fourcc(&priv->ch[0].info->var)) { 780 switch (priv->ch[0].format->fourcc) {
584 case V4L2_PIX_FMT_RGB565: 781 case V4L2_PIX_FMT_RGB565:
585 case V4L2_PIX_FMT_NV21: 782 case V4L2_PIX_FMT_NV21:
586 case V4L2_PIX_FMT_NV61: 783 case V4L2_PIX_FMT_NV61:
@@ -609,7 +806,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
609static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 806static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
610{ 807{
611 struct sh_mobile_meram_info *mdev = priv->meram_dev; 808 struct sh_mobile_meram_info *mdev = priv->meram_dev;
612 struct sh_mobile_lcdc_board_cfg *board_cfg;
613 struct sh_mobile_lcdc_chan *ch; 809 struct sh_mobile_lcdc_chan *ch;
614 unsigned long tmp; 810 unsigned long tmp;
615 int ret; 811 int ret;
@@ -626,15 +822,15 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
626 lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0); 822 lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0);
627 823
628 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 824 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
629 ch = &priv->ch[k]; 825 const struct sh_mobile_lcdc_panel_cfg *panel;
630 826
827 ch = &priv->ch[k];
631 if (!ch->enabled) 828 if (!ch->enabled)
632 continue; 829 continue;
633 830
634 board_cfg = &ch->cfg.board_cfg; 831 panel = &ch->cfg->panel_cfg;
635 if (board_cfg->setup_sys) { 832 if (panel->setup_sys) {
636 ret = board_cfg->setup_sys(board_cfg->board_data, ch, 833 ret = panel->setup_sys(ch, &sh_mobile_lcdc_sys_bus_ops);
637 &sh_mobile_lcdc_sys_bus_ops);
638 if (ret) 834 if (ret)
639 return ret; 835 return ret;
640 } 836 }
@@ -642,33 +838,30 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
642 838
643 /* Compute frame buffer base address and pitch for each channel. */ 839 /* Compute frame buffer base address and pitch for each channel. */
644 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 840 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
645 struct sh_mobile_meram_cfg *cfg;
646 int pixelformat; 841 int pixelformat;
842 void *meram;
647 843
648 ch = &priv->ch[k]; 844 ch = &priv->ch[k];
649 if (!ch->enabled) 845 if (!ch->enabled)
650 continue; 846 continue;
651 847
652 ch->base_addr_y = ch->info->fix.smem_start; 848 ch->base_addr_y = ch->dma_handle;
653 ch->base_addr_c = ch->base_addr_y 849 ch->base_addr_c = ch->base_addr_y + ch->xres * ch->yres_virtual;
654 + ch->info->var.xres
655 * ch->info->var.yres_virtual;
656 ch->pitch = ch->info->fix.line_length;
657 850
658 /* Enable MERAM if possible. */ 851 /* Enable MERAM if possible. */
659 cfg = ch->cfg.meram_cfg; 852 if (mdev == NULL || mdev->ops == NULL ||
660 if (mdev == NULL || mdev->ops == NULL || cfg == NULL) 853 ch->cfg->meram_cfg == NULL)
661 continue; 854 continue;
662 855
663 /* we need to de-init configured ICBs before we can 856 /* we need to de-init configured ICBs before we can
664 * re-initialize them. 857 * re-initialize them.
665 */ 858 */
666 if (ch->meram_enabled) { 859 if (ch->meram) {
667 mdev->ops->meram_unregister(mdev, cfg); 860 mdev->ops->meram_unregister(mdev, ch->meram);
668 ch->meram_enabled = 0; 861 ch->meram = NULL;
669 } 862 }
670 863
671 switch (sh_mobile_format_fourcc(&ch->info->var)) { 864 switch (ch->format->fourcc) {
672 case V4L2_PIX_FMT_NV12: 865 case V4L2_PIX_FMT_NV12:
673 case V4L2_PIX_FMT_NV21: 866 case V4L2_PIX_FMT_NV21:
674 case V4L2_PIX_FMT_NV16: 867 case V4L2_PIX_FMT_NV16:
@@ -687,13 +880,15 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
687 break; 880 break;
688 } 881 }
689 882
690 ret = mdev->ops->meram_register(mdev, cfg, ch->pitch, 883 meram = mdev->ops->meram_register(mdev, ch->cfg->meram_cfg,
691 ch->info->var.yres, pixelformat, 884 ch->pitch, ch->yres, pixelformat,
692 ch->base_addr_y, ch->base_addr_c,
693 &ch->base_addr_y, &ch->base_addr_c,
694 &ch->pitch); 885 &ch->pitch);
695 if (!ret) 886 if (!IS_ERR(meram)) {
696 ch->meram_enabled = 1; 887 mdev->ops->meram_update(mdev, meram,
888 ch->base_addr_y, ch->base_addr_c,
889 &ch->base_addr_y, &ch->base_addr_c);
890 ch->meram = meram;
891 }
697 } 892 }
698 893
699 /* Start the LCDC. */ 894 /* Start the LCDC. */
@@ -707,7 +902,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
707 if (!ch->enabled) 902 if (!ch->enabled)
708 continue; 903 continue;
709 904
710 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; 905 tmp = ch->cfg->sys_bus_cfg.deferred_io_msec;
711 if (ch->ldmt1r_value & LDMT1R_IFM && tmp) { 906 if (ch->ldmt1r_value & LDMT1R_IFM && tmp) {
712 ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; 907 ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
713 ch->defio.delay = msecs_to_jiffies(tmp); 908 ch->defio.delay = msecs_to_jiffies(tmp);
@@ -715,11 +910,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
715 fb_deferred_io_init(ch->info); 910 fb_deferred_io_init(ch->info);
716 } 911 }
717 912
718 board_cfg = &ch->cfg.board_cfg; 913 sh_mobile_lcdc_display_on(ch);
719 if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
720 board_cfg->display_on(board_cfg->board_data, ch->info);
721 module_put(board_cfg->owner);
722 }
723 914
724 if (ch->bl) { 915 if (ch->bl) {
725 ch->bl->props.power = FB_BLANK_UNBLANK; 916 ch->bl->props.power = FB_BLANK_UNBLANK;
@@ -733,7 +924,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
733static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) 924static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
734{ 925{
735 struct sh_mobile_lcdc_chan *ch; 926 struct sh_mobile_lcdc_chan *ch;
736 struct sh_mobile_lcdc_board_cfg *board_cfg;
737 int k; 927 int k;
738 928
739 /* clean up deferred io and ask board code to disable panel */ 929 /* clean up deferred io and ask board code to disable panel */
@@ -760,20 +950,14 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
760 backlight_update_status(ch->bl); 950 backlight_update_status(ch->bl);
761 } 951 }
762 952
763 board_cfg = &ch->cfg.board_cfg; 953 sh_mobile_lcdc_display_off(ch);
764 if (board_cfg->display_off && try_module_get(board_cfg->owner)) {
765 board_cfg->display_off(board_cfg->board_data);
766 module_put(board_cfg->owner);
767 }
768 954
769 /* disable the meram */ 955 /* disable the meram */
770 if (ch->meram_enabled) { 956 if (ch->meram) {
771 struct sh_mobile_meram_cfg *cfg;
772 struct sh_mobile_meram_info *mdev; 957 struct sh_mobile_meram_info *mdev;
773 cfg = ch->cfg.meram_cfg;
774 mdev = priv->meram_dev; 958 mdev = priv->meram_dev;
775 mdev->ops->meram_unregister(mdev, cfg); 959 mdev->ops->meram_unregister(mdev, ch->meram);
776 ch->meram_enabled = 0; 960 ch->meram = 0;
777 } 961 }
778 962
779 } 963 }
@@ -790,86 +974,9 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
790 sh_mobile_lcdc_clk_off(priv); 974 sh_mobile_lcdc_clk_off(priv);
791} 975}
792 976
793static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch) 977/* -----------------------------------------------------------------------------
794{ 978 * Frame buffer operations
795 int interface_type = ch->cfg.interface_type; 979 */
796
797 switch (interface_type) {
798 case RGB8:
799 case RGB9:
800 case RGB12A:
801 case RGB12B:
802 case RGB16:
803 case RGB18:
804 case RGB24:
805 case SYS8A:
806 case SYS8B:
807 case SYS8C:
808 case SYS8D:
809 case SYS9:
810 case SYS12:
811 case SYS16A:
812 case SYS16B:
813 case SYS16C:
814 case SYS18:
815 case SYS24:
816 break;
817 default:
818 return -EINVAL;
819 }
820
821 /* SUBLCD only supports SYS interface */
822 if (lcdc_chan_is_sublcd(ch)) {
823 if (!(interface_type & LDMT1R_IFM))
824 return -EINVAL;
825
826 interface_type &= ~LDMT1R_IFM;
827 }
828
829 ch->ldmt1r_value = interface_type;
830 return 0;
831}
832
833static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
834 int clock_source,
835 struct sh_mobile_lcdc_priv *priv)
836{
837 char *str;
838
839 switch (clock_source) {
840 case LCDC_CLK_BUS:
841 str = "bus_clk";
842 priv->lddckr = LDDCKR_ICKSEL_BUS;
843 break;
844 case LCDC_CLK_PERIPHERAL:
845 str = "peripheral_clk";
846 priv->lddckr = LDDCKR_ICKSEL_MIPI;
847 break;
848 case LCDC_CLK_EXTERNAL:
849 str = NULL;
850 priv->lddckr = LDDCKR_ICKSEL_HDMI;
851 break;
852 default:
853 return -EINVAL;
854 }
855
856 if (str) {
857 priv->dot_clk = clk_get(&pdev->dev, str);
858 if (IS_ERR(priv->dot_clk)) {
859 dev_err(&pdev->dev, "cannot get dot clock %s\n", str);
860 return PTR_ERR(priv->dot_clk);
861 }
862 }
863
864 /* Runtime PM support involves two step for this driver:
865 * 1) Enable Runtime PM
866 * 2) Force Runtime PM Resume since hardware is accessed from probe()
867 */
868 priv->dev = &pdev->dev;
869 pm_runtime_enable(priv->dev);
870 pm_runtime_resume(priv->dev);
871 return 0;
872}
873 980
874static int sh_mobile_lcdc_setcolreg(u_int regno, 981static int sh_mobile_lcdc_setcolreg(u_int regno,
875 u_int red, u_int green, u_int blue, 982 u_int red, u_int green, u_int blue,
@@ -936,14 +1043,12 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
936 unsigned long new_pan_offset; 1043 unsigned long new_pan_offset;
937 unsigned long base_addr_y, base_addr_c; 1044 unsigned long base_addr_y, base_addr_c;
938 unsigned long c_offset; 1045 unsigned long c_offset;
939 bool yuv = sh_mobile_format_is_yuv(&info->var);
940 1046
941 if (!yuv) 1047 if (!ch->format->yuv)
942 new_pan_offset = var->yoffset * info->fix.line_length 1048 new_pan_offset = var->yoffset * ch->pitch
943 + var->xoffset * (info->var.bits_per_pixel / 8); 1049 + var->xoffset * (ch->format->bpp / 8);
944 else 1050 else
945 new_pan_offset = var->yoffset * info->fix.line_length 1051 new_pan_offset = var->yoffset * ch->pitch + var->xoffset;
946 + var->xoffset;
947 1052
948 if (new_pan_offset == ch->pan_offset) 1053 if (new_pan_offset == ch->pan_offset)
949 return 0; /* No change, do nothing */ 1054 return 0; /* No change, do nothing */
@@ -952,39 +1057,33 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
952 1057
953 /* Set the source address for the next refresh */ 1058 /* Set the source address for the next refresh */
954 base_addr_y = ch->dma_handle + new_pan_offset; 1059 base_addr_y = ch->dma_handle + new_pan_offset;
955 if (yuv) { 1060 if (ch->format->yuv) {
956 /* Set y offset */ 1061 /* Set y offset */
957 c_offset = var->yoffset * info->fix.line_length 1062 c_offset = var->yoffset * ch->pitch
958 * (info->var.bits_per_pixel - 8) / 8; 1063 * (ch->format->bpp - 8) / 8;
959 base_addr_c = ch->dma_handle 1064 base_addr_c = ch->dma_handle + ch->xres * ch->yres_virtual
960 + info->var.xres * info->var.yres_virtual
961 + c_offset; 1065 + c_offset;
962 /* Set x offset */ 1066 /* Set x offset */
963 if (sh_mobile_format_fourcc(&info->var) == V4L2_PIX_FMT_NV24) 1067 if (ch->format->fourcc == V4L2_PIX_FMT_NV24)
964 base_addr_c += 2 * var->xoffset; 1068 base_addr_c += 2 * var->xoffset;
965 else 1069 else
966 base_addr_c += var->xoffset; 1070 base_addr_c += var->xoffset;
967 } 1071 }
968 1072
969 if (ch->meram_enabled) { 1073 if (ch->meram) {
970 struct sh_mobile_meram_cfg *cfg;
971 struct sh_mobile_meram_info *mdev; 1074 struct sh_mobile_meram_info *mdev;
972 int ret;
973 1075
974 cfg = ch->cfg.meram_cfg;
975 mdev = priv->meram_dev; 1076 mdev = priv->meram_dev;
976 ret = mdev->ops->meram_update(mdev, cfg, 1077 mdev->ops->meram_update(mdev, ch->meram,
977 base_addr_y, base_addr_c, 1078 base_addr_y, base_addr_c,
978 &base_addr_y, &base_addr_c); 1079 &base_addr_y, &base_addr_c);
979 if (ret)
980 return ret;
981 } 1080 }
982 1081
983 ch->base_addr_y = base_addr_y; 1082 ch->base_addr_y = base_addr_y;
984 ch->base_addr_c = base_addr_c; 1083 ch->base_addr_c = base_addr_c;
985 1084
986 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); 1085 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
987 if (yuv) 1086 if (ch->format->yuv)
988 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); 1087 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
989 1088
990 if (lcdc_chan_is_sublcd(ch)) 1089 if (lcdc_chan_is_sublcd(ch))
@@ -999,27 +1098,6 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
999 return 0; 1098 return 0;
1000} 1099}
1001 1100
1002static int sh_mobile_wait_for_vsync(struct fb_info *info)
1003{
1004 struct sh_mobile_lcdc_chan *ch = info->par;
1005 unsigned long ldintr;
1006 int ret;
1007
1008 /* Enable VSync End interrupt and be careful not to acknowledge any
1009 * pending interrupt.
1010 */
1011 ldintr = lcdc_read(ch->lcdc, _LDINTR);
1012 ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK;
1013 lcdc_write(ch->lcdc, _LDINTR, ldintr);
1014
1015 ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
1016 msecs_to_jiffies(100));
1017 if (!ret)
1018 return -ETIMEDOUT;
1019
1020 return 0;
1021}
1022
1023static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd, 1101static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
1024 unsigned long arg) 1102 unsigned long arg)
1025{ 1103{
@@ -1027,7 +1105,7 @@ static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
1027 1105
1028 switch (cmd) { 1106 switch (cmd) {
1029 case FBIO_WAITFORVSYNC: 1107 case FBIO_WAITFORVSYNC:
1030 retval = sh_mobile_wait_for_vsync(info); 1108 retval = sh_mobile_wait_for_vsync(info->par);
1031 break; 1109 break;
1032 1110
1033 default: 1111 default:
@@ -1040,7 +1118,8 @@ static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
1040static void sh_mobile_fb_reconfig(struct fb_info *info) 1118static void sh_mobile_fb_reconfig(struct fb_info *info)
1041{ 1119{
1042 struct sh_mobile_lcdc_chan *ch = info->par; 1120 struct sh_mobile_lcdc_chan *ch = info->par;
1043 struct fb_videomode mode1, mode2; 1121 struct fb_var_screeninfo var;
1122 struct fb_videomode mode;
1044 struct fb_event event; 1123 struct fb_event event;
1045 int evnt = FB_EVENT_MODE_CHANGE_ALL; 1124 int evnt = FB_EVENT_MODE_CHANGE_ALL;
1046 1125
@@ -1048,14 +1127,19 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
1048 /* More framebuffer users are active */ 1127 /* More framebuffer users are active */
1049 return; 1128 return;
1050 1129
1051 fb_var_to_videomode(&mode1, &ch->display_var); 1130 fb_var_to_videomode(&mode, &info->var);
1052 fb_var_to_videomode(&mode2, &info->var);
1053 1131
1054 if (fb_mode_is_equal(&mode1, &mode2)) 1132 if (fb_mode_is_equal(&ch->display.mode, &mode))
1055 return; 1133 return;
1056 1134
1057 /* Display has been re-plugged, framebuffer is free now, reconfigure */ 1135 /* Display has been re-plugged, framebuffer is free now, reconfigure */
1058 if (fb_set_var(info, &ch->display_var) < 0) 1136 var = info->var;
1137 fb_videomode_to_var(&var, &ch->display.mode);
1138 var.width = ch->display.width;
1139 var.height = ch->display.height;
1140 var.activate = FB_ACTIVATE_NOW;
1141
1142 if (fb_set_var(info, &var) < 0)
1059 /* Couldn't reconfigure, hopefully, can continue as before */ 1143 /* Couldn't reconfigure, hopefully, can continue as before */
1060 return; 1144 return;
1061 1145
@@ -1065,7 +1149,7 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
1065 * user event, we have to call the chain ourselves. 1149 * user event, we have to call the chain ourselves.
1066 */ 1150 */
1067 event.info = info; 1151 event.info = info;
1068 event.data = &mode1; 1152 event.data = &ch->display.mode;
1069 fb_notifier_call_chain(evnt, &event); 1153 fb_notifier_call_chain(evnt, &event);
1070} 1154}
1071 1155
@@ -1124,8 +1208,8 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
1124 * distance between two modes is defined as the size of the 1208 * distance between two modes is defined as the size of the
1125 * non-overlapping parts of the two rectangles. 1209 * non-overlapping parts of the two rectangles.
1126 */ 1210 */
1127 for (i = 0; i < ch->cfg.num_cfg; ++i) { 1211 for (i = 0; i < ch->cfg->num_modes; ++i) {
1128 const struct fb_videomode *mode = &ch->cfg.lcd_cfg[i]; 1212 const struct fb_videomode *mode = &ch->cfg->lcd_modes[i];
1129 unsigned int dist; 1213 unsigned int dist;
1130 1214
1131 /* We can only round up. */ 1215 /* We can only round up. */
@@ -1144,7 +1228,7 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
1144 } 1228 }
1145 1229
1146 /* If no available mode can be used, return an error. */ 1230 /* If no available mode can be used, return an error. */
1147 if (ch->cfg.num_cfg != 0) { 1231 if (ch->cfg->num_modes != 0) {
1148 if (best_dist == (unsigned int)-1) 1232 if (best_dist == (unsigned int)-1)
1149 return -EINVAL; 1233 return -EINVAL;
1150 1234
@@ -1161,32 +1245,17 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
1161 var->yres_virtual = var->yres; 1245 var->yres_virtual = var->yres;
1162 1246
1163 if (sh_mobile_format_is_fourcc(var)) { 1247 if (sh_mobile_format_is_fourcc(var)) {
1164 switch (var->grayscale) { 1248 const struct sh_mobile_lcdc_format_info *format;
1165 case V4L2_PIX_FMT_NV12: 1249
1166 case V4L2_PIX_FMT_NV21: 1250 format = sh_mobile_format_info(var->grayscale);
1167 var->bits_per_pixel = 12; 1251 if (format == NULL)
1168 break;
1169 case V4L2_PIX_FMT_RGB565:
1170 case V4L2_PIX_FMT_NV16:
1171 case V4L2_PIX_FMT_NV61:
1172 var->bits_per_pixel = 16;
1173 break;
1174 case V4L2_PIX_FMT_BGR24:
1175 case V4L2_PIX_FMT_NV24:
1176 case V4L2_PIX_FMT_NV42:
1177 var->bits_per_pixel = 24;
1178 break;
1179 case V4L2_PIX_FMT_BGR32:
1180 var->bits_per_pixel = 32;
1181 break;
1182 default:
1183 return -EINVAL; 1252 return -EINVAL;
1184 } 1253 var->bits_per_pixel = format->bpp;
1185 1254
1186 /* Default to RGB and JPEG color-spaces for RGB and YUV formats 1255 /* Default to RGB and JPEG color-spaces for RGB and YUV formats
1187 * respectively. 1256 * respectively.
1188 */ 1257 */
1189 if (!sh_mobile_format_is_yuv(var)) 1258 if (!format->yuv)
1190 var->colorspace = V4L2_COLORSPACE_SRGB; 1259 var->colorspace = V4L2_COLORSPACE_SRGB;
1191 else if (var->colorspace != V4L2_COLORSPACE_REC709) 1260 else if (var->colorspace != V4L2_COLORSPACE_REC709)
1192 var->colorspace = V4L2_COLORSPACE_JPEG; 1261 var->colorspace = V4L2_COLORSPACE_JPEG;
@@ -1246,22 +1315,28 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
1246static int sh_mobile_set_par(struct fb_info *info) 1315static int sh_mobile_set_par(struct fb_info *info)
1247{ 1316{
1248 struct sh_mobile_lcdc_chan *ch = info->par; 1317 struct sh_mobile_lcdc_chan *ch = info->par;
1249 u32 line_length = info->fix.line_length;
1250 int ret; 1318 int ret;
1251 1319
1252 sh_mobile_lcdc_stop(ch->lcdc); 1320 sh_mobile_lcdc_stop(ch->lcdc);
1253 1321
1254 if (sh_mobile_format_is_yuv(&info->var)) 1322 ch->format = sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
1255 info->fix.line_length = info->var.xres; 1323 ch->colorspace = info->var.colorspace;
1324
1325 ch->xres = info->var.xres;
1326 ch->xres_virtual = info->var.xres_virtual;
1327 ch->yres = info->var.yres;
1328 ch->yres_virtual = info->var.yres_virtual;
1329
1330 if (ch->format->yuv)
1331 ch->pitch = info->var.xres;
1256 else 1332 else
1257 info->fix.line_length = info->var.xres 1333 ch->pitch = info->var.xres * ch->format->bpp / 8;
1258 * info->var.bits_per_pixel / 8;
1259 1334
1260 ret = sh_mobile_lcdc_start(ch->lcdc); 1335 ret = sh_mobile_lcdc_start(ch->lcdc);
1261 if (ret < 0) { 1336 if (ret < 0)
1262 dev_err(info->dev, "%s: unable to restart LCDC\n", __func__); 1337 dev_err(info->dev, "%s: unable to restart LCDC\n", __func__);
1263 info->fix.line_length = line_length; 1338
1264 } 1339 info->fix.line_length = ch->pitch;
1265 1340
1266 if (sh_mobile_format_is_fourcc(&info->var)) { 1341 if (sh_mobile_format_is_fourcc(&info->var)) {
1267 info->fix.type = FB_TYPE_FOURCC; 1342 info->fix.type = FB_TYPE_FOURCC;
@@ -1290,8 +1365,8 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
1290 /* blank the screen? */ 1365 /* blank the screen? */
1291 if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) { 1366 if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) {
1292 struct fb_fillrect rect = { 1367 struct fb_fillrect rect = {
1293 .width = info->var.xres, 1368 .width = ch->xres,
1294 .height = info->var.yres, 1369 .height = ch->yres,
1295 }; 1370 };
1296 sh_mobile_lcdc_fillrect(info, &rect); 1371 sh_mobile_lcdc_fillrect(info, &rect);
1297 } 1372 }
@@ -1307,8 +1382,8 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
1307 * mode will reenable the clocks and update the screen in time, 1382 * mode will reenable the clocks and update the screen in time,
1308 * so it does not need this. */ 1383 * so it does not need this. */
1309 if (!info->fbdefio) { 1384 if (!info->fbdefio) {
1310 sh_mobile_wait_for_vsync(info); 1385 sh_mobile_wait_for_vsync(ch);
1311 sh_mobile_wait_for_vsync(info); 1386 sh_mobile_wait_for_vsync(ch);
1312 } 1387 }
1313 sh_mobile_lcdc_clk_off(p); 1388 sh_mobile_lcdc_clk_off(p);
1314 } 1389 }
@@ -1334,25 +1409,161 @@ static struct fb_ops sh_mobile_lcdc_ops = {
1334 .fb_set_par = sh_mobile_set_par, 1409 .fb_set_par = sh_mobile_set_par,
1335}; 1410};
1336 1411
1412static void
1413sh_mobile_lcdc_channel_fb_unregister(struct sh_mobile_lcdc_chan *ch)
1414{
1415 if (ch->info && ch->info->dev)
1416 unregister_framebuffer(ch->info);
1417}
1418
1419static int __devinit
1420sh_mobile_lcdc_channel_fb_register(struct sh_mobile_lcdc_chan *ch)
1421{
1422 struct fb_info *info = ch->info;
1423 int ret;
1424
1425 if (info->fbdefio) {
1426 ch->sglist = vmalloc(sizeof(struct scatterlist) *
1427 ch->fb_size >> PAGE_SHIFT);
1428 if (!ch->sglist) {
1429 dev_err(ch->lcdc->dev, "cannot allocate sglist\n");
1430 return -ENOMEM;
1431 }
1432 }
1433
1434 info->bl_dev = ch->bl;
1435
1436 ret = register_framebuffer(info);
1437 if (ret < 0)
1438 return ret;
1439
1440 dev_info(ch->lcdc->dev, "registered %s/%s as %dx%d %dbpp.\n",
1441 dev_name(ch->lcdc->dev), (ch->cfg->chan == LCDC_CHAN_MAINLCD) ?
1442 "mainlcd" : "sublcd", info->var.xres, info->var.yres,
1443 info->var.bits_per_pixel);
1444
1445 /* deferred io mode: disable clock to save power */
1446 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
1447 sh_mobile_lcdc_clk_off(ch->lcdc);
1448
1449 return ret;
1450}
1451
1452static void
1453sh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch)
1454{
1455 struct fb_info *info = ch->info;
1456
1457 if (!info || !info->device)
1458 return;
1459
1460 if (ch->sglist)
1461 vfree(ch->sglist);
1462
1463 fb_dealloc_cmap(&info->cmap);
1464 framebuffer_release(info);
1465}
1466
1467static int __devinit
1468sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
1469 const struct fb_videomode *mode,
1470 unsigned int num_modes)
1471{
1472 struct sh_mobile_lcdc_priv *priv = ch->lcdc;
1473 struct fb_var_screeninfo *var;
1474 struct fb_info *info;
1475 int ret;
1476
1477 /* Allocate and initialize the frame buffer device. Create the modes
1478 * list and allocate the color map.
1479 */
1480 info = framebuffer_alloc(0, priv->dev);
1481 if (info == NULL) {
1482 dev_err(priv->dev, "unable to allocate fb_info\n");
1483 return -ENOMEM;
1484 }
1485
1486 ch->info = info;
1487
1488 info->flags = FBINFO_FLAG_DEFAULT;
1489 info->fbops = &sh_mobile_lcdc_ops;
1490 info->device = priv->dev;
1491 info->screen_base = ch->fb_mem;
1492 info->pseudo_palette = &ch->pseudo_palette;
1493 info->par = ch;
1494
1495 fb_videomode_to_modelist(mode, num_modes, &info->modelist);
1496
1497 ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
1498 if (ret < 0) {
1499 dev_err(priv->dev, "unable to allocate cmap\n");
1500 return ret;
1501 }
1502
1503 /* Initialize fixed screen information. Restrict pan to 2 lines steps
1504 * for NV12 and NV21.
1505 */
1506 info->fix = sh_mobile_lcdc_fix;
1507 info->fix.smem_start = ch->dma_handle;
1508 info->fix.smem_len = ch->fb_size;
1509 info->fix.line_length = ch->pitch;
1510
1511 if (ch->format->yuv)
1512 info->fix.visual = FB_VISUAL_FOURCC;
1513 else
1514 info->fix.visual = FB_VISUAL_TRUECOLOR;
1515
1516 if (ch->format->fourcc == V4L2_PIX_FMT_NV12 ||
1517 ch->format->fourcc == V4L2_PIX_FMT_NV21)
1518 info->fix.ypanstep = 2;
1519
1520 /* Initialize variable screen information using the first mode as
1521 * default. The default Y virtual resolution is twice the panel size to
1522 * allow for double-buffering.
1523 */
1524 var = &info->var;
1525 fb_videomode_to_var(var, mode);
1526 var->width = ch->cfg->panel_cfg.width;
1527 var->height = ch->cfg->panel_cfg.height;
1528 var->yres_virtual = var->yres * 2;
1529 var->activate = FB_ACTIVATE_NOW;
1530
1531 /* Use the legacy API by default for RGB formats, and the FOURCC API
1532 * for YUV formats.
1533 */
1534 if (!ch->format->yuv)
1535 var->bits_per_pixel = ch->format->bpp;
1536 else
1537 var->grayscale = ch->format->fourcc;
1538
1539 ret = sh_mobile_check_var(var, info);
1540 if (ret)
1541 return ret;
1542
1543 return 0;
1544}
1545
1546/* -----------------------------------------------------------------------------
1547 * Backlight
1548 */
1549
1337static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev) 1550static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
1338{ 1551{
1339 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev); 1552 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
1340 struct sh_mobile_lcdc_board_cfg *cfg = &ch->cfg.board_cfg;
1341 int brightness = bdev->props.brightness; 1553 int brightness = bdev->props.brightness;
1342 1554
1343 if (bdev->props.power != FB_BLANK_UNBLANK || 1555 if (bdev->props.power != FB_BLANK_UNBLANK ||
1344 bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) 1556 bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
1345 brightness = 0; 1557 brightness = 0;
1346 1558
1347 return cfg->set_brightness(cfg->board_data, brightness); 1559 return ch->cfg->bl_info.set_brightness(brightness);
1348} 1560}
1349 1561
1350static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev) 1562static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev)
1351{ 1563{
1352 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev); 1564 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
1353 struct sh_mobile_lcdc_board_cfg *cfg = &ch->cfg.board_cfg;
1354 1565
1355 return cfg->get_brightness(cfg->board_data); 1566 return ch->cfg->bl_info.get_brightness();
1356} 1567}
1357 1568
1358static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev, 1569static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev,
@@ -1373,7 +1584,7 @@ static struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent,
1373{ 1584{
1374 struct backlight_device *bl; 1585 struct backlight_device *bl;
1375 1586
1376 bl = backlight_device_register(ch->cfg.bl_info.name, parent, ch, 1587 bl = backlight_device_register(ch->cfg->bl_info.name, parent, ch,
1377 &sh_mobile_lcdc_bl_ops, NULL); 1588 &sh_mobile_lcdc_bl_ops, NULL);
1378 if (IS_ERR(bl)) { 1589 if (IS_ERR(bl)) {
1379 dev_err(parent, "unable to register backlight device: %ld\n", 1590 dev_err(parent, "unable to register backlight device: %ld\n",
@@ -1381,7 +1592,7 @@ static struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent,
1381 return NULL; 1592 return NULL;
1382 } 1593 }
1383 1594
1384 bl->props.max_brightness = ch->cfg.bl_info.max_brightness; 1595 bl->props.max_brightness = ch->cfg->bl_info.max_brightness;
1385 bl->props.brightness = bl->props.max_brightness; 1596 bl->props.brightness = bl->props.max_brightness;
1386 backlight_update_status(bl); 1597 backlight_update_status(bl);
1387 1598
@@ -1393,6 +1604,10 @@ static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev)
1393 backlight_device_unregister(bdev); 1604 backlight_device_unregister(bdev);
1394} 1605}
1395 1606
1607/* -----------------------------------------------------------------------------
1608 * Power management
1609 */
1610
1396static int sh_mobile_lcdc_suspend(struct device *dev) 1611static int sh_mobile_lcdc_suspend(struct device *dev)
1397{ 1612{
1398 struct platform_device *pdev = to_platform_device(dev); 1613 struct platform_device *pdev = to_platform_device(dev);
@@ -1436,6 +1651,10 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
1436 .runtime_resume = sh_mobile_lcdc_runtime_resume, 1651 .runtime_resume = sh_mobile_lcdc_runtime_resume,
1437}; 1652};
1438 1653
1654/* -----------------------------------------------------------------------------
1655 * Framebuffer notifier
1656 */
1657
1439/* locking: called with info->lock held */ 1658/* locking: called with info->lock held */
1440static int sh_mobile_lcdc_notify(struct notifier_block *nb, 1659static int sh_mobile_lcdc_notify(struct notifier_block *nb,
1441 unsigned long action, void *data) 1660 unsigned long action, void *data)
@@ -1443,7 +1662,6 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
1443 struct fb_event *event = data; 1662 struct fb_event *event = data;
1444 struct fb_info *info = event->info; 1663 struct fb_info *info = event->info;
1445 struct sh_mobile_lcdc_chan *ch = info->par; 1664 struct sh_mobile_lcdc_chan *ch = info->par;
1446 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
1447 1665
1448 if (&ch->lcdc->notifier != nb) 1666 if (&ch->lcdc->notifier != nb)
1449 return NOTIFY_DONE; 1667 return NOTIFY_DONE;
@@ -1453,10 +1671,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
1453 1671
1454 switch(action) { 1672 switch(action) {
1455 case FB_EVENT_SUSPEND: 1673 case FB_EVENT_SUSPEND:
1456 if (board_cfg->display_off && try_module_get(board_cfg->owner)) { 1674 sh_mobile_lcdc_display_off(ch);
1457 board_cfg->display_off(board_cfg->board_data);
1458 module_put(board_cfg->owner);
1459 }
1460 sh_mobile_lcdc_stop(ch->lcdc); 1675 sh_mobile_lcdc_stop(ch->lcdc);
1461 break; 1676 break;
1462 case FB_EVENT_RESUME: 1677 case FB_EVENT_RESUME:
@@ -1464,47 +1679,60 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
1464 sh_mobile_fb_reconfig(info); 1679 sh_mobile_fb_reconfig(info);
1465 mutex_unlock(&ch->open_lock); 1680 mutex_unlock(&ch->open_lock);
1466 1681
1467 /* HDMI must be enabled before LCDC configuration */ 1682 sh_mobile_lcdc_display_on(ch);
1468 if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
1469 board_cfg->display_on(board_cfg->board_data, info);
1470 module_put(board_cfg->owner);
1471 }
1472
1473 sh_mobile_lcdc_start(ch->lcdc); 1683 sh_mobile_lcdc_start(ch->lcdc);
1474 } 1684 }
1475 1685
1476 return NOTIFY_OK; 1686 return NOTIFY_OK;
1477} 1687}
1478 1688
1689/* -----------------------------------------------------------------------------
1690 * Probe/remove and driver init/exit
1691 */
1692
1693static const struct fb_videomode default_720p __devinitconst = {
1694 .name = "HDMI 720p",
1695 .xres = 1280,
1696 .yres = 720,
1697
1698 .left_margin = 220,
1699 .right_margin = 110,
1700 .hsync_len = 40,
1701
1702 .upper_margin = 20,
1703 .lower_margin = 5,
1704 .vsync_len = 5,
1705
1706 .pixclock = 13468,
1707 .refresh = 60,
1708 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
1709};
1710
1479static int sh_mobile_lcdc_remove(struct platform_device *pdev) 1711static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1480{ 1712{
1481 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); 1713 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
1482 struct fb_info *info;
1483 int i; 1714 int i;
1484 1715
1485 fb_unregister_client(&priv->notifier); 1716 fb_unregister_client(&priv->notifier);
1486 1717
1487 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) 1718 for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
1488 if (priv->ch[i].info && priv->ch[i].info->dev) 1719 sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]);
1489 unregister_framebuffer(priv->ch[i].info);
1490 1720
1491 sh_mobile_lcdc_stop(priv); 1721 sh_mobile_lcdc_stop(priv);
1492 1722
1493 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { 1723 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
1494 info = priv->ch[i].info; 1724 struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
1495 1725
1496 if (!info || !info->device) 1726 if (ch->tx_dev) {
1497 continue; 1727 ch->tx_dev->lcdc = NULL;
1728 module_put(ch->cfg->tx_dev->dev.driver->owner);
1729 }
1498 1730
1499 if (priv->ch[i].sglist) 1731 sh_mobile_lcdc_channel_fb_cleanup(ch);
1500 vfree(priv->ch[i].sglist);
1501 1732
1502 if (info->screen_base) 1733 if (ch->fb_mem)
1503 dma_free_coherent(&pdev->dev, info->fix.smem_len, 1734 dma_free_coherent(&pdev->dev, ch->fb_size,
1504 info->screen_base, 1735 ch->fb_mem, ch->dma_handle);
1505 priv->ch[i].dma_handle);
1506 fb_dealloc_cmap(&info->cmap);
1507 framebuffer_release(info);
1508 } 1736 }
1509 1737
1510 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { 1738 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
@@ -1512,11 +1740,10 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1512 sh_mobile_lcdc_bl_remove(priv->ch[i].bl); 1740 sh_mobile_lcdc_bl_remove(priv->ch[i].bl);
1513 } 1741 }
1514 1742
1515 if (priv->dot_clk) 1743 if (priv->dot_clk) {
1744 pm_runtime_disable(&pdev->dev);
1516 clk_put(priv->dot_clk); 1745 clk_put(priv->dot_clk);
1517 1746 }
1518 if (priv->dev)
1519 pm_runtime_disable(priv->dev);
1520 1747
1521 if (priv->base) 1748 if (priv->base)
1522 iounmap(priv->base); 1749 iounmap(priv->base);
@@ -1527,49 +1754,82 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1527 return 0; 1754 return 0;
1528} 1755}
1529 1756
1530static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch, 1757static int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
1531 struct device *dev)
1532{ 1758{
1533 struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg; 1759 int interface_type = ch->cfg->interface_type;
1760
1761 switch (interface_type) {
1762 case RGB8:
1763 case RGB9:
1764 case RGB12A:
1765 case RGB12B:
1766 case RGB16:
1767 case RGB18:
1768 case RGB24:
1769 case SYS8A:
1770 case SYS8B:
1771 case SYS8C:
1772 case SYS8D:
1773 case SYS9:
1774 case SYS12:
1775 case SYS16A:
1776 case SYS16B:
1777 case SYS16C:
1778 case SYS18:
1779 case SYS24:
1780 break;
1781 default:
1782 return -EINVAL;
1783 }
1784
1785 /* SUBLCD only supports SYS interface */
1786 if (lcdc_chan_is_sublcd(ch)) {
1787 if (!(interface_type & LDMT1R_IFM))
1788 return -EINVAL;
1789
1790 interface_type &= ~LDMT1R_IFM;
1791 }
1792
1793 ch->ldmt1r_value = interface_type;
1794 return 0;
1795}
1796
1797static int __devinit
1798sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
1799 struct sh_mobile_lcdc_chan *ch)
1800{
1801 const struct sh_mobile_lcdc_format_info *format;
1802 const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg;
1534 const struct fb_videomode *max_mode; 1803 const struct fb_videomode *max_mode;
1535 const struct fb_videomode *mode; 1804 const struct fb_videomode *mode;
1536 struct fb_var_screeninfo *var; 1805 unsigned int num_modes;
1537 struct fb_info *info;
1538 unsigned int max_size; 1806 unsigned int max_size;
1539 int num_cfg; 1807 unsigned int i;
1540 void *buf;
1541 int ret;
1542 int i;
1543 1808
1544 mutex_init(&ch->open_lock); 1809 mutex_init(&ch->open_lock);
1810 ch->notify = sh_mobile_lcdc_display_notify;
1545 1811
1546 /* Allocate the frame buffer device. */ 1812 /* Validate the format. */
1547 ch->info = framebuffer_alloc(0, dev); 1813 format = sh_mobile_format_info(cfg->fourcc);
1548 if (!ch->info) { 1814 if (format == NULL) {
1549 dev_err(dev, "unable to allocate fb_info\n"); 1815 dev_err(priv->dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
1550 return -ENOMEM; 1816 return -EINVAL;
1551 } 1817 }
1552 1818
1553 info = ch->info;
1554 info->fbops = &sh_mobile_lcdc_ops;
1555 info->par = ch;
1556 info->pseudo_palette = &ch->pseudo_palette;
1557 info->flags = FBINFO_FLAG_DEFAULT;
1558
1559 /* Iterate through the modes to validate them and find the highest 1819 /* Iterate through the modes to validate them and find the highest
1560 * resolution. 1820 * resolution.
1561 */ 1821 */
1562 max_mode = NULL; 1822 max_mode = NULL;
1563 max_size = 0; 1823 max_size = 0;
1564 1824
1565 for (i = 0, mode = cfg->lcd_cfg; i < cfg->num_cfg; i++, mode++) { 1825 for (i = 0, mode = cfg->lcd_modes; i < cfg->num_modes; i++, mode++) {
1566 unsigned int size = mode->yres * mode->xres; 1826 unsigned int size = mode->yres * mode->xres;
1567 1827
1568 /* NV12/NV21 buffers must have even number of lines */ 1828 /* NV12/NV21 buffers must have even number of lines */
1569 if ((cfg->fourcc == V4L2_PIX_FMT_NV12 || 1829 if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
1570 cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) { 1830 cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
1571 dev_err(dev, "yres must be multiple of 2 for YCbCr420 " 1831 dev_err(priv->dev, "yres must be multiple of 2 for "
1572 "mode.\n"); 1832 "YCbCr420 mode.\n");
1573 return -EINVAL; 1833 return -EINVAL;
1574 } 1834 }
1575 1835
@@ -1582,93 +1842,59 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
1582 if (!max_size) 1842 if (!max_size)
1583 max_size = MAX_XRES * MAX_YRES; 1843 max_size = MAX_XRES * MAX_YRES;
1584 else 1844 else
1585 dev_dbg(dev, "Found largest videomode %ux%u\n", 1845 dev_dbg(priv->dev, "Found largest videomode %ux%u\n",
1586 max_mode->xres, max_mode->yres); 1846 max_mode->xres, max_mode->yres);
1587 1847
1588 /* Create the mode list. */ 1848 if (cfg->lcd_modes == NULL) {
1589 if (cfg->lcd_cfg == NULL) {
1590 mode = &default_720p; 1849 mode = &default_720p;
1591 num_cfg = 1; 1850 num_modes = 1;
1592 } else { 1851 } else {
1593 mode = cfg->lcd_cfg; 1852 mode = cfg->lcd_modes;
1594 num_cfg = cfg->num_cfg; 1853 num_modes = cfg->num_modes;
1595 } 1854 }
1596 1855
1597 fb_videomode_to_modelist(mode, num_cfg, &info->modelist); 1856 /* Use the first mode as default. */
1857 ch->format = format;
1858 ch->xres = mode->xres;
1859 ch->xres_virtual = mode->xres;
1860 ch->yres = mode->yres;
1861 ch->yres_virtual = mode->yres * 2;
1598 1862
1599 /* Initialize variable screen information using the first mode as 1863 if (!format->yuv) {
1600 * default. The default Y virtual resolution is twice the panel size to 1864 ch->colorspace = V4L2_COLORSPACE_SRGB;
1601 * allow for double-buffering. 1865 ch->pitch = ch->xres * format->bpp / 8;
1602 */ 1866 } else {
1603 var = &info->var; 1867 ch->colorspace = V4L2_COLORSPACE_REC709;
1604 fb_videomode_to_var(var, mode); 1868 ch->pitch = ch->xres;
1605 var->width = cfg->lcd_size_cfg.width;
1606 var->height = cfg->lcd_size_cfg.height;
1607 var->yres_virtual = var->yres * 2;
1608 var->activate = FB_ACTIVATE_NOW;
1609
1610 switch (cfg->fourcc) {
1611 case V4L2_PIX_FMT_RGB565:
1612 var->bits_per_pixel = 16;
1613 break;
1614 case V4L2_PIX_FMT_BGR24:
1615 var->bits_per_pixel = 24;
1616 break;
1617 case V4L2_PIX_FMT_BGR32:
1618 var->bits_per_pixel = 32;
1619 break;
1620 default:
1621 var->grayscale = cfg->fourcc;
1622 break;
1623 } 1869 }
1624 1870
1625 /* Make sure the memory size check won't fail. smem_len is initialized 1871 ch->display.width = cfg->panel_cfg.width;
1626 * later based on var. 1872 ch->display.height = cfg->panel_cfg.height;
1627 */ 1873 ch->display.mode = *mode;
1628 info->fix.smem_len = UINT_MAX;
1629 ret = sh_mobile_check_var(var, info);
1630 if (ret)
1631 return ret;
1632
1633 max_size = max_size * var->bits_per_pixel / 8 * 2;
1634 1874
1635 /* Allocate frame buffer memory and color map. */ 1875 /* Allocate frame buffer memory. */
1636 buf = dma_alloc_coherent(dev, max_size, &ch->dma_handle, GFP_KERNEL); 1876 ch->fb_size = max_size * format->bpp / 8 * 2;
1637 if (!buf) { 1877 ch->fb_mem = dma_alloc_coherent(priv->dev, ch->fb_size, &ch->dma_handle,
1638 dev_err(dev, "unable to allocate buffer\n"); 1878 GFP_KERNEL);
1879 if (ch->fb_mem == NULL) {
1880 dev_err(priv->dev, "unable to allocate buffer\n");
1639 return -ENOMEM; 1881 return -ENOMEM;
1640 } 1882 }
1641 1883
1642 ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); 1884 /* Initialize the transmitter device if present. */
1643 if (ret < 0) { 1885 if (cfg->tx_dev) {
1644 dev_err(dev, "unable to allocate cmap\n"); 1886 if (!cfg->tx_dev->dev.driver ||
1645 dma_free_coherent(dev, max_size, buf, ch->dma_handle); 1887 !try_module_get(cfg->tx_dev->dev.driver->owner)) {
1646 return ret; 1888 dev_warn(priv->dev,
1647 } 1889 "unable to get transmitter device\n");
1648 1890 return -EINVAL;
1649 /* Initialize fixed screen information. Restrict pan to 2 lines steps 1891 }
1650 * for NV12 and NV21. 1892 ch->tx_dev = platform_get_drvdata(cfg->tx_dev);
1651 */ 1893 ch->tx_dev->lcdc = ch;
1652 info->fix = sh_mobile_lcdc_fix; 1894 ch->tx_dev->def_mode = *mode;
1653 info->fix.smem_start = ch->dma_handle;
1654 info->fix.smem_len = max_size;
1655 if (cfg->fourcc == V4L2_PIX_FMT_NV12 ||
1656 cfg->fourcc == V4L2_PIX_FMT_NV21)
1657 info->fix.ypanstep = 2;
1658
1659 if (sh_mobile_format_is_yuv(var)) {
1660 info->fix.line_length = var->xres;
1661 info->fix.visual = FB_VISUAL_FOURCC;
1662 } else {
1663 info->fix.line_length = var->xres * var->bits_per_pixel / 8;
1664 info->fix.visual = FB_VISUAL_TRUECOLOR;
1665 } 1895 }
1666 1896
1667 info->screen_base = buf; 1897 return sh_mobile_lcdc_channel_fb_init(ch, mode, num_modes);
1668 info->device = dev;
1669 ch->display_var = *var;
1670
1671 return 0;
1672} 1898}
1673 1899
1674static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) 1900static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
@@ -1698,6 +1924,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1698 return -ENOMEM; 1924 return -ENOMEM;
1699 } 1925 }
1700 1926
1927 priv->dev = &pdev->dev;
1928 priv->meram_dev = pdata->meram_dev;
1701 platform_set_drvdata(pdev, priv); 1929 platform_set_drvdata(pdev, priv);
1702 1930
1703 error = request_irq(i, sh_mobile_lcdc_irq, 0, 1931 error = request_irq(i, sh_mobile_lcdc_irq, 0,
@@ -1714,7 +1942,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1714 struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels; 1942 struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels;
1715 1943
1716 ch->lcdc = priv; 1944 ch->lcdc = priv;
1717 memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i])); 1945 ch->cfg = &pdata->ch[i];
1718 1946
1719 error = sh_mobile_lcdc_check_interface(ch); 1947 error = sh_mobile_lcdc_check_interface(ch);
1720 if (error) { 1948 if (error) {
@@ -1726,7 +1954,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1726 ch->pan_offset = 0; 1954 ch->pan_offset = 0;
1727 1955
1728 /* probe the backlight is there is one defined */ 1956 /* probe the backlight is there is one defined */
1729 if (ch->cfg.bl_info.max_brightness) 1957 if (ch->cfg->bl_info.max_brightness)
1730 ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch); 1958 ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch);
1731 1959
1732 switch (pdata->ch[i].chan) { 1960 switch (pdata->ch[i].chan) {
@@ -1757,18 +1985,19 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1757 if (!priv->base) 1985 if (!priv->base)
1758 goto err1; 1986 goto err1;
1759 1987
1760 error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv); 1988 error = sh_mobile_lcdc_setup_clocks(priv, pdata->clock_source);
1761 if (error) { 1989 if (error) {
1762 dev_err(&pdev->dev, "unable to setup clocks\n"); 1990 dev_err(&pdev->dev, "unable to setup clocks\n");
1763 goto err1; 1991 goto err1;
1764 } 1992 }
1765 1993
1766 priv->meram_dev = pdata->meram_dev; 1994 /* Enable runtime PM. */
1995 pm_runtime_enable(&pdev->dev);
1767 1996
1768 for (i = 0; i < num_channels; i++) { 1997 for (i = 0; i < num_channels; i++) {
1769 struct sh_mobile_lcdc_chan *ch = priv->ch + i; 1998 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1770 1999
1771 error = sh_mobile_lcdc_channel_init(ch, &pdev->dev); 2000 error = sh_mobile_lcdc_channel_init(priv, ch);
1772 if (error) 2001 if (error)
1773 goto err1; 2002 goto err1;
1774 } 2003 }
@@ -1781,31 +2010,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1781 2010
1782 for (i = 0; i < num_channels; i++) { 2011 for (i = 0; i < num_channels; i++) {
1783 struct sh_mobile_lcdc_chan *ch = priv->ch + i; 2012 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1784 struct fb_info *info = ch->info;
1785
1786 if (info->fbdefio) {
1787 ch->sglist = vmalloc(sizeof(struct scatterlist) *
1788 info->fix.smem_len >> PAGE_SHIFT);
1789 if (!ch->sglist) {
1790 dev_err(&pdev->dev, "cannot allocate sglist\n");
1791 goto err1;
1792 }
1793 }
1794
1795 info->bl_dev = ch->bl;
1796 2013
1797 error = register_framebuffer(info); 2014 error = sh_mobile_lcdc_channel_fb_register(ch);
1798 if (error < 0) 2015 if (error)
1799 goto err1; 2016 goto err1;
1800
1801 dev_info(info->dev, "registered %s/%s as %dx%d %dbpp.\n",
1802 pdev->name, (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
1803 "mainlcd" : "sublcd", info->var.xres, info->var.yres,
1804 info->var.bits_per_pixel);
1805
1806 /* deferred io mode: disable clock to save power */
1807 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
1808 sh_mobile_lcdc_clk_off(priv);
1809 } 2017 }
1810 2018
1811 /* Failure ignored */ 2019 /* Failure ignored */
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index a58a0f38848b..da1c26e78a57 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -14,9 +14,35 @@ enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
14 14
15#define PALETTE_NR 16 15#define PALETTE_NR 16
16 16
17struct sh_mobile_lcdc_priv;
18struct fb_info;
19struct backlight_device; 17struct backlight_device;
18struct fb_info;
19struct module;
20struct sh_mobile_lcdc_chan;
21struct sh_mobile_lcdc_entity;
22struct sh_mobile_lcdc_format_info;
23struct sh_mobile_lcdc_priv;
24
25#define SH_MOBILE_LCDC_DISPLAY_DISCONNECTED 0
26#define SH_MOBILE_LCDC_DISPLAY_CONNECTED 1
27
28struct sh_mobile_lcdc_entity_ops {
29 /* Display */
30 int (*display_on)(struct sh_mobile_lcdc_entity *entity);
31 void (*display_off)(struct sh_mobile_lcdc_entity *entity);
32};
33
34enum sh_mobile_lcdc_entity_event {
35 SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT,
36 SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT,
37 SH_MOBILE_LCDC_EVENT_DISPLAY_MODE,
38};
39
40struct sh_mobile_lcdc_entity {
41 struct module *owner;
42 const struct sh_mobile_lcdc_entity_ops *ops;
43 struct sh_mobile_lcdc_chan *lcdc;
44 struct fb_videomode def_mode;
45};
20 46
21/* 47/*
22 * struct sh_mobile_lcdc_chan - LCDC display channel 48 * struct sh_mobile_lcdc_chan - LCDC display channel
@@ -27,29 +53,57 @@ struct backlight_device;
27 */ 53 */
28struct sh_mobile_lcdc_chan { 54struct sh_mobile_lcdc_chan {
29 struct sh_mobile_lcdc_priv *lcdc; 55 struct sh_mobile_lcdc_priv *lcdc;
56 struct sh_mobile_lcdc_entity *tx_dev;
57 const struct sh_mobile_lcdc_chan_cfg *cfg;
58
30 unsigned long *reg_offs; 59 unsigned long *reg_offs;
31 unsigned long ldmt1r_value; 60 unsigned long ldmt1r_value;
32 unsigned long enabled; /* ME and SE in LDCNT2R */ 61 unsigned long enabled; /* ME and SE in LDCNT2R */
33 struct sh_mobile_lcdc_chan_cfg cfg; 62 void *meram;
34 u32 pseudo_palette[PALETTE_NR]; 63
35 struct fb_info *info; 64 struct mutex open_lock; /* protects the use counter */
36 struct backlight_device *bl; 65 int use_count;
66
67 void *fb_mem;
68 unsigned long fb_size;
69
37 dma_addr_t dma_handle; 70 dma_addr_t dma_handle;
38 struct fb_deferred_io defio;
39 struct scatterlist *sglist;
40 unsigned long frame_end;
41 unsigned long pan_offset; 71 unsigned long pan_offset;
72
73 unsigned long frame_end;
42 wait_queue_head_t frame_end_wait; 74 wait_queue_head_t frame_end_wait;
43 struct completion vsync_completion; 75 struct completion vsync_completion;
44 struct fb_var_screeninfo display_var; 76
45 int use_count; 77 const struct sh_mobile_lcdc_format_info *format;
46 int blank_status; 78 u32 colorspace;
47 struct mutex open_lock; /* protects the use counter */ 79 unsigned int xres;
48 int meram_enabled; 80 unsigned int xres_virtual;
81 unsigned int yres;
82 unsigned int yres_virtual;
83 unsigned int pitch;
49 84
50 unsigned long base_addr_y; 85 unsigned long base_addr_y;
51 unsigned long base_addr_c; 86 unsigned long base_addr_c;
52 unsigned int pitch; 87
88 int (*notify)(struct sh_mobile_lcdc_chan *ch,
89 enum sh_mobile_lcdc_entity_event event,
90 const struct fb_videomode *mode,
91 const struct fb_monspecs *monspec);
92
93 /* Backlight */
94 struct backlight_device *bl;
95
96 /* FB */
97 struct fb_info *info;
98 u32 pseudo_palette[PALETTE_NR];
99 struct {
100 unsigned int width;
101 unsigned int height;
102 struct fb_videomode mode;
103 } display;
104 struct fb_deferred_io defio;
105 struct scatterlist *sglist;
106 int blank_status;
53}; 107};
54 108
55#endif 109#endif
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index f45d83ecfd21..82ba830bf95d 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -9,16 +9,22 @@
9 * for more details. 9 * for more details.
10 */ 10 */
11 11
12#include <linux/device.h>
13#include <linux/err.h>
14#include <linux/genalloc.h>
15#include <linux/io.h>
12#include <linux/kernel.h> 16#include <linux/kernel.h>
13#include <linux/module.h> 17#include <linux/module.h>
14#include <linux/device.h> 18#include <linux/platform_device.h>
15#include <linux/pm_runtime.h> 19#include <linux/pm_runtime.h>
16#include <linux/io.h>
17#include <linux/slab.h> 20#include <linux/slab.h>
18#include <linux/platform_device.h> 21
19#include <video/sh_mobile_meram.h> 22#include <video/sh_mobile_meram.h>
20 23
21/* meram registers */ 24/* -----------------------------------------------------------------------------
25 * MERAM registers
26 */
27
22#define MEVCR1 0x4 28#define MEVCR1 0x4
23#define MEVCR1_RST (1 << 31) 29#define MEVCR1_RST (1 << 31)
24#define MEVCR1_WD (1 << 30) 30#define MEVCR1_WD (1 << 30)
@@ -81,16 +87,14 @@
81 ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \ 87 ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \
82 ((xszm1) << MExxBSIZE_XSZM1_SHIFT)) 88 ((xszm1) << MExxBSIZE_XSZM1_SHIFT))
83 89
84#define SH_MOBILE_MERAM_ICB_NUM 32 90static const unsigned long common_regs[] = {
85
86static unsigned long common_regs[] = {
87 MEVCR1, 91 MEVCR1,
88 MEQSEL1, 92 MEQSEL1,
89 MEQSEL2, 93 MEQSEL2,
90}; 94};
91#define CMN_REGS_SIZE ARRAY_SIZE(common_regs) 95#define MERAM_REGS_SIZE ARRAY_SIZE(common_regs)
92 96
93static unsigned long icb_regs[] = { 97static const unsigned long icb_regs[] = {
94 MExxCTL, 98 MExxCTL,
95 MExxBSIZE, 99 MExxBSIZE,
96 MExxMNCF, 100 MExxMNCF,
@@ -100,216 +104,269 @@ static unsigned long icb_regs[] = {
100}; 104};
101#define ICB_REGS_SIZE ARRAY_SIZE(icb_regs) 105#define ICB_REGS_SIZE ARRAY_SIZE(icb_regs)
102 106
107/*
108 * sh_mobile_meram_icb - MERAM ICB information
109 * @regs: Registers cache
110 * @index: ICB index
111 * @offset: MERAM block offset
112 * @size: MERAM block size in KiB
113 * @cache_unit: Bytes to cache per ICB
114 * @pixelformat: Video pixel format of the data stored in the ICB
115 * @current_reg: Which of Start Address Register A (0) or B (1) is in use
116 */
117struct sh_mobile_meram_icb {
118 unsigned long regs[ICB_REGS_SIZE];
119 unsigned int index;
120 unsigned long offset;
121 unsigned int size;
122
123 unsigned int cache_unit;
124 unsigned int pixelformat;
125 unsigned int current_reg;
126};
127
128#define MERAM_ICB_NUM 32
129
130struct sh_mobile_meram_fb_plane {
131 struct sh_mobile_meram_icb *marker;
132 struct sh_mobile_meram_icb *cache;
133};
134
135struct sh_mobile_meram_fb_cache {
136 unsigned int nplanes;
137 struct sh_mobile_meram_fb_plane planes[2];
138};
139
140/*
141 * sh_mobile_meram_priv - MERAM device
142 * @base: Registers base address
143 * @meram: MERAM physical address
144 * @regs: Registers cache
145 * @lock: Protects used_icb and icbs
146 * @used_icb: Bitmask of used ICBs
147 * @icbs: ICBs
148 * @pool: Allocation pool to manage the MERAM
149 */
103struct sh_mobile_meram_priv { 150struct sh_mobile_meram_priv {
104 void __iomem *base; 151 void __iomem *base;
105 struct mutex lock; 152 unsigned long meram;
106 unsigned long used_icb; 153 unsigned long regs[MERAM_REGS_SIZE];
107 int used_meram_cache_regions; 154
108 unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM]; 155 struct mutex lock;
109 unsigned long cmn_saved_regs[CMN_REGS_SIZE]; 156 unsigned long used_icb;
110 unsigned long icb_saved_regs[ICB_REGS_SIZE * SH_MOBILE_MERAM_ICB_NUM]; 157 struct sh_mobile_meram_icb icbs[MERAM_ICB_NUM];
158
159 struct gen_pool *pool;
111}; 160};
112 161
113/* settings */ 162/* settings */
114#define MERAM_SEC_LINE 15 163#define MERAM_GRANULARITY 1024
115#define MERAM_LINE_WIDTH 2048 164#define MERAM_SEC_LINE 15
165#define MERAM_LINE_WIDTH 2048
116 166
117/* 167/* -----------------------------------------------------------------------------
118 * MERAM/ICB access functions 168 * Registers access
119 */ 169 */
120 170
121#define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20) 171#define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20)
122 172
123static inline void meram_write_icb(void __iomem *base, int idx, int off, 173static inline void meram_write_icb(void __iomem *base, unsigned int idx,
124 unsigned long val) 174 unsigned int off, unsigned long val)
125{ 175{
126 iowrite32(val, MERAM_ICB_OFFSET(base, idx, off)); 176 iowrite32(val, MERAM_ICB_OFFSET(base, idx, off));
127} 177}
128 178
129static inline unsigned long meram_read_icb(void __iomem *base, int idx, int off) 179static inline unsigned long meram_read_icb(void __iomem *base, unsigned int idx,
180 unsigned int off)
130{ 181{
131 return ioread32(MERAM_ICB_OFFSET(base, idx, off)); 182 return ioread32(MERAM_ICB_OFFSET(base, idx, off));
132} 183}
133 184
134static inline void meram_write_reg(void __iomem *base, int off, 185static inline void meram_write_reg(void __iomem *base, unsigned int off,
135 unsigned long val) 186 unsigned long val)
136{ 187{
137 iowrite32(val, base + off); 188 iowrite32(val, base + off);
138} 189}
139 190
140static inline unsigned long meram_read_reg(void __iomem *base, int off) 191static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
141{ 192{
142 return ioread32(base + off); 193 return ioread32(base + off);
143} 194}
144 195
145/* 196/* -----------------------------------------------------------------------------
146 * register ICB 197 * Allocation
147 */
148
149#define MERAM_CACHE_START(p) ((p) >> 16)
150#define MERAM_CACHE_END(p) ((p) & 0xffff)
151#define MERAM_CACHE_SET(o, s) ((((o) & 0xffff) << 16) | \
152 (((o) + (s) - 1) & 0xffff))
153
154/*
155 * check if there's no overlaps in MERAM allocation.
156 */ 198 */
157 199
158static inline int meram_check_overlap(struct sh_mobile_meram_priv *priv, 200/* Allocate ICBs and MERAM for a plane. */
159 struct sh_mobile_meram_icb *new) 201static int __meram_alloc(struct sh_mobile_meram_priv *priv,
202 struct sh_mobile_meram_fb_plane *plane,
203 size_t size)
160{ 204{
161 int i; 205 unsigned long mem;
162 int used_start, used_end, meram_start, meram_end; 206 unsigned long idx;
163 207
164 /* valid ICB? */ 208 idx = find_first_zero_bit(&priv->used_icb, 28);
165 if (new->marker_icb & ~0x1f || new->cache_icb & ~0x1f) 209 if (idx == 28)
166 return 1; 210 return -ENOMEM;
211 plane->cache = &priv->icbs[idx];
167 212
168 if (test_bit(new->marker_icb, &priv->used_icb) || 213 idx = find_next_zero_bit(&priv->used_icb, 32, 28);
169 test_bit(new->cache_icb, &priv->used_icb)) 214 if (idx == 32)
170 return 1; 215 return -ENOMEM;
216 plane->marker = &priv->icbs[idx];
171 217
172 for (i = 0; i < priv->used_meram_cache_regions; i++) { 218 mem = gen_pool_alloc(priv->pool, size * 1024);
173 used_start = MERAM_CACHE_START(priv->used_meram_cache[i]); 219 if (mem == 0)
174 used_end = MERAM_CACHE_END(priv->used_meram_cache[i]); 220 return -ENOMEM;
175 meram_start = new->meram_offset;
176 meram_end = new->meram_offset + new->meram_size;
177 221
178 if ((meram_start >= used_start && meram_start < used_end) || 222 __set_bit(plane->marker->index, &priv->used_icb);
179 (meram_end > used_start && meram_end < used_end)) 223 __set_bit(plane->cache->index, &priv->used_icb);
180 return 1; 224
181 } 225 plane->marker->offset = mem - priv->meram;
226 plane->marker->size = size;
182 227
183 return 0; 228 return 0;
184} 229}
185 230
186/* 231/* Free ICBs and MERAM for a plane. */
187 * mark the specified ICB as used 232static void __meram_free(struct sh_mobile_meram_priv *priv,
188 */ 233 struct sh_mobile_meram_fb_plane *plane)
234{
235 gen_pool_free(priv->pool, priv->meram + plane->marker->offset,
236 plane->marker->size * 1024);
189 237
190static inline void meram_mark(struct sh_mobile_meram_priv *priv, 238 __clear_bit(plane->marker->index, &priv->used_icb);
191 struct sh_mobile_meram_icb *new) 239 __clear_bit(plane->cache->index, &priv->used_icb);
240}
241
242/* Is this a YCbCr(NV12, NV16 or NV24) colorspace? */
243static int is_nvcolor(int cspace)
192{ 244{
193 int n; 245 if (cspace == SH_MOBILE_MERAM_PF_NV ||
246 cspace == SH_MOBILE_MERAM_PF_NV24)
247 return 1;
248 return 0;
249}
194 250
195 if (new->marker_icb < 0 || new->cache_icb < 0) 251/* Allocate memory for the ICBs and mark them as used. */
196 return; 252static struct sh_mobile_meram_fb_cache *
253meram_alloc(struct sh_mobile_meram_priv *priv,
254 const struct sh_mobile_meram_cfg *cfg,
255 int pixelformat)
256{
257 struct sh_mobile_meram_fb_cache *cache;
258 unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
259 int ret;
197 260
198 __set_bit(new->marker_icb, &priv->used_icb); 261 if (cfg->icb[0].meram_size == 0)
199 __set_bit(new->cache_icb, &priv->used_icb); 262 return ERR_PTR(-EINVAL);
200 263
201 n = priv->used_meram_cache_regions; 264 if (nplanes == 2 && cfg->icb[1].meram_size == 0)
265 return ERR_PTR(-EINVAL);
202 266
203 priv->used_meram_cache[n] = MERAM_CACHE_SET(new->meram_offset, 267 cache = kzalloc(sizeof(*cache), GFP_KERNEL);
204 new->meram_size); 268 if (cache == NULL)
269 return ERR_PTR(-ENOMEM);
205 270
206 priv->used_meram_cache_regions++; 271 cache->nplanes = nplanes;
207}
208 272
209/* 273 ret = __meram_alloc(priv, &cache->planes[0], cfg->icb[0].meram_size);
210 * unmark the specified ICB as used 274 if (ret < 0)
211 */ 275 goto error;
212 276
213static inline void meram_unmark(struct sh_mobile_meram_priv *priv, 277 cache->planes[0].marker->current_reg = 1;
214 struct sh_mobile_meram_icb *icb) 278 cache->planes[0].marker->pixelformat = pixelformat;
215{ 279
216 int i; 280 if (cache->nplanes == 1)
217 unsigned long pattern; 281 return cache;
218 282
219 if (icb->marker_icb < 0 || icb->cache_icb < 0) 283 ret = __meram_alloc(priv, &cache->planes[1], cfg->icb[1].meram_size);
220 return; 284 if (ret < 0) {
221 285 __meram_free(priv, &cache->planes[0]);
222 __clear_bit(icb->marker_icb, &priv->used_icb); 286 goto error;
223 __clear_bit(icb->cache_icb, &priv->used_icb);
224
225 pattern = MERAM_CACHE_SET(icb->meram_offset, icb->meram_size);
226 for (i = 0; i < priv->used_meram_cache_regions; i++) {
227 if (priv->used_meram_cache[i] == pattern) {
228 while (i < priv->used_meram_cache_regions - 1) {
229 priv->used_meram_cache[i] =
230 priv->used_meram_cache[i + 1] ;
231 i++;
232 }
233 priv->used_meram_cache[i] = 0;
234 priv->used_meram_cache_regions--;
235 break;
236 }
237 } 287 }
288
289 return cache;
290
291error:
292 kfree(cache);
293 return ERR_PTR(-ENOMEM);
238} 294}
239 295
240/* 296/* Unmark the specified ICB as used. */
241 * is this a YCbCr(NV12, NV16 or NV24) colorspace 297static void meram_free(struct sh_mobile_meram_priv *priv,
242 */ 298 struct sh_mobile_meram_fb_cache *cache)
243static inline int is_nvcolor(int cspace)
244{ 299{
245 if (cspace == SH_MOBILE_MERAM_PF_NV || 300 __meram_free(priv, &cache->planes[0]);
246 cspace == SH_MOBILE_MERAM_PF_NV24) 301 if (cache->nplanes == 2)
247 return 1; 302 __meram_free(priv, &cache->planes[1]);
248 return 0; 303
304 kfree(cache);
249} 305}
250 306
251/* 307/* Set the next address to fetch. */
252 * set the next address to fetch 308static void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
253 */ 309 struct sh_mobile_meram_fb_cache *cache,
254static inline void meram_set_next_addr(struct sh_mobile_meram_priv *priv, 310 unsigned long base_addr_y,
255 struct sh_mobile_meram_cfg *cfg, 311 unsigned long base_addr_c)
256 unsigned long base_addr_y,
257 unsigned long base_addr_c)
258{ 312{
313 struct sh_mobile_meram_icb *icb = cache->planes[0].marker;
259 unsigned long target; 314 unsigned long target;
260 315
261 target = (cfg->current_reg) ? MExxSARA : MExxSARB; 316 icb->current_reg ^= 1;
262 cfg->current_reg ^= 1; 317 target = icb->current_reg ? MExxSARB : MExxSARA;
263 318
264 /* set the next address to fetch */ 319 /* set the next address to fetch */
265 meram_write_icb(priv->base, cfg->icb[0].cache_icb, target, 320 meram_write_icb(priv->base, cache->planes[0].cache->index, target,
266 base_addr_y); 321 base_addr_y);
267 meram_write_icb(priv->base, cfg->icb[0].marker_icb, target, 322 meram_write_icb(priv->base, cache->planes[0].marker->index, target,
268 base_addr_y + cfg->icb[0].cache_unit); 323 base_addr_y + cache->planes[0].marker->cache_unit);
269 324
270 if (is_nvcolor(cfg->pixelformat)) { 325 if (cache->nplanes == 2) {
271 meram_write_icb(priv->base, cfg->icb[1].cache_icb, target, 326 meram_write_icb(priv->base, cache->planes[1].cache->index,
272 base_addr_c); 327 target, base_addr_c);
273 meram_write_icb(priv->base, cfg->icb[1].marker_icb, target, 328 meram_write_icb(priv->base, cache->planes[1].marker->index,
274 base_addr_c + cfg->icb[1].cache_unit); 329 target, base_addr_c +
330 cache->planes[1].marker->cache_unit);
275 } 331 }
276} 332}
277 333
278/* 334/* Get the next ICB address. */
279 * get the next ICB address 335static void
280 */ 336meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
281static inline void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata, 337 struct sh_mobile_meram_fb_cache *cache,
282 struct sh_mobile_meram_cfg *cfg, 338 unsigned long *icb_addr_y, unsigned long *icb_addr_c)
283 unsigned long *icb_addr_y,
284 unsigned long *icb_addr_c)
285{ 339{
340 struct sh_mobile_meram_icb *icb = cache->planes[0].marker;
286 unsigned long icb_offset; 341 unsigned long icb_offset;
287 342
288 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE0) 343 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE0)
289 icb_offset = 0x80000000 | (cfg->current_reg << 29); 344 icb_offset = 0x80000000 | (icb->current_reg << 29);
290 else 345 else
291 icb_offset = 0xc0000000 | (cfg->current_reg << 23); 346 icb_offset = 0xc0000000 | (icb->current_reg << 23);
292 347
293 *icb_addr_y = icb_offset | (cfg->icb[0].marker_icb << 24); 348 *icb_addr_y = icb_offset | (cache->planes[0].marker->index << 24);
294 if (is_nvcolor(cfg->pixelformat)) 349 if (cache->nplanes == 2)
295 *icb_addr_c = icb_offset | (cfg->icb[1].marker_icb << 24); 350 *icb_addr_c = icb_offset
351 | (cache->planes[1].marker->index << 24);
296} 352}
297 353
298#define MERAM_CALC_BYTECOUNT(x, y) \ 354#define MERAM_CALC_BYTECOUNT(x, y) \
299 (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1)) 355 (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
300 356
301/* 357/* Initialize MERAM. */
302 * initialize MERAM
303 */
304
305static int meram_init(struct sh_mobile_meram_priv *priv, 358static int meram_init(struct sh_mobile_meram_priv *priv,
306 struct sh_mobile_meram_icb *icb, 359 struct sh_mobile_meram_fb_plane *plane,
307 int xres, int yres, int *out_pitch) 360 unsigned int xres, unsigned int yres,
361 unsigned int *out_pitch)
308{ 362{
363 struct sh_mobile_meram_icb *marker = plane->marker;
309 unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres); 364 unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
310 unsigned long bnm; 365 unsigned long bnm;
311 int lcdc_pitch, xpitch, line_cnt; 366 unsigned int lcdc_pitch;
312 int save_lines; 367 unsigned int xpitch;
368 unsigned int line_cnt;
369 unsigned int save_lines;
313 370
314 /* adjust pitch to 1024, 2048, 4096 or 8192 */ 371 /* adjust pitch to 1024, 2048, 4096 or 8192 */
315 lcdc_pitch = (xres - 1) | 1023; 372 lcdc_pitch = (xres - 1) | 1023;
@@ -322,13 +379,13 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
322 lcdc_pitch = xpitch = MERAM_LINE_WIDTH; 379 lcdc_pitch = xpitch = MERAM_LINE_WIDTH;
323 line_cnt = total_byte_count >> 11; 380 line_cnt = total_byte_count >> 11;
324 *out_pitch = xres; 381 *out_pitch = xres;
325 save_lines = (icb->meram_size / 16 / MERAM_SEC_LINE); 382 save_lines = plane->marker->size / 16 / MERAM_SEC_LINE;
326 save_lines *= MERAM_SEC_LINE; 383 save_lines *= MERAM_SEC_LINE;
327 } else { 384 } else {
328 xpitch = xres; 385 xpitch = xres;
329 line_cnt = yres; 386 line_cnt = yres;
330 *out_pitch = lcdc_pitch; 387 *out_pitch = lcdc_pitch;
331 save_lines = icb->meram_size / (lcdc_pitch >> 10) / 2; 388 save_lines = plane->marker->size / (lcdc_pitch >> 10) / 2;
332 save_lines &= 0xff; 389 save_lines &= 0xff;
333 } 390 }
334 bnm = (save_lines - 1) << 16; 391 bnm = (save_lines - 1) << 16;
@@ -336,19 +393,20 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
336 /* TODO: we better to check if we have enough MERAM buffer size */ 393 /* TODO: we better to check if we have enough MERAM buffer size */
337 394
338 /* set up ICB */ 395 /* set up ICB */
339 meram_write_icb(priv->base, icb->cache_icb, MExxBSIZE, 396 meram_write_icb(priv->base, plane->cache->index, MExxBSIZE,
340 MERAM_MExxBSIZE_VAL(0x0, line_cnt - 1, xpitch - 1)); 397 MERAM_MExxBSIZE_VAL(0x0, line_cnt - 1, xpitch - 1));
341 meram_write_icb(priv->base, icb->marker_icb, MExxBSIZE, 398 meram_write_icb(priv->base, plane->marker->index, MExxBSIZE,
342 MERAM_MExxBSIZE_VAL(0xf, line_cnt - 1, xpitch - 1)); 399 MERAM_MExxBSIZE_VAL(0xf, line_cnt - 1, xpitch - 1));
343 400
344 meram_write_icb(priv->base, icb->cache_icb, MExxMNCF, bnm); 401 meram_write_icb(priv->base, plane->cache->index, MExxMNCF, bnm);
345 meram_write_icb(priv->base, icb->marker_icb, MExxMNCF, bnm); 402 meram_write_icb(priv->base, plane->marker->index, MExxMNCF, bnm);
346 403
347 meram_write_icb(priv->base, icb->cache_icb, MExxSBSIZE, xpitch); 404 meram_write_icb(priv->base, plane->cache->index, MExxSBSIZE, xpitch);
348 meram_write_icb(priv->base, icb->marker_icb, MExxSBSIZE, xpitch); 405 meram_write_icb(priv->base, plane->marker->index, MExxSBSIZE, xpitch);
349 406
350 /* save a cache unit size */ 407 /* save a cache unit size */
351 icb->cache_unit = xres * save_lines; 408 plane->cache->cache_unit = xres * save_lines;
409 plane->marker->cache_unit = xres * save_lines;
352 410
353 /* 411 /*
354 * Set MERAM for framebuffer 412 * Set MERAM for framebuffer
@@ -356,13 +414,13 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
356 * we also chain the cache_icb and the marker_icb. 414 * we also chain the cache_icb and the marker_icb.
357 * we also split the allocated MERAM buffer between two ICBs. 415 * we also split the allocated MERAM buffer between two ICBs.
358 */ 416 */
359 meram_write_icb(priv->base, icb->cache_icb, MExxCTL, 417 meram_write_icb(priv->base, plane->cache->index, MExxCTL,
360 MERAM_MExxCTL_VAL(icb->marker_icb, icb->meram_offset) | 418 MERAM_MExxCTL_VAL(plane->marker->index, marker->offset)
361 MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM | 419 | MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
362 MExxCTL_MD_FB); 420 MExxCTL_MD_FB);
363 meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 421 meram_write_icb(priv->base, plane->marker->index, MExxCTL,
364 MERAM_MExxCTL_VAL(icb->cache_icb, icb->meram_offset + 422 MERAM_MExxCTL_VAL(plane->cache->index, marker->offset +
365 icb->meram_size / 2) | 423 plane->marker->size / 2) |
366 MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM | 424 MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
367 MExxCTL_MD_FB); 425 MExxCTL_MD_FB);
368 426
@@ -370,239 +428,175 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
370} 428}
371 429
372static void meram_deinit(struct sh_mobile_meram_priv *priv, 430static void meram_deinit(struct sh_mobile_meram_priv *priv,
373 struct sh_mobile_meram_icb *icb) 431 struct sh_mobile_meram_fb_plane *plane)
374{ 432{
375 /* disable ICB */ 433 /* disable ICB */
376 meram_write_icb(priv->base, icb->cache_icb, MExxCTL, 434 meram_write_icb(priv->base, plane->cache->index, MExxCTL,
377 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF); 435 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
378 meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 436 meram_write_icb(priv->base, plane->marker->index, MExxCTL,
379 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF); 437 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
380 icb->cache_unit = 0; 438
439 plane->cache->cache_unit = 0;
440 plane->marker->cache_unit = 0;
381} 441}
382 442
383/* 443/* -----------------------------------------------------------------------------
384 * register the ICB 444 * Registration/unregistration
385 */ 445 */
386 446
387static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata, 447static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
388 struct sh_mobile_meram_cfg *cfg, 448 const struct sh_mobile_meram_cfg *cfg,
389 int xres, int yres, int pixelformat, 449 unsigned int xres, unsigned int yres,
390 unsigned long base_addr_y, 450 unsigned int pixelformat,
391 unsigned long base_addr_c, 451 unsigned int *pitch)
392 unsigned long *icb_addr_y,
393 unsigned long *icb_addr_c,
394 int *pitch)
395{ 452{
396 struct platform_device *pdev; 453 struct sh_mobile_meram_fb_cache *cache;
397 struct sh_mobile_meram_priv *priv; 454 struct sh_mobile_meram_priv *priv = pdata->priv;
398 int n, out_pitch; 455 struct platform_device *pdev = pdata->pdev;
399 int error = 0; 456 unsigned int out_pitch;
400
401 if (!pdata || !pdata->priv || !pdata->pdev || !cfg)
402 return -EINVAL;
403 457
404 if (pixelformat != SH_MOBILE_MERAM_PF_NV && 458 if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
405 pixelformat != SH_MOBILE_MERAM_PF_NV24 && 459 pixelformat != SH_MOBILE_MERAM_PF_NV24 &&
406 pixelformat != SH_MOBILE_MERAM_PF_RGB) 460 pixelformat != SH_MOBILE_MERAM_PF_RGB)
407 return -EINVAL; 461 return ERR_PTR(-EINVAL);
408
409 priv = pdata->priv;
410 pdev = pdata->pdev;
411 462
412 dev_dbg(&pdev->dev, "registering %dx%d (%s) (y=%08lx, c=%08lx)", 463 dev_dbg(&pdev->dev, "registering %dx%d (%s)", xres, yres,
413 xres, yres, (!pixelformat) ? "yuv" : "rgb", 464 !pixelformat ? "yuv" : "rgb");
414 base_addr_y, base_addr_c);
415 465
416 /* we can't handle wider than 8192px */ 466 /* we can't handle wider than 8192px */
417 if (xres > 8192) { 467 if (xres > 8192) {
418 dev_err(&pdev->dev, "width exceeding the limit (> 8192)."); 468 dev_err(&pdev->dev, "width exceeding the limit (> 8192).");
419 return -EINVAL; 469 return ERR_PTR(-EINVAL);
420 }
421
422 /* do we have at least one ICB config? */
423 if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) {
424 dev_err(&pdev->dev, "at least one ICB is required.");
425 return -EINVAL;
426 } 470 }
427 471
428 mutex_lock(&priv->lock); 472 mutex_lock(&priv->lock);
429 473
430 if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) { 474 /* We now register the ICBs and allocate the MERAM regions. */
431 dev_err(&pdev->dev, "no more ICB available."); 475 cache = meram_alloc(priv, cfg, pixelformat);
432 error = -EINVAL; 476 if (IS_ERR(cache)) {
433 goto err; 477 dev_err(&pdev->dev, "MERAM allocation failed (%ld).",
434 } 478 PTR_ERR(cache));
435
436 /* make sure that there's no overlaps */
437 if (meram_check_overlap(priv, &cfg->icb[0])) {
438 dev_err(&pdev->dev, "conflicting config detected.");
439 error = -EINVAL;
440 goto err; 479 goto err;
441 } 480 }
442 n = 1;
443
444 /* do the same if we have the second ICB set */
445 if (cfg->icb[1].marker_icb >= 0 && cfg->icb[1].cache_icb >= 0) {
446 if (meram_check_overlap(priv, &cfg->icb[1])) {
447 dev_err(&pdev->dev, "conflicting config detected.");
448 error = -EINVAL;
449 goto err;
450 }
451 n = 2;
452 }
453
454 if (is_nvcolor(pixelformat) && n != 2) {
455 dev_err(&pdev->dev, "requires two ICB sets for planar Y/C.");
456 error = -EINVAL;
457 goto err;
458 }
459
460 /* we now register the ICB */
461 cfg->pixelformat = pixelformat;
462 meram_mark(priv, &cfg->icb[0]);
463 if (is_nvcolor(pixelformat))
464 meram_mark(priv, &cfg->icb[1]);
465 481
466 /* initialize MERAM */ 482 /* initialize MERAM */
467 meram_init(priv, &cfg->icb[0], xres, yres, &out_pitch); 483 meram_init(priv, &cache->planes[0], xres, yres, &out_pitch);
468 *pitch = out_pitch; 484 *pitch = out_pitch;
469 if (pixelformat == SH_MOBILE_MERAM_PF_NV) 485 if (pixelformat == SH_MOBILE_MERAM_PF_NV)
470 meram_init(priv, &cfg->icb[1], xres, (yres + 1) / 2, 486 meram_init(priv, &cache->planes[1], xres, (yres + 1) / 2,
471 &out_pitch); 487 &out_pitch);
472 else if (pixelformat == SH_MOBILE_MERAM_PF_NV24) 488 else if (pixelformat == SH_MOBILE_MERAM_PF_NV24)
473 meram_init(priv, &cfg->icb[1], 2 * xres, (yres + 1) / 2, 489 meram_init(priv, &cache->planes[1], 2 * xres, (yres + 1) / 2,
474 &out_pitch); 490 &out_pitch);
475 491
476 cfg->current_reg = 1;
477 meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
478 meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c);
479
480 dev_dbg(&pdev->dev, "registered - can access via y=%08lx, c=%08lx",
481 *icb_addr_y, *icb_addr_c);
482
483err: 492err:
484 mutex_unlock(&priv->lock); 493 mutex_unlock(&priv->lock);
485 return error; 494 return cache;
486} 495}
487 496
488static int sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata, 497static void
489 struct sh_mobile_meram_cfg *cfg) 498sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata, void *data)
490{ 499{
491 struct sh_mobile_meram_priv *priv; 500 struct sh_mobile_meram_fb_cache *cache = data;
492 501 struct sh_mobile_meram_priv *priv = pdata->priv;
493 if (!pdata || !pdata->priv || !cfg)
494 return -EINVAL;
495
496 priv = pdata->priv;
497 502
498 mutex_lock(&priv->lock); 503 mutex_lock(&priv->lock);
499 504
500 /* deinit & unmark */ 505 /* deinit & free */
501 if (is_nvcolor(cfg->pixelformat)) { 506 meram_deinit(priv, &cache->planes[0]);
502 meram_deinit(priv, &cfg->icb[1]); 507 if (cache->nplanes == 2)
503 meram_unmark(priv, &cfg->icb[1]); 508 meram_deinit(priv, &cache->planes[1]);
504 }
505 meram_deinit(priv, &cfg->icb[0]);
506 meram_unmark(priv, &cfg->icb[0]);
507 509
508 mutex_unlock(&priv->lock); 510 meram_free(priv, cache);
509 511
510 return 0; 512 mutex_unlock(&priv->lock);
511} 513}
512 514
513static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, 515static void
514 struct sh_mobile_meram_cfg *cfg, 516sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data,
515 unsigned long base_addr_y, 517 unsigned long base_addr_y, unsigned long base_addr_c,
516 unsigned long base_addr_c, 518 unsigned long *icb_addr_y, unsigned long *icb_addr_c)
517 unsigned long *icb_addr_y,
518 unsigned long *icb_addr_c)
519{ 519{
520 struct sh_mobile_meram_priv *priv; 520 struct sh_mobile_meram_fb_cache *cache = data;
521 521 struct sh_mobile_meram_priv *priv = pdata->priv;
522 if (!pdata || !pdata->priv || !cfg)
523 return -EINVAL;
524
525 priv = pdata->priv;
526 522
527 mutex_lock(&priv->lock); 523 mutex_lock(&priv->lock);
528 524
529 meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c); 525 meram_set_next_addr(priv, cache, base_addr_y, base_addr_c);
530 meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c); 526 meram_get_next_icb_addr(pdata, cache, icb_addr_y, icb_addr_c);
531 527
532 mutex_unlock(&priv->lock); 528 mutex_unlock(&priv->lock);
533
534 return 0;
535} 529}
536 530
537static int sh_mobile_meram_runtime_suspend(struct device *dev) 531static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
532 .module = THIS_MODULE,
533 .meram_register = sh_mobile_meram_register,
534 .meram_unregister = sh_mobile_meram_unregister,
535 .meram_update = sh_mobile_meram_update,
536};
537
538/* -----------------------------------------------------------------------------
539 * Power management
540 */
541
542static int sh_mobile_meram_suspend(struct device *dev)
538{ 543{
539 struct platform_device *pdev = to_platform_device(dev); 544 struct platform_device *pdev = to_platform_device(dev);
540 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); 545 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
541 int k, j; 546 unsigned int i, j;
542 547
543 for (k = 0; k < CMN_REGS_SIZE; k++) 548 for (i = 0; i < MERAM_REGS_SIZE; i++)
544 priv->cmn_saved_regs[k] = meram_read_reg(priv->base, 549 priv->regs[i] = meram_read_reg(priv->base, common_regs[i]);
545 common_regs[k]);
546 550
547 for (j = 0; j < 32; j++) { 551 for (i = 0; i < 32; i++) {
548 if (!test_bit(j, &priv->used_icb)) 552 if (!test_bit(i, &priv->used_icb))
549 continue; 553 continue;
550 for (k = 0; k < ICB_REGS_SIZE; k++) { 554 for (j = 0; j < ICB_REGS_SIZE; j++) {
551 priv->icb_saved_regs[j * ICB_REGS_SIZE + k] = 555 priv->icbs[i].regs[j] =
552 meram_read_icb(priv->base, j, icb_regs[k]); 556 meram_read_icb(priv->base, i, icb_regs[j]);
553 /* Reset ICB on resume */ 557 /* Reset ICB on resume */
554 if (icb_regs[k] == MExxCTL) 558 if (icb_regs[j] == MExxCTL)
555 priv->icb_saved_regs[j * ICB_REGS_SIZE + k] |= 559 priv->icbs[i].regs[j] |=
556 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF; 560 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF;
557 } 561 }
558 } 562 }
559 return 0; 563 return 0;
560} 564}
561 565
562static int sh_mobile_meram_runtime_resume(struct device *dev) 566static int sh_mobile_meram_resume(struct device *dev)
563{ 567{
564 struct platform_device *pdev = to_platform_device(dev); 568 struct platform_device *pdev = to_platform_device(dev);
565 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); 569 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
566 int k, j; 570 unsigned int i, j;
567 571
568 for (j = 0; j < 32; j++) { 572 for (i = 0; i < 32; i++) {
569 if (!test_bit(j, &priv->used_icb)) 573 if (!test_bit(i, &priv->used_icb))
570 continue; 574 continue;
571 for (k = 0; k < ICB_REGS_SIZE; k++) { 575 for (j = 0; j < ICB_REGS_SIZE; j++)
572 meram_write_icb(priv->base, j, icb_regs[k], 576 meram_write_icb(priv->base, i, icb_regs[j],
573 priv->icb_saved_regs[j * ICB_REGS_SIZE + k]); 577 priv->icbs[i].regs[j]);
574 }
575 } 578 }
576 579
577 for (k = 0; k < CMN_REGS_SIZE; k++) 580 for (i = 0; i < MERAM_REGS_SIZE; i++)
578 meram_write_reg(priv->base, common_regs[k], 581 meram_write_reg(priv->base, common_regs[i], priv->regs[i]);
579 priv->cmn_saved_regs[k]);
580 return 0; 582 return 0;
581} 583}
582 584
583static const struct dev_pm_ops sh_mobile_meram_dev_pm_ops = { 585static UNIVERSAL_DEV_PM_OPS(sh_mobile_meram_dev_pm_ops,
584 .runtime_suspend = sh_mobile_meram_runtime_suspend, 586 sh_mobile_meram_suspend,
585 .runtime_resume = sh_mobile_meram_runtime_resume, 587 sh_mobile_meram_resume, NULL);
586};
587
588static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
589 .module = THIS_MODULE,
590 .meram_register = sh_mobile_meram_register,
591 .meram_unregister = sh_mobile_meram_unregister,
592 .meram_update = sh_mobile_meram_update,
593};
594 588
595/* 589/* -----------------------------------------------------------------------------
596 * initialize MERAM 590 * Probe/remove and driver init/exit
597 */ 591 */
598 592
599static int sh_mobile_meram_remove(struct platform_device *pdev);
600
601static int __devinit sh_mobile_meram_probe(struct platform_device *pdev) 593static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
602{ 594{
603 struct sh_mobile_meram_priv *priv; 595 struct sh_mobile_meram_priv *priv;
604 struct sh_mobile_meram_info *pdata = pdev->dev.platform_data; 596 struct sh_mobile_meram_info *pdata = pdev->dev.platform_data;
605 struct resource *res; 597 struct resource *regs;
598 struct resource *meram;
599 unsigned int i;
606 int error; 600 int error;
607 601
608 if (!pdata) { 602 if (!pdata) {
@@ -610,8 +604,9 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
610 return -EINVAL; 604 return -EINVAL;
611 } 605 }
612 606
613 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 607 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
614 if (!res) { 608 meram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
609 if (regs == NULL || meram == NULL) {
615 dev_err(&pdev->dev, "cannot get platform resources\n"); 610 dev_err(&pdev->dev, "cannot get platform resources\n");
616 return -ENOENT; 611 return -ENOENT;
617 } 612 }
@@ -622,32 +617,74 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
622 return -ENOMEM; 617 return -ENOMEM;
623 } 618 }
624 619
625 platform_set_drvdata(pdev, priv); 620 /* Initialize private data. */
626
627 /* initialize private data */
628 mutex_init(&priv->lock); 621 mutex_init(&priv->lock);
629 priv->base = ioremap_nocache(res->start, resource_size(res)); 622 priv->used_icb = pdata->reserved_icbs;
623
624 for (i = 0; i < MERAM_ICB_NUM; ++i)
625 priv->icbs[i].index = i;
626
627 pdata->ops = &sh_mobile_meram_ops;
628 pdata->priv = priv;
629 pdata->pdev = pdev;
630
631 /* Request memory regions and remap the registers. */
632 if (!request_mem_region(regs->start, resource_size(regs), pdev->name)) {
633 dev_err(&pdev->dev, "MERAM registers region already claimed\n");
634 error = -EBUSY;
635 goto err_req_regs;
636 }
637
638 if (!request_mem_region(meram->start, resource_size(meram),
639 pdev->name)) {
640 dev_err(&pdev->dev, "MERAM memory region already claimed\n");
641 error = -EBUSY;
642 goto err_req_meram;
643 }
644
645 priv->base = ioremap_nocache(regs->start, resource_size(regs));
630 if (!priv->base) { 646 if (!priv->base) {
631 dev_err(&pdev->dev, "ioremap failed\n"); 647 dev_err(&pdev->dev, "ioremap failed\n");
632 error = -EFAULT; 648 error = -EFAULT;
633 goto err; 649 goto err_ioremap;
634 } 650 }
635 pdata->ops = &sh_mobile_meram_ops; 651
636 pdata->priv = priv; 652 priv->meram = meram->start;
637 pdata->pdev = pdev; 653
654 /* Create and initialize the MERAM memory pool. */
655 priv->pool = gen_pool_create(ilog2(MERAM_GRANULARITY), -1);
656 if (priv->pool == NULL) {
657 error = -ENOMEM;
658 goto err_genpool;
659 }
660
661 error = gen_pool_add(priv->pool, meram->start, resource_size(meram),
662 -1);
663 if (error < 0)
664 goto err_genpool;
638 665
639 /* initialize ICB addressing mode */ 666 /* initialize ICB addressing mode */
640 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1) 667 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1)
641 meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1); 668 meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1);
642 669
670 platform_set_drvdata(pdev, priv);
643 pm_runtime_enable(&pdev->dev); 671 pm_runtime_enable(&pdev->dev);
644 672
645 dev_info(&pdev->dev, "sh_mobile_meram initialized."); 673 dev_info(&pdev->dev, "sh_mobile_meram initialized.");
646 674
647 return 0; 675 return 0;
648 676
649err: 677err_genpool:
650 sh_mobile_meram_remove(pdev); 678 if (priv->pool)
679 gen_pool_destroy(priv->pool);
680 iounmap(priv->base);
681err_ioremap:
682 release_mem_region(meram->start, resource_size(meram));
683err_req_meram:
684 release_mem_region(regs->start, resource_size(regs));
685err_req_regs:
686 mutex_destroy(&priv->lock);
687 kfree(priv);
651 688
652 return error; 689 return error;
653} 690}
@@ -656,11 +693,16 @@ err:
656static int sh_mobile_meram_remove(struct platform_device *pdev) 693static int sh_mobile_meram_remove(struct platform_device *pdev)
657{ 694{
658 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); 695 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
696 struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
697 struct resource *meram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
659 698
660 pm_runtime_disable(&pdev->dev); 699 pm_runtime_disable(&pdev->dev);
661 700
662 if (priv->base) 701 gen_pool_destroy(priv->pool);
663 iounmap(priv->base); 702
703 iounmap(priv->base);
704 release_mem_region(meram->start, resource_size(meram));
705 release_mem_region(regs->start, resource_size(regs));
664 706
665 mutex_destroy(&priv->lock); 707 mutex_destroy(&priv->lock);
666 708
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index a40c05ebbdc2..a159b63e18b9 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -72,6 +72,7 @@ MODULE_DEVICE_TABLE(usb, id_table);
72static bool console = 1; /* Allow fbcon to open framebuffer */ 72static bool console = 1; /* Allow fbcon to open framebuffer */
73static bool fb_defio = 1; /* Detect mmap writes using page faults */ 73static bool fb_defio = 1; /* Detect mmap writes using page faults */
74static bool shadow = 1; /* Optionally disable shadow framebuffer */ 74static bool shadow = 1; /* Optionally disable shadow framebuffer */
75static int pixel_limit; /* Optionally force a pixel resolution limit */
75 76
76/* dlfb keeps a list of urbs for efficient bulk transfers */ 77/* dlfb keeps a list of urbs for efficient bulk transfers */
77static void dlfb_urb_completion(struct urb *urb); 78static void dlfb_urb_completion(struct urb *urb);
@@ -918,10 +919,6 @@ static void dlfb_free(struct kref *kref)
918{ 919{
919 struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref); 920 struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref);
920 921
921 /* this function will wait for all in-flight urbs to complete */
922 if (dev->urbs.count > 0)
923 dlfb_free_urb_list(dev);
924
925 if (dev->backing_buffer) 922 if (dev->backing_buffer)
926 vfree(dev->backing_buffer); 923 vfree(dev->backing_buffer);
927 924
@@ -940,35 +937,42 @@ static void dlfb_release_urb_work(struct work_struct *work)
940 up(&unode->dev->urbs.limit_sem); 937 up(&unode->dev->urbs.limit_sem);
941} 938}
942 939
943static void dlfb_free_framebuffer_work(struct work_struct *work) 940static void dlfb_free_framebuffer(struct dlfb_data *dev)
944{ 941{
945 struct dlfb_data *dev = container_of(work, struct dlfb_data,
946 free_framebuffer_work.work);
947 struct fb_info *info = dev->info; 942 struct fb_info *info = dev->info;
948 int node = info->node;
949 943
950 unregister_framebuffer(info); 944 if (info) {
945 int node = info->node;
951 946
952 if (info->cmap.len != 0) 947 unregister_framebuffer(info);
953 fb_dealloc_cmap(&info->cmap);
954 if (info->monspecs.modedb)
955 fb_destroy_modedb(info->monspecs.modedb);
956 if (info->screen_base)
957 vfree(info->screen_base);
958 948
959 fb_destroy_modelist(&info->modelist); 949 if (info->cmap.len != 0)
950 fb_dealloc_cmap(&info->cmap);
951 if (info->monspecs.modedb)
952 fb_destroy_modedb(info->monspecs.modedb);
953 if (info->screen_base)
954 vfree(info->screen_base);
960 955
961 dev->info = 0; 956 fb_destroy_modelist(&info->modelist);
962 957
963 /* Assume info structure is freed after this point */ 958 dev->info = NULL;
964 framebuffer_release(info);
965 959
966 pr_warn("fb_info for /dev/fb%d has been freed\n", node); 960 /* Assume info structure is freed after this point */
961 framebuffer_release(info);
962
963 pr_warn("fb_info for /dev/fb%d has been freed\n", node);
964 }
967 965
968 /* ref taken in probe() as part of registering framebfufer */ 966 /* ref taken in probe() as part of registering framebfufer */
969 kref_put(&dev->kref, dlfb_free); 967 kref_put(&dev->kref, dlfb_free);
970} 968}
971 969
970static void dlfb_free_framebuffer_work(struct work_struct *work)
971{
972 struct dlfb_data *dev = container_of(work, struct dlfb_data,
973 free_framebuffer_work.work);
974 dlfb_free_framebuffer(dev);
975}
972/* 976/*
973 * Assumes caller is holding info->lock mutex (for open and release at least) 977 * Assumes caller is holding info->lock mutex (for open and release at least)
974 */ 978 */
@@ -1012,7 +1016,8 @@ static int dlfb_is_valid_mode(struct fb_videomode *mode,
1012 return 0; 1016 return 0;
1013 } 1017 }
1014 1018
1015 pr_info("%dx%d valid mode\n", mode->xres, mode->yres); 1019 pr_info("%dx%d @ %d Hz valid mode\n", mode->xres, mode->yres,
1020 mode->refresh);
1016 1021
1017 return 1; 1022 return 1;
1018} 1023}
@@ -1427,19 +1432,22 @@ static ssize_t edid_store(
1427 struct device *fbdev = container_of(kobj, struct device, kobj); 1432 struct device *fbdev = container_of(kobj, struct device, kobj);
1428 struct fb_info *fb_info = dev_get_drvdata(fbdev); 1433 struct fb_info *fb_info = dev_get_drvdata(fbdev);
1429 struct dlfb_data *dev = fb_info->par; 1434 struct dlfb_data *dev = fb_info->par;
1435 int ret;
1430 1436
1431 /* We only support write of entire EDID at once, no offset*/ 1437 /* We only support write of entire EDID at once, no offset*/
1432 if ((src_size != EDID_LENGTH) || (src_off != 0)) 1438 if ((src_size != EDID_LENGTH) || (src_off != 0))
1433 return 0; 1439 return -EINVAL;
1434 1440
1435 dlfb_setup_modes(dev, fb_info, src, src_size); 1441 ret = dlfb_setup_modes(dev, fb_info, src, src_size);
1442 if (ret)
1443 return ret;
1436 1444
1437 if (dev->edid && (memcmp(src, dev->edid, src_size) == 0)) { 1445 if (!dev->edid || memcmp(src, dev->edid, src_size))
1438 pr_info("sysfs written EDID is new default\n"); 1446 return -EINVAL;
1439 dlfb_ops_set_par(fb_info); 1447
1440 return src_size; 1448 pr_info("sysfs written EDID is new default\n");
1441 } else 1449 dlfb_ops_set_par(fb_info);
1442 return 0; 1450 return src_size;
1443} 1451}
1444 1452
1445static ssize_t metrics_reset_store(struct device *fbdev, 1453static ssize_t metrics_reset_store(struct device *fbdev,
@@ -1537,7 +1545,7 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
1537 u8 length; 1545 u8 length;
1538 u16 key; 1546 u16 key;
1539 1547
1540 key = *((u16 *) desc); 1548 key = le16_to_cpu(*((u16 *) desc));
1541 desc += sizeof(u16); 1549 desc += sizeof(u16);
1542 length = *desc; 1550 length = *desc;
1543 desc++; 1551 desc++;
@@ -1570,14 +1578,15 @@ success:
1570 kfree(buf); 1578 kfree(buf);
1571 return true; 1579 return true;
1572} 1580}
1581
1582static void dlfb_init_framebuffer_work(struct work_struct *work);
1583
1573static int dlfb_usb_probe(struct usb_interface *interface, 1584static int dlfb_usb_probe(struct usb_interface *interface,
1574 const struct usb_device_id *id) 1585 const struct usb_device_id *id)
1575{ 1586{
1576 struct usb_device *usbdev; 1587 struct usb_device *usbdev;
1577 struct dlfb_data *dev = 0; 1588 struct dlfb_data *dev = 0;
1578 struct fb_info *info = 0;
1579 int retval = -ENOMEM; 1589 int retval = -ENOMEM;
1580 int i;
1581 1590
1582 /* usb initialization */ 1591 /* usb initialization */
1583 1592
@@ -1589,9 +1598,7 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1589 goto error; 1598 goto error;
1590 } 1599 }
1591 1600
1592 /* we need to wait for both usb and fbdev to spin down on disconnect */
1593 kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */ 1601 kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
1594 kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
1595 1602
1596 dev->udev = usbdev; 1603 dev->udev = usbdev;
1597 dev->gdev = &usbdev->dev; /* our generic struct device * */ 1604 dev->gdev = &usbdev->dev; /* our generic struct device * */
@@ -1613,16 +1620,53 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1613 goto error; 1620 goto error;
1614 } 1621 }
1615 1622
1623 if (pixel_limit) {
1624 pr_warn("DL chip limit of %d overriden"
1625 " by module param to %d\n",
1626 dev->sku_pixel_limit, pixel_limit);
1627 dev->sku_pixel_limit = pixel_limit;
1628 }
1629
1630
1616 if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) { 1631 if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
1617 retval = -ENOMEM; 1632 retval = -ENOMEM;
1618 pr_err("dlfb_alloc_urb_list failed\n"); 1633 pr_err("dlfb_alloc_urb_list failed\n");
1619 goto error; 1634 goto error;
1620 } 1635 }
1621 1636
1637 kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
1638
1622 /* We don't register a new USB class. Our client interface is fbdev */ 1639 /* We don't register a new USB class. Our client interface is fbdev */
1623 1640
1641 /* Workitem keep things fast & simple during USB enumeration */
1642 INIT_DELAYED_WORK(&dev->init_framebuffer_work,
1643 dlfb_init_framebuffer_work);
1644 schedule_delayed_work(&dev->init_framebuffer_work, 0);
1645
1646 return 0;
1647
1648error:
1649 if (dev) {
1650
1651 kref_put(&dev->kref, dlfb_free); /* ref for framebuffer */
1652 kref_put(&dev->kref, dlfb_free); /* last ref from kref_init */
1653
1654 /* dev has been deallocated. Do not dereference */
1655 }
1656
1657 return retval;
1658}
1659
1660static void dlfb_init_framebuffer_work(struct work_struct *work)
1661{
1662 struct dlfb_data *dev = container_of(work, struct dlfb_data,
1663 init_framebuffer_work.work);
1664 struct fb_info *info;
1665 int retval;
1666 int i;
1667
1624 /* allocates framebuffer driver structure, not framebuffer memory */ 1668 /* allocates framebuffer driver structure, not framebuffer memory */
1625 info = framebuffer_alloc(0, &interface->dev); 1669 info = framebuffer_alloc(0, dev->gdev);
1626 if (!info) { 1670 if (!info) {
1627 retval = -ENOMEM; 1671 retval = -ENOMEM;
1628 pr_err("framebuffer_alloc failed\n"); 1672 pr_err("framebuffer_alloc failed\n");
@@ -1668,15 +1712,13 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1668 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) { 1712 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) {
1669 retval = device_create_file(info->dev, &fb_device_attrs[i]); 1713 retval = device_create_file(info->dev, &fb_device_attrs[i]);
1670 if (retval) { 1714 if (retval) {
1671 pr_err("device_create_file failed %d\n", retval); 1715 pr_warn("device_create_file failed %d\n", retval);
1672 goto err_del_attrs;
1673 } 1716 }
1674 } 1717 }
1675 1718
1676 retval = device_create_bin_file(info->dev, &edid_attr); 1719 retval = device_create_bin_file(info->dev, &edid_attr);
1677 if (retval) { 1720 if (retval) {
1678 pr_err("device_create_bin_file failed %d\n", retval); 1721 pr_warn("device_create_bin_file failed %d\n", retval);
1679 goto err_del_attrs;
1680 } 1722 }
1681 1723
1682 pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution." 1724 pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution."
@@ -1684,38 +1726,10 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1684 info->var.xres, info->var.yres, 1726 info->var.xres, info->var.yres,
1685 ((dev->backing_buffer) ? 1727 ((dev->backing_buffer) ?
1686 info->fix.smem_len * 2 : info->fix.smem_len) >> 10); 1728 info->fix.smem_len * 2 : info->fix.smem_len) >> 10);
1687 return 0; 1729 return;
1688
1689err_del_attrs:
1690 for (i -= 1; i >= 0; i--)
1691 device_remove_file(info->dev, &fb_device_attrs[i]);
1692 1730
1693error: 1731error:
1694 if (dev) { 1732 dlfb_free_framebuffer(dev);
1695
1696 if (info) {
1697 if (info->cmap.len != 0)
1698 fb_dealloc_cmap(&info->cmap);
1699 if (info->monspecs.modedb)
1700 fb_destroy_modedb(info->monspecs.modedb);
1701 if (info->screen_base)
1702 vfree(info->screen_base);
1703
1704 fb_destroy_modelist(&info->modelist);
1705
1706 framebuffer_release(info);
1707 }
1708
1709 if (dev->backing_buffer)
1710 vfree(dev->backing_buffer);
1711
1712 kref_put(&dev->kref, dlfb_free); /* ref for framebuffer */
1713 kref_put(&dev->kref, dlfb_free); /* last ref from kref_init */
1714
1715 /* dev has been deallocated. Do not dereference */
1716 }
1717
1718 return retval;
1719} 1733}
1720 1734
1721static void dlfb_usb_disconnect(struct usb_interface *interface) 1735static void dlfb_usb_disconnect(struct usb_interface *interface)
@@ -1735,12 +1749,20 @@ static void dlfb_usb_disconnect(struct usb_interface *interface)
1735 /* When non-active we'll update virtual framebuffer, but no new urbs */ 1749 /* When non-active we'll update virtual framebuffer, but no new urbs */
1736 atomic_set(&dev->usb_active, 0); 1750 atomic_set(&dev->usb_active, 0);
1737 1751
1738 /* remove udlfb's sysfs interfaces */ 1752 /* this function will wait for all in-flight urbs to complete */
1739 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) 1753 dlfb_free_urb_list(dev);
1740 device_remove_file(info->dev, &fb_device_attrs[i]); 1754
1741 device_remove_bin_file(info->dev, &edid_attr); 1755 if (info) {
1742 unlink_framebuffer(info); 1756 /* remove udlfb's sysfs interfaces */
1757 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
1758 device_remove_file(info->dev, &fb_device_attrs[i]);
1759 device_remove_bin_file(info->dev, &edid_attr);
1760 unlink_framebuffer(info);
1761 }
1762
1743 usb_set_intfdata(interface, NULL); 1763 usb_set_intfdata(interface, NULL);
1764 dev->udev = NULL;
1765 dev->gdev = NULL;
1744 1766
1745 /* if clients still have us open, will be freed on last close */ 1767 /* if clients still have us open, will be freed on last close */
1746 if (dev->fb_count == 0) 1768 if (dev->fb_count == 0)
@@ -1806,12 +1828,12 @@ static void dlfb_free_urb_list(struct dlfb_data *dev)
1806 int ret; 1828 int ret;
1807 unsigned long flags; 1829 unsigned long flags;
1808 1830
1809 pr_notice("Waiting for completes and freeing all render urbs\n"); 1831 pr_notice("Freeing all render urbs\n");
1810 1832
1811 /* keep waiting and freeing, until we've got 'em all */ 1833 /* keep waiting and freeing, until we've got 'em all */
1812 while (count--) { 1834 while (count--) {
1813 1835
1814 /* Getting interrupted means a leak, but ok at shutdown*/ 1836 /* Getting interrupted means a leak, but ok at disconnect */
1815 ret = down_interruptible(&dev->urbs.limit_sem); 1837 ret = down_interruptible(&dev->urbs.limit_sem);
1816 if (ret) 1838 if (ret)
1817 break; 1839 break;
@@ -1833,6 +1855,7 @@ static void dlfb_free_urb_list(struct dlfb_data *dev)
1833 kfree(node); 1855 kfree(node);
1834 } 1856 }
1835 1857
1858 dev->urbs.count = 0;
1836} 1859}
1837 1860
1838static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size) 1861static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
@@ -1948,6 +1971,9 @@ MODULE_PARM_DESC(fb_defio, "Page fault detection of mmap writes");
1948module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); 1971module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1949MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf"); 1972MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf");
1950 1973
1974module_param(pixel_limit, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1975MODULE_PARM_DESC(pixel_limit, "Force limit on max mode (in x*y pixels)");
1976
1951MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, " 1977MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, "
1952 "Jaya Kumar <jayakumar.lkml@gmail.com>, " 1978 "Jaya Kumar <jayakumar.lkml@gmail.com>, "
1953 "Bernie Thompson <bernie@plugable.com>"); 1979 "Bernie Thompson <bernie@plugable.com>");
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index e7f69ef572dc..9db3de3a8418 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -362,7 +362,7 @@ static u8 *uvesafb_vbe_state_save(struct uvesafb_par *par)
362 362
363 state = kmalloc(par->vbe_state_size, GFP_KERNEL); 363 state = kmalloc(par->vbe_state_size, GFP_KERNEL);
364 if (!state) 364 if (!state)
365 return NULL; 365 return ERR_PTR(-ENOMEM);
366 366
367 task = uvesafb_prep(); 367 task = uvesafb_prep();
368 if (!task) { 368 if (!task) {
@@ -1172,9 +1172,17 @@ static int uvesafb_open(struct fb_info *info, int user)
1172{ 1172{
1173 struct uvesafb_par *par = info->par; 1173 struct uvesafb_par *par = info->par;
1174 int cnt = atomic_read(&par->ref_count); 1174 int cnt = atomic_read(&par->ref_count);
1175 u8 *buf = NULL;
1175 1176
1176 if (!cnt && par->vbe_state_size) 1177 if (!cnt && par->vbe_state_size) {
1177 par->vbe_state_orig = uvesafb_vbe_state_save(par); 1178 buf = uvesafb_vbe_state_save(par);
1179 if (IS_ERR(buf)) {
1180 printk(KERN_WARNING "uvesafb: save hardware state"
1181 "failed, error code is %ld!\n", PTR_ERR(buf));
1182 } else {
1183 par->vbe_state_orig = buf;
1184 }
1185 }
1178 1186
1179 atomic_inc(&par->ref_count); 1187 atomic_inc(&par->ref_count);
1180 return 0; 1188 return 0;
diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile
index 5108136e8776..159f26e6adb5 100644
--- a/drivers/video/via/Makefile
+++ b/drivers/video/via/Makefile
@@ -6,4 +6,7 @@ obj-$(CONFIG_FB_VIA) += viafb.o
6 6
7viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \ 7viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \
8 via_utility.o vt1636.o global.o tblDPASetting.o viamode.o \ 8 via_utility.o vt1636.o global.o tblDPASetting.o viamode.o \
9 via-core.o via-gpio.o via_modesetting.o via_clock.o 9 via-core.o via-gpio.o via_modesetting.o via_clock.o \
10 via_aux.o via_aux_edid.o via_aux_vt1636.o via_aux_vt1632.o \
11 via_aux_vt1631.o via_aux_vt1625.o via_aux_vt1622.o via_aux_vt1621.o \
12 via_aux_sii164.o via_aux_ch7301.o
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h
index 3ebf20c06eef..d32a5076c20f 100644
--- a/drivers/video/via/chip.h
+++ b/drivers/video/via/chip.h
@@ -146,9 +146,6 @@ struct tmds_setting_information {
146 146
147struct lvds_setting_information { 147struct lvds_setting_information {
148 int iga_path; 148 int iga_path;
149 int h_active;
150 int v_active;
151 int bpp;
152 int lcd_panel_hres; 149 int lcd_panel_hres;
153 int lcd_panel_vres; 150 int lcd_panel_vres;
154 int display_method; 151 int display_method;
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
index 9138e517267c..6be72f0ba21d 100644
--- a/drivers/video/via/dvi.c
+++ b/drivers/video/via/dvi.c
@@ -172,10 +172,11 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
172} 172}
173 173
174/* DVI Set Mode */ 174/* DVI Set Mode */
175void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga) 175void viafb_dvi_set_mode(const struct fb_var_screeninfo *var,
176 u16 cxres, u16 cyres, int iga)
176{ 177{
177 struct fb_var_screeninfo dvi_var = *var; 178 struct fb_var_screeninfo dvi_var = *var;
178 struct crt_mode_table *rb_mode; 179 const struct fb_videomode *rb_mode;
179 int maxPixelClock; 180 int maxPixelClock;
180 181
181 maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock; 182 maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock;
@@ -185,7 +186,7 @@ void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga)
185 viafb_fill_var_timing_info(&dvi_var, rb_mode); 186 viafb_fill_var_timing_info(&dvi_var, rb_mode);
186 } 187 }
187 188
188 viafb_fill_crtc_timing(&dvi_var, iga); 189 viafb_fill_crtc_timing(&dvi_var, cxres, cyres, iga);
189} 190}
190 191
191/* Sense DVI Connector */ 192/* Sense DVI Connector */
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h
index e2116aaf797a..db757850c216 100644
--- a/drivers/video/via/dvi.h
+++ b/drivers/video/via/dvi.h
@@ -59,6 +59,7 @@ void viafb_dvi_enable(void);
59bool __devinit viafb_tmds_trasmitter_identify(void); 59bool __devinit viafb_tmds_trasmitter_identify(void);
60void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, 60void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
61 struct tmds_setting_information *tmds_setting); 61 struct tmds_setting_information *tmds_setting);
62void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga); 62void viafb_dvi_set_mode(const struct fb_var_screeninfo *var,
63 u16 cxres, u16 cyres, int iga);
63 64
64#endif /* __DVI_H__ */ 65#endif /* __DVI_H__ */
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 8497727d66de..898590db5e14 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -1467,28 +1467,32 @@ void viafb_set_vclock(u32 clk, int set_iga)
1467 via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ 1467 via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
1468} 1468}
1469 1469
1470static struct display_timing var_to_timing(const struct fb_var_screeninfo *var) 1470struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
1471 u16 cxres, u16 cyres)
1471{ 1472{
1472 struct display_timing timing; 1473 struct display_timing timing;
1474 u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2;
1473 1475
1474 timing.hor_addr = var->xres; 1476 timing.hor_addr = cxres;
1475 timing.hor_sync_start = timing.hor_addr + var->right_margin; 1477 timing.hor_sync_start = timing.hor_addr + var->right_margin + dx;
1476 timing.hor_sync_end = timing.hor_sync_start + var->hsync_len; 1478 timing.hor_sync_end = timing.hor_sync_start + var->hsync_len;
1477 timing.hor_total = timing.hor_sync_end + var->left_margin; 1479 timing.hor_total = timing.hor_sync_end + var->left_margin + dx;
1478 timing.hor_blank_start = timing.hor_addr; 1480 timing.hor_blank_start = timing.hor_addr + dx;
1479 timing.hor_blank_end = timing.hor_total; 1481 timing.hor_blank_end = timing.hor_total - dx;
1480 timing.ver_addr = var->yres; 1482 timing.ver_addr = cyres;
1481 timing.ver_sync_start = timing.ver_addr + var->lower_margin; 1483 timing.ver_sync_start = timing.ver_addr + var->lower_margin + dy;
1482 timing.ver_sync_end = timing.ver_sync_start + var->vsync_len; 1484 timing.ver_sync_end = timing.ver_sync_start + var->vsync_len;
1483 timing.ver_total = timing.ver_sync_end + var->upper_margin; 1485 timing.ver_total = timing.ver_sync_end + var->upper_margin + dy;
1484 timing.ver_blank_start = timing.ver_addr; 1486 timing.ver_blank_start = timing.ver_addr + dy;
1485 timing.ver_blank_end = timing.ver_total; 1487 timing.ver_blank_end = timing.ver_total - dy;
1486 return timing; 1488 return timing;
1487} 1489}
1488 1490
1489void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga) 1491void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
1492 u16 cxres, u16 cyres, int iga)
1490{ 1493{
1491 struct display_timing crt_reg = var_to_timing(var); 1494 struct display_timing crt_reg = var_to_timing(var,
1495 cxres ? cxres : var->xres, cyres ? cyres : var->yres);
1492 1496
1493 if (iga == IGA1) 1497 if (iga == IGA1)
1494 via_set_primary_timing(&crt_reg); 1498 via_set_primary_timing(&crt_reg);
@@ -1526,13 +1530,6 @@ void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
1526 if (flag == 0) { 1530 if (flag == 0) {
1527 viaparinfo->tmds_setting_info->h_active = hres; 1531 viaparinfo->tmds_setting_info->h_active = hres;
1528 viaparinfo->tmds_setting_info->v_active = vres; 1532 viaparinfo->tmds_setting_info->v_active = vres;
1529
1530 viaparinfo->lvds_setting_info->h_active = hres;
1531 viaparinfo->lvds_setting_info->v_active = vres;
1532 viaparinfo->lvds_setting_info->bpp = bpp;
1533 viaparinfo->lvds_setting_info2->h_active = hres;
1534 viaparinfo->lvds_setting_info2->v_active = vres;
1535 viaparinfo->lvds_setting_info2->bpp = bpp;
1536 } else { 1533 } else {
1537 1534
1538 if (viaparinfo->tmds_setting_info->iga_path == IGA2) { 1535 if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
@@ -1540,16 +1537,6 @@ void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
1540 viaparinfo->tmds_setting_info->v_active = vres; 1537 viaparinfo->tmds_setting_info->v_active = vres;
1541 } 1538 }
1542 1539
1543 if (viaparinfo->lvds_setting_info->iga_path == IGA2) {
1544 viaparinfo->lvds_setting_info->h_active = hres;
1545 viaparinfo->lvds_setting_info->v_active = vres;
1546 viaparinfo->lvds_setting_info->bpp = bpp;
1547 }
1548 if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) {
1549 viaparinfo->lvds_setting_info2->h_active = hres;
1550 viaparinfo->lvds_setting_info2->v_active = vres;
1551 viaparinfo->lvds_setting_info2->bpp = bpp;
1552 }
1553 } 1540 }
1554} 1541}
1555 1542
@@ -1758,13 +1745,13 @@ static void set_display_channel(void)
1758 } 1745 }
1759} 1746}
1760 1747
1761static u8 get_sync(struct fb_info *info) 1748static u8 get_sync(struct fb_var_screeninfo *var)
1762{ 1749{
1763 u8 polarity = 0; 1750 u8 polarity = 0;
1764 1751
1765 if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) 1752 if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
1766 polarity |= VIA_HSYNC_NEGATIVE; 1753 polarity |= VIA_HSYNC_NEGATIVE;
1767 if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) 1754 if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
1768 polarity |= VIA_VSYNC_NEGATIVE; 1755 polarity |= VIA_VSYNC_NEGATIVE;
1769 return polarity; 1756 return polarity;
1770} 1757}
@@ -1844,9 +1831,9 @@ static void hw_init(void)
1844 load_fix_bit_crtc_reg(); 1831 load_fix_bit_crtc_reg();
1845} 1832}
1846 1833
1847int viafb_setmode(int video_bpp, int video_bpp1) 1834int viafb_setmode(void)
1848{ 1835{
1849 int j; 1836 int j, cxres = 0, cyres = 0;
1850 int port; 1837 int port;
1851 u32 devices = viaparinfo->shared->iga1_devices 1838 u32 devices = viaparinfo->shared->iga1_devices
1852 | viaparinfo->shared->iga2_devices; 1839 | viaparinfo->shared->iga2_devices;
@@ -1895,6 +1882,8 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1895 } else if (viafb_SAMM_ON) { 1882 } else if (viafb_SAMM_ON) {
1896 viafb_fill_var_timing_info(&var2, viafb_get_best_mode( 1883 viafb_fill_var_timing_info(&var2, viafb_get_best_mode(
1897 viafb_second_xres, viafb_second_yres, viafb_refresh1)); 1884 viafb_second_xres, viafb_second_yres, viafb_refresh1));
1885 cxres = viafbinfo->var.xres;
1886 cyres = viafbinfo->var.yres;
1898 var2.bits_per_pixel = viafbinfo->var.bits_per_pixel; 1887 var2.bits_per_pixel = viafbinfo->var.bits_per_pixel;
1899 } 1888 }
1900 1889
@@ -1902,9 +1891,9 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1902 if (viafb_CRT_ON) { 1891 if (viafb_CRT_ON) {
1903 if (viaparinfo->shared->iga2_devices & VIA_CRT 1892 if (viaparinfo->shared->iga2_devices & VIA_CRT
1904 && viafb_SAMM_ON) 1893 && viafb_SAMM_ON)
1905 viafb_fill_crtc_timing(&var2, IGA2); 1894 viafb_fill_crtc_timing(&var2, cxres, cyres, IGA2);
1906 else 1895 else
1907 viafb_fill_crtc_timing(&viafbinfo->var, 1896 viafb_fill_crtc_timing(&viafbinfo->var, 0, 0,
1908 (viaparinfo->shared->iga1_devices & VIA_CRT) 1897 (viaparinfo->shared->iga1_devices & VIA_CRT)
1909 ? IGA1 : IGA2); 1898 ? IGA1 : IGA2);
1910 1899
@@ -1922,17 +1911,17 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1922 if (viafb_DVI_ON) { 1911 if (viafb_DVI_ON) {
1923 if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2 1912 if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2
1924 && viafb_SAMM_ON) 1913 && viafb_SAMM_ON)
1925 viafb_dvi_set_mode(&var2, IGA2); 1914 viafb_dvi_set_mode(&var2, cxres, cyres, IGA2);
1926 else 1915 else
1927 viafb_dvi_set_mode(&viafbinfo->var, 1916 viafb_dvi_set_mode(&viafbinfo->var, 0, 0,
1928 viaparinfo->tmds_setting_info->iga_path); 1917 viaparinfo->tmds_setting_info->iga_path);
1929 } 1918 }
1930 1919
1931 if (viafb_LCD_ON) { 1920 if (viafb_LCD_ON) {
1932 if (viafb_SAMM_ON && 1921 if (viafb_SAMM_ON &&
1933 (viaparinfo->lvds_setting_info->iga_path == IGA2)) { 1922 (viaparinfo->lvds_setting_info->iga_path == IGA2)) {
1934 viaparinfo->lvds_setting_info->bpp = video_bpp1; 1923 viafb_lcd_set_mode(&var2, cxres, cyres,
1935 viafb_lcd_set_mode(viaparinfo->lvds_setting_info, 1924 viaparinfo->lvds_setting_info,
1936 &viaparinfo->chip_info->lvds_chip_info); 1925 &viaparinfo->chip_info->lvds_chip_info);
1937 } else { 1926 } else {
1938 /* IGA1 doesn't have LCD scaling, so set it center. */ 1927 /* IGA1 doesn't have LCD scaling, so set it center. */
@@ -1940,16 +1929,16 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1940 viaparinfo->lvds_setting_info->display_method = 1929 viaparinfo->lvds_setting_info->display_method =
1941 LCD_CENTERING; 1930 LCD_CENTERING;
1942 } 1931 }
1943 viaparinfo->lvds_setting_info->bpp = video_bpp; 1932 viafb_lcd_set_mode(&viafbinfo->var, 0, 0,
1944 viafb_lcd_set_mode(viaparinfo->lvds_setting_info, 1933 viaparinfo->lvds_setting_info,
1945 &viaparinfo->chip_info->lvds_chip_info); 1934 &viaparinfo->chip_info->lvds_chip_info);
1946 } 1935 }
1947 } 1936 }
1948 if (viafb_LCD2_ON) { 1937 if (viafb_LCD2_ON) {
1949 if (viafb_SAMM_ON && 1938 if (viafb_SAMM_ON &&
1950 (viaparinfo->lvds_setting_info2->iga_path == IGA2)) { 1939 (viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
1951 viaparinfo->lvds_setting_info2->bpp = video_bpp1; 1940 viafb_lcd_set_mode(&var2, cxres, cyres,
1952 viafb_lcd_set_mode(viaparinfo->lvds_setting_info2, 1941 viaparinfo->lvds_setting_info2,
1953 &viaparinfo->chip_info->lvds_chip_info2); 1942 &viaparinfo->chip_info->lvds_chip_info2);
1954 } else { 1943 } else {
1955 /* IGA1 doesn't have LCD scaling, so set it center. */ 1944 /* IGA1 doesn't have LCD scaling, so set it center. */
@@ -1957,8 +1946,8 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1957 viaparinfo->lvds_setting_info2->display_method = 1946 viaparinfo->lvds_setting_info2->display_method =
1958 LCD_CENTERING; 1947 LCD_CENTERING;
1959 } 1948 }
1960 viaparinfo->lvds_setting_info2->bpp = video_bpp; 1949 viafb_lcd_set_mode(&viafbinfo->var, 0, 0,
1961 viafb_lcd_set_mode(viaparinfo->lvds_setting_info2, 1950 viaparinfo->lvds_setting_info2,
1962 &viaparinfo->chip_info->lvds_chip_info2); 1951 &viaparinfo->chip_info->lvds_chip_info2);
1963 } 1952 }
1964 } 1953 }
@@ -1971,7 +1960,7 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1971 if (!viafb_hotplug) { 1960 if (!viafb_hotplug) {
1972 viafb_hotplug_Xres = viafbinfo->var.xres; 1961 viafb_hotplug_Xres = viafbinfo->var.xres;
1973 viafb_hotplug_Yres = viafbinfo->var.yres; 1962 viafb_hotplug_Yres = viafbinfo->var.yres;
1974 viafb_hotplug_bpp = video_bpp; 1963 viafb_hotplug_bpp = viafbinfo->var.bits_per_pixel;
1975 viafb_hotplug_refresh = viafb_refresh; 1964 viafb_hotplug_refresh = viafb_refresh;
1976 1965
1977 if (viafb_DVI_ON) 1966 if (viafb_DVI_ON)
@@ -1980,13 +1969,13 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1980 viafb_DeviceStatus = CRT_Device; 1969 viafb_DeviceStatus = CRT_Device;
1981 } 1970 }
1982 device_on(); 1971 device_on();
1983 if (!viafb_dual_fb) 1972 if (!viafb_SAMM_ON)
1984 via_set_sync_polarity(devices, get_sync(viafbinfo)); 1973 via_set_sync_polarity(devices, get_sync(&viafbinfo->var));
1985 else { 1974 else {
1986 via_set_sync_polarity(viaparinfo->shared->iga1_devices, 1975 via_set_sync_polarity(viaparinfo->shared->iga1_devices,
1987 get_sync(viafbinfo)); 1976 get_sync(&viafbinfo->var));
1988 via_set_sync_polarity(viaparinfo->shared->iga2_devices, 1977 via_set_sync_polarity(viaparinfo->shared->iga2_devices,
1989 get_sync(viafbinfo1)); 1978 get_sync(&var2));
1990 } 1979 }
1991 1980
1992 clock.set_engine_pll_state(VIA_STATE_ON); 1981 clock.set_engine_pll_state(VIA_STATE_ON);
@@ -2023,20 +2012,20 @@ int viafb_setmode(int video_bpp, int video_bpp1)
2023 2012
2024int viafb_get_refresh(int hres, int vres, u32 long_refresh) 2013int viafb_get_refresh(int hres, int vres, u32 long_refresh)
2025{ 2014{
2026 struct crt_mode_table *best; 2015 const struct fb_videomode *best;
2027 2016
2028 best = viafb_get_best_mode(hres, vres, long_refresh); 2017 best = viafb_get_best_mode(hres, vres, long_refresh);
2029 if (!best) 2018 if (!best)
2030 return 60; 2019 return 60;
2031 2020
2032 if (abs(best->refresh_rate - long_refresh) > 3) { 2021 if (abs(best->refresh - long_refresh) > 3) {
2033 if (hres == 1200 && vres == 900) 2022 if (hres == 1200 && vres == 900)
2034 return 49; /* OLPC DCON only supports 50 Hz */ 2023 return 49; /* OLPC DCON only supports 50 Hz */
2035 else 2024 else
2036 return 60; 2025 return 60;
2037 } 2026 }
2038 2027
2039 return best->refresh_rate; 2028 return best->refresh;
2040} 2029}
2041 2030
2042static void device_off(void) 2031static void device_off(void)
@@ -2129,26 +2118,17 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
2129 } 2118 }
2130} 2119}
2131 2120
2132/*According var's xres, yres fill var's other timing information*/
2133void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, 2121void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
2134 struct crt_mode_table *mode) 2122 const struct fb_videomode *mode)
2135{ 2123{
2136 struct display_timing crt_reg; 2124 var->pixclock = mode->pixclock;
2137 2125 var->xres = mode->xres;
2138 crt_reg = mode->crtc; 2126 var->yres = mode->yres;
2139 var->pixclock = 1000000000 / (crt_reg.hor_total * crt_reg.ver_total) 2127 var->left_margin = mode->left_margin;
2140 * 1000 / mode->refresh_rate; 2128 var->right_margin = mode->right_margin;
2141 var->left_margin = 2129 var->hsync_len = mode->hsync_len;
2142 crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); 2130 var->upper_margin = mode->upper_margin;
2143 var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr; 2131 var->lower_margin = mode->lower_margin;
2144 var->hsync_len = crt_reg.hor_sync_end; 2132 var->vsync_len = mode->vsync_len;
2145 var->upper_margin = 2133 var->sync = mode->sync;
2146 crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end);
2147 var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
2148 var->vsync_len = crt_reg.ver_sync_end;
2149 var->sync = 0;
2150 if (mode->h_sync_polarity == POSITIVE)
2151 var->sync |= FB_SYNC_HOR_HIGH_ACT;
2152 if (mode->v_sync_polarity == POSITIVE)
2153 var->sync |= FB_SYNC_VERT_HIGH_ACT;
2154} 2134}
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 4db5b6e8d8d0..6be243cfc823 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -637,7 +637,10 @@ extern int viafb_LCD_ON;
637extern int viafb_DVI_ON; 637extern int viafb_DVI_ON;
638extern int viafb_hotplug; 638extern int viafb_hotplug;
639 639
640void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga); 640struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
641 u16 cxres, u16 cyres);
642void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
643 u16 cxres, u16 cyres, int iga);
641void viafb_set_vclock(u32 CLK, int set_iga); 644void viafb_set_vclock(u32 CLK, int set_iga);
642void viafb_load_reg(int timing_value, int viafb_load_reg_num, 645void viafb_load_reg(int timing_value, int viafb_load_reg_num,
643 struct io_register *reg, 646 struct io_register *reg,
@@ -657,9 +660,9 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
657void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ 660void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
658 *p_gfx_dpa_setting); 661 *p_gfx_dpa_setting);
659 662
660int viafb_setmode(int video_bpp, int video_bpp1); 663int viafb_setmode(void);
661void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, 664void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
662 struct crt_mode_table *mode); 665 const struct fb_videomode *mode);
663void __devinit viafb_init_chip_info(int chip_type); 666void __devinit viafb_init_chip_info(int chip_type);
664void __devinit viafb_init_dac(int set_iga); 667void __devinit viafb_init_dac(int set_iga);
665int viafb_get_refresh(int hres, int vres, u32 float_refresh); 668int viafb_get_refresh(int hres, int vres, u32 float_refresh);
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index 5f3b4e394e82..165037910536 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -53,10 +53,6 @@ static void __devinit fp_id_to_vindex(int panel_id);
53static int lvds_register_read(int index); 53static int lvds_register_read(int index);
54static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, 54static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
55 int panel_vres); 55 int panel_vres);
56static void via_pitch_alignment_patch_lcd(
57 struct lvds_setting_information *plvds_setting_info,
58 struct lvds_chip_information
59 *plvds_chip_info);
60static void lcd_patch_skew_dvp0(struct lvds_setting_information 56static void lcd_patch_skew_dvp0(struct lvds_setting_information
61 *plvds_setting_info, 57 *plvds_setting_info,
62 struct lvds_chip_information *plvds_chip_info); 58 struct lvds_chip_information *plvds_chip_info);
@@ -79,9 +75,6 @@ static void check_diport_of_integrated_lvds(
79 struct lvds_chip_information *plvds_chip_info, 75 struct lvds_chip_information *plvds_chip_info,
80 struct lvds_setting_information 76 struct lvds_setting_information
81 *plvds_setting_info); 77 *plvds_setting_info);
82static struct display_timing lcd_centering_timging(struct display_timing
83 mode_crt_reg,
84 struct display_timing panel_crt_reg);
85 78
86static inline bool check_lvds_chip(int device_id_subaddr, int device_id) 79static inline bool check_lvds_chip(int device_id_subaddr, int device_id)
87{ 80{
@@ -454,20 +447,17 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
454 } 447 }
455} 448}
456 449
457static void via_pitch_alignment_patch_lcd( 450static void via_pitch_alignment_patch_lcd(int iga_path, int hres, int bpp)
458 struct lvds_setting_information *plvds_setting_info,
459 struct lvds_chip_information
460 *plvds_chip_info)
461{ 451{
462 unsigned char cr13, cr35, cr65, cr66, cr67; 452 unsigned char cr13, cr35, cr65, cr66, cr67;
463 unsigned long dwScreenPitch = 0; 453 unsigned long dwScreenPitch = 0;
464 unsigned long dwPitch; 454 unsigned long dwPitch;
465 455
466 dwPitch = plvds_setting_info->h_active * (plvds_setting_info->bpp >> 3); 456 dwPitch = hres * (bpp >> 3);
467 if (dwPitch & 0x1F) { 457 if (dwPitch & 0x1F) {
468 dwScreenPitch = ((dwPitch + 31) & ~31) >> 3; 458 dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
469 if (plvds_setting_info->iga_path == IGA2) { 459 if (iga_path == IGA2) {
470 if (plvds_setting_info->bpp > 8) { 460 if (bpp > 8) {
471 cr66 = (unsigned char)(dwScreenPitch & 0xFF); 461 cr66 = (unsigned char)(dwScreenPitch & 0xFF);
472 viafb_write_reg(CR66, VIACR, cr66); 462 viafb_write_reg(CR66, VIACR, cr66);
473 cr67 = viafb_read_reg(VIACR, CR67) & 0xFC; 463 cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
@@ -485,7 +475,7 @@ static void via_pitch_alignment_patch_lcd(
485 cr65 += 2; 475 cr65 += 2;
486 viafb_write_reg(CR65, VIACR, cr65); 476 viafb_write_reg(CR65, VIACR, cr65);
487 } else { 477 } else {
488 if (plvds_setting_info->bpp > 8) { 478 if (bpp > 8) {
489 cr13 = (unsigned char)(dwScreenPitch & 0xFF); 479 cr13 = (unsigned char)(dwScreenPitch & 0xFF);
490 viafb_write_reg(CR13, VIACR, cr13); 480 viafb_write_reg(CR13, VIACR, cr13);
491 cr35 = viafb_read_reg(VIACR, CR35) & 0x1F; 481 cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
@@ -548,49 +538,45 @@ static void lcd_patch_skew(struct lvds_setting_information
548} 538}
549 539
550/* LCD Set Mode */ 540/* LCD Set Mode */
551void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info, 541void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
542 u16 cyres, struct lvds_setting_information *plvds_setting_info,
552 struct lvds_chip_information *plvds_chip_info) 543 struct lvds_chip_information *plvds_chip_info)
553{ 544{
554 int set_iga = plvds_setting_info->iga_path; 545 int set_iga = plvds_setting_info->iga_path;
555 int mode_bpp = plvds_setting_info->bpp; 546 int mode_bpp = var->bits_per_pixel;
556 int set_hres = plvds_setting_info->h_active; 547 int set_hres = cxres ? cxres : var->xres;
557 int set_vres = plvds_setting_info->v_active; 548 int set_vres = cyres ? cyres : var->yres;
558 int panel_hres = plvds_setting_info->lcd_panel_hres; 549 int panel_hres = plvds_setting_info->lcd_panel_hres;
559 int panel_vres = plvds_setting_info->lcd_panel_vres; 550 int panel_vres = plvds_setting_info->lcd_panel_vres;
560 u32 clock; 551 u32 clock;
561 struct display_timing mode_crt_reg, panel_crt_reg, timing; 552 struct display_timing timing;
562 struct crt_mode_table *mode_crt_table, *panel_crt_table; 553 struct fb_var_screeninfo panel_var;
554 const struct fb_videomode *mode_crt_table, *panel_crt_table;
563 555
564 DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); 556 DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
565 /* Get mode table */ 557 /* Get mode table */
566 mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60); 558 mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60);
567 mode_crt_reg = mode_crt_table->crtc;
568 /* Get panel table Pointer */ 559 /* Get panel table Pointer */
569 panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60); 560 panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60);
570 panel_crt_reg = panel_crt_table->crtc; 561 viafb_fill_var_timing_info(&panel_var, panel_crt_table);
571 DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); 562 DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
572 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) 563 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
573 viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info); 564 viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
574 clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total 565 clock = PICOS2KHZ(panel_crt_table->pixclock) * 1000;
575 * panel_crt_table->refresh_rate;
576 plvds_setting_info->vclk = clock; 566 plvds_setting_info->vclk = clock;
577 567
578 if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres) 568 if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres)
579 && plvds_setting_info->display_method == LCD_EXPANDSION) { 569 && plvds_setting_info->display_method == LCD_EXPANDSION) {
580 timing = panel_crt_reg; 570 timing = var_to_timing(&panel_var, panel_hres, panel_vres);
581 load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres); 571 load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres);
582 } else { 572 } else {
583 timing = lcd_centering_timging(mode_crt_reg, panel_crt_reg); 573 timing = var_to_timing(&panel_var, set_hres, set_vres);
584 if (set_iga == IGA2) 574 if (set_iga == IGA2)
585 /* disable scaling */ 575 /* disable scaling */
586 via_write_reg_mask(VIACR, 0x79, 0x00, 576 via_write_reg_mask(VIACR, 0x79, 0x00,
587 BIT0 + BIT1 + BIT2); 577 BIT0 + BIT1 + BIT2);
588 } 578 }
589 579
590 timing.hor_blank_end += timing.hor_blank_start;
591 timing.hor_sync_end += timing.hor_sync_start;
592 timing.ver_blank_end += timing.ver_blank_start;
593 timing.ver_sync_end += timing.ver_sync_start;
594 if (set_iga == IGA1) 580 if (set_iga == IGA1)
595 via_set_primary_timing(&timing); 581 via_set_primary_timing(&timing);
596 else if (set_iga == IGA2) 582 else if (set_iga == IGA2)
@@ -613,7 +599,8 @@ void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info,
613 viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0); 599 viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
614 600
615 /* Patch for non 32bit alignment mode */ 601 /* Patch for non 32bit alignment mode */
616 via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info); 602 via_pitch_alignment_patch_lcd(plvds_setting_info->iga_path, set_hres,
603 var->bits_per_pixel);
617} 604}
618 605
619static void integrated_lvds_disable(struct lvds_setting_information 606static void integrated_lvds_disable(struct lvds_setting_information
@@ -973,37 +960,6 @@ void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information
973 } 960 }
974} 961}
975 962
976static struct display_timing lcd_centering_timging(struct display_timing
977 mode_crt_reg,
978 struct display_timing panel_crt_reg)
979{
980 struct display_timing crt_reg;
981
982 crt_reg.hor_total = panel_crt_reg.hor_total;
983 crt_reg.hor_addr = mode_crt_reg.hor_addr;
984 crt_reg.hor_blank_start =
985 (panel_crt_reg.hor_addr - mode_crt_reg.hor_addr) / 2 +
986 crt_reg.hor_addr;
987 crt_reg.hor_blank_end = panel_crt_reg.hor_blank_end;
988 crt_reg.hor_sync_start =
989 (panel_crt_reg.hor_sync_start -
990 panel_crt_reg.hor_blank_start) + crt_reg.hor_blank_start;
991 crt_reg.hor_sync_end = panel_crt_reg.hor_sync_end;
992
993 crt_reg.ver_total = panel_crt_reg.ver_total;
994 crt_reg.ver_addr = mode_crt_reg.ver_addr;
995 crt_reg.ver_blank_start =
996 (panel_crt_reg.ver_addr - mode_crt_reg.ver_addr) / 2 +
997 crt_reg.ver_addr;
998 crt_reg.ver_blank_end = panel_crt_reg.ver_blank_end;
999 crt_reg.ver_sync_start =
1000 (panel_crt_reg.ver_sync_start -
1001 panel_crt_reg.ver_blank_start) + crt_reg.ver_blank_start;
1002 crt_reg.ver_sync_end = panel_crt_reg.ver_sync_end;
1003
1004 return crt_reg;
1005}
1006
1007bool viafb_lcd_get_mobile_state(bool *mobile) 963bool viafb_lcd_get_mobile_state(bool *mobile)
1008{ 964{
1009 unsigned char __iomem *romptr, *tableptr, *biosptr; 965 unsigned char __iomem *romptr, *tableptr, *biosptr;
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h
index 77ca7b862e68..8f3e4e06156c 100644
--- a/drivers/video/via/lcd.h
+++ b/drivers/video/via/lcd.h
@@ -76,7 +76,8 @@ void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information
76 *plvds_chip_info, 76 *plvds_chip_info,
77 struct lvds_setting_information 77 struct lvds_setting_information
78 *plvds_setting_info); 78 *plvds_setting_info);
79void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info, 79void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
80 u16 cyres, struct lvds_setting_information *plvds_setting_info,
80 struct lvds_chip_information *plvds_chip_info); 81 struct lvds_chip_information *plvds_chip_info);
81bool __devinit viafb_lvds_trasmitter_identify(void); 82bool __devinit viafb_lvds_trasmitter_identify(void);
82void viafb_init_lvds_output_interface(struct lvds_chip_information 83void viafb_init_lvds_output_interface(struct lvds_chip_information
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index c01c1c162726..3158dfc90bed 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -283,337 +283,6 @@
283#define HW_LAYOUT_LCD1_LCD2 0x04 283#define HW_LAYOUT_LCD1_LCD2 0x04
284#define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10 284#define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10
285 285
286/* Definition Refresh Rate */
287#define REFRESH_49 49
288#define REFRESH_50 50
289#define REFRESH_60 60
290#define REFRESH_75 75
291#define REFRESH_85 85
292#define REFRESH_100 100
293#define REFRESH_120 120
294
295/* Definition Sync Polarity*/
296#define NEGATIVE 1
297#define POSITIVE 0
298
299/*480x640@60 Sync Polarity (GTF)
300*/
301#define M480X640_R60_HSP NEGATIVE
302#define M480X640_R60_VSP POSITIVE
303
304/*640x480@60 Sync Polarity (VESA Mode)
305*/
306#define M640X480_R60_HSP NEGATIVE
307#define M640X480_R60_VSP NEGATIVE
308
309/*640x480@75 Sync Polarity (VESA Mode)
310*/
311#define M640X480_R75_HSP NEGATIVE
312#define M640X480_R75_VSP NEGATIVE
313
314/*640x480@85 Sync Polarity (VESA Mode)
315*/
316#define M640X480_R85_HSP NEGATIVE
317#define M640X480_R85_VSP NEGATIVE
318
319/*640x480@100 Sync Polarity (GTF Mode)
320*/
321#define M640X480_R100_HSP NEGATIVE
322#define M640X480_R100_VSP POSITIVE
323
324/*640x480@120 Sync Polarity (GTF Mode)
325*/
326#define M640X480_R120_HSP NEGATIVE
327#define M640X480_R120_VSP POSITIVE
328
329/*720x480@60 Sync Polarity (GTF Mode)
330*/
331#define M720X480_R60_HSP NEGATIVE
332#define M720X480_R60_VSP POSITIVE
333
334/*720x576@60 Sync Polarity (GTF Mode)
335*/
336#define M720X576_R60_HSP NEGATIVE
337#define M720X576_R60_VSP POSITIVE
338
339/*800x600@60 Sync Polarity (VESA Mode)
340*/
341#define M800X600_R60_HSP POSITIVE
342#define M800X600_R60_VSP POSITIVE
343
344/*800x600@75 Sync Polarity (VESA Mode)
345*/
346#define M800X600_R75_HSP POSITIVE
347#define M800X600_R75_VSP POSITIVE
348
349/*800x600@85 Sync Polarity (VESA Mode)
350*/
351#define M800X600_R85_HSP POSITIVE
352#define M800X600_R85_VSP POSITIVE
353
354/*800x600@100 Sync Polarity (GTF Mode)
355*/
356#define M800X600_R100_HSP NEGATIVE
357#define M800X600_R100_VSP POSITIVE
358
359/*800x600@120 Sync Polarity (GTF Mode)
360*/
361#define M800X600_R120_HSP NEGATIVE
362#define M800X600_R120_VSP POSITIVE
363
364/*800x480@60 Sync Polarity (CVT Mode)
365*/
366#define M800X480_R60_HSP NEGATIVE
367#define M800X480_R60_VSP POSITIVE
368
369/*848x480@60 Sync Polarity (CVT Mode)
370*/
371#define M848X480_R60_HSP NEGATIVE
372#define M848X480_R60_VSP POSITIVE
373
374/*852x480@60 Sync Polarity (GTF Mode)
375*/
376#define M852X480_R60_HSP NEGATIVE
377#define M852X480_R60_VSP POSITIVE
378
379/*1024x512@60 Sync Polarity (GTF Mode)
380*/
381#define M1024X512_R60_HSP NEGATIVE
382#define M1024X512_R60_VSP POSITIVE
383
384/*1024x600@60 Sync Polarity (GTF Mode)
385*/
386#define M1024X600_R60_HSP NEGATIVE
387#define M1024X600_R60_VSP POSITIVE
388
389/*1024x768@60 Sync Polarity (VESA Mode)
390*/
391#define M1024X768_R60_HSP NEGATIVE
392#define M1024X768_R60_VSP NEGATIVE
393
394/*1024x768@75 Sync Polarity (VESA Mode)
395*/
396#define M1024X768_R75_HSP POSITIVE
397#define M1024X768_R75_VSP POSITIVE
398
399/*1024x768@85 Sync Polarity (VESA Mode)
400*/
401#define M1024X768_R85_HSP POSITIVE
402#define M1024X768_R85_VSP POSITIVE
403
404/*1024x768@100 Sync Polarity (GTF Mode)
405*/
406#define M1024X768_R100_HSP NEGATIVE
407#define M1024X768_R100_VSP POSITIVE
408
409/*1152x864@75 Sync Polarity (VESA Mode)
410*/
411#define M1152X864_R75_HSP POSITIVE
412#define M1152X864_R75_VSP POSITIVE
413
414/*1280x720@60 Sync Polarity (GTF Mode)
415*/
416#define M1280X720_R60_HSP NEGATIVE
417#define M1280X720_R60_VSP POSITIVE
418
419/* 1280x768@50 Sync Polarity (GTF Mode) */
420#define M1280X768_R50_HSP NEGATIVE
421#define M1280X768_R50_VSP POSITIVE
422
423/*1280x768@60 Sync Polarity (GTF Mode)
424*/
425#define M1280X768_R60_HSP NEGATIVE
426#define M1280X768_R60_VSP POSITIVE
427
428/*1280x800@60 Sync Polarity (CVT Mode)
429*/
430#define M1280X800_R60_HSP NEGATIVE
431#define M1280X800_R60_VSP POSITIVE
432
433/*1280x960@60 Sync Polarity (VESA Mode)
434*/
435#define M1280X960_R60_HSP POSITIVE
436#define M1280X960_R60_VSP POSITIVE
437
438/*1280x1024@60 Sync Polarity (VESA Mode)
439*/
440#define M1280X1024_R60_HSP POSITIVE
441#define M1280X1024_R60_VSP POSITIVE
442
443/* 1360x768@60 Sync Polarity (CVT Mode) */
444#define M1360X768_R60_HSP POSITIVE
445#define M1360X768_R60_VSP POSITIVE
446
447/* 1360x768@60 Sync Polarity (CVT Reduce Blanking Mode) */
448#define M1360X768_RB_R60_HSP POSITIVE
449#define M1360X768_RB_R60_VSP NEGATIVE
450
451/* 1368x768@50 Sync Polarity (GTF Mode) */
452#define M1368X768_R50_HSP NEGATIVE
453#define M1368X768_R50_VSP POSITIVE
454
455/* 1368x768@60 Sync Polarity (VESA Mode) */
456#define M1368X768_R60_HSP NEGATIVE
457#define M1368X768_R60_VSP POSITIVE
458
459/*1280x1024@75 Sync Polarity (VESA Mode)
460*/
461#define M1280X1024_R75_HSP POSITIVE
462#define M1280X1024_R75_VSP POSITIVE
463
464/*1280x1024@85 Sync Polarity (VESA Mode)
465*/
466#define M1280X1024_R85_HSP POSITIVE
467#define M1280X1024_R85_VSP POSITIVE
468
469/*1440x1050@60 Sync Polarity (GTF Mode)
470*/
471#define M1440X1050_R60_HSP NEGATIVE
472#define M1440X1050_R60_VSP POSITIVE
473
474/*1600x1200@60 Sync Polarity (VESA Mode)
475*/
476#define M1600X1200_R60_HSP POSITIVE
477#define M1600X1200_R60_VSP POSITIVE
478
479/*1600x1200@75 Sync Polarity (VESA Mode)
480*/
481#define M1600X1200_R75_HSP POSITIVE
482#define M1600X1200_R75_VSP POSITIVE
483
484/* 1680x1050@60 Sync Polarity (CVT Mode) */
485#define M1680x1050_R60_HSP NEGATIVE
486#define M1680x1050_R60_VSP NEGATIVE
487
488/* 1680x1050@60 Sync Polarity (CVT Reduce Blanking Mode) */
489#define M1680x1050_RB_R60_HSP POSITIVE
490#define M1680x1050_RB_R60_VSP NEGATIVE
491
492/* 1680x1050@75 Sync Polarity (CVT Mode) */
493#define M1680x1050_R75_HSP NEGATIVE
494#define M1680x1050_R75_VSP POSITIVE
495
496/*1920x1080@60 Sync Polarity (CVT Mode)
497*/
498#define M1920X1080_R60_HSP NEGATIVE
499#define M1920X1080_R60_VSP POSITIVE
500
501/* 1920x1080@60 Sync Polarity (CVT Reduce Blanking Mode) */
502#define M1920X1080_RB_R60_HSP POSITIVE
503#define M1920X1080_RB_R60_VSP NEGATIVE
504
505/*1920x1440@60 Sync Polarity (VESA Mode)
506*/
507#define M1920X1440_R60_HSP NEGATIVE
508#define M1920X1440_R60_VSP POSITIVE
509
510/*1920x1440@75 Sync Polarity (VESA Mode)
511*/
512#define M1920X1440_R75_HSP NEGATIVE
513#define M1920X1440_R75_VSP POSITIVE
514
515#if 0
516/* 1400x1050@60 Sync Polarity (VESA Mode) */
517#define M1400X1050_R60_HSP NEGATIVE
518#define M1400X1050_R60_VSP NEGATIVE
519#endif
520
521/* 1400x1050@60 Sync Polarity (CVT Mode) */
522#define M1400X1050_R60_HSP NEGATIVE
523#define M1400X1050_R60_VSP POSITIVE
524
525/* 1400x1050@60 Sync Polarity (CVT Reduce Blanking Mode) */
526#define M1400X1050_RB_R60_HSP POSITIVE
527#define M1400X1050_RB_R60_VSP NEGATIVE
528
529/* 1400x1050@75 Sync Polarity (CVT Mode) */
530#define M1400X1050_R75_HSP NEGATIVE
531#define M1400X1050_R75_VSP POSITIVE
532
533/* 960x600@60 Sync Polarity (CVT Mode) */
534#define M960X600_R60_HSP NEGATIVE
535#define M960X600_R60_VSP POSITIVE
536
537/* 1000x600@60 Sync Polarity (GTF Mode) */
538#define M1000X600_R60_HSP NEGATIVE
539#define M1000X600_R60_VSP POSITIVE
540
541/* 1024x576@60 Sync Polarity (GTF Mode) */
542#define M1024X576_R60_HSP NEGATIVE
543#define M1024X576_R60_VSP POSITIVE
544
545/*1024x600@60 Sync Polarity (GTF Mode)*/
546#define M1024X600_R60_HSP NEGATIVE
547#define M1024X600_R60_VSP POSITIVE
548
549/* 1088x612@60 Sync Polarity (CVT Mode) */
550#define M1088X612_R60_HSP NEGATIVE
551#define M1088X612_R60_VSP POSITIVE
552
553/* 1152x720@60 Sync Polarity (CVT Mode) */
554#define M1152X720_R60_HSP NEGATIVE
555#define M1152X720_R60_VSP POSITIVE
556
557/* 1200x720@60 Sync Polarity (GTF Mode) */
558#define M1200X720_R60_HSP NEGATIVE
559#define M1200X720_R60_VSP POSITIVE
560
561/* 1200x900@60 Sync Polarity (DCON) */
562#define M1200X900_R60_HSP POSITIVE
563#define M1200X900_R60_VSP POSITIVE
564
565/* 1280x600@60 Sync Polarity (GTF Mode) */
566#define M1280x600_R60_HSP NEGATIVE
567#define M1280x600_R60_VSP POSITIVE
568
569/* 1280x720@50 Sync Polarity (GTF Mode) */
570#define M1280X720_R50_HSP NEGATIVE
571#define M1280X720_R50_VSP POSITIVE
572
573/* 1440x900@60 Sync Polarity (CVT Mode) */
574#define M1440X900_R60_HSP NEGATIVE
575#define M1440X900_R60_VSP POSITIVE
576
577/* 1440x900@75 Sync Polarity (CVT Mode) */
578#define M1440X900_R75_HSP NEGATIVE
579#define M1440X900_R75_VSP POSITIVE
580
581/* 1440x900@60 Sync Polarity (CVT Reduce Blanking Mode) */
582#define M1440X900_RB_R60_HSP POSITIVE
583#define M1440X900_RB_R60_VSP NEGATIVE
584
585/* 1600x900@60 Sync Polarity (CVT Mode) */
586#define M1600X900_R60_HSP NEGATIVE
587#define M1600X900_R60_VSP POSITIVE
588
589/* 1600x900@60 Sync Polarity (CVT Reduce Blanking Mode) */
590#define M1600X900_RB_R60_HSP POSITIVE
591#define M1600X900_RB_R60_VSP NEGATIVE
592
593/* 1600x1024@60 Sync Polarity (GTF Mode) */
594#define M1600X1024_R60_HSP NEGATIVE
595#define M1600X1024_R60_VSP POSITIVE
596
597/* 1792x1344@60 Sync Polarity (DMT Mode) */
598#define M1792x1344_R60_HSP NEGATIVE
599#define M1792x1344_R60_VSP POSITIVE
600
601/* 1856x1392@60 Sync Polarity (DMT Mode) */
602#define M1856x1392_R60_HSP NEGATIVE
603#define M1856x1392_R60_VSP POSITIVE
604
605/* 1920x1200@60 Sync Polarity (CVT Mode) */
606#define M1920X1200_R60_HSP NEGATIVE
607#define M1920X1200_R60_VSP POSITIVE
608
609/* 1920x1200@60 Sync Polarity (CVT Reduce Blanking Mode) */
610#define M1920X1200_RB_R60_HSP POSITIVE
611#define M1920X1200_RB_R60_VSP NEGATIVE
612
613/* 2048x1536@60 Sync Polarity (CVT Mode) */
614#define M2048x1536_R60_HSP NEGATIVE
615#define M2048x1536_R60_VSP POSITIVE
616
617/* Definition CRTC Timing Index */ 286/* Definition CRTC Timing Index */
618#define H_TOTAL_INDEX 0 287#define H_TOTAL_INDEX 0
619#define H_ADDR_INDEX 1 288#define H_ADDR_INDEX 1
diff --git a/drivers/video/via/via_aux.c b/drivers/video/via/via_aux.c
new file mode 100644
index 000000000000..4a0a55cdac3d
--- /dev/null
+++ b/drivers/video/via/via_aux.c
@@ -0,0 +1,88 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * infrastructure for devices connected via I2C
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap)
29{
30 struct via_aux_bus *bus;
31
32 if (!adap)
33 return NULL;
34
35 bus = kmalloc(sizeof(*bus), GFP_KERNEL);
36 if (!bus)
37 return NULL;
38
39 bus->adap = adap;
40 INIT_LIST_HEAD(&bus->drivers);
41
42 via_aux_edid_probe(bus);
43 via_aux_vt1636_probe(bus);
44 via_aux_vt1632_probe(bus);
45 via_aux_vt1631_probe(bus);
46 via_aux_vt1625_probe(bus);
47 via_aux_vt1622_probe(bus);
48 via_aux_vt1621_probe(bus);
49 via_aux_sii164_probe(bus);
50 via_aux_ch7301_probe(bus);
51
52 return bus;
53}
54
55void via_aux_free(struct via_aux_bus *bus)
56{
57 struct via_aux_drv *pos, *n;
58
59 if (!bus)
60 return;
61
62 list_for_each_entry_safe(pos, n, &bus->drivers, chain) {
63 if (pos->cleanup)
64 pos->cleanup(pos);
65
66 list_del(&pos->chain);
67 kfree(pos->data);
68 kfree(pos);
69 }
70
71 kfree(bus);
72}
73
74const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus)
75{
76 struct via_aux_drv *pos;
77 const struct fb_videomode *mode = NULL;
78
79 if (!bus)
80 return NULL;
81
82 list_for_each_entry(pos, &bus->drivers, chain) {
83 if (pos->get_preferred_mode)
84 mode = pos->get_preferred_mode(pos);
85 }
86
87 return mode;
88}
diff --git a/drivers/video/via/via_aux.h b/drivers/video/via/via_aux.h
new file mode 100644
index 000000000000..a8de3f038cea
--- /dev/null
+++ b/drivers/video/via/via_aux.h
@@ -0,0 +1,93 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * infrastructure for devices connected via I2C
22 */
23
24#ifndef __VIA_AUX_H__
25#define __VIA_AUX_H__
26
27
28#include <linux/list.h>
29#include <linux/i2c.h>
30#include <linux/fb.h>
31
32
33struct via_aux_bus {
34 struct i2c_adapter *adap; /* the I2C device to access the bus */
35 struct list_head drivers; /* drivers for devices on this bus */
36};
37
38struct via_aux_drv {
39 struct list_head chain; /* chain to support multiple drivers */
40
41 struct via_aux_bus *bus; /* the I2C bus used */
42 u8 addr; /* the I2C slave address */
43
44 const char *name; /* human readable name of the driver */
45 void *data; /* private data of this driver */
46
47 void (*cleanup)(struct via_aux_drv *drv);
48 const struct fb_videomode* (*get_preferred_mode)
49 (struct via_aux_drv *drv);
50};
51
52
53struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap);
54void via_aux_free(struct via_aux_bus *bus);
55const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus);
56
57
58static inline bool via_aux_add(struct via_aux_drv *drv)
59{
60 struct via_aux_drv *data = kmalloc(sizeof(*data), GFP_KERNEL);
61
62 if (!data)
63 return false;
64
65 *data = *drv;
66 list_add_tail(&data->chain, &data->bus->drivers);
67 return true;
68}
69
70static inline bool via_aux_read(struct via_aux_drv *drv, u8 start, u8 *buf,
71 u8 len)
72{
73 struct i2c_msg msg[2] = {
74 {.addr = drv->addr, .flags = 0, .len = 1, .buf = &start},
75 {.addr = drv->addr, .flags = I2C_M_RD, .len = len, .buf = buf} };
76
77 return i2c_transfer(drv->bus->adap, msg, 2) == 2;
78}
79
80
81/* probe functions of existing drivers - should only be called in via_aux.c */
82void via_aux_ch7301_probe(struct via_aux_bus *bus);
83void via_aux_edid_probe(struct via_aux_bus *bus);
84void via_aux_sii164_probe(struct via_aux_bus *bus);
85void via_aux_vt1636_probe(struct via_aux_bus *bus);
86void via_aux_vt1632_probe(struct via_aux_bus *bus);
87void via_aux_vt1631_probe(struct via_aux_bus *bus);
88void via_aux_vt1625_probe(struct via_aux_bus *bus);
89void via_aux_vt1622_probe(struct via_aux_bus *bus);
90void via_aux_vt1621_probe(struct via_aux_bus *bus);
91
92
93#endif /* __VIA_AUX_H__ */
diff --git a/drivers/video/via/via_aux_ch7301.c b/drivers/video/via/via_aux_ch7301.c
new file mode 100644
index 000000000000..1cbe5037a6b0
--- /dev/null
+++ b/drivers/video/via/via_aux_ch7301.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for Chrontel CH7301 DVI Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "CH7301 DVI Transmitter";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 u8 tmp;
38
39 if (!via_aux_read(&drv, 0x4B, &tmp, 1) || tmp != 0x17)
40 return;
41
42 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
43 via_aux_add(&drv);
44}
45
46void via_aux_ch7301_probe(struct via_aux_bus *bus)
47{
48 probe(bus, 0x75);
49 probe(bus, 0x76);
50}
diff --git a/drivers/video/via/via_aux_edid.c b/drivers/video/via/via_aux_edid.c
new file mode 100644
index 000000000000..754d4509033f
--- /dev/null
+++ b/drivers/video/via/via_aux_edid.c
@@ -0,0 +1,100 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * generic EDID driver
22 */
23
24#include <linux/slab.h>
25#include <linux/fb.h>
26#include "via_aux.h"
27#include "../edid.h"
28
29
30static const char *name = "EDID";
31
32
33static void query_edid(struct via_aux_drv *drv)
34{
35 struct fb_monspecs *spec = drv->data;
36 unsigned char edid[EDID_LENGTH];
37 bool valid = false;
38
39 if (spec) {
40 fb_destroy_modedb(spec->modedb);
41 } else {
42 spec = kmalloc(sizeof(*spec), GFP_KERNEL);
43 if (!spec)
44 return;
45 }
46
47 spec->version = spec->revision = 0;
48 if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) {
49 fb_edid_to_monspecs(edid, spec);
50 valid = spec->version || spec->revision;
51 }
52
53 if (!valid) {
54 kfree(spec);
55 spec = NULL;
56 } else
57 printk(KERN_DEBUG "EDID: %s %s\n", spec->manufacturer, spec->monitor);
58
59 drv->data = spec;
60}
61
62static const struct fb_videomode *get_preferred_mode(struct via_aux_drv *drv)
63{
64 struct fb_monspecs *spec = drv->data;
65 int i;
66
67 if (!spec || !spec->modedb || !(spec->misc & FB_MISC_1ST_DETAIL))
68 return NULL;
69
70 for (i = 0; i < spec->modedb_len; i++) {
71 if (spec->modedb[i].flag & FB_MODE_IS_FIRST &&
72 spec->modedb[i].flag & FB_MODE_IS_DETAILED)
73 return &spec->modedb[i];
74 }
75
76 return NULL;
77}
78
79static void cleanup(struct via_aux_drv *drv)
80{
81 struct fb_monspecs *spec = drv->data;
82
83 if (spec)
84 fb_destroy_modedb(spec->modedb);
85}
86
87void via_aux_edid_probe(struct via_aux_bus *bus)
88{
89 struct via_aux_drv drv = {
90 .bus = bus,
91 .addr = 0x50,
92 .name = name,
93 .cleanup = cleanup,
94 .get_preferred_mode = get_preferred_mode};
95
96 query_edid(&drv);
97
98 /* as EDID devices can be connected/disconnected just add the driver */
99 via_aux_add(&drv);
100}
diff --git a/drivers/video/via/via_aux_sii164.c b/drivers/video/via/via_aux_sii164.c
new file mode 100644
index 000000000000..ca1b35f033b1
--- /dev/null
+++ b/drivers/video/via/via_aux_sii164.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for Silicon Image SiI 164 PanelLink Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "SiI 164 PanelLink Transmitter";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 /* check vendor id and device id */
38 const u8 id[] = {0x01, 0x00, 0x06, 0x00}, len = ARRAY_SIZE(id);
39 u8 tmp[len];
40
41 if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
42 return;
43
44 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
45 via_aux_add(&drv);
46}
47
48void via_aux_sii164_probe(struct via_aux_bus *bus)
49{
50 u8 i;
51
52 for (i = 0x38; i <= 0x3F; i++)
53 probe(bus, i);
54}
diff --git a/drivers/video/via/via_aux_vt1621.c b/drivers/video/via/via_aux_vt1621.c
new file mode 100644
index 000000000000..38eca8479898
--- /dev/null
+++ b/drivers/video/via/via_aux_vt1621.c
@@ -0,0 +1,44 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1621(M) TV Encoder
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1621(M) TV Encoder";
29
30
31void via_aux_vt1621_probe(struct via_aux_bus *bus)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = 0x20,
36 .name = name};
37 u8 tmp;
38
39 if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x02)
40 return;
41
42 printk(KERN_INFO "viafb: Found %s\n", name);
43 via_aux_add(&drv);
44}
diff --git a/drivers/video/via/via_aux_vt1622.c b/drivers/video/via/via_aux_vt1622.c
new file mode 100644
index 000000000000..8c79c68ba683
--- /dev/null
+++ b/drivers/video/via/via_aux_vt1622.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1622(M) Digital TV Encoder
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1622(M) Digital TV Encoder";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 u8 tmp;
38
39 if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x03)
40 return;
41
42 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
43 via_aux_add(&drv);
44}
45
46void via_aux_vt1622_probe(struct via_aux_bus *bus)
47{
48 probe(bus, 0x20);
49 probe(bus, 0x21);
50}
diff --git a/drivers/video/via/via_aux_vt1625.c b/drivers/video/via/via_aux_vt1625.c
new file mode 100644
index 000000000000..03eb30165d36
--- /dev/null
+++ b/drivers/video/via/via_aux_vt1625.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1625(M) HDTV Encoder
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1625(M) HDTV Encoder";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 u8 tmp;
38
39 if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x50)
40 return;
41
42 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
43 via_aux_add(&drv);
44}
45
46void via_aux_vt1625_probe(struct via_aux_bus *bus)
47{
48 probe(bus, 0x20);
49 probe(bus, 0x21);
50}
diff --git a/drivers/video/via/via_aux_vt1631.c b/drivers/video/via/via_aux_vt1631.c
new file mode 100644
index 000000000000..06e742f1f723
--- /dev/null
+++ b/drivers/video/via/via_aux_vt1631.c
@@ -0,0 +1,46 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1631 LVDS Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1631 LVDS Transmitter";
29
30
31void via_aux_vt1631_probe(struct via_aux_bus *bus)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = 0x38,
36 .name = name};
37 /* check vendor id and device id */
38 const u8 id[] = {0x06, 0x11, 0x91, 0x31}, len = ARRAY_SIZE(id);
39 u8 tmp[len];
40
41 if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
42 return;
43
44 printk(KERN_INFO "viafb: Found %s\n", name);
45 via_aux_add(&drv);
46}
diff --git a/drivers/video/via/via_aux_vt1632.c b/drivers/video/via/via_aux_vt1632.c
new file mode 100644
index 000000000000..d24f4cd97401
--- /dev/null
+++ b/drivers/video/via/via_aux_vt1632.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1632 DVI Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1632 DVI Transmitter";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 /* check vendor id and device id */
38 const u8 id[] = {0x06, 0x11, 0x92, 0x31}, len = ARRAY_SIZE(id);
39 u8 tmp[len];
40
41 if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
42 return;
43
44 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
45 via_aux_add(&drv);
46}
47
48void via_aux_vt1632_probe(struct via_aux_bus *bus)
49{
50 u8 i;
51
52 for (i = 0x08; i <= 0x0F; i++)
53 probe(bus, i);
54}
diff --git a/drivers/video/via/via_aux_vt1636.c b/drivers/video/via/via_aux_vt1636.c
new file mode 100644
index 000000000000..9e015c101d4d
--- /dev/null
+++ b/drivers/video/via/via_aux_vt1636.c
@@ -0,0 +1,46 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1636 LVDS Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1636 LVDS Transmitter";
29
30
31void via_aux_vt1636_probe(struct via_aux_bus *bus)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = 0x40,
36 .name = name};
37 /* check vendor id and device id */
38 const u8 id[] = {0x06, 0x11, 0x45, 0x33}, len = ARRAY_SIZE(id);
39 u8 tmp[len];
40
41 if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
42 return;
43
44 printk(KERN_INFO "viafb: Found %s\n", name);
45 via_aux_add(&drv);
46}
diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
index 78f1405dbab7..dd53058bbbb7 100644
--- a/drivers/video/via/via_i2c.c
+++ b/drivers/video/via/via_i2c.c
@@ -51,7 +51,7 @@ static void via_i2c_setscl(void *data, int state)
51 val |= 0x01; 51 val |= 0x01;
52 break; 52 break;
53 case VIA_PORT_GPIO: 53 case VIA_PORT_GPIO:
54 val |= 0x80; 54 val |= 0x82;
55 break; 55 break;
56 default: 56 default:
57 printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n"); 57 printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
@@ -67,6 +67,9 @@ static int via_i2c_getscl(void *data)
67 int ret = 0; 67 int ret = 0;
68 68
69 spin_lock_irqsave(&i2c_vdev->reg_lock, flags); 69 spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
70 if (adap_data->type == VIA_PORT_GPIO)
71 via_write_reg_mask(adap_data->io_port, adap_data->ioport_index,
72 0, 0x80);
70 if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08) 73 if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08)
71 ret = 1; 74 ret = 1;
72 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); 75 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
@@ -80,6 +83,9 @@ static int via_i2c_getsda(void *data)
80 int ret = 0; 83 int ret = 0;
81 84
82 spin_lock_irqsave(&i2c_vdev->reg_lock, flags); 85 spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
86 if (adap_data->type == VIA_PORT_GPIO)
87 via_write_reg_mask(adap_data->io_port, adap_data->ioport_index,
88 0, 0x40);
83 if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04) 89 if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04)
84 ret = 1; 90 ret = 1;
85 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); 91 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
@@ -103,7 +109,7 @@ static void via_i2c_setsda(void *data, int state)
103 val |= 0x01; 109 val |= 0x01;
104 break; 110 break;
105 case VIA_PORT_GPIO: 111 case VIA_PORT_GPIO:
106 val |= 0x40; 112 val |= 0x42;
107 break; 113 break;
108 default: 114 default:
109 printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n"); 115 printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index a13c258bd32f..0c8837565bc7 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -24,6 +24,7 @@
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/stat.h> 25#include <linux/stat.h>
26#include <linux/via-core.h> 26#include <linux/via-core.h>
27#include <linux/via_i2c.h>
27#include <asm/olpc.h> 28#include <asm/olpc.h>
28 29
29#define _MASTER_FILE 30#define _MASTER_FILE
@@ -286,26 +287,22 @@ static int viafb_set_par(struct fb_info *info)
286 viafb_second_yres, viafb_bpp1, 1); 287 viafb_second_yres, viafb_bpp1, 1);
287 } 288 }
288 289
289 refresh = viafb_get_refresh(info->var.xres, info->var.yres, 290 refresh = get_var_refresh(&info->var);
290 get_var_refresh(&info->var)); 291 if (viafb_dual_fb && viapar->iga_path == IGA2) {
291 if (viafb_get_best_mode(viafbinfo->var.xres, viafbinfo->var.yres, 292 viafb_bpp1 = info->var.bits_per_pixel;
292 refresh)) { 293 viafb_refresh1 = refresh;
293 if (viafb_dual_fb && viapar->iga_path == IGA2) { 294 } else {
294 viafb_bpp1 = info->var.bits_per_pixel; 295 viafb_bpp = info->var.bits_per_pixel;
295 viafb_refresh1 = refresh; 296 viafb_refresh = refresh;
296 } else {
297 viafb_bpp = info->var.bits_per_pixel;
298 viafb_refresh = refresh;
299 }
300
301 if (info->var.accel_flags & FB_ACCELF_TEXT)
302 info->flags &= ~FBINFO_HWACCEL_DISABLED;
303 else
304 info->flags |= FBINFO_HWACCEL_DISABLED;
305 viafb_setmode(info->var.bits_per_pixel, viafb_bpp1);
306 viafb_pan_display(&info->var, info);
307 } 297 }
308 298
299 if (info->var.accel_flags & FB_ACCELF_TEXT)
300 info->flags &= ~FBINFO_HWACCEL_DISABLED;
301 else
302 info->flags |= FBINFO_HWACCEL_DISABLED;
303 viafb_setmode();
304 viafb_pan_display(&info->var, info);
305
309 return 0; 306 return 0;
310} 307}
311 308
@@ -1670,12 +1667,23 @@ static void viafb_remove_proc(struct viafb_shared *shared)
1670} 1667}
1671#undef IS_VT1636 1668#undef IS_VT1636
1672 1669
1673static int parse_mode(const char *str, u32 *xres, u32 *yres) 1670static int parse_mode(const char *str, u32 devices, u32 *xres, u32 *yres)
1674{ 1671{
1672 const struct fb_videomode *mode = NULL;
1675 char *ptr; 1673 char *ptr;
1676 1674
1677 if (!str) { 1675 if (!str) {
1678 if (machine_is_olpc()) { 1676 if (devices == VIA_CRT)
1677 mode = via_aux_get_preferred_mode(
1678 viaparinfo->shared->i2c_26);
1679 else if (devices == VIA_DVP1)
1680 mode = via_aux_get_preferred_mode(
1681 viaparinfo->shared->i2c_31);
1682
1683 if (mode) {
1684 *xres = mode->xres;
1685 *yres = mode->yres;
1686 } else if (machine_is_olpc()) {
1679 *xres = 1200; 1687 *xres = 1200;
1680 *yres = 900; 1688 *yres = 900;
1681 } else { 1689 } else {
@@ -1729,6 +1737,31 @@ static struct viafb_pm_hooks viafb_fb_pm_hooks = {
1729 1737
1730#endif 1738#endif
1731 1739
1740static void __devinit i2c_bus_probe(struct viafb_shared *shared)
1741{
1742 /* should be always CRT */
1743 printk(KERN_INFO "viafb: Probing I2C bus 0x26\n");
1744 shared->i2c_26 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_26));
1745
1746 /* seems to be usually DVP1 */
1747 printk(KERN_INFO "viafb: Probing I2C bus 0x31\n");
1748 shared->i2c_31 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_31));
1749
1750 /* FIXME: what is this? */
1751 if (!machine_is_olpc()) {
1752 printk(KERN_INFO "viafb: Probing I2C bus 0x2C\n");
1753 shared->i2c_2C = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_2C));
1754 }
1755
1756 printk(KERN_INFO "viafb: Finished I2C bus probing");
1757}
1758
1759static void i2c_bus_free(struct viafb_shared *shared)
1760{
1761 via_aux_free(shared->i2c_26);
1762 via_aux_free(shared->i2c_31);
1763 via_aux_free(shared->i2c_2C);
1764}
1732 1765
1733int __devinit via_fb_pci_probe(struct viafb_dev *vdev) 1766int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1734{ 1767{
@@ -1762,6 +1795,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1762 &viaparinfo->shared->lvds_setting_info2; 1795 &viaparinfo->shared->lvds_setting_info2;
1763 viaparinfo->chip_info = &viaparinfo->shared->chip_info; 1796 viaparinfo->chip_info = &viaparinfo->shared->chip_info;
1764 1797
1798 i2c_bus_probe(viaparinfo->shared);
1765 if (viafb_dual_fb) 1799 if (viafb_dual_fb)
1766 viafb_SAMM_ON = 1; 1800 viafb_SAMM_ON = 1;
1767 parse_lcd_port(); 1801 parse_lcd_port();
@@ -1804,10 +1838,11 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1804 viafb_second_size * 1024 * 1024; 1838 viafb_second_size * 1024 * 1024;
1805 } 1839 }
1806 1840
1807 parse_mode(viafb_mode, &default_xres, &default_yres); 1841 parse_mode(viafb_mode, viaparinfo->shared->iga1_devices,
1842 &default_xres, &default_yres);
1808 if (viafb_SAMM_ON == 1) 1843 if (viafb_SAMM_ON == 1)
1809 parse_mode(viafb_mode1, &viafb_second_xres, 1844 parse_mode(viafb_mode1, viaparinfo->shared->iga2_devices,
1810 &viafb_second_yres); 1845 &viafb_second_xres, &viafb_second_yres);
1811 1846
1812 default_var.xres = default_xres; 1847 default_var.xres = default_xres;
1813 default_var.yres = default_yres; 1848 default_var.yres = default_yres;
@@ -1915,6 +1950,7 @@ out_fb1_release:
1915 if (viafbinfo1) 1950 if (viafbinfo1)
1916 framebuffer_release(viafbinfo1); 1951 framebuffer_release(viafbinfo1);
1917out_fb_release: 1952out_fb_release:
1953 i2c_bus_free(viaparinfo->shared);
1918 framebuffer_release(viafbinfo); 1954 framebuffer_release(viafbinfo);
1919 return rc; 1955 return rc;
1920} 1956}
@@ -1927,6 +1963,7 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev)
1927 if (viafb_dual_fb) 1963 if (viafb_dual_fb)
1928 unregister_framebuffer(viafbinfo1); 1964 unregister_framebuffer(viafbinfo1);
1929 viafb_remove_proc(viaparinfo->shared); 1965 viafb_remove_proc(viaparinfo->shared);
1966 i2c_bus_free(viaparinfo->shared);
1930 framebuffer_release(viafbinfo); 1967 framebuffer_release(viafbinfo);
1931 if (viafb_dual_fb) 1968 if (viafb_dual_fb)
1932 framebuffer_release(viafbinfo1); 1969 framebuffer_release(viafbinfo1);
@@ -2033,9 +2070,9 @@ int __init viafb_init(void)
2033 if (r < 0) 2070 if (r < 0)
2034 return r; 2071 return r;
2035#endif 2072#endif
2036 if (parse_mode(viafb_mode, &dummy_x, &dummy_y) 2073 if (parse_mode(viafb_mode, 0, &dummy_x, &dummy_y)
2037 || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh) 2074 || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh)
2038 || parse_mode(viafb_mode1, &dummy_x, &dummy_y) 2075 || parse_mode(viafb_mode1, 0, &dummy_x, &dummy_y)
2039 || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1) 2076 || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1)
2040 || viafb_bpp < 0 || viafb_bpp > 32 2077 || viafb_bpp < 0 || viafb_bpp > 32
2041 || viafb_bpp1 < 0 || viafb_bpp1 > 32 2078 || viafb_bpp1 < 0 || viafb_bpp1 > 32
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index d9440635d1d4..f6b2ddf56e94 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -26,6 +26,7 @@
26#include <linux/fb.h> 26#include <linux/fb.h>
27#include <linux/spinlock.h> 27#include <linux/spinlock.h>
28 28
29#include "via_aux.h"
29#include "ioctl.h" 30#include "ioctl.h"
30#include "share.h" 31#include "share.h"
31#include "chip.h" 32#include "chip.h"
@@ -48,6 +49,11 @@ struct viafb_shared {
48 struct proc_dir_entry *iga2_proc_entry; 49 struct proc_dir_entry *iga2_proc_entry;
49 struct viafb_dev *vdev; /* Global dev info */ 50 struct viafb_dev *vdev; /* Global dev info */
50 51
52 /* I2C busses that may have auxiliary devices */
53 struct via_aux_bus *i2c_26;
54 struct via_aux_bus *i2c_31;
55 struct via_aux_bus *i2c_2C;
56
51 /* All the information will be needed to set engine */ 57 /* All the information will be needed to set engine */
52 struct tmds_setting_information tmds_setting_info; 58 struct tmds_setting_information tmds_setting_info;
53 struct lvds_setting_information lvds_setting_info; 59 struct lvds_setting_information lvds_setting_info;
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index 0911cac1b2ff..0666ab01cf4a 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -268,591 +268,78 @@ struct VPITTable VPIT = {
268/* Mode Table */ 268/* Mode Table */
269/********************/ 269/********************/
270 270
271/* 480x640 */ 271static const struct fb_videomode viafb_modes[] = {
272static struct crt_mode_table CRTM480x640[] = { 272 {NULL, 60, 480, 640, 40285, 72, 24, 19, 1, 48, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
273 /* r_rate, hsp, vsp */ 273 {NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 0, 0, 0},
274 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 274 {NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, 0, 0, 0},
275 {REFRESH_60, M480X640_R60_HSP, M480X640_R60_VSP, 275 {NULL, 85, 640, 480, 27780, 80, 56, 25, 1, 56, 3, 0, 0, 0},
276 {624, 480, 480, 144, 504, 48, 663, 640, 640, 23, 641, 3} } /* GTF*/ 276 {NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
277}; 277 {NULL, 120, 640, 480, 19081, 104, 40, 31, 1, 64, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
278 278 {NULL, 60, 720, 480, 37426, 88, 16, 13, 1, 72, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
279/* 640x480*/ 279 {NULL, 60, 720, 576, 30611, 96, 24, 17, 1, 72, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
280static struct crt_mode_table CRTM640x480[] = { 280 {NULL, 60, 800, 600, 25131, 88, 40, 23, 1, 128, 4, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
281 /*r_rate,hsp,vsp */ 281 {NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
282 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 282 {NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
283 {REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP, 283 {NULL, 100, 800, 600, 14667, 136, 48, 32, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
284 {800, 640, 640, 160, 656, 96, 525, 480, 480, 45, 490, 2} }, 284 {NULL, 120, 800, 600, 11911, 144, 56, 39, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
285 {REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP, 285 {NULL, 60, 800, 480, 33602, 96, 24, 10, 3, 72, 7, FB_SYNC_VERT_HIGH_ACT, 0, 0},
286 {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} }, 286 {NULL, 60, 848, 480, 31565, 104, 24, 12, 3, 80, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
287 {REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP, 287 {NULL, 60, 856, 480, 31517, 104, 16, 13, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
288 {832, 640, 640, 192, 696, 56, 509, 480, 480, 29, 481, 3} }, 288 {NULL, 60, 1024, 512, 24218, 136, 32, 15, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
289 {REFRESH_100, M640X480_R100_HSP, M640X480_R100_VSP, 289 {NULL, 60, 1024, 600, 20423, 144, 40, 18, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
290 {848, 640, 640, 208, 680, 64, 509, 480, 480, 29, 481, 3} }, /*GTF*/ 290 {NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6, 0, 0, 0},
291 {REFRESH_120, M640X480_R120_HSP, M640X480_R120_VSP, 291 {NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
292 {848, 640, 640, 208, 680, 64, 515, 480, 480, 35, 481, 3} } /*GTF*/ 292 {NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
293}; 293 {NULL, 100, 1024, 768, 8825, 184, 72, 42, 1, 112, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
294 294 {NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
295/*720x480 (GTF)*/ 295 {NULL, 60, 1280, 768, 12478, 200, 64, 23, 1, 136, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
296static struct crt_mode_table CRTM720x480[] = { 296 {NULL, 50, 1280, 768, 15342, 184, 56, 19, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
297 /*r_rate,hsp,vsp */ 297 {NULL, 60, 960, 600, 21964, 128, 32, 15, 3, 96, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
298 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 298 {NULL, 60, 1000, 600, 20803, 144, 40, 18, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
299 {REFRESH_60, M720X480_R60_HSP, M720X480_R60_VSP, 299 {NULL, 60, 1024, 576, 21278, 144, 40, 17, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
300 {896, 720, 720, 176, 736, 72, 497, 480, 480, 17, 481, 3} } 300 {NULL, 60, 1088, 612, 18825, 152, 48, 16, 3, 104, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
301 301 {NULL, 60, 1152, 720, 14974, 168, 56, 19, 3, 112, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
302}; 302 {NULL, 60, 1200, 720, 14248, 184, 56, 22, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
303 303 {NULL, 49, 1200, 900, 17703, 21, 11, 1, 1, 32, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
304/*720x576 (GTF)*/ 304 {NULL, 60, 1280, 600, 16259, 184, 56, 18, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
305static struct crt_mode_table CRTM720x576[] = { 305 {NULL, 60, 1280, 800, 11938, 200, 72, 22, 3, 128, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
306 /*r_rate,hsp,vsp */ 306 {NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
307 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 307 {NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
308 {REFRESH_60, M720X576_R60_HSP, M720X576_R60_VSP, 308 {NULL, 75, 1280, 1024, 7409, 248, 16, 38, 1, 144, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
309 {912, 720, 720, 192, 744, 72, 597, 576, 576, 21, 577, 3} } 309 {NULL, 85, 1280, 1024, 6351, 224, 64, 44, 1, 160, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
310}; 310 {NULL, 60, 1360, 768, 11759, 208, 72, 22, 3, 136, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
311 311 {NULL, 60, 1368, 768, 11646, 216, 72, 23, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
312/* 800x480 (CVT) */ 312 {NULL, 50, 1368, 768, 14301, 200, 56, 19, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
313static struct crt_mode_table CRTM800x480[] = { 313 {NULL, 60, 1368, 768, 11646, 216, 72, 23, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
314 /* r_rate, hsp, vsp */ 314 {NULL, 60, 1440, 900, 9372, 232, 80, 25, 3, 152, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
315 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 315 {NULL, 75, 1440, 900, 7311, 248, 96, 33, 3, 152, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
316 {REFRESH_60, M800X480_R60_HSP, M800X480_R60_VSP, 316 {NULL, 60, 1440, 1040, 7993, 248, 96, 33, 1, 152, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
317 {992, 800, 800, 192, 824, 72, 500, 480, 480, 20, 483, 7} } 317 {NULL, 60, 1600, 900, 8449, 256, 88, 26, 3, 168, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
318}; 318 {NULL, 60, 1600, 1024, 7333, 272, 104, 32, 1, 168, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
319 319 {NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
320/* 800x600*/ 320 {NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
321static struct crt_mode_table CRTM800x600[] = { 321 {NULL, 60, 1680, 1050, 6832, 280, 104, 30, 3, 176, 6, 0, 0, 0},
322 /*r_rate,hsp,vsp */ 322 {NULL, 75, 1680, 1050, 5339, 296, 120, 40, 3, 176, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
323 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 323 {NULL, 60, 1792, 1344, 4883, 328, 128, 46, 1, 200, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
324 {REFRESH_60, M800X600_R60_HSP, M800X600_R60_VSP, 324 {NULL, 60, 1856, 1392, 4581, 352, 96, 43, 1, 224, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
325 {1056, 800, 800, 256, 840, 128, 628, 600, 600, 28, 601, 4} }, 325 {NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 208, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
326 {REFRESH_75, M800X600_R75_HSP, M800X600_R75_VSP, 326 {NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
327 {1056, 800, 800, 256, 816, 80, 625, 600, 600, 25, 601, 3} }, 327 {NULL, 60, 2048, 1536, 3738, 376, 152, 49, 3, 224, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0},
328 {REFRESH_85, M800X600_R85_HSP, M800X600_R85_VSP, 328 {NULL, 60, 1280, 720, 13484, 216, 112, 20, 5, 40, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
329 {1048, 800, 800, 248, 832, 64, 631, 600, 600, 31, 601, 3} }, 329 {NULL, 50, 1280, 720, 16538, 176, 48, 17, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
330 {REFRESH_100, M800X600_R100_HSP, M800X600_R100_VSP, 330 {NULL, 60, 1920, 1080, 5776, 328, 128, 32, 3, 200, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
331 {1072, 800, 800, 272, 848, 88, 636, 600, 600, 36, 601, 3} }, 331 {NULL, 60, 1920, 1200, 5164, 336, 136, 36, 3, 200, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
332 {REFRESH_120, M800X600_R120_HSP, M800X600_R120_VSP, 332 {NULL, 60, 1400, 1050, 8210, 232, 88, 32, 3, 144, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0},
333 {1088, 800, 800, 288, 856, 88, 643, 600, 600, 43, 601, 3} } 333 {NULL, 75, 1400, 1050, 6398, 248, 104, 42, 3, 144, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0} };
334}; 334
335 335static const struct fb_videomode viafb_rb_modes[] = {
336/* 848x480 (CVT) */ 336 {NULL, 60, 1360, 768, 13879, 80, 48, 14, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
337static struct crt_mode_table CRTM848x480[] = { 337 {NULL, 60, 1440, 900, 11249, 80, 48, 17, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0},
338 /* r_rate, hsp, vsp */ 338 {NULL, 60, 1400, 1050, 9892, 80, 48, 23, 3, 32, 4, FB_SYNC_HOR_HIGH_ACT, 0, 0},
339 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 339 {NULL, 60, 1600, 900, 10226, 80, 48, 18, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
340 {REFRESH_60, M848X480_R60_HSP, M848X480_R60_VSP, 340 {NULL, 60, 1680, 1050, 8387, 80, 48, 21, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0},
341 {1056, 848, 848, 208, 872, 80, 500, 480, 480, 20, 483, 5} } 341 {NULL, 60, 1920, 1080, 7212, 80, 48, 23, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
342}; 342 {NULL, 60, 1920, 1200, 6488, 80, 48, 26, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0} };
343
344/*856x480 (GTF) convert to 852x480*/
345static struct crt_mode_table CRTM852x480[] = {
346 /*r_rate,hsp,vsp */
347 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
348 {REFRESH_60, M852X480_R60_HSP, M852X480_R60_VSP,
349 {1064, 856, 856, 208, 872, 88, 497, 480, 480, 17, 481, 3} }
350};
351
352/*1024x512 (GTF)*/
353static struct crt_mode_table CRTM1024x512[] = {
354 /*r_rate,hsp,vsp */
355 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
356 {REFRESH_60, M1024X512_R60_HSP, M1024X512_R60_VSP,
357 {1296, 1024, 1024, 272, 1056, 104, 531, 512, 512, 19, 513, 3} }
358
359};
360
361/* 1024x600*/
362static struct crt_mode_table CRTM1024x600[] = {
363 /*r_rate,hsp,vsp */
364 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
365 {REFRESH_60, M1024X600_R60_HSP, M1024X600_R60_VSP,
366 {1312, 1024, 1024, 288, 1064, 104, 622, 600, 600, 22, 601, 3} },
367};
368
369/* 1024x768*/
370static struct crt_mode_table CRTM1024x768[] = {
371 /*r_rate,hsp,vsp */
372 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
373 {REFRESH_60, M1024X768_R60_HSP, M1024X768_R60_VSP,
374 {1344, 1024, 1024, 320, 1048, 136, 806, 768, 768, 38, 771, 6} },
375 {REFRESH_75, M1024X768_R75_HSP, M1024X768_R75_VSP,
376 {1312, 1024, 1024, 288, 1040, 96, 800, 768, 768, 32, 769, 3} },
377 {REFRESH_85, M1024X768_R85_HSP, M1024X768_R85_VSP,
378 {1376, 1024, 1024, 352, 1072, 96, 808, 768, 768, 40, 769, 3} },
379 {REFRESH_100, M1024X768_R100_HSP, M1024X768_R100_VSP,
380 {1392, 1024, 1024, 368, 1096, 112, 814, 768, 768, 46, 769, 3} }
381};
382
383/* 1152x864*/
384static struct crt_mode_table CRTM1152x864[] = {
385 /*r_rate,hsp,vsp */
386 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
387 {REFRESH_75, M1152X864_R75_HSP, M1152X864_R75_VSP,
388 {1600, 1152, 1152, 448, 1216, 128, 900, 864, 864, 36, 865, 3} }
389
390};
391
392/* 1280x720 (HDMI 720P)*/
393static struct crt_mode_table CRTM1280x720[] = {
394 /*r_rate,hsp,vsp */
395 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
396 {REFRESH_60, M1280X720_R60_HSP, M1280X720_R60_VSP,
397 {1648, 1280, 1280, 368, 1392, 40, 750, 720, 720, 30, 725, 5} },
398 {REFRESH_50, M1280X720_R50_HSP, M1280X720_R50_VSP,
399 {1632, 1280, 1280, 352, 1328, 128, 741, 720, 720, 21, 721, 3} }
400};
401
402/*1280x768 (GTF)*/
403static struct crt_mode_table CRTM1280x768[] = {
404 /*r_rate,hsp,vsp */
405 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
406 {REFRESH_60, M1280X768_R60_HSP, M1280X768_R60_VSP,
407 {1680, 1280, 1280, 400, 1344, 136, 795, 768, 768, 27, 769, 3} },
408 {REFRESH_50, M1280X768_R50_HSP, M1280X768_R50_VSP,
409 {1648, 1280, 1280, 368, 1336, 128, 791, 768, 768, 23, 769, 3} }
410};
411
412/* 1280x800 (CVT) */
413static struct crt_mode_table CRTM1280x800[] = {
414 /* r_rate, hsp, vsp */
415 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
416 {REFRESH_60, M1280X800_R60_HSP, M1280X800_R60_VSP,
417 {1680, 1280, 1280, 400, 1352, 128, 831, 800, 800, 31, 803, 6} }
418};
419
420/*1280x960*/
421static struct crt_mode_table CRTM1280x960[] = {
422 /*r_rate,hsp,vsp */
423 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
424 {REFRESH_60, M1280X960_R60_HSP, M1280X960_R60_VSP,
425 {1800, 1280, 1280, 520, 1376, 112, 1000, 960, 960, 40, 961, 3} }
426};
427
428/* 1280x1024*/
429static struct crt_mode_table CRTM1280x1024[] = {
430 /*r_rate,hsp,vsp */
431 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
432 {REFRESH_60, M1280X1024_R60_HSP, M1280X1024_R60_VSP,
433 {1688, 1280, 1280, 408, 1328, 112, 1066, 1024, 1024, 42, 1025,
434 3} },
435 {REFRESH_75, M1280X1024_R75_HSP, M1280X1024_R75_VSP,
436 {1688, 1280, 1280, 408, 1296, 144, 1066, 1024, 1024, 42, 1025,
437 3} },
438 {REFRESH_85, M1280X1024_R85_HSP, M1280X1024_R85_VSP,
439 {1728, 1280, 1280, 448, 1344, 160, 1072, 1024, 1024, 48, 1025, 3} }
440};
441
442/* 1368x768 (GTF) */
443static struct crt_mode_table CRTM1368x768[] = {
444 /* r_rate, hsp, vsp */
445 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
446 {REFRESH_60, M1368X768_R60_HSP, M1368X768_R60_VSP,
447 {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} }
448};
449
450/*1440x1050 (GTF)*/
451static struct crt_mode_table CRTM1440x1050[] = {
452 /*r_rate,hsp,vsp */
453 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
454 {REFRESH_60, M1440X1050_R60_HSP, M1440X1050_R60_VSP,
455 {1936, 1440, 1440, 496, 1536, 152, 1077, 1040, 1040, 37, 1041, 3} }
456};
457
458/* 1600x1200*/
459static struct crt_mode_table CRTM1600x1200[] = {
460 /*r_rate,hsp,vsp */
461 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
462 {REFRESH_60, M1600X1200_R60_HSP, M1600X1200_R60_VSP,
463 {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201,
464 3} },
465 {REFRESH_75, M1600X1200_R75_HSP, M1600X1200_R75_VSP,
466 {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201, 3} }
467
468};
469
470/* 1680x1050 (CVT) */
471static struct crt_mode_table CRTM1680x1050[] = {
472 /* r_rate, hsp, vsp */
473 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
474 {REFRESH_60, M1680x1050_R60_HSP, M1680x1050_R60_VSP,
475 {2240, 1680, 1680, 560, 1784, 176, 1089, 1050, 1050, 39, 1053,
476 6} },
477 {REFRESH_75, M1680x1050_R75_HSP, M1680x1050_R75_VSP,
478 {2272, 1680, 1680, 592, 1800, 176, 1099, 1050, 1050, 49, 1053, 6} }
479};
480
481/* 1680x1050 (CVT Reduce Blanking) */
482static struct crt_mode_table CRTM1680x1050_RB[] = {
483 /* r_rate, hsp, vsp */
484 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
485 {REFRESH_60, M1680x1050_RB_R60_HSP, M1680x1050_RB_R60_VSP,
486 {1840, 1680, 1680, 160, 1728, 32, 1080, 1050, 1050, 30, 1053, 6} }
487};
488
489/* 1920x1080 (CVT)*/
490static struct crt_mode_table CRTM1920x1080[] = {
491 /*r_rate,hsp,vsp */
492 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
493 {REFRESH_60, M1920X1080_R60_HSP, M1920X1080_R60_VSP,
494 {2576, 1920, 1920, 656, 2048, 200, 1120, 1080, 1080, 40, 1083, 5} }
495};
496
497/* 1920x1080 (CVT with Reduce Blanking) */
498static struct crt_mode_table CRTM1920x1080_RB[] = {
499 /* r_rate, hsp, vsp */
500 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
501 {REFRESH_60, M1920X1080_RB_R60_HSP, M1920X1080_RB_R60_VSP,
502 {2080, 1920, 1920, 160, 1968, 32, 1111, 1080, 1080, 31, 1083, 5} }
503};
504
505/* 1920x1440*/
506static struct crt_mode_table CRTM1920x1440[] = {
507 /*r_rate,hsp,vsp */
508 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
509 {REFRESH_60, M1920X1440_R60_HSP, M1920X1440_R60_VSP,
510 {2600, 1920, 1920, 680, 2048, 208, 1500, 1440, 1440, 60, 1441,
511 3} },
512 {REFRESH_75, M1920X1440_R75_HSP, M1920X1440_R75_VSP,
513 {2640, 1920, 1920, 720, 2064, 224, 1500, 1440, 1440, 60, 1441, 3} }
514};
515
516/* 1400x1050 (CVT) */
517static struct crt_mode_table CRTM1400x1050[] = {
518 /* r_rate, hsp, vsp */
519 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
520 {REFRESH_60, M1400X1050_R60_HSP, M1400X1050_R60_VSP,
521 {1864, 1400, 1400, 464, 1488, 144, 1089, 1050, 1050, 39, 1053,
522 4} },
523 {REFRESH_75, M1400X1050_R75_HSP, M1400X1050_R75_VSP,
524 {1896, 1400, 1400, 496, 1504, 144, 1099, 1050, 1050, 49, 1053, 4} }
525};
526
527/* 1400x1050 (CVT Reduce Blanking) */
528static struct crt_mode_table CRTM1400x1050_RB[] = {
529 /* r_rate, hsp, vsp */
530 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
531 {REFRESH_60, M1400X1050_RB_R60_HSP, M1400X1050_RB_R60_VSP,
532 {1560, 1400, 1400, 160, 1448, 32, 1080, 1050, 1050, 30, 1053, 4} }
533};
534
535/* 960x600 (CVT) */
536static struct crt_mode_table CRTM960x600[] = {
537 /* r_rate, hsp, vsp */
538 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
539 {REFRESH_60, M960X600_R60_HSP, M960X600_R60_VSP,
540 {1216, 960, 960, 256, 992, 96, 624, 600, 600, 24, 603, 6} }
541};
542
543/* 1000x600 (GTF) */
544static struct crt_mode_table CRTM1000x600[] = {
545 /* r_rate, hsp, vsp */
546 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
547 {REFRESH_60, M1000X600_R60_HSP, M1000X600_R60_VSP,
548 {1288, 1000, 1000, 288, 1040, 104, 622, 600, 600, 22, 601, 3} }
549};
550
551/* 1024x576 (GTF) */
552static struct crt_mode_table CRTM1024x576[] = {
553 /* r_rate, hsp, vsp */
554 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
555 {REFRESH_60, M1024X576_R60_HSP, M1024X576_R60_VSP,
556 {1312, 1024, 1024, 288, 1064, 104, 597, 576, 576, 21, 577, 3} }
557};
558
559/* 1088x612 (CVT) */
560static struct crt_mode_table CRTM1088x612[] = {
561 /* r_rate, hsp, vsp */
562 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
563 {REFRESH_60, M1088X612_R60_HSP, M1088X612_R60_VSP,
564 {1392, 1088, 1088, 304, 1136, 104, 636, 612, 612, 24, 615, 5} }
565};
566
567/* 1152x720 (CVT) */
568static struct crt_mode_table CRTM1152x720[] = {
569 /* r_rate, hsp, vsp */
570 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
571 {REFRESH_60, M1152X720_R60_HSP, M1152X720_R60_VSP,
572 {1488, 1152, 1152, 336, 1208, 112, 748, 720, 720, 28, 723, 6} }
573};
574
575/* 1200x720 (GTF) */
576static struct crt_mode_table CRTM1200x720[] = {
577 /* r_rate, hsp, vsp */
578 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
579 {REFRESH_60, M1200X720_R60_HSP, M1200X720_R60_VSP,
580 {1568, 1200, 1200, 368, 1256, 128, 746, 720, 720, 26, 721, 3} }
581};
582
583/* 1200x900 (DCON) */
584static struct crt_mode_table DCON1200x900[] = {
585 /* r_rate, hsp, vsp */
586 {REFRESH_49, M1200X900_R60_HSP, M1200X900_R60_VSP,
587 /* The correct htotal is 1240, but this doesn't raster on VX855. */
588 /* Via suggested changing to a multiple of 16, hence 1264. */
589 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
590 {1264, 1200, 1200, 64, 1211, 32, 912, 900, 900, 12, 901, 10} }
591};
592
593/* 1280x600 (GTF) */
594static struct crt_mode_table CRTM1280x600[] = {
595 /* r_rate, hsp, vsp */
596 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
597 {REFRESH_60, M1280x600_R60_HSP, M1280x600_R60_VSP,
598 {1648, 1280, 1280, 368, 1336, 128, 622, 600, 600, 22, 601, 3} }
599};
600
601/* 1360x768 (CVT) */
602static struct crt_mode_table CRTM1360x768[] = {
603 /* r_rate, hsp, vsp */
604 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
605 {REFRESH_60, M1360X768_R60_HSP, M1360X768_R60_VSP,
606 {1776, 1360, 1360, 416, 1432, 136, 798, 768, 768, 30, 771, 5} }
607};
608
609/* 1360x768 (CVT Reduce Blanking) */
610static struct crt_mode_table CRTM1360x768_RB[] = {
611 /* r_rate, hsp, vsp */
612 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
613 {REFRESH_60, M1360X768_RB_R60_HSP, M1360X768_RB_R60_VSP,
614 {1520, 1360, 1360, 160, 1408, 32, 790, 768, 768, 22, 771, 5} }
615};
616
617/* 1366x768 (GTF) */
618static struct crt_mode_table CRTM1366x768[] = {
619 /* r_rate, hsp, vsp */
620 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
621 {REFRESH_60, M1368X768_R60_HSP, M1368X768_R60_VSP,
622 {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} },
623 {REFRESH_50, M1368X768_R50_HSP, M1368X768_R50_VSP,
624 {1768, 1368, 1368, 400, 1424, 144, 791, 768, 768, 23, 769, 3} }
625};
626
627/* 1440x900 (CVT) */
628static struct crt_mode_table CRTM1440x900[] = {
629 /* r_rate, hsp, vsp */
630 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
631 {REFRESH_60, M1440X900_R60_HSP, M1440X900_R60_VSP,
632 {1904, 1440, 1440, 464, 1520, 152, 934, 900, 900, 34, 903, 6} },
633 {REFRESH_75, M1440X900_R75_HSP, M1440X900_R75_VSP,
634 {1936, 1440, 1440, 496, 1536, 152, 942, 900, 900, 42, 903, 6} }
635};
636
637/* 1440x900 (CVT Reduce Blanking) */
638static struct crt_mode_table CRTM1440x900_RB[] = {
639 /* r_rate, hsp, vsp */
640 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
641 {REFRESH_60, M1440X900_RB_R60_HSP, M1440X900_RB_R60_VSP,
642 {1600, 1440, 1440, 160, 1488, 32, 926, 900, 900, 26, 903, 6} }
643};
644
645/* 1600x900 (CVT) */
646static struct crt_mode_table CRTM1600x900[] = {
647 /* r_rate, hsp, vsp */
648 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
649 {REFRESH_60, M1600X900_R60_HSP, M1600X900_R60_VSP,
650 {2112, 1600, 1600, 512, 1688, 168, 934, 900, 900, 34, 903, 5} }
651};
652
653/* 1600x900 (CVT Reduce Blanking) */
654static struct crt_mode_table CRTM1600x900_RB[] = {
655 /* r_rate, hsp, vsp */
656 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
657 {REFRESH_60, M1600X900_RB_R60_HSP, M1600X900_RB_R60_VSP,
658 {1760, 1600, 1600, 160, 1648, 32, 926, 900, 900, 26, 903, 5} }
659};
660
661/* 1600x1024 (GTF) */
662static struct crt_mode_table CRTM1600x1024[] = {
663 /* r_rate, hsp, vsp */
664 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
665 {REFRESH_60, M1600X1024_R60_HSP, M1600X1024_R60_VSP,
666 {2144, 1600, 1600, 544, 1704, 168, 1060, 1024, 1024, 36, 1025, 3} }
667};
668
669/* 1792x1344 (DMT) */
670static struct crt_mode_table CRTM1792x1344[] = {
671 /* r_rate, hsp, vsp */
672 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
673 {REFRESH_60, M1792x1344_R60_HSP, M1792x1344_R60_VSP,
674 {2448, 1792, 1792, 656, 1920, 200, 1394, 1344, 1344, 50, 1345, 3} }
675};
676
677/* 1856x1392 (DMT) */
678static struct crt_mode_table CRTM1856x1392[] = {
679 /* r_rate, hsp, vsp */
680 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
681 {REFRESH_60, M1856x1392_R60_HSP, M1856x1392_R60_VSP,
682 {2528, 1856, 1856, 672, 1952, 224, 1439, 1392, 1392, 47, 1393, 3} }
683};
684
685/* 1920x1200 (CVT) */
686static struct crt_mode_table CRTM1920x1200[] = {
687 /* r_rate, hsp, vsp */
688 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
689 {REFRESH_60, M1920X1200_R60_HSP, M1920X1200_R60_VSP,
690 {2592, 1920, 1920, 672, 2056, 200, 1245, 1200, 1200, 45, 1203, 6} }
691};
692
693/* 1920x1200 (CVT with Reduce Blanking) */
694static struct crt_mode_table CRTM1920x1200_RB[] = {
695 /* r_rate, hsp, vsp */
696 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
697 {REFRESH_60, M1920X1200_RB_R60_HSP, M1920X1200_RB_R60_VSP,
698 {2080, 1920, 1920, 160, 1968, 32, 1235, 1200, 1200, 35, 1203, 6} }
699};
700
701/* 2048x1536 (CVT) */
702static struct crt_mode_table CRTM2048x1536[] = {
703 /* r_rate, hsp, vsp */
704 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
705 {REFRESH_60, M2048x1536_R60_HSP, M2048x1536_R60_VSP,
706 {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} }
707};
708
709static struct VideoModeTable viafb_modes[] = {
710 /* Display : 480x640 (GTF) */
711 {CRTM480x640, ARRAY_SIZE(CRTM480x640)},
712
713 /* Display : 640x480 */
714 {CRTM640x480, ARRAY_SIZE(CRTM640x480)},
715
716 /* Display : 720x480 (GTF) */
717 {CRTM720x480, ARRAY_SIZE(CRTM720x480)},
718
719 /* Display : 720x576 (GTF) */
720 {CRTM720x576, ARRAY_SIZE(CRTM720x576)},
721
722 /* Display : 800x600 */
723 {CRTM800x600, ARRAY_SIZE(CRTM800x600)},
724
725 /* Display : 800x480 (CVT) */
726 {CRTM800x480, ARRAY_SIZE(CRTM800x480)},
727
728 /* Display : 848x480 (CVT) */
729 {CRTM848x480, ARRAY_SIZE(CRTM848x480)},
730
731 /* Display : 852x480 (GTF) */
732 {CRTM852x480, ARRAY_SIZE(CRTM852x480)},
733
734 /* Display : 1024x512 (GTF) */
735 {CRTM1024x512, ARRAY_SIZE(CRTM1024x512)},
736
737 /* Display : 1024x600 */
738 {CRTM1024x600, ARRAY_SIZE(CRTM1024x600)},
739
740 /* Display : 1024x768 */
741 {CRTM1024x768, ARRAY_SIZE(CRTM1024x768)},
742
743 /* Display : 1152x864 */
744 {CRTM1152x864, ARRAY_SIZE(CRTM1152x864)},
745
746 /* Display : 1280x768 (GTF) */
747 {CRTM1280x768, ARRAY_SIZE(CRTM1280x768)},
748
749 /* Display : 960x600 (CVT) */
750 {CRTM960x600, ARRAY_SIZE(CRTM960x600)},
751
752 /* Display : 1000x600 (GTF) */
753 {CRTM1000x600, ARRAY_SIZE(CRTM1000x600)},
754
755 /* Display : 1024x576 (GTF) */
756 {CRTM1024x576, ARRAY_SIZE(CRTM1024x576)},
757
758 /* Display : 1088x612 (GTF) */
759 {CRTM1088x612, ARRAY_SIZE(CRTM1088x612)},
760
761 /* Display : 1152x720 (CVT) */
762 {CRTM1152x720, ARRAY_SIZE(CRTM1152x720)},
763
764 /* Display : 1200x720 (GTF) */
765 {CRTM1200x720, ARRAY_SIZE(CRTM1200x720)},
766
767 /* Display : 1200x900 (DCON) */
768 {DCON1200x900, ARRAY_SIZE(DCON1200x900)},
769
770 /* Display : 1280x600 (GTF) */
771 {CRTM1280x600, ARRAY_SIZE(CRTM1280x600)},
772
773 /* Display : 1280x800 (CVT) */
774 {CRTM1280x800, ARRAY_SIZE(CRTM1280x800)},
775
776 /* Display : 1280x960 */
777 {CRTM1280x960, ARRAY_SIZE(CRTM1280x960)},
778
779 /* Display : 1280x1024 */
780 {CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)},
781
782 /* Display : 1360x768 (CVT) */
783 {CRTM1360x768, ARRAY_SIZE(CRTM1360x768)},
784
785 /* Display : 1366x768 */
786 {CRTM1366x768, ARRAY_SIZE(CRTM1366x768)},
787
788 /* Display : 1368x768 (GTF) */
789 {CRTM1368x768, ARRAY_SIZE(CRTM1368x768)},
790
791 /* Display : 1440x900 (CVT) */
792 {CRTM1440x900, ARRAY_SIZE(CRTM1440x900)},
793
794 /* Display : 1440x1050 (GTF) */
795 {CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)},
796
797 /* Display : 1600x900 (CVT) */
798 {CRTM1600x900, ARRAY_SIZE(CRTM1600x900)},
799
800 /* Display : 1600x1024 (GTF) */
801 {CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)},
802
803 /* Display : 1600x1200 */
804 {CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)},
805
806 /* Display : 1680x1050 (CVT) */
807 {CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)},
808
809 /* Display : 1792x1344 (DMT) */
810 {CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)},
811
812 /* Display : 1856x1392 (DMT) */
813 {CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)},
814
815 /* Display : 1920x1440 */
816 {CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)},
817
818 /* Display : 2048x1536 */
819 {CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)},
820
821 /* Display : 1280x720 */
822 {CRTM1280x720, ARRAY_SIZE(CRTM1280x720)},
823
824 /* Display : 1920x1080 (CVT) */
825 {CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)},
826
827 /* Display : 1920x1200 (CVT) */
828 {CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)},
829
830 /* Display : 1400x1050 (CVT) */
831 {CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)}
832};
833
834static struct VideoModeTable viafb_rb_modes[] = {
835 /* Display : 1360x768 (CVT Reduce Blanking) */
836 {CRTM1360x768_RB, ARRAY_SIZE(CRTM1360x768_RB)},
837
838 /* Display : 1440x900 (CVT Reduce Blanking) */
839 {CRTM1440x900_RB, ARRAY_SIZE(CRTM1440x900_RB)},
840
841 /* Display : 1400x1050 (CVT Reduce Blanking) */
842 {CRTM1400x1050_RB, ARRAY_SIZE(CRTM1400x1050_RB)},
843
844 /* Display : 1600x900 (CVT Reduce Blanking) */
845 {CRTM1600x900_RB, ARRAY_SIZE(CRTM1600x900_RB)},
846
847 /* Display : 1680x1050 (CVT Reduce Blanking) */
848 {CRTM1680x1050_RB, ARRAY_SIZE(CRTM1680x1050_RB)},
849
850 /* Display : 1920x1080 (CVT Reduce Blanking) */
851 {CRTM1920x1080_RB, ARRAY_SIZE(CRTM1920x1080_RB)},
852
853 /* Display : 1920x1200 (CVT Reduce Blanking) */
854 {CRTM1920x1200_RB, ARRAY_SIZE(CRTM1920x1200_RB)}
855};
856 343
857int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs); 344int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs);
858int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs); 345int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs);
@@ -863,56 +350,34 @@ int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs);
863int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); 350int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table);
864 351
865 352
866static struct VideoModeTable *get_modes(struct VideoModeTable *vmt, int n, 353static const struct fb_videomode *get_best_mode(
867 int hres, int vres) 354 const struct fb_videomode *modes, int n,
868{ 355 int hres, int vres, int refresh)
869 int i;
870
871 for (i = 0; i < n; i++)
872 if (vmt[i].mode_array &&
873 vmt[i].crtc[0].crtc.hor_addr == hres &&
874 vmt[i].crtc[0].crtc.ver_addr == vres)
875 return &viafb_modes[i];
876
877 return NULL;
878}
879
880static struct crt_mode_table *get_best_mode(struct VideoModeTable *vmt,
881 int refresh)
882{ 356{
883 struct crt_mode_table *best; 357 const struct fb_videomode *best = NULL;
884 int i; 358 int i;
885 359
886 if (!vmt) 360 for (i = 0; i < n; i++) {
887 return NULL; 361 if (modes[i].xres != hres || modes[i].yres != vres)
362 continue;
888 363
889 best = &vmt->crtc[0]; 364 if (!best || abs(modes[i].refresh - refresh) <
890 for (i = 1; i < vmt->mode_array; i++) { 365 abs(best->refresh - refresh))
891 if (abs(vmt->crtc[i].refresh_rate - refresh) 366 best = &modes[i];
892 < abs(best->refresh_rate - refresh))
893 best = &vmt->crtc[i];
894 } 367 }
895 368
896 return best; 369 return best;
897} 370}
898 371
899static struct VideoModeTable *viafb_get_mode(int hres, int vres) 372const struct fb_videomode *viafb_get_best_mode(int hres, int vres, int refresh)
900{
901 return get_modes(viafb_modes, ARRAY_SIZE(viafb_modes), hres, vres);
902}
903
904struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh)
905{ 373{
906 return get_best_mode(viafb_get_mode(hres, vres), refresh); 374 return get_best_mode(viafb_modes, ARRAY_SIZE(viafb_modes),
375 hres, vres, refresh);
907} 376}
908 377
909static struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) 378const struct fb_videomode *viafb_get_best_rb_mode(int hres, int vres,
910{ 379 int refresh)
911 return get_modes(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes), hres,
912 vres);
913}
914
915struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh)
916{ 380{
917 return get_best_mode(viafb_get_rb_mode(hres, vres), refresh); 381 return get_best_mode(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes),
382 hres, vres, refresh);
918} 383}
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
index 5917a2b00e1b..dd19106698e7 100644
--- a/drivers/video/via/viamode.h
+++ b/drivers/video/via/viamode.h
@@ -31,11 +31,6 @@ struct VPITTable {
31 unsigned char AR[StdAR]; 31 unsigned char AR[StdAR];
32}; 32};
33 33
34struct VideoModeTable {
35 struct crt_mode_table *crtc;
36 int mode_array;
37};
38
39struct patch_table { 34struct patch_table {
40 int table_length; 35 int table_length;
41 struct io_reg *io_reg_table; 36 struct io_reg *io_reg_table;
@@ -60,7 +55,9 @@ extern struct io_reg PM1024x768[];
60extern struct patch_table res_patch_table[]; 55extern struct patch_table res_patch_table[];
61extern struct VPITTable VPIT; 56extern struct VPITTable VPIT;
62 57
63struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh); 58const struct fb_videomode *viafb_get_best_mode(int hres, int vres,
64struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh); 59 int refresh);
60const struct fb_videomode *viafb_get_best_rb_mode(int hres, int vres,
61 int refresh);
65 62
66#endif /* __VIAMODE_H__ */ 63#endif /* __VIAMODE_H__ */
diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
index c0b018790f07..4ff57e81051d 100644
--- a/include/linux/omapfb.h
+++ b/include/linux/omapfb.h
@@ -222,41 +222,11 @@ struct omapfb_display_info {
222 222
223#include <plat/board.h> 223#include <plat/board.h>
224 224
225#ifdef CONFIG_ARCH_OMAP1
226#define OMAPFB_PLANE_NUM 1
227#else
228#define OMAPFB_PLANE_NUM 3
229#endif
230
231struct omapfb_mem_region {
232 u32 paddr;
233 void __iomem *vaddr;
234 unsigned long size;
235 u8 type; /* OMAPFB_PLANE_MEM_* */
236 enum omapfb_color_format format;/* OMAPFB_COLOR_* */
237 unsigned format_used:1; /* Must be set when format is set.
238 * Needed b/c of the badly chosen 0
239 * base for OMAPFB_COLOR_* values
240 */
241 unsigned alloc:1; /* allocated by the driver */
242 unsigned map:1; /* kernel mapped by the driver */
243};
244
245struct omapfb_mem_desc {
246 int region_cnt;
247 struct omapfb_mem_region region[OMAPFB_PLANE_NUM];
248};
249
250struct omapfb_platform_data { 225struct omapfb_platform_data {
251 struct omap_lcd_config lcd; 226 struct omap_lcd_config lcd;
252 struct omapfb_mem_desc mem_desc;
253 void *ctrl_platform_data;
254}; 227};
255 228
256/* in arch/arm/plat-omap/fb.c */ 229void __init omapfb_set_lcd_config(const struct omap_lcd_config *config);
257extern void omapfb_set_platform_data(struct omapfb_platform_data *data);
258extern void omapfb_set_ctrl_platform_data(void *pdata);
259extern void omapfb_reserve_sdram_memblock(void);
260 230
261#endif 231#endif
262 232
diff --git a/include/video/exynos_dp.h b/include/video/exynos_dp.h
new file mode 100644
index 000000000000..8847a9d6dd42
--- /dev/null
+++ b/include/video/exynos_dp.h
@@ -0,0 +1,131 @@
1/*
2 * Samsung SoC DP device support
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _EXYNOS_DP_H
13#define _EXYNOS_DP_H
14
15#define DP_TIMEOUT_LOOP_COUNT 100
16#define MAX_CR_LOOP 5
17#define MAX_EQ_LOOP 4
18
19enum link_rate_type {
20 LINK_RATE_1_62GBPS = 0x06,
21 LINK_RATE_2_70GBPS = 0x0a
22};
23
24enum link_lane_count_type {
25 LANE_COUNT1 = 1,
26 LANE_COUNT2 = 2,
27 LANE_COUNT4 = 4
28};
29
30enum link_training_state {
31 START,
32 CLOCK_RECOVERY,
33 EQUALIZER_TRAINING,
34 FINISHED,
35 FAILED
36};
37
38enum voltage_swing_level {
39 VOLTAGE_LEVEL_0,
40 VOLTAGE_LEVEL_1,
41 VOLTAGE_LEVEL_2,
42 VOLTAGE_LEVEL_3,
43};
44
45enum pre_emphasis_level {
46 PRE_EMPHASIS_LEVEL_0,
47 PRE_EMPHASIS_LEVEL_1,
48 PRE_EMPHASIS_LEVEL_2,
49 PRE_EMPHASIS_LEVEL_3,
50};
51
52enum pattern_set {
53 PRBS7,
54 D10_2,
55 TRAINING_PTN1,
56 TRAINING_PTN2,
57 DP_NONE
58};
59
60enum color_space {
61 COLOR_RGB,
62 COLOR_YCBCR422,
63 COLOR_YCBCR444
64};
65
66enum color_depth {
67 COLOR_6,
68 COLOR_8,
69 COLOR_10,
70 COLOR_12
71};
72
73enum color_coefficient {
74 COLOR_YCBCR601,
75 COLOR_YCBCR709
76};
77
78enum dynamic_range {
79 VESA,
80 CEA
81};
82
83enum pll_status {
84 PLL_UNLOCKED,
85 PLL_LOCKED
86};
87
88enum clock_recovery_m_value_type {
89 CALCULATED_M,
90 REGISTER_M
91};
92
93enum video_timing_recognition_type {
94 VIDEO_TIMING_FROM_CAPTURE,
95 VIDEO_TIMING_FROM_REGISTER
96};
97
98enum analog_power_block {
99 AUX_BLOCK,
100 CH0_BLOCK,
101 CH1_BLOCK,
102 CH2_BLOCK,
103 CH3_BLOCK,
104 ANALOG_TOTAL,
105 POWER_ALL
106};
107
108struct video_info {
109 char *name;
110
111 bool h_sync_polarity;
112 bool v_sync_polarity;
113 bool interlaced;
114
115 enum color_space color_space;
116 enum dynamic_range dynamic_range;
117 enum color_coefficient ycbcr_coeff;
118 enum color_depth color_depth;
119
120 enum link_rate_type link_rate;
121 enum link_lane_count_type lane_count;
122};
123
124struct exynos_dp_platdata {
125 struct video_info *video_info;
126
127 void (*phy_init)(void);
128 void (*phy_exit)(void);
129};
130
131#endif /* _EXYNOS_DP_H */
diff --git a/include/video/exynos_mipi_dsim.h b/include/video/exynos_mipi_dsim.h
new file mode 100644
index 000000000000..772c770535f1
--- /dev/null
+++ b/include/video/exynos_mipi_dsim.h
@@ -0,0 +1,359 @@
1/* include/video/exynos_mipi_dsim.h
2 *
3 * Platform data header for Samsung SoC MIPI-DSIM.
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae <inki.dae@samsung.com>
8 * Donghwa Lee <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#ifndef _EXYNOS_MIPI_DSIM_H
16#define _EXYNOS_MIPI_DSIM_H
17
18#include <linux/device.h>
19#include <linux/fb.h>
20
21#define PANEL_NAME_SIZE (32)
22
23/*
24 * Enumerate display interface type.
25 *
26 * DSIM_COMMAND means cpu interface and rgb interface for DSIM_VIDEO.
27 *
28 * P.S. MIPI DSI Master has two display controller intefaces, RGB Interface
29 * for main display and CPU Interface(same as I80 Interface) for main
30 * and sub display.
31 */
32enum mipi_dsim_interface_type {
33 DSIM_COMMAND,
34 DSIM_VIDEO
35};
36
37enum mipi_dsim_virtual_ch_no {
38 DSIM_VIRTUAL_CH_0,
39 DSIM_VIRTUAL_CH_1,
40 DSIM_VIRTUAL_CH_2,
41 DSIM_VIRTUAL_CH_3
42};
43
44enum mipi_dsim_burst_mode_type {
45 DSIM_NON_BURST_SYNC_EVENT,
46 DSIM_BURST_SYNC_EVENT,
47 DSIM_NON_BURST_SYNC_PULSE,
48 DSIM_BURST,
49 DSIM_NON_VIDEO_MODE
50};
51
52enum mipi_dsim_no_of_data_lane {
53 DSIM_DATA_LANE_1,
54 DSIM_DATA_LANE_2,
55 DSIM_DATA_LANE_3,
56 DSIM_DATA_LANE_4
57};
58
59enum mipi_dsim_byte_clk_src {
60 DSIM_PLL_OUT_DIV8,
61 DSIM_EXT_CLK_DIV8,
62 DSIM_EXT_CLK_BYPASS
63};
64
65enum mipi_dsim_pixel_format {
66 DSIM_CMD_3BPP,
67 DSIM_CMD_8BPP,
68 DSIM_CMD_12BPP,
69 DSIM_CMD_16BPP,
70 DSIM_VID_16BPP_565,
71 DSIM_VID_18BPP_666PACKED,
72 DSIM_18BPP_666LOOSELYPACKED,
73 DSIM_24BPP_888
74};
75
76/*
77 * struct mipi_dsim_config - interface for configuring mipi-dsi controller.
78 *
79 * @auto_flush: enable or disable Auto flush of MD FIFO using VSYNC pulse.
80 * @eot_disable: enable or disable EoT packet in HS mode.
81 * @auto_vertical_cnt: specifies auto vertical count mode.
82 * in Video mode, the vertical line transition uses line counter
83 * configured by VSA, VBP, and Vertical resolution.
84 * If this bit is set to '1', the line counter does not use VSA and VBP
85 * registers.(in command mode, this variable is ignored)
86 * @hse: set horizontal sync event mode.
87 * In VSYNC pulse and Vporch area, MIPI DSI master transfers only HSYNC
88 * start packet to MIPI DSI slave at MIPI DSI spec1.1r02.
89 * this bit transfers HSYNC end packet in VSYNC pulse and Vporch area
90 * (in mommand mode, this variable is ignored)
91 * @hfp: specifies HFP disable mode.
92 * if this variable is set, DSI master ignores HFP area in VIDEO mode.
93 * (in command mode, this variable is ignored)
94 * @hbp: specifies HBP disable mode.
95 * if this variable is set, DSI master ignores HBP area in VIDEO mode.
96 * (in command mode, this variable is ignored)
97 * @hsa: specifies HSA disable mode.
98 * if this variable is set, DSI master ignores HSA area in VIDEO mode.
99 * (in command mode, this variable is ignored)
100 * @cma_allow: specifies the number of horizontal lines, where command packet
101 * transmission is allowed after Stable VFP period.
102 * @e_interface: specifies interface to be used.(CPU or RGB interface)
103 * @e_virtual_ch: specifies virtual channel number that main or
104 * sub diaplsy uses.
105 * @e_pixel_format: specifies pixel stream format for main or sub display.
106 * @e_burst_mode: selects Burst mode in Video mode.
107 * in Non-burst mode, RGB data area is filled with RGB data and NULL
108 * packets, according to input bandwidth of RGB interface.
109 * In Burst mode, RGB data area is filled with RGB data only.
110 * @e_no_data_lane: specifies data lane count to be used by Master.
111 * @e_byte_clk: select byte clock source. (it must be DSIM_PLL_OUT_DIV8)
112 * DSIM_EXT_CLK_DIV8 and DSIM_EXT_CLK_BYPASSS are not supported.
113 * @pll_stable_time: specifies the PLL Timer for stability of the ganerated
114 * clock(System clock cycle base)
115 * if the timer value goes to 0x00000000, the clock stable bit of status
116 * and interrupt register is set.
117 * @esc_clk: specifies escape clock frequency for getting the escape clock
118 * prescaler value.
119 * @stop_holding_cnt: specifies the interval value between transmitting
120 * read packet(or write "set_tear_on" command) and BTA request.
121 * after transmitting read packet or write "set_tear_on" command,
122 * BTA requests to D-PHY automatically. this counter value specifies
123 * the interval between them.
124 * @bta_timeout: specifies the timer for BTA.
125 * this register specifies time out from BTA request to change
126 * the direction with respect to Tx escape clock.
127 * @rx_timeout: specifies the timer for LP Rx mode timeout.
128 * this register specifies time out on how long RxValid deasserts,
129 * after RxLpdt asserts with respect to Tx escape clock.
130 * - RxValid specifies Rx data valid indicator.
131 * - RxLpdt specifies an indicator that D-PHY is under RxLpdt mode.
132 * - RxValid and RxLpdt specifies signal from D-PHY.
133 */
134struct mipi_dsim_config {
135 unsigned char auto_flush;
136 unsigned char eot_disable;
137
138 unsigned char auto_vertical_cnt;
139 unsigned char hse;
140 unsigned char hfp;
141 unsigned char hbp;
142 unsigned char hsa;
143 unsigned char cmd_allow;
144
145 enum mipi_dsim_interface_type e_interface;
146 enum mipi_dsim_virtual_ch_no e_virtual_ch;
147 enum mipi_dsim_pixel_format e_pixel_format;
148 enum mipi_dsim_burst_mode_type e_burst_mode;
149 enum mipi_dsim_no_of_data_lane e_no_data_lane;
150 enum mipi_dsim_byte_clk_src e_byte_clk;
151
152 /*
153 * ===========================================
154 * | P | M | S | MHz |
155 * -------------------------------------------
156 * | 3 | 100 | 3 | 100 |
157 * | 3 | 100 | 2 | 200 |
158 * | 3 | 63 | 1 | 252 |
159 * | 4 | 100 | 1 | 300 |
160 * | 4 | 110 | 1 | 330 |
161 * | 12 | 350 | 1 | 350 |
162 * | 3 | 100 | 1 | 400 |
163 * | 4 | 150 | 1 | 450 |
164 * | 6 | 118 | 1 | 472 |
165 * | 3 | 120 | 1 | 480 |
166 * | 12 | 250 | 0 | 500 |
167 * | 4 | 100 | 0 | 600 |
168 * | 3 | 81 | 0 | 648 |
169 * | 3 | 88 | 0 | 704 |
170 * | 3 | 90 | 0 | 720 |
171 * | 3 | 100 | 0 | 800 |
172 * | 12 | 425 | 0 | 850 |
173 * | 4 | 150 | 0 | 900 |
174 * | 12 | 475 | 0 | 950 |
175 * | 6 | 250 | 0 | 1000 |
176 * -------------------------------------------
177 */
178
179 /*
180 * pms could be calculated as the following.
181 * M * 24 / P * 2 ^ S = MHz
182 */
183 unsigned char p;
184 unsigned short m;
185 unsigned char s;
186
187 unsigned int pll_stable_time;
188 unsigned long esc_clk;
189
190 unsigned short stop_holding_cnt;
191 unsigned char bta_timeout;
192 unsigned short rx_timeout;
193};
194
195/*
196 * struct mipi_dsim_device - global interface for mipi-dsi driver.
197 *
198 * @dev: driver model representation of the device.
199 * @id: unique device id.
200 * @clock: pointer to MIPI-DSI clock of clock framework.
201 * @irq: interrupt number to MIPI-DSI controller.
202 * @reg_base: base address to memory mapped SRF of MIPI-DSI controller.
203 * (virtual address)
204 * @lock: the mutex protecting this data structure.
205 * @dsim_info: infomation for configuring mipi-dsi controller.
206 * @master_ops: callbacks to mipi-dsi operations.
207 * @dsim_lcd_dev: pointer to activated ddi device.
208 * (it would be registered by mipi-dsi driver.)
209 * @dsim_lcd_drv: pointer to activated_ddi driver.
210 * (it would be registered by mipi-dsi driver.)
211 * @lcd_info: pointer to mipi_lcd_info structure.
212 * @state: specifies status of MIPI-DSI controller.
213 * the status could be RESET, INIT, STOP, HSCLKEN and ULPS.
214 * @data_lane: specifiec enabled data lane number.
215 * this variable would be set by driver according to e_no_data_lane
216 * automatically.
217 * @e_clk_src: select byte clock source.
218 * @pd: pointer to MIPI-DSI driver platform data.
219 */
220struct mipi_dsim_device {
221 struct device *dev;
222 int id;
223 struct resource *res;
224 struct clk *clock;
225 unsigned int irq;
226 void __iomem *reg_base;
227 struct mutex lock;
228
229 struct mipi_dsim_config *dsim_config;
230 struct mipi_dsim_master_ops *master_ops;
231 struct mipi_dsim_lcd_device *dsim_lcd_dev;
232 struct mipi_dsim_lcd_driver *dsim_lcd_drv;
233
234 unsigned int state;
235 unsigned int data_lane;
236 unsigned int e_clk_src;
237 bool suspended;
238
239 struct mipi_dsim_platform_data *pd;
240};
241
242/*
243 * struct mipi_dsim_platform_data - interface to platform data
244 * for mipi-dsi driver.
245 *
246 * @lcd_panel_name: specifies lcd panel name registered to mipi-dsi driver.
247 * lcd panel driver searched would be actived.
248 * @dsim_config: pointer of structure for configuring mipi-dsi controller.
249 * @enabled: indicate whether mipi controller got enabled or not.
250 * @lcd_panel_info: pointer for lcd panel specific structure.
251 * this structure specifies width, height, timing and polarity and so on.
252 * @phy_enable: pointer to a callback controlling D-PHY enable/reset
253 */
254struct mipi_dsim_platform_data {
255 char lcd_panel_name[PANEL_NAME_SIZE];
256
257 struct mipi_dsim_config *dsim_config;
258 unsigned int enabled;
259 void *lcd_panel_info;
260
261 int (*phy_enable)(struct platform_device *pdev, bool on);
262};
263
264/*
265 * struct mipi_dsim_master_ops - callbacks to mipi-dsi operations.
266 *
267 * @cmd_write: transfer command to lcd panel at LP mode.
268 * @cmd_read: read command from rx register.
269 * @get_dsim_frame_done: get the status that all screen data have been
270 * transferred to mipi-dsi.
271 * @clear_dsim_frame_done: clear frame done status.
272 * @get_fb_frame_done: get frame done status of display controller.
273 * @trigger: trigger display controller.
274 * - this one would be used only in case of CPU mode.
275 * @set_early_blank_mode: set framebuffer blank mode.
276 * - this callback should be called prior to fb_blank() by a client driver
277 * only if needing.
278 * @set_blank_mode: set framebuffer blank mode.
279 * - this callback should be called after fb_blank() by a client driver
280 * only if needing.
281 */
282
283struct mipi_dsim_master_ops {
284 int (*cmd_write)(struct mipi_dsim_device *dsim, unsigned int data_id,
285 const unsigned char *data0, unsigned int data1);
286 int (*cmd_read)(struct mipi_dsim_device *dsim, unsigned int data_id,
287 unsigned int data0, unsigned int req_size, u8 *rx_buf);
288 int (*get_dsim_frame_done)(struct mipi_dsim_device *dsim);
289 int (*clear_dsim_frame_done)(struct mipi_dsim_device *dsim);
290
291 int (*get_fb_frame_done)(struct fb_info *info);
292 void (*trigger)(struct fb_info *info);
293 int (*set_early_blank_mode)(struct mipi_dsim_device *dsim, int power);
294 int (*set_blank_mode)(struct mipi_dsim_device *dsim, int power);
295};
296
297/*
298 * device structure for mipi-dsi based lcd panel.
299 *
300 * @name: name of the device to use with this device, or an
301 * alias for that name.
302 * @dev: driver model representation of the device.
303 * @id: id of device to be registered.
304 * @bus_id: bus id for identifing connected bus
305 * and this bus id should be same as id of mipi_dsim_device.
306 * @irq: irq number for signaling when framebuffer transfer of
307 * lcd panel module is completed.
308 * this irq would be used only for MIPI-DSI based CPU mode lcd panel.
309 * @master: pointer to mipi-dsi master device object.
310 * @platform_data: lcd panel specific platform data.
311 */
312struct mipi_dsim_lcd_device {
313 char *name;
314 struct device dev;
315 int id;
316 int bus_id;
317 int irq;
318
319 struct mipi_dsim_device *master;
320 void *platform_data;
321};
322
323/*
324 * driver structure for mipi-dsi based lcd panel.
325 *
326 * this structure should be registered by lcd panel driver.
327 * mipi-dsi driver seeks lcd panel registered through name field
328 * and calls these callback functions in appropriate time.
329 *
330 * @name: name of the driver to use with this device, or an
331 * alias for that name.
332 * @id: id of driver to be registered.
333 * this id would be used for finding device object registered.
334 */
335struct mipi_dsim_lcd_driver {
336 char *name;
337 int id;
338
339 void (*power_on)(struct mipi_dsim_lcd_device *dsim_dev, int enable);
340 void (*set_sequence)(struct mipi_dsim_lcd_device *dsim_dev);
341 int (*probe)(struct mipi_dsim_lcd_device *dsim_dev);
342 int (*remove)(struct mipi_dsim_lcd_device *dsim_dev);
343 void (*shutdown)(struct mipi_dsim_lcd_device *dsim_dev);
344 int (*suspend)(struct mipi_dsim_lcd_device *dsim_dev);
345 int (*resume)(struct mipi_dsim_lcd_device *dsim_dev);
346};
347
348/*
349 * register mipi_dsim_lcd_device to mipi-dsi master.
350 */
351int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device
352 *lcd_dev);
353/**
354 * register mipi_dsim_lcd_driver object defined by lcd panel driver
355 * to mipi-dsi driver.
356 */
357int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver
358 *lcd_drv);
359#endif /* _EXYNOS_MIPI_DSIM_H */
diff --git a/include/video/sh_mipi_dsi.h b/include/video/sh_mipi_dsi.h
index 434d56b4a1a5..06c67fbc4eee 100644
--- a/include/video/sh_mipi_dsi.h
+++ b/include/video/sh_mipi_dsi.h
@@ -51,6 +51,7 @@ struct sh_mipi_dsi_info {
51 int lane; 51 int lane;
52 unsigned long flags; 52 unsigned long flags;
53 u32 clksrc; 53 u32 clksrc;
54 u32 phyctrl; /* for extra setting */
54 unsigned int vsynw_offset; 55 unsigned int vsynw_offset;
55 int (*set_dot_clock)(struct platform_device *pdev, 56 int (*set_dot_clock)(struct platform_device *pdev,
56 void __iomem *base, 57 void __iomem *base,
diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h
index b56932927d0a..728f9de9c258 100644
--- a/include/video/sh_mobile_hdmi.h
+++ b/include/video/sh_mobile_hdmi.h
@@ -31,8 +31,6 @@ struct clk;
31#define HDMI_SND_SRC_HBR (3 << 0) 31#define HDMI_SND_SRC_HBR (3 << 0)
32 32
33struct sh_mobile_hdmi_info { 33struct sh_mobile_hdmi_info {
34 struct sh_mobile_lcdc_chan_cfg *lcd_chan;
35 struct device *lcd_dev;
36 unsigned int flags; 34 unsigned int flags;
37 long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq, 35 long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq,
38 unsigned long *parent_freq); 36 unsigned long *parent_freq);
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index fe30b759c51e..7571b27a0ba1 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -147,29 +147,23 @@ struct sh_mobile_lcdc_sys_bus_ops {
147 unsigned long (*read_data)(void *handle); 147 unsigned long (*read_data)(void *handle);
148}; 148};
149 149
150struct module; 150struct sh_mobile_lcdc_panel_cfg {
151struct sh_mobile_lcdc_board_cfg { 151 unsigned long width; /* Panel width in mm */
152 struct module *owner; 152 unsigned long height; /* Panel height in mm */
153 void *board_data; 153 int (*setup_sys)(void *sys_ops_handle,
154 int (*setup_sys)(void *board_data, void *sys_ops_handle,
155 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 154 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
156 void (*start_transfer)(void *board_data, void *sys_ops_handle, 155 void (*start_transfer)(void *sys_ops_handle,
157 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 156 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
158 void (*display_on)(void *board_data, struct fb_info *info); 157 void (*display_on)(void);
159 void (*display_off)(void *board_data); 158 void (*display_off)(void);
160 int (*set_brightness)(void *board_data, int brightness);
161 int (*get_brightness)(void *board_data);
162};
163
164struct sh_mobile_lcdc_lcd_size_cfg { /* width and height of panel in mm */
165 unsigned long width;
166 unsigned long height;
167}; 159};
168 160
169/* backlight info */ 161/* backlight info */
170struct sh_mobile_lcdc_bl_info { 162struct sh_mobile_lcdc_bl_info {
171 const char *name; 163 const char *name;
172 int max_brightness; 164 int max_brightness;
165 int (*set_brightness)(int brightness);
166 int (*get_brightness)(void);
173}; 167};
174 168
175struct sh_mobile_lcdc_chan_cfg { 169struct sh_mobile_lcdc_chan_cfg {
@@ -179,13 +173,14 @@ struct sh_mobile_lcdc_chan_cfg {
179 int interface_type; /* selects RGBn or SYSn I/F, see above */ 173 int interface_type; /* selects RGBn or SYSn I/F, see above */
180 int clock_divider; 174 int clock_divider;
181 unsigned long flags; /* LCDC_FLAGS_... */ 175 unsigned long flags; /* LCDC_FLAGS_... */
182 const struct fb_videomode *lcd_cfg; 176 const struct fb_videomode *lcd_modes;
183 int num_cfg; 177 int num_modes;
184 struct sh_mobile_lcdc_lcd_size_cfg lcd_size_cfg; 178 struct sh_mobile_lcdc_panel_cfg panel_cfg;
185 struct sh_mobile_lcdc_board_cfg board_cfg;
186 struct sh_mobile_lcdc_bl_info bl_info; 179 struct sh_mobile_lcdc_bl_info bl_info;
187 struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */ 180 struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */
188 struct sh_mobile_meram_cfg *meram_cfg; 181 const struct sh_mobile_meram_cfg *meram_cfg;
182
183 struct platform_device *tx_dev; /* HDMI/DSI transmitter device */
189}; 184};
190 185
191struct sh_mobile_lcdc_info { 186struct sh_mobile_lcdc_info {
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
index af602d602b28..29b2fd3b147e 100644
--- a/include/video/sh_mobile_meram.h
+++ b/include/video/sh_mobile_meram.h
@@ -17,52 +17,47 @@ enum {
17struct sh_mobile_meram_priv; 17struct sh_mobile_meram_priv;
18struct sh_mobile_meram_ops; 18struct sh_mobile_meram_ops;
19 19
20/*
21 * struct sh_mobile_meram_info - MERAM platform data
22 * @reserved_icbs: Bitmask of reserved ICBs (for instance used through UIO)
23 */
20struct sh_mobile_meram_info { 24struct sh_mobile_meram_info {
21 int addr_mode; 25 int addr_mode;
26 u32 reserved_icbs;
22 struct sh_mobile_meram_ops *ops; 27 struct sh_mobile_meram_ops *ops;
23 struct sh_mobile_meram_priv *priv; 28 struct sh_mobile_meram_priv *priv;
24 struct platform_device *pdev; 29 struct platform_device *pdev;
25}; 30};
26 31
27/* icb config */ 32/* icb config */
28struct sh_mobile_meram_icb { 33struct sh_mobile_meram_icb_cfg {
29 int marker_icb; /* ICB # for Marker ICB */ 34 unsigned int meram_size; /* MERAM Buffer Size to use */
30 int cache_icb; /* ICB # for Cache ICB */
31 int meram_offset; /* MERAM Buffer Offset to use */
32 int meram_size; /* MERAM Buffer Size to use */
33
34 int cache_unit; /* bytes to cache per ICB */
35}; 35};
36 36
37struct sh_mobile_meram_cfg { 37struct sh_mobile_meram_cfg {
38 struct sh_mobile_meram_icb icb[2]; 38 struct sh_mobile_meram_icb_cfg icb[2];
39 int pixelformat;
40 int current_reg;
41}; 39};
42 40
43struct module; 41struct module;
44struct sh_mobile_meram_ops { 42struct sh_mobile_meram_ops {
45 struct module *module; 43 struct module *module;
46 /* register usage of meram */ 44 /* register usage of meram */
47 int (*meram_register)(struct sh_mobile_meram_info *meram_dev, 45 void *(*meram_register)(struct sh_mobile_meram_info *meram_dev,
48 struct sh_mobile_meram_cfg *cfg, 46 const struct sh_mobile_meram_cfg *cfg,
49 int xres, int yres, int pixelformat, 47 unsigned int xres, unsigned int yres,
50 unsigned long base_addr_y, 48 unsigned int pixelformat,
51 unsigned long base_addr_c, 49 unsigned int *pitch);
52 unsigned long *icb_addr_y,
53 unsigned long *icb_addr_c, int *pitch);
54 50
55 /* unregister usage of meram */ 51 /* unregister usage of meram */
56 int (*meram_unregister)(struct sh_mobile_meram_info *meram_dev, 52 void (*meram_unregister)(struct sh_mobile_meram_info *meram_dev,
57 struct sh_mobile_meram_cfg *cfg); 53 void *data);
58 54
59 /* update meram settings */ 55 /* update meram settings */
60 int (*meram_update)(struct sh_mobile_meram_info *meram_dev, 56 void (*meram_update)(struct sh_mobile_meram_info *meram_dev, void *data,
61 struct sh_mobile_meram_cfg *cfg, 57 unsigned long base_addr_y,
62 unsigned long base_addr_y, 58 unsigned long base_addr_c,
63 unsigned long base_addr_c, 59 unsigned long *icb_addr_y,
64 unsigned long *icb_addr_y, 60 unsigned long *icb_addr_c);
65 unsigned long *icb_addr_c);
66}; 61};
67 62
68#endif /* __VIDEO_SH_MOBILE_MERAM_H__ */ 63#endif /* __VIDEO_SH_MOBILE_MERAM_H__ */
diff --git a/include/video/udlfb.h b/include/video/udlfb.h
index c41f308c9636..f9466fa54ba4 100644
--- a/include/video/udlfb.h
+++ b/include/video/udlfb.h
@@ -41,6 +41,7 @@ struct dlfb_data {
41 char *backing_buffer; 41 char *backing_buffer;
42 int fb_count; 42 int fb_count;
43 bool virtualized; /* true when physical usb device not present */ 43 bool virtualized; /* true when physical usb device not present */
44 struct delayed_work init_framebuffer_work;
44 struct delayed_work free_framebuffer_work; 45 struct delayed_work free_framebuffer_work;
45 atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */ 46 atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
46 atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */ 47 atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */