From 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 Mon Sep 17 00:00:00 2001 From: Yunhong Jiang Date: Tue, 4 Aug 2015 12:17:53 -0700 Subject: Add the rt linux 4.1.3-rt3 as base Import the rt linux 4.1.3-rt3 as OPNFV kvm base. It's from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-4.1.y-rt and the base is: commit 0917f823c59692d751951bf5ea699a2d1e2f26a2 Author: Sebastian Andrzej Siewior Date: Sat Jul 25 12:13:34 2015 +0200 Prepare v4.1.3-rt3 Signed-off-by: Sebastian Andrzej Siewior We lose all the git history this way and it's not good. We should apply another opnfv project repo in future. Change-Id: I87543d81c9df70d99c5001fbdf646b202c19f423 Signed-off-by: Yunhong Jiang --- kernel/drivers/video/Kconfig | 55 + kernel/drivers/video/Makefile | 13 + kernel/drivers/video/backlight/88pm860x_bl.c | 274 + kernel/drivers/video/backlight/Kconfig | 456 + kernel/drivers/video/backlight/Makefile | 56 + kernel/drivers/video/backlight/aat2870_bl.c | 233 + kernel/drivers/video/backlight/adp5520_bl.c | 389 + kernel/drivers/video/backlight/adp8860_bl.c | 822 ++ kernel/drivers/video/backlight/adp8870_bl.c | 995 ++ kernel/drivers/video/backlight/ams369fg06.c | 571 + kernel/drivers/video/backlight/apple_bl.c | 257 + kernel/drivers/video/backlight/as3711_bl.c | 479 + kernel/drivers/video/backlight/backlight.c | 601 + kernel/drivers/video/backlight/bd6107.c | 207 + kernel/drivers/video/backlight/corgi_lcd.c | 613 + kernel/drivers/video/backlight/cr_bllcd.c | 288 + kernel/drivers/video/backlight/da903x_bl.c | 175 + kernel/drivers/video/backlight/da9052_bl.c | 185 + kernel/drivers/video/backlight/ep93xx_bl.c | 141 + kernel/drivers/video/backlight/generic_bl.c | 119 + kernel/drivers/video/backlight/gpio_backlight.c | 164 + kernel/drivers/video/backlight/hp680_bl.c | 175 + kernel/drivers/video/backlight/hx8357.c | 682 ++ kernel/drivers/video/backlight/ili922x.c | 551 + kernel/drivers/video/backlight/ili9320.c | 303 + kernel/drivers/video/backlight/ili9320.h | 80 + kernel/drivers/video/backlight/ipaq_micro_bl.c | 83 + kernel/drivers/video/backlight/jornada720_bl.c | 154 + kernel/drivers/video/backlight/jornada720_lcd.c | 131 + kernel/drivers/video/backlight/kb3886_bl.c | 197 + kernel/drivers/video/backlight/l4f00242t03.c | 269 + kernel/drivers/video/backlight/lcd.c | 364 + kernel/drivers/video/backlight/ld9040.c | 812 ++ kernel/drivers/video/backlight/ld9040_gamma.h | 202 + kernel/drivers/video/backlight/lm3533_bl.c | 411 + kernel/drivers/video/backlight/lm3630a_bl.c | 483 + kernel/drivers/video/backlight/lm3639_bl.c | 432 + kernel/drivers/video/backlight/lms283gf05.c | 204 + kernel/drivers/video/backlight/lms501kf03.c | 437 + kernel/drivers/video/backlight/locomolcd.c | 255 + kernel/drivers/video/backlight/lp855x_bl.c | 518 + kernel/drivers/video/backlight/lp8788_bl.c | 325 + kernel/drivers/video/backlight/ltv350qv.c | 312 + kernel/drivers/video/backlight/ltv350qv.h | 95 + kernel/drivers/video/backlight/lv5207lp.c | 164 + kernel/drivers/video/backlight/max8925_bl.c | 209 + kernel/drivers/video/backlight/omap1_bl.c | 188 + kernel/drivers/video/backlight/ot200_bl.c | 165 + kernel/drivers/video/backlight/pandora_bl.c | 154 + .../drivers/video/backlight/pcf50633-backlight.c | 164 + kernel/drivers/video/backlight/platform_lcd.c | 161 + kernel/drivers/video/backlight/pwm_bl.c | 412 + kernel/drivers/video/backlight/s6e63m0.c | 858 ++ kernel/drivers/video/backlight/s6e63m0_gamma.h | 266 + .../drivers/video/backlight/sky81452-backlight.c | 353 + kernel/drivers/video/backlight/tdo24m.c | 453 + kernel/drivers/video/backlight/tosa_bl.c | 178 + kernel/drivers/video/backlight/tosa_lcd.c | 278 + kernel/drivers/video/backlight/tps65217_bl.c | 334 + kernel/drivers/video/backlight/vgg2432a4.c | 267 + kernel/drivers/video/backlight/wm831x_bl.c | 230 + kernel/drivers/video/console/Kconfig | 144 + kernel/drivers/video/console/Makefile | 19 + kernel/drivers/video/console/bitblit.c | 422 + kernel/drivers/video/console/dummycon.c | 77 + kernel/drivers/video/console/fbcon.c | 3654 ++++++ kernel/drivers/video/console/fbcon.h | 264 + kernel/drivers/video/console/fbcon_ccw.c | 424 + kernel/drivers/video/console/fbcon_cw.c | 407 + kernel/drivers/video/console/fbcon_rotate.c | 116 + kernel/drivers/video/console/fbcon_rotate.h | 96 + kernel/drivers/video/console/fbcon_ud.c | 452 + kernel/drivers/video/console/mdacon.c | 607 + kernel/drivers/video/console/newport_con.c | 802 ++ kernel/drivers/video/console/softcursor.c | 82 + kernel/drivers/video/console/sticon.c | 395 + kernel/drivers/video/console/sticore.c | 1119 ++ kernel/drivers/video/console/tileblit.c | 159 + kernel/drivers/video/console/vgacon.c | 1446 +++ kernel/drivers/video/display_timing.c | 24 + kernel/drivers/video/fbdev/68328fb.c | 497 + kernel/drivers/video/fbdev/Kconfig | 2483 +++++ kernel/drivers/video/fbdev/Makefile | 154 + kernel/drivers/video/fbdev/acornfb.c | 1143 ++ kernel/drivers/video/fbdev/acornfb.h | 169 + kernel/drivers/video/fbdev/amba-clcd-versatile.c | 182 + kernel/drivers/video/fbdev/amba-clcd.c | 932 ++ kernel/drivers/video/fbdev/amifb.c | 3791 +++++++ kernel/drivers/video/fbdev/arcfb.c | 667 ++ kernel/drivers/video/fbdev/arkfb.c | 1231 +++ kernel/drivers/video/fbdev/asiliantfb.c | 624 ++ kernel/drivers/video/fbdev/atafb.c | 3268 ++++++ kernel/drivers/video/fbdev/atafb.h | 36 + kernel/drivers/video/fbdev/atafb_iplan2p2.c | 293 + kernel/drivers/video/fbdev/atafb_iplan2p4.c | 308 + kernel/drivers/video/fbdev/atafb_iplan2p8.c | 345 + kernel/drivers/video/fbdev/atafb_mfb.c | 112 + kernel/drivers/video/fbdev/atafb_utils.h | 400 + kernel/drivers/video/fbdev/atmel_lcdfb.c | 1476 +++ kernel/drivers/video/fbdev/aty/Makefile | 15 + kernel/drivers/video/fbdev/aty/ati_ids.h | 214 + kernel/drivers/video/fbdev/aty/aty128fb.c | 2632 +++++ kernel/drivers/video/fbdev/aty/atyfb.h | 369 + kernel/drivers/video/fbdev/aty/atyfb_base.c | 4026 +++++++ kernel/drivers/video/fbdev/aty/mach64_accel.c | 430 + kernel/drivers/video/fbdev/aty/mach64_ct.c | 649 ++ kernel/drivers/video/fbdev/aty/mach64_cursor.c | 225 + kernel/drivers/video/fbdev/aty/mach64_gx.c | 910 ++ kernel/drivers/video/fbdev/aty/radeon_accel.c | 328 + kernel/drivers/video/fbdev/aty/radeon_backlight.c | 215 + kernel/drivers/video/fbdev/aty/radeon_base.c | 2568 +++++ kernel/drivers/video/fbdev/aty/radeon_i2c.c | 167 + kernel/drivers/video/fbdev/aty/radeon_monitor.c | 1052 ++ kernel/drivers/video/fbdev/aty/radeon_pm.c | 2906 +++++ kernel/drivers/video/fbdev/aty/radeonfb.h | 634 ++ kernel/drivers/video/fbdev/au1100fb.c | 650 ++ kernel/drivers/video/fbdev/au1100fb.h | 378 + kernel/drivers/video/fbdev/au1200fb.c | 1852 ++++ kernel/drivers/video/fbdev/au1200fb.h | 572 + kernel/drivers/video/fbdev/auo_k1900fb.c | 204 + kernel/drivers/video/fbdev/auo_k1901fb.c | 257 + kernel/drivers/video/fbdev/auo_k190x.c | 1198 ++ kernel/drivers/video/fbdev/auo_k190x.h | 129 + kernel/drivers/video/fbdev/bf537-lq035.c | 914 ++ kernel/drivers/video/fbdev/bf54x-lq043fb.c | 764 ++ kernel/drivers/video/fbdev/bfin-lq035q1-fb.c | 864 ++ kernel/drivers/video/fbdev/bfin-t350mcqb-fb.c | 669 ++ kernel/drivers/video/fbdev/bfin_adv7393fb.c | 827 ++ kernel/drivers/video/fbdev/bfin_adv7393fb.h | 321 + kernel/drivers/video/fbdev/broadsheetfb.c | 1224 ++ kernel/drivers/video/fbdev/bt431.h | 235 + kernel/drivers/video/fbdev/bt455.h | 94 + kernel/drivers/video/fbdev/bw2.c | 405 + kernel/drivers/video/fbdev/c2p.h | 19 + kernel/drivers/video/fbdev/c2p_core.h | 153 + kernel/drivers/video/fbdev/c2p_iplan2.c | 153 + kernel/drivers/video/fbdev/c2p_planar.c | 156 + kernel/drivers/video/fbdev/carminefb.c | 788 ++ kernel/drivers/video/fbdev/carminefb.h | 64 + kernel/drivers/video/fbdev/carminefb_regs.h | 159 + kernel/drivers/video/fbdev/cg14.c | 625 ++ kernel/drivers/video/fbdev/cg3.c | 491 + kernel/drivers/video/fbdev/cg6.c | 884 ++ kernel/drivers/video/fbdev/chipsfb.c | 519 + kernel/drivers/video/fbdev/cirrusfb.c | 2952 +++++ kernel/drivers/video/fbdev/clps711x-fb.c | 396 + kernel/drivers/video/fbdev/clps711xfb.c | 314 + kernel/drivers/video/fbdev/cobalt_lcdfb.c | 400 + kernel/drivers/video/fbdev/controlfb.c | 1089 ++ kernel/drivers/video/fbdev/controlfb.h | 145 + kernel/drivers/video/fbdev/core/Makefile | 17 + kernel/drivers/video/fbdev/core/cfbcopyarea.c | 437 + kernel/drivers/video/fbdev/core/cfbfillrect.c | 371 + kernel/drivers/video/fbdev/core/cfbimgblt.c | 313 + kernel/drivers/video/fbdev/core/fb_cmdline.c | 110 + kernel/drivers/video/fbdev/core/fb_ddc.c | 119 + kernel/drivers/video/fbdev/core/fb_defio.c | 246 + kernel/drivers/video/fbdev/core/fb_draw.h | 186 + kernel/drivers/video/fbdev/core/fb_notify.c | 47 + kernel/drivers/video/fbdev/core/fb_sys_fops.c | 104 + kernel/drivers/video/fbdev/core/fbcmap.c | 362 + kernel/drivers/video/fbdev/core/fbcvt.c | 379 + kernel/drivers/video/fbdev/core/fbmem.c | 1911 ++++ kernel/drivers/video/fbdev/core/fbmon.c | 1612 +++ kernel/drivers/video/fbdev/core/fbsysfs.c | 578 + kernel/drivers/video/fbdev/core/modedb.c | 1245 +++ kernel/drivers/video/fbdev/core/svgalib.c | 672 ++ kernel/drivers/video/fbdev/core/syscopyarea.c | 370 + kernel/drivers/video/fbdev/core/sysfillrect.c | 335 + kernel/drivers/video/fbdev/core/sysimgblt.c | 288 + kernel/drivers/video/fbdev/cyber2000fb.c | 1901 ++++ kernel/drivers/video/fbdev/cyber2000fb.h | 497 + kernel/drivers/video/fbdev/da8xx-fb.c | 1669 +++ kernel/drivers/video/fbdev/dnfb.c | 303 + kernel/drivers/video/fbdev/edid.h | 138 + kernel/drivers/video/fbdev/efifb.c | 320 + kernel/drivers/video/fbdev/ep93xx-fb.c | 633 ++ kernel/drivers/video/fbdev/exynos/Kconfig | 32 + kernel/drivers/video/fbdev/exynos/Makefile | 7 + .../drivers/video/fbdev/exynos/exynos_mipi_dsi.c | 573 + .../video/fbdev/exynos/exynos_mipi_dsi_common.c | 880 ++ .../video/fbdev/exynos/exynos_mipi_dsi_common.h | 46 + .../video/fbdev/exynos/exynos_mipi_dsi_lowlevel.c | 618 ++ .../video/fbdev/exynos/exynos_mipi_dsi_lowlevel.h | 112 + .../video/fbdev/exynos/exynos_mipi_dsi_regs.h | 149 + kernel/drivers/video/fbdev/exynos/s6e8ax0.c | 892 ++ kernel/drivers/video/fbdev/fb-puv3.c | 840 ++ kernel/drivers/video/fbdev/ffb.c | 1080 ++ kernel/drivers/video/fbdev/fm2fb.c | 323 + kernel/drivers/video/fbdev/fsl-diu-fb.c | 1993 ++++ kernel/drivers/video/fbdev/g364fb.c | 255 + kernel/drivers/video/fbdev/gbefb.c | 1310 +++ kernel/drivers/video/fbdev/geode/Kconfig | 54 + kernel/drivers/video/fbdev/geode/Makefile | 9 + kernel/drivers/video/fbdev/geode/display_gx.c | 184 + kernel/drivers/video/fbdev/geode/display_gx1.c | 214 + kernel/drivers/video/fbdev/geode/display_gx1.h | 154 + kernel/drivers/video/fbdev/geode/geodefb.h | 38 + kernel/drivers/video/fbdev/geode/gx1fb_core.c | 474 + kernel/drivers/video/fbdev/geode/gxfb.h | 358 + kernel/drivers/video/fbdev/geode/gxfb_core.c | 545 + kernel/drivers/video/fbdev/geode/lxfb.h | 452 + kernel/drivers/video/fbdev/geode/lxfb_core.c | 681 ++ kernel/drivers/video/fbdev/geode/lxfb_ops.c | 845 ++ kernel/drivers/video/fbdev/geode/suspend_gx.c | 267 + kernel/drivers/video/fbdev/geode/video_cs5530.c | 193 + kernel/drivers/video/fbdev/geode/video_cs5530.h | 75 + kernel/drivers/video/fbdev/geode/video_gx.c | 349 + kernel/drivers/video/fbdev/goldfishfb.c | 318 + kernel/drivers/video/fbdev/grvga.c | 562 + kernel/drivers/video/fbdev/gxt4500.c | 783 ++ kernel/drivers/video/fbdev/hecubafb.c | 310 + kernel/drivers/video/fbdev/hgafb.c | 666 ++ kernel/drivers/video/fbdev/hitfb.c | 499 + kernel/drivers/video/fbdev/hpfb.c | 429 + kernel/drivers/video/fbdev/hyperv_fb.c | 965 ++ kernel/drivers/video/fbdev/i740_reg.h | 309 + kernel/drivers/video/fbdev/i740fb.c | 1333 +++ kernel/drivers/video/fbdev/i810/Makefile | 17 + kernel/drivers/video/fbdev/i810/i810-i2c.c | 175 + kernel/drivers/video/fbdev/i810/i810.h | 299 + kernel/drivers/video/fbdev/i810/i810_accel.c | 456 + kernel/drivers/video/fbdev/i810/i810_dvt.c | 312 + kernel/drivers/video/fbdev/i810/i810_gtf.c | 276 + kernel/drivers/video/fbdev/i810/i810_main.c | 2218 ++++ kernel/drivers/video/fbdev/i810/i810_main.h | 95 + kernel/drivers/video/fbdev/i810/i810_regs.h | 275 + kernel/drivers/video/fbdev/igafb.c | 579 + kernel/drivers/video/fbdev/imsttfb.c | 1622 +++ kernel/drivers/video/fbdev/imxfb.c | 1074 ++ kernel/drivers/video/fbdev/intelfb/Makefile | 7 + kernel/drivers/video/fbdev/intelfb/intelfb.h | 383 + kernel/drivers/video/fbdev/intelfb/intelfb_i2c.c | 209 + kernel/drivers/video/fbdev/intelfb/intelfbdrv.c | 1704 +++ kernel/drivers/video/fbdev/intelfb/intelfbhw.c | 2120 ++++ kernel/drivers/video/fbdev/intelfb/intelfbhw.h | 609 + kernel/drivers/video/fbdev/jz4740_fb.c | 806 ++ kernel/drivers/video/fbdev/kyro/Makefile | 8 + .../drivers/video/fbdev/kyro/STG4000InitDevice.c | 326 + kernel/drivers/video/fbdev/kyro/STG4000Interface.h | 61 + .../video/fbdev/kyro/STG4000OverlayDevice.c | 601 + kernel/drivers/video/fbdev/kyro/STG4000Ramdac.c | 163 + kernel/drivers/video/fbdev/kyro/STG4000Reg.h | 283 + kernel/drivers/video/fbdev/kyro/STG4000VTG.c | 170 + kernel/drivers/video/fbdev/kyro/fbdev.c | 808 ++ kernel/drivers/video/fbdev/leo.c | 690 ++ kernel/drivers/video/fbdev/macfb.c | 928 ++ kernel/drivers/video/fbdev/macmodes.c | 414 + kernel/drivers/video/fbdev/macmodes.h | 71 + kernel/drivers/video/fbdev/matrox/Makefile | 11 + kernel/drivers/video/fbdev/matrox/g450_pll.c | 539 + kernel/drivers/video/fbdev/matrox/g450_pll.h | 12 + kernel/drivers/video/fbdev/matrox/i2c-matroxfb.c | 238 + .../drivers/video/fbdev/matrox/matroxfb_DAC1064.c | 1107 ++ .../drivers/video/fbdev/matrox/matroxfb_DAC1064.h | 179 + .../drivers/video/fbdev/matrox/matroxfb_Ti3026.c | 745 ++ .../drivers/video/fbdev/matrox/matroxfb_Ti3026.h | 11 + kernel/drivers/video/fbdev/matrox/matroxfb_accel.c | 519 + kernel/drivers/video/fbdev/matrox/matroxfb_accel.h | 8 + kernel/drivers/video/fbdev/matrox/matroxfb_base.c | 2622 +++++ kernel/drivers/video/fbdev/matrox/matroxfb_base.h | 735 ++ kernel/drivers/video/fbdev/matrox/matroxfb_crtc2.c | 739 ++ kernel/drivers/video/fbdev/matrox/matroxfb_crtc2.h | 34 + kernel/drivers/video/fbdev/matrox/matroxfb_g450.c | 640 ++ kernel/drivers/video/fbdev/matrox/matroxfb_g450.h | 14 + kernel/drivers/video/fbdev/matrox/matroxfb_maven.c | 1303 +++ kernel/drivers/video/fbdev/matrox/matroxfb_maven.h | 20 + kernel/drivers/video/fbdev/matrox/matroxfb_misc.c | 815 ++ kernel/drivers/video/fbdev/matrox/matroxfb_misc.h | 21 + kernel/drivers/video/fbdev/maxinefb.c | 177 + kernel/drivers/video/fbdev/mb862xx/Makefile | 8 + kernel/drivers/video/fbdev/mb862xx/mb862xx-i2c.c | 179 + kernel/drivers/video/fbdev/mb862xx/mb862xx_reg.h | 188 + kernel/drivers/video/fbdev/mb862xx/mb862xxfb.h | 121 + .../drivers/video/fbdev/mb862xx/mb862xxfb_accel.c | 335 + .../drivers/video/fbdev/mb862xx/mb862xxfb_accel.h | 203 + kernel/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c | 1205 ++ kernel/drivers/video/fbdev/mbx/Makefile | 3 + kernel/drivers/video/fbdev/mbx/mbxdebugfs.c | 251 + kernel/drivers/video/fbdev/mbx/mbxfb.c | 1055 ++ kernel/drivers/video/fbdev/mbx/reg_bits.h | 613 + kernel/drivers/video/fbdev/mbx/regs.h | 195 + kernel/drivers/video/fbdev/metronomefb.c | 779 ++ kernel/drivers/video/fbdev/mmp/Kconfig | 11 + kernel/drivers/video/fbdev/mmp/Makefile | 3 + kernel/drivers/video/fbdev/mmp/core.c | 251 + kernel/drivers/video/fbdev/mmp/fb/Kconfig | 13 + kernel/drivers/video/fbdev/mmp/fb/Makefile | 1 + kernel/drivers/video/fbdev/mmp/fb/mmpfb.c | 688 ++ kernel/drivers/video/fbdev/mmp/fb/mmpfb.h | 54 + kernel/drivers/video/fbdev/mmp/hw/Kconfig | 20 + kernel/drivers/video/fbdev/mmp/hw/Makefile | 2 + kernel/drivers/video/fbdev/mmp/hw/mmp_ctrl.c | 586 + kernel/drivers/video/fbdev/mmp/hw/mmp_ctrl.h | 1470 +++ kernel/drivers/video/fbdev/mmp/hw/mmp_spi.c | 180 + kernel/drivers/video/fbdev/mmp/panel/Kconfig | 6 + kernel/drivers/video/fbdev/mmp/panel/Makefile | 1 + .../video/fbdev/mmp/panel/tpo_tj032md01bw.c | 186 + kernel/drivers/video/fbdev/msm/Makefile | 19 + kernel/drivers/video/fbdev/msm/mddi.c | 821 ++ kernel/drivers/video/fbdev/msm/mddi_client_dummy.c | 85 + .../drivers/video/fbdev/msm/mddi_client_nt35399.c | 252 + .../drivers/video/fbdev/msm/mddi_client_toshiba.c | 280 + kernel/drivers/video/fbdev/msm/mddi_hw.h | 305 + kernel/drivers/video/fbdev/msm/mdp.c | 520 + kernel/drivers/video/fbdev/msm/mdp_csc_table.h | 582 + kernel/drivers/video/fbdev/msm/mdp_hw.h | 627 ++ kernel/drivers/video/fbdev/msm/mdp_ppp.c | 731 ++ kernel/drivers/video/fbdev/msm/mdp_scale_tables.c | 766 ++ kernel/drivers/video/fbdev/msm/mdp_scale_tables.h | 38 + kernel/drivers/video/fbdev/msm/msm_fb.c | 659 ++ kernel/drivers/video/fbdev/mx3fb.c | 1706 +++ kernel/drivers/video/fbdev/mxsfb.c | 1019 ++ kernel/drivers/video/fbdev/n411.c | 202 + kernel/drivers/video/fbdev/neofb.c | 2247 ++++ kernel/drivers/video/fbdev/nuc900fb.c | 764 ++ kernel/drivers/video/fbdev/nuc900fb.h | 55 + kernel/drivers/video/fbdev/nvidia/Makefile | 12 + kernel/drivers/video/fbdev/nvidia/nv_accel.c | 416 + kernel/drivers/video/fbdev/nvidia/nv_backlight.c | 142 + kernel/drivers/video/fbdev/nvidia/nv_dma.h | 188 + kernel/drivers/video/fbdev/nvidia/nv_hw.c | 1687 +++ kernel/drivers/video/fbdev/nvidia/nv_i2c.c | 171 + kernel/drivers/video/fbdev/nvidia/nv_local.h | 114 + kernel/drivers/video/fbdev/nvidia/nv_of.c | 79 + kernel/drivers/video/fbdev/nvidia/nv_proto.h | 67 + kernel/drivers/video/fbdev/nvidia/nv_setup.c | 675 ++ kernel/drivers/video/fbdev/nvidia/nv_type.h | 180 + kernel/drivers/video/fbdev/nvidia/nvidia.c | 1603 +++ kernel/drivers/video/fbdev/ocfb.c | 440 + kernel/drivers/video/fbdev/offb.c | 678 ++ kernel/drivers/video/fbdev/omap/Kconfig | 61 + kernel/drivers/video/fbdev/omap/Makefile | 27 + kernel/drivers/video/fbdev/omap/hwa742.c | 1059 ++ kernel/drivers/video/fbdev/omap/lcd_ams_delta.c | 224 + kernel/drivers/video/fbdev/omap/lcd_h3.c | 126 + kernel/drivers/video/fbdev/omap/lcd_htcherald.c | 117 + kernel/drivers/video/fbdev/omap/lcd_inn1510.c | 112 + kernel/drivers/video/fbdev/omap/lcd_inn1610.c | 133 + kernel/drivers/video/fbdev/omap/lcd_mipid.c | 615 + kernel/drivers/video/fbdev/omap/lcd_osk.c | 132 + kernel/drivers/video/fbdev/omap/lcd_palmte.c | 109 + kernel/drivers/video/fbdev/omap/lcd_palmtt.c | 115 + kernel/drivers/video/fbdev/omap/lcd_palmz71.c | 111 + kernel/drivers/video/fbdev/omap/lcdc.c | 793 ++ kernel/drivers/video/fbdev/omap/lcdc.h | 9 + kernel/drivers/video/fbdev/omap/omapfb.h | 246 + kernel/drivers/video/fbdev/omap/omapfb_main.c | 1971 ++++ kernel/drivers/video/fbdev/omap/sossi.c | 693 ++ kernel/drivers/video/fbdev/omap2/Kconfig | 10 + kernel/drivers/video/fbdev/omap2/Makefile | 5 + .../drivers/video/fbdev/omap2/displays-new/Kconfig | 86 + .../video/fbdev/omap2/displays-new/Makefile | 14 + .../fbdev/omap2/displays-new/connector-analog-tv.c | 320 + .../video/fbdev/omap2/displays-new/connector-dvi.c | 398 + .../fbdev/omap2/displays-new/connector-hdmi.c | 348 + .../fbdev/omap2/displays-new/encoder-opa362.c | 285 + .../fbdev/omap2/displays-new/encoder-tfp410.c | 320 + .../fbdev/omap2/displays-new/encoder-tpd12s015.c | 379 + .../video/fbdev/omap2/displays-new/panel-dpi.c | 337 + .../video/fbdev/omap2/displays-new/panel-dsi-cm.c | 1388 +++ .../omap2/displays-new/panel-lgphilips-lb035q02.c | 406 + .../omap2/displays-new/panel-nec-nl8048hl11.c | 438 + .../omap2/displays-new/panel-sharp-ls037v7dw01.c | 420 + .../omap2/displays-new/panel-sony-acx565akm.c | 917 ++ .../omap2/displays-new/panel-tpo-td028ttec1.c | 512 + .../omap2/displays-new/panel-tpo-td043mtea1.c | 687 ++ kernel/drivers/video/fbdev/omap2/dss/Kconfig | 135 + kernel/drivers/video/fbdev/omap2/dss/Makefile | 18 + kernel/drivers/video/fbdev/omap2/dss/apply.c | 1702 +++ kernel/drivers/video/fbdev/omap2/dss/core.c | 369 + .../drivers/video/fbdev/omap2/dss/dispc-compat.c | 667 ++ .../drivers/video/fbdev/omap2/dss/dispc-compat.h | 30 + kernel/drivers/video/fbdev/omap2/dss/dispc.c | 4033 +++++++ kernel/drivers/video/fbdev/omap2/dss/dispc.h | 916 ++ kernel/drivers/video/fbdev/omap2/dss/dispc_coefs.c | 325 + .../drivers/video/fbdev/omap2/dss/display-sysfs.c | 356 + kernel/drivers/video/fbdev/omap2/dss/display.c | 338 + kernel/drivers/video/fbdev/omap2/dss/dpi.c | 881 ++ kernel/drivers/video/fbdev/omap2/dss/dsi.c | 5590 ++++++++++ kernel/drivers/video/fbdev/omap2/dss/dss-of.c | 181 + kernel/drivers/video/fbdev/omap2/dss/dss.c | 1235 +++ kernel/drivers/video/fbdev/omap2/dss/dss.h | 472 + .../drivers/video/fbdev/omap2/dss/dss_features.c | 962 ++ .../drivers/video/fbdev/omap2/dss/dss_features.h | 105 + kernel/drivers/video/fbdev/omap2/dss/hdmi.h | 363 + kernel/drivers/video/fbdev/omap2/dss/hdmi4.c | 777 ++ kernel/drivers/video/fbdev/omap2/dss/hdmi4_core.c | 894 ++ kernel/drivers/video/fbdev/omap2/dss/hdmi4_core.h | 273 + kernel/drivers/video/fbdev/omap2/dss/hdmi5.c | 813 ++ kernel/drivers/video/fbdev/omap2/dss/hdmi5_core.c | 913 ++ kernel/drivers/video/fbdev/omap2/dss/hdmi5_core.h | 304 + kernel/drivers/video/fbdev/omap2/dss/hdmi_common.c | 148 + kernel/drivers/video/fbdev/omap2/dss/hdmi_phy.c | 247 + kernel/drivers/video/fbdev/omap2/dss/hdmi_pll.c | 255 + kernel/drivers/video/fbdev/omap2/dss/hdmi_wp.c | 266 + .../drivers/video/fbdev/omap2/dss/manager-sysfs.c | 531 + kernel/drivers/video/fbdev/omap2/dss/manager.c | 263 + .../video/fbdev/omap2/dss/omapdss-boot-init.c | 227 + kernel/drivers/video/fbdev/omap2/dss/output.c | 267 + .../drivers/video/fbdev/omap2/dss/overlay-sysfs.c | 456 + kernel/drivers/video/fbdev/omap2/dss/overlay.c | 202 + kernel/drivers/video/fbdev/omap2/dss/pll.c | 389 + kernel/drivers/video/fbdev/omap2/dss/rfbi.c | 1058 ++ kernel/drivers/video/fbdev/omap2/dss/sdi.c | 435 + kernel/drivers/video/fbdev/omap2/dss/venc.c | 980 ++ kernel/drivers/video/fbdev/omap2/dss/video-pll.c | 211 + kernel/drivers/video/fbdev/omap2/omapfb/Kconfig | 27 + kernel/drivers/video/fbdev/omap2/omapfb/Makefile | 2 + .../video/fbdev/omap2/omapfb/omapfb-ioctl.c | 925 ++ .../drivers/video/fbdev/omap2/omapfb/omapfb-main.c | 2655 +++++ .../video/fbdev/omap2/omapfb/omapfb-sysfs.c | 605 + kernel/drivers/video/fbdev/omap2/omapfb/omapfb.h | 208 + kernel/drivers/video/fbdev/omap2/vrfb.c | 399 + kernel/drivers/video/fbdev/p9100.c | 381 + kernel/drivers/video/fbdev/platinumfb.c | 713 ++ kernel/drivers/video/fbdev/platinumfb.h | 368 + kernel/drivers/video/fbdev/pm2fb.c | 1858 ++++ kernel/drivers/video/fbdev/pm3fb.c | 1586 +++ kernel/drivers/video/fbdev/pmag-aa-fb.c | 510 + kernel/drivers/video/fbdev/pmag-ba-fb.c | 295 + kernel/drivers/video/fbdev/pmagb-b-fb.c | 413 + kernel/drivers/video/fbdev/ps3fb.c | 1307 +++ kernel/drivers/video/fbdev/pvr2fb.c | 1140 ++ kernel/drivers/video/fbdev/pxa168fb.c | 836 ++ kernel/drivers/video/fbdev/pxa168fb.h | 558 + kernel/drivers/video/fbdev/pxa3xx-gcu.c | 721 ++ kernel/drivers/video/fbdev/pxa3xx-gcu.h | 38 + kernel/drivers/video/fbdev/pxafb.c | 2331 ++++ kernel/drivers/video/fbdev/pxafb.h | 200 + kernel/drivers/video/fbdev/q40fb.c | 155 + kernel/drivers/video/fbdev/riva/Makefile | 11 + kernel/drivers/video/fbdev/riva/fbdev.c | 2221 ++++ kernel/drivers/video/fbdev/riva/nv_driver.c | 422 + kernel/drivers/video/fbdev/riva/nv_type.h | 58 + kernel/drivers/video/fbdev/riva/nvreg.h | 188 + kernel/drivers/video/fbdev/riva/riva_hw.c | 2267 ++++ kernel/drivers/video/fbdev/riva/riva_hw.h | 563 + kernel/drivers/video/fbdev/riva/riva_tbl.h | 1008 ++ kernel/drivers/video/fbdev/riva/rivafb-i2c.c | 166 + kernel/drivers/video/fbdev/riva/rivafb.h | 77 + kernel/drivers/video/fbdev/s1d13xxxfb.c | 1040 ++ kernel/drivers/video/fbdev/s3c-fb.c | 1983 ++++ kernel/drivers/video/fbdev/s3c2410fb.c | 1144 ++ kernel/drivers/video/fbdev/s3c2410fb.h | 48 + kernel/drivers/video/fbdev/s3fb.c | 1598 +++ kernel/drivers/video/fbdev/sa1100fb.c | 1361 +++ kernel/drivers/video/fbdev/sa1100fb.h | 97 + kernel/drivers/video/fbdev/savage/Makefile | 9 + kernel/drivers/video/fbdev/savage/savagefb-i2c.c | 241 + kernel/drivers/video/fbdev/savage/savagefb.h | 409 + kernel/drivers/video/fbdev/savage/savagefb_accel.c | 137 + .../drivers/video/fbdev/savage/savagefb_driver.c | 2571 +++++ kernel/drivers/video/fbdev/sbuslib.c | 267 + kernel/drivers/video/fbdev/sbuslib.h | 27 + kernel/drivers/video/fbdev/sh7760fb.c | 590 + kernel/drivers/video/fbdev/sh_mipi_dsi.c | 587 + kernel/drivers/video/fbdev/sh_mobile_hdmi.c | 1489 +++ kernel/drivers/video/fbdev/sh_mobile_lcdcfb.c | 2862 +++++ kernel/drivers/video/fbdev/sh_mobile_lcdcfb.h | 112 + kernel/drivers/video/fbdev/sh_mobile_meram.c | 758 ++ kernel/drivers/video/fbdev/simplefb.c | 419 + kernel/drivers/video/fbdev/sis/300vtbl.h | 1072 ++ kernel/drivers/video/fbdev/sis/310vtbl.h | 1339 +++ kernel/drivers/video/fbdev/sis/Makefile | 7 + kernel/drivers/video/fbdev/sis/init.c | 3655 ++++++ kernel/drivers/video/fbdev/sis/init.h | 1541 +++ kernel/drivers/video/fbdev/sis/init301.c | 11071 +++++++++++++++++++ kernel/drivers/video/fbdev/sis/init301.h | 456 + kernel/drivers/video/fbdev/sis/initdef.h | 708 ++ kernel/drivers/video/fbdev/sis/initextlfb.c | 231 + kernel/drivers/video/fbdev/sis/oem300.h | 840 ++ kernel/drivers/video/fbdev/sis/oem310.h | 430 + kernel/drivers/video/fbdev/sis/sis.h | 586 + kernel/drivers/video/fbdev/sis/sis_accel.c | 423 + kernel/drivers/video/fbdev/sis/sis_accel.h | 400 + kernel/drivers/video/fbdev/sis/sis_main.c | 6836 ++++++++++++ kernel/drivers/video/fbdev/sis/sis_main.h | 781 ++ kernel/drivers/video/fbdev/sis/vgatypes.h | 97 + kernel/drivers/video/fbdev/sis/vstruct.h | 551 + kernel/drivers/video/fbdev/skeletonfb.c | 1037 ++ kernel/drivers/video/fbdev/sm501fb.c | 2240 ++++ kernel/drivers/video/fbdev/smscufx.c | 1978 ++++ kernel/drivers/video/fbdev/ssd1307fb.c | 603 + kernel/drivers/video/fbdev/sstfb.c | 1532 +++ kernel/drivers/video/fbdev/sticore.h | 401 + kernel/drivers/video/fbdev/stifb.c | 1417 +++ kernel/drivers/video/fbdev/sunxvr1000.c | 228 + kernel/drivers/video/fbdev/sunxvr2500.c | 276 + kernel/drivers/video/fbdev/sunxvr500.c | 462 + kernel/drivers/video/fbdev/tcx.c | 540 + kernel/drivers/video/fbdev/tdfxfb.c | 1686 +++ kernel/drivers/video/fbdev/tgafb.c | 1611 +++ kernel/drivers/video/fbdev/tmiofb.c | 1048 ++ kernel/drivers/video/fbdev/tridentfb.c | 1659 +++ kernel/drivers/video/fbdev/udlfb.c | 1979 ++++ kernel/drivers/video/fbdev/uvesafb.c | 2026 ++++ kernel/drivers/video/fbdev/valkyriefb.c | 593 + kernel/drivers/video/fbdev/valkyriefb.h | 200 + kernel/drivers/video/fbdev/vermilion/Makefile | 5 + kernel/drivers/video/fbdev/vermilion/cr_pll.c | 208 + kernel/drivers/video/fbdev/vermilion/vermilion.c | 1176 ++ kernel/drivers/video/fbdev/vermilion/vermilion.h | 259 + kernel/drivers/video/fbdev/vesafb.c | 521 + kernel/drivers/video/fbdev/vfb.c | 610 + kernel/drivers/video/fbdev/vga16fb.c | 1464 +++ kernel/drivers/video/fbdev/via/Makefile | 12 + kernel/drivers/video/fbdev/via/accel.c | 547 + kernel/drivers/video/fbdev/via/accel.h | 211 + kernel/drivers/video/fbdev/via/chip.h | 176 + kernel/drivers/video/fbdev/via/debug.h | 41 + kernel/drivers/video/fbdev/via/dvi.c | 478 + kernel/drivers/video/fbdev/via/dvi.h | 65 + kernel/drivers/video/fbdev/via/global.c | 50 + kernel/drivers/video/fbdev/via/global.h | 80 + kernel/drivers/video/fbdev/via/hw.c | 2134 ++++ kernel/drivers/video/fbdev/via/hw.h | 676 ++ kernel/drivers/video/fbdev/via/ioctl.c | 116 + kernel/drivers/video/fbdev/via/ioctl.h | 203 + kernel/drivers/video/fbdev/via/lcd.c | 1005 ++ kernel/drivers/video/fbdev/via/lcd.h | 89 + kernel/drivers/video/fbdev/via/share.h | 332 + kernel/drivers/video/fbdev/via/tblDPASetting.c | 86 + kernel/drivers/video/fbdev/via/tblDPASetting.h | 45 + kernel/drivers/video/fbdev/via/via-core.c | 790 ++ kernel/drivers/video/fbdev/via/via-gpio.c | 312 + kernel/drivers/video/fbdev/via/via_aux.c | 88 + kernel/drivers/video/fbdev/via/via_aux.h | 93 + kernel/drivers/video/fbdev/via/via_aux_ch7301.c | 50 + kernel/drivers/video/fbdev/via/via_aux_edid.c | 100 + kernel/drivers/video/fbdev/via/via_aux_sii164.c | 54 + kernel/drivers/video/fbdev/via/via_aux_vt1621.c | 44 + kernel/drivers/video/fbdev/via/via_aux_vt1622.c | 50 + kernel/drivers/video/fbdev/via/via_aux_vt1625.c | 50 + kernel/drivers/video/fbdev/via/via_aux_vt1631.c | 46 + kernel/drivers/video/fbdev/via/via_aux_vt1632.c | 54 + kernel/drivers/video/fbdev/via/via_aux_vt1636.c | 46 + kernel/drivers/video/fbdev/via/via_clock.c | 368 + kernel/drivers/video/fbdev/via/via_clock.h | 76 + kernel/drivers/video/fbdev/via/via_i2c.c | 295 + kernel/drivers/video/fbdev/via/via_modesetting.c | 230 + kernel/drivers/video/fbdev/via/via_modesetting.h | 61 + kernel/drivers/video/fbdev/via/via_utility.c | 242 + kernel/drivers/video/fbdev/via/via_utility.h | 34 + kernel/drivers/video/fbdev/via/viafbdev.c | 2175 ++++ kernel/drivers/video/fbdev/via/viafbdev.h | 110 + kernel/drivers/video/fbdev/via/viamode.c | 383 + kernel/drivers/video/fbdev/via/viamode.h | 63 + kernel/drivers/video/fbdev/via/vt1636.c | 244 + kernel/drivers/video/fbdev/via/vt1636.h | 44 + kernel/drivers/video/fbdev/vt8500lcdfb.c | 497 + kernel/drivers/video/fbdev/vt8500lcdfb.h | 34 + kernel/drivers/video/fbdev/vt8623fb.c | 958 ++ kernel/drivers/video/fbdev/w100fb.c | 1637 +++ kernel/drivers/video/fbdev/w100fb.h | 928 ++ kernel/drivers/video/fbdev/wm8505fb.c | 420 + kernel/drivers/video/fbdev/wm8505fb_regs.h | 76 + kernel/drivers/video/fbdev/wmt_ge_rops.c | 181 + kernel/drivers/video/fbdev/wmt_ge_rops.h | 28 + kernel/drivers/video/fbdev/xen-fbfront.c | 720 ++ kernel/drivers/video/fbdev/xilinxfb.c | 508 + kernel/drivers/video/hdmi.c | 1244 +++ kernel/drivers/video/logo/.gitignore | 7 + kernel/drivers/video/logo/Kconfig | 85 + kernel/drivers/video/logo/Makefile | 61 + kernel/drivers/video/logo/clut_vga16.ppm | 20 + kernel/drivers/video/logo/logo.c | 117 + .../drivers/video/logo/logo_blackfin_clut224.ppm | 1127 ++ kernel/drivers/video/logo/logo_blackfin_vga16.ppm | 1127 ++ kernel/drivers/video/logo/logo_dec_clut224.ppm | 1604 +++ kernel/drivers/video/logo/logo_linux_clut224.ppm | 1604 +++ kernel/drivers/video/logo/logo_linux_mono.pbm | 203 + kernel/drivers/video/logo/logo_linux_vga16.ppm | 1604 +++ kernel/drivers/video/logo/logo_m32r_clut224.ppm | 1292 +++ kernel/drivers/video/logo/logo_mac_clut224.ppm | 1604 +++ kernel/drivers/video/logo/logo_parisc_clut224.ppm | 1604 +++ kernel/drivers/video/logo/logo_sgi_clut224.ppm | 1604 +++ kernel/drivers/video/logo/logo_spe_clut224.ppm | 283 + kernel/drivers/video/logo/logo_sun_clut224.ppm | 1604 +++ kernel/drivers/video/logo/logo_superh_clut224.ppm | 1604 +++ kernel/drivers/video/logo/logo_superh_mono.pbm | 203 + kernel/drivers/video/logo/logo_superh_vga16.ppm | 1604 +++ kernel/drivers/video/of_display_timing.c | 265 + kernel/drivers/video/of_videomode.c | 54 + kernel/drivers/video/vgastate.c | 490 + kernel/drivers/video/videomode.c | 45 + 586 files changed, 358498 insertions(+) create mode 100644 kernel/drivers/video/Kconfig create mode 100644 kernel/drivers/video/Makefile create mode 100644 kernel/drivers/video/backlight/88pm860x_bl.c create mode 100644 kernel/drivers/video/backlight/Kconfig create mode 100644 kernel/drivers/video/backlight/Makefile create mode 100644 kernel/drivers/video/backlight/aat2870_bl.c create mode 100644 kernel/drivers/video/backlight/adp5520_bl.c create mode 100644 kernel/drivers/video/backlight/adp8860_bl.c create mode 100644 kernel/drivers/video/backlight/adp8870_bl.c create mode 100644 kernel/drivers/video/backlight/ams369fg06.c create mode 100644 kernel/drivers/video/backlight/apple_bl.c create mode 100644 kernel/drivers/video/backlight/as3711_bl.c create mode 100644 kernel/drivers/video/backlight/backlight.c create mode 100644 kernel/drivers/video/backlight/bd6107.c create mode 100644 kernel/drivers/video/backlight/corgi_lcd.c create mode 100644 kernel/drivers/video/backlight/cr_bllcd.c create mode 100644 kernel/drivers/video/backlight/da903x_bl.c create mode 100644 kernel/drivers/video/backlight/da9052_bl.c create mode 100644 kernel/drivers/video/backlight/ep93xx_bl.c create mode 100644 kernel/drivers/video/backlight/generic_bl.c create mode 100644 kernel/drivers/video/backlight/gpio_backlight.c create mode 100644 kernel/drivers/video/backlight/hp680_bl.c create mode 100644 kernel/drivers/video/backlight/hx8357.c create mode 100644 kernel/drivers/video/backlight/ili922x.c create mode 100644 kernel/drivers/video/backlight/ili9320.c create mode 100644 kernel/drivers/video/backlight/ili9320.h create mode 100644 kernel/drivers/video/backlight/ipaq_micro_bl.c create mode 100644 kernel/drivers/video/backlight/jornada720_bl.c create mode 100644 kernel/drivers/video/backlight/jornada720_lcd.c create mode 100644 kernel/drivers/video/backlight/kb3886_bl.c create mode 100644 kernel/drivers/video/backlight/l4f00242t03.c create mode 100644 kernel/drivers/video/backlight/lcd.c create mode 100644 kernel/drivers/video/backlight/ld9040.c create mode 100644 kernel/drivers/video/backlight/ld9040_gamma.h create mode 100644 kernel/drivers/video/backlight/lm3533_bl.c create mode 100644 kernel/drivers/video/backlight/lm3630a_bl.c create mode 100644 kernel/drivers/video/backlight/lm3639_bl.c create mode 100644 kernel/drivers/video/backlight/lms283gf05.c create mode 100644 kernel/drivers/video/backlight/lms501kf03.c create mode 100644 kernel/drivers/video/backlight/locomolcd.c create mode 100644 kernel/drivers/video/backlight/lp855x_bl.c create mode 100644 kernel/drivers/video/backlight/lp8788_bl.c create mode 100644 kernel/drivers/video/backlight/ltv350qv.c create mode 100644 kernel/drivers/video/backlight/ltv350qv.h create mode 100644 kernel/drivers/video/backlight/lv5207lp.c create mode 100644 kernel/drivers/video/backlight/max8925_bl.c create mode 100644 kernel/drivers/video/backlight/omap1_bl.c create mode 100644 kernel/drivers/video/backlight/ot200_bl.c create mode 100644 kernel/drivers/video/backlight/pandora_bl.c create mode 100644 kernel/drivers/video/backlight/pcf50633-backlight.c create mode 100644 kernel/drivers/video/backlight/platform_lcd.c create mode 100644 kernel/drivers/video/backlight/pwm_bl.c create mode 100644 kernel/drivers/video/backlight/s6e63m0.c create mode 100644 kernel/drivers/video/backlight/s6e63m0_gamma.h create mode 100644 kernel/drivers/video/backlight/sky81452-backlight.c create mode 100644 kernel/drivers/video/backlight/tdo24m.c create mode 100644 kernel/drivers/video/backlight/tosa_bl.c create mode 100644 kernel/drivers/video/backlight/tosa_lcd.c create mode 100644 kernel/drivers/video/backlight/tps65217_bl.c create mode 100644 kernel/drivers/video/backlight/vgg2432a4.c create mode 100644 kernel/drivers/video/backlight/wm831x_bl.c create mode 100644 kernel/drivers/video/console/Kconfig create mode 100644 kernel/drivers/video/console/Makefile create mode 100644 kernel/drivers/video/console/bitblit.c create mode 100644 kernel/drivers/video/console/dummycon.c create mode 100644 kernel/drivers/video/console/fbcon.c create mode 100644 kernel/drivers/video/console/fbcon.h create mode 100644 kernel/drivers/video/console/fbcon_ccw.c create mode 100644 kernel/drivers/video/console/fbcon_cw.c create mode 100644 kernel/drivers/video/console/fbcon_rotate.c create mode 100644 kernel/drivers/video/console/fbcon_rotate.h create mode 100644 kernel/drivers/video/console/fbcon_ud.c create mode 100644 kernel/drivers/video/console/mdacon.c create mode 100644 kernel/drivers/video/console/newport_con.c create mode 100644 kernel/drivers/video/console/softcursor.c create mode 100644 kernel/drivers/video/console/sticon.c create mode 100644 kernel/drivers/video/console/sticore.c create mode 100644 kernel/drivers/video/console/tileblit.c create mode 100644 kernel/drivers/video/console/vgacon.c create mode 100644 kernel/drivers/video/display_timing.c create mode 100644 kernel/drivers/video/fbdev/68328fb.c create mode 100644 kernel/drivers/video/fbdev/Kconfig create mode 100644 kernel/drivers/video/fbdev/Makefile create mode 100644 kernel/drivers/video/fbdev/acornfb.c create mode 100644 kernel/drivers/video/fbdev/acornfb.h create mode 100644 kernel/drivers/video/fbdev/amba-clcd-versatile.c create mode 100644 kernel/drivers/video/fbdev/amba-clcd.c create mode 100644 kernel/drivers/video/fbdev/amifb.c create mode 100644 kernel/drivers/video/fbdev/arcfb.c create mode 100644 kernel/drivers/video/fbdev/arkfb.c create mode 100644 kernel/drivers/video/fbdev/asiliantfb.c create mode 100644 kernel/drivers/video/fbdev/atafb.c create mode 100644 kernel/drivers/video/fbdev/atafb.h create mode 100644 kernel/drivers/video/fbdev/atafb_iplan2p2.c create mode 100644 kernel/drivers/video/fbdev/atafb_iplan2p4.c create mode 100644 kernel/drivers/video/fbdev/atafb_iplan2p8.c create mode 100644 kernel/drivers/video/fbdev/atafb_mfb.c create mode 100644 kernel/drivers/video/fbdev/atafb_utils.h create mode 100644 kernel/drivers/video/fbdev/atmel_lcdfb.c create mode 100644 kernel/drivers/video/fbdev/aty/Makefile create mode 100644 kernel/drivers/video/fbdev/aty/ati_ids.h create mode 100644 kernel/drivers/video/fbdev/aty/aty128fb.c create mode 100644 kernel/drivers/video/fbdev/aty/atyfb.h create mode 100644 kernel/drivers/video/fbdev/aty/atyfb_base.c create mode 100644 kernel/drivers/video/fbdev/aty/mach64_accel.c create mode 100644 kernel/drivers/video/fbdev/aty/mach64_ct.c create mode 100644 kernel/drivers/video/fbdev/aty/mach64_cursor.c create mode 100644 kernel/drivers/video/fbdev/aty/mach64_gx.c create mode 100644 kernel/drivers/video/fbdev/aty/radeon_accel.c create mode 100644 kernel/drivers/video/fbdev/aty/radeon_backlight.c create mode 100644 kernel/drivers/video/fbdev/aty/radeon_base.c create mode 100644 kernel/drivers/video/fbdev/aty/radeon_i2c.c create mode 100644 kernel/drivers/video/fbdev/aty/radeon_monitor.c create mode 100644 kernel/drivers/video/fbdev/aty/radeon_pm.c create mode 100644 kernel/drivers/video/fbdev/aty/radeonfb.h create mode 100644 kernel/drivers/video/fbdev/au1100fb.c create mode 100644 kernel/drivers/video/fbdev/au1100fb.h create mode 100644 kernel/drivers/video/fbdev/au1200fb.c create mode 100644 kernel/drivers/video/fbdev/au1200fb.h create mode 100644 kernel/drivers/video/fbdev/auo_k1900fb.c create mode 100644 kernel/drivers/video/fbdev/auo_k1901fb.c create mode 100644 kernel/drivers/video/fbdev/auo_k190x.c create mode 100644 kernel/drivers/video/fbdev/auo_k190x.h create mode 100644 kernel/drivers/video/fbdev/bf537-lq035.c create mode 100644 kernel/drivers/video/fbdev/bf54x-lq043fb.c create mode 100644 kernel/drivers/video/fbdev/bfin-lq035q1-fb.c create mode 100644 kernel/drivers/video/fbdev/bfin-t350mcqb-fb.c create mode 100644 kernel/drivers/video/fbdev/bfin_adv7393fb.c create mode 100644 kernel/drivers/video/fbdev/bfin_adv7393fb.h create mode 100644 kernel/drivers/video/fbdev/broadsheetfb.c create mode 100644 kernel/drivers/video/fbdev/bt431.h create mode 100644 kernel/drivers/video/fbdev/bt455.h create mode 100644 kernel/drivers/video/fbdev/bw2.c create mode 100644 kernel/drivers/video/fbdev/c2p.h create mode 100644 kernel/drivers/video/fbdev/c2p_core.h create mode 100644 kernel/drivers/video/fbdev/c2p_iplan2.c create mode 100644 kernel/drivers/video/fbdev/c2p_planar.c create mode 100644 kernel/drivers/video/fbdev/carminefb.c create mode 100644 kernel/drivers/video/fbdev/carminefb.h create mode 100644 kernel/drivers/video/fbdev/carminefb_regs.h create mode 100644 kernel/drivers/video/fbdev/cg14.c create mode 100644 kernel/drivers/video/fbdev/cg3.c create mode 100644 kernel/drivers/video/fbdev/cg6.c create mode 100644 kernel/drivers/video/fbdev/chipsfb.c create mode 100644 kernel/drivers/video/fbdev/cirrusfb.c create mode 100644 kernel/drivers/video/fbdev/clps711x-fb.c create mode 100644 kernel/drivers/video/fbdev/clps711xfb.c create mode 100644 kernel/drivers/video/fbdev/cobalt_lcdfb.c create mode 100644 kernel/drivers/video/fbdev/controlfb.c create mode 100644 kernel/drivers/video/fbdev/controlfb.h create mode 100644 kernel/drivers/video/fbdev/core/Makefile create mode 100644 kernel/drivers/video/fbdev/core/cfbcopyarea.c create mode 100644 kernel/drivers/video/fbdev/core/cfbfillrect.c create mode 100644 kernel/drivers/video/fbdev/core/cfbimgblt.c create mode 100644 kernel/drivers/video/fbdev/core/fb_cmdline.c create mode 100644 kernel/drivers/video/fbdev/core/fb_ddc.c create mode 100644 kernel/drivers/video/fbdev/core/fb_defio.c create mode 100644 kernel/drivers/video/fbdev/core/fb_draw.h create mode 100644 kernel/drivers/video/fbdev/core/fb_notify.c create mode 100644 kernel/drivers/video/fbdev/core/fb_sys_fops.c create mode 100644 kernel/drivers/video/fbdev/core/fbcmap.c create mode 100644 kernel/drivers/video/fbdev/core/fbcvt.c create mode 100644 kernel/drivers/video/fbdev/core/fbmem.c create mode 100644 kernel/drivers/video/fbdev/core/fbmon.c create mode 100644 kernel/drivers/video/fbdev/core/fbsysfs.c create mode 100644 kernel/drivers/video/fbdev/core/modedb.c create mode 100644 kernel/drivers/video/fbdev/core/svgalib.c create mode 100644 kernel/drivers/video/fbdev/core/syscopyarea.c create mode 100644 kernel/drivers/video/fbdev/core/sysfillrect.c create mode 100644 kernel/drivers/video/fbdev/core/sysimgblt.c create mode 100644 kernel/drivers/video/fbdev/cyber2000fb.c create mode 100644 kernel/drivers/video/fbdev/cyber2000fb.h create mode 100644 kernel/drivers/video/fbdev/da8xx-fb.c create mode 100644 kernel/drivers/video/fbdev/dnfb.c create mode 100644 kernel/drivers/video/fbdev/edid.h create mode 100644 kernel/drivers/video/fbdev/efifb.c create mode 100644 kernel/drivers/video/fbdev/ep93xx-fb.c create mode 100644 kernel/drivers/video/fbdev/exynos/Kconfig create mode 100644 kernel/drivers/video/fbdev/exynos/Makefile create mode 100644 kernel/drivers/video/fbdev/exynos/exynos_mipi_dsi.c create mode 100644 kernel/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.c create mode 100644 kernel/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.h create mode 100644 kernel/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.c create mode 100644 kernel/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.h create mode 100644 kernel/drivers/video/fbdev/exynos/exynos_mipi_dsi_regs.h create mode 100644 kernel/drivers/video/fbdev/exynos/s6e8ax0.c create mode 100644 kernel/drivers/video/fbdev/fb-puv3.c create mode 100644 kernel/drivers/video/fbdev/ffb.c create mode 100644 kernel/drivers/video/fbdev/fm2fb.c create mode 100644 kernel/drivers/video/fbdev/fsl-diu-fb.c create mode 100644 kernel/drivers/video/fbdev/g364fb.c create mode 100644 kernel/drivers/video/fbdev/gbefb.c create mode 100644 kernel/drivers/video/fbdev/geode/Kconfig create mode 100644 kernel/drivers/video/fbdev/geode/Makefile create mode 100644 kernel/drivers/video/fbdev/geode/display_gx.c create mode 100644 kernel/drivers/video/fbdev/geode/display_gx1.c create mode 100644 kernel/drivers/video/fbdev/geode/display_gx1.h create mode 100644 kernel/drivers/video/fbdev/geode/geodefb.h create mode 100644 kernel/drivers/video/fbdev/geode/gx1fb_core.c create mode 100644 kernel/drivers/video/fbdev/geode/gxfb.h create mode 100644 kernel/drivers/video/fbdev/geode/gxfb_core.c create mode 100644 kernel/drivers/video/fbdev/geode/lxfb.h create mode 100644 kernel/drivers/video/fbdev/geode/lxfb_core.c create mode 100644 kernel/drivers/video/fbdev/geode/lxfb_ops.c create mode 100644 kernel/drivers/video/fbdev/geode/suspend_gx.c create mode 100644 kernel/drivers/video/fbdev/geode/video_cs5530.c create mode 100644 kernel/drivers/video/fbdev/geode/video_cs5530.h create mode 100644 kernel/drivers/video/fbdev/geode/video_gx.c create mode 100644 kernel/drivers/video/fbdev/goldfishfb.c create mode 100644 kernel/drivers/video/fbdev/grvga.c create mode 100644 kernel/drivers/video/fbdev/gxt4500.c create mode 100644 kernel/drivers/video/fbdev/hecubafb.c create mode 100644 kernel/drivers/video/fbdev/hgafb.c create mode 100644 kernel/drivers/video/fbdev/hitfb.c create mode 100644 kernel/drivers/video/fbdev/hpfb.c create mode 100644 kernel/drivers/video/fbdev/hyperv_fb.c create mode 100644 kernel/drivers/video/fbdev/i740_reg.h create mode 100644 kernel/drivers/video/fbdev/i740fb.c create mode 100644 kernel/drivers/video/fbdev/i810/Makefile create mode 100644 kernel/drivers/video/fbdev/i810/i810-i2c.c create mode 100644 kernel/drivers/video/fbdev/i810/i810.h create mode 100644 kernel/drivers/video/fbdev/i810/i810_accel.c create mode 100644 kernel/drivers/video/fbdev/i810/i810_dvt.c create mode 100644 kernel/drivers/video/fbdev/i810/i810_gtf.c create mode 100644 kernel/drivers/video/fbdev/i810/i810_main.c create mode 100644 kernel/drivers/video/fbdev/i810/i810_main.h create mode 100644 kernel/drivers/video/fbdev/i810/i810_regs.h create mode 100644 kernel/drivers/video/fbdev/igafb.c create mode 100644 kernel/drivers/video/fbdev/imsttfb.c create mode 100644 kernel/drivers/video/fbdev/imxfb.c create mode 100644 kernel/drivers/video/fbdev/intelfb/Makefile create mode 100644 kernel/drivers/video/fbdev/intelfb/intelfb.h create mode 100644 kernel/drivers/video/fbdev/intelfb/intelfb_i2c.c create mode 100644 kernel/drivers/video/fbdev/intelfb/intelfbdrv.c create mode 100644 kernel/drivers/video/fbdev/intelfb/intelfbhw.c create mode 100644 kernel/drivers/video/fbdev/intelfb/intelfbhw.h create mode 100644 kernel/drivers/video/fbdev/jz4740_fb.c create mode 100644 kernel/drivers/video/fbdev/kyro/Makefile create mode 100644 kernel/drivers/video/fbdev/kyro/STG4000InitDevice.c create mode 100644 kernel/drivers/video/fbdev/kyro/STG4000Interface.h create mode 100644 kernel/drivers/video/fbdev/kyro/STG4000OverlayDevice.c create mode 100644 kernel/drivers/video/fbdev/kyro/STG4000Ramdac.c create mode 100644 kernel/drivers/video/fbdev/kyro/STG4000Reg.h create mode 100644 kernel/drivers/video/fbdev/kyro/STG4000VTG.c create mode 100644 kernel/drivers/video/fbdev/kyro/fbdev.c create mode 100644 kernel/drivers/video/fbdev/leo.c create mode 100644 kernel/drivers/video/fbdev/macfb.c create mode 100644 kernel/drivers/video/fbdev/macmodes.c create mode 100644 kernel/drivers/video/fbdev/macmodes.h create mode 100644 kernel/drivers/video/fbdev/matrox/Makefile create mode 100644 kernel/drivers/video/fbdev/matrox/g450_pll.c create mode 100644 kernel/drivers/video/fbdev/matrox/g450_pll.h create mode 100644 kernel/drivers/video/fbdev/matrox/i2c-matroxfb.c create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_DAC1064.c create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_DAC1064.h create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_Ti3026.c create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_Ti3026.h create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_accel.c create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_accel.h create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_base.c create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_base.h create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_crtc2.c create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_crtc2.h create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_g450.c create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_g450.h create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_maven.c create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_maven.h create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_misc.c create mode 100644 kernel/drivers/video/fbdev/matrox/matroxfb_misc.h create mode 100644 kernel/drivers/video/fbdev/maxinefb.c create mode 100644 kernel/drivers/video/fbdev/mb862xx/Makefile create mode 100644 kernel/drivers/video/fbdev/mb862xx/mb862xx-i2c.c create mode 100644 kernel/drivers/video/fbdev/mb862xx/mb862xx_reg.h create mode 100644 kernel/drivers/video/fbdev/mb862xx/mb862xxfb.h create mode 100644 kernel/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c create mode 100644 kernel/drivers/video/fbdev/mb862xx/mb862xxfb_accel.h create mode 100644 kernel/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c create mode 100644 kernel/drivers/video/fbdev/mbx/Makefile create mode 100644 kernel/drivers/video/fbdev/mbx/mbxdebugfs.c create mode 100644 kernel/drivers/video/fbdev/mbx/mbxfb.c create mode 100644 kernel/drivers/video/fbdev/mbx/reg_bits.h create mode 100644 kernel/drivers/video/fbdev/mbx/regs.h create mode 100644 kernel/drivers/video/fbdev/metronomefb.c create mode 100644 kernel/drivers/video/fbdev/mmp/Kconfig create mode 100644 kernel/drivers/video/fbdev/mmp/Makefile create mode 100644 kernel/drivers/video/fbdev/mmp/core.c create mode 100644 kernel/drivers/video/fbdev/mmp/fb/Kconfig create mode 100644 kernel/drivers/video/fbdev/mmp/fb/Makefile create mode 100644 kernel/drivers/video/fbdev/mmp/fb/mmpfb.c create mode 100644 kernel/drivers/video/fbdev/mmp/fb/mmpfb.h create mode 100644 kernel/drivers/video/fbdev/mmp/hw/Kconfig create mode 100644 kernel/drivers/video/fbdev/mmp/hw/Makefile create mode 100644 kernel/drivers/video/fbdev/mmp/hw/mmp_ctrl.c create mode 100644 kernel/drivers/video/fbdev/mmp/hw/mmp_ctrl.h create mode 100644 kernel/drivers/video/fbdev/mmp/hw/mmp_spi.c create mode 100644 kernel/drivers/video/fbdev/mmp/panel/Kconfig create mode 100644 kernel/drivers/video/fbdev/mmp/panel/Makefile create mode 100644 kernel/drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c create mode 100644 kernel/drivers/video/fbdev/msm/Makefile create mode 100644 kernel/drivers/video/fbdev/msm/mddi.c create mode 100644 kernel/drivers/video/fbdev/msm/mddi_client_dummy.c create mode 100644 kernel/drivers/video/fbdev/msm/mddi_client_nt35399.c create mode 100644 kernel/drivers/video/fbdev/msm/mddi_client_toshiba.c create mode 100644 kernel/drivers/video/fbdev/msm/mddi_hw.h create mode 100644 kernel/drivers/video/fbdev/msm/mdp.c create mode 100644 kernel/drivers/video/fbdev/msm/mdp_csc_table.h create mode 100644 kernel/drivers/video/fbdev/msm/mdp_hw.h create mode 100644 kernel/drivers/video/fbdev/msm/mdp_ppp.c create mode 100644 kernel/drivers/video/fbdev/msm/mdp_scale_tables.c create mode 100644 kernel/drivers/video/fbdev/msm/mdp_scale_tables.h create mode 100644 kernel/drivers/video/fbdev/msm/msm_fb.c create mode 100644 kernel/drivers/video/fbdev/mx3fb.c create mode 100644 kernel/drivers/video/fbdev/mxsfb.c create mode 100644 kernel/drivers/video/fbdev/n411.c create mode 100644 kernel/drivers/video/fbdev/neofb.c create mode 100644 kernel/drivers/video/fbdev/nuc900fb.c create mode 100644 kernel/drivers/video/fbdev/nuc900fb.h create mode 100644 kernel/drivers/video/fbdev/nvidia/Makefile create mode 100644 kernel/drivers/video/fbdev/nvidia/nv_accel.c create mode 100644 kernel/drivers/video/fbdev/nvidia/nv_backlight.c create mode 100644 kernel/drivers/video/fbdev/nvidia/nv_dma.h create mode 100644 kernel/drivers/video/fbdev/nvidia/nv_hw.c create mode 100644 kernel/drivers/video/fbdev/nvidia/nv_i2c.c create mode 100644 kernel/drivers/video/fbdev/nvidia/nv_local.h create mode 100644 kernel/drivers/video/fbdev/nvidia/nv_of.c create mode 100644 kernel/drivers/video/fbdev/nvidia/nv_proto.h create mode 100644 kernel/drivers/video/fbdev/nvidia/nv_setup.c create mode 100644 kernel/drivers/video/fbdev/nvidia/nv_type.h create mode 100644 kernel/drivers/video/fbdev/nvidia/nvidia.c create mode 100644 kernel/drivers/video/fbdev/ocfb.c create mode 100644 kernel/drivers/video/fbdev/offb.c create mode 100644 kernel/drivers/video/fbdev/omap/Kconfig create mode 100644 kernel/drivers/video/fbdev/omap/Makefile create mode 100644 kernel/drivers/video/fbdev/omap/hwa742.c create mode 100644 kernel/drivers/video/fbdev/omap/lcd_ams_delta.c create mode 100644 kernel/drivers/video/fbdev/omap/lcd_h3.c create mode 100644 kernel/drivers/video/fbdev/omap/lcd_htcherald.c create mode 100644 kernel/drivers/video/fbdev/omap/lcd_inn1510.c create mode 100644 kernel/drivers/video/fbdev/omap/lcd_inn1610.c create mode 100644 kernel/drivers/video/fbdev/omap/lcd_mipid.c create mode 100644 kernel/drivers/video/fbdev/omap/lcd_osk.c create mode 100644 kernel/drivers/video/fbdev/omap/lcd_palmte.c create mode 100644 kernel/drivers/video/fbdev/omap/lcd_palmtt.c create mode 100644 kernel/drivers/video/fbdev/omap/lcd_palmz71.c create mode 100644 kernel/drivers/video/fbdev/omap/lcdc.c create mode 100644 kernel/drivers/video/fbdev/omap/lcdc.h create mode 100644 kernel/drivers/video/fbdev/omap/omapfb.h create mode 100644 kernel/drivers/video/fbdev/omap/omapfb_main.c create mode 100644 kernel/drivers/video/fbdev/omap/sossi.c create mode 100644 kernel/drivers/video/fbdev/omap2/Kconfig create mode 100644 kernel/drivers/video/fbdev/omap2/Makefile create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/Kconfig create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/Makefile create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/connector-dvi.c create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/encoder-opa362.c create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/panel-dpi.c create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c create mode 100644 kernel/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/Kconfig create mode 100644 kernel/drivers/video/fbdev/omap2/dss/Makefile create mode 100644 kernel/drivers/video/fbdev/omap2/dss/apply.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/core.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/dispc-compat.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/dispc-compat.h create mode 100644 kernel/drivers/video/fbdev/omap2/dss/dispc.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/dispc.h create mode 100644 kernel/drivers/video/fbdev/omap2/dss/dispc_coefs.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/display-sysfs.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/display.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/dpi.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/dsi.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/dss-of.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/dss.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/dss.h create mode 100644 kernel/drivers/video/fbdev/omap2/dss/dss_features.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/dss_features.h create mode 100644 kernel/drivers/video/fbdev/omap2/dss/hdmi.h create mode 100644 kernel/drivers/video/fbdev/omap2/dss/hdmi4.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/hdmi4_core.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/hdmi4_core.h create mode 100644 kernel/drivers/video/fbdev/omap2/dss/hdmi5.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/hdmi5_core.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/hdmi5_core.h create mode 100644 kernel/drivers/video/fbdev/omap2/dss/hdmi_common.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/hdmi_phy.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/hdmi_pll.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/hdmi_wp.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/manager-sysfs.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/manager.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/output.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/overlay-sysfs.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/overlay.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/pll.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/rfbi.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/sdi.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/venc.c create mode 100644 kernel/drivers/video/fbdev/omap2/dss/video-pll.c create mode 100644 kernel/drivers/video/fbdev/omap2/omapfb/Kconfig create mode 100644 kernel/drivers/video/fbdev/omap2/omapfb/Makefile create mode 100644 kernel/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c create mode 100644 kernel/drivers/video/fbdev/omap2/omapfb/omapfb-main.c create mode 100644 kernel/drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c create mode 100644 kernel/drivers/video/fbdev/omap2/omapfb/omapfb.h create mode 100644 kernel/drivers/video/fbdev/omap2/vrfb.c create mode 100644 kernel/drivers/video/fbdev/p9100.c create mode 100644 kernel/drivers/video/fbdev/platinumfb.c create mode 100644 kernel/drivers/video/fbdev/platinumfb.h create mode 100644 kernel/drivers/video/fbdev/pm2fb.c create mode 100644 kernel/drivers/video/fbdev/pm3fb.c create mode 100644 kernel/drivers/video/fbdev/pmag-aa-fb.c create mode 100644 kernel/drivers/video/fbdev/pmag-ba-fb.c create mode 100644 kernel/drivers/video/fbdev/pmagb-b-fb.c create mode 100644 kernel/drivers/video/fbdev/ps3fb.c create mode 100644 kernel/drivers/video/fbdev/pvr2fb.c create mode 100644 kernel/drivers/video/fbdev/pxa168fb.c create mode 100644 kernel/drivers/video/fbdev/pxa168fb.h create mode 100644 kernel/drivers/video/fbdev/pxa3xx-gcu.c create mode 100644 kernel/drivers/video/fbdev/pxa3xx-gcu.h create mode 100644 kernel/drivers/video/fbdev/pxafb.c create mode 100644 kernel/drivers/video/fbdev/pxafb.h create mode 100644 kernel/drivers/video/fbdev/q40fb.c create mode 100644 kernel/drivers/video/fbdev/riva/Makefile create mode 100644 kernel/drivers/video/fbdev/riva/fbdev.c create mode 100644 kernel/drivers/video/fbdev/riva/nv_driver.c create mode 100644 kernel/drivers/video/fbdev/riva/nv_type.h create mode 100644 kernel/drivers/video/fbdev/riva/nvreg.h create mode 100644 kernel/drivers/video/fbdev/riva/riva_hw.c create mode 100644 kernel/drivers/video/fbdev/riva/riva_hw.h create mode 100644 kernel/drivers/video/fbdev/riva/riva_tbl.h create mode 100644 kernel/drivers/video/fbdev/riva/rivafb-i2c.c create mode 100644 kernel/drivers/video/fbdev/riva/rivafb.h create mode 100644 kernel/drivers/video/fbdev/s1d13xxxfb.c create mode 100644 kernel/drivers/video/fbdev/s3c-fb.c create mode 100644 kernel/drivers/video/fbdev/s3c2410fb.c create mode 100644 kernel/drivers/video/fbdev/s3c2410fb.h create mode 100644 kernel/drivers/video/fbdev/s3fb.c create mode 100644 kernel/drivers/video/fbdev/sa1100fb.c create mode 100644 kernel/drivers/video/fbdev/sa1100fb.h create mode 100644 kernel/drivers/video/fbdev/savage/Makefile create mode 100644 kernel/drivers/video/fbdev/savage/savagefb-i2c.c create mode 100644 kernel/drivers/video/fbdev/savage/savagefb.h create mode 100644 kernel/drivers/video/fbdev/savage/savagefb_accel.c create mode 100644 kernel/drivers/video/fbdev/savage/savagefb_driver.c create mode 100644 kernel/drivers/video/fbdev/sbuslib.c create mode 100644 kernel/drivers/video/fbdev/sbuslib.h create mode 100644 kernel/drivers/video/fbdev/sh7760fb.c create mode 100644 kernel/drivers/video/fbdev/sh_mipi_dsi.c create mode 100644 kernel/drivers/video/fbdev/sh_mobile_hdmi.c create mode 100644 kernel/drivers/video/fbdev/sh_mobile_lcdcfb.c create mode 100644 kernel/drivers/video/fbdev/sh_mobile_lcdcfb.h create mode 100644 kernel/drivers/video/fbdev/sh_mobile_meram.c create mode 100644 kernel/drivers/video/fbdev/simplefb.c create mode 100644 kernel/drivers/video/fbdev/sis/300vtbl.h create mode 100644 kernel/drivers/video/fbdev/sis/310vtbl.h create mode 100644 kernel/drivers/video/fbdev/sis/Makefile create mode 100644 kernel/drivers/video/fbdev/sis/init.c create mode 100644 kernel/drivers/video/fbdev/sis/init.h create mode 100644 kernel/drivers/video/fbdev/sis/init301.c create mode 100644 kernel/drivers/video/fbdev/sis/init301.h create mode 100644 kernel/drivers/video/fbdev/sis/initdef.h create mode 100644 kernel/drivers/video/fbdev/sis/initextlfb.c create mode 100644 kernel/drivers/video/fbdev/sis/oem300.h create mode 100644 kernel/drivers/video/fbdev/sis/oem310.h create mode 100644 kernel/drivers/video/fbdev/sis/sis.h create mode 100644 kernel/drivers/video/fbdev/sis/sis_accel.c create mode 100644 kernel/drivers/video/fbdev/sis/sis_accel.h create mode 100644 kernel/drivers/video/fbdev/sis/sis_main.c create mode 100644 kernel/drivers/video/fbdev/sis/sis_main.h create mode 100644 kernel/drivers/video/fbdev/sis/vgatypes.h create mode 100644 kernel/drivers/video/fbdev/sis/vstruct.h create mode 100644 kernel/drivers/video/fbdev/skeletonfb.c create mode 100644 kernel/drivers/video/fbdev/sm501fb.c create mode 100644 kernel/drivers/video/fbdev/smscufx.c create mode 100644 kernel/drivers/video/fbdev/ssd1307fb.c create mode 100644 kernel/drivers/video/fbdev/sstfb.c create mode 100644 kernel/drivers/video/fbdev/sticore.h create mode 100644 kernel/drivers/video/fbdev/stifb.c create mode 100644 kernel/drivers/video/fbdev/sunxvr1000.c create mode 100644 kernel/drivers/video/fbdev/sunxvr2500.c create mode 100644 kernel/drivers/video/fbdev/sunxvr500.c create mode 100644 kernel/drivers/video/fbdev/tcx.c create mode 100644 kernel/drivers/video/fbdev/tdfxfb.c create mode 100644 kernel/drivers/video/fbdev/tgafb.c create mode 100644 kernel/drivers/video/fbdev/tmiofb.c create mode 100644 kernel/drivers/video/fbdev/tridentfb.c create mode 100644 kernel/drivers/video/fbdev/udlfb.c create mode 100644 kernel/drivers/video/fbdev/uvesafb.c create mode 100644 kernel/drivers/video/fbdev/valkyriefb.c create mode 100644 kernel/drivers/video/fbdev/valkyriefb.h create mode 100644 kernel/drivers/video/fbdev/vermilion/Makefile create mode 100644 kernel/drivers/video/fbdev/vermilion/cr_pll.c create mode 100644 kernel/drivers/video/fbdev/vermilion/vermilion.c create mode 100644 kernel/drivers/video/fbdev/vermilion/vermilion.h create mode 100644 kernel/drivers/video/fbdev/vesafb.c create mode 100644 kernel/drivers/video/fbdev/vfb.c create mode 100644 kernel/drivers/video/fbdev/vga16fb.c create mode 100644 kernel/drivers/video/fbdev/via/Makefile create mode 100644 kernel/drivers/video/fbdev/via/accel.c create mode 100644 kernel/drivers/video/fbdev/via/accel.h create mode 100644 kernel/drivers/video/fbdev/via/chip.h create mode 100644 kernel/drivers/video/fbdev/via/debug.h create mode 100644 kernel/drivers/video/fbdev/via/dvi.c create mode 100644 kernel/drivers/video/fbdev/via/dvi.h create mode 100644 kernel/drivers/video/fbdev/via/global.c create mode 100644 kernel/drivers/video/fbdev/via/global.h create mode 100644 kernel/drivers/video/fbdev/via/hw.c create mode 100644 kernel/drivers/video/fbdev/via/hw.h create mode 100644 kernel/drivers/video/fbdev/via/ioctl.c create mode 100644 kernel/drivers/video/fbdev/via/ioctl.h create mode 100644 kernel/drivers/video/fbdev/via/lcd.c create mode 100644 kernel/drivers/video/fbdev/via/lcd.h create mode 100644 kernel/drivers/video/fbdev/via/share.h create mode 100644 kernel/drivers/video/fbdev/via/tblDPASetting.c create mode 100644 kernel/drivers/video/fbdev/via/tblDPASetting.h create mode 100644 kernel/drivers/video/fbdev/via/via-core.c create mode 100644 kernel/drivers/video/fbdev/via/via-gpio.c create mode 100644 kernel/drivers/video/fbdev/via/via_aux.c create mode 100644 kernel/drivers/video/fbdev/via/via_aux.h create mode 100644 kernel/drivers/video/fbdev/via/via_aux_ch7301.c create mode 100644 kernel/drivers/video/fbdev/via/via_aux_edid.c create mode 100644 kernel/drivers/video/fbdev/via/via_aux_sii164.c create mode 100644 kernel/drivers/video/fbdev/via/via_aux_vt1621.c create mode 100644 kernel/drivers/video/fbdev/via/via_aux_vt1622.c create mode 100644 kernel/drivers/video/fbdev/via/via_aux_vt1625.c create mode 100644 kernel/drivers/video/fbdev/via/via_aux_vt1631.c create mode 100644 kernel/drivers/video/fbdev/via/via_aux_vt1632.c create mode 100644 kernel/drivers/video/fbdev/via/via_aux_vt1636.c create mode 100644 kernel/drivers/video/fbdev/via/via_clock.c create mode 100644 kernel/drivers/video/fbdev/via/via_clock.h create mode 100644 kernel/drivers/video/fbdev/via/via_i2c.c create mode 100644 kernel/drivers/video/fbdev/via/via_modesetting.c create mode 100644 kernel/drivers/video/fbdev/via/via_modesetting.h create mode 100644 kernel/drivers/video/fbdev/via/via_utility.c create mode 100644 kernel/drivers/video/fbdev/via/via_utility.h create mode 100644 kernel/drivers/video/fbdev/via/viafbdev.c create mode 100644 kernel/drivers/video/fbdev/via/viafbdev.h create mode 100644 kernel/drivers/video/fbdev/via/viamode.c create mode 100644 kernel/drivers/video/fbdev/via/viamode.h create mode 100644 kernel/drivers/video/fbdev/via/vt1636.c create mode 100644 kernel/drivers/video/fbdev/via/vt1636.h create mode 100644 kernel/drivers/video/fbdev/vt8500lcdfb.c create mode 100644 kernel/drivers/video/fbdev/vt8500lcdfb.h create mode 100644 kernel/drivers/video/fbdev/vt8623fb.c create mode 100644 kernel/drivers/video/fbdev/w100fb.c create mode 100644 kernel/drivers/video/fbdev/w100fb.h create mode 100644 kernel/drivers/video/fbdev/wm8505fb.c create mode 100644 kernel/drivers/video/fbdev/wm8505fb_regs.h create mode 100644 kernel/drivers/video/fbdev/wmt_ge_rops.c create mode 100644 kernel/drivers/video/fbdev/wmt_ge_rops.h create mode 100644 kernel/drivers/video/fbdev/xen-fbfront.c create mode 100644 kernel/drivers/video/fbdev/xilinxfb.c create mode 100644 kernel/drivers/video/hdmi.c create mode 100644 kernel/drivers/video/logo/.gitignore create mode 100644 kernel/drivers/video/logo/Kconfig create mode 100644 kernel/drivers/video/logo/Makefile create mode 100644 kernel/drivers/video/logo/clut_vga16.ppm create mode 100644 kernel/drivers/video/logo/logo.c create mode 100644 kernel/drivers/video/logo/logo_blackfin_clut224.ppm create mode 100644 kernel/drivers/video/logo/logo_blackfin_vga16.ppm create mode 100644 kernel/drivers/video/logo/logo_dec_clut224.ppm create mode 100644 kernel/drivers/video/logo/logo_linux_clut224.ppm create mode 100644 kernel/drivers/video/logo/logo_linux_mono.pbm create mode 100644 kernel/drivers/video/logo/logo_linux_vga16.ppm create mode 100644 kernel/drivers/video/logo/logo_m32r_clut224.ppm create mode 100644 kernel/drivers/video/logo/logo_mac_clut224.ppm create mode 100644 kernel/drivers/video/logo/logo_parisc_clut224.ppm create mode 100644 kernel/drivers/video/logo/logo_sgi_clut224.ppm create mode 100644 kernel/drivers/video/logo/logo_spe_clut224.ppm create mode 100644 kernel/drivers/video/logo/logo_sun_clut224.ppm create mode 100644 kernel/drivers/video/logo/logo_superh_clut224.ppm create mode 100644 kernel/drivers/video/logo/logo_superh_mono.pbm create mode 100644 kernel/drivers/video/logo/logo_superh_vga16.ppm create mode 100644 kernel/drivers/video/of_display_timing.c create mode 100644 kernel/drivers/video/of_videomode.c create mode 100644 kernel/drivers/video/vgastate.c create mode 100644 kernel/drivers/video/videomode.c (limited to 'kernel/drivers/video') diff --git a/kernel/drivers/video/Kconfig b/kernel/drivers/video/Kconfig new file mode 100644 index 000000000..8bf495ffb --- /dev/null +++ b/kernel/drivers/video/Kconfig @@ -0,0 +1,55 @@ +# +# Video configuration +# + +menu "Graphics support" + depends on HAS_IOMEM + +config HAVE_FB_ATMEL + bool + +config SH_MIPI_DSI + tristate + depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK + +config SH_LCD_MIPI_DSI + bool + +source "drivers/char/agp/Kconfig" + +source "drivers/gpu/vga/Kconfig" + +source "drivers/gpu/host1x/Kconfig" +source "drivers/gpu/ipu-v3/Kconfig" + +menu "Direct Rendering Manager" +source "drivers/gpu/drm/Kconfig" +endmenu + +menu "Frame buffer Devices" +source "drivers/video/fbdev/Kconfig" +endmenu + +source "drivers/video/backlight/Kconfig" + +config VGASTATE + tristate + default n + +config VIDEOMODE_HELPERS + bool + +config HDMI + bool + +if VT + source "drivers/video/console/Kconfig" +endif + +if FB || SGI_NEWPORT_CONSOLE + source "drivers/video/logo/Kconfig" + +endif + + +endmenu diff --git a/kernel/drivers/video/Makefile b/kernel/drivers/video/Makefile new file mode 100644 index 000000000..9ad3c17d6 --- /dev/null +++ b/kernel/drivers/video/Makefile @@ -0,0 +1,13 @@ +obj-$(CONFIG_VGASTATE) += vgastate.o +obj-$(CONFIG_HDMI) += hdmi.o + +obj-$(CONFIG_VT) += console/ +obj-$(CONFIG_LOGO) += logo/ +obj-y += backlight/ + +obj-y += fbdev/ + +obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o +ifeq ($(CONFIG_OF),y) +obj-$(CONFIG_VIDEOMODE_HELPERS) += of_display_timing.o of_videomode.o +endif diff --git a/kernel/drivers/video/backlight/88pm860x_bl.c b/kernel/drivers/video/backlight/88pm860x_bl.c new file mode 100644 index 000000000..2da586287 --- /dev/null +++ b/kernel/drivers/video/backlight/88pm860x_bl.c @@ -0,0 +1,274 @@ +/* + * Backlight driver for Marvell Semiconductor 88PM8606 + * + * Copyright (C) 2009 Marvell International Ltd. + * Haojian Zhuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_BRIGHTNESS (0xFF) +#define MIN_BRIGHTNESS (0) + +#define CURRENT_BITMASK (0x1F << 1) + +struct pm860x_backlight_data { + struct pm860x_chip *chip; + struct i2c_client *i2c; + int current_brightness; + int port; + int pwm; + int iset; + int reg_duty_cycle; + int reg_always_on; + int reg_current; +}; + +static int backlight_power_set(struct pm860x_chip *chip, int port, + int on) +{ + int ret = -EINVAL; + + switch (port) { + case 0: + ret = on ? pm8606_osc_enable(chip, WLED1_DUTY) : + pm8606_osc_disable(chip, WLED1_DUTY); + break; + case 1: + ret = on ? pm8606_osc_enable(chip, WLED2_DUTY) : + pm8606_osc_disable(chip, WLED2_DUTY); + break; + case 2: + ret = on ? pm8606_osc_enable(chip, WLED3_DUTY) : + pm8606_osc_disable(chip, WLED3_DUTY); + break; + } + return ret; +} + +static int pm860x_backlight_set(struct backlight_device *bl, int brightness) +{ + struct pm860x_backlight_data *data = bl_get_data(bl); + struct pm860x_chip *chip = data->chip; + unsigned char value; + int ret; + + if (brightness > MAX_BRIGHTNESS) + value = MAX_BRIGHTNESS; + else + value = brightness; + + if (brightness) + backlight_power_set(chip, data->port, 1); + + ret = pm860x_reg_write(data->i2c, data->reg_duty_cycle, value); + if (ret < 0) + goto out; + + if ((data->current_brightness == 0) && brightness) { + if (data->iset) { + ret = pm860x_set_bits(data->i2c, data->reg_current, + CURRENT_BITMASK, data->iset); + if (ret < 0) + goto out; + } + if (data->pwm) { + ret = pm860x_set_bits(data->i2c, PM8606_PWM, + PM8606_PWM_FREQ_MASK, data->pwm); + if (ret < 0) + goto out; + } + if (brightness == MAX_BRIGHTNESS) { + /* set WLED_ON bit as 100% */ + ret = pm860x_set_bits(data->i2c, data->reg_always_on, + PM8606_WLED_ON, PM8606_WLED_ON); + } + } else { + if (brightness == MAX_BRIGHTNESS) { + /* set WLED_ON bit as 100% */ + ret = pm860x_set_bits(data->i2c, data->reg_always_on, + PM8606_WLED_ON, PM8606_WLED_ON); + } else { + /* clear WLED_ON bit since it's not 100% */ + ret = pm860x_set_bits(data->i2c, data->reg_always_on, + PM8606_WLED_ON, 0); + } + } + if (ret < 0) + goto out; + + if (brightness == 0) + backlight_power_set(chip, data->port, 0); + + dev_dbg(chip->dev, "set brightness %d\n", value); + data->current_brightness = value; + return 0; +out: + dev_dbg(chip->dev, "set brightness %d failure with return value: %d\n", + value, ret); + return ret; +} + +static int pm860x_backlight_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + + if (bl->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.state & BL_CORE_SUSPENDED) + brightness = 0; + + return pm860x_backlight_set(bl, brightness); +} + +static int pm860x_backlight_get_brightness(struct backlight_device *bl) +{ + struct pm860x_backlight_data *data = bl_get_data(bl); + struct pm860x_chip *chip = data->chip; + int ret; + + ret = pm860x_reg_read(data->i2c, data->reg_duty_cycle); + if (ret < 0) + goto out; + data->current_brightness = ret; + dev_dbg(chip->dev, "get brightness %d\n", data->current_brightness); + return data->current_brightness; +out: + return -EINVAL; +} + +static const struct backlight_ops pm860x_backlight_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = pm860x_backlight_update_status, + .get_brightness = pm860x_backlight_get_brightness, +}; + +#ifdef CONFIG_OF +static int pm860x_backlight_dt_init(struct platform_device *pdev, + struct pm860x_backlight_data *data, + char *name) +{ + struct device_node *nproot, *np; + int iset = 0; + + nproot = of_get_child_by_name(pdev->dev.parent->of_node, "backlights"); + if (!nproot) { + dev_err(&pdev->dev, "failed to find backlights node\n"); + return -ENODEV; + } + for_each_child_of_node(nproot, np) { + if (!of_node_cmp(np->name, name)) { + of_property_read_u32(np, "marvell,88pm860x-iset", + &iset); + data->iset = PM8606_WLED_CURRENT(iset); + of_property_read_u32(np, "marvell,88pm860x-pwm", + &data->pwm); + break; + } + } + of_node_put(nproot); + return 0; +} +#else +#define pm860x_backlight_dt_init(x, y, z) (-1) +#endif + +static int pm860x_backlight_probe(struct platform_device *pdev) +{ + struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct pm860x_backlight_pdata *pdata = dev_get_platdata(&pdev->dev); + struct pm860x_backlight_data *data; + struct backlight_device *bl; + struct resource *res; + struct backlight_properties props; + char name[MFD_NAME_SIZE]; + int ret = 0; + + data = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_backlight_data), + GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + res = platform_get_resource_byname(pdev, IORESOURCE_REG, "duty cycle"); + if (!res) { + dev_err(&pdev->dev, "No REG resource for duty cycle\n"); + return -ENXIO; + } + data->reg_duty_cycle = res->start; + res = platform_get_resource_byname(pdev, IORESOURCE_REG, "always on"); + if (!res) { + dev_err(&pdev->dev, "No REG resource for always on\n"); + return -ENXIO; + } + data->reg_always_on = res->start; + res = platform_get_resource_byname(pdev, IORESOURCE_REG, "current"); + if (!res) { + dev_err(&pdev->dev, "No REG resource for current\n"); + return -ENXIO; + } + data->reg_current = res->start; + + memset(name, 0, MFD_NAME_SIZE); + sprintf(name, "backlight-%d", pdev->id); + data->port = pdev->id; + data->chip = chip; + data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; + data->current_brightness = MAX_BRIGHTNESS; + if (pm860x_backlight_dt_init(pdev, data, name)) { + if (pdata) { + data->pwm = pdata->pwm; + data->iset = pdata->iset; + } + } + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; + props.max_brightness = MAX_BRIGHTNESS; + bl = devm_backlight_device_register(&pdev->dev, name, &pdev->dev, data, + &pm860x_backlight_ops, &props); + if (IS_ERR(bl)) { + dev_err(&pdev->dev, "failed to register backlight\n"); + return PTR_ERR(bl); + } + bl->props.brightness = MAX_BRIGHTNESS; + + platform_set_drvdata(pdev, bl); + + /* read current backlight */ + ret = pm860x_backlight_get_brightness(bl); + if (ret < 0) + return ret; + + backlight_update_status(bl); + return 0; +} + +static struct platform_driver pm860x_backlight_driver = { + .driver = { + .name = "88pm860x-backlight", + }, + .probe = pm860x_backlight_probe, +}; + +module_platform_driver(pm860x_backlight_driver); + +MODULE_DESCRIPTION("Backlight Driver for Marvell Semiconductor 88PM8606"); +MODULE_AUTHOR("Haojian Zhuang "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:88pm860x-backlight"); diff --git a/kernel/drivers/video/backlight/Kconfig b/kernel/drivers/video/backlight/Kconfig new file mode 100644 index 000000000..2d9923a60 --- /dev/null +++ b/kernel/drivers/video/backlight/Kconfig @@ -0,0 +1,456 @@ +# +# Backlight & LCD drivers configuration +# + +menuconfig BACKLIGHT_LCD_SUPPORT + bool "Backlight & LCD device support" + help + Enable this to be able to choose the drivers for controlling the + backlight and the LCD panel on some platforms, for example on PDAs. + +if BACKLIGHT_LCD_SUPPORT + +# +# LCD +# +config LCD_CLASS_DEVICE + tristate "Lowlevel LCD controls" + default m + help + This framework adds support for low-level control of LCD. + Some framebuffer devices connect to platform-specific LCD modules + in order to have a platform-specific way to control the flat panel + (contrast and applying power to the LCD (not to the backlight!)). + + To have support for your specific LCD panel you will have to + select the proper drivers which depend on this option. + +if LCD_CLASS_DEVICE + +config LCD_CORGI + tristate "LCD Panel support for SHARP corgi/spitz model" + depends on SPI_MASTER && PXA_SHARPSL && BACKLIGHT_CLASS_DEVICE + help + Say y here to support the LCD panels usually found on SHARP + corgi (C7x0) and spitz (Cxx00) models. + +config LCD_L4F00242T03 + tristate "Epson L4F00242T03 LCD" + depends on SPI_MASTER && GPIOLIB + help + SPI driver for Epson L4F00242T03. This provides basic support + for init and powering the LCD up/down through a sysfs interface. + +config LCD_LMS283GF05 + tristate "Samsung LMS283GF05 LCD" + depends on SPI_MASTER && GPIOLIB + help + SPI driver for Samsung LMS283GF05. This provides basic support + for powering the LCD up/down through a sysfs interface. + +config LCD_LTV350QV + tristate "Samsung LTV350QV LCD Panel" + depends on SPI_MASTER + help + If you have a Samsung LTV350QV LCD panel, say y to include a + power control driver for it. The panel starts up in power + off state, so you need this driver in order to see any + output. + + The LTV350QV panel is present on all ATSTK1000 boards. + +config LCD_ILI922X + tristate "ILI Technology ILI9221/ILI9222 support" + depends on SPI + help + If you have a panel based on the ILI9221/9222 controller + chip then say y to include a driver for it. + +config LCD_ILI9320 + tristate "ILI Technology ILI9320 controller support" + depends on SPI + help + If you have a panel based on the ILI9320 controller chip + then say y to include a power driver for it. + +config LCD_TDO24M + tristate "Toppoly TDO24M and TDO35S LCD Panels support" + depends on SPI_MASTER + help + If you have a Toppoly TDO24M/TDO35S series LCD panel, say y here to + include the support for it. + +config LCD_VGG2432A4 + tristate "VGG2432A4 LCM device support" + depends on SPI_MASTER + select LCD_ILI9320 + help + If you have a VGG2432A4 panel based on the ILI9320 controller chip + then say y to include a power driver for it. + +config LCD_PLATFORM + tristate "Platform LCD controls" + help + This driver provides a platform-device registered LCD power + control interface. + +config LCD_TOSA + tristate "Sharp SL-6000 LCD Driver" + depends on I2C && SPI && MACH_TOSA + help + If you have an Sharp SL-6000 Zaurus say Y to enable a driver + for its LCD. + +config LCD_HP700 + tristate "HP Jornada 700 series LCD Driver" + depends on SA1100_JORNADA720_SSP && !PREEMPT + default y + help + If you have an HP Jornada 700 series handheld (710/720/728) + say Y to enable LCD control driver. + +config LCD_S6E63M0 + tristate "S6E63M0 AMOLED LCD Driver" + depends on SPI && BACKLIGHT_CLASS_DEVICE + default n + help + If you have an S6E63M0 LCD Panel, say Y to enable its + LCD control driver. + +config LCD_LD9040 + tristate "LD9040 AMOLED LCD Driver" + depends on SPI && BACKLIGHT_CLASS_DEVICE + default n + help + If you have an LD9040 Panel, say Y to enable its + control driver. + +config LCD_AMS369FG06 + tristate "AMS369FG06 AMOLED LCD Driver" + depends on SPI && BACKLIGHT_CLASS_DEVICE + default n + help + If you have an AMS369FG06 AMOLED Panel, say Y to enable its + LCD control driver. + +config LCD_LMS501KF03 + tristate "LMS501KF03 LCD Driver" + depends on SPI + default n + help + If you have an LMS501KF03 LCD Panel, say Y to enable its + LCD control driver. + +config LCD_HX8357 + tristate "Himax HX-8357 LCD Driver" + depends on SPI + help + If you have a HX-8357 LCD panel, say Y to enable its LCD control + driver. + +endif # LCD_CLASS_DEVICE + +# +# Backlight +# +config BACKLIGHT_CLASS_DEVICE + tristate "Lowlevel Backlight controls" + default m + help + This framework adds support for low-level control of the LCD + backlight. This includes support for brightness and power. + + To have support for your specific LCD panel you will have to + select the proper drivers which depend on this option. + +if BACKLIGHT_CLASS_DEVICE + +config BACKLIGHT_ATMEL_LCDC + bool "Atmel LCDC Contrast-as-Backlight control" + depends on FB_ATMEL + help + This provides a backlight control internal to the Atmel LCDC + driver. If the LCD "contrast control" on your board is wired + so it controls the backlight brightness, select this option to + export this as a PWM-based backlight control. + + If in doubt, it's safe to enable this option; it doesn't kick + in unless the board's description says it's wired that way. + +config BACKLIGHT_EP93XX + tristate "Cirrus EP93xx Backlight Driver" + depends on FB_EP93XX + help + If you have a LCD backlight connected to the BRIGHT output of + the EP93xx, say Y here to enable this driver. + + To compile this driver as a module, choose M here: the module will + be called ep93xx_bl. + +config BACKLIGHT_GENERIC + tristate "Generic (aka Sharp Corgi) Backlight Driver" + default y + help + Say y to enable the generic platform backlight driver previously + known as the Corgi backlight driver. If you have a Sharp Zaurus + SL-C7xx, SL-Cxx00 or SL-6000x say y. + +config BACKLIGHT_IPAQ_MICRO + tristate "iPAQ microcontroller backlight driver" + depends on MFD_IPAQ_MICRO + default y + help + Say y to enable the backlight driver for Compaq iPAQ handheld + computers. Say yes if you have one of the h3100/h3600/h3700 + machines. + +config BACKLIGHT_LM3533 + tristate "Backlight Driver for LM3533" + depends on BACKLIGHT_CLASS_DEVICE + depends on MFD_LM3533 + help + Say Y to enable the backlight driver for National Semiconductor / TI + LM3533 Lighting Power chips. + + The backlights can be controlled directly, through PWM input, or by + the ambient-light-sensor interface. The chip supports 256 brightness + levels. + +config BACKLIGHT_LOCOMO + tristate "Sharp LOCOMO LCD/Backlight Driver" + depends on SHARP_LOCOMO + default y + help + If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to + enable the LCD/backlight driver. + +config BACKLIGHT_OMAP1 + tristate "OMAP1 PWL-based LCD Backlight" + depends on ARCH_OMAP1 + default y + help + This driver controls the LCD backlight level and power for + the PWL module of OMAP1 processors. Say Y if your board + uses this hardware. + +config BACKLIGHT_HP680 + tristate "HP Jornada 680 Backlight Driver" + depends on SH_HP6XX + default y + help + If you have a HP Jornada 680, say y to enable the + backlight driver. + +config BACKLIGHT_HP700 + tristate "HP Jornada 700 series Backlight Driver" + depends on SA1100_JORNADA720_SSP && !PREEMPT + default y + help + If you have an HP Jornada 700 series, + say Y to include backlight control driver. + +config BACKLIGHT_CARILLO_RANCH + tristate "Intel Carillo Ranch Backlight Driver" + depends on LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578 + help + If you have a Intel LE80578 (Carillo Ranch) say Y to enable the + backlight driver. + +config BACKLIGHT_PWM + tristate "Generic PWM based Backlight Driver" + depends on PWM + help + If you have a LCD backlight adjustable by PWM, say Y to enable + this driver. + +config BACKLIGHT_DA903X + tristate "Backlight Driver for DA9030/DA9034 using WLED" + depends on PMIC_DA903X + help + If you have a LCD backlight connected to the WLED output of DA9030 + or DA9034 WLED output, say Y here to enable this driver. + +config BACKLIGHT_DA9052 + tristate "Dialog DA9052/DA9053 WLED" + depends on PMIC_DA9052 + help + Enable the Backlight Driver for DA9052-BC and DA9053-AA/Bx PMICs. + +config BACKLIGHT_MAX8925 + tristate "Backlight driver for MAX8925" + depends on MFD_MAX8925 + help + If you have a LCD backlight connected to the WLED output of MAX8925 + WLED output, say Y here to enable this driver. + +config BACKLIGHT_APPLE + tristate "Apple Backlight Driver" + depends on X86 && ACPI + help + If you have an Intel-based Apple say Y to enable a driver for its + backlight. + +config BACKLIGHT_TOSA + tristate "Sharp SL-6000 Backlight Driver" + depends on I2C && MACH_TOSA && LCD_TOSA + help + If you have an Sharp SL-6000 Zaurus say Y to enable a driver + for its backlight + +config BACKLIGHT_SAHARA + tristate "Tabletkiosk Sahara Touch-iT Backlight Driver" + depends on X86 + help + If you have a Tabletkiosk Sahara Touch-iT, say y to enable the + backlight driver. + +config BACKLIGHT_WM831X + tristate "WM831x PMIC Backlight Driver" + depends on MFD_WM831X + help + If you have a backlight driven by the ISINK and DCDC of a + WM831x PMIC say y to enable the backlight driver for it. + +config BACKLIGHT_ADP5520 + tristate "Backlight Driver for ADP5520/ADP5501 using WLED" + depends on PMIC_ADP5520 + help + If you have a LCD backlight connected to the BST/BL_SNK output of + ADP5520 or ADP5501, say Y here to enable this driver. + + To compile this driver as a module, choose M here: the module will + be called adp5520_bl. + +config BACKLIGHT_ADP8860 + tristate "Backlight Driver for ADP8860/ADP8861/ADP8863 using WLED" + depends on BACKLIGHT_CLASS_DEVICE && I2C + select NEW_LEDS + select LEDS_CLASS + help + If you have a LCD backlight connected to the ADP8860, ADP8861 or + ADP8863 say Y here to enable this driver. + + To compile this driver as a module, choose M here: the module will + be called adp8860_bl. + +config BACKLIGHT_ADP8870 + tristate "Backlight Driver for ADP8870 using WLED" + depends on BACKLIGHT_CLASS_DEVICE && I2C + select NEW_LEDS + select LEDS_CLASS + help + If you have a LCD backlight connected to the ADP8870, + say Y here to enable this driver. + + To compile this driver as a module, choose M here: the module will + be called adp8870_bl. + +config BACKLIGHT_88PM860X + tristate "Backlight Driver for 88PM8606 using WLED" + depends on MFD_88PM860X + help + Say Y to enable the backlight driver for Marvell 88PM8606. + +config BACKLIGHT_PCF50633 + tristate "Backlight driver for NXP PCF50633 MFD" + depends on BACKLIGHT_CLASS_DEVICE && MFD_PCF50633 + help + If you have a backlight driven by a NXP PCF50633 MFD, say Y here to + enable its driver. + +config BACKLIGHT_AAT2870 + tristate "AnalogicTech AAT2870 Backlight" + depends on BACKLIGHT_CLASS_DEVICE && MFD_AAT2870_CORE + help + If you have a AnalogicTech AAT2870 say Y to enable the + backlight driver. + +config BACKLIGHT_LM3630A + tristate "Backlight Driver for LM3630A" + depends on BACKLIGHT_CLASS_DEVICE && I2C && PWM + select REGMAP_I2C + help + This supports TI LM3630A Backlight Driver + +config BACKLIGHT_LM3639 + tristate "Backlight Driver for LM3639" + depends on BACKLIGHT_CLASS_DEVICE && I2C + select REGMAP_I2C + select NEW_LEDS + select LEDS_CLASS + help + This supports TI LM3639 Backlight + 1.5A Flash LED Driver + +config BACKLIGHT_LP855X + tristate "Backlight driver for TI LP855X" + depends on BACKLIGHT_CLASS_DEVICE && I2C && PWM + help + This supports TI LP8550, LP8551, LP8552, LP8553, LP8555, LP8556 and + LP8557 backlight driver. + +config BACKLIGHT_LP8788 + tristate "Backlight driver for TI LP8788 MFD" + depends on BACKLIGHT_CLASS_DEVICE && MFD_LP8788 && PWM + help + This supports TI LP8788 backlight driver. + +config BACKLIGHT_OT200 + tristate "Backlight driver for ot200 visualisation device" + depends on BACKLIGHT_CLASS_DEVICE && CS5535_MFGPT && GPIO_CS5535 + help + To compile this driver as a module, choose M here: the module will be + called ot200_bl. + +config BACKLIGHT_PANDORA + tristate "Backlight driver for Pandora console" + depends on TWL4030_CORE + help + If you have a Pandora console, say Y to enable the + backlight driver. + +config BACKLIGHT_SKY81452 + tristate "Backlight driver for SKY81452" + depends on BACKLIGHT_CLASS_DEVICE && MFD_SKY81452 + help + If you have a Skyworks SKY81452, say Y to enable the + backlight driver. + + To compile this driver as a module, choose M here: the module will + be called sky81452-backlight + +config BACKLIGHT_TPS65217 + tristate "TPS65217 Backlight" + depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217 + help + If you have a Texas Instruments TPS65217 say Y to enable the + backlight driver. + +config BACKLIGHT_AS3711 + tristate "AS3711 Backlight" + depends on BACKLIGHT_CLASS_DEVICE && MFD_AS3711 + help + If you have an Austrian Microsystems AS3711 say Y to enable the + backlight driver. + +config BACKLIGHT_GPIO + tristate "Generic GPIO based Backlight Driver" + depends on GPIOLIB + help + If you have a LCD backlight adjustable by GPIO, say Y to enable + this driver. + +config BACKLIGHT_LV5207LP + tristate "Sanyo LV5207LP Backlight" + depends on I2C + help + If you have a Sanyo LV5207LP say Y to enable the backlight driver. + +config BACKLIGHT_BD6107 + tristate "Rohm BD6107 Backlight" + depends on I2C + help + If you have a Rohm BD6107 say Y to enable the backlight driver. + +endif # BACKLIGHT_CLASS_DEVICE + +endif # BACKLIGHT_LCD_SUPPORT diff --git a/kernel/drivers/video/backlight/Makefile b/kernel/drivers/video/backlight/Makefile new file mode 100644 index 000000000..d67073f9d --- /dev/null +++ b/kernel/drivers/video/backlight/Makefile @@ -0,0 +1,56 @@ +# Backlight & LCD drivers + +obj-$(CONFIG_LCD_AMS369FG06) += ams369fg06.o +obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o +obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o +obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o +obj-$(CONFIG_LCD_HX8357) += hx8357.o +obj-$(CONFIG_LCD_ILI922X) += ili922x.o +obj-$(CONFIG_LCD_ILI9320) += ili9320.o +obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o +obj-$(CONFIG_LCD_LD9040) += ld9040.o +obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o +obj-$(CONFIG_LCD_LMS501KF03) += lms501kf03.o +obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o +obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o +obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o +obj-$(CONFIG_LCD_TDO24M) += tdo24m.o +obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o +obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o + +obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o +obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o +obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o +obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o +obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o +obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o +obj-$(CONFIG_BACKLIGHT_AS3711) += as3711_bl.o +obj-$(CONFIG_BACKLIGHT_BD6107) += bd6107.o +obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o +obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o +obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o +obj-$(CONFIG_BACKLIGHT_DA9052) += da9052_bl.o +obj-$(CONFIG_BACKLIGHT_EP93XX) += ep93xx_bl.o +obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o +obj-$(CONFIG_BACKLIGHT_GPIO) += gpio_backlight.o +obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o +obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o +obj-$(CONFIG_BACKLIGHT_IPAQ_MICRO) += ipaq_micro_bl.o +obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o +obj-$(CONFIG_BACKLIGHT_LM3630A) += lm3630a_bl.o +obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o +obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o +obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o +obj-$(CONFIG_BACKLIGHT_LP8788) += lp8788_bl.o +obj-$(CONFIG_BACKLIGHT_LV5207LP) += lv5207lp.o +obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o +obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o +obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o +obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o +obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o +obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o +obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o +obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o +obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o +obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o +obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o diff --git a/kernel/drivers/video/backlight/aat2870_bl.c b/kernel/drivers/video/backlight/aat2870_bl.c new file mode 100644 index 000000000..50774e657 --- /dev/null +++ b/kernel/drivers/video/backlight/aat2870_bl.c @@ -0,0 +1,233 @@ +/* + * linux/drivers/video/backlight/aat2870_bl.c + * + * Copyright (c) 2011, NVIDIA Corporation. + * Author: Jin Park + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct aat2870_bl_driver_data { + struct platform_device *pdev; + struct backlight_device *bd; + + int channels; + int max_current; + int brightness; /* current brightness */ +}; + +static inline int aat2870_brightness(struct aat2870_bl_driver_data *aat2870_bl, + int brightness) +{ + struct backlight_device *bd = aat2870_bl->bd; + int val; + + val = brightness * (aat2870_bl->max_current - 1); + val /= bd->props.max_brightness; + + return val; +} + +static inline int aat2870_bl_enable(struct aat2870_bl_driver_data *aat2870_bl) +{ + struct aat2870_data *aat2870 + = dev_get_drvdata(aat2870_bl->pdev->dev.parent); + + return aat2870->write(aat2870, AAT2870_BL_CH_EN, + (u8)aat2870_bl->channels); +} + +static inline int aat2870_bl_disable(struct aat2870_bl_driver_data *aat2870_bl) +{ + struct aat2870_data *aat2870 + = dev_get_drvdata(aat2870_bl->pdev->dev.parent); + + return aat2870->write(aat2870, AAT2870_BL_CH_EN, 0x0); +} + +static int aat2870_bl_update_status(struct backlight_device *bd) +{ + struct aat2870_bl_driver_data *aat2870_bl = bl_get_data(bd); + struct aat2870_data *aat2870 = + dev_get_drvdata(aat2870_bl->pdev->dev.parent); + int brightness = bd->props.brightness; + int ret; + + if ((brightness < 0) || (bd->props.max_brightness < brightness)) { + dev_err(&bd->dev, "invalid brightness, %d\n", brightness); + return -EINVAL; + } + + dev_dbg(&bd->dev, "brightness=%d, power=%d, state=%d\n", + bd->props.brightness, bd->props.power, bd->props.state); + + if ((bd->props.power != FB_BLANK_UNBLANK) || + (bd->props.state & BL_CORE_FBBLANK) || + (bd->props.state & BL_CORE_SUSPENDED)) + brightness = 0; + + ret = aat2870->write(aat2870, AAT2870_BLM, + (u8)aat2870_brightness(aat2870_bl, brightness)); + if (ret < 0) + return ret; + + if (brightness == 0) { + ret = aat2870_bl_disable(aat2870_bl); + if (ret < 0) + return ret; + } else if (aat2870_bl->brightness == 0) { + ret = aat2870_bl_enable(aat2870_bl); + if (ret < 0) + return ret; + } + + aat2870_bl->brightness = brightness; + + return 0; +} + +static int aat2870_bl_check_fb(struct backlight_device *bd, struct fb_info *fi) +{ + return 1; +} + +static const struct backlight_ops aat2870_bl_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = aat2870_bl_update_status, + .check_fb = aat2870_bl_check_fb, +}; + +static int aat2870_bl_probe(struct platform_device *pdev) +{ + struct aat2870_bl_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct aat2870_bl_driver_data *aat2870_bl; + struct backlight_device *bd; + struct backlight_properties props; + int ret = 0; + + if (!pdata) { + dev_err(&pdev->dev, "No platform data\n"); + ret = -ENXIO; + goto out; + } + + if (pdev->id != AAT2870_ID_BL) { + dev_err(&pdev->dev, "Invalid device ID, %d\n", pdev->id); + ret = -EINVAL; + goto out; + } + + aat2870_bl = devm_kzalloc(&pdev->dev, + sizeof(struct aat2870_bl_driver_data), + GFP_KERNEL); + if (!aat2870_bl) { + ret = -ENOMEM; + goto out; + } + + memset(&props, 0, sizeof(struct backlight_properties)); + + props.type = BACKLIGHT_RAW; + bd = devm_backlight_device_register(&pdev->dev, "aat2870-backlight", + &pdev->dev, aat2870_bl, &aat2870_bl_ops, + &props); + if (IS_ERR(bd)) { + dev_err(&pdev->dev, + "Failed allocate memory for backlight device\n"); + ret = PTR_ERR(bd); + goto out; + } + + aat2870_bl->pdev = pdev; + platform_set_drvdata(pdev, aat2870_bl); + + aat2870_bl->bd = bd; + + if (pdata->channels > 0) + aat2870_bl->channels = pdata->channels; + else + aat2870_bl->channels = AAT2870_BL_CH_ALL; + + if (pdata->max_current > 0) + aat2870_bl->max_current = pdata->max_current; + else + aat2870_bl->max_current = AAT2870_CURRENT_27_9; + + if (pdata->max_brightness > 0) + bd->props.max_brightness = pdata->max_brightness; + else + bd->props.max_brightness = 255; + + aat2870_bl->brightness = 0; + bd->props.power = FB_BLANK_UNBLANK; + bd->props.brightness = bd->props.max_brightness; + + ret = aat2870_bl_update_status(bd); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to initialize\n"); + return ret; + } + + return 0; + +out: + return ret; +} + +static int aat2870_bl_remove(struct platform_device *pdev) +{ + struct aat2870_bl_driver_data *aat2870_bl = platform_get_drvdata(pdev); + struct backlight_device *bd = aat2870_bl->bd; + + bd->props.power = FB_BLANK_POWERDOWN; + bd->props.brightness = 0; + backlight_update_status(bd); + + return 0; +} + +static struct platform_driver aat2870_bl_driver = { + .driver = { + .name = "aat2870-backlight", + }, + .probe = aat2870_bl_probe, + .remove = aat2870_bl_remove, +}; + +static int __init aat2870_bl_init(void) +{ + return platform_driver_register(&aat2870_bl_driver); +} +subsys_initcall(aat2870_bl_init); + +static void __exit aat2870_bl_exit(void) +{ + platform_driver_unregister(&aat2870_bl_driver); +} +module_exit(aat2870_bl_exit); + +MODULE_DESCRIPTION("AnalogicTech AAT2870 Backlight"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jin Park "); diff --git a/kernel/drivers/video/backlight/adp5520_bl.c b/kernel/drivers/video/backlight/adp5520_bl.c new file mode 100644 index 000000000..dd88ba1d7 --- /dev/null +++ b/kernel/drivers/video/backlight/adp5520_bl.c @@ -0,0 +1,389 @@ +/* + * Backlight driver for Analog Devices ADP5520/ADP5501 MFD PMICs + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct adp5520_bl { + struct device *master; + struct adp5520_backlight_platform_data *pdata; + struct mutex lock; + unsigned long cached_daylight_max; + int id; + int current_brightness; +}; + +static int adp5520_bl_set(struct backlight_device *bl, int brightness) +{ + struct adp5520_bl *data = bl_get_data(bl); + struct device *master = data->master; + int ret = 0; + + if (data->pdata->en_ambl_sens) { + if ((brightness > 0) && (brightness < ADP5020_MAX_BRIGHTNESS)) { + /* Disable Ambient Light auto adjust */ + ret |= adp5520_clr_bits(master, ADP5520_BL_CONTROL, + ADP5520_BL_AUTO_ADJ); + ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX, + brightness); + } else { + /* + * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust + * restore daylight l3 sysfs brightness + */ + ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX, + data->cached_daylight_max); + ret |= adp5520_set_bits(master, ADP5520_BL_CONTROL, + ADP5520_BL_AUTO_ADJ); + } + } else { + ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX, brightness); + } + + if (data->current_brightness && brightness == 0) + ret |= adp5520_set_bits(master, + ADP5520_MODE_STATUS, ADP5520_DIM_EN); + else if (data->current_brightness == 0 && brightness) + ret |= adp5520_clr_bits(master, + ADP5520_MODE_STATUS, ADP5520_DIM_EN); + + if (!ret) + data->current_brightness = brightness; + + return ret; +} + +static int adp5520_bl_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + + if (bl->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + return adp5520_bl_set(bl, brightness); +} + +static int adp5520_bl_get_brightness(struct backlight_device *bl) +{ + struct adp5520_bl *data = bl_get_data(bl); + int error; + uint8_t reg_val; + + error = adp5520_read(data->master, ADP5520_BL_VALUE, ®_val); + + return error ? data->current_brightness : reg_val; +} + +static const struct backlight_ops adp5520_bl_ops = { + .update_status = adp5520_bl_update_status, + .get_brightness = adp5520_bl_get_brightness, +}; + +static int adp5520_bl_setup(struct backlight_device *bl) +{ + struct adp5520_bl *data = bl_get_data(bl); + struct device *master = data->master; + struct adp5520_backlight_platform_data *pdata = data->pdata; + int ret = 0; + + ret |= adp5520_write(master, ADP5520_DAYLIGHT_MAX, + pdata->l1_daylight_max); + ret |= adp5520_write(master, ADP5520_DAYLIGHT_DIM, + pdata->l1_daylight_dim); + + if (pdata->en_ambl_sens) { + data->cached_daylight_max = pdata->l1_daylight_max; + ret |= adp5520_write(master, ADP5520_OFFICE_MAX, + pdata->l2_office_max); + ret |= adp5520_write(master, ADP5520_OFFICE_DIM, + pdata->l2_office_dim); + ret |= adp5520_write(master, ADP5520_DARK_MAX, + pdata->l3_dark_max); + ret |= adp5520_write(master, ADP5520_DARK_DIM, + pdata->l3_dark_dim); + ret |= adp5520_write(master, ADP5520_L2_TRIP, + pdata->l2_trip); + ret |= adp5520_write(master, ADP5520_L2_HYS, + pdata->l2_hyst); + ret |= adp5520_write(master, ADP5520_L3_TRIP, + pdata->l3_trip); + ret |= adp5520_write(master, ADP5520_L3_HYS, + pdata->l3_hyst); + ret |= adp5520_write(master, ADP5520_ALS_CMPR_CFG, + ALS_CMPR_CFG_VAL(pdata->abml_filt, + ADP5520_L3_EN)); + } + + ret |= adp5520_write(master, ADP5520_BL_CONTROL, + BL_CTRL_VAL(pdata->fade_led_law, + pdata->en_ambl_sens)); + + ret |= adp5520_write(master, ADP5520_BL_FADE, FADE_VAL(pdata->fade_in, + pdata->fade_out)); + + ret |= adp5520_set_bits(master, ADP5520_MODE_STATUS, + ADP5520_BL_EN | ADP5520_DIM_EN); + + return ret; +} + +static ssize_t adp5520_show(struct device *dev, char *buf, int reg) +{ + struct adp5520_bl *data = dev_get_drvdata(dev); + int ret; + uint8_t reg_val; + + mutex_lock(&data->lock); + ret = adp5520_read(data->master, reg, ®_val); + mutex_unlock(&data->lock); + + if (ret < 0) + return ret; + + return sprintf(buf, "%u\n", reg_val); +} + +static ssize_t adp5520_store(struct device *dev, const char *buf, + size_t count, int reg) +{ + struct adp5520_bl *data = dev_get_drvdata(dev); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&data->lock); + adp5520_write(data->master, reg, val); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t adp5520_bl_dark_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp5520_show(dev, buf, ADP5520_DARK_MAX); +} + +static ssize_t adp5520_bl_dark_max_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp5520_store(dev, buf, count, ADP5520_DARK_MAX); +} +static DEVICE_ATTR(dark_max, 0664, adp5520_bl_dark_max_show, + adp5520_bl_dark_max_store); + +static ssize_t adp5520_bl_office_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp5520_show(dev, buf, ADP5520_OFFICE_MAX); +} + +static ssize_t adp5520_bl_office_max_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp5520_store(dev, buf, count, ADP5520_OFFICE_MAX); +} +static DEVICE_ATTR(office_max, 0664, adp5520_bl_office_max_show, + adp5520_bl_office_max_store); + +static ssize_t adp5520_bl_daylight_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp5520_show(dev, buf, ADP5520_DAYLIGHT_MAX); +} + +static ssize_t adp5520_bl_daylight_max_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adp5520_bl *data = dev_get_drvdata(dev); + int ret; + + ret = kstrtoul(buf, 10, &data->cached_daylight_max); + if (ret < 0) + return ret; + + return adp5520_store(dev, buf, count, ADP5520_DAYLIGHT_MAX); +} +static DEVICE_ATTR(daylight_max, 0664, adp5520_bl_daylight_max_show, + adp5520_bl_daylight_max_store); + +static ssize_t adp5520_bl_dark_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp5520_show(dev, buf, ADP5520_DARK_DIM); +} + +static ssize_t adp5520_bl_dark_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp5520_store(dev, buf, count, ADP5520_DARK_DIM); +} +static DEVICE_ATTR(dark_dim, 0664, adp5520_bl_dark_dim_show, + adp5520_bl_dark_dim_store); + +static ssize_t adp5520_bl_office_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp5520_show(dev, buf, ADP5520_OFFICE_DIM); +} + +static ssize_t adp5520_bl_office_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp5520_store(dev, buf, count, ADP5520_OFFICE_DIM); +} +static DEVICE_ATTR(office_dim, 0664, adp5520_bl_office_dim_show, + adp5520_bl_office_dim_store); + +static ssize_t adp5520_bl_daylight_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp5520_show(dev, buf, ADP5520_DAYLIGHT_DIM); +} + +static ssize_t adp5520_bl_daylight_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp5520_store(dev, buf, count, ADP5520_DAYLIGHT_DIM); +} +static DEVICE_ATTR(daylight_dim, 0664, adp5520_bl_daylight_dim_show, + adp5520_bl_daylight_dim_store); + +static struct attribute *adp5520_bl_attributes[] = { + &dev_attr_dark_max.attr, + &dev_attr_dark_dim.attr, + &dev_attr_office_max.attr, + &dev_attr_office_dim.attr, + &dev_attr_daylight_max.attr, + &dev_attr_daylight_dim.attr, + NULL +}; + +static const struct attribute_group adp5520_bl_attr_group = { + .attrs = adp5520_bl_attributes, +}; + +static int adp5520_bl_probe(struct platform_device *pdev) +{ + struct backlight_properties props; + struct backlight_device *bl; + struct adp5520_bl *data; + int ret = 0; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + data->master = pdev->dev.parent; + data->pdata = dev_get_platdata(&pdev->dev); + + if (data->pdata == NULL) { + dev_err(&pdev->dev, "missing platform data\n"); + return -ENODEV; + } + + data->id = pdev->id; + data->current_brightness = 0; + + mutex_init(&data->lock); + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; + props.max_brightness = ADP5020_MAX_BRIGHTNESS; + bl = devm_backlight_device_register(&pdev->dev, pdev->name, + data->master, data, &adp5520_bl_ops, + &props); + if (IS_ERR(bl)) { + dev_err(&pdev->dev, "failed to register backlight\n"); + return PTR_ERR(bl); + } + + bl->props.brightness = ADP5020_MAX_BRIGHTNESS; + if (data->pdata->en_ambl_sens) + ret = sysfs_create_group(&bl->dev.kobj, + &adp5520_bl_attr_group); + + if (ret) { + dev_err(&pdev->dev, "failed to register sysfs\n"); + return ret; + } + + platform_set_drvdata(pdev, bl); + ret |= adp5520_bl_setup(bl); + backlight_update_status(bl); + + return ret; +} + +static int adp5520_bl_remove(struct platform_device *pdev) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + struct adp5520_bl *data = bl_get_data(bl); + + adp5520_clr_bits(data->master, ADP5520_MODE_STATUS, ADP5520_BL_EN); + + if (data->pdata->en_ambl_sens) + sysfs_remove_group(&bl->dev.kobj, + &adp5520_bl_attr_group); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int adp5520_bl_suspend(struct device *dev) +{ + struct backlight_device *bl = dev_get_drvdata(dev); + + return adp5520_bl_set(bl, 0); +} + +static int adp5520_bl_resume(struct device *dev) +{ + struct backlight_device *bl = dev_get_drvdata(dev); + + backlight_update_status(bl); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(adp5520_bl_pm_ops, adp5520_bl_suspend, + adp5520_bl_resume); + +static struct platform_driver adp5520_bl_driver = { + .driver = { + .name = "adp5520-backlight", + .pm = &adp5520_bl_pm_ops, + }, + .probe = adp5520_bl_probe, + .remove = adp5520_bl_remove, +}; + +module_platform_driver(adp5520_bl_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("ADP5520(01) Backlight Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:adp5520-backlight"); diff --git a/kernel/drivers/video/backlight/adp8860_bl.c b/kernel/drivers/video/backlight/adp8860_bl.c new file mode 100644 index 000000000..71147f446 --- /dev/null +++ b/kernel/drivers/video/backlight/adp8860_bl.c @@ -0,0 +1,822 @@ +/* + * Backlight driver for Analog Devices ADP8860 Backlight Devices + * + * Copyright 2009-2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#define ADP8860_EXT_FEATURES +#define ADP8860_USE_LEDS + +#define ADP8860_MFDVID 0x00 /* Manufacturer and device ID */ +#define ADP8860_MDCR 0x01 /* Device mode and status */ +#define ADP8860_MDCR2 0x02 /* Device mode and Status Register 2 */ +#define ADP8860_INTR_EN 0x03 /* Interrupts enable */ +#define ADP8860_CFGR 0x04 /* Configuration register */ +#define ADP8860_BLSEN 0x05 /* Sink enable backlight or independent */ +#define ADP8860_BLOFF 0x06 /* Backlight off timeout */ +#define ADP8860_BLDIM 0x07 /* Backlight dim timeout */ +#define ADP8860_BLFR 0x08 /* Backlight fade in and out rates */ +#define ADP8860_BLMX1 0x09 /* Backlight (Brightness Level 1-daylight) maximum current */ +#define ADP8860_BLDM1 0x0A /* Backlight (Brightness Level 1-daylight) dim current */ +#define ADP8860_BLMX2 0x0B /* Backlight (Brightness Level 2-office) maximum current */ +#define ADP8860_BLDM2 0x0C /* Backlight (Brightness Level 2-office) dim current */ +#define ADP8860_BLMX3 0x0D /* Backlight (Brightness Level 3-dark) maximum current */ +#define ADP8860_BLDM3 0x0E /* Backlight (Brightness Level 3-dark) dim current */ +#define ADP8860_ISCFR 0x0F /* Independent sink current fade control register */ +#define ADP8860_ISCC 0x10 /* Independent sink current control register */ +#define ADP8860_ISCT1 0x11 /* Independent Sink Current Timer Register LED[7:5] */ +#define ADP8860_ISCT2 0x12 /* Independent Sink Current Timer Register LED[4:1] */ +#define ADP8860_ISCF 0x13 /* Independent sink current fade register */ +#define ADP8860_ISC7 0x14 /* Independent Sink Current LED7 */ +#define ADP8860_ISC6 0x15 /* Independent Sink Current LED6 */ +#define ADP8860_ISC5 0x16 /* Independent Sink Current LED5 */ +#define ADP8860_ISC4 0x17 /* Independent Sink Current LED4 */ +#define ADP8860_ISC3 0x18 /* Independent Sink Current LED3 */ +#define ADP8860_ISC2 0x19 /* Independent Sink Current LED2 */ +#define ADP8860_ISC1 0x1A /* Independent Sink Current LED1 */ +#define ADP8860_CCFG 0x1B /* Comparator configuration */ +#define ADP8860_CCFG2 0x1C /* Second comparator configuration */ +#define ADP8860_L2_TRP 0x1D /* L2 comparator reference */ +#define ADP8860_L2_HYS 0x1E /* L2 hysteresis */ +#define ADP8860_L3_TRP 0x1F /* L3 comparator reference */ +#define ADP8860_L3_HYS 0x20 /* L3 hysteresis */ +#define ADP8860_PH1LEVL 0x21 /* First phototransistor ambient light level-low byte register */ +#define ADP8860_PH1LEVH 0x22 /* First phototransistor ambient light level-high byte register */ +#define ADP8860_PH2LEVL 0x23 /* Second phototransistor ambient light level-low byte register */ +#define ADP8860_PH2LEVH 0x24 /* Second phototransistor ambient light level-high byte register */ + +#define ADP8860_MANUFID 0x0 /* Analog Devices ADP8860 Manufacturer ID */ +#define ADP8861_MANUFID 0x4 /* Analog Devices ADP8861 Manufacturer ID */ +#define ADP8863_MANUFID 0x2 /* Analog Devices ADP8863 Manufacturer ID */ + +#define ADP8860_DEVID(x) ((x) & 0xF) +#define ADP8860_MANID(x) ((x) >> 4) + +/* MDCR Device mode and status */ +#define INT_CFG (1 << 6) +#define NSTBY (1 << 5) +#define DIM_EN (1 << 4) +#define GDWN_DIS (1 << 3) +#define SIS_EN (1 << 2) +#define CMP_AUTOEN (1 << 1) +#define BLEN (1 << 0) + +/* ADP8860_CCFG Main ALS comparator level enable */ +#define L3_EN (1 << 1) +#define L2_EN (1 << 0) + +#define CFGR_BLV_SHIFT 3 +#define CFGR_BLV_MASK 0x3 +#define ADP8860_FLAG_LED_MASK 0xFF + +#define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4)) +#define BL_CFGR_VAL(law, blv) ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1)) +#define ALS_CCFG_VAL(filt) ((0x7 & filt) << 5) + +enum { + adp8860, + adp8861, + adp8863 +}; + +struct adp8860_led { + struct led_classdev cdev; + struct work_struct work; + struct i2c_client *client; + enum led_brightness new_brightness; + int id; + int flags; +}; + +struct adp8860_bl { + struct i2c_client *client; + struct backlight_device *bl; + struct adp8860_led *led; + struct adp8860_backlight_platform_data *pdata; + struct mutex lock; + unsigned long cached_daylight_max; + int id; + int revid; + int current_brightness; + unsigned en_ambl_sens:1; + unsigned gdwn_dis:1; +}; + +static int adp8860_read(struct i2c_client *client, int reg, uint8_t *val) +{ + int ret; + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret < 0) { + dev_err(&client->dev, "failed reading at 0x%02x\n", reg); + return ret; + } + + *val = (uint8_t)ret; + return 0; +} + +static int adp8860_write(struct i2c_client *client, u8 reg, u8 val) +{ + return i2c_smbus_write_byte_data(client, reg, val); +} + +static int adp8860_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask) +{ + struct adp8860_bl *data = i2c_get_clientdata(client); + uint8_t reg_val; + int ret; + + mutex_lock(&data->lock); + + ret = adp8860_read(client, reg, ®_val); + + if (!ret && ((reg_val & bit_mask) != bit_mask)) { + reg_val |= bit_mask; + ret = adp8860_write(client, reg, reg_val); + } + + mutex_unlock(&data->lock); + return ret; +} + +static int adp8860_clr_bits(struct i2c_client *client, int reg, uint8_t bit_mask) +{ + struct adp8860_bl *data = i2c_get_clientdata(client); + uint8_t reg_val; + int ret; + + mutex_lock(&data->lock); + + ret = adp8860_read(client, reg, ®_val); + + if (!ret && (reg_val & bit_mask)) { + reg_val &= ~bit_mask; + ret = adp8860_write(client, reg, reg_val); + } + + mutex_unlock(&data->lock); + return ret; +} + +/* + * Independent sink / LED + */ +#if defined(ADP8860_USE_LEDS) +static void adp8860_led_work(struct work_struct *work) +{ + struct adp8860_led *led = container_of(work, struct adp8860_led, work); + + adp8860_write(led->client, ADP8860_ISC1 - led->id + 1, + led->new_brightness >> 1); +} + +static void adp8860_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct adp8860_led *led; + + led = container_of(led_cdev, struct adp8860_led, cdev); + led->new_brightness = value; + schedule_work(&led->work); +} + +static int adp8860_led_setup(struct adp8860_led *led) +{ + struct i2c_client *client = led->client; + int ret = 0; + + ret = adp8860_write(client, ADP8860_ISC1 - led->id + 1, 0); + ret |= adp8860_set_bits(client, ADP8860_ISCC, 1 << (led->id - 1)); + + if (led->id > 4) + ret |= adp8860_set_bits(client, ADP8860_ISCT1, + (led->flags & 0x3) << ((led->id - 5) * 2)); + else + ret |= adp8860_set_bits(client, ADP8860_ISCT2, + (led->flags & 0x3) << ((led->id - 1) * 2)); + + return ret; +} + +static int adp8860_led_probe(struct i2c_client *client) +{ + struct adp8860_backlight_platform_data *pdata = + dev_get_platdata(&client->dev); + struct adp8860_bl *data = i2c_get_clientdata(client); + struct adp8860_led *led, *led_dat; + struct led_info *cur_led; + int ret, i; + + led = devm_kzalloc(&client->dev, sizeof(*led) * pdata->num_leds, + GFP_KERNEL); + if (led == NULL) + return -ENOMEM; + + ret = adp8860_write(client, ADP8860_ISCFR, pdata->led_fade_law); + ret = adp8860_write(client, ADP8860_ISCT1, + (pdata->led_on_time & 0x3) << 6); + ret |= adp8860_write(client, ADP8860_ISCF, + FADE_VAL(pdata->led_fade_in, pdata->led_fade_out)); + + if (ret) { + dev_err(&client->dev, "failed to write\n"); + return ret; + } + + for (i = 0; i < pdata->num_leds; ++i) { + cur_led = &pdata->leds[i]; + led_dat = &led[i]; + + led_dat->id = cur_led->flags & ADP8860_FLAG_LED_MASK; + + if (led_dat->id > 7 || led_dat->id < 1) { + dev_err(&client->dev, "Invalid LED ID %d\n", + led_dat->id); + ret = -EINVAL; + goto err; + } + + if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) { + dev_err(&client->dev, "LED %d used by Backlight\n", + led_dat->id); + ret = -EBUSY; + goto err; + } + + led_dat->cdev.name = cur_led->name; + led_dat->cdev.default_trigger = cur_led->default_trigger; + led_dat->cdev.brightness_set = adp8860_led_set; + led_dat->cdev.brightness = LED_OFF; + led_dat->flags = cur_led->flags >> FLAG_OFFT_SHIFT; + led_dat->client = client; + led_dat->new_brightness = LED_OFF; + INIT_WORK(&led_dat->work, adp8860_led_work); + + ret = led_classdev_register(&client->dev, &led_dat->cdev); + if (ret) { + dev_err(&client->dev, "failed to register LED %d\n", + led_dat->id); + goto err; + } + + ret = adp8860_led_setup(led_dat); + if (ret) { + dev_err(&client->dev, "failed to write\n"); + i++; + goto err; + } + } + + data->led = led; + + return 0; + + err: + for (i = i - 1; i >= 0; --i) { + led_classdev_unregister(&led[i].cdev); + cancel_work_sync(&led[i].work); + } + + return ret; +} + +static int adp8860_led_remove(struct i2c_client *client) +{ + struct adp8860_backlight_platform_data *pdata = + dev_get_platdata(&client->dev); + struct adp8860_bl *data = i2c_get_clientdata(client); + int i; + + for (i = 0; i < pdata->num_leds; i++) { + led_classdev_unregister(&data->led[i].cdev); + cancel_work_sync(&data->led[i].work); + } + + return 0; +} +#else +static int adp8860_led_probe(struct i2c_client *client) +{ + return 0; +} + +static int adp8860_led_remove(struct i2c_client *client) +{ + return 0; +} +#endif + +static int adp8860_bl_set(struct backlight_device *bl, int brightness) +{ + struct adp8860_bl *data = bl_get_data(bl); + struct i2c_client *client = data->client; + int ret = 0; + + if (data->en_ambl_sens) { + if ((brightness > 0) && (brightness < ADP8860_MAX_BRIGHTNESS)) { + /* Disable Ambient Light auto adjust */ + ret |= adp8860_clr_bits(client, ADP8860_MDCR, + CMP_AUTOEN); + ret |= adp8860_write(client, ADP8860_BLMX1, brightness); + } else { + /* + * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust + * restore daylight l1 sysfs brightness + */ + ret |= adp8860_write(client, ADP8860_BLMX1, + data->cached_daylight_max); + ret |= adp8860_set_bits(client, ADP8860_MDCR, + CMP_AUTOEN); + } + } else + ret |= adp8860_write(client, ADP8860_BLMX1, brightness); + + if (data->current_brightness && brightness == 0) + ret |= adp8860_set_bits(client, + ADP8860_MDCR, DIM_EN); + else if (data->current_brightness == 0 && brightness) + ret |= adp8860_clr_bits(client, + ADP8860_MDCR, DIM_EN); + + if (!ret) + data->current_brightness = brightness; + + return ret; +} + +static int adp8860_bl_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + + if (bl->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + return adp8860_bl_set(bl, brightness); +} + +static int adp8860_bl_get_brightness(struct backlight_device *bl) +{ + struct adp8860_bl *data = bl_get_data(bl); + + return data->current_brightness; +} + +static const struct backlight_ops adp8860_bl_ops = { + .update_status = adp8860_bl_update_status, + .get_brightness = adp8860_bl_get_brightness, +}; + +static int adp8860_bl_setup(struct backlight_device *bl) +{ + struct adp8860_bl *data = bl_get_data(bl); + struct i2c_client *client = data->client; + struct adp8860_backlight_platform_data *pdata = data->pdata; + int ret = 0; + + ret |= adp8860_write(client, ADP8860_BLSEN, ~pdata->bl_led_assign); + ret |= adp8860_write(client, ADP8860_BLMX1, pdata->l1_daylight_max); + ret |= adp8860_write(client, ADP8860_BLDM1, pdata->l1_daylight_dim); + + if (data->en_ambl_sens) { + data->cached_daylight_max = pdata->l1_daylight_max; + ret |= adp8860_write(client, ADP8860_BLMX2, + pdata->l2_office_max); + ret |= adp8860_write(client, ADP8860_BLDM2, + pdata->l2_office_dim); + ret |= adp8860_write(client, ADP8860_BLMX3, + pdata->l3_dark_max); + ret |= adp8860_write(client, ADP8860_BLDM3, + pdata->l3_dark_dim); + + ret |= adp8860_write(client, ADP8860_L2_TRP, pdata->l2_trip); + ret |= adp8860_write(client, ADP8860_L2_HYS, pdata->l2_hyst); + ret |= adp8860_write(client, ADP8860_L3_TRP, pdata->l3_trip); + ret |= adp8860_write(client, ADP8860_L3_HYS, pdata->l3_hyst); + ret |= adp8860_write(client, ADP8860_CCFG, L2_EN | L3_EN | + ALS_CCFG_VAL(pdata->abml_filt)); + } + + ret |= adp8860_write(client, ADP8860_CFGR, + BL_CFGR_VAL(pdata->bl_fade_law, 0)); + + ret |= adp8860_write(client, ADP8860_BLFR, FADE_VAL(pdata->bl_fade_in, + pdata->bl_fade_out)); + + ret |= adp8860_set_bits(client, ADP8860_MDCR, BLEN | DIM_EN | NSTBY | + (data->gdwn_dis ? GDWN_DIS : 0)); + + return ret; +} + +static ssize_t adp8860_show(struct device *dev, char *buf, int reg) +{ + struct adp8860_bl *data = dev_get_drvdata(dev); + int error; + uint8_t reg_val; + + mutex_lock(&data->lock); + error = adp8860_read(data->client, reg, ®_val); + mutex_unlock(&data->lock); + + if (error < 0) + return error; + + return sprintf(buf, "%u\n", reg_val); +} + +static ssize_t adp8860_store(struct device *dev, const char *buf, + size_t count, int reg) +{ + struct adp8860_bl *data = dev_get_drvdata(dev); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&data->lock); + adp8860_write(data->client, reg, val); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t adp8860_bl_l3_dark_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8860_show(dev, buf, ADP8860_BLMX3); +} + +static ssize_t adp8860_bl_l3_dark_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8860_store(dev, buf, count, ADP8860_BLMX3); +} + +static DEVICE_ATTR(l3_dark_max, 0664, adp8860_bl_l3_dark_max_show, + adp8860_bl_l3_dark_max_store); + +static ssize_t adp8860_bl_l2_office_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8860_show(dev, buf, ADP8860_BLMX2); +} + +static ssize_t adp8860_bl_l2_office_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8860_store(dev, buf, count, ADP8860_BLMX2); +} +static DEVICE_ATTR(l2_office_max, 0664, adp8860_bl_l2_office_max_show, + adp8860_bl_l2_office_max_store); + +static ssize_t adp8860_bl_l1_daylight_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8860_show(dev, buf, ADP8860_BLMX1); +} + +static ssize_t adp8860_bl_l1_daylight_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct adp8860_bl *data = dev_get_drvdata(dev); + int ret = kstrtoul(buf, 10, &data->cached_daylight_max); + + if (ret) + return ret; + + return adp8860_store(dev, buf, count, ADP8860_BLMX1); +} +static DEVICE_ATTR(l1_daylight_max, 0664, adp8860_bl_l1_daylight_max_show, + adp8860_bl_l1_daylight_max_store); + +static ssize_t adp8860_bl_l3_dark_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8860_show(dev, buf, ADP8860_BLDM3); +} + +static ssize_t adp8860_bl_l3_dark_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8860_store(dev, buf, count, ADP8860_BLDM3); +} +static DEVICE_ATTR(l3_dark_dim, 0664, adp8860_bl_l3_dark_dim_show, + adp8860_bl_l3_dark_dim_store); + +static ssize_t adp8860_bl_l2_office_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8860_show(dev, buf, ADP8860_BLDM2); +} + +static ssize_t adp8860_bl_l2_office_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8860_store(dev, buf, count, ADP8860_BLDM2); +} +static DEVICE_ATTR(l2_office_dim, 0664, adp8860_bl_l2_office_dim_show, + adp8860_bl_l2_office_dim_store); + +static ssize_t adp8860_bl_l1_daylight_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8860_show(dev, buf, ADP8860_BLDM1); +} + +static ssize_t adp8860_bl_l1_daylight_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8860_store(dev, buf, count, ADP8860_BLDM1); +} +static DEVICE_ATTR(l1_daylight_dim, 0664, adp8860_bl_l1_daylight_dim_show, + adp8860_bl_l1_daylight_dim_store); + +#ifdef ADP8860_EXT_FEATURES +static ssize_t adp8860_bl_ambient_light_level_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct adp8860_bl *data = dev_get_drvdata(dev); + int error; + uint8_t reg_val; + uint16_t ret_val; + + mutex_lock(&data->lock); + error = adp8860_read(data->client, ADP8860_PH1LEVL, ®_val); + ret_val = reg_val; + error |= adp8860_read(data->client, ADP8860_PH1LEVH, ®_val); + mutex_unlock(&data->lock); + + if (error < 0) + return error; + + /* Return 13-bit conversion value for the first light sensor */ + ret_val += (reg_val & 0x1F) << 8; + + return sprintf(buf, "%u\n", ret_val); +} +static DEVICE_ATTR(ambient_light_level, 0444, + adp8860_bl_ambient_light_level_show, NULL); + +static ssize_t adp8860_bl_ambient_light_zone_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct adp8860_bl *data = dev_get_drvdata(dev); + int error; + uint8_t reg_val; + + mutex_lock(&data->lock); + error = adp8860_read(data->client, ADP8860_CFGR, ®_val); + mutex_unlock(&data->lock); + + if (error < 0) + return error; + + return sprintf(buf, "%u\n", + ((reg_val >> CFGR_BLV_SHIFT) & CFGR_BLV_MASK) + 1); +} + +static ssize_t adp8860_bl_ambient_light_zone_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adp8860_bl *data = dev_get_drvdata(dev); + unsigned long val; + uint8_t reg_val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + if (val == 0) { + /* Enable automatic ambient light sensing */ + adp8860_set_bits(data->client, ADP8860_MDCR, CMP_AUTOEN); + } else if ((val > 0) && (val <= 3)) { + /* Disable automatic ambient light sensing */ + adp8860_clr_bits(data->client, ADP8860_MDCR, CMP_AUTOEN); + + /* Set user supplied ambient light zone */ + mutex_lock(&data->lock); + adp8860_read(data->client, ADP8860_CFGR, ®_val); + reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT); + reg_val |= (val - 1) << CFGR_BLV_SHIFT; + adp8860_write(data->client, ADP8860_CFGR, reg_val); + mutex_unlock(&data->lock); + } + + return count; +} +static DEVICE_ATTR(ambient_light_zone, 0664, + adp8860_bl_ambient_light_zone_show, + adp8860_bl_ambient_light_zone_store); +#endif + +static struct attribute *adp8860_bl_attributes[] = { + &dev_attr_l3_dark_max.attr, + &dev_attr_l3_dark_dim.attr, + &dev_attr_l2_office_max.attr, + &dev_attr_l2_office_dim.attr, + &dev_attr_l1_daylight_max.attr, + &dev_attr_l1_daylight_dim.attr, +#ifdef ADP8860_EXT_FEATURES + &dev_attr_ambient_light_level.attr, + &dev_attr_ambient_light_zone.attr, +#endif + NULL +}; + +static const struct attribute_group adp8860_bl_attr_group = { + .attrs = adp8860_bl_attributes, +}; + +static int adp8860_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct backlight_device *bl; + struct adp8860_bl *data; + struct adp8860_backlight_platform_data *pdata = + dev_get_platdata(&client->dev); + struct backlight_properties props; + uint8_t reg_val; + int ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); + return -EIO; + } + + if (!pdata) { + dev_err(&client->dev, "no platform data?\n"); + return -EINVAL; + } + + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + ret = adp8860_read(client, ADP8860_MFDVID, ®_val); + if (ret < 0) + return ret; + + switch (ADP8860_MANID(reg_val)) { + case ADP8863_MANUFID: + data->gdwn_dis = !!pdata->gdwn_dis; + case ADP8860_MANUFID: + data->en_ambl_sens = !!pdata->en_ambl_sens; + break; + case ADP8861_MANUFID: + data->gdwn_dis = !!pdata->gdwn_dis; + break; + default: + dev_err(&client->dev, "failed to probe\n"); + return -ENODEV; + } + + /* It's confirmed that the DEVID field is actually a REVID */ + + data->revid = ADP8860_DEVID(reg_val); + data->client = client; + data->pdata = pdata; + data->id = id->driver_data; + data->current_brightness = 0; + i2c_set_clientdata(client, data); + + memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; + props.max_brightness = ADP8860_MAX_BRIGHTNESS; + + mutex_init(&data->lock); + + bl = devm_backlight_device_register(&client->dev, + dev_driver_string(&client->dev), + &client->dev, data, &adp8860_bl_ops, &props); + if (IS_ERR(bl)) { + dev_err(&client->dev, "failed to register backlight\n"); + return PTR_ERR(bl); + } + + bl->props.brightness = ADP8860_MAX_BRIGHTNESS; + + data->bl = bl; + + if (data->en_ambl_sens) + ret = sysfs_create_group(&bl->dev.kobj, + &adp8860_bl_attr_group); + + if (ret) { + dev_err(&client->dev, "failed to register sysfs\n"); + return ret; + } + + ret = adp8860_bl_setup(bl); + if (ret) { + ret = -EIO; + goto out; + } + + backlight_update_status(bl); + + dev_info(&client->dev, "%s Rev.%d Backlight\n", + client->name, data->revid); + + if (pdata->num_leds) + adp8860_led_probe(client); + + return 0; + +out: + if (data->en_ambl_sens) + sysfs_remove_group(&data->bl->dev.kobj, + &adp8860_bl_attr_group); + + return ret; +} + +static int adp8860_remove(struct i2c_client *client) +{ + struct adp8860_bl *data = i2c_get_clientdata(client); + + adp8860_clr_bits(client, ADP8860_MDCR, NSTBY); + + if (data->led) + adp8860_led_remove(client); + + if (data->en_ambl_sens) + sysfs_remove_group(&data->bl->dev.kobj, + &adp8860_bl_attr_group); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int adp8860_i2c_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + adp8860_clr_bits(client, ADP8860_MDCR, NSTBY); + + return 0; +} + +static int adp8860_i2c_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + adp8860_set_bits(client, ADP8860_MDCR, NSTBY | BLEN); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(adp8860_i2c_pm_ops, adp8860_i2c_suspend, + adp8860_i2c_resume); + +static const struct i2c_device_id adp8860_id[] = { + { "adp8860", adp8860 }, + { "adp8861", adp8861 }, + { "adp8863", adp8863 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adp8860_id); + +static struct i2c_driver adp8860_driver = { + .driver = { + .name = KBUILD_MODNAME, + .pm = &adp8860_i2c_pm_ops, + }, + .probe = adp8860_probe, + .remove = adp8860_remove, + .id_table = adp8860_id, +}; + +module_i2c_driver(adp8860_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("ADP8860 Backlight driver"); +MODULE_ALIAS("i2c:adp8860-backlight"); diff --git a/kernel/drivers/video/backlight/adp8870_bl.c b/kernel/drivers/video/backlight/adp8870_bl.c new file mode 100644 index 000000000..037e43083 --- /dev/null +++ b/kernel/drivers/video/backlight/adp8870_bl.c @@ -0,0 +1,995 @@ +/* + * Backlight driver for Analog Devices ADP8870 Backlight Devices + * + * Copyright 2009-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#define ADP8870_EXT_FEATURES +#define ADP8870_USE_LEDS + + +#define ADP8870_MFDVID 0x00 /* Manufacturer and device ID */ +#define ADP8870_MDCR 0x01 /* Device mode and status */ +#define ADP8870_INT_STAT 0x02 /* Interrupts status */ +#define ADP8870_INT_EN 0x03 /* Interrupts enable */ +#define ADP8870_CFGR 0x04 /* Configuration register */ +#define ADP8870_BLSEL 0x05 /* Sink enable backlight or independent */ +#define ADP8870_PWMLED 0x06 /* PWM Enable Selection Register */ +#define ADP8870_BLOFF 0x07 /* Backlight off timeout */ +#define ADP8870_BLDIM 0x08 /* Backlight dim timeout */ +#define ADP8870_BLFR 0x09 /* Backlight fade in and out rates */ +#define ADP8870_BLMX1 0x0A /* Backlight (Brightness Level 1-daylight) maximum current */ +#define ADP8870_BLDM1 0x0B /* Backlight (Brightness Level 1-daylight) dim current */ +#define ADP8870_BLMX2 0x0C /* Backlight (Brightness Level 2-bright) maximum current */ +#define ADP8870_BLDM2 0x0D /* Backlight (Brightness Level 2-bright) dim current */ +#define ADP8870_BLMX3 0x0E /* Backlight (Brightness Level 3-office) maximum current */ +#define ADP8870_BLDM3 0x0F /* Backlight (Brightness Level 3-office) dim current */ +#define ADP8870_BLMX4 0x10 /* Backlight (Brightness Level 4-indoor) maximum current */ +#define ADP8870_BLDM4 0x11 /* Backlight (Brightness Level 4-indoor) dim current */ +#define ADP8870_BLMX5 0x12 /* Backlight (Brightness Level 5-dark) maximum current */ +#define ADP8870_BLDM5 0x13 /* Backlight (Brightness Level 5-dark) dim current */ +#define ADP8870_ISCLAW 0x1A /* Independent sink current fade law register */ +#define ADP8870_ISCC 0x1B /* Independent sink current control register */ +#define ADP8870_ISCT1 0x1C /* Independent Sink Current Timer Register LED[7:5] */ +#define ADP8870_ISCT2 0x1D /* Independent Sink Current Timer Register LED[4:1] */ +#define ADP8870_ISCF 0x1E /* Independent sink current fade register */ +#define ADP8870_ISC1 0x1F /* Independent Sink Current LED1 */ +#define ADP8870_ISC2 0x20 /* Independent Sink Current LED2 */ +#define ADP8870_ISC3 0x21 /* Independent Sink Current LED3 */ +#define ADP8870_ISC4 0x22 /* Independent Sink Current LED4 */ +#define ADP8870_ISC5 0x23 /* Independent Sink Current LED5 */ +#define ADP8870_ISC6 0x24 /* Independent Sink Current LED6 */ +#define ADP8870_ISC7 0x25 /* Independent Sink Current LED7 (Brightness Level 1-daylight) */ +#define ADP8870_ISC7_L2 0x26 /* Independent Sink Current LED7 (Brightness Level 2-bright) */ +#define ADP8870_ISC7_L3 0x27 /* Independent Sink Current LED7 (Brightness Level 3-office) */ +#define ADP8870_ISC7_L4 0x28 /* Independent Sink Current LED7 (Brightness Level 4-indoor) */ +#define ADP8870_ISC7_L5 0x29 /* Independent Sink Current LED7 (Brightness Level 5-dark) */ +#define ADP8870_CMP_CTL 0x2D /* ALS Comparator Control Register */ +#define ADP8870_ALS1_EN 0x2E /* Main ALS comparator level enable */ +#define ADP8870_ALS2_EN 0x2F /* Second ALS comparator level enable */ +#define ADP8870_ALS1_STAT 0x30 /* Main ALS Comparator Status Register */ +#define ADP8870_ALS2_STAT 0x31 /* Second ALS Comparator Status Register */ +#define ADP8870_L2TRP 0x32 /* L2 comparator reference */ +#define ADP8870_L2HYS 0x33 /* L2 hysteresis */ +#define ADP8870_L3TRP 0x34 /* L3 comparator reference */ +#define ADP8870_L3HYS 0x35 /* L3 hysteresis */ +#define ADP8870_L4TRP 0x36 /* L4 comparator reference */ +#define ADP8870_L4HYS 0x37 /* L4 hysteresis */ +#define ADP8870_L5TRP 0x38 /* L5 comparator reference */ +#define ADP8870_L5HYS 0x39 /* L5 hysteresis */ +#define ADP8870_PH1LEVL 0x40 /* First phototransistor ambient light level-low byte register */ +#define ADP8870_PH1LEVH 0x41 /* First phototransistor ambient light level-high byte register */ +#define ADP8870_PH2LEVL 0x42 /* Second phototransistor ambient light level-low byte register */ +#define ADP8870_PH2LEVH 0x43 /* Second phototransistor ambient light level-high byte register */ + +#define ADP8870_MANUFID 0x3 /* Analog Devices AD8870 Manufacturer and device ID */ +#define ADP8870_DEVID(x) ((x) & 0xF) +#define ADP8870_MANID(x) ((x) >> 4) + +/* MDCR Device mode and status */ +#define D7ALSEN (1 << 7) +#define INT_CFG (1 << 6) +#define NSTBY (1 << 5) +#define DIM_EN (1 << 4) +#define GDWN_DIS (1 << 3) +#define SIS_EN (1 << 2) +#define CMP_AUTOEN (1 << 1) +#define BLEN (1 << 0) + +/* ADP8870_ALS1_EN Main ALS comparator level enable */ +#define L5_EN (1 << 3) +#define L4_EN (1 << 2) +#define L3_EN (1 << 1) +#define L2_EN (1 << 0) + +#define CFGR_BLV_SHIFT 3 +#define CFGR_BLV_MASK 0x7 +#define ADP8870_FLAG_LED_MASK 0xFF + +#define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4)) +#define BL_CFGR_VAL(law, blv) ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1)) +#define ALS_CMPR_CFG_VAL(filt) ((0x7 & (filt)) << 1) + +struct adp8870_bl { + struct i2c_client *client; + struct backlight_device *bl; + struct adp8870_led *led; + struct adp8870_backlight_platform_data *pdata; + struct mutex lock; + unsigned long cached_daylight_max; + int id; + int revid; + int current_brightness; +}; + +struct adp8870_led { + struct led_classdev cdev; + struct work_struct work; + struct i2c_client *client; + enum led_brightness new_brightness; + int id; + int flags; +}; + +static int adp8870_read(struct i2c_client *client, int reg, uint8_t *val) +{ + int ret; + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret < 0) { + dev_err(&client->dev, "failed reading at 0x%02x\n", reg); + return ret; + } + + *val = ret; + return 0; +} + + +static int adp8870_write(struct i2c_client *client, u8 reg, u8 val) +{ + int ret = i2c_smbus_write_byte_data(client, reg, val); + + if (ret) + dev_err(&client->dev, "failed to write\n"); + + return ret; +} + +static int adp8870_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask) +{ + struct adp8870_bl *data = i2c_get_clientdata(client); + uint8_t reg_val; + int ret; + + mutex_lock(&data->lock); + + ret = adp8870_read(client, reg, ®_val); + + if (!ret && ((reg_val & bit_mask) != bit_mask)) { + reg_val |= bit_mask; + ret = adp8870_write(client, reg, reg_val); + } + + mutex_unlock(&data->lock); + return ret; +} + +static int adp8870_clr_bits(struct i2c_client *client, int reg, uint8_t bit_mask) +{ + struct adp8870_bl *data = i2c_get_clientdata(client); + uint8_t reg_val; + int ret; + + mutex_lock(&data->lock); + + ret = adp8870_read(client, reg, ®_val); + + if (!ret && (reg_val & bit_mask)) { + reg_val &= ~bit_mask; + ret = adp8870_write(client, reg, reg_val); + } + + mutex_unlock(&data->lock); + return ret; +} + +/* + * Independent sink / LED + */ +#if defined(ADP8870_USE_LEDS) +static void adp8870_led_work(struct work_struct *work) +{ + struct adp8870_led *led = container_of(work, struct adp8870_led, work); + + adp8870_write(led->client, ADP8870_ISC1 + led->id - 1, + led->new_brightness >> 1); +} + +static void adp8870_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct adp8870_led *led; + + led = container_of(led_cdev, struct adp8870_led, cdev); + led->new_brightness = value; + /* + * Use workqueue for IO since I2C operations can sleep. + */ + schedule_work(&led->work); +} + +static int adp8870_led_setup(struct adp8870_led *led) +{ + struct i2c_client *client = led->client; + int ret = 0; + + ret = adp8870_write(client, ADP8870_ISC1 + led->id - 1, 0); + if (ret) + return ret; + + ret = adp8870_set_bits(client, ADP8870_ISCC, 1 << (led->id - 1)); + if (ret) + return ret; + + if (led->id > 4) + ret = adp8870_set_bits(client, ADP8870_ISCT1, + (led->flags & 0x3) << ((led->id - 5) * 2)); + else + ret = adp8870_set_bits(client, ADP8870_ISCT2, + (led->flags & 0x3) << ((led->id - 1) * 2)); + + return ret; +} + +static int adp8870_led_probe(struct i2c_client *client) +{ + struct adp8870_backlight_platform_data *pdata = + dev_get_platdata(&client->dev); + struct adp8870_bl *data = i2c_get_clientdata(client); + struct adp8870_led *led, *led_dat; + struct led_info *cur_led; + int ret, i; + + led = devm_kzalloc(&client->dev, pdata->num_leds * sizeof(*led), + GFP_KERNEL); + if (led == NULL) + return -ENOMEM; + + ret = adp8870_write(client, ADP8870_ISCLAW, pdata->led_fade_law); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_ISCT1, + (pdata->led_on_time & 0x3) << 6); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_ISCF, + FADE_VAL(pdata->led_fade_in, pdata->led_fade_out)); + if (ret) + return ret; + + for (i = 0; i < pdata->num_leds; ++i) { + cur_led = &pdata->leds[i]; + led_dat = &led[i]; + + led_dat->id = cur_led->flags & ADP8870_FLAG_LED_MASK; + + if (led_dat->id > 7 || led_dat->id < 1) { + dev_err(&client->dev, "Invalid LED ID %d\n", + led_dat->id); + ret = -EINVAL; + goto err; + } + + if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) { + dev_err(&client->dev, "LED %d used by Backlight\n", + led_dat->id); + ret = -EBUSY; + goto err; + } + + led_dat->cdev.name = cur_led->name; + led_dat->cdev.default_trigger = cur_led->default_trigger; + led_dat->cdev.brightness_set = adp8870_led_set; + led_dat->cdev.brightness = LED_OFF; + led_dat->flags = cur_led->flags >> FLAG_OFFT_SHIFT; + led_dat->client = client; + led_dat->new_brightness = LED_OFF; + INIT_WORK(&led_dat->work, adp8870_led_work); + + ret = led_classdev_register(&client->dev, &led_dat->cdev); + if (ret) { + dev_err(&client->dev, "failed to register LED %d\n", + led_dat->id); + goto err; + } + + ret = adp8870_led_setup(led_dat); + if (ret) { + dev_err(&client->dev, "failed to write\n"); + i++; + goto err; + } + } + + data->led = led; + + return 0; + + err: + for (i = i - 1; i >= 0; --i) { + led_classdev_unregister(&led[i].cdev); + cancel_work_sync(&led[i].work); + } + + return ret; +} + +static int adp8870_led_remove(struct i2c_client *client) +{ + struct adp8870_backlight_platform_data *pdata = + dev_get_platdata(&client->dev); + struct adp8870_bl *data = i2c_get_clientdata(client); + int i; + + for (i = 0; i < pdata->num_leds; i++) { + led_classdev_unregister(&data->led[i].cdev); + cancel_work_sync(&data->led[i].work); + } + + return 0; +} +#else +static int adp8870_led_probe(struct i2c_client *client) +{ + return 0; +} + +static int adp8870_led_remove(struct i2c_client *client) +{ + return 0; +} +#endif + +static int adp8870_bl_set(struct backlight_device *bl, int brightness) +{ + struct adp8870_bl *data = bl_get_data(bl); + struct i2c_client *client = data->client; + int ret = 0; + + if (data->pdata->en_ambl_sens) { + if ((brightness > 0) && (brightness < ADP8870_MAX_BRIGHTNESS)) { + /* Disable Ambient Light auto adjust */ + ret = adp8870_clr_bits(client, ADP8870_MDCR, + CMP_AUTOEN); + if (ret) + return ret; + ret = adp8870_write(client, ADP8870_BLMX1, brightness); + if (ret) + return ret; + } else { + /* + * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust + * restore daylight l1 sysfs brightness + */ + ret = adp8870_write(client, ADP8870_BLMX1, + data->cached_daylight_max); + if (ret) + return ret; + + ret = adp8870_set_bits(client, ADP8870_MDCR, + CMP_AUTOEN); + if (ret) + return ret; + } + } else { + ret = adp8870_write(client, ADP8870_BLMX1, brightness); + if (ret) + return ret; + } + + if (data->current_brightness && brightness == 0) + ret = adp8870_set_bits(client, + ADP8870_MDCR, DIM_EN); + else if (data->current_brightness == 0 && brightness) + ret = adp8870_clr_bits(client, + ADP8870_MDCR, DIM_EN); + + if (!ret) + data->current_brightness = brightness; + + return ret; +} + +static int adp8870_bl_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + + if (bl->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + return adp8870_bl_set(bl, brightness); +} + +static int adp8870_bl_get_brightness(struct backlight_device *bl) +{ + struct adp8870_bl *data = bl_get_data(bl); + + return data->current_brightness; +} + +static const struct backlight_ops adp8870_bl_ops = { + .update_status = adp8870_bl_update_status, + .get_brightness = adp8870_bl_get_brightness, +}; + +static int adp8870_bl_setup(struct backlight_device *bl) +{ + struct adp8870_bl *data = bl_get_data(bl); + struct i2c_client *client = data->client; + struct adp8870_backlight_platform_data *pdata = data->pdata; + int ret = 0; + + ret = adp8870_write(client, ADP8870_BLSEL, ~pdata->bl_led_assign); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_PWMLED, pdata->pwm_assign); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLMX1, pdata->l1_daylight_max); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLDM1, pdata->l1_daylight_dim); + if (ret) + return ret; + + if (pdata->en_ambl_sens) { + data->cached_daylight_max = pdata->l1_daylight_max; + ret = adp8870_write(client, ADP8870_BLMX2, + pdata->l2_bright_max); + if (ret) + return ret; + ret = adp8870_write(client, ADP8870_BLDM2, + pdata->l2_bright_dim); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLMX3, + pdata->l3_office_max); + if (ret) + return ret; + ret = adp8870_write(client, ADP8870_BLDM3, + pdata->l3_office_dim); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLMX4, + pdata->l4_indoor_max); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLDM4, + pdata->l4_indor_dim); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLMX5, + pdata->l5_dark_max); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLDM5, + pdata->l5_dark_dim); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L2TRP, pdata->l2_trip); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L2HYS, pdata->l2_hyst); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L3TRP, pdata->l3_trip); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L3HYS, pdata->l3_hyst); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L4TRP, pdata->l4_trip); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L4HYS, pdata->l4_hyst); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L5TRP, pdata->l5_trip); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_L5HYS, pdata->l5_hyst); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_ALS1_EN, L5_EN | L4_EN | + L3_EN | L2_EN); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_CMP_CTL, + ALS_CMPR_CFG_VAL(pdata->abml_filt)); + if (ret) + return ret; + } + + ret = adp8870_write(client, ADP8870_CFGR, + BL_CFGR_VAL(pdata->bl_fade_law, 0)); + if (ret) + return ret; + + ret = adp8870_write(client, ADP8870_BLFR, FADE_VAL(pdata->bl_fade_in, + pdata->bl_fade_out)); + if (ret) + return ret; + /* + * ADP8870 Rev0 requires GDWN_DIS bit set + */ + + ret = adp8870_set_bits(client, ADP8870_MDCR, BLEN | DIM_EN | NSTBY | + (data->revid == 0 ? GDWN_DIS : 0)); + + return ret; +} + +static ssize_t adp8870_show(struct device *dev, char *buf, int reg) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + int error; + uint8_t reg_val; + + mutex_lock(&data->lock); + error = adp8870_read(data->client, reg, ®_val); + mutex_unlock(&data->lock); + + if (error < 0) + return error; + + return sprintf(buf, "%u\n", reg_val); +} + +static ssize_t adp8870_store(struct device *dev, const char *buf, + size_t count, int reg) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&data->lock); + adp8870_write(data->client, reg, val); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t adp8870_bl_l5_dark_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX5); +} + +static ssize_t adp8870_bl_l5_dark_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLMX5); +} +static DEVICE_ATTR(l5_dark_max, 0664, adp8870_bl_l5_dark_max_show, + adp8870_bl_l5_dark_max_store); + + +static ssize_t adp8870_bl_l4_indoor_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX4); +} + +static ssize_t adp8870_bl_l4_indoor_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLMX4); +} +static DEVICE_ATTR(l4_indoor_max, 0664, adp8870_bl_l4_indoor_max_show, + adp8870_bl_l4_indoor_max_store); + + +static ssize_t adp8870_bl_l3_office_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX3); +} + +static ssize_t adp8870_bl_l3_office_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLMX3); +} + +static DEVICE_ATTR(l3_office_max, 0664, adp8870_bl_l3_office_max_show, + adp8870_bl_l3_office_max_store); + +static ssize_t adp8870_bl_l2_bright_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX2); +} + +static ssize_t adp8870_bl_l2_bright_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLMX2); +} +static DEVICE_ATTR(l2_bright_max, 0664, adp8870_bl_l2_bright_max_show, + adp8870_bl_l2_bright_max_store); + +static ssize_t adp8870_bl_l1_daylight_max_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLMX1); +} + +static ssize_t adp8870_bl_l1_daylight_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + int ret = kstrtoul(buf, 10, &data->cached_daylight_max); + + if (ret) + return ret; + + return adp8870_store(dev, buf, count, ADP8870_BLMX1); +} +static DEVICE_ATTR(l1_daylight_max, 0664, adp8870_bl_l1_daylight_max_show, + adp8870_bl_l1_daylight_max_store); + +static ssize_t adp8870_bl_l5_dark_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM5); +} + +static ssize_t adp8870_bl_l5_dark_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM5); +} +static DEVICE_ATTR(l5_dark_dim, 0664, adp8870_bl_l5_dark_dim_show, + adp8870_bl_l5_dark_dim_store); + +static ssize_t adp8870_bl_l4_indoor_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM4); +} + +static ssize_t adp8870_bl_l4_indoor_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM4); +} +static DEVICE_ATTR(l4_indoor_dim, 0664, adp8870_bl_l4_indoor_dim_show, + adp8870_bl_l4_indoor_dim_store); + + +static ssize_t adp8870_bl_l3_office_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM3); +} + +static ssize_t adp8870_bl_l3_office_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM3); +} +static DEVICE_ATTR(l3_office_dim, 0664, adp8870_bl_l3_office_dim_show, + adp8870_bl_l3_office_dim_store); + +static ssize_t adp8870_bl_l2_bright_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM2); +} + +static ssize_t adp8870_bl_l2_bright_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM2); +} +static DEVICE_ATTR(l2_bright_dim, 0664, adp8870_bl_l2_bright_dim_show, + adp8870_bl_l2_bright_dim_store); + +static ssize_t adp8870_bl_l1_daylight_dim_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return adp8870_show(dev, buf, ADP8870_BLDM1); +} + +static ssize_t adp8870_bl_l1_daylight_dim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return adp8870_store(dev, buf, count, ADP8870_BLDM1); +} +static DEVICE_ATTR(l1_daylight_dim, 0664, adp8870_bl_l1_daylight_dim_show, + adp8870_bl_l1_daylight_dim_store); + +#ifdef ADP8870_EXT_FEATURES +static ssize_t adp8870_bl_ambient_light_level_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + int error; + uint8_t reg_val; + uint16_t ret_val; + + mutex_lock(&data->lock); + error = adp8870_read(data->client, ADP8870_PH1LEVL, ®_val); + if (error < 0) { + mutex_unlock(&data->lock); + return error; + } + ret_val = reg_val; + error = adp8870_read(data->client, ADP8870_PH1LEVH, ®_val); + mutex_unlock(&data->lock); + + if (error < 0) + return error; + + /* Return 13-bit conversion value for the first light sensor */ + ret_val += (reg_val & 0x1F) << 8; + + return sprintf(buf, "%u\n", ret_val); +} +static DEVICE_ATTR(ambient_light_level, 0444, + adp8870_bl_ambient_light_level_show, NULL); + +static ssize_t adp8870_bl_ambient_light_zone_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + int error; + uint8_t reg_val; + + mutex_lock(&data->lock); + error = adp8870_read(data->client, ADP8870_CFGR, ®_val); + mutex_unlock(&data->lock); + + if (error < 0) + return error; + + return sprintf(buf, "%u\n", + ((reg_val >> CFGR_BLV_SHIFT) & CFGR_BLV_MASK) + 1); +} + +static ssize_t adp8870_bl_ambient_light_zone_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adp8870_bl *data = dev_get_drvdata(dev); + unsigned long val; + uint8_t reg_val; + int ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + if (val == 0) { + /* Enable automatic ambient light sensing */ + adp8870_set_bits(data->client, ADP8870_MDCR, CMP_AUTOEN); + } else if ((val > 0) && (val < 6)) { + /* Disable automatic ambient light sensing */ + adp8870_clr_bits(data->client, ADP8870_MDCR, CMP_AUTOEN); + + /* Set user supplied ambient light zone */ + mutex_lock(&data->lock); + adp8870_read(data->client, ADP8870_CFGR, ®_val); + reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT); + reg_val |= (val - 1) << CFGR_BLV_SHIFT; + adp8870_write(data->client, ADP8870_CFGR, reg_val); + mutex_unlock(&data->lock); + } + + return count; +} +static DEVICE_ATTR(ambient_light_zone, 0664, + adp8870_bl_ambient_light_zone_show, + adp8870_bl_ambient_light_zone_store); +#endif + +static struct attribute *adp8870_bl_attributes[] = { + &dev_attr_l5_dark_max.attr, + &dev_attr_l5_dark_dim.attr, + &dev_attr_l4_indoor_max.attr, + &dev_attr_l4_indoor_dim.attr, + &dev_attr_l3_office_max.attr, + &dev_attr_l3_office_dim.attr, + &dev_attr_l2_bright_max.attr, + &dev_attr_l2_bright_dim.attr, + &dev_attr_l1_daylight_max.attr, + &dev_attr_l1_daylight_dim.attr, +#ifdef ADP8870_EXT_FEATURES + &dev_attr_ambient_light_level.attr, + &dev_attr_ambient_light_zone.attr, +#endif + NULL +}; + +static const struct attribute_group adp8870_bl_attr_group = { + .attrs = adp8870_bl_attributes, +}; + +static int adp8870_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct backlight_properties props; + struct backlight_device *bl; + struct adp8870_bl *data; + struct adp8870_backlight_platform_data *pdata = + dev_get_platdata(&client->dev); + uint8_t reg_val; + int ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); + return -EIO; + } + + if (!pdata) { + dev_err(&client->dev, "no platform data?\n"); + return -EINVAL; + } + + ret = adp8870_read(client, ADP8870_MFDVID, ®_val); + if (ret < 0) + return -EIO; + + if (ADP8870_MANID(reg_val) != ADP8870_MANUFID) { + dev_err(&client->dev, "failed to probe\n"); + return -ENODEV; + } + + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + data->revid = ADP8870_DEVID(reg_val); + data->client = client; + data->pdata = pdata; + data->id = id->driver_data; + data->current_brightness = 0; + i2c_set_clientdata(client, data); + + mutex_init(&data->lock); + + memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; + props.max_brightness = props.brightness = ADP8870_MAX_BRIGHTNESS; + bl = devm_backlight_device_register(&client->dev, + dev_driver_string(&client->dev), + &client->dev, data, &adp8870_bl_ops, &props); + if (IS_ERR(bl)) { + dev_err(&client->dev, "failed to register backlight\n"); + return PTR_ERR(bl); + } + + data->bl = bl; + + if (pdata->en_ambl_sens) { + ret = sysfs_create_group(&bl->dev.kobj, + &adp8870_bl_attr_group); + if (ret) { + dev_err(&client->dev, "failed to register sysfs\n"); + return ret; + } + } + + ret = adp8870_bl_setup(bl); + if (ret) { + ret = -EIO; + goto out; + } + + backlight_update_status(bl); + + dev_info(&client->dev, "Rev.%d Backlight\n", data->revid); + + if (pdata->num_leds) + adp8870_led_probe(client); + + return 0; + +out: + if (data->pdata->en_ambl_sens) + sysfs_remove_group(&data->bl->dev.kobj, + &adp8870_bl_attr_group); + + return ret; +} + +static int adp8870_remove(struct i2c_client *client) +{ + struct adp8870_bl *data = i2c_get_clientdata(client); + + adp8870_clr_bits(client, ADP8870_MDCR, NSTBY); + + if (data->led) + adp8870_led_remove(client); + + if (data->pdata->en_ambl_sens) + sysfs_remove_group(&data->bl->dev.kobj, + &adp8870_bl_attr_group); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int adp8870_i2c_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + adp8870_clr_bits(client, ADP8870_MDCR, NSTBY); + + return 0; +} + +static int adp8870_i2c_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + adp8870_set_bits(client, ADP8870_MDCR, NSTBY | BLEN); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(adp8870_i2c_pm_ops, adp8870_i2c_suspend, + adp8870_i2c_resume); + +static const struct i2c_device_id adp8870_id[] = { + { "adp8870", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adp8870_id); + +static struct i2c_driver adp8870_driver = { + .driver = { + .name = KBUILD_MODNAME, + .pm = &adp8870_i2c_pm_ops, + }, + .probe = adp8870_probe, + .remove = adp8870_remove, + .id_table = adp8870_id, +}; + +module_i2c_driver(adp8870_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("ADP8870 Backlight driver"); +MODULE_ALIAS("i2c:adp8870-backlight"); diff --git a/kernel/drivers/video/backlight/ams369fg06.c b/kernel/drivers/video/backlight/ams369fg06.c new file mode 100644 index 000000000..5f897f99c --- /dev/null +++ b/kernel/drivers/video/backlight/ams369fg06.c @@ -0,0 +1,571 @@ +/* + * ams369fg06 AMOLED LCD panel driver. + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * Author: Jingoo Han + * + * Derived from drivers/video/s6e63m0.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SLEEPMSEC 0x1000 +#define ENDDEF 0x2000 +#define DEFMASK 0xFF00 +#define COMMAND_ONLY 0xFE +#define DATA_ONLY 0xFF + +#define MAX_GAMMA_LEVEL 5 +#define GAMMA_TABLE_COUNT 21 + +#define MIN_BRIGHTNESS 0 +#define MAX_BRIGHTNESS 255 +#define DEFAULT_BRIGHTNESS 150 + +struct ams369fg06 { + struct device *dev; + struct spi_device *spi; + unsigned int power; + struct lcd_device *ld; + struct backlight_device *bd; + struct lcd_platform_data *lcd_pd; +}; + +static const unsigned short seq_display_on[] = { + 0x14, 0x03, + ENDDEF, 0x0000 +}; + +static const unsigned short seq_display_off[] = { + 0x14, 0x00, + ENDDEF, 0x0000 +}; + +static const unsigned short seq_stand_by_on[] = { + 0x1D, 0xA1, + SLEEPMSEC, 200, + ENDDEF, 0x0000 +}; + +static const unsigned short seq_stand_by_off[] = { + 0x1D, 0xA0, + SLEEPMSEC, 250, + ENDDEF, 0x0000 +}; + +static const unsigned short seq_setting[] = { + 0x31, 0x08, + 0x32, 0x14, + 0x30, 0x02, + 0x27, 0x01, + 0x12, 0x08, + 0x13, 0x08, + 0x15, 0x00, + 0x16, 0x00, + + 0xef, 0xd0, + DATA_ONLY, 0xe8, + + 0x39, 0x44, + 0x40, 0x00, + 0x41, 0x3f, + 0x42, 0x2a, + 0x43, 0x27, + 0x44, 0x27, + 0x45, 0x1f, + 0x46, 0x44, + 0x50, 0x00, + 0x51, 0x00, + 0x52, 0x17, + 0x53, 0x24, + 0x54, 0x26, + 0x55, 0x1f, + 0x56, 0x43, + 0x60, 0x00, + 0x61, 0x3f, + 0x62, 0x2a, + 0x63, 0x25, + 0x64, 0x24, + 0x65, 0x1b, + 0x66, 0x5c, + + 0x17, 0x22, + 0x18, 0x33, + 0x19, 0x03, + 0x1a, 0x01, + 0x22, 0xa4, + 0x23, 0x00, + 0x26, 0xa0, + + 0x1d, 0xa0, + SLEEPMSEC, 300, + + 0x14, 0x03, + + ENDDEF, 0x0000 +}; + +/* gamma value: 2.2 */ +static const unsigned int ams369fg06_22_250[] = { + 0x00, 0x3f, 0x2a, 0x27, 0x27, 0x1f, 0x44, + 0x00, 0x00, 0x17, 0x24, 0x26, 0x1f, 0x43, + 0x00, 0x3f, 0x2a, 0x25, 0x24, 0x1b, 0x5c, +}; + +static const unsigned int ams369fg06_22_200[] = { + 0x00, 0x3f, 0x28, 0x29, 0x27, 0x21, 0x3e, + 0x00, 0x00, 0x10, 0x25, 0x27, 0x20, 0x3d, + 0x00, 0x3f, 0x28, 0x27, 0x25, 0x1d, 0x53, +}; + +static const unsigned int ams369fg06_22_150[] = { + 0x00, 0x3f, 0x2d, 0x29, 0x28, 0x23, 0x37, + 0x00, 0x00, 0x0b, 0x25, 0x28, 0x22, 0x36, + 0x00, 0x3f, 0x2b, 0x28, 0x26, 0x1f, 0x4a, +}; + +static const unsigned int ams369fg06_22_100[] = { + 0x00, 0x3f, 0x30, 0x2a, 0x2b, 0x24, 0x2f, + 0x00, 0x00, 0x00, 0x25, 0x29, 0x24, 0x2e, + 0x00, 0x3f, 0x2f, 0x29, 0x29, 0x21, 0x3f, +}; + +static const unsigned int ams369fg06_22_50[] = { + 0x00, 0x3f, 0x3c, 0x2c, 0x2d, 0x27, 0x24, + 0x00, 0x00, 0x00, 0x22, 0x2a, 0x27, 0x23, + 0x00, 0x3f, 0x3b, 0x2c, 0x2b, 0x24, 0x31, +}; + +struct ams369fg06_gamma { + unsigned int *gamma_22_table[MAX_GAMMA_LEVEL]; +}; + +static struct ams369fg06_gamma gamma_table = { + .gamma_22_table[0] = (unsigned int *)&ams369fg06_22_50, + .gamma_22_table[1] = (unsigned int *)&ams369fg06_22_100, + .gamma_22_table[2] = (unsigned int *)&ams369fg06_22_150, + .gamma_22_table[3] = (unsigned int *)&ams369fg06_22_200, + .gamma_22_table[4] = (unsigned int *)&ams369fg06_22_250, +}; + +static int ams369fg06_spi_write_byte(struct ams369fg06 *lcd, int addr, int data) +{ + u16 buf[1]; + struct spi_message msg; + + struct spi_transfer xfer = { + .len = 2, + .tx_buf = buf, + }; + + buf[0] = (addr << 8) | data; + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + + return spi_sync(lcd->spi, &msg); +} + +static int ams369fg06_spi_write(struct ams369fg06 *lcd, unsigned char address, + unsigned char command) +{ + int ret = 0; + + if (address != DATA_ONLY) + ret = ams369fg06_spi_write_byte(lcd, 0x70, address); + if (command != COMMAND_ONLY) + ret = ams369fg06_spi_write_byte(lcd, 0x72, command); + + return ret; +} + +static int ams369fg06_panel_send_sequence(struct ams369fg06 *lcd, + const unsigned short *wbuf) +{ + int ret = 0, i = 0; + + while ((wbuf[i] & DEFMASK) != ENDDEF) { + if ((wbuf[i] & DEFMASK) != SLEEPMSEC) { + ret = ams369fg06_spi_write(lcd, wbuf[i], wbuf[i+1]); + if (ret) + break; + } else { + msleep(wbuf[i+1]); + } + i += 2; + } + + return ret; +} + +static int _ams369fg06_gamma_ctl(struct ams369fg06 *lcd, + const unsigned int *gamma) +{ + unsigned int i = 0; + int ret = 0; + + for (i = 0 ; i < GAMMA_TABLE_COUNT / 3; i++) { + ret = ams369fg06_spi_write(lcd, 0x40 + i, gamma[i]); + ret = ams369fg06_spi_write(lcd, 0x50 + i, gamma[i+7*1]); + ret = ams369fg06_spi_write(lcd, 0x60 + i, gamma[i+7*2]); + if (ret) { + dev_err(lcd->dev, "failed to set gamma table.\n"); + goto gamma_err; + } + } + +gamma_err: + return ret; +} + +static int ams369fg06_gamma_ctl(struct ams369fg06 *lcd, int brightness) +{ + int ret = 0; + int gamma = 0; + + if ((brightness >= 0) && (brightness <= 50)) + gamma = 0; + else if ((brightness > 50) && (brightness <= 100)) + gamma = 1; + else if ((brightness > 100) && (brightness <= 150)) + gamma = 2; + else if ((brightness > 150) && (brightness <= 200)) + gamma = 3; + else if ((brightness > 200) && (brightness <= 255)) + gamma = 4; + + ret = _ams369fg06_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]); + + return ret; +} + +static int ams369fg06_ldi_init(struct ams369fg06 *lcd) +{ + int ret, i; + static const unsigned short *init_seq[] = { + seq_setting, + seq_stand_by_off, + }; + + for (i = 0; i < ARRAY_SIZE(init_seq); i++) { + ret = ams369fg06_panel_send_sequence(lcd, init_seq[i]); + if (ret) + break; + } + + return ret; +} + +static int ams369fg06_ldi_enable(struct ams369fg06 *lcd) +{ + int ret, i; + static const unsigned short *init_seq[] = { + seq_stand_by_off, + seq_display_on, + }; + + for (i = 0; i < ARRAY_SIZE(init_seq); i++) { + ret = ams369fg06_panel_send_sequence(lcd, init_seq[i]); + if (ret) + break; + } + + return ret; +} + +static int ams369fg06_ldi_disable(struct ams369fg06 *lcd) +{ + int ret, i; + + static const unsigned short *init_seq[] = { + seq_display_off, + seq_stand_by_on, + }; + + for (i = 0; i < ARRAY_SIZE(init_seq); i++) { + ret = ams369fg06_panel_send_sequence(lcd, init_seq[i]); + if (ret) + break; + } + + return ret; +} + +static int ams369fg06_power_is_on(int power) +{ + return power <= FB_BLANK_NORMAL; +} + +static int ams369fg06_power_on(struct ams369fg06 *lcd) +{ + int ret = 0; + struct lcd_platform_data *pd; + struct backlight_device *bd; + + pd = lcd->lcd_pd; + bd = lcd->bd; + + if (pd->power_on) { + pd->power_on(lcd->ld, 1); + msleep(pd->power_on_delay); + } + + if (!pd->reset) { + dev_err(lcd->dev, "reset is NULL.\n"); + return -EINVAL; + } + + pd->reset(lcd->ld); + msleep(pd->reset_delay); + + ret = ams369fg06_ldi_init(lcd); + if (ret) { + dev_err(lcd->dev, "failed to initialize ldi.\n"); + return ret; + } + + ret = ams369fg06_ldi_enable(lcd); + if (ret) { + dev_err(lcd->dev, "failed to enable ldi.\n"); + return ret; + } + + /* set brightness to current value after power on or resume. */ + ret = ams369fg06_gamma_ctl(lcd, bd->props.brightness); + if (ret) { + dev_err(lcd->dev, "lcd gamma setting failed.\n"); + return ret; + } + + return 0; +} + +static int ams369fg06_power_off(struct ams369fg06 *lcd) +{ + int ret; + struct lcd_platform_data *pd; + + pd = lcd->lcd_pd; + + ret = ams369fg06_ldi_disable(lcd); + if (ret) { + dev_err(lcd->dev, "lcd setting failed.\n"); + return -EIO; + } + + msleep(pd->power_off_delay); + + if (pd->power_on) + pd->power_on(lcd->ld, 0); + + return 0; +} + +static int ams369fg06_power(struct ams369fg06 *lcd, int power) +{ + int ret = 0; + + if (ams369fg06_power_is_on(power) && + !ams369fg06_power_is_on(lcd->power)) + ret = ams369fg06_power_on(lcd); + else if (!ams369fg06_power_is_on(power) && + ams369fg06_power_is_on(lcd->power)) + ret = ams369fg06_power_off(lcd); + + if (!ret) + lcd->power = power; + + return ret; +} + +static int ams369fg06_get_power(struct lcd_device *ld) +{ + struct ams369fg06 *lcd = lcd_get_data(ld); + + return lcd->power; +} + +static int ams369fg06_set_power(struct lcd_device *ld, int power) +{ + struct ams369fg06 *lcd = lcd_get_data(ld); + + if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && + power != FB_BLANK_NORMAL) { + dev_err(lcd->dev, "power value should be 0, 1 or 4.\n"); + return -EINVAL; + } + + return ams369fg06_power(lcd, power); +} + +static int ams369fg06_set_brightness(struct backlight_device *bd) +{ + int ret = 0; + int brightness = bd->props.brightness; + struct ams369fg06 *lcd = bl_get_data(bd); + + if (brightness < MIN_BRIGHTNESS || + brightness > bd->props.max_brightness) { + dev_err(&bd->dev, "lcd brightness should be %d to %d.\n", + MIN_BRIGHTNESS, MAX_BRIGHTNESS); + return -EINVAL; + } + + ret = ams369fg06_gamma_ctl(lcd, bd->props.brightness); + if (ret) { + dev_err(&bd->dev, "lcd brightness setting failed.\n"); + return -EIO; + } + + return ret; +} + +static struct lcd_ops ams369fg06_lcd_ops = { + .get_power = ams369fg06_get_power, + .set_power = ams369fg06_set_power, +}; + +static const struct backlight_ops ams369fg06_backlight_ops = { + .update_status = ams369fg06_set_brightness, +}; + +static int ams369fg06_probe(struct spi_device *spi) +{ + int ret = 0; + struct ams369fg06 *lcd = NULL; + struct lcd_device *ld = NULL; + struct backlight_device *bd = NULL; + struct backlight_properties props; + + lcd = devm_kzalloc(&spi->dev, sizeof(struct ams369fg06), GFP_KERNEL); + if (!lcd) + return -ENOMEM; + + /* ams369fg06 lcd panel uses 3-wire 16bits SPI Mode. */ + spi->bits_per_word = 16; + + ret = spi_setup(spi); + if (ret < 0) { + dev_err(&spi->dev, "spi setup failed.\n"); + return ret; + } + + lcd->spi = spi; + lcd->dev = &spi->dev; + + lcd->lcd_pd = dev_get_platdata(&spi->dev); + if (!lcd->lcd_pd) { + dev_err(&spi->dev, "platform data is NULL\n"); + return -EINVAL; + } + + ld = devm_lcd_device_register(&spi->dev, "ams369fg06", &spi->dev, lcd, + &ams369fg06_lcd_ops); + if (IS_ERR(ld)) + return PTR_ERR(ld); + + lcd->ld = ld; + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; + props.max_brightness = MAX_BRIGHTNESS; + + bd = devm_backlight_device_register(&spi->dev, "ams369fg06-bl", + &spi->dev, lcd, + &ams369fg06_backlight_ops, &props); + if (IS_ERR(bd)) + return PTR_ERR(bd); + + bd->props.brightness = DEFAULT_BRIGHTNESS; + lcd->bd = bd; + + if (!lcd->lcd_pd->lcd_enabled) { + /* + * if lcd panel was off from bootloader then + * current lcd status is powerdown and then + * it enables lcd panel. + */ + lcd->power = FB_BLANK_POWERDOWN; + + ams369fg06_power(lcd, FB_BLANK_UNBLANK); + } else { + lcd->power = FB_BLANK_UNBLANK; + } + + spi_set_drvdata(spi, lcd); + + dev_info(&spi->dev, "ams369fg06 panel driver has been probed.\n"); + + return 0; +} + +static int ams369fg06_remove(struct spi_device *spi) +{ + struct ams369fg06 *lcd = spi_get_drvdata(spi); + + ams369fg06_power(lcd, FB_BLANK_POWERDOWN); + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int ams369fg06_suspend(struct device *dev) +{ + struct ams369fg06 *lcd = dev_get_drvdata(dev); + + dev_dbg(dev, "lcd->power = %d\n", lcd->power); + + /* + * when lcd panel is suspend, lcd panel becomes off + * regardless of status. + */ + return ams369fg06_power(lcd, FB_BLANK_POWERDOWN); +} + +static int ams369fg06_resume(struct device *dev) +{ + struct ams369fg06 *lcd = dev_get_drvdata(dev); + + lcd->power = FB_BLANK_POWERDOWN; + + return ams369fg06_power(lcd, FB_BLANK_UNBLANK); +} +#endif + +static SIMPLE_DEV_PM_OPS(ams369fg06_pm_ops, ams369fg06_suspend, + ams369fg06_resume); + +static void ams369fg06_shutdown(struct spi_device *spi) +{ + struct ams369fg06 *lcd = spi_get_drvdata(spi); + + ams369fg06_power(lcd, FB_BLANK_POWERDOWN); +} + +static struct spi_driver ams369fg06_driver = { + .driver = { + .name = "ams369fg06", + .owner = THIS_MODULE, + .pm = &ams369fg06_pm_ops, + }, + .probe = ams369fg06_probe, + .remove = ams369fg06_remove, + .shutdown = ams369fg06_shutdown, +}; + +module_spi_driver(ams369fg06_driver); + +MODULE_AUTHOR("Jingoo Han "); +MODULE_DESCRIPTION("ams369fg06 LCD Driver"); +MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/video/backlight/apple_bl.c b/kernel/drivers/video/backlight/apple_bl.c new file mode 100644 index 000000000..d84329676 --- /dev/null +++ b/kernel/drivers/video/backlight/apple_bl.c @@ -0,0 +1,257 @@ +/* + * Backlight Driver for Intel-based Apples + * + * Copyright (c) Red Hat + * Based on code from Pommed: + * Copyright (C) 2006 Nicolas Boichat + * Copyright (C) 2006 Felipe Alfaro Solana + * Copyright (C) 2007 Julien BLACHE + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This driver triggers SMIs which cause the firmware to change the + * backlight brightness. This is icky in many ways, but it's impractical to + * get at the firmware code in order to figure out what it's actually doing. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct backlight_device *apple_backlight_device; + +struct hw_data { + /* I/O resource to allocate. */ + unsigned long iostart; + unsigned long iolen; + /* Backlight operations structure. */ + const struct backlight_ops backlight_ops; + void (*set_brightness)(int); +}; + +static const struct hw_data *hw_data; + +/* Module parameters. */ +static int debug; +module_param_named(debug, debug, int, 0644); +MODULE_PARM_DESC(debug, "Set to one to enable debugging messages."); + +/* + * Implementation for machines with Intel chipset. + */ +static void intel_chipset_set_brightness(int intensity) +{ + outb(0x04 | (intensity << 4), 0xb3); + outb(0xbf, 0xb2); +} + +static int intel_chipset_send_intensity(struct backlight_device *bd) +{ + int intensity = bd->props.brightness; + + if (debug) + pr_debug("setting brightness to %d\n", intensity); + + intel_chipset_set_brightness(intensity); + return 0; +} + +static int intel_chipset_get_intensity(struct backlight_device *bd) +{ + int intensity; + + outb(0x03, 0xb3); + outb(0xbf, 0xb2); + intensity = inb(0xb3) >> 4; + + if (debug) + pr_debug("read brightness of %d\n", intensity); + + return intensity; +} + +static const struct hw_data intel_chipset_data = { + .iostart = 0xb2, + .iolen = 2, + .backlight_ops = { + .options = BL_CORE_SUSPENDRESUME, + .get_brightness = intel_chipset_get_intensity, + .update_status = intel_chipset_send_intensity, + }, + .set_brightness = intel_chipset_set_brightness, +}; + +/* + * Implementation for machines with Nvidia chipset. + */ +static void nvidia_chipset_set_brightness(int intensity) +{ + outb(0x04 | (intensity << 4), 0x52f); + outb(0xbf, 0x52e); +} + +static int nvidia_chipset_send_intensity(struct backlight_device *bd) +{ + int intensity = bd->props.brightness; + + if (debug) + pr_debug("setting brightness to %d\n", intensity); + + nvidia_chipset_set_brightness(intensity); + return 0; +} + +static int nvidia_chipset_get_intensity(struct backlight_device *bd) +{ + int intensity; + + outb(0x03, 0x52f); + outb(0xbf, 0x52e); + intensity = inb(0x52f) >> 4; + + if (debug) + pr_debug("read brightness of %d\n", intensity); + + return intensity; +} + +static const struct hw_data nvidia_chipset_data = { + .iostart = 0x52e, + .iolen = 2, + .backlight_ops = { + .options = BL_CORE_SUSPENDRESUME, + .get_brightness = nvidia_chipset_get_intensity, + .update_status = nvidia_chipset_send_intensity + }, + .set_brightness = nvidia_chipset_set_brightness, +}; + +static int apple_bl_add(struct acpi_device *dev) +{ + struct backlight_properties props; + struct pci_dev *host; + int intensity; + + host = pci_get_bus_and_slot(0, 0); + + if (!host) { + pr_err("unable to find PCI host\n"); + return -ENODEV; + } + + if (host->vendor == PCI_VENDOR_ID_INTEL) + hw_data = &intel_chipset_data; + else if (host->vendor == PCI_VENDOR_ID_NVIDIA) + hw_data = &nvidia_chipset_data; + + pci_dev_put(host); + + if (!hw_data) { + pr_err("unknown hardware\n"); + return -ENODEV; + } + + /* Check that the hardware responds - this may not work under EFI */ + + intensity = hw_data->backlight_ops.get_brightness(NULL); + + if (!intensity) { + hw_data->set_brightness(1); + if (!hw_data->backlight_ops.get_brightness(NULL)) + return -ENODEV; + + hw_data->set_brightness(0); + } + + if (!request_region(hw_data->iostart, hw_data->iolen, + "Apple backlight")) + return -ENXIO; + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; + props.max_brightness = 15; + apple_backlight_device = backlight_device_register("apple_backlight", + NULL, NULL, &hw_data->backlight_ops, &props); + + if (IS_ERR(apple_backlight_device)) { + release_region(hw_data->iostart, hw_data->iolen); + return PTR_ERR(apple_backlight_device); + } + + apple_backlight_device->props.brightness = + hw_data->backlight_ops.get_brightness(apple_backlight_device); + backlight_update_status(apple_backlight_device); + + return 0; +} + +static int apple_bl_remove(struct acpi_device *dev) +{ + backlight_device_unregister(apple_backlight_device); + + release_region(hw_data->iostart, hw_data->iolen); + hw_data = NULL; + return 0; +} + +static const struct acpi_device_id apple_bl_ids[] = { + {"APP0002", 0}, + {"", 0}, +}; + +static struct acpi_driver apple_bl_driver = { + .name = "Apple backlight", + .ids = apple_bl_ids, + .ops = { + .add = apple_bl_add, + .remove = apple_bl_remove, + }, +}; + +static atomic_t apple_bl_registered = ATOMIC_INIT(0); + +int apple_bl_register(void) +{ + if (atomic_xchg(&apple_bl_registered, 1) == 0) + return acpi_bus_register_driver(&apple_bl_driver); + + return 0; +} +EXPORT_SYMBOL_GPL(apple_bl_register); + +void apple_bl_unregister(void) +{ + if (atomic_xchg(&apple_bl_registered, 0) == 1) + acpi_bus_unregister_driver(&apple_bl_driver); +} +EXPORT_SYMBOL_GPL(apple_bl_unregister); + +static int __init apple_bl_init(void) +{ + return apple_bl_register(); +} + +static void __exit apple_bl_exit(void) +{ + apple_bl_unregister(); +} + +module_init(apple_bl_init); +module_exit(apple_bl_exit); + +MODULE_AUTHOR("Matthew Garrett "); +MODULE_DESCRIPTION("Apple Backlight Driver"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(acpi, apple_bl_ids); +MODULE_ALIAS("mbp_nvidia_bl"); diff --git a/kernel/drivers/video/backlight/as3711_bl.c b/kernel/drivers/video/backlight/as3711_bl.c new file mode 100644 index 000000000..734a91589 --- /dev/null +++ b/kernel/drivers/video/backlight/as3711_bl.c @@ -0,0 +1,479 @@ +/* + * AS3711 PMIC backlight driver, using DCDC Step Up Converters + * + * Copyright (C) 2012 Renesas Electronics Corporation + * Author: Guennadi Liakhovetski, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License as + * published by the Free Software Foundation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum as3711_bl_type { + AS3711_BL_SU1, + AS3711_BL_SU2, +}; + +struct as3711_bl_data { + bool powered; + const char *fb_name; + struct device *fb_dev; + enum as3711_bl_type type; + int brightness; + struct backlight_device *bl; +}; + +struct as3711_bl_supply { + struct as3711_bl_data su1; + struct as3711_bl_data su2; + const struct as3711_bl_pdata *pdata; + struct as3711 *as3711; +}; + +static struct as3711_bl_supply *to_supply(struct as3711_bl_data *su) +{ + switch (su->type) { + case AS3711_BL_SU1: + return container_of(su, struct as3711_bl_supply, su1); + case AS3711_BL_SU2: + return container_of(su, struct as3711_bl_supply, su2); + } + return NULL; +} + +static int as3711_set_brightness_auto_i(struct as3711_bl_data *data, + unsigned int brightness) +{ + struct as3711_bl_supply *supply = to_supply(data); + struct as3711 *as3711 = supply->as3711; + const struct as3711_bl_pdata *pdata = supply->pdata; + int ret = 0; + + /* Only all equal current values are supported */ + if (pdata->su2_auto_curr1) + ret = regmap_write(as3711->regmap, AS3711_CURR1_VALUE, + brightness); + if (!ret && pdata->su2_auto_curr2) + ret = regmap_write(as3711->regmap, AS3711_CURR2_VALUE, + brightness); + if (!ret && pdata->su2_auto_curr3) + ret = regmap_write(as3711->regmap, AS3711_CURR3_VALUE, + brightness); + + return ret; +} + +static int as3711_set_brightness_v(struct as3711 *as3711, + unsigned int brightness, + unsigned int reg) +{ + if (brightness > 31) + return -EINVAL; + + return regmap_update_bits(as3711->regmap, reg, 0xf0, + brightness << 4); +} + +static int as3711_bl_su2_reset(struct as3711_bl_supply *supply) +{ + struct as3711 *as3711 = supply->as3711; + int ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_5, + 3, supply->pdata->su2_fbprot); + if (!ret) + ret = regmap_update_bits(as3711->regmap, + AS3711_STEPUP_CONTROL_2, 1, 0); + if (!ret) + ret = regmap_update_bits(as3711->regmap, + AS3711_STEPUP_CONTROL_2, 1, 1); + return ret; +} + +/* + * Someone with less fragile or less expensive hardware could try to simplify + * the brightness adjustment procedure. + */ +static int as3711_bl_update_status(struct backlight_device *bl) +{ + struct as3711_bl_data *data = bl_get_data(bl); + struct as3711_bl_supply *supply = to_supply(data); + struct as3711 *as3711 = supply->as3711; + int brightness = bl->props.brightness; + int ret = 0; + + dev_dbg(&bl->dev, "%s(): brightness %u, pwr %x, blank %x, state %x\n", + __func__, bl->props.brightness, bl->props.power, + bl->props.fb_blank, bl->props.state); + + if (bl->props.power != FB_BLANK_UNBLANK || + bl->props.fb_blank != FB_BLANK_UNBLANK || + bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) + brightness = 0; + + if (data->type == AS3711_BL_SU1) { + ret = as3711_set_brightness_v(as3711, brightness, + AS3711_STEPUP_CONTROL_1); + } else { + const struct as3711_bl_pdata *pdata = supply->pdata; + + switch (pdata->su2_feedback) { + case AS3711_SU2_VOLTAGE: + ret = as3711_set_brightness_v(as3711, brightness, + AS3711_STEPUP_CONTROL_2); + break; + case AS3711_SU2_CURR_AUTO: + ret = as3711_set_brightness_auto_i(data, brightness / 4); + if (ret < 0) + return ret; + if (brightness) { + ret = as3711_bl_su2_reset(supply); + if (ret < 0) + return ret; + udelay(500); + ret = as3711_set_brightness_auto_i(data, brightness); + } else { + ret = regmap_update_bits(as3711->regmap, + AS3711_STEPUP_CONTROL_2, 1, 0); + } + break; + /* Manual one current feedback pin below */ + case AS3711_SU2_CURR1: + ret = regmap_write(as3711->regmap, AS3711_CURR1_VALUE, + brightness); + break; + case AS3711_SU2_CURR2: + ret = regmap_write(as3711->regmap, AS3711_CURR2_VALUE, + brightness); + break; + case AS3711_SU2_CURR3: + ret = regmap_write(as3711->regmap, AS3711_CURR3_VALUE, + brightness); + break; + default: + ret = -EINVAL; + } + } + if (!ret) + data->brightness = brightness; + + return ret; +} + +static int as3711_bl_get_brightness(struct backlight_device *bl) +{ + struct as3711_bl_data *data = bl_get_data(bl); + + return data->brightness; +} + +static const struct backlight_ops as3711_bl_ops = { + .update_status = as3711_bl_update_status, + .get_brightness = as3711_bl_get_brightness, +}; + +static int as3711_bl_init_su2(struct as3711_bl_supply *supply) +{ + struct as3711 *as3711 = supply->as3711; + const struct as3711_bl_pdata *pdata = supply->pdata; + u8 ctl = 0; + int ret; + + dev_dbg(as3711->dev, "%s(): use %u\n", __func__, pdata->su2_feedback); + + /* Turn SU2 off */ + ret = regmap_write(as3711->regmap, AS3711_STEPUP_CONTROL_2, 0); + if (ret < 0) + return ret; + + switch (pdata->su2_feedback) { + case AS3711_SU2_VOLTAGE: + ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_4, 3, 0); + break; + case AS3711_SU2_CURR1: + ctl = 1; + ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_4, 3, 1); + break; + case AS3711_SU2_CURR2: + ctl = 4; + ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_4, 3, 2); + break; + case AS3711_SU2_CURR3: + ctl = 0x10; + ret = regmap_update_bits(as3711->regmap, AS3711_STEPUP_CONTROL_4, 3, 3); + break; + case AS3711_SU2_CURR_AUTO: + if (pdata->su2_auto_curr1) + ctl = 2; + if (pdata->su2_auto_curr2) + ctl |= 8; + if (pdata->su2_auto_curr3) + ctl |= 0x20; + ret = 0; + break; + default: + return -EINVAL; + } + + if (!ret) + ret = regmap_write(as3711->regmap, AS3711_CURR_CONTROL, ctl); + + return ret; +} + +static int as3711_bl_register(struct platform_device *pdev, + unsigned int max_brightness, struct as3711_bl_data *su) +{ + struct backlight_properties props = {.type = BACKLIGHT_RAW,}; + struct backlight_device *bl; + + /* max tuning I = 31uA for voltage- and 38250uA for current-feedback */ + props.max_brightness = max_brightness; + + bl = devm_backlight_device_register(&pdev->dev, + su->type == AS3711_BL_SU1 ? + "as3711-su1" : "as3711-su2", + &pdev->dev, su, + &as3711_bl_ops, &props); + if (IS_ERR(bl)) { + dev_err(&pdev->dev, "failed to register backlight\n"); + return PTR_ERR(bl); + } + + bl->props.brightness = props.max_brightness; + + backlight_update_status(bl); + + su->bl = bl; + + return 0; +} + +static int as3711_backlight_parse_dt(struct device *dev) +{ + struct as3711_bl_pdata *pdata = dev_get_platdata(dev); + struct device_node *bl = + of_find_node_by_name(dev->parent->of_node, "backlight"), *fb; + int ret; + + if (!bl) { + dev_dbg(dev, "backlight node not found\n"); + return -ENODEV; + } + + fb = of_parse_phandle(bl, "su1-dev", 0); + if (fb) { + pdata->su1_fb = fb->full_name; + + ret = of_property_read_u32(bl, "su1-max-uA", &pdata->su1_max_uA); + if (pdata->su1_max_uA <= 0) + ret = -EINVAL; + if (ret < 0) + return ret; + } + + fb = of_parse_phandle(bl, "su2-dev", 0); + if (fb) { + int count = 0; + + pdata->su2_fb = fb->full_name; + + ret = of_property_read_u32(bl, "su2-max-uA", &pdata->su2_max_uA); + if (pdata->su2_max_uA <= 0) + ret = -EINVAL; + if (ret < 0) + return ret; + + if (of_find_property(bl, "su2-feedback-voltage", NULL)) { + pdata->su2_feedback = AS3711_SU2_VOLTAGE; + count++; + } + if (of_find_property(bl, "su2-feedback-curr1", NULL)) { + pdata->su2_feedback = AS3711_SU2_CURR1; + count++; + } + if (of_find_property(bl, "su2-feedback-curr2", NULL)) { + pdata->su2_feedback = AS3711_SU2_CURR2; + count++; + } + if (of_find_property(bl, "su2-feedback-curr3", NULL)) { + pdata->su2_feedback = AS3711_SU2_CURR3; + count++; + } + if (of_find_property(bl, "su2-feedback-curr-auto", NULL)) { + pdata->su2_feedback = AS3711_SU2_CURR_AUTO; + count++; + } + if (count != 1) + return -EINVAL; + + count = 0; + if (of_find_property(bl, "su2-fbprot-lx-sd4", NULL)) { + pdata->su2_fbprot = AS3711_SU2_LX_SD4; + count++; + } + if (of_find_property(bl, "su2-fbprot-gpio2", NULL)) { + pdata->su2_fbprot = AS3711_SU2_GPIO2; + count++; + } + if (of_find_property(bl, "su2-fbprot-gpio3", NULL)) { + pdata->su2_fbprot = AS3711_SU2_GPIO3; + count++; + } + if (of_find_property(bl, "su2-fbprot-gpio4", NULL)) { + pdata->su2_fbprot = AS3711_SU2_GPIO4; + count++; + } + if (count != 1) + return -EINVAL; + + count = 0; + if (of_find_property(bl, "su2-auto-curr1", NULL)) { + pdata->su2_auto_curr1 = true; + count++; + } + if (of_find_property(bl, "su2-auto-curr2", NULL)) { + pdata->su2_auto_curr2 = true; + count++; + } + if (of_find_property(bl, "su2-auto-curr3", NULL)) { + pdata->su2_auto_curr3 = true; + count++; + } + + /* + * At least one su2-auto-curr* must be specified iff + * AS3711_SU2_CURR_AUTO is used + */ + if (!count ^ (pdata->su2_feedback != AS3711_SU2_CURR_AUTO)) + return -EINVAL; + } + + return 0; +} + +static int as3711_backlight_probe(struct platform_device *pdev) +{ + struct as3711_bl_pdata *pdata = dev_get_platdata(&pdev->dev); + struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent); + struct as3711_bl_supply *supply; + struct as3711_bl_data *su; + unsigned int max_brightness; + int ret; + + if (!pdata) { + dev_err(&pdev->dev, "No platform data, exiting...\n"); + return -ENODEV; + } + + if (pdev->dev.parent->of_node) { + ret = as3711_backlight_parse_dt(&pdev->dev); + if (ret < 0) { + dev_err(&pdev->dev, "DT parsing failed: %d\n", ret); + return ret; + } + } + + if (!pdata->su1_fb && !pdata->su2_fb) { + dev_err(&pdev->dev, "No framebuffer specified\n"); + return -EINVAL; + } + + /* + * Due to possible hardware damage I chose to block all modes, + * unsupported on my hardware. Anyone, wishing to use any of those modes + * will have to first review the code, then activate and test it. + */ + if (pdata->su1_fb || + pdata->su2_fbprot != AS3711_SU2_GPIO4 || + pdata->su2_feedback != AS3711_SU2_CURR_AUTO) { + dev_warn(&pdev->dev, + "Attention! An untested mode has been chosen!\n" + "Please, review the code, enable, test, and report success:-)\n"); + return -EINVAL; + } + + supply = devm_kzalloc(&pdev->dev, sizeof(*supply), GFP_KERNEL); + if (!supply) + return -ENOMEM; + + supply->as3711 = as3711; + supply->pdata = pdata; + + if (pdata->su1_fb) { + su = &supply->su1; + su->fb_name = pdata->su1_fb; + su->type = AS3711_BL_SU1; + + max_brightness = min(pdata->su1_max_uA, 31); + ret = as3711_bl_register(pdev, max_brightness, su); + if (ret < 0) + return ret; + } + + if (pdata->su2_fb) { + su = &supply->su2; + su->fb_name = pdata->su2_fb; + su->type = AS3711_BL_SU2; + + switch (pdata->su2_fbprot) { + case AS3711_SU2_GPIO2: + case AS3711_SU2_GPIO3: + case AS3711_SU2_GPIO4: + case AS3711_SU2_LX_SD4: + break; + default: + return -EINVAL; + } + + switch (pdata->su2_feedback) { + case AS3711_SU2_VOLTAGE: + max_brightness = min(pdata->su2_max_uA, 31); + break; + case AS3711_SU2_CURR1: + case AS3711_SU2_CURR2: + case AS3711_SU2_CURR3: + case AS3711_SU2_CURR_AUTO: + max_brightness = min(pdata->su2_max_uA / 150, 255); + break; + default: + return -EINVAL; + } + + ret = as3711_bl_init_su2(supply); + if (ret < 0) + return ret; + + ret = as3711_bl_register(pdev, max_brightness, su); + if (ret < 0) + return ret; + } + + platform_set_drvdata(pdev, supply); + + return 0; +} + +static struct platform_driver as3711_backlight_driver = { + .driver = { + .name = "as3711-backlight", + }, + .probe = as3711_backlight_probe, +}; + +module_platform_driver(as3711_backlight_driver); + +MODULE_DESCRIPTION("Backlight Driver for AS3711 PMICs"); +MODULE_AUTHOR("Guennadi Liakhovetski +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PMAC_BACKLIGHT +#include +#endif + +static struct list_head backlight_dev_list; +static struct mutex backlight_dev_list_mutex; +static struct blocking_notifier_head backlight_notifier; + +static const char *const backlight_types[] = { + [BACKLIGHT_RAW] = "raw", + [BACKLIGHT_PLATFORM] = "platform", + [BACKLIGHT_FIRMWARE] = "firmware", +}; + +#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)) +/* This callback gets called when something important happens inside a + * framebuffer driver. We're looking if that important event is blanking, + * and if it is and necessary, we're switching backlight power as well ... + */ +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct backlight_device *bd; + struct fb_event *evdata = data; + int node = evdata->info->node; + int fb_blank = 0; + + /* If we aren't interested in this event, skip it immediately ... */ + if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK) + return 0; + + bd = container_of(self, struct backlight_device, fb_notif); + mutex_lock(&bd->ops_lock); + if (bd->ops) + if (!bd->ops->check_fb || + bd->ops->check_fb(bd, evdata->info)) { + fb_blank = *(int *)evdata->data; + if (fb_blank == FB_BLANK_UNBLANK && + !bd->fb_bl_on[node]) { + bd->fb_bl_on[node] = true; + if (!bd->use_count++) { + bd->props.state &= ~BL_CORE_FBBLANK; + bd->props.fb_blank = FB_BLANK_UNBLANK; + backlight_update_status(bd); + } + } else if (fb_blank != FB_BLANK_UNBLANK && + bd->fb_bl_on[node]) { + bd->fb_bl_on[node] = false; + if (!(--bd->use_count)) { + bd->props.state |= BL_CORE_FBBLANK; + bd->props.fb_blank = fb_blank; + backlight_update_status(bd); + } + } + } + mutex_unlock(&bd->ops_lock); + return 0; +} + +static int backlight_register_fb(struct backlight_device *bd) +{ + memset(&bd->fb_notif, 0, sizeof(bd->fb_notif)); + bd->fb_notif.notifier_call = fb_notifier_callback; + + return fb_register_client(&bd->fb_notif); +} + +static void backlight_unregister_fb(struct backlight_device *bd) +{ + fb_unregister_client(&bd->fb_notif); +} +#else +static inline int backlight_register_fb(struct backlight_device *bd) +{ + return 0; +} + +static inline void backlight_unregister_fb(struct backlight_device *bd) +{ +} +#endif /* CONFIG_FB */ + +static void backlight_generate_event(struct backlight_device *bd, + enum backlight_update_reason reason) +{ + char *envp[2]; + + switch (reason) { + case BACKLIGHT_UPDATE_SYSFS: + envp[0] = "SOURCE=sysfs"; + break; + case BACKLIGHT_UPDATE_HOTKEY: + envp[0] = "SOURCE=hotkey"; + break; + default: + envp[0] = "SOURCE=unknown"; + break; + } + envp[1] = NULL; + kobject_uevent_env(&bd->dev.kobj, KOBJ_CHANGE, envp); + sysfs_notify(&bd->dev.kobj, NULL, "actual_brightness"); +} + +static ssize_t bl_power_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct backlight_device *bd = to_backlight_device(dev); + + return sprintf(buf, "%d\n", bd->props.power); +} + +static ssize_t bl_power_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int rc; + struct backlight_device *bd = to_backlight_device(dev); + unsigned long power; + + rc = kstrtoul(buf, 0, &power); + if (rc) + return rc; + + rc = -ENXIO; + mutex_lock(&bd->ops_lock); + if (bd->ops) { + pr_debug("set power to %lu\n", power); + if (bd->props.power != power) { + bd->props.power = power; + backlight_update_status(bd); + } + rc = count; + } + mutex_unlock(&bd->ops_lock); + + return rc; +} +static DEVICE_ATTR_RW(bl_power); + +static ssize_t brightness_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct backlight_device *bd = to_backlight_device(dev); + + return sprintf(buf, "%d\n", bd->props.brightness); +} + +static ssize_t brightness_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc; + struct backlight_device *bd = to_backlight_device(dev); + unsigned long brightness; + + rc = kstrtoul(buf, 0, &brightness); + if (rc) + return rc; + + rc = -ENXIO; + + mutex_lock(&bd->ops_lock); + if (bd->ops) { + if (brightness > bd->props.max_brightness) + rc = -EINVAL; + else { + pr_debug("set brightness to %lu\n", brightness); + bd->props.brightness = brightness; + backlight_update_status(bd); + rc = count; + } + } + mutex_unlock(&bd->ops_lock); + + backlight_generate_event(bd, BACKLIGHT_UPDATE_SYSFS); + + return rc; +} +static DEVICE_ATTR_RW(brightness); + +static ssize_t type_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct backlight_device *bd = to_backlight_device(dev); + + return sprintf(buf, "%s\n", backlight_types[bd->props.type]); +} +static DEVICE_ATTR_RO(type); + +static ssize_t max_brightness_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct backlight_device *bd = to_backlight_device(dev); + + return sprintf(buf, "%d\n", bd->props.max_brightness); +} +static DEVICE_ATTR_RO(max_brightness); + +static ssize_t actual_brightness_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int rc = -ENXIO; + struct backlight_device *bd = to_backlight_device(dev); + + mutex_lock(&bd->ops_lock); + if (bd->ops && bd->ops->get_brightness) + rc = sprintf(buf, "%d\n", bd->ops->get_brightness(bd)); + else + rc = sprintf(buf, "%d\n", bd->props.brightness); + mutex_unlock(&bd->ops_lock); + + return rc; +} +static DEVICE_ATTR_RO(actual_brightness); + +static struct class *backlight_class; + +#ifdef CONFIG_PM_SLEEP +static int backlight_suspend(struct device *dev) +{ + struct backlight_device *bd = to_backlight_device(dev); + + mutex_lock(&bd->ops_lock); + if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) { + bd->props.state |= BL_CORE_SUSPENDED; + backlight_update_status(bd); + } + mutex_unlock(&bd->ops_lock); + + return 0; +} + +static int backlight_resume(struct device *dev) +{ + struct backlight_device *bd = to_backlight_device(dev); + + mutex_lock(&bd->ops_lock); + if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) { + bd->props.state &= ~BL_CORE_SUSPENDED; + backlight_update_status(bd); + } + mutex_unlock(&bd->ops_lock); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(backlight_class_dev_pm_ops, backlight_suspend, + backlight_resume); + +static void bl_device_release(struct device *dev) +{ + struct backlight_device *bd = to_backlight_device(dev); + kfree(bd); +} + +static struct attribute *bl_device_attrs[] = { + &dev_attr_bl_power.attr, + &dev_attr_brightness.attr, + &dev_attr_actual_brightness.attr, + &dev_attr_max_brightness.attr, + &dev_attr_type.attr, + NULL, +}; +ATTRIBUTE_GROUPS(bl_device); + +/** + * backlight_force_update - tell the backlight subsystem that hardware state + * has changed + * @bd: the backlight device to update + * + * Updates the internal state of the backlight in response to a hardware event, + * and generate a uevent to notify userspace + */ +void backlight_force_update(struct backlight_device *bd, + enum backlight_update_reason reason) +{ + mutex_lock(&bd->ops_lock); + if (bd->ops && bd->ops->get_brightness) + bd->props.brightness = bd->ops->get_brightness(bd); + mutex_unlock(&bd->ops_lock); + backlight_generate_event(bd, reason); +} +EXPORT_SYMBOL(backlight_force_update); + +/** + * backlight_device_register - create and register a new object of + * backlight_device class. + * @name: the name of the new object(must be the same as the name of the + * respective framebuffer device). + * @parent: a pointer to the parent device + * @devdata: an optional pointer to be stored for private driver use. The + * methods may retrieve it by using bl_get_data(bd). + * @ops: the backlight operations structure. + * + * Creates and registers new backlight device. Returns either an + * ERR_PTR() or a pointer to the newly allocated device. + */ +struct backlight_device *backlight_device_register(const char *name, + struct device *parent, void *devdata, const struct backlight_ops *ops, + const struct backlight_properties *props) +{ + struct backlight_device *new_bd; + int rc; + + pr_debug("backlight_device_register: name=%s\n", name); + + new_bd = kzalloc(sizeof(struct backlight_device), GFP_KERNEL); + if (!new_bd) + return ERR_PTR(-ENOMEM); + + mutex_init(&new_bd->update_lock); + mutex_init(&new_bd->ops_lock); + + new_bd->dev.class = backlight_class; + new_bd->dev.parent = parent; + new_bd->dev.release = bl_device_release; + dev_set_name(&new_bd->dev, "%s", name); + dev_set_drvdata(&new_bd->dev, devdata); + + /* Set default properties */ + if (props) { + memcpy(&new_bd->props, props, + sizeof(struct backlight_properties)); + if (props->type <= 0 || props->type >= BACKLIGHT_TYPE_MAX) { + WARN(1, "%s: invalid backlight type", name); + new_bd->props.type = BACKLIGHT_RAW; + } + } else { + new_bd->props.type = BACKLIGHT_RAW; + } + + rc = device_register(&new_bd->dev); + if (rc) { + put_device(&new_bd->dev); + return ERR_PTR(rc); + } + + rc = backlight_register_fb(new_bd); + if (rc) { + device_unregister(&new_bd->dev); + return ERR_PTR(rc); + } + + new_bd->ops = ops; + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_lock(&pmac_backlight_mutex); + if (!pmac_backlight) + pmac_backlight = new_bd; + mutex_unlock(&pmac_backlight_mutex); +#endif + + mutex_lock(&backlight_dev_list_mutex); + list_add(&new_bd->entry, &backlight_dev_list); + mutex_unlock(&backlight_dev_list_mutex); + + blocking_notifier_call_chain(&backlight_notifier, + BACKLIGHT_REGISTERED, new_bd); + + return new_bd; +} +EXPORT_SYMBOL(backlight_device_register); + +bool backlight_device_registered(enum backlight_type type) +{ + bool found = false; + struct backlight_device *bd; + + mutex_lock(&backlight_dev_list_mutex); + list_for_each_entry(bd, &backlight_dev_list, entry) { + if (bd->props.type == type) { + found = true; + break; + } + } + mutex_unlock(&backlight_dev_list_mutex); + + return found; +} +EXPORT_SYMBOL(backlight_device_registered); + +/** + * backlight_device_unregister - unregisters a backlight device object. + * @bd: the backlight device object to be unregistered and freed. + * + * Unregisters a previously registered via backlight_device_register object. + */ +void backlight_device_unregister(struct backlight_device *bd) +{ + if (!bd) + return; + + mutex_lock(&backlight_dev_list_mutex); + list_del(&bd->entry); + mutex_unlock(&backlight_dev_list_mutex); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_lock(&pmac_backlight_mutex); + if (pmac_backlight == bd) + pmac_backlight = NULL; + mutex_unlock(&pmac_backlight_mutex); +#endif + + blocking_notifier_call_chain(&backlight_notifier, + BACKLIGHT_UNREGISTERED, bd); + + mutex_lock(&bd->ops_lock); + bd->ops = NULL; + mutex_unlock(&bd->ops_lock); + + backlight_unregister_fb(bd); + device_unregister(&bd->dev); +} +EXPORT_SYMBOL(backlight_device_unregister); + +static void devm_backlight_device_release(struct device *dev, void *res) +{ + struct backlight_device *backlight = *(struct backlight_device **)res; + + backlight_device_unregister(backlight); +} + +static int devm_backlight_device_match(struct device *dev, void *res, + void *data) +{ + struct backlight_device **r = res; + + return *r == data; +} + +/** + * backlight_register_notifier - get notified of backlight (un)registration + * @nb: notifier block with the notifier to call on backlight (un)registration + * + * @return 0 on success, otherwise a negative error code + * + * Register a notifier to get notified when backlight devices get registered + * or unregistered. + */ +int backlight_register_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&backlight_notifier, nb); +} +EXPORT_SYMBOL(backlight_register_notifier); + +/** + * backlight_unregister_notifier - unregister a backlight notifier + * @nb: notifier block to unregister + * + * @return 0 on success, otherwise a negative error code + * + * Register a notifier to get notified when backlight devices get registered + * or unregistered. + */ +int backlight_unregister_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&backlight_notifier, nb); +} +EXPORT_SYMBOL(backlight_unregister_notifier); + +/** + * devm_backlight_device_register - resource managed backlight_device_register() + * @dev: the device to register + * @name: the name of the device + * @parent: a pointer to the parent device + * @devdata: an optional pointer to be stored for private driver use + * @ops: the backlight operations structure + * @props: the backlight properties + * + * @return a struct backlight on success, or an ERR_PTR on error + * + * Managed backlight_device_register(). The backlight_device returned + * from this function are automatically freed on driver detach. + * See backlight_device_register() for more information. + */ +struct backlight_device *devm_backlight_device_register(struct device *dev, + const char *name, struct device *parent, void *devdata, + const struct backlight_ops *ops, + const struct backlight_properties *props) +{ + struct backlight_device **ptr, *backlight; + + ptr = devres_alloc(devm_backlight_device_release, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + backlight = backlight_device_register(name, parent, devdata, ops, + props); + if (!IS_ERR(backlight)) { + *ptr = backlight; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return backlight; +} +EXPORT_SYMBOL(devm_backlight_device_register); + +/** + * devm_backlight_device_unregister - resource managed backlight_device_unregister() + * @dev: the device to unregister + * @bd: the backlight device to unregister + * + * Deallocated a backlight allocated with devm_backlight_device_register(). + * Normally this function will not need to be called and the resource management + * code will ensure that the resource is freed. + */ +void devm_backlight_device_unregister(struct device *dev, + struct backlight_device *bd) +{ + int rc; + + rc = devres_release(dev, devm_backlight_device_release, + devm_backlight_device_match, bd); + WARN_ON(rc); +} +EXPORT_SYMBOL(devm_backlight_device_unregister); + +#ifdef CONFIG_OF +static int of_parent_match(struct device *dev, const void *data) +{ + return dev->parent && dev->parent->of_node == data; +} + +/** + * of_find_backlight_by_node() - find backlight device by device-tree node + * @node: device-tree node of the backlight device + * + * Returns a pointer to the backlight device corresponding to the given DT + * node or NULL if no such backlight device exists or if the device hasn't + * been probed yet. + * + * This function obtains a reference on the backlight device and it is the + * caller's responsibility to drop the reference by calling put_device() on + * the backlight device's .dev field. + */ +struct backlight_device *of_find_backlight_by_node(struct device_node *node) +{ + struct device *dev; + + dev = class_find_device(backlight_class, NULL, node, of_parent_match); + + return dev ? to_backlight_device(dev) : NULL; +} +EXPORT_SYMBOL(of_find_backlight_by_node); +#endif + +static void __exit backlight_class_exit(void) +{ + class_destroy(backlight_class); +} + +static int __init backlight_class_init(void) +{ + backlight_class = class_create(THIS_MODULE, "backlight"); + if (IS_ERR(backlight_class)) { + pr_warn("Unable to create backlight class; errno = %ld\n", + PTR_ERR(backlight_class)); + return PTR_ERR(backlight_class); + } + + backlight_class->dev_groups = bl_device_groups; + backlight_class->pm = &backlight_class_dev_pm_ops; + INIT_LIST_HEAD(&backlight_dev_list); + mutex_init(&backlight_dev_list_mutex); + BLOCKING_INIT_NOTIFIER_HEAD(&backlight_notifier); + + return 0; +} + +/* + * if this is compiled into the kernel, we need to ensure that the + * class is registered before users of the class try to register lcd's + */ +postcore_initcall(backlight_class_init); +module_exit(backlight_class_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jamey Hicks , Andrew Zabolotny "); +MODULE_DESCRIPTION("Backlight Lowlevel Control Abstraction"); diff --git a/kernel/drivers/video/backlight/bd6107.c b/kernel/drivers/video/backlight/bd6107.c new file mode 100644 index 000000000..fdb2f7e2c --- /dev/null +++ b/kernel/drivers/video/backlight/bd6107.c @@ -0,0 +1,207 @@ +/* + * ROHM Semiconductor BD6107 LED Driver + * + * Copyright (C) 2013 Ideas on board SPRL + * + * Contact: Laurent Pinchart + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BD6107_PSCNT1 0x00 +#define BD6107_PSCNT1_PSCNTREG2 (1 << 2) +#define BD6107_PSCNT1_PSCNTREG1 (1 << 0) +#define BD6107_REGVSET 0x02 +#define BD6107_REGVSET_REG1VSET_2_85V (1 << 2) +#define BD6107_REGVSET_REG1VSET_2_80V (0 << 2) +#define BD6107_LEDCNT1 0x03 +#define BD6107_LEDCNT1_LEDONOFF2 (1 << 1) +#define BD6107_LEDCNT1_LEDONOFF1 (1 << 0) +#define BD6107_PORTSEL 0x04 +#define BD6107_PORTSEL_LEDM(n) (1 << (n)) +#define BD6107_RGB1CNT1 0x05 +#define BD6107_RGB1CNT2 0x06 +#define BD6107_RGB1CNT3 0x07 +#define BD6107_RGB1CNT4 0x08 +#define BD6107_RGB1CNT5 0x09 +#define BD6107_RGB1FLM 0x0a +#define BD6107_RGB2CNT1 0x0b +#define BD6107_RGB2CNT2 0x0c +#define BD6107_RGB2CNT3 0x0d +#define BD6107_RGB2CNT4 0x0e +#define BD6107_RGB2CNT5 0x0f +#define BD6107_RGB2FLM 0x10 +#define BD6107_PSCONT3 0x11 +#define BD6107_SMMONCNT 0x12 +#define BD6107_DCDCCNT 0x13 +#define BD6107_IOSEL 0x14 +#define BD6107_OUT1 0x15 +#define BD6107_OUT2 0x16 +#define BD6107_MASK1 0x17 +#define BD6107_MASK2 0x18 +#define BD6107_FACTOR1 0x19 +#define BD6107_FACTOR2 0x1a +#define BD6107_CLRFACT1 0x1b +#define BD6107_CLRFACT2 0x1c +#define BD6107_STATE1 0x1d +#define BD6107_LSIVER 0x1e +#define BD6107_GRPSEL 0x1f +#define BD6107_LEDCNT2 0x20 +#define BD6107_LEDCNT3 0x21 +#define BD6107_MCURRENT 0x22 +#define BD6107_MAINCNT1 0x23 +#define BD6107_MAINCNT2 0x24 +#define BD6107_SLOPECNT 0x25 +#define BD6107_MSLOPE 0x26 +#define BD6107_RGBSLOPE 0x27 +#define BD6107_TEST 0x29 +#define BD6107_SFTRST 0x2a +#define BD6107_SFTRSTGD 0x2b + +struct bd6107 { + struct i2c_client *client; + struct backlight_device *backlight; + struct bd6107_platform_data *pdata; +}; + +static int bd6107_write(struct bd6107 *bd, u8 reg, u8 data) +{ + return i2c_smbus_write_byte_data(bd->client, reg, data); +} + +static int bd6107_backlight_update_status(struct backlight_device *backlight) +{ + struct bd6107 *bd = bl_get_data(backlight); + int brightness = backlight->props.brightness; + + if (backlight->props.power != FB_BLANK_UNBLANK || + backlight->props.fb_blank != FB_BLANK_UNBLANK || + backlight->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) + brightness = 0; + + if (brightness) { + bd6107_write(bd, BD6107_PORTSEL, BD6107_PORTSEL_LEDM(2) | + BD6107_PORTSEL_LEDM(1) | BD6107_PORTSEL_LEDM(0)); + bd6107_write(bd, BD6107_MAINCNT1, brightness); + bd6107_write(bd, BD6107_LEDCNT1, BD6107_LEDCNT1_LEDONOFF1); + } else { + gpio_set_value(bd->pdata->reset, 0); + msleep(24); + gpio_set_value(bd->pdata->reset, 1); + } + + return 0; +} + +static int bd6107_backlight_check_fb(struct backlight_device *backlight, + struct fb_info *info) +{ + struct bd6107 *bd = bl_get_data(backlight); + + return bd->pdata->fbdev == NULL || bd->pdata->fbdev == info->dev; +} + +static const struct backlight_ops bd6107_backlight_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = bd6107_backlight_update_status, + .check_fb = bd6107_backlight_check_fb, +}; + +static int bd6107_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct bd6107_platform_data *pdata = dev_get_platdata(&client->dev); + struct backlight_device *backlight; + struct backlight_properties props; + struct bd6107 *bd; + int ret; + + if (pdata == NULL || !pdata->reset) { + dev_err(&client->dev, "No reset GPIO in platform data\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_warn(&client->dev, + "I2C adapter doesn't support I2C_FUNC_SMBUS_BYTE\n"); + return -EIO; + } + + bd = devm_kzalloc(&client->dev, sizeof(*bd), GFP_KERNEL); + if (!bd) + return -ENOMEM; + + bd->client = client; + bd->pdata = pdata; + + ret = devm_gpio_request_one(&client->dev, pdata->reset, + GPIOF_DIR_OUT | GPIOF_INIT_LOW, "reset"); + if (ret < 0) { + dev_err(&client->dev, "unable to request reset GPIO\n"); + return ret; + } + + memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; + props.max_brightness = 128; + props.brightness = clamp_t(unsigned int, pdata->def_value, 0, + props.max_brightness); + + backlight = devm_backlight_device_register(&client->dev, + dev_name(&client->dev), + &bd->client->dev, bd, + &bd6107_backlight_ops, &props); + if (IS_ERR(backlight)) { + dev_err(&client->dev, "failed to register backlight\n"); + return PTR_ERR(backlight); + } + + backlight_update_status(backlight); + i2c_set_clientdata(client, backlight); + + return 0; +} + +static int bd6107_remove(struct i2c_client *client) +{ + struct backlight_device *backlight = i2c_get_clientdata(client); + + backlight->props.brightness = 0; + backlight_update_status(backlight); + + return 0; +} + +static const struct i2c_device_id bd6107_ids[] = { + { "bd6107", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, bd6107_ids); + +static struct i2c_driver bd6107_driver = { + .driver = { + .name = "bd6107", + }, + .probe = bd6107_probe, + .remove = bd6107_remove, + .id_table = bd6107_ids, +}; + +module_i2c_driver(bd6107_driver); + +MODULE_DESCRIPTION("Rohm BD6107 Backlight Driver"); +MODULE_AUTHOR("Laurent Pinchart "); +MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/video/backlight/corgi_lcd.c b/kernel/drivers/video/backlight/corgi_lcd.c new file mode 100644 index 000000000..d7c37a8cc --- /dev/null +++ b/kernel/drivers/video/backlight/corgi_lcd.c @@ -0,0 +1,613 @@ +/* + * LCD/Backlight Driver for Sharp Zaurus Handhelds (various models) + * + * Copyright (c) 2004-2006 Richard Purdie + * + * Based on Sharp's 2.4 Backlight Driver + * + * Copyright (c) 2008 Marvell International Ltd. + * Converted to SPI device based LCD/Backlight device driver + * by Eric Miao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) + +/* Register Addresses */ +#define RESCTL_ADRS 0x00 +#define PHACTRL_ADRS 0x01 +#define DUTYCTRL_ADRS 0x02 +#define POWERREG0_ADRS 0x03 +#define POWERREG1_ADRS 0x04 +#define GPOR3_ADRS 0x05 +#define PICTRL_ADRS 0x06 +#define POLCTRL_ADRS 0x07 + +/* Register Bit Definitions */ +#define RESCTL_QVGA 0x01 +#define RESCTL_VGA 0x00 + +#define POWER1_VW_ON 0x01 /* VW Supply FET ON */ +#define POWER1_GVSS_ON 0x02 /* GVSS(-8V) Power Supply ON */ +#define POWER1_VDD_ON 0x04 /* VDD(8V),SVSS(-4V) Power Supply ON */ + +#define POWER1_VW_OFF 0x00 /* VW Supply FET OFF */ +#define POWER1_GVSS_OFF 0x00 /* GVSS(-8V) Power Supply OFF */ +#define POWER1_VDD_OFF 0x00 /* VDD(8V),SVSS(-4V) Power Supply OFF */ + +#define POWER0_COM_DCLK 0x01 /* COM Voltage DC Bias DAC Serial Data Clock */ +#define POWER0_COM_DOUT 0x02 /* COM Voltage DC Bias DAC Serial Data Out */ +#define POWER0_DAC_ON 0x04 /* DAC Power Supply ON */ +#define POWER0_COM_ON 0x08 /* COM Power Supply ON */ +#define POWER0_VCC5_ON 0x10 /* VCC5 Power Supply ON */ + +#define POWER0_DAC_OFF 0x00 /* DAC Power Supply OFF */ +#define POWER0_COM_OFF 0x00 /* COM Power Supply OFF */ +#define POWER0_VCC5_OFF 0x00 /* VCC5 Power Supply OFF */ + +#define PICTRL_INIT_STATE 0x01 +#define PICTRL_INIOFF 0x02 +#define PICTRL_POWER_DOWN 0x04 +#define PICTRL_COM_SIGNAL_OFF 0x08 +#define PICTRL_DAC_SIGNAL_OFF 0x10 + +#define POLCTRL_SYNC_POL_FALL 0x01 +#define POLCTRL_EN_POL_FALL 0x02 +#define POLCTRL_DATA_POL_FALL 0x04 +#define POLCTRL_SYNC_ACT_H 0x08 +#define POLCTRL_EN_ACT_L 0x10 + +#define POLCTRL_SYNC_POL_RISE 0x00 +#define POLCTRL_EN_POL_RISE 0x00 +#define POLCTRL_DATA_POL_RISE 0x00 +#define POLCTRL_SYNC_ACT_L 0x00 +#define POLCTRL_EN_ACT_H 0x00 + +#define PHACTRL_PHASE_MANUAL 0x01 +#define DEFAULT_PHAD_QVGA (9) +#define DEFAULT_COMADJ (125) + +struct corgi_lcd { + struct spi_device *spi_dev; + struct lcd_device *lcd_dev; + struct backlight_device *bl_dev; + + int limit_mask; + int intensity; + int power; + int mode; + char buf[2]; + + int gpio_backlight_on; + int gpio_backlight_cont; + int gpio_backlight_cont_inverted; + + void (*kick_battery)(void); +}; + +static int corgi_ssp_lcdtg_send(struct corgi_lcd *lcd, int reg, uint8_t val); + +static struct corgi_lcd *the_corgi_lcd; +static unsigned long corgibl_flags; +#define CORGIBL_SUSPENDED 0x01 +#define CORGIBL_BATTLOW 0x02 + +/* + * This is only a pseudo I2C interface. We can't use the standard kernel + * routines as the interface is write only. We just assume the data is acked... + */ +static void lcdtg_ssp_i2c_send(struct corgi_lcd *lcd, uint8_t data) +{ + corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS, data); + udelay(10); +} + +static void lcdtg_i2c_send_bit(struct corgi_lcd *lcd, uint8_t data) +{ + lcdtg_ssp_i2c_send(lcd, data); + lcdtg_ssp_i2c_send(lcd, data | POWER0_COM_DCLK); + lcdtg_ssp_i2c_send(lcd, data); +} + +static void lcdtg_i2c_send_start(struct corgi_lcd *lcd, uint8_t base) +{ + lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK | POWER0_COM_DOUT); + lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK); + lcdtg_ssp_i2c_send(lcd, base); +} + +static void lcdtg_i2c_send_stop(struct corgi_lcd *lcd, uint8_t base) +{ + lcdtg_ssp_i2c_send(lcd, base); + lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK); + lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK | POWER0_COM_DOUT); +} + +static void lcdtg_i2c_send_byte(struct corgi_lcd *lcd, + uint8_t base, uint8_t data) +{ + int i; + + for (i = 0; i < 8; i++) { + if (data & 0x80) + lcdtg_i2c_send_bit(lcd, base | POWER0_COM_DOUT); + else + lcdtg_i2c_send_bit(lcd, base); + data <<= 1; + } +} + +static void lcdtg_i2c_wait_ack(struct corgi_lcd *lcd, uint8_t base) +{ + lcdtg_i2c_send_bit(lcd, base); +} + +static void lcdtg_set_common_voltage(struct corgi_lcd *lcd, + uint8_t base_data, uint8_t data) +{ + /* Set Common Voltage to M62332FP via I2C */ + lcdtg_i2c_send_start(lcd, base_data); + lcdtg_i2c_send_byte(lcd, base_data, 0x9c); + lcdtg_i2c_wait_ack(lcd, base_data); + lcdtg_i2c_send_byte(lcd, base_data, 0x00); + lcdtg_i2c_wait_ack(lcd, base_data); + lcdtg_i2c_send_byte(lcd, base_data, data); + lcdtg_i2c_wait_ack(lcd, base_data); + lcdtg_i2c_send_stop(lcd, base_data); +} + +static int corgi_ssp_lcdtg_send(struct corgi_lcd *lcd, int adrs, uint8_t data) +{ + struct spi_message msg; + struct spi_transfer xfer = { + .len = 1, + .cs_change = 1, + .tx_buf = lcd->buf, + }; + + lcd->buf[0] = ((adrs & 0x07) << 5) | (data & 0x1f); + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + + return spi_sync(lcd->spi_dev, &msg); +} + +/* Set Phase Adjust */ +static void lcdtg_set_phadadj(struct corgi_lcd *lcd, int mode) +{ + int adj; + + switch (mode) { + case CORGI_LCD_MODE_VGA: + /* Setting for VGA */ + adj = sharpsl_param.phadadj; + adj = (adj < 0) ? PHACTRL_PHASE_MANUAL : + PHACTRL_PHASE_MANUAL | ((adj & 0xf) << 1); + break; + case CORGI_LCD_MODE_QVGA: + default: + /* Setting for QVGA */ + adj = (DEFAULT_PHAD_QVGA << 1) | PHACTRL_PHASE_MANUAL; + break; + } + + corgi_ssp_lcdtg_send(lcd, PHACTRL_ADRS, adj); +} + +static void corgi_lcd_power_on(struct corgi_lcd *lcd) +{ + int comadj; + + /* Initialize Internal Logic & Port */ + corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, + PICTRL_POWER_DOWN | PICTRL_INIOFF | + PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF | + PICTRL_DAC_SIGNAL_OFF); + + corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS, + POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF | + POWER0_COM_OFF | POWER0_VCC5_OFF); + + corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS, + POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF); + + /* VDD(+8V), SVSS(-4V) ON */ + corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS, + POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON); + mdelay(3); + + /* DAC ON */ + corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS, + POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON | + POWER0_COM_OFF | POWER0_VCC5_OFF); + + /* INIB = H, INI = L */ + /* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */ + corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, + PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF); + + /* Set Common Voltage */ + comadj = sharpsl_param.comadj; + if (comadj < 0) + comadj = DEFAULT_COMADJ; + + lcdtg_set_common_voltage(lcd, POWER0_DAC_ON | POWER0_COM_OFF | + POWER0_VCC5_OFF, comadj); + + /* VCC5 ON, DAC ON */ + corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS, + POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON | + POWER0_COM_OFF | POWER0_VCC5_ON); + + /* GVSS(-8V) ON, VDD ON */ + corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS, + POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON); + mdelay(2); + + /* COM SIGNAL ON (PICTL[3] = L) */ + corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, PICTRL_INIT_STATE); + + /* COM ON, DAC ON, VCC5_ON */ + corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS, + POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON | + POWER0_COM_ON | POWER0_VCC5_ON); + + /* VW ON, GVSS ON, VDD ON */ + corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS, + POWER1_VW_ON | POWER1_GVSS_ON | POWER1_VDD_ON); + + /* Signals output enable */ + corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, 0); + + /* Set Phase Adjust */ + lcdtg_set_phadadj(lcd, lcd->mode); + + /* Initialize for Input Signals from ATI */ + corgi_ssp_lcdtg_send(lcd, POLCTRL_ADRS, + POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE | + POLCTRL_DATA_POL_RISE | POLCTRL_SYNC_ACT_L | + POLCTRL_EN_ACT_H); + udelay(1000); + + switch (lcd->mode) { + case CORGI_LCD_MODE_VGA: + corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_VGA); + break; + case CORGI_LCD_MODE_QVGA: + default: + corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_QVGA); + break; + } +} + +static void corgi_lcd_power_off(struct corgi_lcd *lcd) +{ + /* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */ + msleep(34); + + /* (1)VW OFF */ + corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS, + POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON); + + /* (2)COM OFF */ + corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF); + corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS, + POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON); + + /* (3)Set Common Voltage Bias 0V */ + lcdtg_set_common_voltage(lcd, POWER0_DAC_ON | POWER0_COM_OFF | + POWER0_VCC5_ON, 0); + + /* (4)GVSS OFF */ + corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS, + POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON); + + /* (5)VCC5 OFF */ + corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS, + POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF); + + /* (6)Set PDWN, INIOFF, DACOFF */ + corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, + PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF | + PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF); + + /* (7)DAC OFF */ + corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS, + POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF); + + /* (8)VDD OFF */ + corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS, + POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF); +} + +static int corgi_lcd_set_mode(struct lcd_device *ld, struct fb_videomode *m) +{ + struct corgi_lcd *lcd = lcd_get_data(ld); + int mode = CORGI_LCD_MODE_QVGA; + + if (m->xres == 640 || m->xres == 480) + mode = CORGI_LCD_MODE_VGA; + + if (lcd->mode == mode) + return 0; + + lcdtg_set_phadadj(lcd, mode); + + switch (mode) { + case CORGI_LCD_MODE_VGA: + corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_VGA); + break; + case CORGI_LCD_MODE_QVGA: + default: + corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_QVGA); + break; + } + + lcd->mode = mode; + return 0; +} + +static int corgi_lcd_set_power(struct lcd_device *ld, int power) +{ + struct corgi_lcd *lcd = lcd_get_data(ld); + + if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) + corgi_lcd_power_on(lcd); + + if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) + corgi_lcd_power_off(lcd); + + lcd->power = power; + return 0; +} + +static int corgi_lcd_get_power(struct lcd_device *ld) +{ + struct corgi_lcd *lcd = lcd_get_data(ld); + + return lcd->power; +} + +static struct lcd_ops corgi_lcd_ops = { + .get_power = corgi_lcd_get_power, + .set_power = corgi_lcd_set_power, + .set_mode = corgi_lcd_set_mode, +}; + +static int corgi_bl_get_intensity(struct backlight_device *bd) +{ + struct corgi_lcd *lcd = bl_get_data(bd); + + return lcd->intensity; +} + +static int corgi_bl_set_intensity(struct corgi_lcd *lcd, int intensity) +{ + int cont; + + if (intensity > 0x10) + intensity += 0x10; + + corgi_ssp_lcdtg_send(lcd, DUTYCTRL_ADRS, intensity); + + /* Bit 5 via GPIO_BACKLIGHT_CONT */ + cont = !!(intensity & 0x20) ^ lcd->gpio_backlight_cont_inverted; + + if (gpio_is_valid(lcd->gpio_backlight_cont)) + gpio_set_value_cansleep(lcd->gpio_backlight_cont, cont); + + if (gpio_is_valid(lcd->gpio_backlight_on)) + gpio_set_value_cansleep(lcd->gpio_backlight_on, intensity); + + if (lcd->kick_battery) + lcd->kick_battery(); + + lcd->intensity = intensity; + return 0; +} + +static int corgi_bl_update_status(struct backlight_device *bd) +{ + struct corgi_lcd *lcd = bl_get_data(bd); + int intensity = bd->props.brightness; + + if (bd->props.power != FB_BLANK_UNBLANK) + intensity = 0; + + if (bd->props.fb_blank != FB_BLANK_UNBLANK) + intensity = 0; + + if (corgibl_flags & CORGIBL_SUSPENDED) + intensity = 0; + + if ((corgibl_flags & CORGIBL_BATTLOW) && intensity > lcd->limit_mask) + intensity = lcd->limit_mask; + + return corgi_bl_set_intensity(lcd, intensity); +} + +void corgi_lcd_limit_intensity(int limit) +{ + if (limit) + corgibl_flags |= CORGIBL_BATTLOW; + else + corgibl_flags &= ~CORGIBL_BATTLOW; + + backlight_update_status(the_corgi_lcd->bl_dev); +} +EXPORT_SYMBOL(corgi_lcd_limit_intensity); + +static const struct backlight_ops corgi_bl_ops = { + .get_brightness = corgi_bl_get_intensity, + .update_status = corgi_bl_update_status, +}; + +#ifdef CONFIG_PM_SLEEP +static int corgi_lcd_suspend(struct device *dev) +{ + struct corgi_lcd *lcd = dev_get_drvdata(dev); + + corgibl_flags |= CORGIBL_SUSPENDED; + corgi_bl_set_intensity(lcd, 0); + corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN); + return 0; +} + +static int corgi_lcd_resume(struct device *dev) +{ + struct corgi_lcd *lcd = dev_get_drvdata(dev); + + corgibl_flags &= ~CORGIBL_SUSPENDED; + corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK); + backlight_update_status(lcd->bl_dev); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(corgi_lcd_pm_ops, corgi_lcd_suspend, corgi_lcd_resume); + +static int setup_gpio_backlight(struct corgi_lcd *lcd, + struct corgi_lcd_platform_data *pdata) +{ + struct spi_device *spi = lcd->spi_dev; + int err; + + lcd->gpio_backlight_on = -1; + lcd->gpio_backlight_cont = -1; + + if (gpio_is_valid(pdata->gpio_backlight_on)) { + err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_on, + "BL_ON"); + if (err) { + dev_err(&spi->dev, + "failed to request GPIO%d for backlight_on\n", + pdata->gpio_backlight_on); + return err; + } + + lcd->gpio_backlight_on = pdata->gpio_backlight_on; + gpio_direction_output(lcd->gpio_backlight_on, 0); + } + + if (gpio_is_valid(pdata->gpio_backlight_cont)) { + err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_cont, + "BL_CONT"); + if (err) { + dev_err(&spi->dev, + "failed to request GPIO%d for backlight_cont\n", + pdata->gpio_backlight_cont); + return err; + } + + lcd->gpio_backlight_cont = pdata->gpio_backlight_cont; + + /* spitz and akita use both GPIOs for backlight, and + * have inverted polarity of GPIO_BACKLIGHT_CONT + */ + if (gpio_is_valid(lcd->gpio_backlight_on)) { + lcd->gpio_backlight_cont_inverted = 1; + gpio_direction_output(lcd->gpio_backlight_cont, 1); + } else { + lcd->gpio_backlight_cont_inverted = 0; + gpio_direction_output(lcd->gpio_backlight_cont, 0); + } + } + return 0; +} + +static int corgi_lcd_probe(struct spi_device *spi) +{ + struct backlight_properties props; + struct corgi_lcd_platform_data *pdata = dev_get_platdata(&spi->dev); + struct corgi_lcd *lcd; + int ret = 0; + + if (pdata == NULL) { + dev_err(&spi->dev, "platform data not available\n"); + return -EINVAL; + } + + lcd = devm_kzalloc(&spi->dev, sizeof(struct corgi_lcd), GFP_KERNEL); + if (!lcd) + return -ENOMEM; + + lcd->spi_dev = spi; + + lcd->lcd_dev = devm_lcd_device_register(&spi->dev, "corgi_lcd", + &spi->dev, lcd, &corgi_lcd_ops); + if (IS_ERR(lcd->lcd_dev)) + return PTR_ERR(lcd->lcd_dev); + + lcd->power = FB_BLANK_POWERDOWN; + lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA; + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; + props.max_brightness = pdata->max_intensity; + lcd->bl_dev = devm_backlight_device_register(&spi->dev, "corgi_bl", + &spi->dev, lcd, &corgi_bl_ops, + &props); + if (IS_ERR(lcd->bl_dev)) + return PTR_ERR(lcd->bl_dev); + + lcd->bl_dev->props.brightness = pdata->default_intensity; + lcd->bl_dev->props.power = FB_BLANK_UNBLANK; + + ret = setup_gpio_backlight(lcd, pdata); + if (ret) + return ret; + + lcd->kick_battery = pdata->kick_battery; + + spi_set_drvdata(spi, lcd); + corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK); + backlight_update_status(lcd->bl_dev); + + lcd->limit_mask = pdata->limit_mask; + the_corgi_lcd = lcd; + return 0; +} + +static int corgi_lcd_remove(struct spi_device *spi) +{ + struct corgi_lcd *lcd = spi_get_drvdata(spi); + + lcd->bl_dev->props.power = FB_BLANK_UNBLANK; + lcd->bl_dev->props.brightness = 0; + backlight_update_status(lcd->bl_dev); + corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN); + return 0; +} + +static struct spi_driver corgi_lcd_driver = { + .driver = { + .name = "corgi-lcd", + .owner = THIS_MODULE, + .pm = &corgi_lcd_pm_ops, + }, + .probe = corgi_lcd_probe, + .remove = corgi_lcd_remove, +}; + +module_spi_driver(corgi_lcd_driver); + +MODULE_DESCRIPTION("LCD and backlight driver for SHARP C7x0/Cxx00"); +MODULE_AUTHOR("Eric Miao "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:corgi-lcd"); diff --git a/kernel/drivers/video/backlight/cr_bllcd.c b/kernel/drivers/video/backlight/cr_bllcd.c new file mode 100644 index 000000000..3e3880fc8 --- /dev/null +++ b/kernel/drivers/video/backlight/cr_bllcd.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * This file is part of the Carillo Ranch video subsystem driver. + * The Carillo Ranch video subsystem driver is free software; + * you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The Carillo Ranch video subsystem driver is distributed + * in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this driver; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Thomas Hellstrom + * Alan Hourihane + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The LVDS- and panel power controls sits on the + * GPIO port of the ISA bridge. + */ + +#define CRVML_DEVICE_LPC 0x27B8 +#define CRVML_REG_GPIOBAR 0x48 +#define CRVML_REG_GPIOEN 0x4C +#define CRVML_GPIOEN_BIT (1 << 4) +#define CRVML_PANEL_PORT 0x38 +#define CRVML_LVDS_ON 0x00000001 +#define CRVML_PANEL_ON 0x00000002 +#define CRVML_BACKLIGHT_OFF 0x00000004 + +/* The PLL Clock register sits on Host bridge */ +#define CRVML_DEVICE_MCH 0x5001 +#define CRVML_REG_MCHBAR 0x44 +#define CRVML_REG_MCHEN 0x54 +#define CRVML_MCHEN_BIT (1 << 28) +#define CRVML_MCHMAP_SIZE 4096 +#define CRVML_REG_CLOCK 0xc3c +#define CRVML_CLOCK_SHIFT 8 +#define CRVML_CLOCK_MASK 0x00000f00 + +static struct pci_dev *lpc_dev; +static u32 gpio_bar; + +struct cr_panel { + struct backlight_device *cr_backlight_device; + struct lcd_device *cr_lcd_device; +}; + +static int cr_backlight_set_intensity(struct backlight_device *bd) +{ + int intensity = bd->props.brightness; + u32 addr = gpio_bar + CRVML_PANEL_PORT; + u32 cur = inl(addr); + + if (bd->props.power == FB_BLANK_UNBLANK) + intensity = FB_BLANK_UNBLANK; + if (bd->props.fb_blank == FB_BLANK_UNBLANK) + intensity = FB_BLANK_UNBLANK; + if (bd->props.power == FB_BLANK_POWERDOWN) + intensity = FB_BLANK_POWERDOWN; + if (bd->props.fb_blank == FB_BLANK_POWERDOWN) + intensity = FB_BLANK_POWERDOWN; + + if (intensity == FB_BLANK_UNBLANK) { /* FULL ON */ + cur &= ~CRVML_BACKLIGHT_OFF; + outl(cur, addr); + } else if (intensity == FB_BLANK_POWERDOWN) { /* OFF */ + cur |= CRVML_BACKLIGHT_OFF; + outl(cur, addr); + } /* anything else, don't bother */ + + return 0; +} + +static int cr_backlight_get_intensity(struct backlight_device *bd) +{ + u32 addr = gpio_bar + CRVML_PANEL_PORT; + u32 cur = inl(addr); + u8 intensity; + + if (cur & CRVML_BACKLIGHT_OFF) + intensity = FB_BLANK_POWERDOWN; + else + intensity = FB_BLANK_UNBLANK; + + return intensity; +} + +static const struct backlight_ops cr_backlight_ops = { + .get_brightness = cr_backlight_get_intensity, + .update_status = cr_backlight_set_intensity, +}; + +static void cr_panel_on(void) +{ + u32 addr = gpio_bar + CRVML_PANEL_PORT; + u32 cur = inl(addr); + + if (!(cur & CRVML_PANEL_ON)) { + /* Make sure LVDS controller is down. */ + if (cur & 0x00000001) { + cur &= ~CRVML_LVDS_ON; + outl(cur, addr); + } + /* Power up Panel */ + schedule_timeout(HZ / 10); + cur |= CRVML_PANEL_ON; + outl(cur, addr); + } + + /* Power up LVDS controller */ + + if (!(cur & CRVML_LVDS_ON)) { + schedule_timeout(HZ / 10); + outl(cur | CRVML_LVDS_ON, addr); + } +} + +static void cr_panel_off(void) +{ + u32 addr = gpio_bar + CRVML_PANEL_PORT; + u32 cur = inl(addr); + + /* Power down LVDS controller first to avoid high currents */ + if (cur & CRVML_LVDS_ON) { + cur &= ~CRVML_LVDS_ON; + outl(cur, addr); + } + if (cur & CRVML_PANEL_ON) { + schedule_timeout(HZ / 10); + outl(cur & ~CRVML_PANEL_ON, addr); + } +} + +static int cr_lcd_set_power(struct lcd_device *ld, int power) +{ + if (power == FB_BLANK_UNBLANK) + cr_panel_on(); + if (power == FB_BLANK_POWERDOWN) + cr_panel_off(); + + return 0; +} + +static struct lcd_ops cr_lcd_ops = { + .set_power = cr_lcd_set_power, +}; + +static int cr_backlight_probe(struct platform_device *pdev) +{ + struct backlight_properties props; + struct backlight_device *bdp; + struct lcd_device *ldp; + struct cr_panel *crp; + u8 dev_en; + + lpc_dev = pci_get_device(PCI_VENDOR_ID_INTEL, + CRVML_DEVICE_LPC, NULL); + if (!lpc_dev) { + pr_err("INTEL CARILLO RANCH LPC not found.\n"); + return -ENODEV; + } + + pci_read_config_byte(lpc_dev, CRVML_REG_GPIOEN, &dev_en); + if (!(dev_en & CRVML_GPIOEN_BIT)) { + pr_err("Carillo Ranch GPIO device was not enabled.\n"); + pci_dev_put(lpc_dev); + return -ENODEV; + } + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; + bdp = devm_backlight_device_register(&pdev->dev, "cr-backlight", + &pdev->dev, NULL, &cr_backlight_ops, + &props); + if (IS_ERR(bdp)) { + pci_dev_put(lpc_dev); + return PTR_ERR(bdp); + } + + ldp = devm_lcd_device_register(&pdev->dev, "cr-lcd", &pdev->dev, NULL, + &cr_lcd_ops); + if (IS_ERR(ldp)) { + pci_dev_put(lpc_dev); + return PTR_ERR(ldp); + } + + pci_read_config_dword(lpc_dev, CRVML_REG_GPIOBAR, + &gpio_bar); + gpio_bar &= ~0x3F; + + crp = devm_kzalloc(&pdev->dev, sizeof(*crp), GFP_KERNEL); + if (!crp) { + pci_dev_put(lpc_dev); + return -ENOMEM; + } + + crp->cr_backlight_device = bdp; + crp->cr_lcd_device = ldp; + crp->cr_backlight_device->props.power = FB_BLANK_UNBLANK; + crp->cr_backlight_device->props.brightness = 0; + cr_backlight_set_intensity(crp->cr_backlight_device); + cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_UNBLANK); + + platform_set_drvdata(pdev, crp); + + return 0; +} + +static int cr_backlight_remove(struct platform_device *pdev) +{ + struct cr_panel *crp = platform_get_drvdata(pdev); + + crp->cr_backlight_device->props.power = FB_BLANK_POWERDOWN; + crp->cr_backlight_device->props.brightness = 0; + crp->cr_backlight_device->props.max_brightness = 0; + cr_backlight_set_intensity(crp->cr_backlight_device); + cr_lcd_set_power(crp->cr_lcd_device, FB_BLANK_POWERDOWN); + pci_dev_put(lpc_dev); + + return 0; +} + +static struct platform_driver cr_backlight_driver = { + .probe = cr_backlight_probe, + .remove = cr_backlight_remove, + .driver = { + .name = "cr_backlight", + }, +}; + +static struct platform_device *crp; + +static int __init cr_backlight_init(void) +{ + int ret = platform_driver_register(&cr_backlight_driver); + + if (ret) + return ret; + + crp = platform_device_register_simple("cr_backlight", -1, NULL, 0); + if (IS_ERR(crp)) { + platform_driver_unregister(&cr_backlight_driver); + return PTR_ERR(crp); + } + + pr_info("Carillo Ranch Backlight Driver Initialized.\n"); + + return 0; +} + +static void __exit cr_backlight_exit(void) +{ + platform_device_unregister(crp); + platform_driver_unregister(&cr_backlight_driver); +} + +module_init(cr_backlight_init); +module_exit(cr_backlight_exit); + +MODULE_AUTHOR("Tungsten Graphics Inc."); +MODULE_DESCRIPTION("Carillo Ranch Backlight Driver"); +MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/video/backlight/da903x_bl.c b/kernel/drivers/video/backlight/da903x_bl.c new file mode 100644 index 000000000..f793738f0 --- /dev/null +++ b/kernel/drivers/video/backlight/da903x_bl.c @@ -0,0 +1,175 @@ +/* + * Backlight driver for Dialog Semiconductor DA9030/DA9034 + * + * Copyright (C) 2008 Compulab, Ltd. + * Mike Rapoport + * + * Copyright (C) 2006-2008 Marvell International Ltd. + * Eric Miao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DA9030_WLED_CONTROL 0x25 +#define DA9030_WLED_CP_EN (1 << 6) +#define DA9030_WLED_TRIM(x) ((x) & 0x7) + +#define DA9034_WLED_CONTROL1 0x3C +#define DA9034_WLED_CONTROL2 0x3D +#define DA9034_WLED_ISET(x) ((x) & 0x1f) + +#define DA9034_WLED_BOOST_EN (1 << 5) + +#define DA9030_MAX_BRIGHTNESS 7 +#define DA9034_MAX_BRIGHTNESS 0x7f + +struct da903x_backlight_data { + struct device *da903x_dev; + int id; + int current_brightness; +}; + +static int da903x_backlight_set(struct backlight_device *bl, int brightness) +{ + struct da903x_backlight_data *data = bl_get_data(bl); + struct device *dev = data->da903x_dev; + uint8_t val; + int ret = 0; + + switch (data->id) { + case DA9034_ID_WLED: + ret = da903x_update(dev, DA9034_WLED_CONTROL1, + brightness, 0x7f); + if (ret) + return ret; + + if (data->current_brightness && brightness == 0) + ret = da903x_clr_bits(dev, + DA9034_WLED_CONTROL2, + DA9034_WLED_BOOST_EN); + + if (data->current_brightness == 0 && brightness) + ret = da903x_set_bits(dev, + DA9034_WLED_CONTROL2, + DA9034_WLED_BOOST_EN); + break; + case DA9030_ID_WLED: + val = DA9030_WLED_TRIM(brightness); + val |= brightness ? DA9030_WLED_CP_EN : 0; + ret = da903x_write(dev, DA9030_WLED_CONTROL, val); + break; + } + + if (ret) + return ret; + + data->current_brightness = brightness; + return 0; +} + +static int da903x_backlight_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + + if (bl->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.state & BL_CORE_SUSPENDED) + brightness = 0; + + return da903x_backlight_set(bl, brightness); +} + +static int da903x_backlight_get_brightness(struct backlight_device *bl) +{ + struct da903x_backlight_data *data = bl_get_data(bl); + + return data->current_brightness; +} + +static const struct backlight_ops da903x_backlight_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = da903x_backlight_update_status, + .get_brightness = da903x_backlight_get_brightness, +}; + +static int da903x_backlight_probe(struct platform_device *pdev) +{ + struct da9034_backlight_pdata *pdata = dev_get_platdata(&pdev->dev); + struct da903x_backlight_data *data; + struct backlight_device *bl; + struct backlight_properties props; + int max_brightness; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + switch (pdev->id) { + case DA9030_ID_WLED: + max_brightness = DA9030_MAX_BRIGHTNESS; + break; + case DA9034_ID_WLED: + max_brightness = DA9034_MAX_BRIGHTNESS; + break; + default: + dev_err(&pdev->dev, "invalid backlight device ID(%d)\n", + pdev->id); + return -EINVAL; + } + + data->id = pdev->id; + data->da903x_dev = pdev->dev.parent; + data->current_brightness = 0; + + /* adjust the WLED output current */ + if (pdata) + da903x_write(data->da903x_dev, DA9034_WLED_CONTROL2, + DA9034_WLED_ISET(pdata->output_current)); + + memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; + props.max_brightness = max_brightness; + bl = devm_backlight_device_register(&pdev->dev, pdev->name, + data->da903x_dev, data, + &da903x_backlight_ops, &props); + if (IS_ERR(bl)) { + dev_err(&pdev->dev, "failed to register backlight\n"); + return PTR_ERR(bl); + } + + bl->props.brightness = max_brightness; + + platform_set_drvdata(pdev, bl); + backlight_update_status(bl); + return 0; +} + +static struct platform_driver da903x_backlight_driver = { + .driver = { + .name = "da903x-backlight", + }, + .probe = da903x_backlight_probe, +}; + +module_platform_driver(da903x_backlight_driver); + +MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034"); +MODULE_AUTHOR("Eric Miao "); +MODULE_AUTHOR("Mike Rapoport "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:da903x-backlight"); diff --git a/kernel/drivers/video/backlight/da9052_bl.c b/kernel/drivers/video/backlight/da9052_bl.c new file mode 100644 index 000000000..b1943e773 --- /dev/null +++ b/kernel/drivers/video/backlight/da9052_bl.c @@ -0,0 +1,185 @@ +/* + * Backlight Driver for Dialog DA9052 PMICs + * + * Copyright(c) 2012 Dialog Semiconductor Ltd. + * + * Author: David Dajun Chen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define DA9052_MAX_BRIGHTNESS 0xFF + +enum { + DA9052_WLEDS_OFF, + DA9052_WLEDS_ON, +}; + +enum { + DA9052_TYPE_WLED1, + DA9052_TYPE_WLED2, + DA9052_TYPE_WLED3, +}; + +static const unsigned char wled_bank[] = { + DA9052_LED1_CONF_REG, + DA9052_LED2_CONF_REG, + DA9052_LED3_CONF_REG, +}; + +struct da9052_bl { + struct da9052 *da9052; + uint brightness; + uint state; + uint led_reg; +}; + +static int da9052_adjust_wled_brightness(struct da9052_bl *wleds) +{ + unsigned char boost_en; + unsigned char i_sink; + int ret; + + boost_en = 0x3F; + i_sink = 0xFF; + if (wleds->state == DA9052_WLEDS_OFF) { + boost_en = 0x00; + i_sink = 0x00; + } + + ret = da9052_reg_write(wleds->da9052, DA9052_BOOST_REG, boost_en); + if (ret < 0) + return ret; + + ret = da9052_reg_write(wleds->da9052, DA9052_LED_CONT_REG, i_sink); + if (ret < 0) + return ret; + + ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg], 0x0); + if (ret < 0) + return ret; + + usleep_range(10000, 11000); + + if (wleds->brightness) { + ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg], + wleds->brightness); + if (ret < 0) + return ret; + } + + return 0; +} + +static int da9052_backlight_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + struct da9052_bl *wleds = bl_get_data(bl); + + wleds->brightness = brightness; + wleds->state = DA9052_WLEDS_ON; + + return da9052_adjust_wled_brightness(wleds); +} + +static int da9052_backlight_get_brightness(struct backlight_device *bl) +{ + struct da9052_bl *wleds = bl_get_data(bl); + + return wleds->brightness; +} + +static const struct backlight_ops da9052_backlight_ops = { + .update_status = da9052_backlight_update_status, + .get_brightness = da9052_backlight_get_brightness, +}; + +static int da9052_backlight_probe(struct platform_device *pdev) +{ + struct backlight_device *bl; + struct backlight_properties props; + struct da9052_bl *wleds; + + wleds = devm_kzalloc(&pdev->dev, sizeof(struct da9052_bl), GFP_KERNEL); + if (!wleds) + return -ENOMEM; + + wleds->da9052 = dev_get_drvdata(pdev->dev.parent); + wleds->brightness = 0; + wleds->led_reg = platform_get_device_id(pdev)->driver_data; + wleds->state = DA9052_WLEDS_OFF; + + props.type = BACKLIGHT_RAW; + props.max_brightness = DA9052_MAX_BRIGHTNESS; + + bl = devm_backlight_device_register(&pdev->dev, pdev->name, + wleds->da9052->dev, wleds, + &da9052_backlight_ops, &props); + if (IS_ERR(bl)) { + dev_err(&pdev->dev, "Failed to register backlight\n"); + return PTR_ERR(bl); + } + + bl->props.max_brightness = DA9052_MAX_BRIGHTNESS; + bl->props.brightness = 0; + platform_set_drvdata(pdev, bl); + + return da9052_adjust_wled_brightness(wleds); +} + +static int da9052_backlight_remove(struct platform_device *pdev) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + struct da9052_bl *wleds = bl_get_data(bl); + + wleds->brightness = 0; + wleds->state = DA9052_WLEDS_OFF; + da9052_adjust_wled_brightness(wleds); + + return 0; +} + +static struct platform_device_id da9052_wled_ids[] = { + { + .name = "da9052-wled1", + .driver_data = DA9052_TYPE_WLED1, + }, + { + .name = "da9052-wled2", + .driver_data = DA9052_TYPE_WLED2, + }, + { + .name = "da9052-wled3", + .driver_data = DA9052_TYPE_WLED3, + }, + { }, +}; + +static struct platform_driver da9052_wled_driver = { + .probe = da9052_backlight_probe, + .remove = da9052_backlight_remove, + .id_table = da9052_wled_ids, + .driver = { + .name = "da9052-wled", + }, +}; + +module_platform_driver(da9052_wled_driver); + +MODULE_AUTHOR("David Dajun Chen "); +MODULE_DESCRIPTION("Backlight driver for DA9052 PMIC"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:da9052-backlight"); diff --git a/kernel/drivers/video/backlight/ep93xx_bl.c b/kernel/drivers/video/backlight/ep93xx_bl.c new file mode 100644 index 000000000..006793182 --- /dev/null +++ b/kernel/drivers/video/backlight/ep93xx_bl.c @@ -0,0 +1,141 @@ +/* + * Driver for the Cirrus EP93xx lcd backlight + * + * Copyright (c) 2010 H Hartley Sweeten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This driver controls the pulse width modulated brightness control output, + * BRIGHT, on the Cirrus EP9307, EP9312, and EP9315 processors. + */ + +#include +#include +#include +#include +#include + +#define EP93XX_MAX_COUNT 255 +#define EP93XX_MAX_BRIGHT 255 +#define EP93XX_DEF_BRIGHT 128 + +struct ep93xxbl { + void __iomem *mmio; + int brightness; +}; + +static int ep93xxbl_set(struct backlight_device *bl, int brightness) +{ + struct ep93xxbl *ep93xxbl = bl_get_data(bl); + + writel((brightness << 8) | EP93XX_MAX_COUNT, ep93xxbl->mmio); + + ep93xxbl->brightness = brightness; + + return 0; +} + +static int ep93xxbl_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + + if (bl->props.power != FB_BLANK_UNBLANK || + bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + return ep93xxbl_set(bl, brightness); +} + +static int ep93xxbl_get_brightness(struct backlight_device *bl) +{ + struct ep93xxbl *ep93xxbl = bl_get_data(bl); + + return ep93xxbl->brightness; +} + +static const struct backlight_ops ep93xxbl_ops = { + .update_status = ep93xxbl_update_status, + .get_brightness = ep93xxbl_get_brightness, +}; + +static int ep93xxbl_probe(struct platform_device *dev) +{ + struct ep93xxbl *ep93xxbl; + struct backlight_device *bl; + struct backlight_properties props; + struct resource *res; + + ep93xxbl = devm_kzalloc(&dev->dev, sizeof(*ep93xxbl), GFP_KERNEL); + if (!ep93xxbl) + return -ENOMEM; + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!res) + return -ENXIO; + + /* + * FIXME - We don't do a request_mem_region here because we are + * sharing the register space with the framebuffer driver (see + * drivers/video/ep93xx-fb.c) and doing so will cause the second + * loaded driver to return -EBUSY. + * + * NOTE: No locking is required; the framebuffer does not touch + * this register. + */ + ep93xxbl->mmio = devm_ioremap(&dev->dev, res->start, + resource_size(res)); + if (!ep93xxbl->mmio) + return -ENXIO; + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; + props.max_brightness = EP93XX_MAX_BRIGHT; + bl = devm_backlight_device_register(&dev->dev, dev->name, &dev->dev, + ep93xxbl, &ep93xxbl_ops, &props); + if (IS_ERR(bl)) + return PTR_ERR(bl); + + bl->props.brightness = EP93XX_DEF_BRIGHT; + + platform_set_drvdata(dev, bl); + + ep93xxbl_update_status(bl); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int ep93xxbl_suspend(struct device *dev) +{ + struct backlight_device *bl = dev_get_drvdata(dev); + + return ep93xxbl_set(bl, 0); +} + +static int ep93xxbl_resume(struct device *dev) +{ + struct backlight_device *bl = dev_get_drvdata(dev); + + backlight_update_status(bl); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(ep93xxbl_pm_ops, ep93xxbl_suspend, ep93xxbl_resume); + +static struct platform_driver ep93xxbl_driver = { + .driver = { + .name = "ep93xx-bl", + .pm = &ep93xxbl_pm_ops, + }, + .probe = ep93xxbl_probe, +}; + +module_platform_driver(ep93xxbl_driver); + +MODULE_DESCRIPTION("EP93xx Backlight Driver"); +MODULE_AUTHOR("H Hartley Sweeten "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ep93xx-bl"); diff --git a/kernel/drivers/video/backlight/generic_bl.c b/kernel/drivers/video/backlight/generic_bl.c new file mode 100644 index 000000000..67dfb939a --- /dev/null +++ b/kernel/drivers/video/backlight/generic_bl.c @@ -0,0 +1,119 @@ +/* + * Generic Backlight Driver + * + * Copyright (c) 2004-2008 Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +static int genericbl_intensity; +static struct backlight_device *generic_backlight_device; +static struct generic_bl_info *bl_machinfo; + +/* Flag to signal when the battery is low */ +#define GENERICBL_BATTLOW BL_CORE_DRIVER1 + +static int genericbl_send_intensity(struct backlight_device *bd) +{ + int intensity = bd->props.brightness; + + if (bd->props.power != FB_BLANK_UNBLANK) + intensity = 0; + if (bd->props.state & BL_CORE_FBBLANK) + intensity = 0; + if (bd->props.state & BL_CORE_SUSPENDED) + intensity = 0; + if (bd->props.state & GENERICBL_BATTLOW) + intensity &= bl_machinfo->limit_mask; + + bl_machinfo->set_bl_intensity(intensity); + + genericbl_intensity = intensity; + + if (bl_machinfo->kick_battery) + bl_machinfo->kick_battery(); + + return 0; +} + +static int genericbl_get_intensity(struct backlight_device *bd) +{ + return genericbl_intensity; +} + +static const struct backlight_ops genericbl_ops = { + .options = BL_CORE_SUSPENDRESUME, + .get_brightness = genericbl_get_intensity, + .update_status = genericbl_send_intensity, +}; + +static int genericbl_probe(struct platform_device *pdev) +{ + struct backlight_properties props; + struct generic_bl_info *machinfo = dev_get_platdata(&pdev->dev); + const char *name = "generic-bl"; + struct backlight_device *bd; + + bl_machinfo = machinfo; + if (!machinfo->limit_mask) + machinfo->limit_mask = -1; + + if (machinfo->name) + name = machinfo->name; + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; + props.max_brightness = machinfo->max_intensity; + bd = devm_backlight_device_register(&pdev->dev, name, &pdev->dev, + NULL, &genericbl_ops, &props); + if (IS_ERR(bd)) + return PTR_ERR(bd); + + platform_set_drvdata(pdev, bd); + + bd->props.power = FB_BLANK_UNBLANK; + bd->props.brightness = machinfo->default_intensity; + backlight_update_status(bd); + + generic_backlight_device = bd; + + dev_info(&pdev->dev, "Generic Backlight Driver Initialized.\n"); + return 0; +} + +static int genericbl_remove(struct platform_device *pdev) +{ + struct backlight_device *bd = platform_get_drvdata(pdev); + + bd->props.power = 0; + bd->props.brightness = 0; + backlight_update_status(bd); + + dev_info(&pdev->dev, "Generic Backlight Driver Unloaded\n"); + return 0; +} + +static struct platform_driver genericbl_driver = { + .probe = genericbl_probe, + .remove = genericbl_remove, + .driver = { + .name = "generic-bl", + }, +}; + +module_platform_driver(genericbl_driver); + +MODULE_AUTHOR("Richard Purdie "); +MODULE_DESCRIPTION("Generic Backlight Driver"); +MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/video/backlight/gpio_backlight.c b/kernel/drivers/video/backlight/gpio_backlight.c new file mode 100644 index 000000000..439feb238 --- /dev/null +++ b/kernel/drivers/video/backlight/gpio_backlight.c @@ -0,0 +1,164 @@ +/* + * gpio_backlight.c - Simple GPIO-controlled backlight + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct gpio_backlight { + struct device *dev; + struct device *fbdev; + + int gpio; + int active; + int def_value; +}; + +static int gpio_backlight_update_status(struct backlight_device *bl) +{ + struct gpio_backlight *gbl = bl_get_data(bl); + int brightness = bl->props.brightness; + + if (bl->props.power != FB_BLANK_UNBLANK || + bl->props.fb_blank != FB_BLANK_UNBLANK || + bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) + brightness = 0; + + gpio_set_value_cansleep(gbl->gpio, + brightness ? gbl->active : !gbl->active); + + return 0; +} + +static int gpio_backlight_check_fb(struct backlight_device *bl, + struct fb_info *info) +{ + struct gpio_backlight *gbl = bl_get_data(bl); + + return gbl->fbdev == NULL || gbl->fbdev == info->dev; +} + +static const struct backlight_ops gpio_backlight_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = gpio_backlight_update_status, + .check_fb = gpio_backlight_check_fb, +}; + +static int gpio_backlight_probe_dt(struct platform_device *pdev, + struct gpio_backlight *gbl) +{ + struct device_node *np = pdev->dev.of_node; + enum of_gpio_flags gpio_flags; + + gbl->gpio = of_get_gpio_flags(np, 0, &gpio_flags); + + if (!gpio_is_valid(gbl->gpio)) { + if (gbl->gpio != -EPROBE_DEFER) { + dev_err(&pdev->dev, + "Error: The gpios parameter is missing or invalid.\n"); + } + return gbl->gpio; + } + + gbl->active = (gpio_flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; + + gbl->def_value = of_property_read_bool(np, "default-on"); + + return 0; +} + +static int gpio_backlight_probe(struct platform_device *pdev) +{ + struct gpio_backlight_platform_data *pdata = + dev_get_platdata(&pdev->dev); + struct backlight_properties props; + struct backlight_device *bl; + struct gpio_backlight *gbl; + struct device_node *np = pdev->dev.of_node; + int ret; + + if (!pdata && !np) { + dev_err(&pdev->dev, + "failed to find platform data or device tree node.\n"); + return -ENODEV; + } + + gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL); + if (gbl == NULL) + return -ENOMEM; + + gbl->dev = &pdev->dev; + + if (np) { + ret = gpio_backlight_probe_dt(pdev, gbl); + if (ret) + return ret; + } else { + gbl->fbdev = pdata->fbdev; + gbl->gpio = pdata->gpio; + gbl->active = pdata->active_low ? 0 : 1; + gbl->def_value = pdata->def_value; + } + + ret = devm_gpio_request_one(gbl->dev, gbl->gpio, GPIOF_DIR_OUT | + (gbl->active ? GPIOF_INIT_LOW + : GPIOF_INIT_HIGH), + pdata ? pdata->name : "backlight"); + if (ret < 0) { + dev_err(&pdev->dev, "unable to request GPIO\n"); + return ret; + } + + memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; + props.max_brightness = 1; + bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), + &pdev->dev, gbl, &gpio_backlight_ops, + &props); + if (IS_ERR(bl)) { + dev_err(&pdev->dev, "failed to register backlight\n"); + return PTR_ERR(bl); + } + + bl->props.brightness = gbl->def_value; + backlight_update_status(bl); + + platform_set_drvdata(pdev, bl); + return 0; +} + +#ifdef CONFIG_OF +static struct of_device_id gpio_backlight_of_match[] = { + { .compatible = "gpio-backlight" }, + { /* sentinel */ } +}; +#endif + +static struct platform_driver gpio_backlight_driver = { + .driver = { + .name = "gpio-backlight", + .of_match_table = of_match_ptr(gpio_backlight_of_match), + }, + .probe = gpio_backlight_probe, +}; + +module_platform_driver(gpio_backlight_driver); + +MODULE_AUTHOR("Laurent Pinchart "); +MODULE_DESCRIPTION("GPIO-based Backlight Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:gpio-backlight"); diff --git a/kernel/drivers/video/backlight/hp680_bl.c b/kernel/drivers/video/backlight/hp680_bl.c new file mode 100644 index 000000000..8ea42b8d9 --- /dev/null +++ b/kernel/drivers/video/backlight/hp680_bl.c @@ -0,0 +1,175 @@ +/* + * Backlight Driver for HP Jornada 680 + * + * Copyright (c) 2005 Andriy Skulysh + * + * Based on Sharp's Corgi Backlight Driver + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define HP680_MAX_INTENSITY 255 +#define HP680_DEFAULT_INTENSITY 10 + +static int hp680bl_suspended; +static int current_intensity; +static DEFINE_SPINLOCK(bl_lock); + +static void hp680bl_send_intensity(struct backlight_device *bd) +{ + unsigned long flags; + u16 v; + int intensity = bd->props.brightness; + + if (bd->props.power != FB_BLANK_UNBLANK) + intensity = 0; + if (bd->props.fb_blank != FB_BLANK_UNBLANK) + intensity = 0; + if (hp680bl_suspended) + intensity = 0; + + spin_lock_irqsave(&bl_lock, flags); + if (intensity && current_intensity == 0) { + sh_dac_enable(DAC_LCD_BRIGHTNESS); + v = inw(HD64461_GPBDR); + v &= ~HD64461_GPBDR_LCDOFF; + outw(v, HD64461_GPBDR); + sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + } else if (intensity == 0 && current_intensity != 0) { + sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + sh_dac_disable(DAC_LCD_BRIGHTNESS); + v = inw(HD64461_GPBDR); + v |= HD64461_GPBDR_LCDOFF; + outw(v, HD64461_GPBDR); + } else if (intensity) { + sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + } + spin_unlock_irqrestore(&bl_lock, flags); + + current_intensity = intensity; +} + + +#ifdef CONFIG_PM_SLEEP +static int hp680bl_suspend(struct device *dev) +{ + struct backlight_device *bd = dev_get_drvdata(dev); + + hp680bl_suspended = 1; + hp680bl_send_intensity(bd); + return 0; +} + +static int hp680bl_resume(struct device *dev) +{ + struct backlight_device *bd = dev_get_drvdata(dev); + + hp680bl_suspended = 0; + hp680bl_send_intensity(bd); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(hp680bl_pm_ops, hp680bl_suspend, hp680bl_resume); + +static int hp680bl_set_intensity(struct backlight_device *bd) +{ + hp680bl_send_intensity(bd); + return 0; +} + +static int hp680bl_get_intensity(struct backlight_device *bd) +{ + return current_intensity; +} + +static const struct backlight_ops hp680bl_ops = { + .get_brightness = hp680bl_get_intensity, + .update_status = hp680bl_set_intensity, +}; + +static int hp680bl_probe(struct platform_device *pdev) +{ + struct backlight_properties props; + struct backlight_device *bd; + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; + props.max_brightness = HP680_MAX_INTENSITY; + bd = devm_backlight_device_register(&pdev->dev, "hp680-bl", &pdev->dev, + NULL, &hp680bl_ops, &props); + if (IS_ERR(bd)) + return PTR_ERR(bd); + + platform_set_drvdata(pdev, bd); + + bd->props.brightness = HP680_DEFAULT_INTENSITY; + hp680bl_send_intensity(bd); + + return 0; +} + +static int hp680bl_remove(struct platform_device *pdev) +{ + struct backlight_device *bd = platform_get_drvdata(pdev); + + bd->props.brightness = 0; + bd->props.power = 0; + hp680bl_send_intensity(bd); + + return 0; +} + +static struct platform_driver hp680bl_driver = { + .probe = hp680bl_probe, + .remove = hp680bl_remove, + .driver = { + .name = "hp680-bl", + .pm = &hp680bl_pm_ops, + }, +}; + +static struct platform_device *hp680bl_device; + +static int __init hp680bl_init(void) +{ + int ret; + + ret = platform_driver_register(&hp680bl_driver); + if (ret) + return ret; + hp680bl_device = platform_device_register_simple("hp680-bl", -1, + NULL, 0); + if (IS_ERR(hp680bl_device)) { + platform_driver_unregister(&hp680bl_driver); + return PTR_ERR(hp680bl_device); + } + return 0; +} + +static void __exit hp680bl_exit(void) +{ + platform_device_unregister(hp680bl_device); + platform_driver_unregister(&hp680bl_driver); +} + +module_init(hp680bl_init); +module_exit(hp680bl_exit); + +MODULE_AUTHOR("Andriy Skulysh "); +MODULE_DESCRIPTION("HP Jornada 680 Backlight Driver"); +MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/video/backlight/hx8357.c b/kernel/drivers/video/backlight/hx8357.c new file mode 100644 index 000000000..23f50b92a --- /dev/null +++ b/kernel/drivers/video/backlight/hx8357.c @@ -0,0 +1,682 @@ +/* + * Driver for the Himax HX-8357 LCD Controller + * + * Copyright 2012 Free Electrons + * + * Licensed under the GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define HX8357_NUM_IM_PINS 3 + +#define HX8357_SWRESET 0x01 +#define HX8357_GET_RED_CHANNEL 0x06 +#define HX8357_GET_GREEN_CHANNEL 0x07 +#define HX8357_GET_BLUE_CHANNEL 0x08 +#define HX8357_GET_POWER_MODE 0x0a +#define HX8357_GET_MADCTL 0x0b +#define HX8357_GET_PIXEL_FORMAT 0x0c +#define HX8357_GET_DISPLAY_MODE 0x0d +#define HX8357_GET_SIGNAL_MODE 0x0e +#define HX8357_GET_DIAGNOSTIC_RESULT 0x0f +#define HX8357_ENTER_SLEEP_MODE 0x10 +#define HX8357_EXIT_SLEEP_MODE 0x11 +#define HX8357_ENTER_PARTIAL_MODE 0x12 +#define HX8357_ENTER_NORMAL_MODE 0x13 +#define HX8357_EXIT_INVERSION_MODE 0x20 +#define HX8357_ENTER_INVERSION_MODE 0x21 +#define HX8357_SET_DISPLAY_OFF 0x28 +#define HX8357_SET_DISPLAY_ON 0x29 +#define HX8357_SET_COLUMN_ADDRESS 0x2a +#define HX8357_SET_PAGE_ADDRESS 0x2b +#define HX8357_WRITE_MEMORY_START 0x2c +#define HX8357_READ_MEMORY_START 0x2e +#define HX8357_SET_PARTIAL_AREA 0x30 +#define HX8357_SET_SCROLL_AREA 0x33 +#define HX8357_SET_TEAR_OFF 0x34 +#define HX8357_SET_TEAR_ON 0x35 +#define HX8357_SET_ADDRESS_MODE 0x36 +#define HX8357_SET_SCROLL_START 0x37 +#define HX8357_EXIT_IDLE_MODE 0x38 +#define HX8357_ENTER_IDLE_MODE 0x39 +#define HX8357_SET_PIXEL_FORMAT 0x3a +#define HX8357_SET_PIXEL_FORMAT_DBI_3BIT (0x1) +#define HX8357_SET_PIXEL_FORMAT_DBI_16BIT (0x5) +#define HX8357_SET_PIXEL_FORMAT_DBI_18BIT (0x6) +#define HX8357_SET_PIXEL_FORMAT_DPI_3BIT (0x1 << 4) +#define HX8357_SET_PIXEL_FORMAT_DPI_16BIT (0x5 << 4) +#define HX8357_SET_PIXEL_FORMAT_DPI_18BIT (0x6 << 4) +#define HX8357_WRITE_MEMORY_CONTINUE 0x3c +#define HX8357_READ_MEMORY_CONTINUE 0x3e +#define HX8357_SET_TEAR_SCAN_LINES 0x44 +#define HX8357_GET_SCAN_LINES 0x45 +#define HX8357_READ_DDB_START 0xa1 +#define HX8357_SET_DISPLAY_MODE 0xb4 +#define HX8357_SET_DISPLAY_MODE_RGB_THROUGH (0x3) +#define HX8357_SET_DISPLAY_MODE_RGB_INTERFACE (1 << 4) +#define HX8357_SET_PANEL_DRIVING 0xc0 +#define HX8357_SET_DISPLAY_FRAME 0xc5 +#define HX8357_SET_RGB 0xc6 +#define HX8357_SET_RGB_ENABLE_HIGH (1 << 1) +#define HX8357_SET_GAMMA 0xc8 +#define HX8357_SET_POWER 0xd0 +#define HX8357_SET_VCOM 0xd1 +#define HX8357_SET_POWER_NORMAL 0xd2 +#define HX8357_SET_PANEL_RELATED 0xe9 + +#define HX8369_SET_DISPLAY_BRIGHTNESS 0x51 +#define HX8369_WRITE_CABC_DISPLAY_VALUE 0x53 +#define HX8369_WRITE_CABC_BRIGHT_CTRL 0x55 +#define HX8369_WRITE_CABC_MIN_BRIGHTNESS 0x5e +#define HX8369_SET_POWER 0xb1 +#define HX8369_SET_DISPLAY_MODE 0xb2 +#define HX8369_SET_DISPLAY_WAVEFORM_CYC 0xb4 +#define HX8369_SET_VCOM 0xb6 +#define HX8369_SET_EXTENSION_COMMAND 0xb9 +#define HX8369_SET_GIP 0xd5 +#define HX8369_SET_GAMMA_CURVE_RELATED 0xe0 + +struct hx8357_data { + unsigned im_pins[HX8357_NUM_IM_PINS]; + unsigned reset; + struct spi_device *spi; + int state; + bool use_im_pins; +}; + +static u8 hx8357_seq_power[] = { + HX8357_SET_POWER, 0x44, 0x41, 0x06, +}; + +static u8 hx8357_seq_vcom[] = { + HX8357_SET_VCOM, 0x40, 0x10, +}; + +static u8 hx8357_seq_power_normal[] = { + HX8357_SET_POWER_NORMAL, 0x05, 0x12, +}; + +static u8 hx8357_seq_panel_driving[] = { + HX8357_SET_PANEL_DRIVING, 0x14, 0x3b, 0x00, 0x02, 0x11, +}; + +static u8 hx8357_seq_display_frame[] = { + HX8357_SET_DISPLAY_FRAME, 0x0c, +}; + +static u8 hx8357_seq_panel_related[] = { + HX8357_SET_PANEL_RELATED, 0x01, +}; + +static u8 hx8357_seq_undefined1[] = { + 0xea, 0x03, 0x00, 0x00, +}; + +static u8 hx8357_seq_undefined2[] = { + 0xeb, 0x40, 0x54, 0x26, 0xdb, +}; + +static u8 hx8357_seq_gamma[] = { + HX8357_SET_GAMMA, 0x00, 0x15, 0x00, 0x22, 0x00, + 0x08, 0x77, 0x26, 0x77, 0x22, 0x04, 0x00, +}; + +static u8 hx8357_seq_address_mode[] = { + HX8357_SET_ADDRESS_MODE, 0xc0, +}; + +static u8 hx8357_seq_pixel_format[] = { + HX8357_SET_PIXEL_FORMAT, + HX8357_SET_PIXEL_FORMAT_DPI_18BIT | + HX8357_SET_PIXEL_FORMAT_DBI_18BIT, +}; + +static u8 hx8357_seq_column_address[] = { + HX8357_SET_COLUMN_ADDRESS, 0x00, 0x00, 0x01, 0x3f, +}; + +static u8 hx8357_seq_page_address[] = { + HX8357_SET_PAGE_ADDRESS, 0x00, 0x00, 0x01, 0xdf, +}; + +static u8 hx8357_seq_rgb[] = { + HX8357_SET_RGB, 0x02, +}; + +static u8 hx8357_seq_display_mode[] = { + HX8357_SET_DISPLAY_MODE, + HX8357_SET_DISPLAY_MODE_RGB_THROUGH | + HX8357_SET_DISPLAY_MODE_RGB_INTERFACE, +}; + +static u8 hx8369_seq_write_CABC_min_brightness[] = { + HX8369_WRITE_CABC_MIN_BRIGHTNESS, 0x00, +}; + +static u8 hx8369_seq_write_CABC_control[] = { + HX8369_WRITE_CABC_DISPLAY_VALUE, 0x24, +}; + +static u8 hx8369_seq_set_display_brightness[] = { + HX8369_SET_DISPLAY_BRIGHTNESS, 0xFF, +}; + +static u8 hx8369_seq_write_CABC_control_setting[] = { + HX8369_WRITE_CABC_BRIGHT_CTRL, 0x02, +}; + +static u8 hx8369_seq_extension_command[] = { + HX8369_SET_EXTENSION_COMMAND, 0xff, 0x83, 0x69, +}; + +static u8 hx8369_seq_display_related[] = { + HX8369_SET_DISPLAY_MODE, 0x00, 0x2b, 0x03, 0x03, 0x70, 0x00, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x01, +}; + +static u8 hx8369_seq_panel_waveform_cycle[] = { + HX8369_SET_DISPLAY_WAVEFORM_CYC, 0x0a, 0x1d, 0x80, 0x06, 0x02, +}; + +static u8 hx8369_seq_set_address_mode[] = { + HX8357_SET_ADDRESS_MODE, 0x00, +}; + +static u8 hx8369_seq_vcom[] = { + HX8369_SET_VCOM, 0x3e, 0x3e, +}; + +static u8 hx8369_seq_gip[] = { + HX8369_SET_GIP, 0x00, 0x01, 0x03, 0x25, 0x01, 0x02, 0x28, 0x70, + 0x11, 0x13, 0x00, 0x00, 0x40, 0x26, 0x51, 0x37, 0x00, 0x00, 0x71, + 0x35, 0x60, 0x24, 0x07, 0x0f, 0x04, 0x04, +}; + +static u8 hx8369_seq_power[] = { + HX8369_SET_POWER, 0x01, 0x00, 0x34, 0x03, 0x00, 0x11, 0x11, 0x32, + 0x2f, 0x3f, 0x3f, 0x01, 0x3a, 0x01, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, +}; + +static u8 hx8369_seq_gamma_curve_related[] = { + HX8369_SET_GAMMA_CURVE_RELATED, 0x00, 0x0d, 0x19, 0x2f, 0x3b, 0x3d, + 0x2e, 0x4a, 0x08, 0x0e, 0x0f, 0x14, 0x16, 0x14, 0x14, 0x14, 0x1e, + 0x00, 0x0d, 0x19, 0x2f, 0x3b, 0x3d, 0x2e, 0x4a, 0x08, 0x0e, 0x0f, + 0x14, 0x16, 0x14, 0x14, 0x14, 0x1e, +}; + +static int hx8357_spi_write_then_read(struct lcd_device *lcdev, + u8 *txbuf, u16 txlen, + u8 *rxbuf, u16 rxlen) +{ + struct hx8357_data *lcd = lcd_get_data(lcdev); + struct spi_message msg; + struct spi_transfer xfer[2]; + u16 *local_txbuf = NULL; + int ret = 0; + + memset(xfer, 0, sizeof(xfer)); + spi_message_init(&msg); + + if (txlen) { + int i; + + local_txbuf = kcalloc(txlen, sizeof(*local_txbuf), GFP_KERNEL); + + if (!local_txbuf) + return -ENOMEM; + + for (i = 0; i < txlen; i++) { + local_txbuf[i] = txbuf[i]; + if (i > 0) + local_txbuf[i] |= 1 << 8; + } + + xfer[0].len = 2 * txlen; + xfer[0].bits_per_word = 9; + xfer[0].tx_buf = local_txbuf; + spi_message_add_tail(&xfer[0], &msg); + } + + if (rxlen) { + xfer[1].len = rxlen; + xfer[1].bits_per_word = 8; + xfer[1].rx_buf = rxbuf; + spi_message_add_tail(&xfer[1], &msg); + } + + ret = spi_sync(lcd->spi, &msg); + if (ret < 0) + dev_err(&lcdev->dev, "Couldn't send SPI data\n"); + + if (txlen) + kfree(local_txbuf); + + return ret; +} + +static inline int hx8357_spi_write_array(struct lcd_device *lcdev, + u8 *value, u8 len) +{ + return hx8357_spi_write_then_read(lcdev, value, len, NULL, 0); +} + +static inline int hx8357_spi_write_byte(struct lcd_device *lcdev, + u8 value) +{ + return hx8357_spi_write_then_read(lcdev, &value, 1, NULL, 0); +} + +static int hx8357_enter_standby(struct lcd_device *lcdev) +{ + int ret; + + ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_OFF); + if (ret < 0) + return ret; + + usleep_range(10000, 12000); + + ret = hx8357_spi_write_byte(lcdev, HX8357_ENTER_SLEEP_MODE); + if (ret < 0) + return ret; + + /* + * The controller needs 120ms when entering in sleep mode before we can + * send the command to go off sleep mode + */ + msleep(120); + + return 0; +} + +static int hx8357_exit_standby(struct lcd_device *lcdev) +{ + int ret; + + ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE); + if (ret < 0) + return ret; + + /* + * The controller needs 120ms when exiting from sleep mode before we + * can send the command to enter in sleep mode + */ + msleep(120); + + ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON); + if (ret < 0) + return ret; + + return 0; +} + +static void hx8357_lcd_reset(struct lcd_device *lcdev) +{ + struct hx8357_data *lcd = lcd_get_data(lcdev); + + /* Reset the screen */ + gpio_set_value(lcd->reset, 1); + usleep_range(10000, 12000); + gpio_set_value(lcd->reset, 0); + usleep_range(10000, 12000); + gpio_set_value(lcd->reset, 1); + + /* The controller needs 120ms to recover from reset */ + msleep(120); +} + +static int hx8357_lcd_init(struct lcd_device *lcdev) +{ + struct hx8357_data *lcd = lcd_get_data(lcdev); + int ret; + + /* + * Set the interface selection pins to SPI mode, with three + * wires + */ + if (lcd->use_im_pins) { + gpio_set_value_cansleep(lcd->im_pins[0], 1); + gpio_set_value_cansleep(lcd->im_pins[1], 0); + gpio_set_value_cansleep(lcd->im_pins[2], 1); + } + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_power, + ARRAY_SIZE(hx8357_seq_power)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_vcom, + ARRAY_SIZE(hx8357_seq_vcom)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_power_normal, + ARRAY_SIZE(hx8357_seq_power_normal)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_panel_driving, + ARRAY_SIZE(hx8357_seq_panel_driving)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_display_frame, + ARRAY_SIZE(hx8357_seq_display_frame)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_panel_related, + ARRAY_SIZE(hx8357_seq_panel_related)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_undefined1, + ARRAY_SIZE(hx8357_seq_undefined1)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_undefined2, + ARRAY_SIZE(hx8357_seq_undefined2)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_gamma, + ARRAY_SIZE(hx8357_seq_gamma)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_address_mode, + ARRAY_SIZE(hx8357_seq_address_mode)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_pixel_format, + ARRAY_SIZE(hx8357_seq_pixel_format)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_column_address, + ARRAY_SIZE(hx8357_seq_column_address)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_page_address, + ARRAY_SIZE(hx8357_seq_page_address)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_rgb, + ARRAY_SIZE(hx8357_seq_rgb)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8357_seq_display_mode, + ARRAY_SIZE(hx8357_seq_display_mode)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE); + if (ret < 0) + return ret; + + /* + * The controller needs 120ms to fully recover from exiting sleep mode + */ + msleep(120); + + ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON); + if (ret < 0) + return ret; + + usleep_range(5000, 7000); + + ret = hx8357_spi_write_byte(lcdev, HX8357_WRITE_MEMORY_START); + if (ret < 0) + return ret; + + return 0; +} + +static int hx8369_lcd_init(struct lcd_device *lcdev) +{ + int ret; + + ret = hx8357_spi_write_array(lcdev, hx8369_seq_extension_command, + ARRAY_SIZE(hx8369_seq_extension_command)); + if (ret < 0) + return ret; + usleep_range(10000, 12000); + + ret = hx8357_spi_write_array(lcdev, hx8369_seq_display_related, + ARRAY_SIZE(hx8369_seq_display_related)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8369_seq_panel_waveform_cycle, + ARRAY_SIZE(hx8369_seq_panel_waveform_cycle)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8369_seq_set_address_mode, + ARRAY_SIZE(hx8369_seq_set_address_mode)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8369_seq_vcom, + ARRAY_SIZE(hx8369_seq_vcom)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8369_seq_gip, + ARRAY_SIZE(hx8369_seq_gip)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, hx8369_seq_power, + ARRAY_SIZE(hx8369_seq_power)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE); + if (ret < 0) + return ret; + + /* + * The controller needs 120ms to fully recover from exiting sleep mode + */ + msleep(120); + + ret = hx8357_spi_write_array(lcdev, hx8369_seq_gamma_curve_related, + ARRAY_SIZE(hx8369_seq_gamma_curve_related)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE); + if (ret < 0) + return ret; + usleep_range(1000, 1200); + + ret = hx8357_spi_write_array(lcdev, hx8369_seq_write_CABC_control, + ARRAY_SIZE(hx8369_seq_write_CABC_control)); + if (ret < 0) + return ret; + usleep_range(10000, 12000); + + ret = hx8357_spi_write_array(lcdev, + hx8369_seq_write_CABC_control_setting, + ARRAY_SIZE(hx8369_seq_write_CABC_control_setting)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_array(lcdev, + hx8369_seq_write_CABC_min_brightness, + ARRAY_SIZE(hx8369_seq_write_CABC_min_brightness)); + if (ret < 0) + return ret; + usleep_range(10000, 12000); + + ret = hx8357_spi_write_array(lcdev, hx8369_seq_set_display_brightness, + ARRAY_SIZE(hx8369_seq_set_display_brightness)); + if (ret < 0) + return ret; + + ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON); + if (ret < 0) + return ret; + + return 0; +} + +#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) + +static int hx8357_set_power(struct lcd_device *lcdev, int power) +{ + struct hx8357_data *lcd = lcd_get_data(lcdev); + int ret = 0; + + if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->state)) + ret = hx8357_exit_standby(lcdev); + else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->state)) + ret = hx8357_enter_standby(lcdev); + + if (ret == 0) + lcd->state = power; + else + dev_warn(&lcdev->dev, "failed to set power mode %d\n", power); + + return ret; +} + +static int hx8357_get_power(struct lcd_device *lcdev) +{ + struct hx8357_data *lcd = lcd_get_data(lcdev); + + return lcd->state; +} + +static struct lcd_ops hx8357_ops = { + .set_power = hx8357_set_power, + .get_power = hx8357_get_power, +}; + +static const struct of_device_id hx8357_dt_ids[] = { + { + .compatible = "himax,hx8357", + .data = hx8357_lcd_init, + }, + { + .compatible = "himax,hx8369", + .data = hx8369_lcd_init, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, hx8357_dt_ids); + +static int hx8357_probe(struct spi_device *spi) +{ + struct lcd_device *lcdev; + struct hx8357_data *lcd; + const struct of_device_id *match; + int i, ret; + + lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL); + if (!lcd) + return -ENOMEM; + + ret = spi_setup(spi); + if (ret < 0) { + dev_err(&spi->dev, "SPI setup failed.\n"); + return ret; + } + + lcd->spi = spi; + + match = of_match_device(hx8357_dt_ids, &spi->dev); + if (!match || !match->data) + return -EINVAL; + + lcd->reset = of_get_named_gpio(spi->dev.of_node, "gpios-reset", 0); + if (!gpio_is_valid(lcd->reset)) { + dev_err(&spi->dev, "Missing dt property: gpios-reset\n"); + return -EINVAL; + } + + ret = devm_gpio_request_one(&spi->dev, lcd->reset, + GPIOF_OUT_INIT_HIGH, + "hx8357-reset"); + if (ret) { + dev_err(&spi->dev, + "failed to request gpio %d: %d\n", + lcd->reset, ret); + return -EINVAL; + } + + if (of_find_property(spi->dev.of_node, "im-gpios", NULL)) { + lcd->use_im_pins = 1; + + for (i = 0; i < HX8357_NUM_IM_PINS; i++) { + lcd->im_pins[i] = of_get_named_gpio(spi->dev.of_node, + "im-gpios", i); + if (lcd->im_pins[i] == -EPROBE_DEFER) { + dev_info(&spi->dev, "GPIO requested is not here yet, deferring the probe\n"); + return -EPROBE_DEFER; + } + if (!gpio_is_valid(lcd->im_pins[i])) { + dev_err(&spi->dev, "Missing dt property: im-gpios\n"); + return -EINVAL; + } + + ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i], + GPIOF_OUT_INIT_LOW, + "im_pins"); + if (ret) { + dev_err(&spi->dev, "failed to request gpio %d: %d\n", + lcd->im_pins[i], ret); + return -EINVAL; + } + } + } else { + lcd->use_im_pins = 0; + } + + lcdev = devm_lcd_device_register(&spi->dev, "mxsfb", &spi->dev, lcd, + &hx8357_ops); + if (IS_ERR(lcdev)) { + ret = PTR_ERR(lcdev); + return ret; + } + spi_set_drvdata(spi, lcdev); + + hx8357_lcd_reset(lcdev); + + ret = ((int (*)(struct lcd_device *))match->data)(lcdev); + if (ret) { + dev_err(&spi->dev, "Couldn't initialize panel\n"); + return ret; + } + + dev_info(&spi->dev, "Panel probed\n"); + + return 0; +} + +static struct spi_driver hx8357_driver = { + .probe = hx8357_probe, + .driver = { + .name = "hx8357", + .of_match_table = hx8357_dt_ids, + }, +}; + +module_spi_driver(hx8357_driver); + +MODULE_AUTHOR("Maxime Ripard "); +MODULE_DESCRIPTION("Himax HX-8357 LCD Driver"); +MODULE_LICENSE("GPL"); diff --git a/kernel/drivers/video/backlight/ili922x.c b/kernel/drivers/video/backlight/ili922x.c new file mode 100644 index 000000000..e7f0890cc --- /dev/null +++ b/kernel/drivers/video/backlight/ili922x.c @@ -0,0 +1,551 @@ +/* + * (C) Copyright 2008 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This driver implements a lcd device for the ILITEK 922x display + * controller. The interface to the display is SPI and the display's + * memory is cyclically updated over the RGB interface. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register offset, see manual section 8.2 */ +#define REG_START_OSCILLATION 0x00 +#define REG_DRIVER_CODE_READ 0x00 +#define REG_DRIVER_OUTPUT_CONTROL 0x01 +#define REG_LCD_AC_DRIVEING_CONTROL 0x02 +#define REG_ENTRY_MODE 0x03 +#define REG_COMPARE_1 0x04 +#define REG_COMPARE_2 0x05 +#define REG_DISPLAY_CONTROL_1 0x07 +#define REG_DISPLAY_CONTROL_2 0x08 +#define REG_DISPLAY_CONTROL_3 0x09 +#define REG_FRAME_CYCLE_CONTROL 0x0B +#define REG_EXT_INTF_CONTROL 0x0C +#define REG_POWER_CONTROL_1 0x10 +#define REG_POWER_CONTROL_2 0x11 +#define REG_POWER_CONTROL_3 0x12 +#define REG_POWER_CONTROL_4 0x13 +#define REG_RAM_ADDRESS_SET 0x21 +#define REG_WRITE_DATA_TO_GRAM 0x22 +#define REG_RAM_WRITE_MASK1 0x23 +#define REG_RAM_WRITE_MASK2 0x24 +#define REG_GAMMA_CONTROL_1 0x30 +#define REG_GAMMA_CONTROL_2 0x31 +#define REG_GAMMA_CONTROL_3 0x32 +#define REG_GAMMA_CONTROL_4 0x33 +#define REG_GAMMA_CONTROL_5 0x34 +#define REG_GAMMA_CONTROL_6 0x35 +#define REG_GAMMA_CONTROL_7 0x36 +#define REG_GAMMA_CONTROL_8 0x37 +#define REG_GAMMA_CONTROL_9 0x38 +#define REG_GAMMA_CONTROL_10 0x39 +#define REG_GATE_SCAN_CONTROL 0x40 +#define REG_VERT_SCROLL_CONTROL 0x41 +#define REG_FIRST_SCREEN_DRIVE_POS 0x42 +#define REG_SECOND_SCREEN_DRIVE_POS 0x43 +#define REG_RAM_ADDR_POS_H 0x44 +#define REG_RAM_ADDR_POS_V 0x45 +#define REG_OSCILLATOR_CONTROL 0x4F +#define REG_GPIO 0x60 +#define REG_OTP_VCM_PROGRAMMING 0x61 +#define REG_OTP_VCM_STATUS_ENABLE 0x62 +#define REG_OTP_PROGRAMMING_ID_KEY 0x65 + +/* + * maximum frequency for register access + * (not for the GRAM access) + */ +#define ILITEK_MAX_FREQ_REG 4000000 + +/* + * Device ID as found in the datasheet (supports 9221 and 9222) + */ +#define ILITEK_DEVICE_ID 0x9220 +#define ILITEK_DEVICE_ID_MASK 0xFFF0 + +/* Last two bits in the START BYTE */ +#define START_RS_INDEX 0 +#define START_RS_REG 1 +#define START_RW_WRITE 0 +#define START_RW_READ 1 + +/** + * START_BYTE(id, rs, rw) + * + * Set the start byte according to the required operation. + * The start byte is defined as: + * ---------------------------------- + * | 0 | 1 | 1 | 1 | 0 | ID | RS | RW | + * ---------------------------------- + * @id: display's id as set by the manufacturer + * @rs: operation type bit, one of: + * - START_RS_INDEX set the index register + * - START_RS_REG write/read registers/GRAM + * @rw: read/write operation + * - START_RW_WRITE write + * - START_RW_READ read + */ +#define START_BYTE(id, rs, rw) \ + (0x70 | (((id) & 0x01) << 2) | (((rs) & 0x01) << 1) | ((rw) & 0x01)) + +/** + * CHECK_FREQ_REG(spi_device s, spi_transfer x) - Check the frequency + * for the SPI transfer. According to the datasheet, the controller + * accept higher frequency for the GRAM transfer, but it requires + * lower frequency when the registers are read/written. + * The macro sets the frequency in the spi_transfer structure if + * the frequency exceeds the maximum value. + */ +#define CHECK_FREQ_REG(s, x) \ + do { \ + if (s->max_speed_hz > ILITEK_MAX_FREQ_REG) \ + ((struct spi_transfer *)x)->speed_hz = \ + ILITEK_MAX_FREQ_REG; \ + } while (0) + +#define CMD_BUFSIZE 16 + +#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) + +#define set_tx_byte(b) (tx_invert ? ~(b) : b) + +/** + * ili922x_id - id as set by manufacturer + */ +static int ili922x_id = 1; +module_param(ili922x_id, int, 0); + +static int tx_invert; +module_param(tx_invert, int, 0); + +/** + * driver's private structure + */ +struct ili922x { + struct spi_device *spi; + struct lcd_device *ld; + int power; +}; + +/** + * ili922x_read_status - read status register from display + * @spi: spi device + * @rs: output value + */ +static int ili922x_read_status(struct spi_device *spi, u16 *rs) +{ + struct spi_message msg; + struct spi_transfer xfer; + unsigned char tbuf[CMD_BUFSIZE]; + unsigned char rbuf[CMD_BUFSIZE]; + int ret, i; + + memset(&xfer, 0, sizeof(struct spi_transfer)); + spi_message_init(&msg); + xfer.tx_buf = tbuf; + xfer.rx_buf = rbuf; + xfer.cs_change = 1; + CHECK_FREQ_REG(spi, &xfer); + + tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX, + START_RW_READ)); + /* + * we need 4-byte xfer here due to invalid dummy byte + * received after start byte + */ + for (i = 1; i < 4; i++) + tbuf[i] = set_tx_byte(0); /* dummy */ + + xfer.bits_per_word = 8; + xfer.len = 4; + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(spi, &msg); + if (ret < 0) { + dev_dbg(&spi->dev, "Error sending SPI message 0x%x", ret); + return ret; + } + + *rs = (rbuf[2] << 8) + rbuf[3]; + return 0; +} + +/** + * ili922x_read - read register from display + * @spi: spi device + * @reg: offset of the register to be read + * @rx: output value + */ +static int ili922x_read(struct spi_device *spi, u8 reg, u16 *rx) +{ + struct spi_message msg; + struct spi_transfer xfer_regindex, xfer_regvalue; + unsigned char tbuf[CMD_BUFSIZE]; + unsigned char rbuf[CMD_BUFSIZE]; + int ret, len = 0, send_bytes; + + memset(&xfer_regindex, 0, sizeof(struct spi_transfer)); + memset(&xfer_regvalue, 0, sizeof(struct spi_transfer)); + spi_message_init(&msg); + xfer_regindex.tx_buf = tbuf; + xfer_regindex.rx_buf = rbuf; + xfer_regindex.cs_change = 1; + CHECK_FREQ_REG(spi, &xfer_regindex); + + tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX, + START_RW_WRITE)); + tbuf[1] = set_tx_byte(0); + tbuf[2] = set_tx_byte(reg); + xfer_regindex.bits_per_word = 8; + len = xfer_regindex.len = 3; + spi_message_add_tail(&xfer_regindex, &msg); + + send_bytes = len; + + tbuf[len++] = set_tx_byte(START_BYTE(ili922x_id, START_RS_REG, + START_RW_READ)); + tbuf[len++] = set_tx_byte(0); + tbuf[len] = set_tx_byte(0); + + xfer_regvalue.cs_change = 1; + xfer_regvalue.len = 3; + xfer_regvalue.tx_buf = &tbuf[send_bytes]; + xfer_regvalue.rx_buf = &rbuf[send_bytes]; + CHECK_FREQ_REG(spi, &xfer_regvalue); + + spi_message_add_tail(&xfer_regvalue, &msg); + ret = spi_sync(spi, &msg); + if (ret < 0) { + dev_dbg(&spi->dev, "Error sending SPI message 0x%x", ret); + return ret; + } + + *rx = (rbuf[1 + send_bytes] << 8) + rbuf[2 + send_bytes]; + return 0; +} + +/** + * ili922x_write - write a controller register + * @spi: struct spi_device * + * @reg: offset of the register to be written + * @value: value to be written + */ +static int ili922x_write(struct spi_device *spi, u8 reg, u16 value) +{ + struct spi_message msg; + struct spi_transfer xfer_regindex, xfer_regvalue; + unsigned char tbuf[CMD_BUFSIZE]; + unsigned char rbuf[CMD_BUFSIZE]; + int ret, len = 0; + + memset(&xfer_regindex, 0, sizeof(struct spi_transfer)); + memset(&xfer_regvalue, 0, sizeof(struct spi_transfer)); + + spi_message_init(&msg); + xfer_regindex.tx_buf = tbuf; + xfer_regindex.rx_buf = rbuf; + xfer_regindex.cs_change = 1; + CHECK_FREQ_REG(spi, &xfer_regindex); + + tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX, + START_RW_WRITE)); + tbuf[1] = set_tx_byte(0); + tbuf[2] = set_tx_byte(reg); + xfer_regindex.bits_per_word = 8; + xfer_regindex.len = 3; + spi_message_add_tail(&xfer_regindex, &msg); + + ret = spi_sync(spi, &msg); + + spi_message_init(&msg); + len = 0; + tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_REG, + START_RW_WRITE)); + tbuf[1] = set_tx_byte((value & 0xFF00) >> 8); + tbuf[2] = set_tx_byte(value & 0x00FF); + + xfer_regvalue.cs_change = 1; + xfer_regvalue.len = 3; + xfer_regvalue.tx_buf = tbuf; + xfer_regvalue.rx_buf = rbuf; + CHECK_FREQ_REG(spi, &xfer_regvalue); + + spi_message_add_tail(&xfer_regvalue, &msg); + + ret = spi_sync(spi, &msg); + if (ret < 0) { + dev_err(&spi->dev, "Error sending SPI message 0x%x", ret); + return ret; + } + return 0; +} + +#ifdef DEBUG +/** + * ili922x_reg_dump - dump all registers + */ +static void ili922x_reg_dump(struct spi_device *spi) +{ + u8 reg; + u16 rx; + + dev_dbg(&spi->dev, "ILI922x configuration registers:\n"); + for (reg = REG_START_OSCILLATION; + reg <= REG_OTP_PROGRAMMING_ID_KEY; reg++) { + ili922x_read(spi, reg, &rx); + dev_dbg(&spi->dev, "reg @ 0x%02X: 0x%04X\n", reg, rx); + } +} +#else +static inline void ili922x_reg_dump(struct spi_device *spi) {} +#endif + +/** + * set_write_to_gram_reg - initialize the display to write the GRAM + * @spi: spi device + */ +static void set_write_to_gram_reg(struct spi_device *spi) +{ + struct spi_message msg; + struct spi_transfer xfer; + unsigned char tbuf[CMD_BUFSIZE]; + + memset(&xfer, 0, sizeof(struct spi_transfer)); + + spi_message_init(&msg); + xfer.tx_buf = tbuf; + xfer.rx_buf = NULL; + xfer.cs_change = 1; + + tbuf[0] = START_BYTE(ili922x_id, START_RS_INDEX, START_RW_WRITE); + tbuf[1] = 0; + tbuf[2] = REG_WRITE_DATA_TO_GRAM; + + xfer.bits_per_word = 8; + xfer.len = 3; + spi_message_add_tail(&xfer, &msg); + spi_sync(spi, &msg); +} + +/** + * ili922x_poweron - turn the display on + * @spi: spi device + * + * The sequence to turn on the display is taken from + * the datasheet and/or the example code provided by the + * manufacturer. + */ +static int ili922x_poweron(struct spi_device *spi) +{ + int ret; + + /* Power on */ + ret = ili922x_write(spi, REG_POWER_CONTROL_1, 0x0000); + usleep_range(10000, 10500); + ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000); + ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0000); + msleep(40); + ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x0000); + msleep(40); + /* register 0x56 is not documented in the datasheet */ + ret += ili922x_write(spi, 0x56, 0x080F); + ret += ili922x_write(spi, REG_POWER_CONTROL_1, 0x4240); + usleep_range(10000, 10500); + ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000); + ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0014); + msleep(40); + ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x1319); + msleep(40); + + return ret; +} + +/** + * ili922x_poweroff - turn the display off + * @spi: spi device + */ +static int ili922x_poweroff(struct spi_device *spi) +{ + int ret; + + /* Power off */ + ret = ili922x_write(spi, REG_POWER_CONTROL_1, 0x0000); + usleep_range(10000, 10500); + ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000); + ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0000); + msleep(40); + ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x0000); + msleep(40); + + return ret; +} + +/** + * ili922x_display_init - initialize the display by setting + * the configuration registers + * @spi: spi device + */ +static void ili922x_display_init(struct spi_device *spi) +{ + ili922x_write(spi, REG_START_OSCILLATION, 1); + usleep_range(10000, 10500); + ili922x_write(spi, REG_DRIVER_OUTPUT_CONTROL, 0x691B); + ili922x_write(spi, REG_LCD_AC_DRIVEING_CONTROL, 0x0700); + ili922x_write(spi, REG_ENTRY_MODE, 0x1030); + ili922x_write(spi, REG_COMPARE_1, 0x0000); + ili922x_write(spi, REG_COMPARE_2, 0x0000); + ili922x_write(spi, REG_DISPLAY_CONTROL_1, 0x0037); + ili922x_write(spi, REG_DISPLAY_CONTROL_2, 0x0202); + ili922x_write(spi, REG_DISPLAY_CONTROL_3, 0x0000); + ili922x_write(spi, REG_FRAME_CYCLE_CONTROL, 0x0000); + + /* Set RGB interface */ + ili922x_write(spi, REG_EXT_INTF_CONTROL, 0x0110); + + ili922x_poweron(spi); + + ili922x_write(spi, REG_GAMMA_CONTROL_1, 0x0302); + ili922x_write(spi, REG_GAMMA_CONTROL_2, 0x0407); + ili922x_write(spi, REG_GAMMA_CONTROL_3, 0x0304); + ili922x_write(spi, REG_GAMMA_CONTROL_4, 0x0203); + ili922x_write(spi, REG_GAMMA_CONTROL_5, 0x0706); + ili922x_write(spi, REG_GAMMA_CONTROL_6, 0x0407); + ili922x_write(spi, REG_GAMMA_CONTROL_7, 0x0706); + ili922x_write(spi, REG_GAMMA_CONTROL_8, 0x0000); + ili922x_write(spi, REG_GAMMA_CONTROL_9, 0x0C06); + ili922x_write(spi, REG_GAMMA_CONTROL_10, 0x0F00); + ili922x_write(spi, REG_RAM_ADDRESS_SET, 0x0000); + ili922x_write(spi, REG_GATE_SCAN_CONTROL, 0x0000); + ili922x_write(spi, REG_VERT_SCROLL_CONTROL, 0x0000); + ili922x_write(spi, REG_FIRST_SCREEN_DRIVE_POS, 0xDB00); + ili922x_write(spi, REG_SECOND_SCREEN_DRIVE_POS, 0xDB00); + ili922x_write(spi, REG_RAM_ADDR_POS_H, 0xAF00); + ili922x_write(spi, REG_RAM_ADDR_POS_V, 0xDB00); + ili922x_reg_dump(spi); + set_write_to_gram_reg(spi); +} + +static int ili922x_lcd_power(struct ili922x *lcd, int power) +{ + int ret = 0; + + if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) + ret = ili922x_poweron(lcd->spi); + else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) + ret = ili922x_poweroff(lcd->spi); + + if (!ret) + lcd->power = power; + + return ret; +} + +static int ili922x_set_power(struct lcd_device *ld, int power) +{ + struct ili922x *ili = lcd_get_data(ld); + + return ili922x_lcd_power(ili, power); +} + +static int ili922x_get_power(struct lcd_device *ld) +{ + struct ili922x *ili = lcd_get_data(ld); + + return ili->power; +} + +static struct lcd_ops ili922x_ops = { + .get_power = ili922x_get_power, + .set_power = ili922x_set_power, +}; + +static int ili922x_probe(struct spi_device *spi) +{ + struct ili922x *ili; + struct lcd_device *lcd; + int ret; + u16 reg = 0; + + ili = devm_kzalloc(&spi->dev, sizeof(*ili), GFP_KERNEL); + if (!ili) + return -ENOMEM; + + ili->spi = spi; + spi_set_drvdata(spi, ili); + + /* check if the device is connected */ + ret = ili922x_read(spi, REG_DRIVER_CODE_READ, ®); + if (ret || ((reg & ILITEK_DEVICE_ID_MASK) != ILITEK_DEVICE_ID)) { + dev_err(&spi->dev, + "no LCD found: Chip ID 0x%x, ret %d\n", + reg, ret); + return -ENODEV; + } + + dev_info(&spi->dev, "ILI%x found, SPI freq %d, mode %d\n", + reg, spi->max_speed_hz, spi->mode); + + ret = ili922x_read_status(spi, ®); + if (ret) { + dev_err(&spi->dev, "reading RS failed...\n"); + return ret; + } + + dev_dbg(&spi->dev, "status: 0x%x\n", reg); + + ili922x_display_init(spi); + + ili->power = FB_BLANK_POWERDOWN; + + lcd = devm_lcd_device_register(&spi->dev, "ili922xlcd", &spi->dev, ili, + &ili922x_ops); + if (IS_ERR(lcd)) { + dev_err(&spi->dev, "cannot register LCD\n"); + return PTR_ERR(lcd); + } + + ili->ld = lcd; + spi_set_drvdata(spi, ili); + + ili922x_lcd_power(ili, FB_BLANK_UNBLANK); + + return 0; +} + +static int ili922x_remove(struct spi_device *spi) +{ + ili922x_poweroff(spi); + return 0; +} + +static struct spi_driver ili922x_driver = { + .driver = { + .name = "ili922x", + .owner = THIS_MODULE, + }, + .probe = ili922x_probe, + .remove = ili922x_remove, +}; + +module_spi_driver(ili922x_driver); + +MODULE_AUTHOR("Stefano Babic "); +MODULE_DESCRIPTION("ILI9221/9222 LCD driver"); +MODULE_LICENSE("GPL"); +MODULE_PARM_DESC(ili922x_id, "set controller identifier (default=1)"); +MODULE_PARM_DESC(tx_invert, "invert bytes before sending"); diff --git a/kernel/drivers/video/backlight/ili9320.c b/kernel/drivers/video/backlight/ili9320.c new file mode 100644 index 000000000..2cf39e6d5 --- /dev/null +++ b/kernel/drivers/video/backlight/ili9320.c @@ -0,0 +1,303 @@ +/* drivers/video/backlight/ili9320.c + * + * ILI9320 LCD controller driver core. + * + * Copyright 2007 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include