From b673969b102cece38c5de54d35617425459174f5 Mon Sep 17 00:00:00 2001 From: Wolfgang Wiedmeyer Date: Sun, 25 Oct 2015 17:24:31 +0100 Subject: remove unneeded drivers --- drivers/gpu/drm/Kconfig | 8 - drivers/gpu/drm/Makefile | 8 +- drivers/gpu/drm/exynos/Kconfig | 88 - drivers/gpu/drm/exynos/Makefile | 24 - drivers/gpu/drm/exynos/exynos_ddc.c | 57 - drivers/gpu/drm/exynos/exynos_drm_buf.c | 245 --- drivers/gpu/drm/exynos/exynos_drm_buf.h | 47 - drivers/gpu/drm/exynos/exynos_drm_connector.c | 357 ---- drivers/gpu/drm/exynos/exynos_drm_connector.h | 34 - drivers/gpu/drm/exynos/exynos_drm_core.c | 212 -- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 398 ---- drivers/gpu/drm/exynos/exynos_drm_crtc.h | 36 - drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 285 --- drivers/gpu/drm/exynos/exynos_drm_dmabuf.h | 39 - drivers/gpu/drm/exynos/exynos_drm_drv.c | 578 ------ drivers/gpu/drm/exynos/exynos_drm_drv.h | 350 ---- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 432 ---- drivers/gpu/drm/exynos/exynos_drm_encoder.h | 50 - drivers/gpu/drm/exynos/exynos_drm_fb.c | 312 --- drivers/gpu/drm/exynos/exynos_drm_fb.h | 55 - drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 318 --- drivers/gpu/drm/exynos/exynos_drm_fbdev.h | 37 - drivers/gpu/drm/exynos/exynos_drm_fimc.c | 1925 ------------------ drivers/gpu/drm/exynos/exynos_drm_fimc.h | 33 - drivers/gpu/drm/exynos/exynos_drm_g2d.c | 1038 ---------- drivers/gpu/drm/exynos/exynos_drm_g2d.h | 36 - drivers/gpu/drm/exynos/exynos_drm_gem.c | 1698 ---------------- drivers/gpu/drm/exynos/exynos_drm_gem.h | 259 --- drivers/gpu/drm/exynos/exynos_drm_gsc.c | 1385 ------------- drivers/gpu/drm/exynos/exynos_drm_gsc.h | 33 - drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 386 ---- drivers/gpu/drm/exynos/exynos_drm_hdmi.h | 77 - drivers/gpu/drm/exynos/exynos_drm_iommu.c | 237 --- drivers/gpu/drm/exynos/exynos_drm_iommu.h | 58 - drivers/gpu/drm/exynos/exynos_drm_ipp.c | 1638 --------------- drivers/gpu/drm/exynos/exynos_drm_ipp.h | 191 -- drivers/gpu/drm/exynos/exynos_drm_plane.c | 259 --- drivers/gpu/drm/exynos/exynos_drm_plane.h | 20 - drivers/gpu/drm/exynos/exynos_drm_rotator.c | 879 -------- drivers/gpu/drm/exynos/exynos_drm_rotator.h | 13 - drivers/gpu/drm/exynos/exynos_drm_ump.c | 144 -- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 693 ------- drivers/gpu/drm/exynos/exynos_drm_vidi.h | 36 - drivers/gpu/drm/exynos/exynos_hdmi.c | 2681 ------------------------- drivers/gpu/drm/exynos/exynos_hdmi.h | 37 - drivers/gpu/drm/exynos/exynos_hdmiphy.c | 58 - drivers/gpu/drm/exynos/exynos_mixer.c | 1111 ---------- drivers/gpu/drm/exynos/regs-fimc.h | 669 ------ drivers/gpu/drm/exynos/regs-gsc.h | 295 --- drivers/gpu/drm/exynos/regs-hdmi.h | 723 ------- drivers/gpu/drm/exynos/regs-mixer.h | 141 -- drivers/gpu/drm/exynos/regs-vp.h | 91 - drivers/gpu/drm/gma500/Kconfig | 33 - drivers/gpu/drm/gma500/Makefile | 50 - drivers/gpu/drm/gma500/accel_2d.c | 364 ---- drivers/gpu/drm/gma500/backlight.c | 49 - drivers/gpu/drm/gma500/cdv_device.c | 484 ----- drivers/gpu/drm/gma500/cdv_device.h | 36 - drivers/gpu/drm/gma500/cdv_intel_crt.c | 340 ---- drivers/gpu/drm/gma500/cdv_intel_display.c | 1459 -------------- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 393 ---- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 734 ------- drivers/gpu/drm/gma500/framebuffer.c | 800 -------- drivers/gpu/drm/gma500/framebuffer.h | 47 - drivers/gpu/drm/gma500/gem.c | 292 --- drivers/gpu/drm/gma500/gem_glue.c | 90 - drivers/gpu/drm/gma500/gem_glue.h | 2 - drivers/gpu/drm/gma500/gtt.c | 551 ----- drivers/gpu/drm/gma500/gtt.h | 64 - drivers/gpu/drm/gma500/intel_bios.c | 303 --- drivers/gpu/drm/gma500/intel_bios.h | 430 ---- drivers/gpu/drm/gma500/intel_gmbus.c | 493 ----- drivers/gpu/drm/gma500/intel_i2c.c | 168 -- drivers/gpu/drm/gma500/intel_opregion.c | 81 - drivers/gpu/drm/gma500/mdfld_device.c | 691 ------- drivers/gpu/drm/gma500/mdfld_dsi_dpi.c | 1017 ---------- drivers/gpu/drm/gma500/mdfld_dsi_dpi.h | 79 - drivers/gpu/drm/gma500/mdfld_dsi_output.c | 618 ------ drivers/gpu/drm/gma500/mdfld_dsi_output.h | 378 ---- drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c | 694 ------- drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h | 92 - drivers/gpu/drm/gma500/mdfld_intel_display.c | 1180 ----------- drivers/gpu/drm/gma500/mdfld_output.c | 74 - drivers/gpu/drm/gma500/mdfld_output.h | 77 - drivers/gpu/drm/gma500/mdfld_tmd_vid.c | 201 -- drivers/gpu/drm/gma500/mdfld_tpo_vid.c | 124 -- drivers/gpu/drm/gma500/mid_bios.c | 263 --- drivers/gpu/drm/gma500/mid_bios.h | 21 - drivers/gpu/drm/gma500/mmu.c | 849 -------- drivers/gpu/drm/gma500/oaktrail.h | 252 --- drivers/gpu/drm/gma500/oaktrail_crtc.c | 592 ------ drivers/gpu/drm/gma500/oaktrail_device.c | 509 ----- drivers/gpu/drm/gma500/oaktrail_hdmi.c | 540 ----- drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c | 327 --- drivers/gpu/drm/gma500/oaktrail_lvds.c | 448 ----- drivers/gpu/drm/gma500/power.c | 315 --- drivers/gpu/drm/gma500/power.h | 67 - drivers/gpu/drm/gma500/psb_device.c | 330 --- drivers/gpu/drm/gma500/psb_drv.c | 706 ------- drivers/gpu/drm/gma500/psb_drv.h | 993 --------- drivers/gpu/drm/gma500/psb_intel_display.c | 1436 ------------- drivers/gpu/drm/gma500/psb_intel_display.h | 28 - drivers/gpu/drm/gma500/psb_intel_drv.h | 289 --- drivers/gpu/drm/gma500/psb_intel_lvds.c | 867 -------- drivers/gpu/drm/gma500/psb_intel_modes.c | 75 - drivers/gpu/drm/gma500/psb_intel_reg.h | 1318 ------------ drivers/gpu/drm/gma500/psb_intel_sdvo.c | 2607 ------------------------ drivers/gpu/drm/gma500/psb_intel_sdvo_regs.h | 723 ------- drivers/gpu/drm/gma500/psb_irq.c | 622 ------ drivers/gpu/drm/gma500/psb_irq.h | 47 - drivers/gpu/drm/gma500/psb_lid.c | 88 - drivers/gpu/drm/gma500/psb_reg.h | 582 ------ drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c | 829 -------- drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h | 38 - drivers/gpu/drm/udl/Kconfig | 12 - drivers/gpu/drm/udl/Makefile | 6 - drivers/gpu/drm/udl/udl_connector.c | 141 -- drivers/gpu/drm/udl/udl_drv.c | 99 - drivers/gpu/drm/udl/udl_drv.h | 141 -- drivers/gpu/drm/udl/udl_encoder.c | 80 - drivers/gpu/drm/udl/udl_fb.c | 611 ------ drivers/gpu/drm/udl/udl_gem.c | 227 --- drivers/gpu/drm/udl/udl_main.c | 338 ---- drivers/gpu/drm/udl/udl_modeset.c | 414 ---- drivers/gpu/drm/udl/udl_transfer.c | 253 --- drivers/gpu/ion/Kconfig | 6 - drivers/gpu/ion/Makefile | 1 - drivers/gpu/ion/tegra/Makefile | 1 - drivers/gpu/ion/tegra/tegra_ion.c | 96 - 129 files changed, 1 insertion(+), 51488 deletions(-) delete mode 100644 drivers/gpu/drm/exynos/Kconfig delete mode 100644 drivers/gpu/drm/exynos/Makefile delete mode 100644 drivers/gpu/drm/exynos/exynos_ddc.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_buf.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_buf.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_connector.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_core.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_crtc.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_crtc.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_dmabuf.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_dmabuf.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_drv.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_drv.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_encoder.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_encoder.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_fb.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_fb.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_fbdev.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_fbdev.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_fimc.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_fimc.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_g2d.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_g2d.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_gem.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_gem.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_gsc.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_gsc.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_hdmi.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_iommu.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_iommu.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_ipp.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_ipp.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_plane.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_plane.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_rotator.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_rotator.h delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_ump.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_vidi.c delete mode 100644 drivers/gpu/drm/exynos/exynos_drm_vidi.h delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmi.c delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmi.h delete mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy.c delete mode 100644 drivers/gpu/drm/exynos/exynos_mixer.c delete mode 100644 drivers/gpu/drm/exynos/regs-fimc.h delete mode 100644 drivers/gpu/drm/exynos/regs-gsc.h delete mode 100644 drivers/gpu/drm/exynos/regs-hdmi.h delete mode 100644 drivers/gpu/drm/exynos/regs-mixer.h delete mode 100644 drivers/gpu/drm/exynos/regs-vp.h delete mode 100644 drivers/gpu/drm/gma500/Kconfig delete mode 100644 drivers/gpu/drm/gma500/Makefile delete mode 100644 drivers/gpu/drm/gma500/accel_2d.c delete mode 100644 drivers/gpu/drm/gma500/backlight.c delete mode 100644 drivers/gpu/drm/gma500/cdv_device.c delete mode 100644 drivers/gpu/drm/gma500/cdv_device.h delete mode 100644 drivers/gpu/drm/gma500/cdv_intel_crt.c delete mode 100644 drivers/gpu/drm/gma500/cdv_intel_display.c delete mode 100644 drivers/gpu/drm/gma500/cdv_intel_hdmi.c delete mode 100644 drivers/gpu/drm/gma500/cdv_intel_lvds.c delete mode 100644 drivers/gpu/drm/gma500/framebuffer.c delete mode 100644 drivers/gpu/drm/gma500/framebuffer.h delete mode 100644 drivers/gpu/drm/gma500/gem.c delete mode 100644 drivers/gpu/drm/gma500/gem_glue.c delete mode 100644 drivers/gpu/drm/gma500/gem_glue.h delete mode 100644 drivers/gpu/drm/gma500/gtt.c delete mode 100644 drivers/gpu/drm/gma500/gtt.h delete mode 100644 drivers/gpu/drm/gma500/intel_bios.c delete mode 100644 drivers/gpu/drm/gma500/intel_bios.h delete mode 100644 drivers/gpu/drm/gma500/intel_gmbus.c delete mode 100644 drivers/gpu/drm/gma500/intel_i2c.c delete mode 100644 drivers/gpu/drm/gma500/intel_opregion.c delete mode 100644 drivers/gpu/drm/gma500/mdfld_device.c delete mode 100644 drivers/gpu/drm/gma500/mdfld_dsi_dpi.c delete mode 100644 drivers/gpu/drm/gma500/mdfld_dsi_dpi.h delete mode 100644 drivers/gpu/drm/gma500/mdfld_dsi_output.c delete mode 100644 drivers/gpu/drm/gma500/mdfld_dsi_output.h delete mode 100644 drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c delete mode 100644 drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h delete mode 100644 drivers/gpu/drm/gma500/mdfld_intel_display.c delete mode 100644 drivers/gpu/drm/gma500/mdfld_output.c delete mode 100644 drivers/gpu/drm/gma500/mdfld_output.h delete mode 100644 drivers/gpu/drm/gma500/mdfld_tmd_vid.c delete mode 100644 drivers/gpu/drm/gma500/mdfld_tpo_vid.c delete mode 100644 drivers/gpu/drm/gma500/mid_bios.c delete mode 100644 drivers/gpu/drm/gma500/mid_bios.h delete mode 100644 drivers/gpu/drm/gma500/mmu.c delete mode 100644 drivers/gpu/drm/gma500/oaktrail.h delete mode 100644 drivers/gpu/drm/gma500/oaktrail_crtc.c delete mode 100644 drivers/gpu/drm/gma500/oaktrail_device.c delete mode 100644 drivers/gpu/drm/gma500/oaktrail_hdmi.c delete mode 100644 drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c delete mode 100644 drivers/gpu/drm/gma500/oaktrail_lvds.c delete mode 100644 drivers/gpu/drm/gma500/power.c delete mode 100644 drivers/gpu/drm/gma500/power.h delete mode 100644 drivers/gpu/drm/gma500/psb_device.c delete mode 100644 drivers/gpu/drm/gma500/psb_drv.c delete mode 100644 drivers/gpu/drm/gma500/psb_drv.h delete mode 100644 drivers/gpu/drm/gma500/psb_intel_display.c delete mode 100644 drivers/gpu/drm/gma500/psb_intel_display.h delete mode 100644 drivers/gpu/drm/gma500/psb_intel_drv.h delete mode 100644 drivers/gpu/drm/gma500/psb_intel_lvds.c delete mode 100644 drivers/gpu/drm/gma500/psb_intel_modes.c delete mode 100644 drivers/gpu/drm/gma500/psb_intel_reg.h delete mode 100644 drivers/gpu/drm/gma500/psb_intel_sdvo.c delete mode 100644 drivers/gpu/drm/gma500/psb_intel_sdvo_regs.h delete mode 100644 drivers/gpu/drm/gma500/psb_irq.c delete mode 100644 drivers/gpu/drm/gma500/psb_irq.h delete mode 100644 drivers/gpu/drm/gma500/psb_lid.c delete mode 100644 drivers/gpu/drm/gma500/psb_reg.h delete mode 100644 drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c delete mode 100644 drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h delete mode 100644 drivers/gpu/drm/udl/Kconfig delete mode 100644 drivers/gpu/drm/udl/Makefile delete mode 100644 drivers/gpu/drm/udl/udl_connector.c delete mode 100644 drivers/gpu/drm/udl/udl_drv.c delete mode 100644 drivers/gpu/drm/udl/udl_drv.h delete mode 100644 drivers/gpu/drm/udl/udl_encoder.c delete mode 100644 drivers/gpu/drm/udl/udl_fb.c delete mode 100644 drivers/gpu/drm/udl/udl_gem.c delete mode 100644 drivers/gpu/drm/udl/udl_main.c delete mode 100644 drivers/gpu/drm/udl/udl_modeset.c delete mode 100644 drivers/gpu/drm/udl/udl_transfer.c delete mode 100644 drivers/gpu/ion/tegra/Makefile delete mode 100644 drivers/gpu/ion/tegra/tegra_ion.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 9fc6d9b..d7e67d1 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -176,11 +176,3 @@ config DRM_SAVAGE help Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister chipset. If M is selected the module will be called savage. - -source "drivers/gpu/drm/exynos/Kconfig" - -source "drivers/gpu/drm/vmwgfx/Kconfig" - -source "drivers/gpu/drm/gma500/Kconfig" - -source "drivers/gpu/drm/udl/Kconfig" diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index d11f4f3..b346ed8 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -9,7 +9,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \ drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ - drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ + drm_platform.o drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ drm_crtc.o drm_modes.o drm_edid.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o \ drm_trace_points.o drm_global.o drm_prime.o drm_backlight.o @@ -39,10 +39,4 @@ obj-$(CONFIG_DRM_SAVAGE)+= savage/ obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/ obj-$(CONFIG_DRM_VIA) +=via/ obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/ -ifeq ($(CONFIG_NAPLES_COMMON),y) -else -obj-$(CONFIG_DRM_EXYNOS) +=exynos/ -endif -obj-$(CONFIG_DRM_GMA500) += gma500/ -obj-$(CONFIG_DRM_UDL) += udl/ obj-y += i2c/ diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig deleted file mode 100644 index b4ae4c5..0000000 --- a/drivers/gpu/drm/exynos/Kconfig +++ /dev/null @@ -1,88 +0,0 @@ -config DRM_EXYNOS - tristate "DRM Support for Samsung SoC EXYNOS Series" - depends on DRM && PLAT_SAMSUNG - select DRM_KMS_HELPER - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE - help - Choose this option if you have a Samsung SoC EXYNOS chipset. - If M is selected the module will be called exynosdrm. - -config DRM_EXYNOS_MEMSIZE - int "Memory size in kbytes for DRM" - depends on DRM_EXYNOS - default "32768" - -config DRM_EXYNOS_IOMMU - bool "GEM IOMMU Support" - depends on DRM_EXYNOS - help - Choose this option if you want to use GEM IOMMU feature for DRM. - -config DRM_EXYNOS_DMABUF - bool "GEM DMABUF Support" - depends on DRM_EXYNOS - help - Choose this option if you want to use GEM DMABUF feature for DRM. - -config DRM_EXYNOS_FIMD - bool "Samsung DRM FIMD" - depends on DRM_EXYNOS - help - Choose this option if you want to use Samsung FIMD for DRM. - -config DRM_EXYNOS_FIMD_WB - bool "Samsung DRM FIMD WB" - depends on DRM_EXYNOS_FIMD - help - This option enables writeback operations in FIMD for DRM. - It can support fimd streams data to fimc destinations ram. - writeback operations support final blended stream. - when enable this options. - -config DRM_EXYNOS_HDMI - bool "Samsung DRM HDMI" - depends on DRM_EXYNOS - help - Choose this option if you want to use Samsung HDMI for DRM. - -config DRM_EXYNOS_VIDI - bool "Samsung DRM Virtual Display" - depends on DRM_EXYNOS - help - Choose this option if you want to use Samsung VIDI for DRM. - -config DRM_EXYNOS_G2D - bool "Samsung DRM G2D" - depends on DRM_EXYNOS - help - Choose this option if you want to use Samsung G2D for DRM. - -config DRM_EXYNOS_IPP - bool "Samsung DRM IPP" - depends on DRM_EXYNOS - help - This option enables IPP drivers for FIMC, GSC, Rotator. - It can support user space ioctl for each devices. - ipp operations support rotating and scaling, writeback, flip, output - when enable this options. - -config DRM_EXYNOS_ROTATOR - bool "Samsung DRM Rotator" - depends on DRM_EXYNOS_IPP - help - Choose this option if you want to use Samsung Rotator for DRM. - -config DRM_EXYNOS_FIMC - bool "Samsung DRM FIMC" - depends on DRM_EXYNOS_IPP - help - Choose this option if you want to use Samsung FIMC for DRM. - -config DRM_EXYNOS_GSC - bool "Samsung DRM GSC" - depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 - help - Choose this option if you want to use Samsung GSC for DRM. diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile deleted file mode 100644 index 369b3a5..0000000 --- a/drivers/gpu/drm/exynos/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# -# Makefile for the drm device driver. This driver provides support for the -# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. - -ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos \ - -Idrivers/media/video/samsung/ump/include -exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \ - exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \ - exynos_drm_buf.o exynos_drm_ump.o exynos_drm_gem.o \ - exynos_drm_core.o exynos_drm_plane.o - -exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o -exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o -exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o -exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o exynos_ddc.o \ - exynos_hdmiphy.o exynos_drm_hdmi.o -exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o -exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o -exynosdrm-$(CONFIG_DRM_EXYNOS_IPP) += exynos_drm_ipp.o -exynosdrm-$(CONFIG_DRM_EXYNOS_ROTATOR) += exynos_drm_rotator.o -exynosdrm-$(CONFIG_DRM_EXYNOS_FIMC) += exynos_drm_fimc.o -exynosdrm-$(CONFIG_DRM_EXYNOS_GSC) += exynos_drm_gsc.o - -obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o diff --git a/drivers/gpu/drm/exynos/exynos_ddc.c b/drivers/gpu/drm/exynos/exynos_ddc.c deleted file mode 100644 index 7e1051d..0000000 --- a/drivers/gpu/drm/exynos/exynos_ddc.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics Co.Ltd - * Authors: - * Seung-Woo Kim - * Inki Dae - * - * 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 "drmP.h" - -#include -#include -#include - - -#include "exynos_drm_drv.h" -#include "exynos_hdmi.h" - -static int s5p_ddc_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - hdmi_attach_ddc_client(client); - - dev_info(&client->adapter->dev, "attached s5p_ddc " - "into i2c adapter successfully\n"); - - return 0; -} - -static int s5p_ddc_remove(struct i2c_client *client) -{ - dev_info(&client->adapter->dev, "detached s5p_ddc " - "from i2c adapter successfully\n"); - - return 0; -} - -static struct i2c_device_id ddc_idtable[] = { - {"s5p_ddc", 0}, - { }, -}; - -struct i2c_driver ddc_driver = { - .driver = { - .name = "s5p_ddc", - .owner = THIS_MODULE, - }, - .id_table = ddc_idtable, - .probe = s5p_ddc_probe, - .remove = __devexit_p(s5p_ddc_remove), - .command = NULL, -}; diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c deleted file mode 100644 index a0b27d9..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_buf.c +++ /dev/null @@ -1,245 +0,0 @@ -/* exynos_drm_buf.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Author: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm.h" -#include "exynos_drm.h" - -#include -#include "exynos_drm_drv.h" -#include "exynos_drm_gem.h" -#include "exynos_drm_buf.h" - -static int lowlevel_buffer_allocate(struct drm_device *dev, - unsigned int flags, struct exynos_drm_gem_buf *buf) -{ - dma_addr_t start_addr; - unsigned int npages, i = 0; - struct scatterlist *sgl; - int ret = 0; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (IS_NONCONTIG_BUFFER(flags)) { - DRM_DEBUG_KMS("not support allocation type.\n"); - return -EINVAL; - } - - if (buf->paddr) { - DRM_DEBUG_KMS("already allocated.\n"); - return 0; - } - - if (buf->size >= SZ_1M) { - npages = buf->size >> SECTION_SHIFT; - buf->page_size = SECTION_SIZE; - } else if (buf->size >= SZ_64K) { - npages = buf->size >> 16; - buf->page_size = SZ_64K; - } else { - npages = buf->size >> PAGE_SHIFT; - buf->page_size = PAGE_SIZE; - } - - buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); - if (!buf->sgt) { - DRM_ERROR("failed to allocate sg table.\n"); - return -ENOMEM; - } - - ret = sg_alloc_table(buf->sgt, npages, GFP_KERNEL); - if (ret < 0) { - DRM_ERROR("failed to initialize sg table.\n"); - kfree(buf->sgt); - buf->sgt = NULL; - return -ENOMEM; - } - -#ifdef CONFIG_CMA - buf->paddr = cma_alloc(dev->dev, "drm", buf->size, - buf->page_size); - if (IS_ERR((void *)buf->paddr)) { - DRM_DEBUG_KMS("cma_alloc of size %ld failed\n", - buf->size); - ret = -ENOMEM; - goto err1; - } - - buf->kvaddr = phys_to_virt(buf->paddr); -#else - /* align it as page size(page or section) TODO */ - - buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size, - &buf->paddr, GFP_KERNEL); - if (!buf->kvaddr) { - DRM_ERROR("failed to allocate buffer.\n"); - ret = -ENOMEM; - goto err1; - } -#endif - buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL); - if (!buf->pages) { - DRM_ERROR("failed to allocate pages.\n"); - ret = -ENOMEM; - goto err2; - } - - sgl = buf->sgt->sgl; - start_addr = buf->paddr; - - while (i < npages) { - buf->pages[i] = phys_to_page(start_addr); - sg_set_page(sgl, buf->pages[i], buf->page_size, 0); - sg_dma_address(sgl) = start_addr; - start_addr += buf->page_size; - sgl = sg_next(sgl); - i++; - } - - DRM_INFO("vaddr(0x%lx), paddr(0x%lx), size(0x%lx)\n", - (unsigned long)buf->kvaddr, - (unsigned long)buf->paddr, - buf->size); - - return ret; -err2: -#ifdef CONFIG_CMA - cma_free(buf->paddr); -#else - dma_free_writecombine(dev->dev, buf->size, buf->kvaddr, - (dma_addr_t)buf->paddr); -#endif - buf->paddr = (dma_addr_t)NULL; -err1: - sg_free_table(buf->sgt); - kfree(buf->sgt); - buf->sgt = NULL; - - return ret; -} - -static void lowlevel_buffer_deallocate(struct drm_device *dev, - unsigned int flags, struct exynos_drm_gem_buf *buf) -{ - DRM_DEBUG_KMS("%s.\n", __FILE__); - - /* - * release only physically continuous memory and - * non-continuous memory would be released by exynos - * gem framework. - */ - if (IS_NONCONTIG_BUFFER(flags)) { - DRM_DEBUG_KMS("not support allocation type.\n"); - return; - } - - if (!buf->paddr) { - DRM_DEBUG_KMS("paddr is invalid.\n"); - return; - } - - if (buf->sgt) { - sg_free_table(buf->sgt); - kfree(buf->sgt); - buf->sgt = NULL; - } - - kfree(buf->pages); - buf->pages = NULL; - - /* - * now buffer is being shared and it would be released - * by original owner so ignor free action. - * this buffer was imported from physical memory to gem directly - * and this feature is used temporarily so removed later. - */ - if (buf->shared) - return; - -#ifdef CONFIG_CMA - cma_free(buf->paddr); -#else - dma_free_writecombine(dev->dev, buf->size, buf->kvaddr, - (dma_addr_t)buf->paddr); -#endif - buf->paddr = (dma_addr_t)NULL; -} - -struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev, - unsigned int size) -{ - struct exynos_drm_gem_buf *buffer; - - DRM_DEBUG_KMS("%s.\n", __FILE__); - DRM_DEBUG_KMS("desired size = 0x%x\n", size); - - buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); - if (!buffer) { - DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n"); - return NULL; - } - - buffer->size = size; - return buffer; -} - -void exynos_drm_fini_buf(struct drm_device *dev, - struct exynos_drm_gem_buf *buffer) -{ - DRM_DEBUG_KMS("%s.\n", __FILE__); - - if (!buffer) { - DRM_DEBUG_KMS("buffer is null.\n"); - return; - } - - kfree(buffer); - buffer = NULL; -} - -int exynos_drm_alloc_buf(struct drm_device *dev, - struct exynos_drm_gem_buf *buf, unsigned int flags) -{ - - /* - * allocate memory region and set the memory information - * to vaddr and paddr of a buffer object. - */ - if (lowlevel_buffer_allocate(dev, flags, buf) < 0) - return -ENOMEM; - - return 0; -} - -void exynos_drm_free_buf(struct drm_device *dev, - unsigned int flags, struct exynos_drm_gem_buf *buffer) -{ - - lowlevel_buffer_deallocate(dev, flags, buffer); -} - -MODULE_AUTHOR("Inki Dae "); -MODULE_DESCRIPTION("Samsung SoC DRM Buffer Management Module"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.h b/drivers/gpu/drm/exynos/exynos_drm_buf.h deleted file mode 100644 index 3388e4e..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_buf.h +++ /dev/null @@ -1,47 +0,0 @@ -/* exynos_drm_buf.h - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Author: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_BUF_H_ -#define _EXYNOS_DRM_BUF_H_ - -/* create and initialize buffer object. */ -struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev, - unsigned int size); - -/* destroy buffer object. */ -void exynos_drm_fini_buf(struct drm_device *dev, - struct exynos_drm_gem_buf *buffer); - -/* allocate physical memory region and setup sgt and pages. */ -int exynos_drm_alloc_buf(struct drm_device *dev, - struct exynos_drm_gem_buf *buf, - unsigned int flags); - -/* release physical memory region, sgt and pages. */ -void exynos_drm_free_buf(struct drm_device *dev, - unsigned int flags, - struct exynos_drm_gem_buf *buffer); - -#endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c deleted file mode 100644 index 0efb6df..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm_crtc_helper.h" - -#include -#include "exynos_drm_drv.h" -#include "exynos_drm_encoder.h" - -#define MAX_EDID 256 -#define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\ - drm_connector) - -struct exynos_drm_connector { - struct drm_connector drm_connector; - uint32_t encoder_id; - struct exynos_drm_manager *manager; -}; - -/* convert exynos_video_timings to drm_display_mode */ -static inline void -convert_to_display_mode(struct drm_display_mode *mode, - struct exynos_drm_panel_info *panel) -{ - struct fb_videomode *timing = &panel->timing; - DRM_DEBUG_KMS("%s\n", __FILE__); - - mode->clock = timing->pixclock / 1000; - mode->vrefresh = timing->refresh; - - mode->hdisplay = timing->xres; - mode->hsync_start = mode->hdisplay + timing->right_margin; - mode->hsync_end = mode->hsync_start + timing->hsync_len; - mode->htotal = mode->hsync_end + timing->left_margin; - - mode->vdisplay = timing->yres; - mode->vsync_start = mode->vdisplay + timing->lower_margin; - mode->vsync_end = mode->vsync_start + timing->vsync_len; - mode->vtotal = mode->vsync_end + timing->upper_margin; - mode->width_mm = panel->width_mm; - mode->height_mm = panel->height_mm; - - if (timing->vmode & FB_VMODE_INTERLACED) - mode->flags |= DRM_MODE_FLAG_INTERLACE; - - if (timing->vmode & FB_VMODE_DOUBLE) - mode->flags |= DRM_MODE_FLAG_DBLSCAN; -} - -/* convert drm_display_mode to exynos_video_timings */ -static inline void -convert_to_video_timing(struct fb_videomode *timing, - struct drm_display_mode *mode) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - memset(timing, 0, sizeof(*timing)); - - timing->pixclock = mode->clock * 1000; - timing->refresh = drm_mode_vrefresh(mode); - - timing->xres = mode->hdisplay; - timing->right_margin = mode->hsync_start - mode->hdisplay; - timing->hsync_len = mode->hsync_end - mode->hsync_start; - timing->left_margin = mode->htotal - mode->hsync_end; - - timing->yres = mode->vdisplay; - timing->lower_margin = mode->vsync_start - mode->vdisplay; - timing->vsync_len = mode->vsync_end - mode->vsync_start; - timing->upper_margin = mode->vtotal - mode->vsync_end; - - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - timing->vmode = FB_VMODE_INTERLACED; - else - timing->vmode = FB_VMODE_NONINTERLACED; - - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - timing->vmode |= FB_VMODE_DOUBLE; -} - -static int exynos_drm_connector_get_modes(struct drm_connector *connector) -{ - struct exynos_drm_connector *exynos_connector = - to_exynos_connector(connector); - struct exynos_drm_manager *manager = exynos_connector->manager; - struct exynos_drm_display_ops *display_ops = manager->display_ops; - unsigned int count; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!display_ops) { - DRM_DEBUG_KMS("display_ops is null.\n"); - return 0; - } - - /* - * if get_edid() exists then get_edid() callback of hdmi side - * is called to get edid data through i2c interface else - * get timing from the FIMD driver(display controller). - * - * P.S. in case of lcd panel, count is always 1 if success - * because lcd panel has only one mode. - */ - if (display_ops->get_edid) { - int ret; - void *edid; - - edid = kzalloc(MAX_EDID, GFP_KERNEL); - if (!edid) { - DRM_ERROR("failed to allocate edid\n"); - return 0; - } - - ret = display_ops->get_edid(manager->dev, connector, - edid, MAX_EDID); - if (ret < 0) { - DRM_ERROR("failed to get edid data.\n"); - kfree(edid); - edid = NULL; - return 0; - } - - drm_mode_connector_update_edid_property(connector, edid); - count = drm_add_edid_modes(connector, edid); - - kfree(connector->display_info.raw_edid); - connector->display_info.raw_edid = edid; - } else { - struct drm_display_mode *mode = drm_mode_create(connector->dev); - struct exynos_drm_panel_info *panel; - - if (display_ops->get_panel) - panel = display_ops->get_panel(manager->dev); - else { - drm_mode_destroy(connector->dev, mode); - return 0; - } - - convert_to_display_mode(mode, panel); - connector->display_info.width_mm = mode->width_mm; - connector->display_info.height_mm = mode->height_mm; - - mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; - drm_mode_set_name(mode); - drm_mode_probed_add(connector, mode); - - count = 1; - } - - return count; -} - -static int exynos_drm_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct exynos_drm_connector *exynos_connector = - to_exynos_connector(connector); - struct exynos_drm_manager *manager = exynos_connector->manager; - struct exynos_drm_display_ops *display_ops = manager->display_ops; - struct fb_videomode timing; - int ret = MODE_BAD; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - convert_to_video_timing(&timing, mode); - - if (display_ops && display_ops->check_timing) - if (!display_ops->check_timing(manager->dev, (void *)&timing)) - ret = MODE_OK; - - return ret; -} - -struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector) -{ - struct drm_device *dev = connector->dev; - struct exynos_drm_connector *exynos_connector = - to_exynos_connector(connector); - struct drm_mode_object *obj; - struct drm_encoder *encoder; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - obj = drm_mode_object_find(dev, exynos_connector->encoder_id, - DRM_MODE_OBJECT_ENCODER); - if (!obj) { - DRM_DEBUG_KMS("Unknown ENCODER ID %d\n", - exynos_connector->encoder_id); - return NULL; - } - - encoder = obj_to_encoder(obj); - - return encoder; -} - -static struct drm_connector_helper_funcs exynos_connector_helper_funcs = { - .get_modes = exynos_drm_connector_get_modes, - .mode_valid = exynos_drm_connector_mode_valid, - .best_encoder = exynos_drm_best_encoder, -}; - -static int exynos_drm_connector_fill_modes(struct drm_connector *connector, - unsigned int max_width, unsigned int max_height) -{ - struct exynos_drm_connector *exynos_connector = - to_exynos_connector(connector); - struct exynos_drm_manager *manager = exynos_connector->manager; - struct exynos_drm_manager_ops *ops = manager->ops; - unsigned int width, height; - - width = max_width; - height = max_height; - - /* - * if specific driver want to find desired_mode using maxmum - * resolution then get max width and height from that driver. - */ - if (ops && ops->get_max_resol) - ops->get_max_resol(manager->dev, &width, &height); - - return drm_helper_probe_single_connector_modes(connector, width, - height); -} - -/* get detection status of display device. */ -static enum drm_connector_status -exynos_drm_connector_detect(struct drm_connector *connector, bool force) -{ - struct exynos_drm_connector *exynos_connector = - to_exynos_connector(connector); - struct exynos_drm_manager *manager = exynos_connector->manager; - struct exynos_drm_display_ops *display_ops = - manager->display_ops; - enum drm_connector_status status = connector_status_disconnected; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (display_ops && display_ops->is_connected) { - if (display_ops->is_connected(manager->dev)) - status = connector_status_connected; - else - status = connector_status_disconnected; - } - - return status; -} - -static void exynos_drm_connector_destroy(struct drm_connector *connector) -{ - struct exynos_drm_connector *exynos_connector = - to_exynos_connector(connector); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - drm_sysfs_connector_remove(connector); - drm_connector_cleanup(connector); - kfree(exynos_connector); -} - -static struct drm_connector_funcs exynos_connector_funcs = { - .dpms = drm_helper_connector_dpms, - .fill_modes = exynos_drm_connector_fill_modes, - .detect = exynos_drm_connector_detect, - .destroy = exynos_drm_connector_destroy, -}; - -struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, - struct drm_encoder *encoder) -{ - struct exynos_drm_connector *exynos_connector; - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); - struct drm_connector *connector; - int type; - int err; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL); - if (!exynos_connector) { - DRM_ERROR("failed to allocate connector\n"); - return NULL; - } - - connector = &exynos_connector->drm_connector; - - switch (manager->display_ops->type) { - case EXYNOS_DISPLAY_TYPE_HDMI: - type = DRM_MODE_CONNECTOR_HDMIA; - connector->interlace_allowed = true; - connector->polled = DRM_CONNECTOR_POLL_HPD; - break; - case EXYNOS_DISPLAY_TYPE_LCD: - type = DRM_MODE_CONNECTOR_LVDS; - break; - case EXYNOS_DISPLAY_TYPE_VIDI: - type = DRM_MODE_CONNECTOR_VIRTUAL; - connector->polled = DRM_CONNECTOR_POLL_HPD; - break; - default: - type = DRM_MODE_CONNECTOR_Unknown; - break; - } - - drm_connector_init(dev, connector, &exynos_connector_funcs, type); - drm_connector_helper_add(connector, &exynos_connector_helper_funcs); - - err = drm_sysfs_connector_add(connector); - if (err) - goto err_connector; - - exynos_connector->encoder_id = encoder->base.id; - exynos_connector->manager = manager; - connector->encoder = encoder; - - err = drm_mode_connector_attach_encoder(connector, encoder); - if (err) { - DRM_ERROR("failed to attach a connector to a encoder\n"); - goto err_sysfs; - } - - DRM_DEBUG_KMS("connector has been created\n"); - - return connector; - -err_sysfs: - drm_sysfs_connector_remove(connector); -err_connector: - drm_connector_cleanup(connector); - kfree(exynos_connector); - return NULL; -} diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.h b/drivers/gpu/drm/exynos/exynos_drm_connector.h deleted file mode 100644 index 1c7b2b5..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_CONNECTOR_H_ -#define _EXYNOS_DRM_CONNECTOR_H_ - -struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, - struct drm_encoder *encoder); - -#endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c deleted file mode 100644 index 80cba2f..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_core.c +++ /dev/null @@ -1,212 +0,0 @@ -/* exynos_drm_core.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Author: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "exynos_drm_drv.h" -#include "exynos_drm_encoder.h" -#include "exynos_drm_connector.h" -#include "exynos_drm_fbdev.h" - -static LIST_HEAD(exynos_drm_subdrv_list); - -static int exynos_drm_subdrv_probe(struct drm_device *dev, - struct exynos_drm_subdrv *subdrv) -{ - struct drm_encoder *encoder; - struct drm_connector *connector; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - if (subdrv->probe) { - int ret; - - /* - * this probe callback would be called by sub driver - * after setting of all resources to this sub driver, - * such as clock, irq and register map are done or by load() - * of exynos drm driver. - * - * P.S. note that this driver is considered for modularization. - */ - ret = subdrv->probe(dev, subdrv->dev); - if (ret) - return ret; - } - - if (!subdrv->manager) - return 0; - - subdrv->manager->dev = subdrv->dev; - - /* create and initialize a encoder for this sub driver. */ - encoder = exynos_drm_encoder_create(dev, subdrv->manager, - (1 << MAX_CRTC) - 1); - if (!encoder) { - DRM_ERROR("failed to create encoder\n"); - return -EFAULT; - } - - /* - * create and initialize a connector for this sub driver and - * attach the encoder created above to the connector. - */ - connector = exynos_drm_connector_create(dev, encoder); - if (!connector) { - DRM_ERROR("failed to create connector\n"); - encoder->funcs->destroy(encoder); - return -EFAULT; - } - - subdrv->encoder = encoder; - subdrv->connector = connector; - - return 0; -} - -static void exynos_drm_subdrv_remove(struct drm_device *dev, - struct exynos_drm_subdrv *subdrv) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - if (subdrv->remove) - subdrv->remove(dev, subdrv->dev); - - if (subdrv->encoder) { - struct drm_encoder *encoder = subdrv->encoder; - encoder->funcs->destroy(encoder); - subdrv->encoder = NULL; - } - - if (subdrv->connector) { - struct drm_connector *connector = subdrv->connector; - connector->funcs->destroy(connector); - subdrv->connector = NULL; - } -} - -int exynos_drm_device_register(struct drm_device *dev) -{ - struct exynos_drm_subdrv *subdrv, *n; - int err; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - if (!dev) - return -EINVAL; - - list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) { - subdrv->drm_dev = dev; - err = exynos_drm_subdrv_probe(dev, subdrv); - if (err) { - DRM_DEBUG("exynos drm subdrv probe failed.\n"); - list_del(&subdrv->list); - } - } - - return 0; -} -EXPORT_SYMBOL_GPL(exynos_drm_device_register); - -int exynos_drm_device_unregister(struct drm_device *dev) -{ - struct exynos_drm_subdrv *subdrv; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - if (!dev) { - WARN(1, "Unexpected drm device unregister!\n"); - return -EINVAL; - } - - list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) - exynos_drm_subdrv_remove(dev, subdrv); - - return 0; -} -EXPORT_SYMBOL_GPL(exynos_drm_device_unregister); - -int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - if (!subdrv) - return -EINVAL; - - list_add_tail(&subdrv->list, &exynos_drm_subdrv_list); - - return 0; -} -EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register); - -int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - if (!subdrv) - return -EINVAL; - - list_del(&subdrv->list); - - return 0; -} -EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister); - -int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file) -{ - struct exynos_drm_subdrv *subdrv; - int ret; - - list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) { - if (subdrv->open) { - ret = subdrv->open(dev, subdrv->dev, file); - if (ret) - goto err; - } - } - - return 0; - -err: - list_for_each_entry_reverse(subdrv, &subdrv->list, list) { - if (subdrv->close) - subdrv->close(dev, subdrv->dev, file); - } - return ret; -} -EXPORT_SYMBOL_GPL(exynos_drm_subdrv_open); - -void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file) -{ - struct exynos_drm_subdrv *subdrv; - - list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) { - if (subdrv->close) - subdrv->close(dev, subdrv->dev, file); - } -} -EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close); diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c deleted file mode 100644 index 5904c58..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ /dev/null @@ -1,398 +0,0 @@ -/* exynos_drm_crtc.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm_crtc_helper.h" - -#include "exynos_drm_drv.h" -#include "exynos_drm_encoder.h" -#include "exynos_drm_plane.h" - -#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\ - drm_crtc) - -enum exynos_crtc_mode { - CRTC_MODE_NORMAL, /* normal mode */ - CRTC_MODE_BLANK, /* The private plane of crtc is blank */ -}; - -/* - * Exynos specific crtc structure. - * - * @drm_crtc: crtc object. - * @drm_plane: pointer of private plane object for this crtc - * @pipe: a crtc index created at load() with a new crtc object creation - * and the crtc object would be set to private->crtc array - * to get a crtc object corresponding to this pipe from private->crtc - * array when irq interrupt occured. the reason of using this pipe is that - * drm framework doesn't support multiple irq yet. - * we can refer to the crtc to current hardware interrupt occured through - * this pipe value. - * @dpms: store the crtc dpms value - * @mode: store the crtc mode value - */ -struct exynos_drm_crtc { - struct drm_crtc drm_crtc; - struct drm_plane *plane; - unsigned int pipe; - unsigned int dpms; - enum exynos_crtc_mode mode; -}; - -static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) -{ - struct drm_device *dev = crtc->dev; - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - - DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode); - - if (exynos_crtc->dpms == mode) { - DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n"); - return; - } - - mutex_lock(&dev->struct_mutex); - - exynos_drm_fn_encoder(crtc, &mode, exynos_drm_encoder_crtc_dpms); - exynos_crtc->dpms = mode; - - mutex_unlock(&dev->struct_mutex); -} - -static void exynos_drm_crtc_prepare(struct drm_crtc *crtc) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* drm framework doesn't check NULL. */ -} - -static void exynos_drm_crtc_commit(struct drm_crtc *crtc) -{ - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_plane_commit(exynos_crtc->plane); - exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON); -} - -static bool -exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* drm framework doesn't check NULL */ - return true; -} - -static int -exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y, - struct drm_framebuffer *old_fb) -{ - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct drm_plane *plane = exynos_crtc->plane; - unsigned int crtc_w; - unsigned int crtc_h; - int pipe = exynos_crtc->pipe; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON); - - /* - * copy the mode data adjusted by mode_fixup() into crtc->mode - * so that hardware can be seet to proper mode. - */ - memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode)); - - crtc_w = crtc->fb->width - x; - crtc_h = crtc->fb->height - y; - - ret = exynos_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h, - x, y, crtc_w, crtc_h); - if (ret) - return ret; - - plane->crtc = crtc; - plane->fb = crtc->fb; - - exynos_drm_fn_encoder(crtc, &pipe, exynos_drm_encoder_crtc_pipe); - - return 0; -} - -static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) -{ - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct drm_plane *plane = exynos_crtc->plane; - unsigned int crtc_w; - unsigned int crtc_h; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - crtc_w = crtc->fb->width - x; - crtc_h = crtc->fb->height - y; - - ret = exynos_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h, - x, y, crtc_w, crtc_h); - if (ret) - return ret; - - exynos_drm_crtc_commit(crtc); - - return 0; -} - -static void exynos_drm_crtc_load_lut(struct drm_crtc *crtc) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - /* drm framework doesn't check NULL */ -} - -static void exynos_drm_crtc_disable(struct drm_crtc *crtc) -{ - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_OFF); - exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); -} - -static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { - .dpms = exynos_drm_crtc_dpms, - .prepare = exynos_drm_crtc_prepare, - .commit = exynos_drm_crtc_commit, - .mode_fixup = exynos_drm_crtc_mode_fixup, - .mode_set = exynos_drm_crtc_mode_set, - .mode_set_base = exynos_drm_crtc_mode_set_base, - .load_lut = exynos_drm_crtc_load_lut, - .disable = exynos_drm_crtc_disable, -}; - -static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event) -{ - struct drm_device *dev = crtc->dev; - struct exynos_drm_private *dev_priv = dev->dev_private; - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct drm_framebuffer *old_fb = crtc->fb; - int ret = -EINVAL; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - mutex_lock(&dev->struct_mutex); - - if (event) { - /* - * the pipe from user always is 0 so we can set pipe number - * of current owner to event. - */ - event->pipe = exynos_crtc->pipe; - - ret = drm_vblank_get(dev, exynos_crtc->pipe); - if (ret) { - DRM_DEBUG("failed to acquire vblank counter\n"); - list_del(&event->base.link); - - goto out; - } - - list_add_tail(&event->base.link, - &dev_priv->pageflip_event_list); - - crtc->fb = fb; - ret = exynos_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y, - NULL); - if (ret) { - crtc->fb = old_fb; - drm_vblank_put(dev, exynos_crtc->pipe); - list_del(&event->base.link); - - goto out; - } - } -out: - mutex_unlock(&dev->struct_mutex); - return ret; -} - -static void exynos_drm_crtc_destroy(struct drm_crtc *crtc) -{ - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct exynos_drm_private *private = crtc->dev->dev_private; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - private->crtc[exynos_crtc->pipe] = NULL; - - drm_crtc_cleanup(crtc); - kfree(exynos_crtc); -} - -static int exynos_drm_crtc_set_property(struct drm_crtc *crtc, - struct drm_property *property, - uint64_t val) -{ - struct drm_device *dev = crtc->dev; - struct exynos_drm_private *dev_priv = dev->dev_private; - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - - DRM_DEBUG_KMS("%s\n", __func__); - - if (property == dev_priv->crtc_mode_property) { - enum exynos_crtc_mode mode = val; - - if (mode == exynos_crtc->mode) - return 0; - - exynos_crtc->mode = mode; - - switch (mode) { - case CRTC_MODE_NORMAL: - exynos_drm_crtc_commit(crtc); - break; - case CRTC_MODE_BLANK: - exynos_plane_dpms(exynos_crtc->plane, - DRM_MODE_DPMS_OFF); - break; - default: - break; - } - - return 0; - } - - return -EINVAL; -} - -static struct drm_crtc_funcs exynos_crtc_funcs = { - .set_config = drm_crtc_helper_set_config, - .page_flip = exynos_drm_crtc_page_flip, - .destroy = exynos_drm_crtc_destroy, - .set_property = exynos_drm_crtc_set_property, -}; - -static const struct drm_prop_enum_list mode_names[] = { - { CRTC_MODE_NORMAL, "normal" }, - { CRTC_MODE_BLANK, "blank" }, -}; - -static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct exynos_drm_private *dev_priv = dev->dev_private; - struct drm_property *prop; - - DRM_DEBUG_KMS("%s\n", __func__); - - prop = dev_priv->crtc_mode_property; - if (!prop) { - prop = drm_property_create_enum(dev, 0, "mode", mode_names, - ARRAY_SIZE(mode_names)); - if (!prop) - return; - - dev_priv->crtc_mode_property = prop; - } - - drm_object_attach_property(&crtc->base, prop, 0); -} - -int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) -{ - struct exynos_drm_crtc *exynos_crtc; - struct exynos_drm_private *private = dev->dev_private; - struct drm_crtc *crtc; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL); - if (!exynos_crtc) { - DRM_ERROR("failed to allocate exynos crtc\n"); - return -ENOMEM; - } - - exynos_crtc->pipe = nr; - exynos_crtc->dpms = DRM_MODE_DPMS_ON; - exynos_crtc->plane = exynos_plane_init(dev, 1 << nr, true); - if (!exynos_crtc->plane) { - kfree(exynos_crtc); - return -ENOMEM; - } - - crtc = &exynos_crtc->drm_crtc; - - private->crtc[nr] = crtc; - - drm_crtc_init(dev, crtc, &exynos_crtc_funcs); - drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs); - - exynos_drm_crtc_attach_mode_property(crtc); - - return 0; -} - -int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc) -{ - struct exynos_drm_private *private = dev->dev_private; - struct exynos_drm_crtc *exynos_crtc = - to_exynos_crtc(private->crtc[crtc]); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) - return -EPERM; - - exynos_drm_fn_encoder(private->crtc[crtc], &crtc, - exynos_drm_enable_vblank); - - return 0; -} - -void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc) -{ - struct exynos_drm_private *private = dev->dev_private; - struct exynos_drm_crtc *exynos_crtc = - to_exynos_crtc(private->crtc[crtc]); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) - return; - - exynos_drm_fn_encoder(private->crtc[crtc], &crtc, - exynos_drm_disable_vblank); -} diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h deleted file mode 100644 index 6bae8d8..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h +++ /dev/null @@ -1,36 +0,0 @@ -/* exynos_drm_crtc.h - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_CRTC_H_ -#define _EXYNOS_DRM_CRTC_H_ - -int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr); -int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc); -void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc); - -#endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c deleted file mode 100644 index 128627c..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ /dev/null @@ -1,285 +0,0 @@ -/* exynos_drm_dmabuf.c - * - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * Author: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm.h" -#include "exynos_drm.h" -#include "exynos_drm_drv.h" -#include "exynos_drm_gem.h" - -#include - -static struct sg_table *exynos_pages_to_sg(struct page **pages, int nr_pages, - unsigned int page_size) -{ - struct sg_table *sgt = NULL; - struct scatterlist *sgl; - int i, ret; - - sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); - if (!sgt) - goto out; - - ret = sg_alloc_table(sgt, nr_pages, GFP_KERNEL); - if (ret) - goto err_free_sgt; - - if (page_size < PAGE_SIZE) - page_size = PAGE_SIZE; - - for_each_sg(sgt->sgl, sgl, nr_pages, i) - sg_set_page(sgl, pages[i], page_size, 0); - - return sgt; - -err_free_sgt: - kfree(sgt); - sgt = NULL; -out: - return NULL; -} - -static struct sg_table *exynos_gem_map_dma_buf(struct dma_buf_attachment *attach, - enum dma_data_direction dir) -{ - struct exynos_drm_gem_obj *gem_obj = attach->dmabuf->priv; - struct drm_device *dev = gem_obj->base.dev; - struct exynos_drm_gem_buf *buf; - struct sg_table *sgt = NULL; - unsigned int npages; - int nents; - - DRM_DEBUG_PRIME("%s\n", __FILE__); - - mutex_lock(&dev->struct_mutex); - - buf = gem_obj->buffer; - - /* there should always be pages allocated. */ - if (!buf->pages) { - DRM_ERROR("pages is null.\n"); - goto err_unlock; - } - - npages = buf->size / buf->page_size; - - sgt = exynos_pages_to_sg(buf->pages, npages, buf->page_size); - nents = dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir); - - DRM_DEBUG_PRIME("npages = %d buffer size = 0x%lx page_size = 0x%lx\n", - npages, buf->size, buf->page_size); - -err_unlock: - mutex_unlock(&dev->struct_mutex); - return sgt; -} - -static void exynos_gem_unmap_dma_buf(struct dma_buf_attachment *attach, - struct sg_table *sgt, - enum dma_data_direction dir) -{ - dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir); - sg_free_table(sgt); - kfree(sgt); - sgt = NULL; -} - -static void exynos_dmabuf_release(struct dma_buf *dmabuf) -{ - struct exynos_drm_gem_obj *exynos_gem_obj = dmabuf->priv; - - DRM_DEBUG_PRIME("%s\n", __FILE__); - - /* - * exynos_dmabuf_release() call means that file object's - * f_count is 0 and it calls drm_gem_object_handle_unreference() - * to drop the references that these values had been increased - * at drm_prime_handle_to_fd() - */ - if (exynos_gem_obj->base.export_dma_buf == dmabuf) { - exynos_gem_obj->base.export_dma_buf = NULL; - - /* - * drop this gem object refcount to release allocated buffer - * and resources. - */ - drm_gem_object_unreference_unlocked(&exynos_gem_obj->base); - } -} - -static void *exynos_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, - unsigned long page_num) -{ - return NULL; -} - -static void exynos_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf, - unsigned long page_num, - void *addr) -{ - -} - -static void *exynos_gem_dmabuf_kmap(struct dma_buf *dma_buf, - unsigned long page_num) -{ - return NULL; -} - -static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf, - unsigned long page_num, void *addr) -{ - -} - -static struct dma_buf_ops exynos_dmabuf_ops = { - .map_dma_buf = exynos_gem_map_dma_buf, - .unmap_dma_buf = exynos_gem_unmap_dma_buf, - .kmap = exynos_gem_dmabuf_kmap, - .kmap_atomic = exynos_gem_dmabuf_kmap_atomic, - .kunmap = exynos_gem_dmabuf_kunmap, - .kunmap_atomic = exynos_gem_dmabuf_kunmap_atomic, - .release = exynos_dmabuf_release, -}; - -struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev, - struct drm_gem_object *obj, int flags) -{ - struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); - - return dma_buf_export(exynos_gem_obj, &exynos_dmabuf_ops, - exynos_gem_obj->base.size, 0600); -} - -struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, - struct dma_buf *dma_buf) -{ - struct dma_buf_attachment *attach; - struct sg_table *sgt; - struct scatterlist *sgl; - struct exynos_drm_gem_obj *exynos_gem_obj; - struct exynos_drm_gem_buf *buffer; - struct page *page; - int ret; - - DRM_DEBUG_PRIME("%s\n", __FILE__); - - /* is this one of own objects? */ - if (dma_buf->ops == &exynos_dmabuf_ops) { - struct drm_gem_object *obj; - - exynos_gem_obj = dma_buf->priv; - obj = &exynos_gem_obj->base; - - /* is it from our device? */ - if (obj->dev == drm_dev) { - drm_gem_object_reference(obj); - return obj; - } - } - - attach = dma_buf_attach(dma_buf, drm_dev->dev); - if (IS_ERR(attach)) - return ERR_PTR(-EINVAL); - - - sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); - if (IS_ERR(sgt)) { - ret = PTR_ERR(sgt); - goto err_buf_detach; - } - - buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); - if (!buffer) { - DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n"); - ret = -ENOMEM; - goto err_unmap_attach; - } - - buffer->pages = kzalloc(sizeof(*page) * sgt->nents, GFP_KERNEL); - if (!buffer->pages) { - DRM_ERROR("failed to allocate pages.\n"); - ret = -ENOMEM; - goto err_free_buffer; - } - - exynos_gem_obj = exynos_drm_gem_init(drm_dev, dma_buf->size); - if (!exynos_gem_obj) { - ret = -ENOMEM; - goto err_free_pages; - } - - sgl = sgt->sgl; - - if (sgt->nents == 1) { - buffer->dma_addr = sg_dma_address(sgt->sgl); - buffer->size = sg_dma_len(sgt->sgl); - - /* always physically continuous memory if sgt->nents is 1. */ - exynos_gem_obj->flags |= EXYNOS_BO_CONTIG; - } else { - unsigned int i = 0; - - buffer->dma_addr = sg_dma_address(sgl); - while (i < sgt->nents) { - buffer->pages[i] = sg_page(sgl); - buffer->size += sg_dma_len(sgl); - sgl = sg_next(sgl); - i++; - } - - /* - * this case could be CONTIG or NONCONTIG type but now CONTIG. - * we have to find a way that exporter can notify the type of - * its own buffer to importer. TODO - */ - exynos_gem_obj->flags |= EXYNOS_BO_NONCONTIG; - } - - exynos_gem_obj->buffer = buffer; - buffer->sgt = sgt; - exynos_gem_obj->base.import_attach = attach; - - DRM_DEBUG_PRIME("dma_addr = 0x%x, size = 0x%lx\n", buffer->dma_addr, - buffer->size); - - return &exynos_gem_obj->base; - -err_free_pages: - kfree(buffer->pages); - buffer->pages = NULL; -err_free_buffer: - kfree(buffer); - buffer = NULL; -err_unmap_attach: - dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); -err_buf_detach: - dma_buf_detach(dma_buf, attach); - return ERR_PTR(ret); -} - -MODULE_AUTHOR("Inki Dae "); -MODULE_DESCRIPTION("Samsung SoC DRM DMABUF Module"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h deleted file mode 100644 index 662a8f9..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h +++ /dev/null @@ -1,39 +0,0 @@ -/* exynos_drm_dmabuf.h - * - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * Author: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_DMABUF_H_ -#define _EXYNOS_DRM_DMABUF_H_ - -#ifdef CONFIG_DRM_EXYNOS_DMABUF -struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev, - struct drm_gem_object *obj, int flags); - -struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, - struct dma_buf *dma_buf); -#else -#define exynos_dmabuf_prime_export NULL -#define exynos_dmabuf_prime_import NULL -#endif -#endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c deleted file mode 100644 index 90cff3f..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ /dev/null @@ -1,578 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm.h" -#include "drm_crtc_helper.h" - -#include - -#include "exynos_drm_drv.h" -#include "exynos_drm_crtc.h" -#include "exynos_drm_encoder.h" -#include "exynos_drm_fbdev.h" -#include "exynos_drm_fb.h" -#include "exynos_drm_gem.h" -#include "exynos_drm_g2d.h" -#include "exynos_drm_ipp.h" -#include "exynos_drm_plane.h" -#include "exynos_drm_vidi.h" -#include "exynos_drm_dmabuf.h" -#include "exynos_drm_iommu.h" - -#define DRIVER_NAME "exynos" -#define DRIVER_DESC "Samsung SoC DRM" -#define DRIVER_DATE "20110530" -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 0 - -#define VBLANK_OFF_DELAY 50000 - -struct exynos_drm_gem_info_data { - struct drm_file *filp; - struct seq_file *m; -}; - -static int exynos_drm_gem_one_info(int id, void *ptr, void *data) -{ - struct drm_gem_object *obj = ptr; - struct exynos_drm_gem_info_data *gem_info_data = data; - struct drm_exynos_file_private *file_priv = - gem_info_data->filp->driver_priv; - struct exynos_drm_gem_obj *exynos_gem = to_exynos_gem_obj(obj); - struct exynos_drm_gem_buf *buf = exynos_gem->buffer; - - seq_printf(gem_info_data->m, "%3d \t%3d \t%3d \t%2d \t\t%2d \t0x%08lx"\ - " \t0x%x \t0x%08lx \t%2d \t\t%2d \t\t%2d\n", - gem_info_data->filp->pid, - file_priv->tgid, - id, - atomic_read(&obj->refcount.refcount), - atomic_read(&obj->handle_count), - exynos_gem->size, - exynos_gem->flags, - buf->page_size, - buf->pfnmap, - obj->export_dma_buf ? 1 : 0, - obj->import_attach ? 1 : 0); - - return 0; -} - -static int exynos_drm_gem_info(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *)m->private; - struct drm_device *drm_dev = node->minor->dev; - struct exynos_drm_gem_info_data gem_info_data; - - gem_info_data.m = m; - - seq_printf(gem_info_data.m, "pid \ttgid \thandle \trefcount \thcount "\ - "\tsize \t\tflags \tpage_size \tpfnmap \t"\ - "exyport_to_fd \timport_from_fd\n"); - - list_for_each_entry(gem_info_data.filp, &drm_dev->filelist, lhead) - idr_for_each(&gem_info_data.filp->object_idr, - exynos_drm_gem_one_info, &gem_info_data); - - return 0; -} - -static struct drm_info_list exynos_drm_debugfs_list[] = { - {"gem_info", exynos_drm_gem_info, DRIVER_GEM}, -}; -#define EXYNOS_DRM_DEBUGFS_ENTRIES ARRAY_SIZE(exynos_drm_debugfs_list) - -static int exynos_drm_load(struct drm_device *dev, unsigned long flags) -{ - struct exynos_drm_private *private; - struct drm_minor *minor; - int ret; - int nr; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL); - if (!private) { - DRM_ERROR("failed to allocate private\n"); - return -ENOMEM; - } - - /* maximum size of userptr is limited to 16MB as default. */ - private->userptr_limit = SZ_16M; - - /* setup device address space for iommu. */ - private->vmm = exynos_drm_iommu_setup(0x80000000, 0x40000000); - if (IS_ERR(private->vmm)) { - DRM_ERROR("failed to setup iommu.\n"); - kfree(private); - return PTR_ERR(private->vmm); - } - - INIT_LIST_HEAD(&private->pageflip_event_list); - dev->dev_private = (void *)private; - - drm_mode_config_init(dev); - - /* init kms poll for handling hpd */ - drm_kms_helper_poll_init(dev); - - exynos_drm_mode_config_init(dev); - - /* - * EXYNOS4 is enough to have two CRTCs and each crtc would be used - * without dependency of hardware. - */ - for (nr = 0; nr < MAX_CRTC; nr++) { - ret = exynos_drm_crtc_create(dev, nr); - if (ret) - goto err_crtc; - } - - for (nr = 0; nr < MAX_PLANE; nr++) { - struct drm_plane *plane; - unsigned int possible_crtcs = (1 << MAX_CRTC) - 1; - - plane = exynos_plane_init(dev, possible_crtcs, false); - if (!plane) - goto err_crtc; - } - - ret = drm_vblank_init(dev, MAX_CRTC); - if (ret) - goto err_crtc; - - /* - * probe sub drivers such as display controller and hdmi driver, - * that were registered at probe() of platform driver - * to the sub driver and create encoder and connector for them. - */ - ret = exynos_drm_device_register(dev); - if (ret) - goto err_vblank; - - /* setup possible_clones. */ - exynos_drm_encoder_setup(dev); - - /* - * create and configure fb helper and also exynos specific - * fbdev object. - */ - ret = exynos_drm_fbdev_init(dev); - if (ret) { - DRM_ERROR("failed to initialize drm fbdev\n"); - goto err_drm_device; - } - - drm_vblank_offdelay = VBLANK_OFF_DELAY; - - minor = dev->primary; - ret = drm_debugfs_create_files(exynos_drm_debugfs_list, - EXYNOS_DRM_DEBUGFS_ENTRIES, - minor->debugfs_root, minor); - if (ret) - DRM_DEBUG_DRIVER("failed to create exynos-drm debugfs.\n"); - - return 0; - -err_drm_device: - exynos_drm_device_unregister(dev); -err_vblank: - drm_vblank_cleanup(dev); -err_crtc: - drm_mode_config_cleanup(dev); - kfree(private); - - return ret; -} - -static int exynos_drm_unload(struct drm_device *dev) -{ - struct exynos_drm_private *private; - - private = dev->dev_private; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - /* release vmm object and device address space for iommu. */ - exynos_drm_iommu_cleanup(private->vmm); - - exynos_drm_fbdev_fini(dev); - exynos_drm_device_unregister(dev); - drm_vblank_cleanup(dev); - drm_kms_helper_poll_fini(dev); - drm_mode_config_cleanup(dev); - kfree(dev->dev_private); - - dev->dev_private = NULL; - - drm_debugfs_remove_files(exynos_drm_debugfs_list, - EXYNOS_DRM_DEBUGFS_ENTRIES, dev->primary); - - return 0; -} - -static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) -{ - struct drm_exynos_file_private *file_priv; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); - if (!file_priv) - return -ENOMEM; - - file_priv->tgid = task_tgid_nr(current); - - drm_prime_init_file_private(&file->prime); - file->driver_priv = file_priv; - - return exynos_drm_subdrv_open(dev, file); -} - -static void exynos_drm_preclose(struct drm_device *dev, - struct drm_file *file) -{ - struct exynos_drm_private *private = dev->dev_private; - struct drm_pending_vblank_event *e, *t; - unsigned long flags; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - /* release events of current file */ - spin_lock_irqsave(&dev->event_lock, flags); - list_for_each_entry_safe(e, t, &private->pageflip_event_list, - base.link) { - if (e->base.file_priv == file) { - list_del(&e->base.link); - e->base.destroy(&e->base); - } - } - drm_prime_destroy_file_private(&file->prime); - spin_unlock_irqrestore(&dev->event_lock, flags); - - exynos_drm_subdrv_close(dev, file); -} - -static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - if (!file->driver_priv) - return; - - kfree(file->driver_priv); - file->driver_priv = NULL; -} - -static void exynos_drm_lastclose(struct drm_device *dev) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - exynos_drm_fbdev_restore_mode(dev); -} - -static struct vm_operations_struct exynos_drm_gem_vm_ops = { - .fault = exynos_drm_gem_fault, - .open = drm_gem_vm_open, - .close = drm_gem_vm_close, -}; - -static struct drm_ioctl_desc exynos_ioctls[] = { - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl, - DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET, - exynos_drm_gem_map_offset_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP, - exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_USERPTR, - exynos_drm_gem_userptr_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET, - exynos_drm_gem_get_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(EXYNOS_USER_LIMIT, - exynos_drm_gem_user_limit_ioctl, DRM_MASTER | - DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_EXPORT_UMP, - exynos_drm_gem_export_ump_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CACHE_OP, - exynos_drm_gem_cache_op_ioctl, DRM_UNLOCKED), - /* temporary ioctl commands. */ - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET_PHY, - exynos_drm_gem_get_phy_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_PHY_IMP, - exynos_drm_gem_phy_imp_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION, - vidi_connection_ioctl, DRM_UNLOCKED | DRM_AUTH), - - DRM_IOCTL_DEF_DRV(EXYNOS_G2D_GET_VER, - exynos_g2d_get_ver_ioctl, DRM_UNLOCKED | DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_G2D_SET_CMDLIST, - exynos_g2d_set_cmdlist_ioctl, DRM_UNLOCKED | DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC, - exynos_g2d_exec_ioctl, DRM_UNLOCKED | DRM_AUTH), - - DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_PROPERTY, - exynos_drm_ipp_get_property, DRM_UNLOCKED | DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_IPP_SET_PROPERTY, - exynos_drm_ipp_set_property, DRM_UNLOCKED | DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_IPP_BUF, - exynos_drm_ipp_buf, DRM_UNLOCKED | DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_IPP_CTRL, - exynos_drm_ipp_ctrl, DRM_UNLOCKED | DRM_AUTH), -}; - -static const struct file_operations exynos_drm_driver_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .mmap = exynos_drm_gem_mmap, - .poll = drm_poll, - .read = drm_read, - .unlocked_ioctl = drm_ioctl, - .release = drm_release, -}; - -static struct drm_driver exynos_drm_driver = { - .driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET | - DRIVER_GEM | DRIVER_PRIME, - .load = exynos_drm_load, - .unload = exynos_drm_unload, - .open = exynos_drm_open, - .preclose = exynos_drm_preclose, - .lastclose = exynos_drm_lastclose, - .postclose = exynos_drm_postclose, - .get_vblank_counter = drm_vblank_count, - .enable_vblank = exynos_drm_crtc_enable_vblank, - .disable_vblank = exynos_drm_crtc_disable_vblank, - .gem_init_object = exynos_drm_gem_init_object, - .gem_free_object = exynos_drm_gem_free_object, - .gem_vm_ops = &exynos_drm_gem_vm_ops, - .gem_close_object = &exynos_drm_gem_close_object, - .dumb_create = exynos_drm_gem_dumb_create, - .dumb_map_offset = exynos_drm_gem_dumb_map_offset, - .dumb_destroy = exynos_drm_gem_dumb_destroy, - .prime_handle_to_fd = drm_gem_prime_handle_to_fd, - .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = exynos_dmabuf_prime_export, - .gem_prime_import = exynos_dmabuf_prime_import, - .ioctls = exynos_ioctls, - .fops = &exynos_drm_driver_fops, - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, -}; - -static int exynos_drm_platform_probe(struct platform_device *pdev) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls); - - return drm_platform_init(&exynos_drm_driver, pdev); -} - -static int exynos_drm_platform_remove(struct platform_device *pdev) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - drm_platform_exit(&exynos_drm_driver, pdev); - - return 0; -} - -static struct platform_driver exynos_drm_platform_driver = { - .probe = exynos_drm_platform_probe, - .remove = __devexit_p(exynos_drm_platform_remove), - .driver = { - .owner = THIS_MODULE, - .name = "exynos-drm", - }, -}; - -static int __init exynos_drm_init(void) -{ - int ret; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - -#ifdef CONFIG_DRM_EXYNOS_FIMD - ret = platform_driver_register(&fimd_driver); - if (ret < 0) - goto out_fimd; -#endif - -#ifdef CONFIG_DRM_EXYNOS_HDMI - ret = platform_driver_register(&hdmi_driver); - if (ret < 0) - goto out_hdmi; - ret = platform_driver_register(&mixer_driver); - if (ret < 0) - goto out_mixer; - ret = platform_driver_register(&exynos_drm_common_hdmi_driver); - if (ret < 0) - goto out_common_hdmi; -#endif - -#ifdef CONFIG_DRM_EXYNOS_VIDI - ret = platform_driver_register(&vidi_driver); - if (ret < 0) - goto out_vidi; -#endif - -#ifdef CONFIG_DRM_EXYNOS_G2D - ret = platform_driver_register(&g2d_driver); - if (ret < 0) - goto out_g2d; -#endif - -#ifdef CONFIG_DRM_EXYNOS_ROTATOR - ret = platform_driver_register(&rotator_driver); - if (ret < 0) - goto out_rotator; -#endif - -#ifdef CONFIG_DRM_EXYNOS_FIMC - ret = platform_driver_register(&fimc_driver); - if (ret < 0) - goto out_fimc; -#endif - -#ifdef CONFIG_DRM_EXYNOS_GSC - ret = platform_driver_register(&gsc_driver); - if (ret < 0) - goto out_gsc; -#endif - -#ifdef CONFIG_DRM_EXYNOS_IPP - ret = platform_driver_register(&ipp_driver); - if (ret < 0) - goto out_ipp; -#endif - - ret = platform_driver_register(&exynos_drm_platform_driver); - if (ret < 0) - goto out; - - return 0; - -out: -#ifdef CONFIG_DRM_EXYNOS_IPP - platform_driver_unregister(&ipp_driver); -out_ipp: -#endif - -#ifdef CONFIG_DRM_EXYNOS_GSC - platform_driver_unregister(&gsc_driver); -out_gsc: -#endif - -#ifdef CONFIG_DRM_EXYNOS_FIMC - platform_driver_unregister(&fimc_driver); -out_fimc: -#endif - -#ifdef CONFIG_DRM_EXYNOS_ROTATOR - platform_driver_unregister(&rotator_driver); -out_rotator: -#endif - -#ifdef CONFIG_DRM_EXYNOS_G2D - platform_driver_unregister(&g2d_driver); -out_g2d: -#endif - -#ifdef CONFIG_DRM_EXYNOS_VIDI - platform_driver_unregister(&vidi_driver); -out_vidi: -#endif - -#ifdef CONFIG_DRM_EXYNOS_HDMI - platform_driver_unregister(&exynos_drm_common_hdmi_driver); -out_common_hdmi: - platform_driver_unregister(&mixer_driver); -out_mixer: - platform_driver_unregister(&hdmi_driver); -out_hdmi: -#endif - -#ifdef CONFIG_DRM_EXYNOS_FIMD - platform_driver_unregister(&fimd_driver); -out_fimd: -#endif - return ret; -} - -static void __exit exynos_drm_exit(void) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - platform_driver_unregister(&exynos_drm_platform_driver); - -#ifdef CONFIG_DRM_EXYNOS_IPP - platform_driver_unregister(&ipp_driver); -#endif - -#ifdef CONFIG_DRM_EXYNOS_GSC - platform_driver_unregister(&gsc_driver); -#endif - -#ifdef CONFIG_DRM_EXYNOS_FIMC - platform_driver_unregister(&fimc_driver); -#endif - -#ifdef CONFIG_DRM_EXYNOS_ROTATOR - platform_driver_unregister(&rotator_driver); -#endif - -#ifdef CONFIG_DRM_EXYNOS_G2D - platform_driver_unregister(&g2d_driver); -#endif - -#ifdef CONFIG_DRM_EXYNOS_VIDI - platform_driver_unregister(&vidi_driver); -#endif - -#ifdef CONFIG_DRM_EXYNOS_HDMI - platform_driver_unregister(&exynos_drm_common_hdmi_driver); - platform_driver_unregister(&mixer_driver); - platform_driver_unregister(&hdmi_driver); -#endif - -#ifdef CONFIG_DRM_EXYNOS_FIMD - platform_driver_unregister(&fimd_driver); -#endif -} - -module_init(exynos_drm_init); -module_exit(exynos_drm_exit); - -MODULE_AUTHOR("Inki Dae "); -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_AUTHOR("Seung-Woo Kim "); -MODULE_DESCRIPTION("Samsung SoC DRM Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h deleted file mode 100644 index 8cdf93b..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ /dev/null @@ -1,350 +0,0 @@ -/* exynos_drm_drv.h - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_DRV_H_ -#define _EXYNOS_DRM_DRV_H_ - -#include -#include "drm.h" - -#define MAX_CRTC 3 -#define MAX_PLANE 5 -#define MAX_FB_BUFFER 4 -#define DEFAULT_ZPOS -1 - -struct drm_device; -struct exynos_drm_overlay; -struct drm_connector; - -extern unsigned int drm_vblank_offdelay; - -/* this enumerates display type. */ -enum exynos_drm_output_type { - EXYNOS_DISPLAY_TYPE_NONE, - /* RGB or CPU Interface. */ - EXYNOS_DISPLAY_TYPE_LCD, - /* HDMI Interface. */ - EXYNOS_DISPLAY_TYPE_HDMI, - /* Virtual Display Interface. */ - EXYNOS_DISPLAY_TYPE_VIDI, -}; - -/* - * Exynos drm overlay ops structure. - * - * @mode_set: copy drm overlay info to hw specific overlay info. - * @commit: apply hardware specific overlay data to registers. - * @enable: enable hardware specific overlay. - * @disable: disable hardware specific overlay. - */ -struct exynos_drm_overlay_ops { - void (*mode_set)(struct device *subdrv_dev, - struct exynos_drm_overlay *overlay); - void (*commit)(struct device *subdrv_dev, int zpos); - void (*enable)(struct device *subdrv_dev, int zpos); - void (*disable)(struct device *subdrv_dev, int zpos); -}; - -/* - * Exynos drm common overlay structure. - * - * @fb_x: offset x on a framebuffer to be displayed. - * - the unit is screen coordinates. - * @fb_y: offset y on a framebuffer to be displayed. - * - the unit is screen coordinates. - * @fb_width: width of a framebuffer. - * @fb_height: height of a framebuffer. - * @src_width: width of a partial image to be displayed from framebuffer. - * @src_height: height of a partial image to be displayed from framebuffer. - * @crtc_x: offset x on hardware screen. - * @crtc_y: offset y on hardware screen. - * @crtc_width: window width to be displayed (hardware screen). - * @crtc_height: window height to be displayed (hardware screen). - * @mode_width: width of screen mode. - * @mode_height: height of screen mode. - * @refresh: refresh rate. - * @scan_flag: interlace or progressive way. - * (it could be DRM_MODE_FLAG_*) - * @bpp: pixel size.(in bit) - * @pixel_format: fourcc pixel format of this overlay - * @dma_addr: array of bus(accessed by dma) address to the memory region - * allocated for a overlay. - * @vaddr: array of virtual memory addresss to this overlay. - * @zpos: order of overlay layer(z position). - * @default_win: a window to be enabled. - * @color_key: color key on or off. - * @index_color: if using color key feature then this value would be used - * as index color. - * @local_path: in case of lcd type, local path mode on or off. - * @transparency: transparency on or off. - * @activated: activated or not. - * - * this structure is common to exynos SoC and its contents would be copied - * to hardware specific overlay info. - */ -struct exynos_drm_overlay { - unsigned int fb_x; - unsigned int fb_y; - unsigned int fb_width; - unsigned int fb_height; - unsigned int src_width; - unsigned int src_height; - unsigned int crtc_x; - unsigned int crtc_y; - unsigned int crtc_width; - unsigned int crtc_height; - unsigned int mode_width; - unsigned int mode_height; - unsigned int refresh; - unsigned int scan_flag; - unsigned int bpp; - unsigned int pitch; - uint32_t pixel_format; - dma_addr_t dma_addr[MAX_FB_BUFFER]; - void __iomem *vaddr[MAX_FB_BUFFER]; - int zpos; - - bool default_win; - bool color_key; - unsigned int index_color; - bool local_path; - bool transparency; - bool activated; -}; - -/* - * Exynos DRM Display Structure. - * - this structure is common to analog tv, digital tv and lcd panel. - * - * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. - * @is_connected: check for that display is connected or not. - * @get_edid: get edid modes from display driver. - * @get_panel: get panel object from display driver. - * @check_timing: check if timing is valid or not. - * @power_on: display device on or off. - */ -struct exynos_drm_display_ops { - enum exynos_drm_output_type type; - bool (*is_connected)(struct device *dev); - int (*get_edid)(struct device *dev, struct drm_connector *connector, - u8 *edid, int len); - void *(*get_panel)(struct device *dev); - int (*check_timing)(struct device *dev, void *timing); - int (*power_on)(struct device *dev, int mode); -}; - -/* - * Exynos drm manager ops - * - * @dpms: control device power. - * @apply: set timing, vblank and overlay data to registers. - * @mode_fixup: fix mode data comparing to hw specific display mode. - * @mode_set: convert drm_display_mode to hw specific display mode and - * would be called by encoder->mode_set(). - * @get_max_resol: get maximum resolution to specific hardware. - * @commit: set current hw specific display mode to hw. - * @enable_vblank: specific driver callback for enabling vblank interrupt. - * @disable_vblank: specific driver callback for disabling vblank interrupt. - */ -struct exynos_drm_manager_ops { - void (*dpms)(struct device *subdrv_dev, int mode); - void (*apply)(struct device *subdrv_dev); - void (*mode_fixup)(struct device *subdrv_dev, - struct drm_connector *connector, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); - void (*mode_set)(struct device *subdrv_dev, void *mode); - void (*get_max_resol)(struct device *subdrv_dev, unsigned int *width, - unsigned int *height); - void (*commit)(struct device *subdrv_dev); - int (*enable_vblank)(struct device *subdrv_dev); - void (*disable_vblank)(struct device *subdrv_dev); -}; - -/* - * Exynos drm common manager structure. - * - * @dev: pointer to device object for subdrv device driver. - * sub drivers such as display controller or hdmi driver, - * have their own device object. - * @ops: pointer to callbacks for exynos drm specific framebuffer. - * these callbacks should be set by specific drivers such fimd - * or hdmi driver and are used to control hardware global registers. - * @overlay_ops: pointer to callbacks for exynos drm specific framebuffer. - * these callbacks should be set by specific drivers such fimd - * or hdmi driver and are used to control hardware overlay reigsters. - * @display: pointer to callbacks for exynos drm specific framebuffer. - * these callbacks should be set by specific drivers such fimd - * or hdmi driver and are used to control display devices such as - * analog tv, digital tv and lcd panel and also get timing data for them. - */ -struct exynos_drm_manager { - struct device *dev; - int pipe; - struct exynos_drm_manager_ops *ops; - struct exynos_drm_overlay_ops *overlay_ops; - struct exynos_drm_display_ops *display_ops; -}; - -struct iommu_info_node { - struct list_head list; - dma_addr_t dma_addr; - void *gem_obj; - /* TODO */ -}; - -/* - * Exynos drm g2d private structure - * - * @dev: device object to device driver for using iommu. - */ -struct exynos_drm_g2d_private { - struct device *dev; - struct list_head inuse_cmdlist; - struct list_head event_list; -}; - -/* - * Exynos drm ipp private structure - * - * @dev: device object to device driver for using driver data. - * @ippdrv: link used ippdrv. - * @event_list: list head to event. - */ -struct exynos_drm_ipp_private { - struct device *dev; - void *ippdrv; - struct list_head event_list; -}; - -struct drm_exynos_file_private { - struct exynos_drm_g2d_private *g2d_priv; - struct exynos_drm_ipp_private *ipp_priv; - pid_t tgid; -}; - -/* - * Exynos drm private structure. - */ -struct exynos_drm_private { - struct drm_fb_helper *fb_helper; - - /* list head for new event to be added. */ - struct list_head pageflip_event_list; - - /* - * created crtc object would be contained at this array and - * this array is used to be aware of which crtc did it request vblank. - */ - struct drm_crtc *crtc[MAX_CRTC]; - - /* - * maximum size of allocation by userptr feature. - * - as default, this has 16MB and only root user can change it. - */ - unsigned long userptr_limit; - - /* a iovmm object for iommu support. */ - void *vmm; - - struct drm_property *plane_zpos_property; - struct drm_property *crtc_mode_property; -}; - -/* - * Exynos drm sub driver structure. - * - * @list: sub driver has its own list object to register to exynos drm driver. - * @dev: pointer to device object for subdrv device driver. - * @drm_dev: pointer to drm_device and this pointer would be set - * when sub driver calls exynos_drm_subdrv_register(). - * @manager: subdrv has its own manager to control a hardware appropriately - * and we can access a hardware drawing on this manager. - * @probe: this callback would be called by exynos drm driver after - * subdrv is registered to it. - * @remove: this callback is used to release resources created - * by probe callback. - * @open: this would be called with drm device file open. - * @close: this would be called with drm device file close. - * @encoder: encoder object owned by this sub driver. - * @connector: connector object owned by this sub driver. - */ -struct exynos_drm_subdrv { - struct list_head list; - struct device *dev; - struct drm_device *drm_dev; - struct exynos_drm_manager *manager; - - int (*probe)(struct drm_device *drm_dev, struct device *dev); - void (*remove)(struct drm_device *drm_dev, struct device *dev); - int (*open)(struct drm_device *drm_dev, struct device *dev, - struct drm_file *file); - void (*close)(struct drm_device *drm_dev, struct device *dev, - struct drm_file *file); - - struct drm_encoder *encoder; - struct drm_connector *connector; -}; - -/* - * this function calls a probe callback registered to sub driver list and - * create its own encoder and connector and then set drm_device object - * to global one. - */ -int exynos_drm_device_register(struct drm_device *dev); -/* - * this function calls a remove callback registered to sub driver list and - * destroy its own encoder and connetor. - */ -int exynos_drm_device_unregister(struct drm_device *dev); - -/* - * this function would be called by sub drivers such as display controller - * or hdmi driver to register this sub driver object to exynos drm driver - * and when a sub driver is registered to exynos drm driver a probe callback - * of the sub driver is called and creates its own encoder and connector. - */ -int exynos_drm_subdrv_register(struct exynos_drm_subdrv *drm_subdrv); - -/* this function removes subdrv list from exynos drm driver */ -int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *drm_subdrv); - -int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file); -void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file); - -extern struct platform_driver fimd_driver; -extern struct platform_driver hdmi_driver; -extern struct platform_driver mixer_driver; -extern struct platform_driver exynos_drm_common_hdmi_driver; -extern struct platform_driver vidi_driver; -extern struct platform_driver g2d_driver; -extern struct platform_driver rotator_driver; -extern struct platform_driver fimc_driver; -extern struct platform_driver gsc_driver; -extern struct platform_driver ipp_driver; -#endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c deleted file mode 100644 index ebc4456..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ /dev/null @@ -1,432 +0,0 @@ -/* exynos_drm_encoder.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm_crtc_helper.h" - -#include "exynos_drm_drv.h" -#include "exynos_drm_encoder.h" - -#define to_exynos_encoder(x) container_of(x, struct exynos_drm_encoder,\ - drm_encoder) - -/* - * exynos specific encoder structure. - * - * @drm_encoder: encoder object. - * @manager: specific encoder has its own manager to control a hardware - * appropriately and we can access a hardware drawing on this manager. - * @dpms: store the encoder dpms value. - */ -struct exynos_drm_encoder { - struct drm_encoder drm_encoder; - struct exynos_drm_manager *manager; - int dpms; -}; - -static void exynos_drm_display_power(struct drm_encoder *encoder, int mode) -{ - struct drm_device *dev = encoder->dev; - struct drm_connector *connector; - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { - struct exynos_drm_display_ops *display_ops = - manager->display_ops; - - DRM_DEBUG_KMS("connector[%d] dpms[%d]\n", - connector->base.id, mode); - if (display_ops && display_ops->power_on) - display_ops->power_on(manager->dev, mode); - } - } -} - -static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - struct drm_device *dev = encoder->dev; - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); - struct exynos_drm_manager_ops *manager_ops = manager->ops; - struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); - - DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode); - - if (exynos_encoder->dpms == mode) { - DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n"); - return; - } - - mutex_lock(&dev->struct_mutex); - - switch (mode) { - case DRM_MODE_DPMS_ON: - if (manager_ops && manager_ops->apply) - manager_ops->apply(manager->dev); - exynos_drm_display_power(encoder, mode); - exynos_encoder->dpms = mode; - break; - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: - exynos_drm_display_power(encoder, mode); - exynos_encoder->dpms = mode; - break; - default: - DRM_ERROR("unspecified mode %d\n", mode); - break; - } - - mutex_unlock(&dev->struct_mutex); -} - -static bool -exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_device *dev = encoder->dev; - struct drm_connector *connector; - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); - struct exynos_drm_manager_ops *manager_ops = manager->ops; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) - if (manager_ops && manager_ops->mode_fixup) - manager_ops->mode_fixup(manager->dev, connector, - mode, adjusted_mode); - } - - return true; -} - -static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_device *dev = encoder->dev; - struct drm_connector *connector; - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); - struct exynos_drm_manager_ops *manager_ops = manager->ops; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_drm_encoder_dpms(encoder, DRM_MODE_DPMS_ON); - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) - if (manager_ops && manager_ops->mode_set) - manager_ops->mode_set(manager->dev, - adjusted_mode); - } -} - -static void exynos_drm_encoder_prepare(struct drm_encoder *encoder) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* drm framework doesn't check NULL. */ -} - -static void exynos_drm_encoder_commit(struct drm_encoder *encoder) -{ - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); - struct exynos_drm_manager_ops *manager_ops = manager->ops; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (manager_ops && manager_ops->commit) - manager_ops->commit(manager->dev); -} - -static struct drm_crtc * -exynos_drm_encoder_get_crtc(struct drm_encoder *encoder) -{ - return encoder->crtc; -} - -static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = { - .dpms = exynos_drm_encoder_dpms, - .mode_fixup = exynos_drm_encoder_mode_fixup, - .mode_set = exynos_drm_encoder_mode_set, - .prepare = exynos_drm_encoder_prepare, - .commit = exynos_drm_encoder_commit, - .get_crtc = exynos_drm_encoder_get_crtc, -}; - -static void exynos_drm_encoder_destroy(struct drm_encoder *encoder) -{ - struct exynos_drm_encoder *exynos_encoder = - to_exynos_encoder(encoder); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_encoder->manager->pipe = -1; - - drm_encoder_cleanup(encoder); - kfree(exynos_encoder); -} - -static struct drm_encoder_funcs exynos_encoder_funcs = { - .destroy = exynos_drm_encoder_destroy, -}; - -static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder) -{ - struct drm_encoder *clone; - struct drm_device *dev = encoder->dev; - struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); - struct exynos_drm_display_ops *display_ops = - exynos_encoder->manager->display_ops; - unsigned int clone_mask = 0; - int cnt = 0; - - list_for_each_entry(clone, &dev->mode_config.encoder_list, head) { - switch (display_ops->type) { - case EXYNOS_DISPLAY_TYPE_LCD: - case EXYNOS_DISPLAY_TYPE_HDMI: - case EXYNOS_DISPLAY_TYPE_VIDI: - clone_mask |= (1 << (cnt++)); - break; - default: - continue; - } - } - - return clone_mask; -} - -void exynos_drm_encoder_setup(struct drm_device *dev) -{ - struct drm_encoder *encoder; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) - encoder->possible_clones = exynos_drm_encoder_clones(encoder); -} - -struct drm_encoder * -exynos_drm_encoder_create(struct drm_device *dev, - struct exynos_drm_manager *manager, - unsigned int possible_crtcs) -{ - struct drm_encoder *encoder; - struct exynos_drm_encoder *exynos_encoder; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!manager || !possible_crtcs) - return NULL; - - if (!manager->dev) - return NULL; - - exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL); - if (!exynos_encoder) { - DRM_ERROR("failed to allocate encoder\n"); - return NULL; - } - - exynos_encoder->dpms = DRM_MODE_DPMS_ON; - exynos_encoder->manager = manager; - encoder = &exynos_encoder->drm_encoder; - encoder->possible_crtcs = possible_crtcs; - - DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs); - - drm_encoder_init(dev, encoder, &exynos_encoder_funcs, - DRM_MODE_ENCODER_TMDS); - - drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs); - - DRM_DEBUG_KMS("encoder has been created\n"); - - return encoder; -} - -struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder) -{ - return to_exynos_encoder(encoder)->manager; -} - -void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, - void (*fn)(struct drm_encoder *, void *)) -{ - struct drm_device *dev = crtc->dev; - struct drm_encoder *encoder; - struct exynos_drm_private *private = dev->dev_private; - struct exynos_drm_manager *manager; - - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - /* - * if crtc is detached from encoder, check pipe, - * otherwise check crtc attached to encoder - */ - if (!encoder->crtc) { - manager = to_exynos_encoder(encoder)->manager; - if (manager->pipe < 0 || - private->crtc[manager->pipe] != crtc) - continue; - } else { - if (encoder->crtc != crtc) - continue; - } - - fn(encoder, data); - } -} - -void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data) -{ - struct exynos_drm_manager *manager = - to_exynos_encoder(encoder)->manager; - struct exynos_drm_manager_ops *manager_ops = manager->ops; - int crtc = *(int *)data; - - if (manager->pipe != crtc) - return; - - if (manager_ops->enable_vblank) - manager_ops->enable_vblank(manager->dev); -} - -void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data) -{ - struct exynos_drm_manager *manager = - to_exynos_encoder(encoder)->manager; - struct exynos_drm_manager_ops *manager_ops = manager->ops; - int crtc = *(int *)data; - - if (manager->pipe != crtc) - return; - - if (manager_ops->disable_vblank) - manager_ops->disable_vblank(manager->dev); -} - -void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data) -{ - struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); - struct exynos_drm_manager *manager = exynos_encoder->manager; - struct exynos_drm_manager_ops *manager_ops = manager->ops; - int mode = *(int *)data; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (manager_ops && manager_ops->dpms) - manager_ops->dpms(manager->dev, mode); - - /* - * if this condition is ok then it means that the crtc is already - * detached from encoder and last function for detaching is properly - * done, so clear pipe from manager to prevent repeated call. - */ - if (mode > DRM_MODE_DPMS_ON) { - if (!encoder->crtc) - manager->pipe = -1; - } -} - -void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data) -{ - struct exynos_drm_manager *manager = - to_exynos_encoder(encoder)->manager; - int pipe = *(int *)data; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* - * when crtc is detached from encoder, this pipe is used - * to select manager operation - */ - manager->pipe = pipe; -} - -void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data) -{ - struct exynos_drm_manager *manager = - to_exynos_encoder(encoder)->manager; - struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; - struct exynos_drm_overlay *overlay = data; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (overlay_ops && overlay_ops->mode_set) - overlay_ops->mode_set(manager->dev, overlay); -} - -void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data) -{ - struct exynos_drm_manager *manager = - to_exynos_encoder(encoder)->manager; - struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; - int zpos = DEFAULT_ZPOS; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (data) - zpos = *(int *)data; - - if (overlay_ops && overlay_ops->commit) - overlay_ops->commit(manager->dev, zpos); -} - -void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data) -{ - struct exynos_drm_manager *manager = - to_exynos_encoder(encoder)->manager; - struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; - int zpos = DEFAULT_ZPOS; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (data) - zpos = *(int *)data; - - if (overlay_ops && overlay_ops->enable) - overlay_ops->enable(manager->dev, zpos); -} - -void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data) -{ - struct exynos_drm_manager *manager = - to_exynos_encoder(encoder)->manager; - struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; - int zpos = DEFAULT_ZPOS; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (data) - zpos = *(int *)data; - - if (overlay_ops && overlay_ops->disable) - overlay_ops->disable(manager->dev, zpos); -} diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h deleted file mode 100644 index 6470d9d..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_ENCODER_H_ -#define _EXYNOS_DRM_ENCODER_H_ - -struct exynos_drm_manager; - -void exynos_drm_encoder_setup(struct drm_device *dev); -struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev, - struct exynos_drm_manager *mgr, - unsigned int possible_crtcs); -struct exynos_drm_manager * -exynos_drm_get_manager(struct drm_encoder *encoder); -void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, - void (*fn)(struct drm_encoder *, void *)); -void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data); -void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data); -void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data); -void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data); -void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data); -void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data); -void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data); -void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data); - -#endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c deleted file mode 100644 index 41009e4..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ /dev/null @@ -1,312 +0,0 @@ -/* exynos_drm_fb.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm_crtc.h" -#include "drm_crtc_helper.h" -#include "drm_fb_helper.h" - -#include "exynos_drm.h" -#include "exynos_drm_drv.h" -#include "exynos_drm_fb.h" -#include "exynos_drm_gem.h" - -#define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb) - -/* - * exynos specific framebuffer structure. - * - * @fb: drm framebuffer obejct. - * @exynos_gem_obj: array of exynos specific gem object containing a gem object. - */ -struct exynos_drm_fb { - struct drm_framebuffer fb; - struct exynos_drm_gem_obj *exynos_gem_obj[MAX_FB_BUFFER]; -}; - -static int check_fb_gem_memory_type(struct drm_device *drm_dev, - struct exynos_drm_gem_obj *exynos_gem_obj) -{ - struct exynos_drm_private *private = drm_dev->dev_private; - unsigned int flags; - - /* - * if exynos drm driver supports iommu then framebuffer can use - * all the buffer types. - */ - if (private->vmm) - return 0; - - flags = exynos_gem_obj->flags; - - /* not support physically non-continuous memory for fb yet. TODO */ - if (IS_NONCONTIG_BUFFER(flags)) { - DRM_ERROR("cannot use this gem memory type for fb.\n"); - return -EINVAL; - } - - return 0; -} - -static int check_fb_gem_size(struct drm_device *drm_dev, - struct drm_framebuffer *fb, - unsigned int nr) -{ - unsigned long fb_size; - struct drm_gem_object *obj; - struct exynos_drm_gem_obj *exynos_gem_obj; - struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); - - /* in case of RGB format, only one plane is used. */ - if (nr < 2) { - exynos_gem_obj = exynos_fb->exynos_gem_obj[0]; - obj = &exynos_gem_obj->base; - fb_size = fb->pitches[0] * fb->height; - - if (fb_size != exynos_gem_obj->packed_size) { - DRM_ERROR("invalid fb or gem size.\n"); - return -EINVAL; - } - /* in case of NV12MT, YUV420M and so on, two and three planes. */ - } else { - unsigned int i; - - for (i = 0; i < nr; i++) { - exynos_gem_obj = exynos_fb->exynos_gem_obj[i]; - obj = &exynos_gem_obj->base; - fb_size = fb->pitches[i] * fb->height; - - if (fb_size != exynos_gem_obj->packed_size) { - DRM_ERROR("invalid fb or gem size.\n"); - return -EINVAL; - } - } - } - - return 0; -} - -static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) -{ - struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); - unsigned int i; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - drm_framebuffer_cleanup(fb); - - for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem_obj); i++) { - struct drm_gem_object *obj; - - if (exynos_fb->exynos_gem_obj[i] == NULL) - continue; - - obj = &exynos_fb->exynos_gem_obj[i]->base; - drm_gem_object_unreference_unlocked(obj); - } - - kfree(exynos_fb); - exynos_fb = NULL; -} - -static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb, - struct drm_file *file_priv, - unsigned int *handle) -{ - struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - return drm_gem_handle_create(file_priv, - &exynos_fb->exynos_gem_obj[0]->base, handle); -} - -static int exynos_drm_fb_dirty(struct drm_framebuffer *fb, - struct drm_file *file_priv, unsigned flags, - unsigned color, struct drm_clip_rect *clips, - unsigned num_clips) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* TODO */ - - return 0; -} - -static struct drm_framebuffer_funcs exynos_drm_fb_funcs = { - .destroy = exynos_drm_fb_destroy, - .create_handle = exynos_drm_fb_create_handle, - .dirty = exynos_drm_fb_dirty, -}; - -struct drm_framebuffer * -exynos_drm_framebuffer_init(struct drm_device *dev, - struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj) -{ - struct exynos_drm_fb *exynos_fb; - struct exynos_drm_gem_obj *exynos_gem_obj; - int ret; - - exynos_gem_obj = to_exynos_gem_obj(obj); - - ret = check_fb_gem_memory_type(dev, exynos_gem_obj); - if (ret < 0) { - DRM_ERROR("cannot use this gem memory type for fb.\n"); - return ERR_PTR(-EINVAL); - } - - exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); - if (!exynos_fb) { - DRM_ERROR("failed to allocate exynos drm framebuffer\n"); - return ERR_PTR(-ENOMEM); - } - - exynos_fb->exynos_gem_obj[0] = exynos_gem_obj; - - ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); - if (ret) { - DRM_ERROR("failed to initialize framebuffer\n"); - return ERR_PTR(ret); - } - - drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); - - return &exynos_fb->fb; -} - -static struct drm_framebuffer * -exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, - struct drm_mode_fb_cmd2 *mode_cmd) -{ - struct drm_gem_object *obj; - struct drm_framebuffer *fb; - struct exynos_drm_fb *exynos_fb; - int nr, i, ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); - if (!obj) { - DRM_ERROR("failed to lookup gem object\n"); - return ERR_PTR(-ENOENT); - } - - fb = exynos_drm_framebuffer_init(dev, mode_cmd, obj); - if (IS_ERR(fb)) { - drm_gem_object_unreference_unlocked(obj); - return fb; - } - - exynos_fb = to_exynos_fb(fb); - nr = exynos_drm_format_num_buffers(fb->pixel_format); - - for (i = 1; i < nr; i++) { - struct exynos_drm_gem_obj *exynos_gem_obj; - int ret; - - obj = drm_gem_object_lookup(dev, file_priv, - mode_cmd->handles[i]); - if (!obj) { - DRM_ERROR("failed to lookup gem object\n"); - exynos_drm_fb_destroy(fb); - return ERR_PTR(-ENOENT); - } - - exynos_gem_obj = to_exynos_gem_obj(obj); - - ret = check_fb_gem_memory_type(dev, exynos_gem_obj); - if (ret < 0) { - DRM_ERROR("cannot use this gem memory type for fb.\n"); - exynos_drm_fb_destroy(fb); - return ERR_PTR(ret); - } - - exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj); - } - - ret = check_fb_gem_size(dev, fb, nr); - if (ret < 0) { - exynos_drm_fb_destroy(fb); - return ERR_PTR(ret); - } - - return fb; -} - -struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, - int index) -{ - struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); - struct exynos_drm_gem_buf *buffer; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (index >= MAX_FB_BUFFER) - return NULL; - - buffer = exynos_fb->exynos_gem_obj[index]->buffer; - if (!buffer) - return NULL; - - DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n", - (unsigned long)buffer->kvaddr, - (unsigned long)buffer->dma_addr); - - return buffer; -} - -static void exynos_drm_output_poll_changed(struct drm_device *dev) -{ - struct exynos_drm_private *private = dev->dev_private; - struct drm_fb_helper *fb_helper = private->fb_helper; - - if (fb_helper) - drm_fb_helper_hotplug_event(fb_helper); -} - -static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { - .fb_create = exynos_user_fb_create, - .output_poll_changed = exynos_drm_output_poll_changed, -}; - -void exynos_drm_mode_config_init(struct drm_device *dev) -{ - dev->mode_config.min_width = 0; - dev->mode_config.min_height = 0; - - /* - * set max width and height as default value(4096x4096). - * this value would be used to check framebuffer size limitation - * at drm_mode_addfb(). - */ - dev->mode_config.max_width = 4096; - dev->mode_config.max_height = 4096; - - dev->mode_config.funcs = &exynos_drm_mode_config_funcs; -} diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h deleted file mode 100644 index 3ecb30d..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_FB_H_ -#define _EXYNOS_DRM_FB_H - -static inline int exynos_drm_format_num_buffers(uint32_t format) -{ - switch (format) { - case DRM_FORMAT_NV12M: - case DRM_FORMAT_NV12MT: - return 2; - case DRM_FORMAT_YUV420M: - return 3; - default: - return 1; - } -} - -struct drm_framebuffer * -exynos_drm_framebuffer_init(struct drm_device *dev, - struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj); - -/* get memory information of a drm framebuffer */ -struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, - int index); - -void exynos_drm_mode_config_init(struct drm_device *dev); - -#endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c deleted file mode 100644 index df34adf..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ /dev/null @@ -1,318 +0,0 @@ -/* exynos_drm_fbdev.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm_crtc.h" -#include "drm_fb_helper.h" -#include "drm_crtc_helper.h" - -#include "exynos_drm_drv.h" -#include "exynos_drm_fb.h" -#include "exynos_drm_gem.h" - -#define MAX_CONNECTOR 4 -#define PREFERRED_BPP 32 - -#define to_exynos_fbdev(x) container_of(x, struct exynos_drm_fbdev,\ - drm_fb_helper) - -struct exynos_drm_fbdev { - struct drm_fb_helper drm_fb_helper; - struct exynos_drm_gem_obj *exynos_gem_obj; -}; - -static struct fb_ops exynos_drm_fb_ops = { - .owner = THIS_MODULE, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, - .fb_blank = drm_fb_helper_blank, - .fb_pan_display = drm_fb_helper_pan_display, - .fb_setcmap = drm_fb_helper_setcmap, -}; - -static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, - struct drm_framebuffer *fb) -{ - struct fb_info *fbi = helper->fbdev; - struct drm_device *dev = helper->dev; - struct exynos_drm_gem_buf *buffer; - unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); - unsigned long offset; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); - drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height); - - /* RGB formats use only one buffer */ - buffer = exynos_drm_fb_buffer(fb, 0); - if (!buffer) { - DRM_LOG_KMS("buffer is null.\n"); - return -EFAULT; - } - - offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); - offset += fbi->var.yoffset * fb->pitches[0]; - - dev->mode_config.fb_base = (resource_size_t)buffer->paddr; - fbi->screen_base = buffer->kvaddr + offset; - fbi->fix.smem_start = (unsigned long)(buffer->paddr + offset); - fbi->screen_size = size; - fbi->fix.smem_len = size; - - return 0; -} - -static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper); - struct exynos_drm_gem_obj *exynos_gem_obj; - struct drm_device *dev = helper->dev; - struct fb_info *fbi; - struct drm_mode_fb_cmd2 mode_cmd = { 0 }; - struct platform_device *pdev = dev->platformdev; - unsigned long size; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n", - sizes->surface_width, sizes->surface_height, - sizes->surface_bpp); - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = sizes->surface_width * (sizes->surface_bpp >> 3); - mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, - sizes->surface_depth); - - mutex_lock(&dev->struct_mutex); - - fbi = framebuffer_alloc(0, &pdev->dev); - if (!fbi) { - DRM_ERROR("failed to allocate fb info.\n"); - ret = -ENOMEM; - goto out; - } - - size = mode_cmd.pitches[0] * mode_cmd.height; - - /* 0 means to allocate physically continuous memory */ - exynos_gem_obj = exynos_drm_gem_create(dev, 0, size); - if (IS_ERR(exynos_gem_obj)) { - ret = PTR_ERR(exynos_gem_obj); - goto out; - } - - exynos_fbdev->exynos_gem_obj = exynos_gem_obj; - - helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, - &exynos_gem_obj->base); - if (IS_ERR_OR_NULL(helper->fb)) { - DRM_ERROR("failed to create drm framebuffer.\n"); - ret = PTR_ERR(helper->fb); - goto out; - } - - helper->fbdev = fbi; - - fbi->par = helper; - fbi->flags = FBINFO_FLAG_DEFAULT; - fbi->fbops = &exynos_drm_fb_ops; - - ret = fb_alloc_cmap(&fbi->cmap, 256, 0); - if (ret) { - DRM_ERROR("failed to allocate cmap.\n"); - goto out; - } - - ret = exynos_drm_fbdev_update(helper, helper->fb); - if (ret < 0) { - fb_dealloc_cmap(&fbi->cmap); - goto out; - } - -/* - * if failed, all resources allocated above would be released by - * drm_mode_config_cleanup() when drm_load() had been called prior - * to any specific driver such as fimd or hdmi driver. - */ -out: - mutex_unlock(&dev->struct_mutex); - return ret; -} - -static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - int ret = 0; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* - * with !helper->fb, it means that this funcion is called first time - * and after that, the helper->fb would be used as clone mode. - */ - if (!helper->fb) { - ret = exynos_drm_fbdev_create(helper, sizes); - if (ret < 0) { - DRM_ERROR("failed to create fbdev.\n"); - return ret; - } - - /* - * fb_helper expects a value more than 1 if succeed - * because register_framebuffer() should be called. - */ - ret = 1; - } - - return ret; -} - -static struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = { - .fb_probe = exynos_drm_fbdev_probe, -}; - -int exynos_drm_fbdev_init(struct drm_device *dev) -{ - struct exynos_drm_fbdev *fbdev; - struct exynos_drm_private *private = dev->dev_private; - struct drm_fb_helper *helper; - unsigned int num_crtc; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector) - return 0; - - fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); - if (!fbdev) { - DRM_ERROR("failed to allocate drm fbdev.\n"); - return -ENOMEM; - } - - private->fb_helper = helper = &fbdev->drm_fb_helper; - helper->funcs = &exynos_drm_fb_helper_funcs; - - num_crtc = dev->mode_config.num_crtc; - - ret = drm_fb_helper_init(dev, helper, num_crtc, MAX_CONNECTOR); - if (ret < 0) { - DRM_ERROR("failed to initialize drm fb helper.\n"); - goto err_init; - } - - ret = drm_fb_helper_single_add_all_connectors(helper); - if (ret < 0) { - DRM_ERROR("failed to register drm_fb_helper_connector.\n"); - goto err_setup; - - } - - ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP); - if (ret < 0) { - DRM_ERROR("failed to set up hw configuration.\n"); - goto err_setup; - } - - return 0; - -err_setup: - drm_fb_helper_fini(helper); - -err_init: - private->fb_helper = NULL; - kfree(fbdev); - - return ret; -} - -static void exynos_drm_fbdev_destroy(struct drm_device *dev, - struct drm_fb_helper *fb_helper) -{ - struct drm_framebuffer *fb; - - /* release drm framebuffer and real buffer */ - if (fb_helper->fb && fb_helper->fb->funcs) { - fb = fb_helper->fb; - if (fb && fb->funcs->destroy) - fb->funcs->destroy(fb); - } - - /* release linux framebuffer */ - if (fb_helper->fbdev) { - struct fb_info *info; - int ret; - - info = fb_helper->fbdev; - ret = unregister_framebuffer(info); - if (ret < 0) - DRM_DEBUG_KMS("failed unregister_framebuffer()\n"); - - if (info->cmap.len) - fb_dealloc_cmap(&info->cmap); - - framebuffer_release(info); - } - - drm_fb_helper_fini(fb_helper); -} - -void exynos_drm_fbdev_fini(struct drm_device *dev) -{ - struct exynos_drm_private *private = dev->dev_private; - struct exynos_drm_fbdev *fbdev; - - if (!private || !private->fb_helper) - return; - - fbdev = to_exynos_fbdev(private->fb_helper); - - if (fbdev->exynos_gem_obj) - exynos_drm_gem_destroy(fbdev->exynos_gem_obj); - - exynos_drm_fbdev_destroy(dev, private->fb_helper); - kfree(fbdev); - private->fb_helper = NULL; -} - -void exynos_drm_fbdev_restore_mode(struct drm_device *dev) -{ - struct exynos_drm_private *private = dev->dev_private; - - if (!private || !private->fb_helper) - return; - - drm_fb_helper_restore_fbdev_mode(private->fb_helper); -} diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.h b/drivers/gpu/drm/exynos/exynos_drm_fbdev.h deleted file mode 100644 index ccfce8a..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_FBDEV_H_ -#define _EXYNOS_DRM_FBDEV_H_ - -int exynos_drm_fbdev_init(struct drm_device *dev); -int exynos_drm_fbdev_reinit(struct drm_device *dev); -void exynos_drm_fbdev_fini(struct drm_device *dev); -void exynos_drm_fbdev_restore_mode(struct drm_device *dev); - -#endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c deleted file mode 100644 index fdf5be8..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ /dev/null @@ -1,1925 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Authors: - * Eunchul Kim - * - * 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 "drmP.h" -#include "drm_backlight.h" -#include -#include -#include -#include -#include -#include -#include - -#include "regs-fimc.h" -#include -#include "exynos_drm_drv.h" -#include "exynos_drm_gem.h" -#include "exynos_drm_ipp.h" -#include "exynos_drm_fimc.h" - -/* - * FIMC is stand for Fully Interactive Mobile Camera and - * supports image scaler/rotator and input/output DMA operations. - * input DMA reads image data from the memory. - * output DMA writes image data to memory. - * FIMC supports image rotation and image effect functions. - */ - -#define FIMC_MAX_DEVS 4 -#define FIMC_MAX_SRC 2 -#define FIMC_MAX_DST 32 -#ifdef CONFIG_SLP_DISP_DEBUG -#define FIMC_MAX_REG 128 -#define FIMC_BASE_REG(id) (0x11800000 + (0x10000 * id)) -#endif -#define FIMC_CLK_RATE 166750000 -#define FIMC_BUF_STOP 1 -#define FIMC_BUF_START 2 -#define FIMC_REG_SZ 32 -#define FIMC_WIDTH_ITU_709 1280 - -#define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev)) -#define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\ - struct fimc_context, ippdrv); -#define fimc_read(offset) readl(ctx->regs + (offset)); -#define fimc_write(cfg, offset) writel(cfg, ctx->regs + (offset)); - -enum fimc_wb { - FIMC_WB_NONE, - FIMC_WB_A, - FIMC_WB_B, -}; - -/* - * A structure of scaler. - * - * @range: narrow, wide. - * @bypass: unused scaler path. - * @up_h: horizontal scale up. - * @up_v: vertical scale up. - * @hratio: horizontal ratio. - * @vratio: vertical ratio. - */ -struct fimc_scaler { - bool range; - bool bypass; - bool up_h; - bool up_v; - u32 hratio; - u32 vratio; -}; - -/* - * A structure of scaler capability. - * - * find user manual table 43-1. - * @in_hori: scaler input horizontal size. - * @bypass: scaler bypass mode. - * @dst_h_wo_rot: target horizontal size without output rotation. - * @dst_h_rot: target horizontal size with output rotation. - * @rl_w_wo_rot: real width without input rotation. - * @rl_h_rot: real height without output rotation. - */ -struct fimc_capability { - /* scaler */ - u32 in_hori; - u32 bypass; - /* output rotator */ - u32 dst_h_wo_rot; - u32 dst_h_rot; - /* input rotator */ - u32 rl_w_wo_rot; - u32 rl_h_rot; -}; - -/* - * A structure of fimc context. - * - * @ippdrv: prepare initialization using ippdrv. - * @regs_res: register resources. - * @regs: memory mapped io registers. - * @lock: locking of operations. - * @sclk_fimc_clk: fimc source clock. - * @fimc_clk: fimc clock. - * @wb_clk: writeback a clock. - * @wb_b_clk: writeback b clock. - * @sc: scaler infomations. - * @capa: scaler capability. - * @odr: ordering of YUV. - * @ver: fimc version. - * @pol: porarity of writeback. - * @id: fimc id. - * @irq: irq number. - * @suspended: qos operations. - */ -struct fimc_context { - struct exynos_drm_ippdrv ippdrv; - struct resource *regs_res; - void __iomem *regs; - struct mutex lock; - struct clk *sclk_fimc_clk; - struct clk *fimc_clk; - struct clk *wb_clk; - struct clk *wb_b_clk; - struct fimc_scaler sc; - struct fimc_capability *capa; - enum exynos_drm_fimc_ver ver; - struct exynos_drm_fimc_pol pol; - int id; - int irq; - bool suspended; -}; - -struct fimc_capability fimc51_capa[FIMC_MAX_DEVS] = { - { - .in_hori = 4224, - .bypass = 8192, - .dst_h_wo_rot = 4224, - .dst_h_rot = 1920, - .rl_w_wo_rot = 8192, - .rl_h_rot = 1920, - }, { - .in_hori = 4224, - .bypass = 8192, - .dst_h_wo_rot = 4224, - .dst_h_rot = 1920, - .rl_w_wo_rot = 8192, - .rl_h_rot = 1920, - }, { - .in_hori = 4224, - .bypass = 8192, - .dst_h_wo_rot = 4224, - .dst_h_rot = 1920, - .rl_w_wo_rot = 8192, - .rl_h_rot = 1920, - }, { - .in_hori = 1920, - .bypass = 8192, - .dst_h_wo_rot = 1920, - .dst_h_rot = 1366, - .rl_w_wo_rot = 8192, - .rl_h_rot = 1366, - }, -}; - -static void fimc_sw_reset(struct fimc_context *ctx, bool pattern) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:pattern[%d]\n", __func__, pattern); - - cfg = fimc_read(EXYNOS_CISRCFMT); - cfg |= EXYNOS_CISRCFMT_ITU601_8BIT; - if (pattern) - cfg |= EXYNOS_CIGCTRL_TESTPATTERN_COLOR_BAR; - - fimc_write(cfg, EXYNOS_CISRCFMT); - - /* s/w reset */ - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg |= (EXYNOS_CIGCTRL_SWRST); - fimc_write(cfg, EXYNOS_CIGCTRL); - - /* s/w reset complete */ - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg &= ~EXYNOS_CIGCTRL_SWRST; - fimc_write(cfg, EXYNOS_CIGCTRL); - - /* reset sequence */ - fimc_write(0x0, EXYNOS_CIFCNTSEQ); -} - -static void fimc_set_camblk_fimd0_wb(struct fimc_context *ctx) -{ - u32 camblk_cfg; - - DRM_DEBUG_KMS("%s\n", __func__); - - camblk_cfg = readl(SYSREG_CAMERA_BLK); - camblk_cfg &= ~(SYSREG_FIMD0WB_DEST_MASK); - camblk_cfg |= ctx->id << (SYSREG_FIMD0WB_DEST_SHIFT); - - writel(camblk_cfg, SYSREG_CAMERA_BLK); -} - -static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:wb[%d]\n", __func__, wb); - - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK | - EXYNOS_CIGCTRL_SELCAM_ITU_MASK | - EXYNOS_CIGCTRL_SELCAM_MIPI_MASK | - EXYNOS_CIGCTRL_SELCAM_FIMC_MASK | - EXYNOS_CIGCTRL_SELWB_CAMIF_MASK | - EXYNOS_CIGCTRL_SELWRITEBACK_MASK); - - switch (wb) { - case FIMC_WB_A: - cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_A | - EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK); - break; - case FIMC_WB_B: - cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_B | - EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK); - break; - case FIMC_WB_NONE: - default: - cfg |= (EXYNOS_CIGCTRL_SELCAM_ITU_A | - EXYNOS_CIGCTRL_SELWRITEBACK_A | - EXYNOS_CIGCTRL_SELCAM_MIPI_A | - EXYNOS_CIGCTRL_SELCAM_FIMC_ITU); - break; - } - - fimc_write(cfg, EXYNOS_CIGCTRL); -} - -static void fimc_set_polarity(struct fimc_context *ctx, - struct exynos_drm_fimc_pol *pol) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:inv_pclk[%d]inv_vsync[%d]\n", - __func__, pol->inv_pclk, pol->inv_vsync); - DRM_DEBUG_KMS("%s:inv_href[%d]inv_hsync[%d]\n", - __func__, pol->inv_href, pol->inv_hsync); - - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg &= ~(EXYNOS_CIGCTRL_INVPOLPCLK | EXYNOS_CIGCTRL_INVPOLVSYNC | - EXYNOS_CIGCTRL_INVPOLHREF | EXYNOS_CIGCTRL_INVPOLHSYNC); - - if (pol->inv_pclk) - cfg |= EXYNOS_CIGCTRL_INVPOLPCLK; - if (pol->inv_vsync) - cfg |= EXYNOS_CIGCTRL_INVPOLVSYNC; - if (pol->inv_href) - cfg |= EXYNOS_CIGCTRL_INVPOLHREF; - if (pol->inv_hsync) - cfg |= EXYNOS_CIGCTRL_INVPOLHSYNC; - - fimc_write(cfg, EXYNOS_CIGCTRL); -} - -static void fimc_handle_jpeg(struct fimc_context *ctx, bool enable) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable); - - cfg = fimc_read(EXYNOS_CIGCTRL); - if (enable) - cfg |= EXYNOS_CIGCTRL_CAM_JPEG; - else - cfg &= ~EXYNOS_CIGCTRL_CAM_JPEG; - - fimc_write(cfg, EXYNOS_CIGCTRL); -} - -static void fimc_handle_irq(struct fimc_context *ctx, bool enable, - bool overflow, bool level) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__, - enable, overflow, level); - - cfg = fimc_read(EXYNOS_CIGCTRL); - if (enable) { - cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_LEVEL); - cfg |= EXYNOS_CIGCTRL_IRQ_ENABLE; - if (overflow) - cfg |= EXYNOS_CIGCTRL_IRQ_OVFEN; - if (level) - cfg |= EXYNOS_CIGCTRL_IRQ_LEVEL; - } else - cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_ENABLE); - - fimc_write(cfg, EXYNOS_CIGCTRL); -} - -static void fimc_clear_irq(struct fimc_context *ctx) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s\n", __func__); - - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg |= EXYNOS_CIGCTRL_IRQ_CLR; - fimc_write(cfg, EXYNOS_CIGCTRL); -} - -static bool fimc_check_ovf(struct fimc_context *ctx) -{ - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg, status, flag; - - status = fimc_read(EXYNOS_CISTATUS); - flag = EXYNOS_CISTATUS_OVFIY | EXYNOS_CISTATUS_OVFICB | - EXYNOS_CISTATUS_OVFICR; - - DRM_DEBUG_KMS("%s:flag[0x%x]\n", __func__, flag); - - if (status & flag) { - cfg = fimc_read(EXYNOS_CIWDOFST); - cfg |= (EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB | - EXYNOS_CIWDOFST_CLROVFICR); - - fimc_write(cfg, EXYNOS_CIWDOFST); - - cfg = fimc_read(EXYNOS_CIWDOFST); - cfg &= ~(EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB | - EXYNOS_CIWDOFST_CLROVFICR); - - fimc_write(cfg, EXYNOS_CIWDOFST); - - dev_err(ippdrv->dev, "occured overflow at %d, status 0x%x.\n", - ctx->id, status); - return true; - } - - return false; -} - -static bool fimc_check_frame_end(struct fimc_context *ctx) -{ - u32 cfg; - - cfg = fimc_read(EXYNOS_CISTATUS); - - DRM_DEBUG_KMS("%s:cfg[0x%x]\n", __func__, cfg); - - if (!(cfg & EXYNOS_CISTATUS_FRAMEEND)) - return false; - - cfg &= ~(EXYNOS_CISTATUS_FRAMEEND); - fimc_write(cfg, EXYNOS_CISTATUS); - - return true; -} - -static int fimc_get_buf_id(struct fimc_context *ctx) -{ - u32 cfg; - int frame_cnt, buf_id; - - DRM_DEBUG_KMS("%s\n", __func__); - - cfg = fimc_read(EXYNOS_CISTATUS2); - frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg); - - if (frame_cnt == 0) - frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg); - - DRM_DEBUG_KMS("%s:present[%d]before[%d]\n", __func__, - EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg), - EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg)); - - if (frame_cnt == 0) { - DRM_ERROR("failed to get frame count.\n"); - return -EIO; - } - - buf_id = frame_cnt - 1; - DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id); - - return buf_id; -} - -static void fimc_handle_lastend(struct fimc_context *ctx, bool enable) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable); - - cfg = fimc_read(EXYNOS_CIOCTRL); - if (enable) - cfg |= EXYNOS_CIOCTRL_LASTENDEN; - else - cfg &= ~EXYNOS_CIOCTRL_LASTENDEN; - - fimc_write(cfg, EXYNOS_CIOCTRL); -} - -static int fimc_set_planar_addr(struct drm_exynos_ipp_buf_info *buf_info, - u32 fmt, struct drm_exynos_sz *sz) -{ - dma_addr_t *y_addr = &buf_info->base[EXYNOS_DRM_PLANAR_Y]; - dma_addr_t *cb_addr = &buf_info->base[EXYNOS_DRM_PLANAR_CB]; - dma_addr_t *cr_addr = &buf_info->base[EXYNOS_DRM_PLANAR_CR]; - uint64_t y_ofs, cb_ofs, cr_ofs; - - /* - * ToDo: check the buffer size between gem allocated buffers - * and each planar size. - */ - switch (fmt) { - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - y_ofs = sz->hsize * sz->vsize; - cb_ofs = y_ofs >> 1; - cr_ofs = 0; - break; - case DRM_FORMAT_NV12M: - y_ofs = ALIGN(ALIGN(sz->hsize, 16) * - ALIGN(sz->vsize, 16), SZ_2K); - cb_ofs = ALIGN(ALIGN(sz->hsize, 16) * - ALIGN(sz->vsize >> 1, 16), SZ_2K); - cr_ofs = 0; - break; - case DRM_FORMAT_NV12MT: - y_ofs = ALIGN(ALIGN(sz->hsize, 128) * - ALIGN(sz->vsize, 32), SZ_8K); - cb_ofs = ALIGN(ALIGN(sz->hsize, 128) * - ALIGN(sz->vsize >> 1, 32), SZ_8K); - cr_ofs = 0; - break; - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - case DRM_FORMAT_YUV411: - case DRM_FORMAT_YVU411: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YVU422: - case DRM_FORMAT_YUV444: - case DRM_FORMAT_YVU444: - case DRM_FORMAT_YUV420M: - y_ofs = sz->hsize * sz->vsize; - cb_ofs = cr_ofs = y_ofs >> 2; - break; - default: - y_ofs = cb_ofs = cr_ofs = 0; - break; - } - - if (y_ofs && *y_addr) { - *cb_addr = *y_addr + y_ofs; - - if (cb_ofs && *cb_addr) - *cr_addr = *cb_addr + cb_ofs; - } - - return 0; -} - -static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt) -{ - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt); - - /* RGB */ - cfg = fimc_read(EXYNOS_CISCCTRL); - cfg &= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK; - - switch (fmt) { - case DRM_FORMAT_RGB565: - cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB565; - fimc_write(cfg, EXYNOS_CISCCTRL); - return 0; - case DRM_FORMAT_RGB888: - case DRM_FORMAT_XRGB8888: - cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB888; - fimc_write(cfg, EXYNOS_CISCCTRL); - return 0; - default: - /* bypass */ - break; - } - - /* YUV */ - cfg = fimc_read(EXYNOS_MSCTRL); - cfg &= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK | - EXYNOS_MSCTRL_C_INT_IN_2PLANE | - EXYNOS_MSCTRL_ORDER422_YCBYCR); - - switch (fmt) { - case DRM_FORMAT_YUYV: - cfg |= EXYNOS_MSCTRL_ORDER422_YCBYCR; - break; - case DRM_FORMAT_YVYU: - cfg |= EXYNOS_MSCTRL_ORDER422_YCRYCB; - break; - case DRM_FORMAT_UYVY: - cfg |= EXYNOS_MSCTRL_ORDER422_CBYCRY; - break; - case DRM_FORMAT_VYUY: - case DRM_FORMAT_YUV444: - cfg |= EXYNOS_MSCTRL_ORDER422_CRYCBY; - break; - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV61: - cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB | - EXYNOS_MSCTRL_C_INT_IN_2PLANE); - break; - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - cfg |= EXYNOS_MSCTRL_C_INT_IN_3PLANE; - break; - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12M: - case DRM_FORMAT_NV12MT: - case DRM_FORMAT_NV16: - cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR | - EXYNOS_MSCTRL_C_INT_IN_2PLANE); - break; - default: - dev_err(ippdrv->dev, "inavlid source yuv order 0x%x.\n", fmt); - return -EINVAL; - } - - fimc_write(cfg, EXYNOS_MSCTRL); - - return 0; -} - -static int fimc_src_set_fmt(struct device *dev, u32 fmt) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt); - - cfg = fimc_read(EXYNOS_MSCTRL); - cfg &= ~EXYNOS_MSCTRL_INFORMAT_RGB; - - switch (fmt) { - case DRM_FORMAT_RGB565: - case DRM_FORMAT_RGB888: - case DRM_FORMAT_XRGB8888: - cfg |= EXYNOS_MSCTRL_INFORMAT_RGB; - break; - case DRM_FORMAT_YUV444: - cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420; - break; - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE; - break; - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_YUV422: - cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422; - break; - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12M: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV12MT: - cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420; - break; - default: - dev_err(ippdrv->dev, "inavlid source format 0x%x.\n", fmt); - return -EINVAL; - } - - fimc_write(cfg, EXYNOS_MSCTRL); - - cfg = fimc_read(EXYNOS_CIDMAPARAM); - cfg &= ~EXYNOS_CIDMAPARAM_R_MODE_MASK; - - if (fmt == DRM_FORMAT_NV12MT) - cfg |= EXYNOS_CIDMAPARAM_R_MODE_64X32; - else - cfg |= EXYNOS_CIDMAPARAM_R_MODE_LINEAR; - - fimc_write(cfg, EXYNOS_CIDMAPARAM); - - return fimc_src_set_fmt_order(ctx, fmt); -} - -static int fimc_src_set_transf(struct device *dev, - enum drm_exynos_degree degree, - enum drm_exynos_flip flip) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__, - degree, flip); - - cfg = fimc_read(EXYNOS_MSCTRL); - cfg &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR | - EXYNOS_MSCTRL_FLIP_Y_MIRROR); - cfg &= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE; - - switch (degree) { - case EXYNOS_DRM_DEGREE_0: - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg |= EXYNOS_MSCTRL_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg |= EXYNOS_MSCTRL_FLIP_Y_MIRROR; - break; - case EXYNOS_DRM_DEGREE_90: - cfg |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE; - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg |= EXYNOS_MSCTRL_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg |= EXYNOS_MSCTRL_FLIP_Y_MIRROR; - break; - case EXYNOS_DRM_DEGREE_180: - cfg |= (EXYNOS_MSCTRL_FLIP_X_MIRROR | - EXYNOS_MSCTRL_FLIP_Y_MIRROR); - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR; - break; - case EXYNOS_DRM_DEGREE_270: - cfg |= (EXYNOS_CITRGFMT_INROT90_CLOCKWISE | - EXYNOS_MSCTRL_FLIP_X_MIRROR | - EXYNOS_MSCTRL_FLIP_Y_MIRROR); - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR; - break; - default: - dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree); - return -EINVAL; - } - - fimc_write(cfg, EXYNOS_MSCTRL); - - return (cfg & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) ? 1 : 0; -} - -static int fimc_set_window(struct fimc_context *ctx, - struct drm_exynos_pos *pos, struct drm_exynos_sz *sz) -{ - u32 cfg, h1, h2, v1, v2; - - /* cropped image */ - h1 = pos->x; - h2 = sz->hsize - pos->w - pos->x; - v1 = pos->y; - v2 = sz->vsize - pos->h - pos->y; - - DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n", - __func__, pos->x, pos->y, pos->w, pos->h, sz->hsize, sz->vsize); - DRM_DEBUG_KMS("%s:h1[%d]h2[%d]v1[%d]v2[%d]\n", __func__, - h1, h2, v1, v2); - - /* - * set window offset 1, 2 size - * check figure 43-21 in user manual - */ - cfg = fimc_read(EXYNOS_CIWDOFST); - cfg &= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK | - EXYNOS_CIWDOFST_WINVEROFST_MASK); - cfg |= (EXYNOS_CIWDOFST_WINHOROFST(h1) | - EXYNOS_CIWDOFST_WINVEROFST(v1)); - cfg |= EXYNOS_CIWDOFST_WINOFSEN; - fimc_write(cfg, EXYNOS_CIWDOFST); - - cfg = (EXYNOS_CIWDOFST2_WINHOROFST2(h2) | - EXYNOS_CIWDOFST2_WINVEROFST2(v2)); - fimc_write(cfg, EXYNOS_CIWDOFST2); - - return 0; -} - -static int fimc_src_set_size(struct device *dev, int swap, - struct drm_exynos_pos *pos, struct drm_exynos_sz *sz) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_property *property = ippdrv->property; - struct drm_exynos_ipp_config *config = - &property->config[EXYNOS_DRM_OPS_SRC]; - struct drm_exynos_pos img_pos = *pos; - struct drm_exynos_sz img_sz = *sz; - u32 cfg; - - /* ToDo: check width and height */ - - DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n", - __func__, swap, sz->hsize, sz->vsize); - - /* original size */ - cfg = (EXYNOS_ORGISIZE_HORIZONTAL(img_sz.hsize) | - EXYNOS_ORGISIZE_VERTICAL(img_sz.vsize)); - - fimc_write(cfg, EXYNOS_ORGISIZE); - - DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n", __func__, - pos->x, pos->y, pos->w, pos->h); - - if (swap) { - img_pos.w = pos->h; - img_pos.h = pos->w; - img_sz.hsize = sz->vsize; - img_sz.vsize = sz->hsize; - } - - /* set input DMA image size */ - cfg = fimc_read(EXYNOS_CIREAL_ISIZE); - cfg &= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK | - EXYNOS_CIREAL_ISIZE_WIDTH_MASK); - cfg |= (EXYNOS_CIREAL_ISIZE_WIDTH(img_sz.hsize) | - EXYNOS_CIREAL_ISIZE_HEIGHT(img_sz.vsize)); - fimc_write(cfg, EXYNOS_CIREAL_ISIZE); - - /* - * set input FIFO image size - * for now, we support only ITU601 8 bit mode - */ - cfg = (EXYNOS_CISRCFMT_ITU601_8BIT | - EXYNOS_CISRCFMT_SOURCEHSIZE(img_sz.hsize) | - EXYNOS_CISRCFMT_SOURCEVSIZE(img_sz.vsize)); - fimc_write(cfg, EXYNOS_CISRCFMT); - - config->sz = img_sz; - config->pos = img_pos; - - return fimc_set_window(ctx, &img_pos, &img_sz); -} - -static int fimc_src_set_addr(struct device *dev, - struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id, - enum drm_exynos_ipp_buf_ctrl buf_ctrl) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_property *property = ippdrv->property; - struct drm_exynos_ipp_config *config = - &property->config[EXYNOS_DRM_OPS_SRC]; - int ret; - - DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__, - buf_id, buf_ctrl); - - if (buf_id > FIMC_MAX_SRC) { - dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id); - return -ENOMEM; - } - - /* address register set */ - switch (buf_ctrl) { - case IPP_BUF_CTRL_QUEUE: - case IPP_BUF_CTRL_DEQUEUE: - ret = fimc_set_planar_addr(buf_info, config->fmt, &config->sz); - - if (ret) { - dev_err(dev, "failed to set plane addr.\n"); - return ret; - } - - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y], - EXYNOS_CIIYSA(buf_id)); - - if (config->fmt == DRM_FORMAT_YVU420) { - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR], - EXYNOS_CIICBSA(buf_id)); - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], - EXYNOS_CIICRSA(buf_id)); - } else { - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], - EXYNOS_CIICBSA(buf_id)); - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR], - EXYNOS_CIICRSA(buf_id)); - } - break; - default: - /* bypass */ - break; - } - - return 0; -} - -static struct exynos_drm_ipp_ops fimc_src_ops = { - .set_fmt = fimc_src_set_fmt, - .set_transf = fimc_src_set_transf, - .set_size = fimc_src_set_size, - .set_addr = fimc_src_set_addr, -}; - -static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt) -{ - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt); - - /* RGB */ - cfg = fimc_read(EXYNOS_CISCCTRL); - cfg &= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK; - - switch (fmt) { - case DRM_FORMAT_RGB565: - cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565; - fimc_write(cfg, EXYNOS_CISCCTRL); - return 0; - case DRM_FORMAT_RGB888: - cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888; - fimc_write(cfg, EXYNOS_CISCCTRL); - return 0; - case DRM_FORMAT_XRGB8888: - cfg |= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 | - EXYNOS_CISCCTRL_EXTRGB_EXTENSION); - fimc_write(cfg, EXYNOS_CISCCTRL); - break; - default: - /* bypass */ - break; - } - - /* YUV */ - cfg = fimc_read(EXYNOS_CIOCTRL); - cfg &= ~(EXYNOS_CIOCTRL_ORDER2P_MASK | - EXYNOS_CIOCTRL_ORDER422_MASK | - EXYNOS_CIOCTRL_YCBCR_PLANE_MASK); - - switch (fmt) { - case DRM_FORMAT_XRGB8888: - cfg |= EXYNOS_CIOCTRL_ALPHA_OUT; - break; - case DRM_FORMAT_YUYV: - cfg |= EXYNOS_CIOCTRL_ORDER422_YCBYCR; - break; - case DRM_FORMAT_YVYU: - cfg |= EXYNOS_CIOCTRL_ORDER422_YCRYCB; - break; - case DRM_FORMAT_UYVY: - cfg |= EXYNOS_CIOCTRL_ORDER422_CBYCRY; - break; - case DRM_FORMAT_VYUY: - cfg |= EXYNOS_CIOCTRL_ORDER422_CRYCBY; - break; - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV61: - cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB; - cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE; - break; - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - cfg |= EXYNOS_CIOCTRL_YCBCR_3PLANE; - break; - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12M: - case DRM_FORMAT_NV12MT: - case DRM_FORMAT_NV16: - cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR; - cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE; - break; - default: - dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt); - return -EINVAL; - } - - fimc_write(cfg, EXYNOS_CIOCTRL); - - return 0; -} - -static int fimc_dst_set_fmt(struct device *dev, u32 fmt) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt); - - cfg = fimc_read(EXYNOS_CIEXTEN); - - if (fmt == DRM_FORMAT_AYUV) { - cfg |= EXYNOS_CIEXTEN_YUV444_OUT; - fimc_write(cfg, EXYNOS_CIEXTEN); - } else { - cfg &= ~EXYNOS_CIEXTEN_YUV444_OUT; - fimc_write(cfg, EXYNOS_CIEXTEN); - - cfg = fimc_read(EXYNOS_CITRGFMT); - cfg &= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK; - - switch (fmt) { - case DRM_FORMAT_RGB565: - case DRM_FORMAT_RGB888: - case DRM_FORMAT_XRGB8888: - cfg |= EXYNOS_CITRGFMT_OUTFORMAT_RGB; - break; - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE; - break; - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_YUV422: - cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422; - break; - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12M: - case DRM_FORMAT_NV12MT: - case DRM_FORMAT_NV21: - cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420; - break; - default: - dev_err(ippdrv->dev, "inavlid target format 0x%x.\n", - fmt); - return -EINVAL; - } - - fimc_write(cfg, EXYNOS_CITRGFMT); - } - - cfg = fimc_read(EXYNOS_CIDMAPARAM); - cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK; - - if (fmt == DRM_FORMAT_NV12MT) - cfg |= EXYNOS_CIDMAPARAM_W_MODE_64X32; - else - cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR; - - fimc_write(cfg, EXYNOS_CIDMAPARAM); - - return fimc_dst_set_fmt_order(ctx, fmt); -} - -static int fimc_dst_set_transf(struct device *dev, - enum drm_exynos_degree degree, - enum drm_exynos_flip flip) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__, - degree, flip); - - cfg = fimc_read(EXYNOS_CITRGFMT); - cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK; - cfg &= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE; - - switch (degree) { - case EXYNOS_DRM_DEGREE_0: - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR; - break; - case EXYNOS_DRM_DEGREE_90: - cfg |= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE; - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR; - break; - case EXYNOS_DRM_DEGREE_180: - cfg |= (EXYNOS_CITRGFMT_FLIP_X_MIRROR | - EXYNOS_CITRGFMT_FLIP_Y_MIRROR); - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR; - break; - case EXYNOS_DRM_DEGREE_270: - cfg |= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE | - EXYNOS_CITRGFMT_FLIP_X_MIRROR | - EXYNOS_CITRGFMT_FLIP_Y_MIRROR); - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR; - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR; - break; - default: - dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree); - return -EINVAL; - } - - fimc_write(cfg, EXYNOS_CITRGFMT); - - return (cfg & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) ? 1 : 0; -} - -static int fimc_get_ratio_shift(u32 src, u32 dst, u32 *ratio, u32 *shift) -{ - DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst); - - if (src >= dst * 64) { - DRM_ERROR("failed to make ratio and shift.\n"); - return -EINVAL; - } else if (src >= dst * 32) { - *ratio = 32; - *shift = 5; - } else if (src >= dst * 16) { - *ratio = 16; - *shift = 4; - } else if (src >= dst * 8) { - *ratio = 8; - *shift = 3; - } else if (src >= dst * 4) { - *ratio = 4; - *shift = 2; - } else if (src >= dst * 2) { - *ratio = 2; - *shift = 1; - } else { - *ratio = 1; - *shift = 0; - } - - return 0; -} - -static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc, - struct drm_exynos_pos *src, struct drm_exynos_pos *dst) -{ - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg, shfactor; - u32 pre_dst_width, pre_dst_height; - u32 pre_hratio, hfactor, pre_vratio, vfactor; - int ret = 0; - - ret = fimc_get_ratio_shift(src->w, dst->w, &pre_hratio, &hfactor); - if (ret) { - dev_err(ippdrv->dev, "failed to get ratio horizontal.\n"); - return ret; - } - - ret = fimc_get_ratio_shift(src->h, dst->h, &pre_vratio, &vfactor); - if (ret) { - dev_err(ippdrv->dev, "failed to get ratio vertical.\n"); - return ret; - } - - pre_dst_width = src->w / pre_hratio; - pre_dst_height = src->h / pre_vratio; - DRM_DEBUG_KMS("%s:pre_dst_width[%d]pre_dst_height[%d]\n", __func__, - pre_dst_width, pre_dst_height); - DRM_DEBUG_KMS("%s:pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n", - __func__, pre_hratio, hfactor, pre_vratio, vfactor); - - sc->hratio = (src->w << 14) / (dst->w << hfactor); - sc->vratio = (src->h << 14) / (dst->h << vfactor); - sc->up_h = (dst->w >= src->w) ? true : false; - sc->up_v = (dst->h >= src->h) ? true : false; - DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n", - __func__, sc->hratio, sc->vratio, sc->up_h, sc->up_v); - - shfactor = 10 - (hfactor + vfactor); - DRM_DEBUG_KMS("%s:shfactor[%d]\n", __func__, shfactor); - - cfg = (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor) | - EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio) | - EXYNOS_CISCPRERATIO_PREVERRATIO(pre_vratio)); - fimc_write(cfg, EXYNOS_CISCPRERATIO); - - cfg = (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width) | - EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height)); - fimc_write(cfg, EXYNOS_CISCPREDST); - - return ret; -} - -static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc) -{ - u32 cfg, cfg_ext; - - DRM_DEBUG_KMS("%s:range[%d]bypass[%d]up_h[%d]up_v[%d]\n", - __func__, sc->range, sc->bypass, sc->up_h, sc->up_v); - DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]\n", - __func__, sc->hratio, sc->vratio); - - cfg = fimc_read(EXYNOS_CISCCTRL); - cfg &= ~(EXYNOS_CISCCTRL_SCALERBYPASS | - EXYNOS_CISCCTRL_SCALEUP_H | EXYNOS_CISCCTRL_SCALEUP_V | - EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK | - EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK | - EXYNOS_CISCCTRL_CSCR2Y_WIDE | - EXYNOS_CISCCTRL_CSCY2R_WIDE); - - if (sc->range) - cfg |= (EXYNOS_CISCCTRL_CSCR2Y_WIDE | - EXYNOS_CISCCTRL_CSCY2R_WIDE); - if (sc->bypass) - cfg |= EXYNOS_CISCCTRL_SCALERBYPASS; - if (sc->up_h) - cfg |= EXYNOS_CISCCTRL_SCALEUP_H; - if (sc->up_v) - cfg |= EXYNOS_CISCCTRL_SCALEUP_V; - - cfg |= (EXYNOS_CISCCTRL_MAINHORRATIO((sc->hratio >> 6)) | - EXYNOS_CISCCTRL_MAINVERRATIO((sc->vratio >> 6))); - fimc_write(cfg, EXYNOS_CISCCTRL); - - cfg_ext = fimc_read(EXYNOS_CIEXTEN); - cfg_ext &= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK; - cfg_ext &= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK; - cfg_ext |= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc->hratio) | - EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc->vratio)); - fimc_write(cfg_ext, EXYNOS_CIEXTEN); -} - -static int fimc_dst_set_size(struct device *dev, int swap, - struct drm_exynos_pos *pos, struct drm_exynos_sz *sz) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_property *property = ippdrv->property; - struct drm_exynos_ipp_config *config = - &property->config[EXYNOS_DRM_OPS_DST]; - struct drm_exynos_pos img_pos = *pos; - struct drm_exynos_sz img_sz = *sz; - u32 cfg; - - DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n", - __func__, swap, sz->hsize, sz->vsize); - - /* original size */ - cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz.hsize) | - EXYNOS_ORGOSIZE_VERTICAL(img_sz.vsize)); - - fimc_write(cfg, EXYNOS_ORGOSIZE); - - DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n", - __func__, pos->x, pos->y, pos->w, pos->h); - - /* CSC ITU */ - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg &= ~EXYNOS_CIGCTRL_CSC_MASK; - - if (sz->hsize >= FIMC_WIDTH_ITU_709) - cfg |= EXYNOS_CIGCTRL_CSC_ITU709; - else - cfg |= EXYNOS_CIGCTRL_CSC_ITU601; - - fimc_write(cfg, EXYNOS_CIGCTRL); - - if (swap) { - img_pos.w = pos->h; - img_pos.h = pos->w; - img_sz.hsize = sz->vsize; - img_sz.vsize = sz->hsize; - } - - /* target image size */ - cfg = fimc_read(EXYNOS_CITRGFMT); - cfg &= ~(EXYNOS_CITRGFMT_TARGETH_MASK | - EXYNOS_CITRGFMT_TARGETV_MASK); - cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos.w) | - EXYNOS_CITRGFMT_TARGETVSIZE(img_pos.h)); - fimc_write(cfg, EXYNOS_CITRGFMT); - - /* target area */ - cfg = EXYNOS_CITAREA_TARGET_AREA(img_pos.w * img_pos.h); - fimc_write(cfg, EXYNOS_CITAREA); - - /* ToDo: Move Scaler in this line and YUV */ - config->sz = img_sz; - config->pos = img_pos; - - /* offset Y(RGB), Cb, Cr */ - cfg = (EXYNOS_CIOYOFF_HORIZONTAL(img_pos.x) | - EXYNOS_CIOYOFF_VERTICAL(img_pos.y)); - fimc_write(cfg, EXYNOS_CIOYOFF); - cfg = (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos.x) | - EXYNOS_CIOCBOFF_VERTICAL(img_pos.y)); - fimc_write(cfg, EXYNOS_CIOCBOFF); - cfg = (EXYNOS_CIOCROFF_HORIZONTAL(img_pos.x) | - EXYNOS_CIOCROFF_VERTICAL(img_pos.y)); - fimc_write(cfg, EXYNOS_CIOCROFF); - - return 0; -} - -static int fimc_dst_get_buf_seq(struct fimc_context *ctx) -{ - u32 cfg, i, buf_num = 0; - u32 mask = 0x00000001; - - cfg = fimc_read(EXYNOS_CIFCNTSEQ); - - for (i = 0; i < FIMC_REG_SZ; i++) - if (cfg & (mask << i)) - buf_num++; - - DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num); - - return buf_num; -} - -static int fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id, - enum drm_exynos_ipp_buf_ctrl buf_ctrl) -{ - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - bool enable; - u32 cfg; - u32 mask = 0x00000001 << buf_id; - - DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__, - buf_id, buf_ctrl); - - /* mask register set */ - cfg = fimc_read(EXYNOS_CIFCNTSEQ); - - switch (buf_ctrl) { - case IPP_BUF_CTRL_QUEUE: - enable = true; - break; - case IPP_BUF_CTRL_DEQUEUE: - enable = false; - break; - default: - dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n"); - return -EINVAL; - } - - /* sequence id */ - cfg &= (~mask); - cfg |= (enable << buf_id); - fimc_write(cfg, EXYNOS_CIFCNTSEQ); - - /* interrupt enable */ - if (buf_ctrl == IPP_BUF_CTRL_QUEUE && - fimc_dst_get_buf_seq(ctx) >= FIMC_BUF_START) - fimc_handle_irq(ctx, true, false, true); - - /* interrupt disable */ - if (buf_ctrl == IPP_BUF_CTRL_DEQUEUE && - fimc_dst_get_buf_seq(ctx) <= FIMC_BUF_STOP) - fimc_handle_irq(ctx, false, false, true); - - return 0; -} - -static int fimc_dst_set_addr(struct device *dev, - struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id, - enum drm_exynos_ipp_buf_ctrl buf_ctrl) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_property *property = ippdrv->property; - struct drm_exynos_ipp_config *config = - &property->config[EXYNOS_DRM_OPS_DST]; - int ret; - - DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__, - buf_id, buf_ctrl); - - if (buf_id > FIMC_MAX_DST) { - dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id); - return -ENOMEM; - } - - /* address register set */ - switch (buf_ctrl) { - case IPP_BUF_CTRL_QUEUE: - case IPP_BUF_CTRL_DEQUEUE: - ret = fimc_set_planar_addr(buf_info, config->fmt, &config->sz); - - if (ret) { - dev_err(dev, "failed to set plane addr.\n"); - return ret; - } - - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y], - EXYNOS_CIOYSA(buf_id)); - - if (config->fmt == DRM_FORMAT_YVU420) { - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR], - EXYNOS_CIOCBSA(buf_id)); - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], - EXYNOS_CIOCRSA(buf_id)); - } else { - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], - EXYNOS_CIOCBSA(buf_id)); - fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR], - EXYNOS_CIOCRSA(buf_id)); - } - break; - default: - /* bypass */ - break; - } - - return fimc_dst_set_buf_seq(ctx, buf_id, buf_ctrl); -} - -static struct exynos_drm_ipp_ops fimc_dst_ops = { - .set_fmt = fimc_dst_set_fmt, - .set_transf = fimc_dst_set_transf, - .set_size = fimc_dst_set_size, - .set_addr = fimc_dst_set_addr, -}; - -static int fimc_power_on(struct fimc_context *ctx, bool enable) -{ - DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable); - - if (enable) { - clk_enable(ctx->sclk_fimc_clk); - clk_enable(ctx->fimc_clk); - clk_enable(ctx->wb_clk); - /* ToDo : wb_b_clk */ - ctx->suspended = false; - } else { - clk_disable(ctx->sclk_fimc_clk); - clk_disable(ctx->fimc_clk); - clk_disable(ctx->wb_clk); - /* ToDo : wb_b_clk */ - ctx->suspended = true; - } - - return 0; -} - -static irqreturn_t fimc_irq_handler(int irq, void *dev_id) -{ - struct fimc_context *ctx = dev_id; - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - int buf_id; - u32 status1, status2; - - DRM_DEBUG_KMS("%s:fimc id[%d]\n", __func__, ctx->id); - - /* ToDo: must be remove debug routine */ - status1 = fimc_read(EXYNOS_CISTATUS); - status2 = fimc_read(EXYNOS_CISTATUS2); - DRM_DEBUG_KMS("%s:status1[0x%x]status2[0x%x]\n", - __func__, status1, status2); - - fimc_clear_irq(ctx); - if (fimc_check_ovf(ctx)) - return IRQ_NONE; - - if (!fimc_check_frame_end(ctx)) - return IRQ_NONE; - - if (list_empty(&ippdrv->event_list)) { - DRM_DEBUG_KMS("%s:event list empty. so ignore.\n", __func__); - - return IRQ_NONE; - } - - buf_id = fimc_get_buf_id(ctx); - if (buf_id < 0) - return IRQ_HANDLED; - - DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id); - - if (fimc_dst_set_buf_seq(ctx, buf_id, - IPP_BUF_CTRL_DEQUEUE) < 0) { - DRM_ERROR("failed to dequeue.\n"); - - return IRQ_HANDLED; - } - - ipp_send_event_handler(ippdrv, buf_id); - - if (fimc_dst_get_buf_seq(ctx) <= FIMC_BUF_STOP) - fimc_handle_irq(ctx, false, false, true); - - return IRQ_HANDLED; -} - -static int fimc_ippdrv_check_property(struct device *dev, - struct drm_exynos_ipp_property *property) -{ - /* ToDo: check valid using property information */ - DRM_DEBUG_KMS("%s\n", __func__); - - return 0; -} - -static int fimc_ippdrv_reset(struct device *dev) -{ - struct fimc_context *ctx = get_fimc_context(dev); - - DRM_DEBUG_KMS("%s\n", __func__); - - /* reset h/w block */ - fimc_sw_reset(ctx, false); - - /* reset scaler capability */ - memset(&ctx->sc, 0x0, sizeof(ctx->sc)); - - return 0; -} - -static int fimc_check_prepare(struct fimc_context *ctx) -{ - /* ToDo: check prepare using read register */ - DRM_DEBUG_KMS("%s\n", __func__); - - return 0; -} - -static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_property *property = ippdrv->property; - struct drm_exynos_ipp_config *config; - struct drm_exynos_pos img_pos[EXYNOS_DRM_OPS_MAX]; - int ret, i; - int enable = 1; - u32 cfg0, cfg1; - - DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd); - - ret = fimc_check_prepare(ctx); - if (ret) { - dev_err(dev, "failed to check prepare.\n"); - return ret; - } - - ippdrv->cmd = cmd; - fimc_handle_irq(ctx, true, false, true); - - /* ToDo: window size, prescaler config */ - for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) { - config = &property->config[i]; - img_pos[i] = config->pos; - } - - ret = fimc_set_prescaler(ctx, &ctx->sc, - &img_pos[EXYNOS_DRM_OPS_SRC], - &img_pos[EXYNOS_DRM_OPS_DST]); - if (ret) { - dev_err(dev, "failed to set precalser.\n"); - return ret; - } - - /* If set ture, we can save jpeg about screen */ - fimc_handle_jpeg(ctx, false); - fimc_set_scaler(ctx, &ctx->sc); - fimc_set_polarity(ctx, &ctx->pol); - - switch (cmd) { - case IPP_CMD_M2M: - fimc_set_type_ctrl(ctx, FIMC_WB_NONE); - fimc_handle_lastend(ctx, false); - - /* setup dma */ - cfg0 = fimc_read(EXYNOS_MSCTRL); - cfg0 &= ~EXYNOS_MSCTRL_INPUT_MASK; - cfg0 |= EXYNOS_MSCTRL_INPUT_MEMORY; - fimc_write(cfg0, EXYNOS_MSCTRL); - break; - case IPP_CMD_WB: - fimc_set_type_ctrl(ctx, FIMC_WB_A); - fimc_handle_lastend(ctx, true); - - /* setup FIMD */ - fimc_set_camblk_fimd0_wb(ctx); - exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)enable); - break; - case IPP_CMD_OUTPUT: - default: - ret = -EINVAL; - dev_err(dev, "invalid operations.\n"); - return ret; - } - - /* Reset status */ - fimc_write(0x0, EXYNOS_CISTATUS); - - cfg0 = fimc_read(EXYNOS_CIIMGCPT); - cfg0 &= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC; - cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN_SC; - - /* Scaler */ - cfg1 = fimc_read(EXYNOS_CISCCTRL); - cfg1 &= ~EXYNOS_CISCCTRL_SCAN_MASK; - cfg1 |= (EXYNOS_CISCCTRL_PROGRESSIVE | - EXYNOS_CISCCTRL_SCALERSTART); - - fimc_write(cfg1, EXYNOS_CISCCTRL); - - /* Enable image capture*/ - cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN; - fimc_write(cfg0, EXYNOS_CIIMGCPT); - - /* Disable frame end irq */ - cfg0 = fimc_read(EXYNOS_CIGCTRL); - cfg0 &= ~EXYNOS_CIGCTRL_IRQ_END_DISABLE; - fimc_write(cfg0, EXYNOS_CIGCTRL); - - cfg0 = fimc_read(EXYNOS_CIOCTRL); - cfg0 &= ~EXYNOS_CIOCTRL_WEAVE_MASK; - fimc_write(cfg0, EXYNOS_CIOCTRL); - - /* ToDo: m2m start errata - refer fimd */ - if (cmd == IPP_CMD_M2M) { - cfg0 = fimc_read(EXYNOS_MSCTRL); - cfg0 |= EXYNOS_MSCTRL_ENVID; - fimc_write(cfg0, EXYNOS_MSCTRL); - - cfg0 = fimc_read(EXYNOS_MSCTRL); - cfg0 |= EXYNOS_MSCTRL_ENVID; - fimc_write(cfg0, EXYNOS_MSCTRL); - } - - return 0; -} - -static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd) -{ - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - int enable = 0; - u32 cfg; - - DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd); - - switch (cmd) { - case IPP_CMD_M2M: - /* Source clear */ - cfg = fimc_read(EXYNOS_MSCTRL); - cfg &= ~EXYNOS_MSCTRL_INPUT_MASK; - cfg &= ~EXYNOS_MSCTRL_ENVID; - fimc_write(cfg, EXYNOS_MSCTRL); - break; - case IPP_CMD_WB: - exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)enable); - break; - case IPP_CMD_OUTPUT: - default: - dev_err(dev, "invalid operations.\n"); - break; - } - - ippdrv->cmd = IPP_CMD_NONE; - fimc_handle_irq(ctx, false, false, true); - - /* reset sequence */ - fimc_write(0x0, EXYNOS_CIFCNTSEQ); - - /* Scaler disable */ - cfg = fimc_read(EXYNOS_CISCCTRL); - cfg &= ~EXYNOS_CISCCTRL_SCALERSTART; - fimc_write(cfg, EXYNOS_CISCCTRL); - - /* Disable image capture */ - cfg = fimc_read(EXYNOS_CIIMGCPT); - cfg &= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN); - fimc_write(cfg, EXYNOS_CIIMGCPT); - - /* Enable frame end irq */ - cfg = fimc_read(EXYNOS_CIGCTRL); - cfg |= EXYNOS_CIGCTRL_IRQ_END_DISABLE; - fimc_write(cfg, EXYNOS_CIGCTRL); -} - -static struct fimc_capability *fimc_get_capability( - enum exynos_drm_fimc_ver ver) -{ - struct fimc_capability *capa; - - DRM_DEBUG_KMS("%s:ver[0x%x]\n", __func__, ver); - - /* ToDo: version check */ - switch (ver) { - case FIMC_EXYNOS_4412: - default: - capa = fimc51_capa; - break; - } - - return capa; -} - -#ifdef CONFIG_SLP_DISP_DEBUG -static int fimc_read_reg(struct fimc_context *ctx, char *buf) -{ - u32 cfg; - int i; - int pos = 0; - - pos += sprintf(buf+pos, "0x%.8x | ", FIMC_BASE_REG(ctx->id)); - for (i = 1; i < FIMC_MAX_REG + 1; i++) { - cfg = fimc_read((i-1) * sizeof(u32)); - pos += sprintf(buf+pos, "0x%.8x ", cfg); - if (i % 4 == 0) - pos += sprintf(buf+pos, "\n0x%.8x | ", - FIMC_BASE_REG(ctx->id) + (i * sizeof(u32))); - } - - pos += sprintf(buf+pos, "\n"); - - return pos; -} - -static ssize_t show_read_reg(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct fimc_context *ctx = get_fimc_context(dev); - - if (!ctx->regs) { - dev_err(dev, "failed to get current register.\n"); - return -EINVAL; - } - - return fimc_read_reg(ctx, buf); -} - -static struct device_attribute device_attrs[] = { - __ATTR(read_reg, S_IRUGO, show_read_reg, NULL), -}; -#endif - -static int __devinit fimc_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct fimc_context *ctx; - struct clk *parent_clk; - struct resource *res; - struct exynos_drm_ippdrv *ippdrv; - struct exynos_drm_fimc_pdata *pdata; - int ret = -EINVAL; -#ifdef CONFIG_SLP_DISP_DEBUG - int i; -#endif - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(dev, "no platform data specified.\n"); - return -EINVAL; - } - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - /* clock control */ - ctx->sclk_fimc_clk = clk_get(dev, "sclk_fimc"); - if (IS_ERR(ctx->sclk_fimc_clk)) { - dev_err(dev, "failed to get src fimc clock.\n"); - ret = PTR_ERR(ctx->sclk_fimc_clk); - goto err_ctx; - } - clk_enable(ctx->sclk_fimc_clk); - - ctx->fimc_clk = clk_get(dev, "fimc"); - if (IS_ERR(ctx->fimc_clk)) { - dev_err(dev, "failed to get fimc clock.\n"); - ret = PTR_ERR(ctx->fimc_clk); - clk_put(ctx->sclk_fimc_clk); - goto err_ctx; - } - - ctx->wb_clk = clk_get(dev, "pxl_async0"); - if (IS_ERR(ctx->wb_clk)) { - dev_err(dev, "failed to get writeback a clock.\n"); - ret = PTR_ERR(ctx->wb_clk); - clk_put(ctx->sclk_fimc_clk); - clk_put(ctx->fimc_clk); - goto err_ctx; - } - - ctx->wb_b_clk = clk_get(dev, "pxl_async1"); - if (IS_ERR(ctx->wb_b_clk)) { - dev_err(dev, "failed to get writeback b clock.\n"); - ret = PTR_ERR(ctx->wb_b_clk); - clk_put(ctx->sclk_fimc_clk); - clk_put(ctx->fimc_clk); - clk_put(ctx->wb_clk); - goto err_ctx; - } - - if (pdata->ver == FIMC_EXYNOS_4212 || - pdata->ver == FIMC_EXYNOS_4412) - parent_clk = clk_get(dev, "mout_mpll_user"); - else - parent_clk = clk_get(dev, "mout_mpll"); - - if (IS_ERR(parent_clk)) { - dev_err(dev, "failed to get parent clock.\n"); - ret = PTR_ERR(parent_clk); - clk_put(ctx->sclk_fimc_clk); - clk_put(ctx->fimc_clk); - clk_put(ctx->wb_clk); - clk_put(ctx->wb_b_clk); - goto err_ctx; - } - - if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) { - dev_err(dev, "failed to set parent.\n"); - clk_put(parent_clk); - clk_put(ctx->sclk_fimc_clk); - clk_put(ctx->fimc_clk); - clk_put(ctx->wb_clk); - clk_put(ctx->wb_b_clk); - goto err_ctx; - } - clk_put(parent_clk); - clk_set_rate(ctx->sclk_fimc_clk, FIMC_CLK_RATE); - clk_disable(ctx->sclk_fimc_clk); - - /* resource memory */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "failed to find registers.\n"); - ret = -ENOENT; - goto err_clk; - } - - ctx->regs_res = request_mem_region(res->start, resource_size(res), - dev_name(dev)); - if (!ctx->regs_res) { - dev_err(dev, "failed to claim register region.\n"); - ret = -ENOENT; - goto err_clk; - } - - ctx->regs = ioremap(res->start, resource_size(res)); - if (!ctx->regs) { - dev_err(dev, "failed to map registers.\n"); - ret = -ENXIO; - goto err_req_region; - } - - /* resource irq */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(dev, "failed to request irq resource.\n"); - goto err_get_regs; - } - - ctx->irq = res->start; - ret = request_threaded_irq(ctx->irq, NULL, fimc_irq_handler, - IRQF_ONESHOT, "drm_fimc", ctx); - if (ret < 0) { - dev_err(dev, "failed to request irq.\n"); - goto err_get_regs; - } - - /* context initailization */ - ctx->ver = pdata->ver; - ctx->id = pdev->id; - ctx->capa = fimc_get_capability(ctx->ver); - if (!ctx->capa) { - dev_err(dev, "failed to get capability.\n"); - goto err_get_irq; - } - ctx->pol = pdata->pol; - -#ifdef CONFIG_SLP_DISP_DEBUG - for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { - ret = device_create_file(&(pdev->dev), - &device_attrs[i]); - if (ret) - break; - } - - if (ret < 0) - dev_err(&pdev->dev, "failed to add sysfs entries\n"); -#endif - - DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id); - - ippdrv = &ctx->ippdrv; - ippdrv->dev = dev; - ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops; - ippdrv->ops[EXYNOS_DRM_OPS_DST] = &fimc_dst_ops; - ippdrv->check_property = fimc_ippdrv_check_property; - ippdrv->reset = fimc_ippdrv_reset; - ippdrv->start = fimc_ippdrv_start; - ippdrv->stop = fimc_ippdrv_stop; - - mutex_init(&ctx->lock); - platform_set_drvdata(pdev, ctx); - - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - - ret = exynos_drm_ippdrv_register(ippdrv); - if (ret < 0) { - dev_err(dev, "failed to register drm fimc device.\n"); - goto err_get_irq; - } - - dev_info(&pdev->dev, "drm fimc registered successfully.\n"); - - return 0; - -err_get_irq: - free_irq(ctx->irq, ctx); -err_get_regs: - iounmap(ctx->regs); -err_req_region: - release_resource(ctx->regs_res); - kfree(ctx->regs_res); -err_clk: - clk_put(ctx->sclk_fimc_clk); - clk_put(ctx->fimc_clk); - clk_put(ctx->wb_clk); - clk_put(ctx->wb_b_clk); -err_ctx: - kfree(ctx); - return ret; -} - -static int __devexit fimc_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct fimc_context *ctx = get_fimc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - - exynos_drm_ippdrv_unregister(ippdrv); - - pm_runtime_set_suspended(dev); - pm_runtime_disable(dev); - - free_irq(ctx->irq, ctx); - iounmap(ctx->regs); - release_resource(ctx->regs_res); - kfree(ctx->regs_res); - - clk_put(ctx->sclk_fimc_clk); - clk_put(ctx->fimc_clk); - clk_put(ctx->wb_clk); - clk_put(ctx->wb_b_clk); - - kfree(ctx); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int fimc_suspend(struct device *dev) -{ - struct fimc_context *ctx = get_fimc_context(dev); - - DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id); - if (pm_runtime_suspended(dev)) - return 0; - /* ToDo */ - return fimc_power_on(ctx, false); -} - -static int fimc_resume(struct device *dev) -{ - struct fimc_context *ctx = get_fimc_context(dev); - - DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id); - if (!pm_runtime_suspended(dev)) - return fimc_power_on(ctx, true); - /* ToDo */ - return 0; -} -#endif - -#ifdef CONFIG_PM_RUNTIME -static int fimc_runtime_suspend(struct device *dev) -{ - struct fimc_context *ctx = get_fimc_context(dev); - - DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id); - /* ToDo */ - return fimc_power_on(ctx, false); -} - -static int fimc_runtime_resume(struct device *dev) -{ - struct fimc_context *ctx = get_fimc_context(dev); - - DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id); - /* ToDo */ - return fimc_power_on(ctx, true); -} -#endif - -static const struct dev_pm_ops fimc_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume) - SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL) -}; - -/* ToDo: need to check use case platform_device_id */ -struct platform_driver fimc_driver = { - .probe = fimc_probe, - .remove = __devexit_p(fimc_remove), - .driver = { - .name = "exynos-drm-fimc", - .owner = THIS_MODULE, - .pm = &fimc_pm_ops, - }, -}; - diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.h b/drivers/gpu/drm/exynos/exynos_drm_fimc.h deleted file mode 100644 index e631774..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * - * Authors: - * Eunchul Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_FIMC_H_ -#define _EXYNOS_DRM_FIMC_H_ - -/* ToDo */ - -#endif /* _EXYNOS_DRM_FIMC_H_ */ - diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c deleted file mode 100644 index 5633207..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ /dev/null @@ -1,1038 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Authors: Joonyoung Shim - * - * 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 Foundationr - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "drmP.h" -#include "exynos_drm.h" -#include "exynos_drm_drv.h" -#include "exynos_drm_gem.h" -#include "exynos_drm_iommu.h" - -#define G2D_HW_MAJOR_VER 4 -#define G2D_HW_MINOR_VER 1 - -/* vaild register range set from user: 0x0104 ~ 0x0880 */ -#define G2D_VALID_START 0x0104 -#define G2D_VALID_END 0x0880 - -/* general registers */ -#define G2D_SOFT_RESET 0x0000 -#define G2D_INTEN 0x0004 -#define G2D_INTC_PEND 0x000C -#define G2D_DMA_SFR_BASE_ADDR 0x0080 -#define G2D_DMA_COMMAND 0x0084 -#define G2D_DMA_STATUS 0x008C -#define G2D_DMA_HOLD_CMD 0x0090 - -/* command registers */ -#define G2D_BITBLT_START 0x0100 - -/* registers for base address */ -#define G2D_SRC_BASE_ADDR 0x0304 -#define G2D_SRC_PLANE2_BASE_ADDR 0x0318 -#define G2D_DST_BASE_ADDR 0x0404 -#define G2D_DST_PLANE2_BASE_ADDR 0x0418 -#define G2D_PAT_BASE_ADDR 0x0500 -#define G2D_MSK_BASE_ADDR 0x0520 - -/* G2D_SOFT_RESET */ -#define G2D_SFRCLEAR (1 << 1) -#define G2D_R (1 << 0) - -/* G2D_INTEN */ -#define G2D_INTEN_ACF (1 << 3) -#define G2D_INTEN_UCF (1 << 2) -#define G2D_INTEN_GCF (1 << 1) -#define G2D_INTEN_SCF (1 << 0) - -/* G2D_INTC_PEND */ -#define G2D_INTP_ACMD_FIN (1 << 3) -#define G2D_INTP_UCMD_FIN (1 << 2) -#define G2D_INTP_GCMD_FIN (1 << 1) -#define G2D_INTP_SCMD_FIN (1 << 0) - -/* G2D_DMA_COMMAND */ -#define G2D_DMA_HALT (1 << 2) -#define G2D_DMA_CONTINUE (1 << 1) -#define G2D_DMA_START (1 << 0) - -/* G2D_DMA_STATUS */ -#define G2D_DMA_LIST_DONE_COUNT (0xFF << 17) -#define G2D_DMA_BITBLT_DONE_COUNT (0xFFFF << 1) -#define G2D_DMA_DONE (1 << 0) -#define G2D_DMA_LIST_DONE_COUNT_OFFSET 17 - -/* G2D_DMA_HOLD_CMD */ -#define G2D_USET_HOLD (1 << 2) -#define G2D_LIST_HOLD (1 << 1) -#define G2D_BITBLT_HOLD (1 << 0) - -/* G2D_BITBLT_START */ -#define G2D_START_CASESEL (1 << 2) -#define G2D_START_NHOLT (1 << 1) -#define G2D_START_BITBLT (1 << 0) - -#define G2D_CMDLIST_SIZE (PAGE_SIZE / 4) -#define G2D_CMDLIST_NUM 64 -#define G2D_CMDLIST_POOL_SIZE (G2D_CMDLIST_SIZE * G2D_CMDLIST_NUM) -#define G2D_CMDLIST_DATA_NUM (G2D_CMDLIST_SIZE / sizeof(u32) - 2) - -#define MAX_BUF_ADDR_NR 6 - -/* cmdlist data structure */ -struct g2d_cmdlist { - u32 head; - u32 data[G2D_CMDLIST_DATA_NUM]; - u32 last; /* last data offset */ -}; - -struct drm_exynos_pending_g2d_event { - struct drm_pending_event base; - struct drm_exynos_g2d_event event; -}; - -struct g2d_cmdlist_node { - struct list_head list; - struct g2d_cmdlist *cmdlist; - unsigned int map_nr; - void *gem_objs[MAX_BUF_ADDR_NR]; - dma_addr_t dma_addr; - - struct drm_exynos_pending_g2d_event *event; -}; - -struct g2d_runqueue_node { - struct list_head list; - struct list_head run_cmdlist; - struct list_head event_list; - struct completion complete; - int async; -}; - -struct g2d_data { - struct device *dev; - struct clk *gate_clk; - struct resource *regs_res; - void __iomem *regs; - int irq; - struct workqueue_struct *g2d_workq; - struct work_struct runqueue_work; - struct exynos_drm_subdrv subdrv; - struct pm_qos_request_list pm_qos; - bool suspended; - - /* cmdlist */ - struct g2d_cmdlist_node *cmdlist_node; - struct list_head free_cmdlist; - struct mutex cmdlist_mutex; - dma_addr_t cmdlist_pool; - dma_addr_t cmdlist_pool_map; - void *cmdlist_pool_virt; - - /* runqueue*/ - struct g2d_runqueue_node *runqueue_node; - struct list_head runqueue; - struct mutex runqueue_mutex; - struct kmem_cache *runqueue_slab; -}; - -static int g2d_init_cmdlist(struct g2d_data *g2d, - struct exynos_drm_private *drm_priv) -{ - struct device *dev = g2d->dev; - struct g2d_cmdlist_node *node = g2d->cmdlist_node; - int nr; - int ret; - - g2d->cmdlist_pool_virt = dma_alloc_coherent(dev, G2D_CMDLIST_POOL_SIZE, - &g2d->cmdlist_pool, GFP_KERNEL); - if (!g2d->cmdlist_pool_virt) { - dev_err(dev, "failed to allocate dma memory\n"); - return -ENOMEM; - } - - /* - * Allocate device address space for command list pool and then map all - * pages contained in sg list to iommu table. Command list pool also is - * accessed by dma through device address with using iommu. - */ - g2d->cmdlist_pool_map = exynos_drm_iommu_map(drm_priv->vmm, - g2d->cmdlist_pool, - G2D_CMDLIST_POOL_SIZE); - if (!g2d->cmdlist_pool_map) { - dev_err(dev, "failed map to iommu\n"); - ret = -EFAULT; - goto err; - } - - node = kcalloc(G2D_CMDLIST_NUM, G2D_CMDLIST_NUM * sizeof(*node), - GFP_KERNEL); - if (!node) { - dev_err(dev, "failed to allocate memory\n"); - ret = -ENOMEM; - goto err_iommu_unmap; - } - - for (nr = 0; nr < G2D_CMDLIST_NUM; nr++) { - node[nr].cmdlist = - g2d->cmdlist_pool_virt + nr * G2D_CMDLIST_SIZE; - node[nr].dma_addr = - g2d->cmdlist_pool_map + nr * G2D_CMDLIST_SIZE; - - list_add_tail(&node[nr].list, &g2d->free_cmdlist); - } - - return 0; - -err_iommu_unmap: - exynos_drm_iommu_unmap(drm_priv->vmm, g2d->cmdlist_pool_map); -err: - dma_free_coherent(dev, G2D_CMDLIST_POOL_SIZE, g2d->cmdlist_pool_virt, - g2d->cmdlist_pool); - return ret; -} - -static void g2d_fini_cmdlist(struct g2d_data *g2d) -{ - struct exynos_drm_private *drm_priv; - struct exynos_drm_subdrv *subdrv = &g2d->subdrv; - - drm_priv = subdrv->drm_dev->dev_private; - - if (drm_priv->vmm) - exynos_drm_iommu_unmap(drm_priv->vmm, g2d->cmdlist_pool_map); - - kfree(g2d->cmdlist_node); - dma_free_coherent(g2d->dev, G2D_CMDLIST_POOL_SIZE, - g2d->cmdlist_pool_virt, - g2d->cmdlist_pool); -} - -static struct g2d_cmdlist_node *g2d_get_cmdlist(struct g2d_data *g2d) -{ - struct device *dev = g2d->dev; - struct g2d_cmdlist_node *node; - - mutex_lock(&g2d->cmdlist_mutex); - if (list_empty(&g2d->free_cmdlist)) { - dev_err(dev, "there is no free cmdlist\n"); - mutex_unlock(&g2d->cmdlist_mutex); - return NULL; - } - - node = list_first_entry(&g2d->free_cmdlist, struct g2d_cmdlist_node, - list); - list_del_init(&node->list); - mutex_unlock(&g2d->cmdlist_mutex); - - return node; -} - -static void g2d_put_cmdlist(struct g2d_data *g2d, struct g2d_cmdlist_node *node) -{ - mutex_lock(&g2d->cmdlist_mutex); - list_move_tail(&node->list, &g2d->free_cmdlist); - mutex_unlock(&g2d->cmdlist_mutex); -} - -static void g2d_add_cmdlist_to_inuse(struct exynos_drm_g2d_private *g2d_priv, - struct g2d_cmdlist_node *node) -{ - struct g2d_cmdlist_node *lnode; - - if (list_empty(&g2d_priv->inuse_cmdlist)) - goto add_to_list; - - /* this links to base address of new cmdlist */ - lnode = list_entry(g2d_priv->inuse_cmdlist.prev, - struct g2d_cmdlist_node, list); - lnode->cmdlist->data[lnode->cmdlist->last] = node->dma_addr; - -add_to_list: - list_add_tail(&node->list, &g2d_priv->inuse_cmdlist); - - if (node->event) - list_add_tail(&node->event->base.link, &g2d_priv->event_list); -} - -static int g2d_map_cmdlist_gem(struct g2d_data *g2d, - struct g2d_cmdlist_node *node, - struct drm_device *drm_dev, - struct drm_file *file) -{ - struct g2d_cmdlist *cmdlist = node->cmdlist; - int offset; - int i; - - for (i = 0; i < node->map_nr; i++) { - unsigned int gem_handle, gem_obj; - dma_addr_t *addr; - - offset = cmdlist->last - (i * 2 + 1); - gem_handle = cmdlist->data[offset]; - - addr = exynos_drm_gem_get_dma_addr(drm_dev, gem_handle, - file, - &gem_obj); - if (IS_ERR(addr)) { - node->map_nr = i; - return -EFAULT; - } - - cmdlist->data[offset] = *addr; - node->gem_objs[i] = (void *)gem_obj; - } - - return 0; -} - -static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d, - struct g2d_cmdlist_node *node) -{ - struct exynos_drm_subdrv *subdrv = &g2d->subdrv; - int i; - - for (i = 0; i < node->map_nr; i++) { - void *gem_obj = node->gem_objs[i]; - - if (gem_obj) - exynos_drm_gem_put_dma_addr(subdrv->drm_dev, gem_obj); - - node->gem_objs[i] = NULL; - } - - node->map_nr = 0; -} - -static void g2d_dma_start(struct g2d_data *g2d, - struct g2d_runqueue_node *runqueue_node) -{ - struct g2d_cmdlist_node *node = - list_first_entry(&runqueue_node->run_cmdlist, - struct g2d_cmdlist_node, list); - - pm_runtime_get_sync(g2d->dev); - clk_enable(g2d->gate_clk); - pm_qos_update_request(&g2d->pm_qos, 400200); - - /* interrupt enable */ - writel_relaxed(G2D_INTEN_ACF | G2D_INTEN_UCF | G2D_INTEN_GCF, - g2d->regs + G2D_INTEN); - - writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR); - writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND); -} - -static struct g2d_runqueue_node *g2d_get_runqueue_node(struct g2d_data *g2d) -{ - struct g2d_runqueue_node *runqueue_node; - - if (list_empty(&g2d->runqueue)) - return NULL; - - runqueue_node = list_first_entry(&g2d->runqueue, - struct g2d_runqueue_node, list); - list_del_init(&runqueue_node->list); - return runqueue_node; -} - -static void g2d_free_runqueue_node(struct g2d_data *g2d, - struct g2d_runqueue_node *runqueue_node) -{ - struct g2d_cmdlist_node *node; - - if (!runqueue_node) - return; - - mutex_lock(&g2d->cmdlist_mutex); - /* - * commands in run_cmdlist have been completed so unmap all gem - * objects in each command node so that they are unreferenced. - */ - list_for_each_entry(node, &runqueue_node->run_cmdlist, list) - g2d_unmap_cmdlist_gem(g2d, node); - list_splice_tail_init(&runqueue_node->run_cmdlist, &g2d->free_cmdlist); - mutex_unlock(&g2d->cmdlist_mutex); - - kmem_cache_free(g2d->runqueue_slab, runqueue_node); -} - -static void g2d_exec_runqueue(struct g2d_data *g2d) -{ - g2d->runqueue_node = g2d_get_runqueue_node(g2d); - if (g2d->runqueue_node) - g2d_dma_start(g2d, g2d->runqueue_node); -} - -static void g2d_runqueue_worker(struct work_struct *work) -{ - struct g2d_data *g2d = container_of(work, struct g2d_data, - runqueue_work); - - pm_qos_update_request(&g2d->pm_qos, 0); - - mutex_lock(&g2d->runqueue_mutex); - clk_disable(g2d->gate_clk); - pm_runtime_put_sync(g2d->dev); - - /* if async mode, do not call complete. */ - if (!g2d->runqueue_node->async) - complete(&g2d->runqueue_node->complete); - - /* - * if async mode, run_cmdlist of runqueue_node is not freed - * at exynos_g2d_exec_ioctl once complete because wait_for_completion - * wasn't called there so free it here. - */ - if (g2d->runqueue_node->async) - g2d_free_runqueue_node(g2d, g2d->runqueue_node); - - if (g2d->suspended) - g2d->runqueue_node = NULL; - else - g2d_exec_runqueue(g2d); - mutex_unlock(&g2d->runqueue_mutex); -} - -static void g2d_finish_event(struct g2d_data *g2d, u32 cmdlist_no) -{ - struct drm_device *drm_dev = g2d->subdrv.drm_dev; - struct g2d_runqueue_node *runqueue_node = g2d->runqueue_node; - struct drm_exynos_pending_g2d_event *e; - struct timeval now; - unsigned long flags; - - if (list_empty(&runqueue_node->event_list)) - return; - - e = list_first_entry(&runqueue_node->event_list, - struct drm_exynos_pending_g2d_event, base.link); - - do_gettimeofday(&now); - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; - e->event.cmdlist_no = cmdlist_no; - - spin_lock_irqsave(&drm_dev->event_lock, flags); - list_move_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); - spin_unlock_irqrestore(&drm_dev->event_lock, flags); -} - -static irqreturn_t g2d_irq_handler(int irq, void *dev_id) -{ - struct g2d_data *g2d = dev_id; - u32 pending; - - pending = readl_relaxed(g2d->regs + G2D_INTC_PEND); - if (pending) - writel_relaxed(pending, g2d->regs + G2D_INTC_PEND); - - if (pending & G2D_INTP_GCMD_FIN) { - u32 value, list_done_count; - - value = readl_relaxed(g2d->regs + G2D_DMA_STATUS); - - list_done_count = (value & G2D_DMA_LIST_DONE_COUNT) >> - G2D_DMA_LIST_DONE_COUNT_OFFSET; - - g2d_finish_event(g2d, list_done_count); - - writel_relaxed(0, g2d->regs + G2D_DMA_HOLD_CMD); - if (!(pending & G2D_INTP_ACMD_FIN)) { - writel_relaxed(G2D_DMA_CONTINUE, - g2d->regs + G2D_DMA_COMMAND); - } - } - - if (pending & G2D_INTP_ACMD_FIN) - queue_work(g2d->g2d_workq, &g2d->runqueue_work); - - writel_relaxed(pending, g2d->regs + G2D_INTC_PEND); - - return IRQ_HANDLED; -} - -static int g2d_check_reg_offset(struct device *dev, struct g2d_cmdlist *cmdlist, - int nr, bool for_addr) -{ - int reg_offset; - int index; - int i; - - for (i = 0; i < nr; i++) { - index = cmdlist->last - 2 * (i + 1); - reg_offset = cmdlist->data[index] & ~0xfffff000; - - if (reg_offset < G2D_VALID_START || reg_offset > G2D_VALID_END) - goto err; - if (reg_offset % 4) - goto err; - - switch (reg_offset) { - case G2D_SRC_BASE_ADDR: - case G2D_SRC_PLANE2_BASE_ADDR: - case G2D_DST_BASE_ADDR: - case G2D_DST_PLANE2_BASE_ADDR: - case G2D_PAT_BASE_ADDR: - case G2D_MSK_BASE_ADDR: - if (!for_addr) - goto err; - break; - default: - if (for_addr) - goto err; - break; - } - } - - return 0; - -err: - dev_err(dev, "Bad register offset: 0x%x\n", cmdlist->data[index]); - return -EINVAL; -} - -/* ioctl functions */ -int exynos_g2d_get_ver_ioctl(struct drm_device *drm_dev, void *data, - struct drm_file *file) -{ - struct drm_exynos_g2d_get_ver *ver = data; - - ver->major = G2D_HW_MAJOR_VER; - ver->minor = G2D_HW_MINOR_VER; - - return 0; -} -EXPORT_SYMBOL_GPL(exynos_g2d_get_ver_ioctl); - -int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, - struct drm_file *file) -{ - struct drm_exynos_file_private *file_priv = file->driver_priv; - struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv; - struct device *dev = g2d_priv->dev; - struct g2d_data *g2d; - struct drm_exynos_g2d_set_cmdlist *req = data; - struct drm_exynos_pending_g2d_event *e; - struct g2d_cmdlist_node *node; - struct g2d_cmdlist *cmdlist; - unsigned long flags; - int size; - int ret; - - if (!dev) - return -ENODEV; - - g2d = dev_get_drvdata(dev); - if (!g2d) - return -EFAULT; - - node = g2d_get_cmdlist(g2d); - if (!node) - return -ENOMEM; - - node->event = NULL; - - if (req->event_type != G2D_EVENT_NOT) { - spin_lock_irqsave(&drm_dev->event_lock, flags); - if (file->event_space < sizeof(e->event)) { - spin_unlock_irqrestore(&drm_dev->event_lock, flags); - ret = -ENOMEM; - goto err; - } - file->event_space -= sizeof(e->event); - spin_unlock_irqrestore(&drm_dev->event_lock, flags); - - e = kzalloc(sizeof(*node->event), GFP_KERNEL); - if (!e) { - dev_err(dev, "failed to allocate event\n"); - - spin_lock_irqsave(&drm_dev->event_lock, flags); - file->event_space += sizeof(e->event); - spin_unlock_irqrestore(&drm_dev->event_lock, flags); - - ret = -ENOMEM; - goto err; - } - - e->event.base.type = DRM_EXYNOS_G2D_EVENT; - e->event.base.length = sizeof(e->event); - e->event.user_data = req->user_data; - e->base.event = &e->event.base; - e->base.file_priv = file; - e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; - - node->event = e; - } - - cmdlist = node->cmdlist; - - cmdlist->last = 0; - - /* - * If don't clear SFR registers, the cmdlist is affected by register - * values of previous cmdlist. G2D hw executes SFR clear command and - * a next command at the same time then the next command is ignored and - * is executed rightly from next next command, so needs a dummy command - * to next command of SFR clear command. - */ - cmdlist->data[cmdlist->last++] = G2D_SOFT_RESET; - cmdlist->data[cmdlist->last++] = G2D_SFRCLEAR; - cmdlist->data[cmdlist->last++] = G2D_SRC_BASE_ADDR; - cmdlist->data[cmdlist->last++] = 0; - - if (node->event) { - cmdlist->data[cmdlist->last++] = G2D_DMA_HOLD_CMD; - cmdlist->data[cmdlist->last++] = G2D_LIST_HOLD; - } - - /* Check size of cmdlist: last 2 is about G2D_BITBLT_START */ - size = cmdlist->last + req->cmd_nr * 2 + req->cmd_gem_nr * 2 + 2; - if (size > G2D_CMDLIST_DATA_NUM) { - dev_err(dev, "cmdlist size is too big\n"); - ret = -EINVAL; - goto err_free_event; - } - - if (copy_from_user(cmdlist->data + cmdlist->last, - (void __user *)req->cmd, - sizeof(*req->cmd) * req->cmd_nr)) { - ret = -EFAULT; - goto err_free_event; - } - cmdlist->last += req->cmd_nr * 2; - - ret = g2d_check_reg_offset(dev, cmdlist, req->cmd_nr, false); - if (ret < 0) - goto err_free_event; - - node->map_nr = req->cmd_gem_nr; - if (req->cmd_gem_nr) { - struct drm_exynos_g2d_cmd *cmd_gem = req->cmd_gem; - - if (copy_from_user(cmdlist->data + cmdlist->last, - (void __user *)cmd_gem, - sizeof(*cmd_gem) * req->cmd_gem_nr)) { - ret = -EFAULT; - goto err_free_event; - } - cmdlist->last += req->cmd_gem_nr * 2; - - ret = g2d_check_reg_offset(dev, cmdlist, req->cmd_gem_nr, true); - if (ret < 0) - goto err_free_event; - - ret = g2d_map_cmdlist_gem(g2d, node, drm_dev, file); - if (ret < 0) - goto err_unmap; - } - - cmdlist->data[cmdlist->last++] = G2D_BITBLT_START; - cmdlist->data[cmdlist->last++] = G2D_START_BITBLT; - - /* head */ - cmdlist->head = cmdlist->last / 2; - - /* tail */ - cmdlist->data[cmdlist->last] = 0; - - g2d_add_cmdlist_to_inuse(g2d_priv, node); - - return 0; - -err_unmap: - g2d_unmap_cmdlist_gem(g2d, node); -err_free_event: - if (node->event) { - spin_lock_irqsave(&drm_dev->event_lock, flags); - file->event_space += sizeof(e->event); - spin_unlock_irqrestore(&drm_dev->event_lock, flags); - kfree(node->event); - } -err: - g2d_put_cmdlist(g2d, node); - return ret; -} -EXPORT_SYMBOL_GPL(exynos_g2d_set_cmdlist_ioctl); - -int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data, - struct drm_file *file) -{ - struct drm_exynos_file_private *file_priv = file->driver_priv; - struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv; - struct device *dev = g2d_priv->dev; - struct g2d_data *g2d; - struct drm_exynos_g2d_exec *req = data; - struct g2d_runqueue_node *runqueue_node; - struct list_head *run_cmdlist; - struct list_head *event_list; - - if (!dev) - return -ENODEV; - - g2d = dev_get_drvdata(dev); - if (!g2d) - return -EFAULT; - - runqueue_node = kmem_cache_alloc(g2d->runqueue_slab, GFP_KERNEL); - if (!runqueue_node) { - dev_err(dev, "failed to allocate memory\n"); - return -ENOMEM; - } - run_cmdlist = &runqueue_node->run_cmdlist; - event_list = &runqueue_node->event_list; - INIT_LIST_HEAD(run_cmdlist); - INIT_LIST_HEAD(event_list); - init_completion(&runqueue_node->complete); - runqueue_node->async = req->async; - - list_splice_init(&g2d_priv->inuse_cmdlist, run_cmdlist); - list_splice_init(&g2d_priv->event_list, event_list); - - if (list_empty(run_cmdlist)) { - dev_err(dev, "there is no inuse cmdlist\n"); - kmem_cache_free(g2d->runqueue_slab, runqueue_node); - return -EPERM; - } - - mutex_lock(&g2d->runqueue_mutex); - list_add_tail(&runqueue_node->list, &g2d->runqueue); - if (!g2d->runqueue_node) - g2d_exec_runqueue(g2d); - mutex_unlock(&g2d->runqueue_mutex); - - if (runqueue_node->async) - goto out; - - wait_for_completion(&runqueue_node->complete); - g2d_free_runqueue_node(g2d, runqueue_node); - -out: - return 0; -} -EXPORT_SYMBOL_GPL(exynos_g2d_exec_ioctl); - -static int g2d_subdrv_probe(struct drm_device *drm_dev, struct device *dev) -{ - struct exynos_drm_private *drm_priv; - struct g2d_data *g2d; - int ret; - - drm_priv = drm_dev->dev_private; - - g2d = dev_get_drvdata(dev); - if (!g2d) - return -EFAULT; - - /* allocate dma-aware cmdlist buffer and map it with iommu table. */ - ret = g2d_init_cmdlist(g2d, drm_priv); - if (ret < 0) - return ret; - - /* enable iommu to g2d hardware */ - ret = exynos_drm_iommu_activate(drm_priv->vmm, dev); - if (ret < 0) { - dev_err(dev, "failed to activate iommu\n"); - goto err_fini_cmdlist; - } - - return ret; - -err_fini_cmdlist: - g2d_fini_cmdlist(g2d); - return ret; -} - -static void g2d_subdrv_remove(struct drm_device *drm_dev, struct device *dev) -{ - struct exynos_drm_private *drm_priv; - - drm_priv = drm_dev->dev_private; - - if (drm_priv->vmm) - exynos_drm_iommu_deactivate(drm_priv->vmm, dev); -} - -static int g2d_subdrv_open(struct drm_device *drm_dev, struct device *dev, - struct drm_file *file) -{ - struct drm_exynos_file_private *file_priv = file->driver_priv; - struct exynos_drm_g2d_private *g2d_priv; - struct g2d_data *g2d; - - g2d = dev_get_drvdata(dev); - if (!g2d) - return -EFAULT; - - g2d_priv = kzalloc(sizeof(*g2d_priv), GFP_KERNEL); - if (!g2d_priv) { - dev_err(dev, "failed to allocate g2d private data\n"); - return -ENOMEM; - } - - g2d_priv->dev = dev; - file_priv->g2d_priv = g2d_priv; - - INIT_LIST_HEAD(&g2d_priv->inuse_cmdlist); - INIT_LIST_HEAD(&g2d_priv->event_list); - - return 0; -} - -static void g2d_subdrv_close(struct drm_device *drm_dev, struct device *dev, - struct drm_file *file) -{ - struct drm_exynos_file_private *file_priv = file->driver_priv; - struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv; - struct g2d_data *g2d; - struct g2d_cmdlist_node *node, *n; - - if (!dev) - return; - - g2d = dev_get_drvdata(dev); - if (!g2d) - return; - - mutex_lock(&g2d->cmdlist_mutex); - list_for_each_entry_safe(node, n, &g2d_priv->inuse_cmdlist, list) { - /* - * unmap all gem objects not completed. - * - * P.S. if current process was terminated forcely then - * there may be some commands in inuse_cmdlist so unmap - * them. - */ - g2d_unmap_cmdlist_gem(g2d, node); - list_move_tail(&node->list, &g2d->free_cmdlist); - } - mutex_unlock(&g2d->cmdlist_mutex); - - kfree(file_priv->g2d_priv); -} - -static int __devinit g2d_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct resource *res; - struct g2d_data *g2d; - struct exynos_drm_subdrv *subdrv; - int ret; - - g2d = kzalloc(sizeof(*g2d), GFP_KERNEL); - if (!g2d) { - dev_err(dev, "failed to allocate driver data\n"); - return -ENOMEM; - } - - g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab", - sizeof(struct g2d_runqueue_node), 0, 0, NULL); - if (!g2d->runqueue_slab) { - ret = -ENOMEM; - goto err_free_mem; - } - - g2d->dev = dev; - - g2d->g2d_workq = create_singlethread_workqueue("g2d"); - if (!g2d->g2d_workq) { - dev_err(dev, "failed to create workqueue\n"); - ret = -EINVAL; - goto err_destroy_slab; - } - - INIT_WORK(&g2d->runqueue_work, g2d_runqueue_worker); - INIT_LIST_HEAD(&g2d->free_cmdlist); - INIT_LIST_HEAD(&g2d->runqueue); - - mutex_init(&g2d->cmdlist_mutex); - mutex_init(&g2d->runqueue_mutex); - - g2d->gate_clk = clk_get(dev, "fimg2d"); - if (IS_ERR(g2d->gate_clk)) { - dev_err(dev, "failed to get gate clock\n"); - ret = PTR_ERR(g2d->gate_clk); - goto err_destory_workqueue; - } - - pm_runtime_enable(dev); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "failed to get I/O memory\n"); - ret = -ENOENT; - goto err_put_clk; - } - - g2d->regs_res = request_mem_region(res->start, resource_size(res), - dev_name(dev)); - if (!g2d->regs_res) { - dev_err(dev, "failed to request I/O memory\n"); - ret = -ENOENT; - goto err_put_clk; - } - - g2d->regs = ioremap(res->start, resource_size(res)); - if (!g2d->regs) { - dev_err(dev, "failed to remap I/O memory\n"); - ret = -ENXIO; - goto err_release_res; - } - - g2d->irq = platform_get_irq(pdev, 0); - if (g2d->irq < 0) { - dev_err(dev, "failed to get irq\n"); - ret = g2d->irq; - goto err_unmap_base; - } - - ret = request_irq(g2d->irq, g2d_irq_handler, 0, "drm_g2d", g2d); - if (ret < 0) { - dev_err(dev, "irq request failed\n"); - goto err_unmap_base; - } - - platform_set_drvdata(pdev, g2d); - - subdrv = &g2d->subdrv; - subdrv->dev = dev; - subdrv->probe = g2d_subdrv_probe; - subdrv->remove = g2d_subdrv_remove; - subdrv->open = g2d_subdrv_open; - subdrv->close = g2d_subdrv_close; - - ret = exynos_drm_subdrv_register(subdrv); - if (ret < 0) { - dev_err(dev, "failed to register drm g2d device\n"); - goto err_free_irq; - } - - pm_qos_add_request(&g2d->pm_qos, PM_QOS_BUS_DMA_THROUGHPUT, 0); - - dev_info(dev, "The exynos g2d(ver %d.%d) successfully probed\n", - G2D_HW_MAJOR_VER, G2D_HW_MINOR_VER); - - return 0; - -err_free_irq: - free_irq(g2d->irq, g2d); -err_unmap_base: - iounmap(g2d->regs); -err_release_res: - release_resource(g2d->regs_res); - kfree(g2d->regs_res); -err_put_clk: - pm_runtime_disable(dev); - clk_put(g2d->gate_clk); -err_destory_workqueue: - destroy_workqueue(g2d->g2d_workq); -err_destroy_slab: - kmem_cache_destroy(g2d->runqueue_slab); -err_free_mem: - kfree(g2d); - return ret; -} - -static int __devexit g2d_remove(struct platform_device *pdev) -{ - struct g2d_data *g2d = platform_get_drvdata(pdev); - - cancel_work_sync(&g2d->runqueue_work); - pm_qos_remove_request(&g2d->pm_qos); - exynos_drm_subdrv_unregister(&g2d->subdrv); - free_irq(g2d->irq, g2d); - - while (g2d->runqueue_node) { - g2d_free_runqueue_node(g2d, g2d->runqueue_node); - g2d->runqueue_node = g2d_get_runqueue_node(g2d); - } - - iounmap(g2d->regs); - release_resource(g2d->regs_res); - kfree(g2d->regs_res); - - pm_runtime_disable(&pdev->dev); - clk_put(g2d->gate_clk); - - g2d_fini_cmdlist(g2d); - destroy_workqueue(g2d->g2d_workq); - kmem_cache_destroy(g2d->runqueue_slab); - kfree(g2d); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int g2d_suspend(struct device *dev) -{ - struct g2d_data *g2d = dev_get_drvdata(dev); - struct drm_device *drm_dev = g2d->subdrv.drm_dev; - struct exynos_drm_private *drm_priv = drm_dev->dev_private; - - mutex_lock(&g2d->runqueue_mutex); - g2d->suspended = true; - mutex_unlock(&g2d->runqueue_mutex); - - while (g2d->runqueue_node) - /* FIXME: good range? */ - usleep_range(500, 1000); - - flush_work_sync(&g2d->runqueue_work); - - /* disable iommu to g2d device. */ - exynos_drm_iommu_deactivate(drm_priv->vmm, dev); - - return 0; -} - -static int g2d_resume(struct device *dev) -{ - struct g2d_data *g2d = dev_get_drvdata(dev); - struct drm_device *drm_dev = g2d->subdrv.drm_dev; - struct exynos_drm_private *drm_priv = drm_dev->dev_private; - int ret; - - /* enable iommu to g2d hardware */ - ret = exynos_drm_iommu_activate(drm_priv->vmm, dev); - if (ret < 0) { - dev_err(dev, "failed to activate iommu\n"); - return ret; - } - - g2d->suspended = false; - g2d_exec_runqueue(g2d); - - return 0; -} -#endif - -SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume); - -struct platform_driver g2d_driver = { - .probe = g2d_probe, - .remove = __devexit_p(g2d_remove), - .driver = { - /* FIXME */ - .name = "s5p-fimg2d", - .owner = THIS_MODULE, - .pm = &g2d_pm_ops, - }, -}; diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.h b/drivers/gpu/drm/exynos/exynos_drm_g2d.h deleted file mode 100644 index 1a9c7ca..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Authors: Joonyoung Shim - * - * 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 Foundationr - */ - -#ifdef CONFIG_DRM_EXYNOS_G2D -extern int exynos_g2d_get_ver_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int exynos_g2d_set_cmdlist_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int exynos_g2d_exec_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -#else -static inline int exynos_g2d_get_ver_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - return -ENODEV; -} - -static inline int exynos_g2d_set_cmdlist_ioctl(struct drm_device *dev, - void *data, - struct drm_file *file_priv) -{ - return -ENODEV; -} - -static inline int exynos_g2d_exec_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - return -ENODEV; -} -#endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c deleted file mode 100644 index 7d12f6c..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ /dev/null @@ -1,1698 +0,0 @@ -/* exynos_drm_gem.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Author: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm.h" - -#include -#include -#include - -#include "exynos_drm_drv.h" -#include "exynos_drm_gem.h" -#include "exynos_drm_buf.h" -#include "exynos_drm_iommu.h" - -#define USERPTR_MAX_SIZE SZ_64M - -static struct exynos_drm_private_cb *private_cb; - -void exynos_drm_priv_cb_register(struct exynos_drm_private_cb *cb) -{ - if (cb) - private_cb = cb; -} - -int register_buf_to_priv_mgr(struct exynos_drm_gem_obj *obj, - unsigned int *priv_handle, unsigned int *priv_id) -{ - if (private_cb && private_cb->add_buffer) - return private_cb->add_buffer(obj, priv_handle, priv_id); - - return 0; -} - -static unsigned int convert_to_vm_err_msg(int msg) -{ - unsigned int out_msg; - - switch (msg) { - case 0: - case -ERESTARTSYS: - case -EINTR: - out_msg = VM_FAULT_NOPAGE; - break; - - case -ENOMEM: - out_msg = VM_FAULT_OOM; - break; - - default: - out_msg = VM_FAULT_SIGBUS; - break; - } - - return out_msg; -} - -static int check_gem_flags(unsigned int flags) -{ - if (flags & ~(EXYNOS_BO_MASK)) { - DRM_ERROR("invalid flags.\n"); - return -EINVAL; - } - - return 0; -} - -static int check_cache_flags(unsigned int flags) -{ - if (flags & ~(EXYNOS_DRM_CACHE_SEL_MASK | EXYNOS_DRM_CACHE_OP_MASK)) { - DRM_ERROR("invalid flags.\n"); - return -EINVAL; - } - - return 0; -} - -static struct vm_area_struct *get_vma(struct vm_area_struct *vma) -{ - struct vm_area_struct *vma_copy; - - vma_copy = kmalloc(sizeof(*vma_copy), GFP_KERNEL); - if (!vma_copy) - return NULL; - - if (vma->vm_ops && vma->vm_ops->open) - vma->vm_ops->open(vma); - - if (vma->vm_file) - get_file(vma->vm_file); - - memcpy(vma_copy, vma, sizeof(*vma)); - - vma_copy->vm_mm = NULL; - vma_copy->vm_next = NULL; - vma_copy->vm_prev = NULL; - - return vma_copy; -} - -static void put_vma(struct vm_area_struct *vma) -{ - if (!vma) - return; - - if (vma->vm_ops && vma->vm_ops->close) - vma->vm_ops->close(vma); - - if (vma->vm_file) - fput(vma->vm_file); - - kfree(vma); -} - -/* - * lock_userptr_vma - lock VMAs within user address space - * - * this function locks vma within user address space to avoid pages - * to the userspace from being swapped out. - * if this vma isn't locked, the pages to the userspace could be swapped out - * so unprivileged user might access different pages and dma of any device - * could access physical memory region not intended once swap-in. - */ -static int lock_userptr_vma(struct exynos_drm_gem_buf *buf, unsigned int lock) -{ - struct vm_area_struct *vma; - unsigned long start, end; - - start = buf->userptr; - end = buf->userptr + buf->size - 1; - - down_write(¤t->mm->mmap_sem); - - do { - vma = find_vma(current->mm, start); - if (!vma) { - up_write(¤t->mm->mmap_sem); - return -EFAULT; - } - - if (lock) - vma->vm_flags |= VM_LOCKED; - else - vma->vm_flags &= ~VM_LOCKED; - - start = vma->vm_end + 1; - } while (vma->vm_end < end); - - up_write(¤t->mm->mmap_sem); - - return 0; -} - -static void update_vm_cache_attr(struct exynos_drm_gem_obj *obj, - struct vm_area_struct *vma) -{ - DRM_DEBUG_KMS("flags = 0x%x\n", obj->flags); - - /* non-cachable as default. */ - if (obj->flags & EXYNOS_BO_CACHABLE) - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); - else if (obj->flags & EXYNOS_BO_WC) - vma->vm_page_prot = - pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); - else - vma->vm_page_prot = - pgprot_noncached(vm_get_page_prot(vma->vm_flags)); -} - -static unsigned long roundup_gem_size(unsigned long size, unsigned int flags) -{ - if (!IS_NONCONTIG_BUFFER(flags)) { - if (size >= SZ_1M) - return roundup(size, SECTION_SIZE); - else if (size >= SZ_64K) - return roundup(size, SZ_64K); - else - goto out; - } -out: - return roundup(size, PAGE_SIZE); -} - -struct page **exynos_gem_get_pages(struct drm_gem_object *obj, - gfp_t gfpmask) -{ - struct page *p, **pages; - int i, npages; - - npages = obj->size >> PAGE_SHIFT; - - pages = drm_malloc_ab(npages, sizeof(struct page *)); - if (pages == NULL) - return ERR_PTR(-ENOMEM); - - for (i = 0; i < npages; i++) { - p = alloc_page(gfpmask); - if (IS_ERR(p)) - goto fail; - pages[i] = p; - } - - return pages; - -fail: - while (--i) - __free_page(pages[i]); - - drm_free_large(pages); - return ERR_PTR(PTR_ERR(p)); -} - -static void exynos_gem_put_pages(struct drm_gem_object *obj, - struct page **pages) -{ - int npages; - - npages = obj->size >> PAGE_SHIFT; - - while (--npages >= 0) - __free_page(pages[npages]); - - drm_free_large(pages); -} - -static int exynos_drm_gem_map_pages(struct drm_gem_object *obj, - struct vm_area_struct *vma, - unsigned long f_vaddr, - pgoff_t page_offset) -{ - struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); - struct exynos_drm_gem_buf *buf = exynos_gem_obj->buffer; - unsigned long pfn; - - if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) { - if (!buf->pages) - return -EINTR; - - pfn = page_to_pfn(buf->pages[page_offset++]); - } else - pfn = (buf->paddr >> PAGE_SHIFT) + page_offset; - - return vm_insert_mixed(vma, f_vaddr, pfn); -} - -static int exynos_drm_gem_get_pages(struct drm_gem_object *obj) -{ - struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); - struct exynos_drm_gem_buf *buf = exynos_gem_obj->buffer; - struct scatterlist *sgl; - struct page **pages; - unsigned int npages, i = 0; - int ret; - - if (buf->pages) { - DRM_DEBUG_KMS("already allocated.\n"); - return -EINVAL; - } - - pages = exynos_gem_get_pages(obj, GFP_HIGHUSER_MOVABLE); - if (IS_ERR(pages)) { - DRM_ERROR("failed to get pages.\n"); - return PTR_ERR(pages); - } - - npages = obj->size >> PAGE_SHIFT; - buf->page_size = PAGE_SIZE; - - buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); - if (!buf->sgt) { - DRM_ERROR("failed to allocate sg table.\n"); - ret = -ENOMEM; - goto err; - } - - ret = sg_alloc_table(buf->sgt, npages, GFP_KERNEL); - if (ret < 0) { - DRM_ERROR("failed to initialize sg table.\n"); - ret = -EFAULT; - goto err1; - } - - sgl = buf->sgt->sgl; - - /* set all pages to sg list. */ - while (i < npages) { - sg_set_page(sgl, pages[i], PAGE_SIZE, 0); - sg_dma_address(sgl) = page_to_phys(pages[i]); - i++; - sgl = sg_next(sgl); - } - - buf->pages = pages; - return ret; -err1: - kfree(buf->sgt); - buf->sgt = NULL; -err: - exynos_gem_put_pages(obj, pages); - return ret; - -} - -static void exynos_drm_gem_put_pages(struct drm_gem_object *obj) -{ - struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); - struct exynos_drm_gem_buf *buf = exynos_gem_obj->buffer; - - /* - * if buffer typs is EXYNOS_BO_NONCONTIG then release all pages - * allocated at gem fault handler. - */ - sg_free_table(buf->sgt); - kfree(buf->sgt); - buf->sgt = NULL; - - exynos_gem_put_pages(obj, buf->pages); - buf->pages = NULL; - - /* add some codes for UNCACHED type here. TODO */ -} - -static void exynos_drm_put_userptr(struct drm_gem_object *obj) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct exynos_drm_gem_buf *buf; - struct vm_area_struct *vma; - int npages; - - exynos_gem_obj = to_exynos_gem_obj(obj); - buf = exynos_gem_obj->buffer; - vma = exynos_gem_obj->vma; - - if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) { - put_vma(exynos_gem_obj->vma); - goto out; - } - - npages = buf->size >> PAGE_SHIFT; - - if (exynos_gem_obj->flags & EXYNOS_BO_USERPTR && !buf->pfnmap) - lock_userptr_vma(buf, 0); - - npages--; - while (npages >= 0) { - if (buf->write) - set_page_dirty_lock(buf->pages[npages]); - - put_page(buf->pages[npages]); - npages--; - } - -out: - kfree(buf->pages); - buf->pages = NULL; - - kfree(buf->sgt); - buf->sgt = NULL; -} - -static int exynos_drm_gem_handle_create(struct drm_gem_object *obj, - struct drm_file *file_priv, - unsigned int *handle) -{ - int ret; - - /* - * allocate a id of idr table where the obj is registered - * and handle has the id what user can see. - */ - ret = drm_gem_handle_create(file_priv, obj, handle); - if (ret) - return ret; - - DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle); - - /* drop reference from allocate - handle holds it now. */ - drm_gem_object_unreference_unlocked(obj); - - return 0; -} - -void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj) -{ - struct drm_gem_object *obj; - struct exynos_drm_gem_buf *buf; - struct exynos_drm_private *private; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - obj = &exynos_gem_obj->base; - private = obj->dev->dev_private; - buf = exynos_gem_obj->buffer; - - DRM_DEBUG_KMS("handle count = %d\n", atomic_read(&obj->handle_count)); - - /* - * release a private buffer from its table. - * - * this callback will release a ump object only if user requested - * ump export otherwise just return. - */ - if (private_cb->release_buffer) - private_cb->release_buffer(exynos_gem_obj->priv_handle); - - if (!buf->pages) - return; - - /* - * do not release memory region from exporter. - * - * the region will be released by exporter - * once dmabuf's refcount becomes 0. - */ - if (obj->import_attach) - goto out; - - if (private->vmm) - exynos_drm_iommu_unmap_gem(obj); - - if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) - exynos_drm_gem_put_pages(obj); - else if (exynos_gem_obj->flags & EXYNOS_BO_USERPTR) - exynos_drm_put_userptr(obj); - else - exynos_drm_free_buf(obj->dev, exynos_gem_obj->flags, buf); - -out: - exynos_drm_fini_buf(obj->dev, buf); - exynos_gem_obj->buffer = NULL; - - if (obj->map_list.map) - drm_gem_free_mmap_offset(obj); - - /* release file pointer to gem object. */ - drm_gem_object_release(obj); - - kfree(exynos_gem_obj); - exynos_gem_obj = NULL; -} - -struct exynos_drm_gem_obj *exynos_drm_gem_get_obj(struct drm_device *dev, - unsigned int gem_handle, - struct drm_file *file_priv) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct drm_gem_object *obj; - - obj = drm_gem_object_lookup(dev, file_priv, gem_handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - return ERR_PTR(-EINVAL); - } - - exynos_gem_obj = to_exynos_gem_obj(obj); - - drm_gem_object_unreference_unlocked(obj); - - return exynos_gem_obj; -} - -unsigned long exynos_drm_gem_get_size(struct drm_device *dev, - unsigned int gem_handle, - struct drm_file *file_priv) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct drm_gem_object *obj; - - obj = drm_gem_object_lookup(dev, file_priv, gem_handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - return 0; - } - - exynos_gem_obj = to_exynos_gem_obj(obj); - - drm_gem_object_unreference_unlocked(obj); - - return exynos_gem_obj->buffer->size; -} - - -struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev, - unsigned long size) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct drm_gem_object *obj; - int ret; - - exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL); - if (!exynos_gem_obj) { - DRM_ERROR("failed to allocate exynos gem object\n"); - return NULL; - } - - exynos_gem_obj->size = size; - obj = &exynos_gem_obj->base; - - ret = drm_gem_object_init(dev, obj, size); - if (ret < 0) { - DRM_ERROR("failed to initialize gem object\n"); - kfree(exynos_gem_obj); - return NULL; - } - - DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp); - - return exynos_gem_obj; -} - -struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, - unsigned int flags, - unsigned long size) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct exynos_drm_private *private = dev->dev_private; - struct exynos_drm_gem_buf *buf; - unsigned long packed_size = size; - int ret; - - if (!size) { - DRM_ERROR("invalid size.\n"); - return ERR_PTR(-EINVAL); - } - - size = roundup_gem_size(size, flags); - DRM_DEBUG_KMS("%s\n", __FILE__); - - ret = check_gem_flags(flags); - if (ret) - return ERR_PTR(ret); - - buf = exynos_drm_init_buf(dev, size); - if (!buf) - return ERR_PTR(-ENOMEM); - - exynos_gem_obj = exynos_drm_gem_init(dev, size); - if (!exynos_gem_obj) { - ret = -ENOMEM; - goto err_fini_buf; - } - - exynos_gem_obj->packed_size = packed_size; - exynos_gem_obj->buffer = buf; - - /* set memory type and cache attribute from user side. */ - exynos_gem_obj->flags = flags; - - /* - * allocate all pages as desired size if user wants to allocate - * physically non-continuous memory. - */ - if (flags & EXYNOS_BO_NONCONTIG) { - ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base); - if (ret < 0) { - drm_gem_object_release(&exynos_gem_obj->base); - goto err_fini_buf; - } - } else { - ret = exynos_drm_alloc_buf(dev, buf, flags); - if (ret < 0) { - drm_gem_object_release(&exynos_gem_obj->base); - goto err_fini_buf; - } - } - - if (private->vmm) { - exynos_gem_obj->vmm = private->vmm; - - buf->dev_addr = exynos_drm_iommu_map_gem(dev, - &exynos_gem_obj->base); - if (!buf->dev_addr) { - DRM_ERROR("failed to map gem with iommu table.\n"); - ret = -EFAULT; - - if (flags & EXYNOS_BO_NONCONTIG) - exynos_drm_gem_put_pages(&exynos_gem_obj->base); - else - exynos_drm_free_buf(dev, flags, buf); - - drm_gem_object_release(&exynos_gem_obj->base); - - goto err_fini_buf; - } - - buf->dma_addr = buf->dev_addr; - } else - buf->dma_addr = buf->paddr; - - DRM_DEBUG_KMS("dma_addr = 0x%x\n", buf->dma_addr); - - return exynos_gem_obj; - -err_fini_buf: - exynos_drm_fini_buf(dev, buf); - return ERR_PTR(ret); -} - -int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_exynos_gem_create *args = data; - struct exynos_drm_gem_obj *exynos_gem_obj; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size); - if (IS_ERR(exynos_gem_obj)) - return PTR_ERR(exynos_gem_obj); - - ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv, - &args->handle); - if (ret) { - exynos_drm_gem_destroy(exynos_gem_obj); - return ret; - } - - return ret; -} - -void *exynos_drm_gem_get_dma_addr(struct drm_device *dev, - unsigned int gem_handle, - struct drm_file *filp, - unsigned int *gem_obj) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct exynos_drm_gem_buf *buf; - struct drm_gem_object *obj; - - obj = drm_gem_object_lookup(dev, filp, gem_handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - return ERR_PTR(-EINVAL); - } - - exynos_gem_obj = to_exynos_gem_obj(obj); - buf = exynos_gem_obj->buffer; - - *gem_obj = (unsigned int)obj; - - return &buf->dma_addr; -} - -void exynos_drm_gem_put_dma_addr(struct drm_device *dev, void *gem_obj) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct drm_gem_object *obj; - - if (!gem_obj) - return; - - /* use gem handle instead of object. TODO */ - - obj = gem_obj; - - exynos_gem_obj = to_exynos_gem_obj(obj); - - /* - * unreference this gem object because this had already been - * referenced at exynos_drm_gem_get_dma_addr(). - */ - drm_gem_object_unreference_unlocked(obj); -} - -int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_exynos_gem_map_off *args = data; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - DRM_DEBUG_KMS("handle = 0x%x, offset = 0x%lx\n", - args->handle, (unsigned long)args->offset); - - if (!(dev->driver->driver_features & DRIVER_GEM)) { - DRM_ERROR("does not support GEM.\n"); - return -ENODEV; - } - - return exynos_drm_gem_dumb_map_offset(file_priv, dev, args->handle, - &args->offset); -} - -static int exynos_drm_gem_mmap_buffer(struct file *filp, - struct vm_area_struct *vma) -{ - struct drm_gem_object *obj = filp->private_data; - struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); - struct exynos_drm_gem_buf *buffer; - unsigned long pfn, vm_size, usize, uaddr = vma->vm_start; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - vma->vm_flags |= (VM_IO | VM_RESERVED); - - update_vm_cache_attr(exynos_gem_obj, vma); - - vma->vm_file = filp; - - vm_size = usize = vma->vm_end - vma->vm_start; - - /* - * a buffer contains information to physically continuous memory - * allocated by user request or at framebuffer creation. - */ - buffer = exynos_gem_obj->buffer; - - /* check if user-requested size is valid. */ - if (vm_size > buffer->size) - return -EINVAL; - - if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) { - int i = 0; - - if (!buffer->pages) - return -EINVAL; - - vma->vm_flags |= VM_MIXEDMAP; - - do { - ret = vm_insert_page(vma, uaddr, buffer->pages[i++]); - if (ret) { - DRM_ERROR("failed to remap user space.\n"); - return ret; - } - - uaddr += PAGE_SIZE; - usize -= PAGE_SIZE; - } while (usize > 0); - } else { - /* - * get page frame number to physical memory to be mapped - * to user space. - */ - pfn = ((unsigned long)exynos_gem_obj->buffer->paddr) >> - PAGE_SHIFT; - - DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn); - - if (remap_pfn_range(vma, vma->vm_start, pfn, vm_size, - vma->vm_page_prot)) { - DRM_ERROR("failed to remap pfn range.\n"); - return -EAGAIN; - } - } - - return 0; -} - -static const struct file_operations exynos_drm_gem_fops = { - .mmap = exynos_drm_gem_mmap_buffer, -}; - -int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_exynos_gem_mmap *args = data; - struct drm_gem_object *obj; - unsigned int addr; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!(dev->driver->driver_features & DRIVER_GEM)) { - DRM_ERROR("does not support GEM.\n"); - return -ENODEV; - } - - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - return -EINVAL; - } - - obj->filp->f_op = &exynos_drm_gem_fops; - obj->filp->private_data = obj; - - down_write(¤t->mm->mmap_sem); - addr = do_mmap(obj->filp, 0, args->size, - PROT_READ | PROT_WRITE, MAP_SHARED, 0); - up_write(¤t->mm->mmap_sem); - - drm_gem_object_unreference_unlocked(obj); - - if (IS_ERR((void *)addr)) - return PTR_ERR((void *)addr); - - args->mapped = addr; - - DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped); - - return 0; -} - -static int exynos_drm_get_userptr(struct drm_device *dev, - struct exynos_drm_gem_obj *obj, - unsigned long userptr, - unsigned int write) -{ - unsigned int get_npages; - unsigned long npages = 0; - struct vm_area_struct *vma; - struct exynos_drm_gem_buf *buf = obj->buffer; - int ret; - - down_read(¤t->mm->mmap_sem); - vma = find_vma(current->mm, userptr); - - /* the memory region mmaped with VM_PFNMAP. */ - if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) { - unsigned long this_pfn, prev_pfn, pa; - unsigned long start, end, offset; - struct scatterlist *sgl; - int ret; - - start = userptr; - offset = userptr & ~PAGE_MASK; - end = start + buf->size; - sgl = buf->sgt->sgl; - - for (prev_pfn = 0; start < end; start += PAGE_SIZE) { - ret = follow_pfn(vma, start, &this_pfn); - if (ret) - goto err; - - if (prev_pfn == 0) { - pa = this_pfn << PAGE_SHIFT; - buf->paddr = pa + offset; - } else if (this_pfn != prev_pfn + 1) { - ret = -EINVAL; - goto err; - } - - sg_dma_address(sgl) = (pa + offset); - sg_dma_len(sgl) = PAGE_SIZE; - prev_pfn = this_pfn; - pa += PAGE_SIZE; - npages++; - sgl = sg_next(sgl); - } - - obj->vma = get_vma(vma); - if (!obj->vma) { - ret = -ENOMEM; - goto err; - } - - up_read(¤t->mm->mmap_sem); - buf->pfnmap = true; - - return npages; -err: - buf->paddr = 0; - up_read(¤t->mm->mmap_sem); - - return ret; - } - - up_read(¤t->mm->mmap_sem); - - /* - * lock the vma within userptr to avoid userspace buffer - * from being swapped out. - */ - ret = lock_userptr_vma(buf, 1); - if (ret < 0) { - DRM_ERROR("failed to lock vma for userptr.\n"); - lock_userptr_vma(buf, 0); - return 0; - } - - buf->write = write; - npages = buf->size >> PAGE_SHIFT; - - down_read(¤t->mm->mmap_sem); - get_npages = get_user_pages(current, current->mm, userptr, - npages, write, 1, buf->pages, NULL); - up_read(¤t->mm->mmap_sem); - if (get_npages != npages) - DRM_ERROR("failed to get user_pages.\n"); - - buf->userptr = userptr; - buf->pfnmap = false; - - return get_npages; -} - -int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct exynos_drm_private *priv = dev->dev_private; - struct exynos_drm_gem_obj *exynos_gem_obj; - struct drm_exynos_gem_userptr *args = data; - struct exynos_drm_gem_buf *buf; - struct scatterlist *sgl; - unsigned long size, userptr, packed_size; - unsigned int npages; - int ret, get_npages; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!args->size) { - DRM_ERROR("invalid size.\n"); - return -EINVAL; - } - - ret = check_gem_flags(args->flags); - if (ret) - return ret; - - packed_size = args->size; - - size = roundup_gem_size(args->size, EXYNOS_BO_USERPTR); - - if (size > priv->userptr_limit) { - DRM_ERROR("excessed maximum size of userptr.\n"); - return -EINVAL; - } - - userptr = args->userptr; - - buf = exynos_drm_init_buf(dev, size); - if (!buf) - return -ENOMEM; - - exynos_gem_obj = exynos_drm_gem_init(dev, size); - if (!exynos_gem_obj) { - ret = -ENOMEM; - goto err_free_buffer; - } - - exynos_gem_obj->packed_size = packed_size; - - buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); - if (!buf->sgt) { - DRM_ERROR("failed to allocate buf->sgt.\n"); - ret = -ENOMEM; - goto err_release_gem; - } - - npages = size >> PAGE_SHIFT; - - ret = sg_alloc_table(buf->sgt, npages, GFP_KERNEL); - if (ret < 0) { - DRM_ERROR("failed to initailize sg table.\n"); - goto err_free_sgt; - } - - buf->pages = kzalloc(npages * sizeof(struct page *), GFP_KERNEL); - if (!buf->pages) { - DRM_ERROR("failed to allocate buf->pages\n"); - ret = -ENOMEM; - goto err_free_table; - } - - exynos_gem_obj->buffer = buf; - - get_npages = exynos_drm_get_userptr(dev, exynos_gem_obj, userptr, 1); - if (get_npages != npages) { - DRM_ERROR("failed to get user_pages.\n"); - ret = get_npages; - goto err_release_userptr; - } - - ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv, - &args->handle); - if (ret < 0) { - DRM_ERROR("failed to create gem handle.\n"); - goto err_release_userptr; - } - - sgl = buf->sgt->sgl; - - /* - * if buf->pfnmap is true then update sgl of sgt with pages but - * if buf->pfnmap is false then it means the sgl was updated already - * so it doesn't need to update the sgl. - */ - if (!buf->pfnmap) { - unsigned int i = 0; - - /* set all pages to sg list. */ - while (i < npages) { - sg_set_page(sgl, buf->pages[i], PAGE_SIZE, 0); - sg_dma_address(sgl) = page_to_phys(buf->pages[i]); - i++; - sgl = sg_next(sgl); - } - } - - /* always use EXYNOS_BO_USERPTR as memory type for userptr. */ - exynos_gem_obj->flags |= EXYNOS_BO_USERPTR; - - if (priv->vmm) { - exynos_gem_obj->vmm = priv->vmm; - - buf->dev_addr = exynos_drm_iommu_map_gem(dev, - &exynos_gem_obj->base); - if (!buf->dev_addr) { - DRM_ERROR("failed to map gem with iommu table.\n"); - ret = -EFAULT; - - exynos_drm_free_buf(dev, exynos_gem_obj->flags, buf); - - drm_gem_object_release(&exynos_gem_obj->base); - - goto err_release_handle; - } - - buf->dma_addr = buf->dev_addr; - } else - buf->dma_addr = buf->paddr; - - return 0; - -err_release_handle: - drm_gem_handle_delete(file_priv, args->handle); -err_release_userptr: - get_npages--; - while (get_npages >= 0) - put_page(buf->pages[get_npages--]); - kfree(buf->pages); - buf->pages = NULL; -err_free_table: - sg_free_table(buf->sgt); -err_free_sgt: - kfree(buf->sgt); - buf->sgt = NULL; -err_release_gem: - drm_gem_object_release(&exynos_gem_obj->base); - kfree(exynos_gem_obj); - exynos_gem_obj = NULL; -err_free_buffer: - exynos_drm_free_buf(dev, 0, buf); - return ret; -} - -int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ struct exynos_drm_gem_obj *exynos_gem_obj; - struct drm_exynos_gem_info *args = data; - struct drm_gem_object *obj; - - mutex_lock(&dev->struct_mutex); - - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - mutex_unlock(&dev->struct_mutex); - return -EINVAL; - } - - exynos_gem_obj = to_exynos_gem_obj(obj); - - args->flags = exynos_gem_obj->flags; - args->size = exynos_gem_obj->size; - - drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); - - return 0; -} - -int exynos_drm_gem_user_limit_ioctl(struct drm_device *dev, void *data, - struct drm_file *filp) -{ - struct exynos_drm_private *priv = dev->dev_private; - struct drm_exynos_user_limit *limit = data; - - if (limit->userptr_limit < PAGE_SIZE || - limit->userptr_limit > USERPTR_MAX_SIZE) { - DRM_DEBUG_KMS("invalid userptr_limit size.\n"); - return -EINVAL; - } - - if (priv->userptr_limit == limit->userptr_limit) - return 0; - - priv->userptr_limit = limit->userptr_limit; - - return 0; -} - -int exynos_drm_gem_export_ump_ioctl(struct drm_device *dev, void *data, - struct drm_file *file) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct drm_gem_object *obj; - struct drm_exynos_gem_ump *ump = data; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - mutex_lock(&dev->struct_mutex); - - obj = drm_gem_object_lookup(dev, file, ump->gem_handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - mutex_unlock(&dev->struct_mutex); - return -EINVAL; - } - - exynos_gem_obj = to_exynos_gem_obj(obj); - - /* register gem buffer to private buffer. */ - ret = register_buf_to_priv_mgr(exynos_gem_obj, - (unsigned int *)&exynos_gem_obj->priv_handle, - (unsigned int *)&exynos_gem_obj->priv_id); - if (ret < 0) - goto err_unreference_gem; - - ump->secure_id = exynos_gem_obj->priv_id; - drm_gem_object_unreference(obj); - - mutex_unlock(&dev->struct_mutex); - - DRM_DEBUG_KMS("got secure id = %d\n", ump->secure_id); - - return 0; - -err_unreference_gem: - drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); - return ret; - -} - -static int exynos_gem_l1_cache_ops(struct drm_device *drm_dev, - struct drm_exynos_gem_cache_op *op) { - if (op->flags & EXYNOS_DRM_CACHE_FSH_ALL) { - /* - * cortex-A9 core has individual l1 cache so flush l1 caches - * for all cores but other cores should be considered later. - * TODO - */ - if (op->flags & EXYNOS_DRM_ALL_CORES) - flush_all_cpu_caches(); - else - __cpuc_flush_user_all(); - - } else if (op->flags & EXYNOS_DRM_CACHE_FSH_RANGE) { - struct vm_area_struct *vma; - - down_read(¤t->mm->mmap_sem); - vma = find_vma(current->mm, op->usr_addr); - up_read(¤t->mm->mmap_sem); - - if (!vma) { - DRM_ERROR("failed to get vma.\n"); - return -EFAULT; - } - - __cpuc_flush_user_range(op->usr_addr, op->usr_addr + op->size, - vma->vm_flags); - } - - return 0; -} - -static int exynos_gem_l2_cache_ops(struct drm_device *drm_dev, - struct drm_file *filp, - struct drm_exynos_gem_cache_op *op) -{ - if (op->flags & EXYNOS_DRM_CACHE_FSH_RANGE || - op->flags & EXYNOS_DRM_CACHE_INV_RANGE || - op->flags & EXYNOS_DRM_CACHE_CLN_RANGE) { - unsigned long virt_start = op->usr_addr, pfn; - phys_addr_t phy_start, phy_end; - struct vm_area_struct *vma; - int ret; - - down_read(¤t->mm->mmap_sem); - vma = find_vma(current->mm, op->usr_addr); - up_read(¤t->mm->mmap_sem); - - if (!vma) { - DRM_ERROR("failed to get vma.\n"); - return -EFAULT; - } - - /* - * Range operation to l2 cache(PIPT) - */ - if (vma && (vma->vm_flags & VM_PFNMAP)) { - ret = follow_pfn(vma, virt_start, &pfn); - if (ret < 0) { - DRM_ERROR("failed to get pfn.\n"); - return ret; - } - - /* - * the memory region with VM_PFNMAP is contiguous - * physically so do range operagion just one time. - */ - phy_start = pfn << PAGE_SHIFT; - phy_end = phy_start + op->size; - - if (op->flags & EXYNOS_DRM_CACHE_FSH_RANGE) - outer_flush_range(phy_start, phy_end); - else if (op->flags & EXYNOS_DRM_CACHE_INV_RANGE) - outer_inv_range(phy_start, phy_end); - else if (op->flags & EXYNOS_DRM_CACHE_CLN_RANGE) - outer_clean_range(phy_start, phy_end); - - return 0; - } else { - struct exynos_drm_gem_obj *exynos_obj; - struct exynos_drm_gem_buf *buf; - struct drm_gem_object *obj; - struct scatterlist *sgl; - unsigned int npages, i = 0; - - mutex_lock(&drm_dev->struct_mutex); - - obj = drm_gem_object_lookup(drm_dev, filp, - op->gem_handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - mutex_unlock(&drm_dev->struct_mutex); - return -EINVAL; - } - - exynos_obj = to_exynos_gem_obj(obj); - buf = exynos_obj->buffer; - npages = buf->size >> PAGE_SHIFT; - sgl = buf->sgt->sgl; - - drm_gem_object_unreference(obj); - mutex_unlock(&drm_dev->struct_mutex); - - /* - * in this case, the memory region is non-contiguous - * physically so do range operation to all the pages. - */ - while (i < npages) { - phy_start = sg_dma_address(sgl); - phy_end = phy_start + buf->page_size; - - if (op->flags & EXYNOS_DRM_CACHE_FSH_RANGE) - outer_flush_range(phy_start, phy_end); - else if (op->flags & EXYNOS_DRM_CACHE_INV_RANGE) - outer_inv_range(phy_start, phy_end); - else if (op->flags & EXYNOS_DRM_CACHE_CLN_RANGE) - outer_clean_range(phy_start, phy_end); - - i++; - sgl = sg_next(sgl); - } - - return 0; - } - } - - if (op->flags & EXYNOS_DRM_CACHE_FSH_ALL) - outer_flush_all(); - else if (op->flags & EXYNOS_DRM_CACHE_INV_ALL) - outer_inv_all(); - else if (op->flags & EXYNOS_DRM_CACHE_CLN_ALL) - outer_clean_all(); - else { - DRM_ERROR("invalid l2 cache operation.\n"); - return -EINVAL; - } - - - return 0; -} - -int exynos_drm_gem_cache_op_ioctl(struct drm_device *drm_dev, void *data, - struct drm_file *file_priv) -{ - struct drm_exynos_gem_cache_op *op = data; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - ret = check_cache_flags(op->flags); - if (ret) - return -EINVAL; - - /* - * do cache operation for all cache range if op->size is bigger - * than SZ_1M because cache range operation with bit size has - * big cost. - */ - if (op->size >= SZ_1M) { - if (op->flags & EXYNOS_DRM_CACHE_FSH_RANGE) { - if (op->flags & EXYNOS_DRM_L1_CACHE) - __cpuc_flush_user_all(); - - if (op->flags & EXYNOS_DRM_L2_CACHE) - outer_flush_all(); - - return 0; - } else if (op->flags & EXYNOS_DRM_CACHE_INV_RANGE) { - if (op->flags & EXYNOS_DRM_L2_CACHE) - outer_inv_all(); - - return 0; - } else if (op->flags & EXYNOS_DRM_CACHE_CLN_RANGE) { - if (op->flags & EXYNOS_DRM_L2_CACHE) - outer_clean_all(); - - return 0; - } - } - - if (op->flags & EXYNOS_DRM_L1_CACHE || - op->flags & EXYNOS_DRM_ALL_CACHES) { - ret = exynos_gem_l1_cache_ops(drm_dev, op); - if (ret < 0) - goto err; - } - - if (op->flags & EXYNOS_DRM_L2_CACHE || - op->flags & EXYNOS_DRM_ALL_CACHES) - ret = exynos_gem_l2_cache_ops(drm_dev, file_priv, op); -err: - return ret; -} - -/* temporary functions. */ -int exynos_drm_gem_get_phy_ioctl(struct drm_device *drm_dev, void *data, - struct drm_file *file_priv) -{ - struct drm_exynos_gem_get_phy *get_phy = data; - struct exynos_drm_gem_obj *exynos_gem_obj; - struct drm_gem_object *obj; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - mutex_lock(&drm_dev->struct_mutex); - - obj = drm_gem_object_lookup(drm_dev, file_priv, get_phy->gem_handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - mutex_unlock(&drm_dev->struct_mutex); - return -EINVAL; - } - - exynos_gem_obj = to_exynos_gem_obj(obj); - - /* - * we can get physical address only for EXYNOS_DRM_GEM_PC memory type. - */ - if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) { - DRM_DEBUG_KMS("not physically continuous memory type.\n"); - drm_gem_object_unreference(obj); - mutex_unlock(&drm_dev->struct_mutex); - return -EINVAL; - } - - get_phy->phy_addr = exynos_gem_obj->buffer->paddr; - get_phy->size = exynos_gem_obj->buffer->size; - - drm_gem_object_unreference(obj); - mutex_unlock(&drm_dev->struct_mutex); - - return 0; -} - -int exynos_drm_gem_phy_imp_ioctl(struct drm_device *drm_dev, void *data, - struct drm_file *file_priv) -{ - struct drm_exynos_gem_phy_imp *args = data; - struct exynos_drm_gem_obj *exynos_gem_obj; - struct exynos_drm_private *private = drm_dev->dev_private; - struct exynos_drm_gem_buf *buffer; - unsigned long size, packed_size; - unsigned int flags = EXYNOS_BO_CONTIG; - unsigned int npages, i = 0; - struct scatterlist *sgl; - dma_addr_t start_addr; - int ret = 0; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - packed_size = args->size; - size = roundup_gem_size(args->size, flags); - - exynos_gem_obj = exynos_drm_gem_init(drm_dev, size); - if (!exynos_gem_obj) - return -ENOMEM; - - buffer = exynos_drm_init_buf(drm_dev, size); - if (!buffer) { - DRM_DEBUG_KMS("failed to allocate buffer\n"); - ret = -ENOMEM; - goto err_release_gem_obj; - } - - exynos_gem_obj->packed_size = packed_size; - buffer->paddr = (dma_addr_t)args->phy_addr; - buffer->size = size; - - /* - * if shared is true, this bufer wouldn't be released. - * this buffer was allocated by other so don't release it. - */ - buffer->shared = true; - - exynos_gem_obj->buffer = buffer; - - ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv, - &args->gem_handle); - if (ret) - goto err_fini_buf; - - DRM_DEBUG_KMS("got gem handle = 0x%x\n", args->gem_handle); - - if (buffer->size >= SZ_1M) { - npages = buffer->size >> SECTION_SHIFT; - buffer->page_size = SECTION_SIZE; - } else if (buffer->size >= SZ_64K) { - npages = buffer->size >> 16; - buffer->page_size = SZ_64K; - } else { - npages = buffer->size >> PAGE_SHIFT; - buffer->page_size = PAGE_SIZE; - } - - buffer->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); - if (!buffer->sgt) { - DRM_ERROR("failed to allocate sg table.\n"); - ret = -ENOMEM; - goto err_release_handle; - } - - ret = sg_alloc_table(buffer->sgt, npages, GFP_KERNEL); - if (ret < 0) { - DRM_ERROR("failed to initialize sg table.\n"); - goto err_free_sgt; - } - - buffer->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL); - if (!buffer->pages) { - DRM_ERROR("failed to allocate pages.\n"); - ret = -ENOMEM; - goto err_sg_free_table; - } - - sgl = buffer->sgt->sgl; - start_addr = buffer->paddr; - - while (i < npages) { - buffer->pages[i] = phys_to_page(start_addr); - sg_set_page(sgl, buffer->pages[i], buffer->page_size, 0); - sg_dma_address(sgl) = start_addr; - start_addr += buffer->page_size; - sgl = sg_next(sgl); - i++; - } - - if (private->vmm) { - exynos_gem_obj->vmm = private->vmm; - - buffer->dev_addr = exynos_drm_iommu_map_gem(drm_dev, - &exynos_gem_obj->base); - if (!buffer->dev_addr) { - DRM_ERROR("failed to map gem with iommu table.\n"); - ret = -EFAULT; - - exynos_drm_free_buf(drm_dev, flags, buffer); - - drm_gem_object_release(&exynos_gem_obj->base); - - goto err_free_pages; - } - - buffer->dma_addr = buffer->dev_addr; - } else - buffer->dma_addr = buffer->paddr; - - DRM_DEBUG_KMS("dma_addr = 0x%x\n", buffer->dma_addr); - - return 0; - -err_free_pages: - kfree(buffer->pages); - buffer->pages = NULL; -err_sg_free_table: - sg_free_table(buffer->sgt); -err_free_sgt: - kfree(buffer->sgt); - buffer->sgt = NULL; -err_release_handle: - drm_gem_handle_delete(file_priv, args->gem_handle); -err_fini_buf: - exynos_drm_fini_buf(drm_dev, buffer); -err_release_gem_obj: - drm_gem_object_release(&exynos_gem_obj->base); - kfree(exynos_gem_obj); - return ret; -} - -int exynos_drm_gem_init_object(struct drm_gem_object *obj) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - return 0; -} - -void exynos_drm_gem_free_object(struct drm_gem_object *obj) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct exynos_drm_gem_buf *buf; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_gem_obj = to_exynos_gem_obj(obj); - buf = exynos_gem_obj->buffer; - - if (obj->import_attach) - drm_prime_gem_destroy(obj, buf->sgt); - - exynos_drm_gem_destroy(to_exynos_gem_obj(obj)); -} - -int exynos_drm_gem_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, - struct drm_mode_create_dumb *args) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* - * alocate memory to be used for framebuffer. - * - this callback would be called by user application - * with DRM_IOCTL_MODE_CREATE_DUMB command. - */ - - args->pitch = args->width * args->bpp >> 3; - args->size = PAGE_ALIGN(args->pitch * args->height); - - exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size); - if (IS_ERR(exynos_gem_obj)) - return PTR_ERR(exynos_gem_obj); - - ret = exynos_drm_gem_handle_create(&exynos_gem_obj->base, file_priv, - &args->handle); - if (ret) { - exynos_drm_gem_destroy(exynos_gem_obj); - return ret; - } - - return 0; -} - -int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv, - struct drm_device *dev, uint32_t handle, - uint64_t *offset) -{ - struct drm_gem_object *obj; - int ret = 0; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - mutex_lock(&dev->struct_mutex); - - /* - * get offset of memory allocated for drm framebuffer. - * - this callback would be called by user application - * with DRM_IOCTL_MODE_MAP_DUMB command. - */ - - obj = drm_gem_object_lookup(dev, file_priv, handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - ret = -EINVAL; - goto unlock; - } - - if (!obj->map_list.map) { - ret = drm_gem_create_mmap_offset(obj); - if (ret) - goto out; - } - - *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT; - DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset); - -out: - drm_gem_object_unreference(obj); -unlock: - mutex_unlock(&dev->struct_mutex); - return ret; -} - -int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv, - struct drm_device *dev, - unsigned int handle) -{ - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* - * obj->refcount and obj->handle_count are decreased and - * if both them are 0 then exynos_drm_gem_free_object() - * would be called by callback to release resources. - */ - ret = drm_gem_handle_delete(file_priv, handle); - if (ret < 0) { - DRM_ERROR("failed to delete drm_gem_handle.\n"); - return ret; - } - - return 0; -} - -void exynos_drm_gem_close_object(struct drm_gem_object *obj, - struct drm_file *file) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* TODO */ -} - -int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - struct drm_gem_object *obj = vma->vm_private_data; - struct drm_device *dev = obj->dev; - unsigned long f_vaddr; - pgoff_t page_offset; - int ret; - - page_offset = ((unsigned long)vmf->virtual_address - - vma->vm_start) >> PAGE_SHIFT; - f_vaddr = (unsigned long)vmf->virtual_address; - - mutex_lock(&dev->struct_mutex); - - ret = exynos_drm_gem_map_pages(obj, vma, f_vaddr, page_offset); - if (ret < 0) - DRM_ERROR("failed to map pages.\n"); - - mutex_unlock(&dev->struct_mutex); - - return convert_to_vm_err_msg(ret); -} - -int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct drm_gem_object *obj; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* set vm_area_struct. */ - ret = drm_gem_mmap(filp, vma); - if (ret < 0) { - DRM_ERROR("failed to mmap.\n"); - return ret; - } - - obj = vma->vm_private_data; - exynos_gem_obj = to_exynos_gem_obj(obj); - - ret = check_gem_flags(exynos_gem_obj->flags); - if (ret) { - drm_gem_vm_close(vma); - drm_gem_free_mmap_offset(obj); - return ret; - } - - vma->vm_flags &= ~VM_PFNMAP; - vma->vm_flags |= VM_MIXEDMAP; - - update_vm_cache_attr(exynos_gem_obj, vma); - - return ret; -} diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h deleted file mode 100644 index c6cd6e0..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ /dev/null @@ -1,259 +0,0 @@ -/* exynos_drm_gem.h - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authoer: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_GEM_H_ -#define _EXYNOS_DRM_GEM_H_ - -#define to_exynos_gem_obj(x) container_of(x,\ - struct exynos_drm_gem_obj, base) - -/* FIMD/HDMI/G2D/FIMC/G3D */ -#define MAX_IOMMU_NR 5 - -#define IS_NONCONTIG_BUFFER(f) ((f & EXYNOS_BO_NONCONTIG) ||\ - (f & EXYNOS_BO_USERPTR)) - -struct exynos_drm_private_cb { - unsigned int (*get_handle)(unsigned int id); - int (*add_buffer)(void *obj, unsigned int *handle, unsigned int *id); - void (*release_buffer)(unsigned int handle); -}; - -/* - * exynos drm iommu information structure. - * - * @mapped: flag a bit of indicating whether any driver's device address - * is mapped to its own iommu or not. - * @dma_addrs: contain device address to each device driver using iommu. - * @devs: device objects that requested mapping to iommu. - */ -struct exynos_drm_iommu_info { - unsigned int mapped; - dma_addr_t dma_addrs[MAX_IOMMU_NR]; - struct device *devs[MAX_IOMMU_NR]; - struct list_head *iommu_lists[MAX_IOMMU_NR]; - /* TODO. */ -}; - -/* - * exynos drm gem buffer structure. - * - * @kvaddr: kernel virtual address to allocated memory region. - * *userptr: user space address. - * @dma_addr: bus address(accessed by dma) to allocated memory region. - * @dev_addr: device address for IOMMU. - * @paddr: physical address to allocated buffer. - * @write: whether pages will be written to by the caller. - * @sgt: sg table to transfer page data. - * @pages: contain all pages to allocated memory region. - * @page_size: could be 4K, 64K or 1MB. - * @size: size of allocated memory region. - * @shared: indicate shared mfc memory region. - * (temporarily used and it should be removed later.) - * @pfnmap: indicate whether memory region from userptr is mmaped with - * VM_PFNMAP or not. - */ -struct exynos_drm_gem_buf { - struct device *dev; - void __iomem *kvaddr; - unsigned long userptr; - dma_addr_t dma_addr; - dma_addr_t dev_addr; - dma_addr_t paddr; - unsigned int write; - struct sg_table *sgt; - struct page **pages; - unsigned long page_size; - unsigned long size; - bool shared; - bool pfnmap; -}; - -/* - * exynos drm buffer structure. - * - * @base: a gem object. - * - a new handle to this gem object would be created - * by drm_gem_handle_create(). - * @buffer: a pointer to exynos_drm_gem_buffer object. - * - contain the information to memory region allocated - * by user request or at framebuffer creation. - * continuous memory region allocated by user request - * or at framebuffer creation. - * @iommu_info: contain iommu mapping information to each device driver - * using its own iommu. - * @size: size requested from user, in bytes and this size is aligned - * in page unit. - * @packed_size: real size of the gem object, in bytes and - * this size isn't aligned in page unit. - * @flags: indicate memory type to allocated buffer and cache attruibute. - * @vmm: vmm object for iommu framework. - * @priv_handle: handle to specific buffer object. - * @priv_id: unique id to specific buffer object. - * - * P.S. this object would be transfered to user as kms_bo.handle so - * user can access the buffer through kms_bo.handle. - */ -struct exynos_drm_gem_obj { - struct drm_gem_object base; - struct exynos_drm_gem_buf *buffer; - struct exynos_drm_iommu_info iommu_info; - unsigned long size; - unsigned long packed_size; - struct vm_area_struct *vma; - unsigned int flags; - void *vmm; - unsigned int priv_handle; - unsigned int priv_id; -}; - -/* register private callback. */ -void exynos_drm_priv_cb_register(struct exynos_drm_private_cb *cb); - -/* register a buffer object to private buffer manager. */ -int register_buf_to_priv_mgr(struct exynos_drm_gem_obj *obj, - unsigned int *priv_handle, unsigned int *priv_id); - -struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask); - -int exynos_drm_gem_user_limit_ioctl(struct drm_device *dev, void *data, - struct drm_file *filp); - -/* destroy a buffer with gem object */ -void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj); - -/* create a private gem object and initialize it. */ -struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev, - unsigned long size); - -/* create a new buffer with gem object */ -struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev, - unsigned int flags, - unsigned long size); - -/* - * request gem object creation and buffer allocation as the size - * that it is calculated with framebuffer information such as width, - * height and bpp. - */ -int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -/* - * get dma address from gem handle and this function could be used for - * other drivers such as 2d/3d acceleration drivers. - * with this function call, gem object reference count would be increased. - */ -void *exynos_drm_gem_get_dma_addr(struct drm_device *dev, - unsigned int gem_handle, - struct drm_file *filp, - unsigned int *gem_obj); - -/* - * put dma address from gem handle and this function could be used for - * other drivers such as 2d/3d acceleration drivers. - * with this function call, gem object reference count would be decreased. - */ -void exynos_drm_gem_put_dma_addr(struct drm_device *dev, void *gem_obj); - -/* get buffer offset to map to user space. */ -int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -/* - * mmap the physically continuous memory that a gem object contains - * to user space. - */ -int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -/* map user space allocated by malloc to pages. */ -int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -/* get buffer information to memory region allocated by gem. */ -int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -/* get buffer size to gem handle. */ -unsigned long exynos_drm_gem_get_size(struct drm_device *dev, - unsigned int gem_handle, - struct drm_file *file_priv); - -/* initialize gem object. */ -int exynos_drm_gem_init_object(struct drm_gem_object *obj); - -/* free gem object. */ -void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj); - -/* create memory region for drm framebuffer. */ -int exynos_drm_gem_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, - struct drm_mode_create_dumb *args); - -/* map memory region for drm framebuffer to user space. */ -int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv, - struct drm_device *dev, uint32_t handle, - uint64_t *offset); - -/* - * destroy memory region allocated. - * - a gem handle and physical memory region pointed by a gem object - * would be released by drm_gem_handle_delete(). - */ -int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv, - struct drm_device *dev, - unsigned int handle); - -/* page fault handler and mmap fault address(virtual) to physical memory. */ -int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); - -/* set vm_flags and we can change the vm attribute to other one at here. */ -int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); - -/* get ump sequre id for UMP. */ -int exynos_drm_gem_export_ump_ioctl(struct drm_device *dev, void *data, - struct drm_file *file); - -/* do user desired cache operation. */ -int exynos_drm_gem_cache_op_ioctl(struct drm_device *drm_dev, void *data, - struct drm_file *file_priv); - -/* temporary functions. */ -/* get physical address from a gem. */ -int exynos_drm_gem_get_phy_ioctl(struct drm_device *drm_dev, void *data, - struct drm_file *file_priv); -/* import physical memory to a gem. */ -int exynos_drm_gem_phy_imp_ioctl(struct drm_device *drm_dev, void *data, - struct drm_file *file_priv); - -void exynos_drm_gem_close_object(struct drm_gem_object *obj, - struct drm_file *file); - -struct exynos_drm_gem_obj *exynos_drm_gem_get_obj(struct drm_device *dev, - unsigned int gem_handle, - struct drm_file *file_priv); - -#endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c deleted file mode 100644 index d5e3a68..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ /dev/null @@ -1,1385 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Authors: - * Eunchul Kim - * - * 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 "drmP.h" -#include "drm_backlight.h" -#include -#include -#include -#include -#include -#include -#include - -#include "regs-gsc.h" -#include -#include "exynos_drm_drv.h" -#include "exynos_drm_gem.h" -#include "exynos_drm_ipp.h" -#include "exynos_drm_gsc.h" - -/* - * GSC is stand for General SCaler and - * supports image scaler/rotator and input/output DMA operations. - * input DMA reads image data from the memory. - * output DMA writes image data to memory. - * GSC supports image rotation and image effect functions. - */ - -#define GSC_MAX_DEVS 4 -#define GSC_MAX_SRC 8 -#define GSC_MAX_DST 32 -#define GSC_RESET_TIMEOUT 50 -#ifdef CONFIG_SLP_DISP_DEBUG -#define GSC_MAX_REG 128 -#define GSC_BASE_REG(id) (0x13E00000 + (0x10000 * id)) -#endif -#define GSC_CLK_RATE 166750000 -#define GSC_BUF_STOP 1 -#define GSC_BUF_START 2 -#define GSC_REG_SZ 32 -#define GSC_WIDTH_ITU_709 1280 - -#define get_gsc_context(dev) platform_get_drvdata(to_platform_device(dev)) -#define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\ - struct gsc_context, ippdrv); -#define gsc_read(offset) readl(ctx->regs + (offset)); -#define gsc_write(cfg, offset) writel(cfg, ctx->regs + (offset)); - -enum gsc_wb { - GSC_WB_NONE, - GSC_WB_A, - GSC_WB_B, -}; - -/* - * A structure of scaler. - * - * @range: narrow, wide. - * @pre_shfactor: pre sclaer shift factor. - * @pre_hratio: horizontal ratio of the prescaler. - * @pre_vratio: vertical ratio of the prescaler. - * @main_hratio: the main scaler's horizontal ratio. - * @main_vratio: the main scaler's vertical ratio. - */ -struct gsc_scaler { - bool range; - u32 pre_shfactor; - u32 pre_hratio; - u32 pre_vratio; - unsigned long main_hratio; - unsigned long main_vratio; -}; - -/* - * A structure of scaler capability. - * - * find user manual 49.2 features. - * @tile_w: tile mode or rotation width. - * @tile_h: tile mode or rotation height. - * @w: other cases width. - * @h: other cases height. - */ -struct gsc_capability { - /* tile or rotation */ - u32 tile_w; - u32 tile_h; - /* other cases */ - u32 w; - u32 h; -}; - -/* - * A structure of gsc context. - * - * @ippdrv: prepare initialization using ippdrv. - * @regs_res: register resources. - * @regs: memory mapped io registers. - * @lock: locking of operations. - * @gsc_clk: gsc clock. - * @sc: scaler infomations. - * @capa: scaler capability. - * @id: gsc id. - * @irq: irq number. - * @suspended: qos operations. - */ -struct gsc_context { - struct exynos_drm_ippdrv ippdrv; - struct resource *regs_res; - void __iomem *regs; - struct mutex lock; - struct clk *gsc_clk; - struct gsc_scaler sc; - struct gsc_capability *capa; - int id; - int irq; - bool suspended; -}; - -struct gsc_capability gsc51_capa[GSC_MAX_DEVS] = { - { - .tile_w = 2048, - .tile_h = 2048, - .w = 4800, - .h = 3344, - }, { - .tile_w = 2048, - .tile_h = 2048, - .w = 4800, - .h = 3344, - }, { - .tile_w = 2048, - .tile_h = 2048, - .w = 4800, - .h = 3344, - }, { - .tile_w = 2048, - .tile_h = 2048, - .w = 4800, - .h = 3344, - }, -}; - -static int gsc_sw_reset(struct gsc_context *ctx) -{ - u32 cfg; - int count = GSC_RESET_TIMEOUT; - - DRM_DEBUG_KMS("%s\n", __func__); - - /* s/w reset */ - cfg = (GSC_SW_RESET_SRESET); - gsc_write(cfg, GSC_SW_RESET); - - /* wait s/w reset complete */ - while (count--) { - cfg = gsc_read(GSC_SW_RESET); - if (!cfg) - break; - usleep_range(1000, 2000); - } - - if (cfg) { - DRM_ERROR("failed to reset gsc h/w.\n"); - return -EBUSY; - } - - /* display fifo reset */ - cfg = readl(SYSREG_GSCBLK_CFG0); - /* - * GSCBLK Pixel asyncy FIFO S/W reset sequence - * set PXLASYNC_SW_RESET as 0 then, - * set PXLASYNC_SW_RESET as 1 again - */ - cfg &= ~GSC_PXLASYNC_RST(ctx->id); - writel(cfg, SYSREG_GSCBLK_CFG0); - cfg |= GSC_PXLASYNC_RST(ctx->id); - writel(cfg, SYSREG_GSCBLK_CFG0); - - /* pixel async reset */ - cfg = readl(SYSREG_DISP1BLK_CFG); - /* - * DISPBLK1 FIFO S/W reset sequence - * set FIFORST_DISP1 as 0 then, - * set FIFORST_DISP1 as 1 again - */ - cfg &= ~FIFORST_DISP1; - writel(cfg, SYSREG_DISP1BLK_CFG); - cfg |= FIFORST_DISP1; - writel(cfg, SYSREG_DISP1BLK_CFG); - - /* reset sequence */ - cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK); - cfg |= (GSC_IN_BASE_ADDR_MASK | - GSC_IN_BASE_ADDR_PINGPONG(0)); - gsc_write(cfg, GSC_IN_BASE_ADDR_Y_MASK); - gsc_write(cfg, GSC_IN_BASE_ADDR_CB_MASK); - gsc_write(cfg, GSC_IN_BASE_ADDR_CR_MASK); - - cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK); - cfg |= (GSC_OUT_BASE_ADDR_MASK | - GSC_OUT_BASE_ADDR_PINGPONG(0)); - gsc_write(cfg, GSC_OUT_BASE_ADDR_Y_MASK); - gsc_write(cfg, GSC_OUT_BASE_ADDR_CB_MASK); - gsc_write(cfg, GSC_OUT_BASE_ADDR_CR_MASK); - - return 0; -} - -static void gsc_set_gscblk_fimd_wb(struct gsc_context *ctx, bool enable) -{ - u32 gscblk_cfg; - - DRM_DEBUG_KMS("%s\n", __func__); - - gscblk_cfg = readl(SYSREG_GSCBLK_CFG1); - - if (enable) - gscblk_cfg |= GSC_BLK_DISP1WB_DEST(ctx->id) | - GSC_BLK_GSCL_WB_IN_SRC_SEL(ctx->id) | - GSC_BLK_SW_RESET_WB_DEST(ctx->id); - else - gscblk_cfg |= GSC_BLK_PXLASYNC_LO_MASK_WB(ctx->id); - - writel(gscblk_cfg, SYSREG_GSCBLK_CFG1); -} - -static void gsc_handle_irq(struct gsc_context *ctx, bool enable, - bool overflow, bool done) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__, - enable, overflow, done); - - cfg = gsc_read(GSC_IRQ); - cfg |= (GSC_IRQ_OR_MASK | GSC_IRQ_FRMDONE_MASK); - - if (enable) { - cfg |= GSC_IRQ_ENABLE; - if (overflow) - cfg &= ~GSC_IRQ_OR_MASK; - if (done) - cfg &= ~GSC_IRQ_FRMDONE_MASK; - } else - cfg &= ~GSC_IRQ_ENABLE; - - gsc_write(cfg, GSC_IRQ); -} - -static int gsc_set_planar_addr(struct drm_exynos_ipp_buf_info *buf_info, - u32 fmt, struct drm_exynos_sz *sz) -{ - dma_addr_t *y_addr = &buf_info->base[EXYNOS_DRM_PLANAR_Y]; - dma_addr_t *cb_addr = &buf_info->base[EXYNOS_DRM_PLANAR_CB]; - dma_addr_t *cr_addr = &buf_info->base[EXYNOS_DRM_PLANAR_CR]; - uint64_t y_ofs, cb_ofs, cr_ofs; - - /* - * ToDo: check the buffer size between gem allocated buffers - * and each planar size. - */ - switch (fmt) { - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - y_ofs = sz->hsize * sz->vsize; - cb_ofs = y_ofs >> 1; - cr_ofs = 0; - break; - case DRM_FORMAT_NV12M: - y_ofs = ALIGN(ALIGN(sz->hsize, 16) * - ALIGN(sz->vsize, 16), SZ_2K); - cb_ofs = ALIGN(ALIGN(sz->hsize, 16) * - ALIGN(sz->vsize >> 1, 16), SZ_2K); - cr_ofs = 0; - break; - case DRM_FORMAT_NV12MT: - y_ofs = ALIGN(ALIGN(sz->hsize, 128) * - ALIGN(sz->vsize, 32), SZ_8K); - cb_ofs = ALIGN(ALIGN(sz->hsize, 128) * - ALIGN(sz->vsize >> 1, 32), SZ_8K); - cr_ofs = 0; - break; - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - case DRM_FORMAT_YUV411: - case DRM_FORMAT_YVU411: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YVU422: - case DRM_FORMAT_YUV444: - case DRM_FORMAT_YVU444: - case DRM_FORMAT_YUV420M: - y_ofs = sz->hsize * sz->vsize; - cb_ofs = cr_ofs = y_ofs >> 2; - break; - default: - y_ofs = cb_ofs = cr_ofs = 0; - break; - } - - if (y_ofs && *y_addr) { - *cb_addr = *y_addr + y_ofs; - - if (cb_ofs && *cb_addr) - *cr_addr = *cb_addr + cb_ofs; - } - - return 0; -} - -static int gsc_src_set_fmt(struct device *dev, u32 fmt) -{ - struct gsc_context *ctx = get_gsc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt); - - cfg = gsc_read(GSC_IN_CON); - cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK | - GSC_IN_CHROMA_ORDER_MASK | GSC_IN_FORMAT_MASK | - GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE); - - switch (fmt) { - case DRM_FORMAT_RGB565: - cfg |= GSC_IN_RGB565; - break; - case DRM_FORMAT_XRGB8888: - cfg |= GSC_IN_XRGB8888; - break; - case DRM_FORMAT_YUYV: - cfg |= (GSC_IN_YUV422_1P | - GSC_IN_YUV422_1P_ORDER_LSB_Y | - GSC_IN_CHROMA_ORDER_CBCR); - break; - case DRM_FORMAT_YVYU: - cfg |= (GSC_IN_YUV422_1P | - GSC_IN_YUV422_1P_ORDER_LSB_Y | - GSC_IN_CHROMA_ORDER_CRCB); - break; - case DRM_FORMAT_UYVY: - cfg |= (GSC_IN_YUV422_1P | - GSC_IN_YUV422_1P_OEDER_LSB_C | - GSC_IN_CHROMA_ORDER_CBCR); - break; - case DRM_FORMAT_VYUY: - cfg |= (GSC_IN_YUV422_1P | - GSC_IN_YUV422_1P_OEDER_LSB_C | - GSC_IN_CHROMA_ORDER_CRCB); - break; - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV61: - cfg |= (GSC_IN_CHROMA_ORDER_CRCB | - GSC_IN_YUV420_2P); - break; - case DRM_FORMAT_YUV422: - cfg |= GSC_IN_YUV422_3P; - break; - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - cfg |= GSC_IN_YUV420_3P; - break; - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12M: - case DRM_FORMAT_NV16: - cfg |= (GSC_IN_CHROMA_ORDER_CBCR | - GSC_IN_YUV420_2P); - break; - case DRM_FORMAT_NV12MT: - cfg |= (GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE); - break; - default: - dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt); - return -EINVAL; - } - - gsc_write(cfg, GSC_IN_CON); - - return 0; -} - -static int gsc_src_set_transf(struct device *dev, - enum drm_exynos_degree degree, - enum drm_exynos_flip flip) -{ - struct gsc_context *ctx = get_gsc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__, - degree, flip); - - cfg = gsc_read(GSC_IN_CON); - cfg &= ~GSC_IN_ROT_MASK; - - switch (degree) { - case EXYNOS_DRM_DEGREE_0: - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg |= GSC_IN_ROT_XFLIP; - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg |= GSC_IN_ROT_YFLIP; - break; - case EXYNOS_DRM_DEGREE_90: - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg |= GSC_IN_ROT_90_XFLIP; - else if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg |= GSC_IN_ROT_90_YFLIP; - else - cfg |= GSC_IN_ROT_90; - break; - case EXYNOS_DRM_DEGREE_180: - cfg |= GSC_IN_ROT_180; - break; - case EXYNOS_DRM_DEGREE_270: - cfg |= GSC_IN_ROT_270; - break; - default: - dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree); - return -EINVAL; - } - - gsc_write(cfg, GSC_IN_CON); - - return cfg ? 1 : 0; -} - -static int gsc_src_set_size(struct device *dev, int swap, - struct drm_exynos_pos *pos, struct drm_exynos_sz *sz) -{ - struct gsc_context *ctx = get_gsc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_property *property = ippdrv->property; - struct drm_exynos_ipp_config *config = - &property->config[EXYNOS_DRM_OPS_SRC]; - struct drm_exynos_pos img_pos = *pos; - struct drm_exynos_sz img_sz = *sz; - u32 cfg; - - /* ToDo: check width and height */ - if (swap) { - img_pos.w = pos->h; - img_pos.h = pos->w; - img_sz.hsize = sz->vsize; - img_sz.vsize = sz->hsize; - } - - DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n", - __func__, pos->x, pos->y, pos->w, pos->h); - - /* pixel offset */ - cfg = (GSC_SRCIMG_OFFSET_X(img_pos.x) | - GSC_SRCIMG_OFFSET_Y(img_pos.y)); - gsc_write(cfg, GSC_SRCIMG_OFFSET); - - /* cropped size */ - cfg = (GSC_CROPPED_WIDTH(img_pos.w) | - GSC_CROPPED_HEIGHT(img_pos.h)); - gsc_write(cfg, GSC_CROPPED_SIZE); - - DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n", - __func__, swap, sz->hsize, sz->vsize); - - /* original size */ - cfg = gsc_read(GSC_SRCIMG_SIZE); - cfg &= ~(GSC_SRCIMG_HEIGHT_MASK | - GSC_SRCIMG_WIDTH_MASK); - - cfg |= (GSC_SRCIMG_WIDTH(sz->hsize) | - GSC_SRCIMG_HEIGHT(sz->vsize)); - - gsc_write(cfg, GSC_SRCIMG_SIZE); - - config->sz = img_sz; - config->pos = img_pos; - - return 0; -} - -static int gsc_src_set_buf_seq(struct gsc_context *ctx, u32 buf_id, - enum drm_exynos_ipp_buf_ctrl buf_ctrl) -{ - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - bool masked; - u32 cfg; - u32 mask = 0x00000001 << buf_id; - - DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__, - buf_id, buf_ctrl); - - /* mask register set */ - cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK); - - switch (buf_ctrl) { - case IPP_BUF_CTRL_QUEUE: - masked = false; - break; - case IPP_BUF_CTRL_DEQUEUE: - masked = true; - break; - default: - dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n"); - return -EINVAL; - } - - /* sequence id */ - cfg &= (~mask); - cfg |= masked << buf_id; - gsc_write(cfg, GSC_IN_BASE_ADDR_Y_MASK); - gsc_write(cfg, GSC_IN_BASE_ADDR_CB_MASK); - gsc_write(cfg, GSC_IN_BASE_ADDR_CR_MASK); - - return 0; -} - -static int gsc_src_set_addr(struct device *dev, - struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id, - enum drm_exynos_ipp_buf_ctrl buf_ctrl) -{ - struct gsc_context *ctx = get_gsc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_property *property = ippdrv->property; - struct drm_exynos_ipp_config *config = - &property->config[EXYNOS_DRM_OPS_SRC]; - int ret; - - DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__, - buf_id, buf_ctrl); - - if (buf_id > GSC_MAX_SRC) { - dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id); - return -ENOMEM; - } - - /* address register set */ - switch (buf_ctrl) { - case IPP_BUF_CTRL_QUEUE: - case IPP_BUF_CTRL_DEQUEUE: - ret = gsc_set_planar_addr(buf_info, config->fmt, &config->sz); - - if (ret) { - dev_err(dev, "failed to set plane addr.\n"); - return ret; - } - - gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y], - GSC_IN_BASE_ADDR_Y(buf_id)); - gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], - GSC_IN_BASE_ADDR_CB(buf_id)); - gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR], - GSC_IN_BASE_ADDR_CR(buf_id)); - break; - default: - /* bypass */ - break; - } - - return gsc_src_set_buf_seq(ctx, buf_id, buf_ctrl); -} - -static struct exynos_drm_ipp_ops gsc_src_ops = { - .set_fmt = gsc_src_set_fmt, - .set_transf = gsc_src_set_transf, - .set_size = gsc_src_set_size, - .set_addr = gsc_src_set_addr, -}; - -static int gsc_dst_set_fmt(struct device *dev, u32 fmt) -{ - struct gsc_context *ctx = get_gsc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt); - - cfg = gsc_read(GSC_OUT_CON); - cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK | - GSC_OUT_CHROMA_ORDER_MASK | GSC_OUT_FORMAT_MASK | - GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE); - - switch (fmt) { - case DRM_FORMAT_RGB565: - cfg |= GSC_OUT_RGB565; - break; - case DRM_FORMAT_XRGB8888: - cfg |= GSC_OUT_XRGB8888; - break; - case DRM_FORMAT_YUYV: - cfg |= (GSC_OUT_YUV422_1P | - GSC_OUT_YUV422_1P_ORDER_LSB_Y | - GSC_OUT_CHROMA_ORDER_CBCR); - break; - case DRM_FORMAT_YVYU: - cfg |= (GSC_OUT_YUV422_1P | - GSC_OUT_YUV422_1P_ORDER_LSB_Y | - GSC_OUT_CHROMA_ORDER_CRCB); - break; - case DRM_FORMAT_UYVY: - cfg |= (GSC_OUT_YUV422_1P | - GSC_OUT_YUV422_1P_OEDER_LSB_C | - GSC_OUT_CHROMA_ORDER_CBCR); - break; - case DRM_FORMAT_VYUY: - cfg |= (GSC_OUT_YUV422_1P | - GSC_OUT_YUV422_1P_OEDER_LSB_C | - GSC_OUT_CHROMA_ORDER_CRCB); - break; - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV61: - cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | - GSC_OUT_YUV420_2P); - break; - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - cfg |= GSC_OUT_YUV420_3P; - break; - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12M: - case DRM_FORMAT_NV16: - cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | - GSC_OUT_YUV420_2P); - break; - case DRM_FORMAT_NV12MT: - cfg |= (GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE); - break; - default: - dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt); - return -EINVAL; - } - - gsc_write(cfg, GSC_OUT_CON); - - return 0; -} - -static int gsc_dst_set_transf(struct device *dev, - enum drm_exynos_degree degree, - enum drm_exynos_flip flip) -{ - struct gsc_context *ctx = get_gsc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - - DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__, - degree, flip); - - cfg = gsc_read(GSC_IN_CON); - cfg &= ~GSC_IN_ROT_MASK; - - switch (degree) { - case EXYNOS_DRM_DEGREE_0: - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg |= GSC_IN_ROT_XFLIP; - if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg |= GSC_IN_ROT_YFLIP; - break; - case EXYNOS_DRM_DEGREE_90: - if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) - cfg |= GSC_IN_ROT_90_XFLIP; - else if (flip & EXYNOS_DRM_FLIP_VERTICAL) - cfg |= GSC_IN_ROT_90_YFLIP; - else - cfg |= GSC_IN_ROT_90; - break; - case EXYNOS_DRM_DEGREE_180: - cfg |= GSC_IN_ROT_180; - break; - case EXYNOS_DRM_DEGREE_270: - cfg |= GSC_IN_ROT_270; - break; - default: - dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree); - return -EINVAL; - } - - gsc_write(cfg, GSC_IN_CON); - - return cfg ? 1 : 0; -} - -static int gsc_get_ratio_shift(u32 src, u32 dst, u32 *ratio, u32 *shift) -{ - DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst); - - if (src >= dst * 64) { - DRM_ERROR("failed to make ratio and shift.\n"); - return -EINVAL; - } else if (src >= dst * 32) { - *ratio = 32; - *shift = 5; - } else if (src >= dst * 16) { - *ratio = 16; - *shift = 4; - } else if (src >= dst * 8) { - *ratio = 8; - *shift = 3; - } else if (src >= dst * 4) { - *ratio = 4; - *shift = 2; - } else if (src >= dst * 2) { - *ratio = 2; - *shift = 1; - } else { - *ratio = 1; - *shift = 0; - } - - return 0; -} - -static int gsc_set_prescaler(struct gsc_context *ctx, struct gsc_scaler *sc, - struct drm_exynos_pos *src, struct drm_exynos_pos *dst) -{ - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - u32 hfactor, vfactor; - int ret = 0; - - ret = gsc_get_ratio_shift(src->w, dst->w, &sc->pre_hratio, &hfactor); - if (ret) { - dev_err(ippdrv->dev, "failed to get ratio horizontal.\n"); - return ret; - } - - ret = gsc_get_ratio_shift(src->h, dst->h, &sc->pre_vratio, &vfactor); - if (ret) { - dev_err(ippdrv->dev, "failed to get ratio vertical.\n"); - return ret; - } - - DRM_DEBUG_KMS("%s:pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n", - __func__, sc->pre_hratio, hfactor, sc->pre_vratio, vfactor); - - sc->main_hratio = (src->w << 16) / (dst->w << hfactor); - sc->main_vratio = (src->h << 16) / (dst->h << vfactor); - DRM_DEBUG_KMS("%s:main_hratio[%ld]main_vratio[%ld]\n", - __func__, sc->main_hratio, sc->main_vratio); - - sc->pre_shfactor = 10 - (hfactor + vfactor); - DRM_DEBUG_KMS("%s:pre_shfactor[%d]\n", __func__, - sc->pre_shfactor); - - cfg = (GSC_PRESC_SHFACTOR(sc->pre_shfactor) | - GSC_PRESC_H_RATIO(sc->pre_hratio) | - GSC_PRESC_V_RATIO(sc->pre_vratio)); - gsc_write(cfg, GSC_PRE_SCALE_RATIO); - - return ret; -} - -static void gsc_set_scaler(struct gsc_context *ctx, struct gsc_scaler *sc) -{ - u32 cfg; - - DRM_DEBUG_KMS("%s:main_hratio[%ld]main_vratio[%ld]\n", - __func__, sc->main_hratio, sc->main_vratio); - - cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio); - gsc_write(cfg, GSC_MAIN_H_RATIO); - - cfg = GSC_MAIN_V_RATIO_VALUE(sc->main_vratio); - gsc_write(cfg, GSC_MAIN_V_RATIO); -} - -static int gsc_dst_set_size(struct device *dev, int swap, - struct drm_exynos_pos *pos, struct drm_exynos_sz *sz) -{ - struct gsc_context *ctx = get_gsc_context(dev); - struct drm_exynos_pos img_pos = *pos; - struct drm_exynos_sz img_sz = *sz; - struct gsc_scaler *sc = &ctx->sc; - u32 cfg; - - DRM_DEBUG_KMS("%s:swap[%d]x[%d]y[%d]w[%d]h[%d]\n", - __func__, swap, pos->x, pos->y, pos->w, pos->h); - - if (swap) { - img_pos.w = pos->h; - img_pos.h = pos->w; - img_sz.hsize = sz->vsize; - img_sz.vsize = sz->hsize; - } - - /* pixel offset */ - cfg = (GSC_DSTIMG_OFFSET_X(img_pos.x) | - GSC_DSTIMG_OFFSET_Y(img_pos.y)); - gsc_write(cfg, GSC_DSTIMG_OFFSET); - - /* scaled size */ - cfg = (GSC_SCALED_WIDTH(pos->w) | GSC_SCALED_HEIGHT(pos->h)); - gsc_write(cfg, GSC_SCALED_SIZE); - - DRM_DEBUG_KMS("%s:hsize[%d]vsize[%d]\n", - __func__, sz->hsize, sz->vsize); - - /* original size */ - cfg = gsc_read(GSC_DSTIMG_SIZE); - cfg &= ~(GSC_DSTIMG_HEIGHT_MASK | - GSC_DSTIMG_WIDTH_MASK); - cfg |= (GSC_DSTIMG_WIDTH(img_sz.hsize) | - GSC_DSTIMG_HEIGHT(img_sz.vsize)); - gsc_write(cfg, GSC_DSTIMG_SIZE); - - cfg = gsc_read(GSC_OUT_CON); - cfg &= ~GSC_OUT_RGB_TYPE_MASK; - - if (pos->w >= GSC_WIDTH_ITU_709) - if (sc->range) - cfg |= GSC_OUT_RGB_HD_WIDE; - else - cfg |= GSC_OUT_RGB_HD_NARROW; - else - if (sc->range) - cfg |= GSC_OUT_RGB_SD_WIDE; - else - cfg |= GSC_OUT_RGB_SD_NARROW; - - gsc_write(cfg, GSC_OUT_CON); - - return 0; -} - -static int gsc_dst_get_buf_seq(struct gsc_context *ctx) -{ - u32 cfg, i, buf_num = GSC_REG_SZ; - u32 mask = 0x00000001; - - cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK); - - for (i = 0; i < GSC_REG_SZ; i++) - if (cfg & (mask << i)) - buf_num--; - - DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num); - - return buf_num; -} - -static int gsc_dst_set_buf_seq(struct gsc_context *ctx, u32 buf_id, - enum drm_exynos_ipp_buf_ctrl buf_ctrl) -{ - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - bool masked; - u32 cfg; - u32 mask = 0x00000001 << buf_id; - - DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__, - buf_id, buf_ctrl); - - /* mask register set */ - cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK); - - switch (buf_ctrl) { - case IPP_BUF_CTRL_QUEUE: - masked = false; - break; - case IPP_BUF_CTRL_DEQUEUE: - masked = true; - break; - default: - dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n"); - return -EINVAL; - } - - /* sequence id */ - cfg &= (~mask); - cfg |= masked << buf_id; - gsc_write(cfg, GSC_OUT_BASE_ADDR_Y_MASK); - gsc_write(cfg, GSC_OUT_BASE_ADDR_CB_MASK); - gsc_write(cfg, GSC_OUT_BASE_ADDR_CR_MASK); - - /* interrupt enable */ - if (buf_ctrl == IPP_BUF_CTRL_QUEUE && - gsc_dst_get_buf_seq(ctx) >= GSC_BUF_START) - gsc_handle_irq(ctx, true, false, true); - - return 0; -} - -static int gsc_dst_set_addr(struct device *dev, - struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id, - enum drm_exynos_ipp_buf_ctrl buf_ctrl) -{ - struct gsc_context *ctx = get_gsc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_property *property = ippdrv->property; - struct drm_exynos_ipp_config *config = - &property->config[EXYNOS_DRM_OPS_DST]; - int ret; - - DRM_DEBUG_KMS("%s:buf_id[%d]buf_ctrl[%d]\n", __func__, - buf_id, buf_ctrl); - - if (buf_id > GSC_MAX_DST) { - dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id); - return -ENOMEM; - } - - /* address register set */ - switch (buf_ctrl) { - case IPP_BUF_CTRL_QUEUE: - case IPP_BUF_CTRL_DEQUEUE: - ret = gsc_set_planar_addr(buf_info, config->fmt, &config->sz); - - if (ret) { - dev_err(dev, "failed to set plane addr.\n"); - return ret; - } - - gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y], - GSC_OUT_BASE_ADDR_Y(buf_id)); - gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], - GSC_OUT_BASE_ADDR_CB(buf_id)); - gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR], - GSC_OUT_BASE_ADDR_CR(buf_id)); - break; - default: - /* bypass */ - break; - } - - return gsc_dst_set_buf_seq(ctx, buf_id, buf_ctrl); -} - -static struct exynos_drm_ipp_ops gsc_dst_ops = { - .set_fmt = gsc_dst_set_fmt, - .set_transf = gsc_dst_set_transf, - .set_size = gsc_dst_set_size, - .set_addr = gsc_dst_set_addr, -}; - -static int gsc_power_on(struct gsc_context *ctx, bool enable) -{ - DRM_DEBUG_KMS("%s:\n", __func__); - - if (enable) { - clk_enable(ctx->gsc_clk); - /* ToDo : wb_b_clk */ - ctx->suspended = false; - } else { - clk_disable(ctx->gsc_clk); - /* ToDo : wb_b_clk */ - ctx->suspended = true; - } - - return 0; -} - -static irqreturn_t gsc_irq_handler(int irq, void *dev_id) -{ - struct gsc_context *ctx = dev_id; - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg, status; - int buf_id = 0; - - DRM_DEBUG_KMS("%s:gsc id[%d]\n", __func__, ctx->id); - - status = gsc_read(GSC_IRQ); - if (status & GSC_IRQ_STATUS_OR_IRQ) { - dev_err(ippdrv->dev, "occured overflow at %d, status 0x%x.\n", - ctx->id, status); - return IRQ_NONE; - } - - if (status & GSC_IRQ_STATUS_OR_FRM_DONE) { - dev_err(ippdrv->dev, "occured frame done at %d, status 0x%x.\n", - ctx->id, status); - /* ToDo: Frame control */ - } - - if (list_empty(&ippdrv->event_list)) { - DRM_DEBUG_KMS("%s:event list empty.\n", __func__); - - return IRQ_HANDLED; - } - - cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK); - buf_id = GSC_IN_CURR_GET_INDEX(cfg); - if (buf_id < 0) - return IRQ_HANDLED; - - DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id); - - if (gsc_dst_set_buf_seq(ctx, buf_id, - IPP_BUF_CTRL_DEQUEUE) < 0) { - DRM_ERROR("failed to dequeue.\n"); - - return IRQ_HANDLED; - } - - ipp_send_event_handler(ippdrv, buf_id); - - if (gsc_dst_get_buf_seq(ctx) <= GSC_BUF_STOP) - gsc_handle_irq(ctx, false, false, true); - - return IRQ_HANDLED; -} - -static int gsc_ippdrv_check_property(struct device *dev, - struct drm_exynos_ipp_property *property) -{ - /* ToDo: check valid using property information */ - DRM_DEBUG_KMS("%s\n", __func__); - - return 0; -} - -static int gsc_ippdrv_reset(struct device *dev) -{ - struct gsc_context *ctx = get_gsc_context(dev); - int ret; - - DRM_DEBUG_KMS("%s\n", __func__); - - /* reset h/w block */ - ret = gsc_sw_reset(ctx); - if (ret < 0) { - dev_err(dev, "failed to reset hardware.\n"); - return ret; - } - - memset(&ctx->sc, 0x0, sizeof(ctx->sc)); - - return 0; -} - -static int gsc_check_prepare(struct gsc_context *ctx) -{ - /* ToDo: check prepare using read register */ - DRM_DEBUG_KMS("%s\n", __func__); - - return 0; -} - -static int gsc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd) -{ - struct gsc_context *ctx = get_gsc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - struct drm_exynos_ipp_property *property = ippdrv->property; - struct drm_exynos_ipp_config *config = - &property->config[EXYNOS_DRM_OPS_DST]; - u32 cfg; - int ret; - int enable = 1; - - DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd); - - ret = gsc_check_prepare(ctx); - if (ret) { - dev_err(dev, "failed to check prepare.\n"); - return ret; - } - - ippdrv->cmd = cmd; - gsc_handle_irq(ctx, true, false, true); - - switch (cmd) { - case IPP_CMD_M2M: - /* bypass */ - break; - case IPP_CMD_WB: - gsc_set_gscblk_fimd_wb(ctx, enable); - exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)enable); - break; - case IPP_CMD_OUTPUT: - default: - ret = -EINVAL; - dev_err(dev, "invalid operations.\n"); - return ret; - } - - ret = gsc_set_prescaler(ctx, &ctx->sc, &config->pos, - &config->pos); - if (ret) { - dev_err(dev, "failed to set precalser.\n"); - return ret; - } - - gsc_set_scaler(ctx, &ctx->sc); - - cfg = gsc_read(GSC_ENABLE); - cfg |= GSC_ENABLE_ON; - gsc_write(cfg, GSC_ENABLE); - - return 0; -} - -static void gsc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd) -{ - struct gsc_context *ctx = get_gsc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - u32 cfg; - int enable = 0; - - DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd); - - switch (cmd) { - case IPP_CMD_M2M: - /* bypass */ - break; - case IPP_CMD_WB: - gsc_set_gscblk_fimd_wb(ctx, enable); - exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)enable); - break; - case IPP_CMD_OUTPUT: - default: - dev_err(dev, "invalid operations.\n"); - break; - } - - ippdrv->cmd = IPP_CMD_NONE; - gsc_handle_irq(ctx, false, false, true); - - /* reset sequence */ - gsc_write(0xff, GSC_OUT_BASE_ADDR_Y_MASK); - gsc_write(0xff, GSC_OUT_BASE_ADDR_CB_MASK); - gsc_write(0xff, GSC_OUT_BASE_ADDR_CR_MASK); - - cfg = gsc_read(GSC_ENABLE); - cfg &= ~GSC_ENABLE_ON; - gsc_write(cfg, GSC_ENABLE); -} - -#ifdef CONFIG_SLP_DISP_DEBUG -static int gsc_read_reg(struct gsc_context *ctx, char *buf) -{ - u32 cfg; - int i; - int pos = 0; - - pos += sprintf(buf+pos, "0x%.8x | ", GSC_BASE_REG(ctx->id)); - for (i = 1; i < GSC_MAX_REG + 1; i++) { - cfg = gsc_read((i-1) * sizeof(u32)); - pos += sprintf(buf+pos, "0x%.8x ", cfg); - if (i % 4 == 0) - pos += sprintf(buf+pos, "\n0x%.8x | ", - GSC_BASE_REG(ctx->id) + (i * sizeof(u32))); - } - - pos += sprintf(buf+pos, "\n"); - - return pos; -} - -static ssize_t show_read_reg(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gsc_context *ctx = get_gsc_context(dev); - - if (!ctx->regs) { - dev_err(dev, "failed to get current register.\n"); - return -EINVAL; - } - - return gsc_read_reg(ctx, buf); -} - -static struct device_attribute device_attrs[] = { - __ATTR(read_reg, S_IRUGO, show_read_reg, NULL), -}; -#endif - -static int __devinit gsc_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct gsc_context *ctx; - struct resource *res; - struct exynos_drm_ippdrv *ippdrv; - struct exynos_drm_gsc_pdata *pdata; - int ret = -EINVAL; -#ifdef CONFIG_SLP_DISP_DEBUG - int i; -#endif - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(dev, "no platform data specified.\n"); - return -EINVAL; - } - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - /* clock control */ - ctx->gsc_clk = clk_get(dev, "gscl"); - if (IS_ERR(ctx->gsc_clk)) { - dev_err(dev, "failed to get gsc clock.\n"); - ret = PTR_ERR(ctx->gsc_clk); - goto err_ctx; - } - - /* resource memory */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "failed to find registers.\n"); - ret = -ENOENT; - goto err_clk; - } - - ctx->regs_res = request_mem_region(res->start, resource_size(res), - dev_name(dev)); - if (!ctx->regs_res) { - dev_err(dev, "failed to claim register region.\n"); - ret = -ENOENT; - goto err_clk; - } - - ctx->regs = ioremap(res->start, resource_size(res)); - if (!ctx->regs) { - dev_err(dev, "failed to map registers.\n"); - ret = -ENXIO; - goto err_req_region; - } - - /* resource irq */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(dev, "failed to request irq resource.\n"); - goto err_get_regs; - } - - ctx->irq = res->start; - ret = request_threaded_irq(ctx->irq, NULL, gsc_irq_handler, - IRQF_ONESHOT, "drm_gsc", ctx); - if (ret < 0) { - dev_err(dev, "failed to request irq.\n"); - goto err_get_regs; - } - - /* context initailization */ - ctx->id = pdev->id; - ctx->capa = gsc51_capa; - if (!ctx->capa) { - dev_err(dev, "failed to get capability.\n"); - goto err_get_irq; - } - -#ifdef CONFIG_SLP_DISP_DEBUG - for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { - ret = device_create_file(&(pdev->dev), - &device_attrs[i]); - if (ret) - break; - } - - if (ret < 0) - dev_err(&pdev->dev, "failed to add sysfs entries\n"); -#endif - - DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id); - - ippdrv = &ctx->ippdrv; - ippdrv->dev = dev; - ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &gsc_src_ops; - ippdrv->ops[EXYNOS_DRM_OPS_DST] = &gsc_dst_ops; - ippdrv->check_property = gsc_ippdrv_check_property; - ippdrv->reset = gsc_ippdrv_reset; - ippdrv->start = gsc_ippdrv_start; - ippdrv->stop = gsc_ippdrv_stop; - - mutex_init(&ctx->lock); - platform_set_drvdata(pdev, ctx); - - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - - ret = exynos_drm_ippdrv_register(ippdrv); - if (ret < 0) { - dev_err(dev, "failed to register drm gsc device.\n"); - goto err_get_irq; - } - - dev_info(&pdev->dev, "drm gsc registered successfully.\n"); - - return 0; - -err_get_irq: - free_irq(ctx->irq, ctx); -err_get_regs: - iounmap(ctx->regs); -err_req_region: - release_resource(ctx->regs_res); - kfree(ctx->regs_res); -err_clk: - clk_put(ctx->gsc_clk); -err_ctx: - kfree(ctx); - return ret; -} - -static int __devexit gsc_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct gsc_context *ctx = get_gsc_context(dev); - struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - - exynos_drm_ippdrv_unregister(ippdrv); - - pm_runtime_set_suspended(dev); - pm_runtime_disable(dev); - - free_irq(ctx->irq, ctx); - iounmap(ctx->regs); - release_resource(ctx->regs_res); - kfree(ctx->regs_res); - - clk_put(ctx->gsc_clk); - - kfree(ctx); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int gsc_suspend(struct device *dev) -{ - struct gsc_context *ctx = get_gsc_context(dev); - - DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id); - if (pm_runtime_suspended(dev)) - return 0; - /* ToDo */ - return gsc_power_on(ctx, false); -} - -static int gsc_resume(struct device *dev) -{ - struct gsc_context *ctx = get_gsc_context(dev); - - DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id); - if (!pm_runtime_suspended(dev)) - return gsc_power_on(ctx, true); - /* ToDo */ - return 0; -} -#endif - -#ifdef CONFIG_PM_RUNTIME -static int gsc_runtime_suspend(struct device *dev) -{ - struct gsc_context *ctx = get_gsc_context(dev); - - DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id); - /* ToDo */ - return gsc_power_on(ctx, false); -} - -static int gsc_runtime_resume(struct device *dev) -{ - struct gsc_context *ctx = get_gsc_context(dev); - - DRM_DEBUG_KMS("%s:id[%d]\n", __FILE__, ctx->id); - /* ToDo */ - return gsc_power_on(ctx, true); -} -#endif - -static const struct dev_pm_ops gsc_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(gsc_suspend, gsc_resume) - SET_RUNTIME_PM_OPS(gsc_runtime_suspend, gsc_runtime_resume, NULL) -}; - -/* ToDo: need to check use case platform_device_id */ -struct platform_driver gsc_driver = { - .probe = gsc_probe, - .remove = __devexit_p(gsc_remove), - .driver = { - .name = "exynos-drm-gsc", - .owner = THIS_MODULE, - .pm = &gsc_pm_ops, - }, -}; - diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.h b/drivers/gpu/drm/exynos/exynos_drm_gsc.h deleted file mode 100644 index 546089e..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * - * Authors: - * Eunchul Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_GSC_H_ -#define _EXYNOS_DRM_GSC_H_ - -/* ToDo */ - -#endif /* _EXYNOS_DRM_GSC_H_ */ - diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c deleted file mode 100644 index 5d9d2c2..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics Co.Ltd - * Authors: - * Inki Dae - * Seung-Woo Kim - * - * 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 "drmP.h" - -#include -#include -#include -#include -#include - -#include - -#include "exynos_drm_drv.h" -#include "exynos_drm_hdmi.h" - -#define to_context(dev) platform_get_drvdata(to_platform_device(dev)) -#define to_subdrv(dev) to_context(dev) -#define get_ctx_from_subdrv(subdrv) container_of(subdrv,\ - struct drm_hdmi_context, subdrv); - -/* these callback points shoud be set by specific drivers. */ -static struct exynos_hdmi_ops *hdmi_ops; -static struct exynos_mixer_ops *mixer_ops; - -struct drm_hdmi_context { - struct exynos_drm_subdrv subdrv; - struct exynos_drm_hdmi_context *hdmi_ctx; - struct exynos_drm_hdmi_context *mixer_ctx; - - bool enabled[MIXER_WIN_NR]; -}; - -void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (ops) - hdmi_ops = ops; -} - -void exynos_mixer_ops_register(struct exynos_mixer_ops *ops) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (ops) - mixer_ops = ops; -} - -static bool drm_hdmi_is_connected(struct device *dev) -{ - struct drm_hdmi_context *ctx = to_context(dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (hdmi_ops && hdmi_ops->is_connected) - return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx); - - return false; -} - -static int drm_hdmi_get_edid(struct device *dev, - struct drm_connector *connector, u8 *edid, int len) -{ - struct drm_hdmi_context *ctx = to_context(dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (hdmi_ops && hdmi_ops->get_edid) - return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid, - len); - - return 0; -} - -static int drm_hdmi_check_timing(struct device *dev, void *timing) -{ - struct drm_hdmi_context *ctx = to_context(dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (hdmi_ops && hdmi_ops->check_timing) - return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing); - - return 0; -} - -static int drm_hdmi_power_on(struct device *dev, int mode) -{ - struct drm_hdmi_context *ctx = to_context(dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (hdmi_ops && hdmi_ops->power_on) - return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode); - - return 0; -} - -static struct exynos_drm_display_ops drm_hdmi_display_ops = { - .type = EXYNOS_DISPLAY_TYPE_HDMI, - .is_connected = drm_hdmi_is_connected, - .get_edid = drm_hdmi_get_edid, - .check_timing = drm_hdmi_check_timing, - .power_on = drm_hdmi_power_on, -}; - -static int drm_hdmi_enable_vblank(struct device *subdrv_dev) -{ - struct drm_hdmi_context *ctx = to_context(subdrv_dev); - struct exynos_drm_subdrv *subdrv = &ctx->subdrv; - struct exynos_drm_manager *manager = subdrv->manager; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (mixer_ops && mixer_ops->enable_vblank) - return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx, - manager->pipe); - - return 0; -} - -static void drm_hdmi_disable_vblank(struct device *subdrv_dev) -{ - struct drm_hdmi_context *ctx = to_context(subdrv_dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (mixer_ops && mixer_ops->disable_vblank) - return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx); -} - -static void drm_hdmi_mode_fixup(struct device *subdrv_dev, - struct drm_connector *connector, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_hdmi_context *ctx = to_context(subdrv_dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (hdmi_ops && hdmi_ops->mode_fixup) - hdmi_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector, mode, - adjusted_mode); -} - -static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode) -{ - struct drm_hdmi_context *ctx = to_context(subdrv_dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (hdmi_ops && hdmi_ops->mode_set) - hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode); -} - -static void drm_hdmi_get_max_resol(struct device *subdrv_dev, - unsigned int *width, unsigned int *height) -{ - struct drm_hdmi_context *ctx = to_context(subdrv_dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (hdmi_ops && hdmi_ops->get_max_resol) - hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height); -} - -static void drm_hdmi_commit(struct device *subdrv_dev) -{ - struct drm_hdmi_context *ctx = to_context(subdrv_dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (hdmi_ops && hdmi_ops->commit) - hdmi_ops->commit(ctx->hdmi_ctx->ctx); -} - -static void drm_hdmi_dpms(struct device *subdrv_dev, int mode) -{ - struct drm_hdmi_context *ctx = to_context(subdrv_dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (mixer_ops && mixer_ops->dpms) - mixer_ops->dpms(ctx->mixer_ctx->ctx, mode); - - if (hdmi_ops && hdmi_ops->dpms) - hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode); -} - -static void drm_hdmi_apply(struct device *subdrv_dev) -{ - struct drm_hdmi_context *ctx = to_context(subdrv_dev); - int i; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - for (i = 0; i < MIXER_WIN_NR; i++) { - if (!ctx->enabled[i]) - continue; - if (mixer_ops && mixer_ops->win_commit) - mixer_ops->win_commit(ctx->mixer_ctx->ctx, i); - } - - if (hdmi_ops && hdmi_ops->commit) - hdmi_ops->commit(ctx->hdmi_ctx->ctx); -} - -static struct exynos_drm_manager_ops drm_hdmi_manager_ops = { - .dpms = drm_hdmi_dpms, - .apply = drm_hdmi_apply, - .enable_vblank = drm_hdmi_enable_vblank, - .disable_vblank = drm_hdmi_disable_vblank, - .mode_fixup = drm_hdmi_mode_fixup, - .mode_set = drm_hdmi_mode_set, - .get_max_resol = drm_hdmi_get_max_resol, - .commit = drm_hdmi_commit, -}; - -static void drm_mixer_mode_set(struct device *subdrv_dev, - struct exynos_drm_overlay *overlay) -{ - struct drm_hdmi_context *ctx = to_context(subdrv_dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (mixer_ops && mixer_ops->win_mode_set) - mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay); -} - -static void drm_mixer_commit(struct device *subdrv_dev, int zpos) -{ - struct drm_hdmi_context *ctx = to_context(subdrv_dev); - int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (win < 0 || win > MIXER_WIN_NR) { - DRM_ERROR("mixer window[%d] is wrong\n", win); - return; - } - - if (mixer_ops && mixer_ops->win_commit) - mixer_ops->win_commit(ctx->mixer_ctx->ctx, win); - - ctx->enabled[win] = true; -} - -static void drm_mixer_disable(struct device *subdrv_dev, int zpos) -{ - struct drm_hdmi_context *ctx = to_context(subdrv_dev); - int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (win < 0 || win > MIXER_WIN_NR) { - DRM_ERROR("mixer window[%d] is wrong\n", win); - return; - } - - if (mixer_ops && mixer_ops->win_disable) - mixer_ops->win_disable(ctx->mixer_ctx->ctx, win); - - ctx->enabled[win] = false; -} - -static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = { - .mode_set = drm_mixer_mode_set, - .commit = drm_mixer_commit, - .disable = drm_mixer_disable, -}; - -static struct exynos_drm_manager hdmi_manager = { - .pipe = -1, - .ops = &drm_hdmi_manager_ops, - .overlay_ops = &drm_hdmi_overlay_ops, - .display_ops = &drm_hdmi_display_ops, -}; - -static int hdmi_subdrv_probe(struct drm_device *drm_dev, - struct device *dev) -{ - struct exynos_drm_subdrv *subdrv = to_subdrv(dev); - struct drm_hdmi_context *ctx; - struct platform_device *pdev = to_platform_device(dev); - struct exynos_drm_common_hdmi_pd *pd; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - pd = pdev->dev.platform_data; - - if (!pd) { - DRM_DEBUG_KMS("platform data is null.\n"); - return -EFAULT; - } - - if (!pd->hdmi_dev) { - DRM_DEBUG_KMS("hdmi device is null.\n"); - return -EFAULT; - } - - if (!pd->mixer_dev) { - DRM_DEBUG_KMS("mixer device is null.\n"); - return -EFAULT; - } - - ctx = get_ctx_from_subdrv(subdrv); - - ctx->hdmi_ctx = (struct exynos_drm_hdmi_context *) - to_context(pd->hdmi_dev); - if (!ctx->hdmi_ctx) { - DRM_DEBUG_KMS("hdmi context is null.\n"); - return -EFAULT; - } - - ctx->hdmi_ctx->drm_dev = drm_dev; - - ctx->mixer_ctx = (struct exynos_drm_hdmi_context *) - to_context(pd->mixer_dev); - if (!ctx->mixer_ctx) { - DRM_DEBUG_KMS("mixer context is null.\n"); - return -EFAULT; - } - - ctx->mixer_ctx->drm_dev = drm_dev; - - return 0; -} - -static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct exynos_drm_subdrv *subdrv; - struct drm_hdmi_context *ctx; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) { - DRM_LOG_KMS("failed to alloc common hdmi context.\n"); - return -ENOMEM; - } - - subdrv = &ctx->subdrv; - - subdrv->dev = dev; - subdrv->manager = &hdmi_manager; - subdrv->probe = hdmi_subdrv_probe; - - platform_set_drvdata(pdev, subdrv); - - exynos_drm_subdrv_register(subdrv); - - return 0; -} - -static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev) -{ - struct drm_hdmi_context *ctx = platform_get_drvdata(pdev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_drm_subdrv_unregister(&ctx->subdrv); - kfree(ctx); - - return 0; -} - -struct platform_driver exynos_drm_common_hdmi_driver = { - .probe = exynos_drm_hdmi_probe, - .remove = __devexit_p(exynos_drm_hdmi_remove), - .driver = { - .name = "exynos-drm-hdmi", - .owner = THIS_MODULE, - }, -}; diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h deleted file mode 100644 index bd81269..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ /dev/null @@ -1,77 +0,0 @@ -/* exynos_drm_hdmi.h - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authoer: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_HDMI_H_ -#define _EXYNOS_DRM_HDMI_H_ - -#define MIXER_WIN_NR 3 -#define MIXER_DEFAULT_WIN 0 - -/* - * exynos hdmi common context structure. - * - * @drm_dev: pointer to drm_device. - * @ctx: pointer to the context of specific device driver. - * this context should be hdmi_context or mixer_context. - */ -struct exynos_drm_hdmi_context { - struct drm_device *drm_dev; - void *ctx; -}; - -struct exynos_hdmi_ops { - /* display */ - bool (*is_connected)(void *ctx); - int (*get_edid)(void *ctx, struct drm_connector *connector, - u8 *edid, int len); - int (*check_timing)(void *ctx, void *timing); - int (*power_on)(void *ctx, int mode); - - /* manager */ - void (*mode_fixup)(void *ctx, struct drm_connector *connector, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); - void (*mode_set)(void *ctx, void *mode); - void (*get_max_resol)(void *ctx, unsigned int *width, - unsigned int *height); - void (*commit)(void *ctx); - void (*dpms)(void *ctx, int mode); -}; - -struct exynos_mixer_ops { - /* manager */ - int (*enable_vblank)(void *ctx, int pipe); - void (*disable_vblank)(void *ctx); - void (*dpms)(void *ctx, int mode); - - /* overlay */ - void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay); - void (*win_commit)(void *ctx, int zpos); - void (*win_disable)(void *ctx, int zpos); -}; - -void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops); -void exynos_mixer_ops_register(struct exynos_mixer_ops *ops); -#endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.c b/drivers/gpu/drm/exynos/exynos_drm_iommu.c deleted file mode 100644 index b0a8e1c..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_iommu.c +++ /dev/null @@ -1,237 +0,0 @@ -/* exynos_drm_iommu.c - * - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * Author: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm.h" - -#include - -#include - -#include "exynos_drm_drv.h" -#include "exynos_drm_gem.h" -#include "exynos_drm_iommu.h" - -static DEFINE_MUTEX(iommu_mutex); - -struct exynos_iommu_ops { - void *(*setup)(unsigned long s_iova, unsigned long size); - void (*cleanup)(void *in_vmm); - int (*activate)(void *in_vmm, struct device *dev); - void (*deactivate)(void *in_vmm, struct device *dev); - dma_addr_t (*map)(void *in_vmm, struct scatterlist *sg, - off_t offset, size_t size); - void (*unmap)(void *in_vmm, dma_addr_t iova); -}; - -static const struct exynos_iommu_ops iommu_ops = { - .setup = iovmm_setup, - .cleanup = iovmm_cleanup, - .activate = iovmm_activate, - .deactivate = iovmm_deactivate, - .map = iovmm_map, - .unmap = iovmm_unmap -}; - -dma_addr_t exynos_drm_iommu_map_gem(struct drm_device *drm_dev, - struct drm_gem_object *obj) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct exynos_drm_gem_buf *buf; - struct sg_table *sgt; - dma_addr_t dev_addr; - - mutex_lock(&iommu_mutex); - - exynos_gem_obj = to_exynos_gem_obj(obj); - - buf = exynos_gem_obj->buffer; - sgt = buf->sgt; - - /* - * if not using iommu, just return base address to physical - * memory region of the gem. - */ - if (!iommu_ops.map) { - mutex_unlock(&iommu_mutex); - return sg_dma_address(&sgt->sgl[0]); - } - - /* - * if a gem buffer was already mapped with iommu table then - * just return dev_addr; - * - * Note: device address is unique to system globally. - */ - if (buf->dev_addr) { - mutex_unlock(&iommu_mutex); - return buf->dev_addr; - } - - /* - * allocate device address space for this driver and then - * map all pages contained in sg list to iommu table. - */ - dev_addr = iommu_ops.map(exynos_gem_obj->vmm, sgt->sgl, (off_t)0, - (size_t)obj->size); - if (!dev_addr) { - mutex_unlock(&iommu_mutex); - return dev_addr; - } - - mutex_unlock(&iommu_mutex); - - return dev_addr; -} - -void exynos_drm_iommu_unmap_gem(struct drm_gem_object *obj) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct exynos_drm_gem_buf *buf; - - if (!iommu_ops.unmap || !obj) - return; - - exynos_gem_obj = to_exynos_gem_obj(obj); - buf = exynos_gem_obj->buffer; - - /* workaround */ - usleep_range(15000, 20000); - - mutex_lock(&iommu_mutex); - - if (!buf->dev_addr) { - mutex_unlock(&iommu_mutex); - DRM_DEBUG_KMS("not mapped with iommu table.\n"); - return; - } - - if (exynos_gem_obj->vmm) - iommu_ops.unmap(exynos_gem_obj->vmm, buf->dev_addr); - - buf->dev_addr = 0; - mutex_unlock(&iommu_mutex); -} - -dma_addr_t exynos_drm_iommu_map(void *in_vmm, dma_addr_t paddr, - size_t size) -{ - struct sg_table *sgt; - struct scatterlist *sgl; - dma_addr_t dma_addr = 0, tmp_addr; - unsigned int npages, i = 0; - int ret; - - /* if not using iommu, just return paddr. */ - if (!iommu_ops.map) - return paddr; - - npages = size >> PAGE_SHIFT; - - sgt = kzalloc(sizeof(struct sg_table) * npages, GFP_KERNEL); - if (!sgt) { - DRM_ERROR("failed to allocate sg table.\n"); - return dma_addr; - } - - ret = sg_alloc_table(sgt, npages, GFP_KERNEL); - if (ret < 0) { - DRM_ERROR("failed to initialize sg table.\n"); - goto err; - } - - sgl = sgt->sgl; - tmp_addr = paddr; - - while (i < npages) { - struct page *page = phys_to_page(tmp_addr); - sg_set_page(sgl, page, PAGE_SIZE, 0); - sg_dma_len(sgl) = PAGE_SIZE; - tmp_addr += PAGE_SIZE; - i++; - sgl = sg_next(sgl); - } - - /* - * allocate device address space for this driver and then - * map all pages contained in sg list to iommu table. - */ - dma_addr = iommu_ops.map(in_vmm, sgt->sgl, (off_t)0, (size_t)size); - if (!dma_addr) - DRM_ERROR("failed to map cmdlist pool.\n"); - - sg_free_table(sgt); -err: - kfree(sgt); - sgt = NULL; - - return dma_addr; -} - - -void exynos_drm_iommu_unmap(void *in_vmm, dma_addr_t dma_addr) -{ - if (iommu_ops.unmap) - iommu_ops.unmap(in_vmm, dma_addr); -} - -void *exynos_drm_iommu_setup(unsigned long s_iova, unsigned long size) -{ - /* - * allocate device address space to this driver and add vmm object - * to s5p_iovmm_list. please know that each iommu will use - * 1GB as its own device address apace. - * - * the device address space : s_iova ~ s_iova + size - */ - if (iommu_ops.setup) - return iommu_ops.setup(s_iova, size); - - return ERR_PTR(-EINVAL); -} - -int exynos_drm_iommu_activate(void *in_vmm, struct device *dev) -{ - if (iommu_ops.activate) - return iovmm_activate(in_vmm, dev); - - return 0; -} - -void exynos_drm_iommu_deactivate(void *in_vmm, struct device *dev) -{ - if (iommu_ops.deactivate) - iommu_ops.deactivate(in_vmm, dev); -} - -void exynos_drm_iommu_cleanup(void *in_vmm) -{ - if (iommu_ops.cleanup) - iommu_ops.cleanup(in_vmm); -} - -MODULE_AUTHOR("Inki Dae "); -MODULE_DESCRIPTION("Samsung SoC DRM IOMMU Framework"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.h b/drivers/gpu/drm/exynos/exynos_drm_iommu.h deleted file mode 100644 index 35d923d..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_iommu.h +++ /dev/null @@ -1,58 +0,0 @@ -/* exynos_drm_iommu.h - * - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * Authoer: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_IOMMU_H_ -#define _EXYNOS_DRM_IOMMU_H_ - -struct exynos_iommu_gem_data { - unsigned int gem_handle_in; - void *gem_obj_out; -}; - -/* get all pages to gem object and map them to iommu table. */ -dma_addr_t exynos_drm_iommu_map_gem(struct drm_device *drm_dev, - struct drm_gem_object *obj); - -/* unmap device address space to gem object from iommu table. */ -void exynos_drm_iommu_unmap_gem(struct drm_gem_object *obj); - -/* map physical memory region pointed by paddr to iommu table. */ -dma_addr_t exynos_drm_iommu_map(void *in_vmm, dma_addr_t paddr, - size_t size); - -/* unmap device address space pointed by dev_addr from iommu table. */ -void exynos_drm_iommu_unmap(void *in_vmm, dma_addr_t dev_addr); - -/* setup device address space for device iommu. */ -void *exynos_drm_iommu_setup(unsigned long s_iova, unsigned long size); - -int exynos_drm_iommu_activate(void *in_vmm, struct device *dev); - -void exynos_drm_iommu_deactivate(void *in_vmm, struct device *dev); - -/* clean up allocated device address space for device iommu. */ -void exynos_drm_iommu_cleanup(void *in_vmm); - -#endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c deleted file mode 100644 index 0293fbf..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ /dev/null @@ -1,1638 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Authors: - * Eunchul Kim - * - * 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 "drmP.h" -#include "drm_backlight.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include "exynos_drm_drv.h" -#include "exynos_drm_gem.h" -#include "exynos_drm_iommu.h" -#include "exynos_drm_ipp.h" - -/* - * IPP is stand for Image Post Processing and - * supports image scaler/rotator and input/output DMA operations. - * using FIMC, GSC, Rotator, so on. - * IPP is integration device driver of same attribute h/w - */ - -#define get_ipp_context(dev) platform_get_drvdata(to_platform_device(dev)) - -/* - * A structure of event. - * - * @base: base of event. - * @event: ipp event. - */ -struct drm_exynos_ipp_send_event { - struct drm_pending_event base; - struct drm_exynos_ipp_event event; -}; - -/* - * A structure of command node. - * - * @list: list head to command queue information. - * @mem_list: list head to source,destination memory queue information. - * @property: property information. - */ -struct drm_exynos_ipp_cmd_node { - struct list_head list; - struct list_head mem_list[EXYNOS_DRM_OPS_MAX]; - struct drm_exynos_ipp_property property; -}; - -/* - * A structure of memory node. - * - * @list: list head to memory queue information. - * @ops_id: id of operations. - * @prop_id: id of property. - * @buf_id: id of buffer. - * @buf_info: gem objects and dma address, size. - */ -struct drm_exynos_ipp_mem_node { - struct list_head list; - enum drm_exynos_ops_id ops_id; - u32 prop_id; - u32 buf_id; - struct drm_exynos_ipp_buf_info buf_info; -}; - -/* - * A structure of ipp context. - * - * @subdrv: prepare initialization using subdrv. - * @lock: locking of operations. - * @ipp_idr: ipp driver idr. - * @sched_event: schdule event list - * @sched_cmd: schdule command list - */ -struct ipp_context { - struct exynos_drm_subdrv subdrv; - struct mutex lock; - struct idr ipp_idr; - struct work_struct sched_event; - struct work_struct sched_cmd; -}; - -static LIST_HEAD(exynos_drm_ippdrv_list); -static BLOCKING_NOTIFIER_HEAD(exynos_drm_ippnb_list); - -int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv) -{ - DRM_DEBUG_KMS("%s\n", __func__); - - if (!ippdrv) - return -EINVAL; - - list_add_tail(&ippdrv->list, &exynos_drm_ippdrv_list); - - return 0; -} -EXPORT_SYMBOL_GPL(exynos_drm_ippdrv_register); - -int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv) -{ - DRM_DEBUG_KMS("%s\n", __func__); - - if (!ippdrv) - return -EINVAL; - - list_del(&ippdrv->list); - - return 0; -} -EXPORT_SYMBOL_GPL(exynos_drm_ippdrv_unregister); - -int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data, - struct drm_file *file) -{ - struct exynos_drm_ippdrv *ippdrv; - - DRM_DEBUG_KMS("%s\n", __func__); - - /* get ipp driver entry */ - list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, list) { - /* check idle state and dedicated state */ - if (ippdrv->state == IPP_STATE_START && - ippdrv->dedicated) - continue; - - /* ToDo: get property */ - DRM_DEBUG_KMS("%s:ipp_id[%d]\n", __func__, ippdrv->ipp_id); - - return 0; - } - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(exynos_drm_ipp_get_property); - -static int ipp_create_id(struct idr *id_idr, void *obj, u32 *idp) -{ - int ret = -EINVAL; - - /* ToDo: need spin_lock ? */ - -again: - /* ensure there is space available to allocate a handle */ - if (idr_pre_get(id_idr, GFP_KERNEL) == 0) - return -ENOMEM; - - ret = idr_get_new_above(id_idr, obj, 1, (int *)idp); - if (ret == -EAGAIN) - goto again; - - return ret; -} - -static void *ipp_find_id(struct idr *id_idr, u32 id) -{ - void *obj; - - /* ToDo: need spin_lock ? */ - - /* find object using handle */ - obj = idr_find(id_idr, id); - if (obj == NULL) - return NULL; - - return obj; -} - -static struct exynos_drm_ippdrv - *ipp_find_driver(struct ipp_context *ctx, - struct drm_exynos_ipp_property *property) -{ - struct exynos_drm_ippdrv *ippdrv; - u32 ipp_id = property->ipp_id; - - DRM_DEBUG_KMS("%s:ipp_id[%d]\n", __func__, ipp_id); - - if (ipp_id) { - /* find ipp driver */ - ippdrv = ipp_find_id(&ctx->ipp_idr, ippdrv->ipp_id); - if (!ippdrv) { - DRM_ERROR("not found ipp%d driver.\n", ipp_id); - return NULL; - } - - /* check idle state and dedicated state */ - if (ippdrv->state == IPP_STATE_START && - ippdrv->dedicated) { - DRM_ERROR("used choose device.\n"); - return NULL; - } - - /* check property */ - if (ippdrv->check_property && - ippdrv->check_property(ippdrv->dev, property)) { - DRM_ERROR("not support property.\n"); - return NULL; - } - - return ippdrv; - } else { - /* get ipp driver entry */ - list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, list) { - /* check idle state and dedicated state */ - if (ippdrv->state == IPP_STATE_IDLE && - ippdrv->dedicated) - continue; - - /* check property */ - if (ippdrv->check_property && - ippdrv->check_property(ippdrv->dev, property)) { - DRM_DEBUG_KMS("not support property.\n"); - continue; - } - - return ippdrv; - } - - DRM_ERROR("not support ipp driver operations.\n"); - } - - return NULL; -} - -int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data, - struct drm_file *file) -{ - struct drm_exynos_file_private *file_priv = file->driver_priv; - struct exynos_drm_ipp_private *priv = file_priv->ipp_priv; - struct device *dev = priv->dev; - struct ipp_context *ctx = get_ipp_context(dev); - struct exynos_drm_ippdrv *ippdrv; - struct drm_exynos_ipp_cmd_node *c_node; - struct drm_exynos_ipp_property *property = data; - int ret, i; - - DRM_DEBUG_KMS("%s\n", __func__); - - if (!ctx) { - DRM_ERROR("invalid context.\n"); - return -EINVAL; - } - - if (!property) { - DRM_ERROR("invalid property parameter.\n"); - return -EINVAL; - } - - /* find ipp driver using ipp id */ - ippdrv = ipp_find_driver(ctx, property); - if (!ippdrv) { - DRM_ERROR("failed to get ipp driver.\n"); - return -EINVAL; - } - - /* allocate command node */ - c_node = kzalloc(sizeof(*c_node), GFP_KERNEL); - if (!c_node) { - DRM_ERROR("failed to allocate map node.\n"); - return -ENOMEM; - } - - /* create property id */ - ret = ipp_create_id(&ippdrv->prop_idr, c_node, &property->prop_id); - if (ret) { - DRM_ERROR("failed to create id.\n"); - goto err_clear; - } - - DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id); - - /* stored property information and ippdrv in private data */ - c_node->property = *property; - for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) - INIT_LIST_HEAD(&c_node->mem_list[i]); - - /* make dedicated state without m2m */ - if (property->cmd != IPP_CMD_M2M) - ippdrv->dedicated = true; - priv->ippdrv = ippdrv; - - list_add_tail(&c_node->list, &ippdrv->cmd_list); - - return 0; - -err_clear: - kfree(c_node); - - return ret; -} -EXPORT_SYMBOL_GPL(exynos_drm_ipp_set_property); - -static struct drm_exynos_ipp_cmd_node - *ipp_find_cmd_node(struct exynos_drm_ippdrv *ippdrv, u32 prop_id) -{ - struct drm_exynos_ipp_cmd_node *c_node; - - DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id); - - /* ToDo: same with find_cmd_node and find_id */ - - /* find ipp driver */ - c_node = ipp_find_id(&ippdrv->prop_idr, prop_id); - if (!c_node) { - DRM_ERROR("not found property%d.\n", prop_id); - return NULL; - } - - return c_node; -} - -static struct drm_exynos_ipp_mem_node - *ipp_find_mem_node(struct drm_exynos_ipp_cmd_node *c_node, - struct drm_exynos_ipp_buf *buf) -{ - struct drm_exynos_ipp_mem_node *m_node; - int count = 0; - - DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf->buf_id); - - /* find memory node entry */ - list_for_each_entry(m_node, &c_node->mem_list[buf->ops_id], list) { - DRM_DEBUG_KMS("%s:count[%d]c_node[0x%x]\n", - __func__, count++, (int)c_node); - - /* compare buffer id */ - if (m_node->buf_id == buf->buf_id) - return m_node; - } - - return NULL; -} - -static struct drm_exynos_ipp_property - *ipp_find_property(struct exynos_drm_ippdrv *ippdrv, u32 prop_id) -{ - struct drm_exynos_ipp_property *property; - struct drm_exynos_ipp_cmd_node *c_node; - int count = 0; - - DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id); - - /* find command node entry */ - list_for_each_entry(c_node, &ippdrv->cmd_list, list) { - DRM_DEBUG_KMS("%s:count[%d]c_node[0x%x]\n", - __func__, count++, (int)c_node); - - property = &c_node->property; - /* compare property id */ - if (property->prop_id == prop_id) - return property; - } - - return NULL; -} - -static int ipp_set_property(struct exynos_drm_ippdrv *ippdrv, - struct drm_exynos_ipp_property *property) -{ - struct exynos_drm_ipp_ops *ops = NULL; - int ret, i, swap = 0; - - if (!property) { - DRM_ERROR("invalid property parameter.\n"); - return -EINVAL; - } - - DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id); - - /* reset h/w block */ - if (ippdrv->reset && - ippdrv->reset(ippdrv->dev)) { - DRM_ERROR("failed to reset.\n"); - return -EINVAL; - } - - /* set source,destination operations */ - for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) { - /* ToDo: integrate property and config */ - struct drm_exynos_ipp_config *config = - &property->config[i]; - - ops = ippdrv->ops[i]; - if (!ops || !config) { - DRM_ERROR("not support ops and config.\n"); - return -EINVAL; - } - - /* set format */ - if (ops->set_fmt) { - ret = ops->set_fmt(ippdrv->dev, config->fmt); - if (ret) { - DRM_ERROR("not support format.\n"); - return ret; - } - } - - /* set transform for rotation, flip */ - if (ops->set_transf) { - swap = ops->set_transf(ippdrv->dev, config->degree, - config->flip); - if (swap < 0) { - DRM_ERROR("not support tranf.\n"); - return -EINVAL; - } - } - - /* set size */ - if (ops->set_size) { - ret = ops->set_size(ippdrv->dev, swap, &config->pos, - &config->sz); - if (ret) { - DRM_ERROR("not support size.\n"); - return ret; - } - } - } - - return 0; -} - -static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv, - struct drm_exynos_ipp_mem_node *node) -{ - struct exynos_drm_ipp_ops *ops = NULL; - int ret; - - DRM_DEBUG_KMS("%s:node[0x%x]\n", __func__, (int)node); - - if (!node) { - DRM_ERROR("invalid queue node.\n"); - ret = -EFAULT; - return ret; - } - - DRM_DEBUG_KMS("%s:ops_id[%d]\n", __func__, node->ops_id); - - /* get operations callback */ - ops = ippdrv->ops[node->ops_id]; - if (!ops) { - DRM_DEBUG_KMS("not support ops.\n"); - ret = -EIO; - return ret; - } - - /* set address and enable irq */ - if (ops->set_addr) { - ret = ops->set_addr(ippdrv->dev, &node->buf_info, - node->buf_id, IPP_BUF_CTRL_QUEUE); - if (ret) { - if (ret != -ENOMEM) - DRM_ERROR("failed to set addr.\n"); - return ret; - } - } - - return 0; -} - -static int ipp_free_mem_node(struct drm_device *drm_dev, - struct exynos_drm_ippdrv *ippdrv, - struct drm_exynos_ipp_mem_node *node) -{ - int ret, i; - - DRM_DEBUG_KMS("%s:node[0x%x]\n", __func__, (int)node); - - if (!node) { - DRM_ERROR("invalid queue node.\n"); - ret = -EFAULT; - return ret; - } - - DRM_DEBUG_KMS("%s:ops_id[%d]\n", __func__, node->ops_id); - - /* put gem buffer */ - for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) { - void *gem_obj = node->buf_info.gem_objs[i]; - - if (gem_obj) - exynos_drm_gem_put_dma_addr(drm_dev, gem_obj); - } - - /* delete list in queue */ - list_del(&node->list); - kfree(node); - - return 0; -} - -/* ToDo: Merge with stop property */ -static void ipp_free_cmd_list(struct drm_device *drm_dev, - struct exynos_drm_ippdrv *ippdrv) -{ - struct drm_exynos_ipp_cmd_node *c_node, *tc_node; - struct drm_exynos_ipp_mem_node *m_node, *tm_node; - struct list_head *head; - int ret, i, count = 0; - - /* get command node entry */ - list_for_each_entry_safe(c_node, tc_node, - &ippdrv->cmd_list, list) { - DRM_DEBUG_KMS("%s:count[%d]c_node[0x%x]\n", - __func__, count++, (int)c_node); - - for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) { - /* source/destination memory list */ - head = &c_node->mem_list[i]; - - /* get memory node entry */ - list_for_each_entry_safe(m_node, tm_node, head, list) { - /* free memory node to ippdrv */ - ret = ipp_free_mem_node(drm_dev, ippdrv, - m_node); - if (ret) - DRM_ERROR("failed to free m node.\n"); - } - } - - /* delete list */ - list_del(&c_node->list); - kfree(c_node); - } - - return; -} - -static int ipp_start_property(struct drm_device *drm_dev, - struct exynos_drm_ippdrv *ippdrv, u32 prop_id) -{ - struct drm_exynos_ipp_cmd_node *c_node; - struct drm_exynos_ipp_mem_node *m_node, tm_node; - struct drm_exynos_ipp_property *property; - struct list_head *head; - int ret, i; - - DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id); - - /* find command node */ - c_node = ipp_find_cmd_node(ippdrv, prop_id); - if (!c_node) { - DRM_ERROR("invalid command node list.\n"); - return -EINVAL; - } - - /* get property */ - property = &c_node->property; - if (property->prop_id != prop_id) { - DRM_ERROR("invalid property id.\n"); - return -EINVAL; - } - - /* set current property in ippdrv */ - ippdrv->property = property; - ret = ipp_set_property(ippdrv, property); - if (ret) { - DRM_ERROR("failed to set property.\n"); - ippdrv->property = NULL; - return ret; - } - - /* check command type */ - switch (property->cmd) { - case IPP_CMD_M2M: - for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) { - /* source/destination memory list */ - head = &c_node->mem_list[i]; - - if (list_empty(head)) { - DRM_DEBUG_KMS("bypass empty list.\n"); - return 0; - } - - /* get first entry */ - m_node = list_first_entry(head, - struct drm_exynos_ipp_mem_node, list); - if (!m_node) { - DRM_DEBUG_KMS("failed to get node.\n"); - ret = -EFAULT; - return ret; - } - - DRM_DEBUG_KMS("%s:m_node[0x%x]\n", - __func__, (int)m_node); - - /* must be set 0 src buffer id in m2m */ - if (i == EXYNOS_DRM_OPS_SRC) { - tm_node = *m_node; - tm_node.buf_id = 0; - m_node = &tm_node; - } - - /* set memory node to ippdrv */ - ret = ipp_set_mem_node(ippdrv, m_node); - if (ret) { - DRM_ERROR("failed to set m node.\n"); - return ret; - } - } - break; - case IPP_CMD_WB: - /* destination memory list */ - head = &c_node->mem_list[EXYNOS_DRM_OPS_DST]; - - /* get list entry */ - list_for_each_entry(m_node, head, list) { - /* set memory node to ippdrv */ - ret = ipp_set_mem_node(ippdrv, m_node); - if (ret) { - DRM_ERROR("failed to set m node.\n"); - return ret; - } - } - break; - case IPP_CMD_OUTPUT: - /* source memory list */ - head = &c_node->mem_list[EXYNOS_DRM_OPS_SRC]; - - /* get list entry */ - list_for_each_entry(m_node, head, list) { - /* set memory node to ippdrv */ - ret = ipp_set_mem_node(ippdrv, m_node); - if (ret) { - DRM_ERROR("failed to set m node.\n"); - return ret; - } - } - break; - default: - DRM_ERROR("invalid operations.\n"); - ret = -EINVAL; - return ret; - } - - /* start operations */ - if (ippdrv->start) { - ret = ippdrv->start(ippdrv->dev, property->cmd); - if (ret) { - DRM_ERROR("failed to start ops.\n"); - return ret; - } - } - - return 0; -} - -static int ipp_stop_property(struct drm_device *drm_dev, - struct exynos_drm_ippdrv *ippdrv, u32 prop_id) -{ - struct drm_exynos_ipp_cmd_node *c_node; - struct drm_exynos_ipp_mem_node *m_node, *tm_node; - struct drm_exynos_ipp_property *property; - enum drm_exynos_ipp_cmd cmd; - struct list_head *head; - int ret, i; - - DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id); - - /* find command node */ - c_node = ipp_find_cmd_node(ippdrv, prop_id); - if (!c_node) { - DRM_ERROR("invalid command node list.\n"); - return -EINVAL; - } - - /* get property */ - property = &c_node->property; - if (property->prop_id != prop_id) { - DRM_ERROR("invalid property id.\n"); - return -EINVAL; - } - - /* copy current command for memory list */ - cmd = property->cmd; - - /* stop operations */ - if (ippdrv->stop) - ippdrv->stop(ippdrv->dev, property->cmd); - - /* check command type */ - switch (property->cmd) { - case IPP_CMD_M2M: - for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) { - /* source/destination memory list */ - head = &c_node->mem_list[i]; - - /* get list entry */ - list_for_each_entry_safe(m_node, tm_node, - head, list) { - /* free memory node to ippdrv */ - ret = ipp_free_mem_node(drm_dev, ippdrv, - m_node); - if (ret) { - DRM_ERROR("failed to free m node.\n"); - return ret; - } - } - } - break; - case IPP_CMD_WB: - /* destination memory list */ - head = &c_node->mem_list[EXYNOS_DRM_OPS_DST]; - - /* get list entry */ - list_for_each_entry_safe(m_node, tm_node, head, list) { - /* free memory node to ippdrv */ - ret = ipp_free_mem_node(drm_dev, ippdrv, m_node); - if (ret) { - DRM_ERROR("failed to free m node.\n"); - return ret; - } - } - break; - case IPP_CMD_OUTPUT: - /* source memory list */ - head = &c_node->mem_list[EXYNOS_DRM_OPS_SRC]; - - /* get list entry */ - list_for_each_entry_safe(m_node, tm_node, head, list) { - /* free memory node to ippdrv */ - ret = ipp_free_mem_node(drm_dev, ippdrv, m_node); - if (ret) { - DRM_ERROR("failed to free m node.\n"); - return ret; - } - } - break; - default: - DRM_ERROR("invalid operations.\n"); - ret = -EINVAL; - return ret; - } - - /* delete list */ - list_del(&c_node->list); - kfree(c_node); - - return 0; -} - -static void ipp_free_event(struct drm_pending_event *event) -{ - kfree(event); -} - -static int ipp_make_event(struct drm_device *drm_dev, struct drm_file *file, - struct exynos_drm_ippdrv *ippdrv, struct drm_exynos_ipp_buf *buf) -{ - struct drm_exynos_ipp_send_event *e; - unsigned long flags; - - DRM_DEBUG_KMS("%s:ops_id[%d]buf_id[%d]\n", __func__, - buf->ops_id, buf->buf_id); - - e = kzalloc(sizeof(*e), GFP_KERNEL); - if (!e) { - DRM_ERROR("failed to allocate event.\n"); - - spin_lock_irqsave(&drm_dev->event_lock, flags); - file->event_space += sizeof(e->event); - spin_unlock_irqrestore(&drm_dev->event_lock, flags); - return -ENOMEM; - } - - DRM_DEBUG_KMS("%s:e[0x%x]\n", __func__, (int)e); - - /* make event */ - e->event.base.type = DRM_EXYNOS_IPP_EVENT; - e->event.base.length = sizeof(e->event); - e->event.user_data = buf->user_data; - e->event.buf_id[EXYNOS_DRM_OPS_DST] = buf->buf_id; - e->base.event = &e->event.base; - e->base.file_priv = file; - e->base.destroy = ipp_free_event; - - list_add_tail(&e->base.link, &ippdrv->event_list); - - return 0; -} - -static struct drm_exynos_ipp_mem_node - *ipp_make_mem_node(struct drm_device *drm_dev, - struct drm_file *file, - struct exynos_drm_ippdrv *ippdrv, - struct drm_exynos_ipp_buf *buf) -{ - struct drm_exynos_ipp_cmd_node *c_node; - struct drm_exynos_ipp_mem_node *m_node; - struct drm_exynos_ipp_buf_info buf_info; - void *addr; - unsigned long size; - int i; - - m_node = kzalloc(sizeof(*m_node), GFP_KERNEL); - if (!m_node) { - DRM_ERROR("failed to allocate queue node.\n"); - return NULL; - } - - /* clear base address for error handling */ - memset(&buf_info, 0x0, sizeof(buf_info)); - - /* find command node */ - c_node = ipp_find_cmd_node(ippdrv, buf->prop_id); - if (!c_node) { - DRM_ERROR("failed to get command node.\n"); - goto err_clear; - } - - /* operations, buffer id */ - m_node->ops_id = buf->ops_id; - m_node->prop_id = buf->prop_id; - m_node->buf_id = buf->buf_id; - - DRM_DEBUG_KMS("%s:m_node[0x%x]ops_id[%d]\n", __func__, - (int)m_node, buf->ops_id); - DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]\n", __func__, - buf->prop_id, m_node->buf_id); - - for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) { - unsigned int gem_obj; - - DRM_DEBUG_KMS("%s:i[%d]handle[0x%x]\n", __func__, - i, buf->handle[i]); - - /* get dma address by handle */ - if (buf->handle[i] != 0) { - addr = exynos_drm_gem_get_dma_addr(drm_dev, - buf->handle[i], file, &gem_obj); - if (!addr) { - DRM_ERROR("failed to get addr.\n"); - goto err_clear; - } - - size = exynos_drm_gem_get_size(drm_dev, - buf->handle[i], file); - if (!size) { - DRM_ERROR("failed to get size.\n"); - goto err_clear; - } - - buf_info.gem_objs[i] = (void *)gem_obj; - buf_info.base[i] = *(dma_addr_t *) addr; - buf_info.size[i] = (uint64_t) size; - } - } - - m_node->buf_info = buf_info; - list_add_tail(&m_node->list, &c_node->mem_list[buf->ops_id]); - - return m_node; - -err_clear: - kfree(m_node); - - return NULL; -} - -int exynos_drm_ipp_buf(struct drm_device *drm_dev, void *data, - struct drm_file *file) -{ - struct drm_exynos_file_private *file_priv = file->driver_priv; - struct exynos_drm_ipp_private *priv = file_priv->ipp_priv; - struct exynos_drm_ippdrv *ippdrv = priv->ippdrv; - struct drm_exynos_ipp_buf *buf = data; - struct exynos_drm_ipp_ops *ops = NULL; - struct drm_exynos_ipp_send_event *e, *te; - struct drm_exynos_ipp_cmd_node *c_node; - struct drm_exynos_ipp_mem_node *m_node = NULL, *tm_node; - struct drm_exynos_ipp_property *property; - struct drm_exynos_ipp_buf_info buf_info; - struct list_head *head; - int ret, i; - - DRM_DEBUG_KMS("%s\n", __func__); - - if (!buf) { - DRM_ERROR("invalid buf parameter.\n"); - return -EINVAL; - } - - if (!ippdrv) { - DRM_ERROR("failed to get ipp driver.\n"); - return -EINVAL; - } - - if (buf->ops_id >= EXYNOS_DRM_OPS_MAX) { - DRM_ERROR("invalid ops parameter.\n"); - return -EINVAL; - } - - ops = ippdrv->ops[buf->ops_id]; - if (!ops) { - DRM_ERROR("failed to get ops.\n"); - return -EINVAL; - } - - DRM_DEBUG_KMS("%s:ops_id[%s]buf_id[%d]buf_ctrl[%d]\n", - __func__, buf->ops_id ? "dst" : "src", - buf->buf_id, buf->buf_ctrl); - - /* clear base address for error handling */ - memset(&buf_info, 0x0, sizeof(buf_info)); - - /* find command node */ - c_node = ipp_find_cmd_node(ippdrv, buf->prop_id); - if (!c_node) { - DRM_ERROR("failed to get command node.\n"); - ret = -EINVAL; - goto err_clear; - } - - /* get property */ - property = &c_node->property; - if (!property) { - DRM_ERROR("invalid property parameter.\n"); - goto err_clear; - } - - /* buffer control */ - switch (buf->buf_ctrl) { - case IPP_BUF_CTRL_QUEUE: - /* make memory node */ - m_node = ipp_make_mem_node(drm_dev, file, ippdrv, buf); - if (!m_node) { - DRM_ERROR("failed to make queue node.\n"); - ret = -EINVAL; - goto err_clear; - } - - buf_info = m_node->buf_info; - - if (pm_runtime_suspended(ippdrv->dev)) - break; - - /* set address */ - if (property->cmd != IPP_CMD_M2M && ops->set_addr) { - ret = ops->set_addr(ippdrv->dev, &buf_info, buf->buf_id, - buf->buf_ctrl); - if (ret) { - DRM_ERROR("failed to set addr.\n"); - goto err_clear; - } - } - break; - case IPP_BUF_CTRL_DEQUEUE: - /* free node */ - list_for_each_entry_safe(m_node, tm_node, - &c_node->mem_list[buf->ops_id], list) { - if (m_node->buf_id == buf->buf_id && - m_node->ops_id == buf->ops_id) { - /* free memory node to ippdrv */ - ret = ipp_free_mem_node(drm_dev, ippdrv, - m_node); - if (ret) { - DRM_ERROR("failed to free m node.\n"); - goto err_clear; - } - } - } - - if (pm_runtime_suspended(ippdrv->dev)) { - DRM_ERROR("suspended:invalid operations.\n"); - ret = -EINVAL; - goto err_clear; - } - - /* clear address */ - if (ops->set_addr) { - ret = ops->set_addr(ippdrv->dev, &buf_info, buf->buf_id, - buf->buf_ctrl); - if (ret) { - DRM_ERROR("failed to set addr.\n"); - goto err_clear; - } - } - break; - default: - DRM_ERROR("invalid buffer control.\n"); - return -EINVAL; - } - - /* destination buffer need event control */ - if (buf->ops_id == EXYNOS_DRM_OPS_DST) { - switch (buf->buf_ctrl) { - case IPP_BUF_CTRL_QUEUE: - /* make event */ - ret = ipp_make_event(drm_dev, file, ippdrv, buf); - if (ret) { - DRM_ERROR("failed to make event.\n"); - goto err_clear; - } - break; - case IPP_BUF_CTRL_DEQUEUE: - /* free event */ - list_for_each_entry_safe(e, te, - &ippdrv->event_list, base.link) { - if (e->event.buf_id[EXYNOS_DRM_OPS_DST] == - buf->buf_id) { - /* delete list */ - list_del(&e->base.link); - kfree(e); - } - } - break; - default: - /* no action */ - break; - } - } - - /* - * If set source, destination buffer and enable pm - * m2m operations need start operations in queue - */ - if (property->cmd == IPP_CMD_M2M) { - /* start operations was not set */ - if (pm_runtime_suspended(ippdrv->dev)) { - DRM_DEBUG_KMS("suspended state.\n"); - return 0; - } - - /* check source/destination buffer status */ - for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) { - /* source/destination memory list */ - head = &c_node->mem_list[i]; - - /* check list empty */ - if (list_empty(head)) { - DRM_DEBUG_KMS("list empty.\n"); - return 0; - } - } - - /* check property id and buffer property id */ - if (property->prop_id != buf->prop_id) { - DRM_ERROR("invalid property id.\n"); - goto err_clear; - } - - /* start property */ - ret = ipp_start_property(drm_dev, ippdrv, property->prop_id); - if (ret) { - DRM_ERROR("failed to start property.\n"); - goto err_clear; - } - } - - return 0; - -err_clear: - DRM_ERROR("%s:failed to set buf.\n", __func__); - - /* delete list */ - list_for_each_entry_safe(m_node, tm_node, - &c_node->mem_list[buf->ops_id], list) { - if (m_node->buf_id == buf->buf_id && - m_node->ops_id == buf->ops_id) { - list_del(&m_node->list); - kfree(m_node); - } - } - - /* put gem buffer */ - for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) { - void *gem_obj = buf_info.gem_objs[i]; - - if (gem_obj) - exynos_drm_gem_put_dma_addr(drm_dev, - gem_obj); - } - - /* free address */ - switch (buf->buf_ctrl) { - case IPP_BUF_CTRL_QUEUE: - case IPP_BUF_CTRL_DEQUEUE: - if (pm_runtime_suspended(ippdrv->dev)) { - DRM_ERROR("suspended:invalid error operations.\n"); - return -EINVAL; - } - - /* clear base address for error handling */ - memset(&buf_info, 0x0, sizeof(buf_info)); - - /* don't need check error case */ - if (ops->set_addr) - ops->set_addr(ippdrv->dev, &buf_info, - buf->buf_id, IPP_BUF_CTRL_DEQUEUE); - break; - default: - /* no action */ - break; - } - - return ret; -} -EXPORT_SYMBOL_GPL(exynos_drm_ipp_buf); - -int exynos_drm_ipp_ctrl(struct drm_device *drm_dev, void *data, - struct drm_file *file) -{ - struct drm_exynos_file_private *file_priv = file->driver_priv; - struct exynos_drm_ipp_private *priv = file_priv->ipp_priv; - struct exynos_drm_ippdrv *ippdrv = priv->ippdrv; - struct drm_exynos_ipp_ctrl *ctrl = data; - int ret; - - DRM_DEBUG_KMS("%s\n", __func__); - - if (!ctrl) { - DRM_ERROR("invalid control parameter.\n"); - return -EINVAL; - } - - if (!ippdrv) { - DRM_ERROR("failed to get ipp driver.\n"); - return -EINVAL; - } - - DRM_DEBUG_KMS("%s:use[%d]\n", __func__, ctrl->use); - - /* ToDo: expand ctrl operation */ - - /* - * start/stop operations, - * set use to 1, you can use start operations - * other case is stop opertions - */ - if (ctrl->use) { - if (pm_runtime_suspended(ippdrv->dev)) - pm_runtime_get_sync(ippdrv->dev); - - ret = ipp_start_property(drm_dev, ippdrv, ctrl->prop_id); - if (ret) { - DRM_ERROR("failed to start property.\n"); - goto err_clear; - } - - ippdrv->state = IPP_STATE_START; - } else { - ippdrv->state = IPP_STATE_STOP; - ippdrv->dedicated = false; - ippdrv->property = NULL; - - ret = ipp_stop_property(drm_dev, ippdrv, ctrl->prop_id); - if (ret) { - DRM_ERROR("failed to stop property.\n"); - goto err_clear; - } - - if (!pm_runtime_suspended(ippdrv->dev)) - pm_runtime_put_sync(ippdrv->dev); - } - - return 0; - -err_clear: - /* - * ToDo: register clear if needed - * If failed choose device using property. then - * revert register clearing if needed - */ - - return ret; -} -EXPORT_SYMBOL_GPL(exynos_drm_ipp_ctrl); - -int exynos_drm_ippnb_register(struct notifier_block *nb) -{ - return blocking_notifier_chain_register( - &exynos_drm_ippnb_list, nb); -} -EXPORT_SYMBOL_GPL(exynos_drm_ippnb_register); - -int exynos_drm_ippnb_unregister(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister( - &exynos_drm_ippnb_list, nb); -} -EXPORT_SYMBOL_GPL(exynos_drm_ippnb_unregister); - -int exynos_drm_ippnb_send_event(unsigned long val, void *v) -{ - return blocking_notifier_call_chain( - &exynos_drm_ippnb_list, val, v); -} -EXPORT_SYMBOL_GPL(exynos_drm_ippnb_send_event); - -void ipp_send_event_handler(struct exynos_drm_ippdrv *ippdrv, - int buf_id) -{ - struct drm_device *drm_dev = ippdrv->drm_dev; - struct drm_exynos_ipp_property *property = ippdrv->property; - struct drm_exynos_ipp_cmd_node *c_node; - struct drm_exynos_ipp_mem_node *m_node; - struct drm_exynos_ipp_buf buf; - struct drm_exynos_ipp_send_event *e; - struct list_head *head; - struct timeval now; - unsigned long flags; - u32 q_buf_id[EXYNOS_DRM_OPS_MAX] = {0, }; - int ret, i; - - DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id); - - if (!drm_dev) { - DRM_ERROR("failed to get drm_dev.\n"); - return; - } - - if (list_empty(&ippdrv->event_list)) { - DRM_ERROR("event list is empty.\n"); - return; - } - - if (!property) { - DRM_ERROR("failed to get property.\n"); - return; - } - - /* find command node */ - c_node = ipp_find_cmd_node(ippdrv, property->prop_id); - if (!c_node) { - DRM_ERROR("invalid command node list.\n"); - return; - } - - /* check command type */ - switch (property->cmd) { - case IPP_CMD_M2M: - for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) { - /* source/destination memory list */ - head = &c_node->mem_list[i]; - - if (list_empty(head)) { - DRM_ERROR("empty list.\n"); - return; - } - - /* get first entry */ - m_node = list_first_entry(head, - struct drm_exynos_ipp_mem_node, list); - if (!m_node) { - DRM_ERROR("empty list.\n"); - return; - } - - q_buf_id[i] = m_node->buf_id; - - /* free memory node to ippdrv */ - ret = ipp_free_mem_node(drm_dev, ippdrv, m_node); - if (ret) - DRM_ERROR("failed to free m node.\n"); - } - break; - case IPP_CMD_WB: - /* clear buf for finding */ - memset(&buf, 0x0, sizeof(buf)); - buf.ops_id = EXYNOS_DRM_OPS_DST; - buf.buf_id = buf_id; - - /* get memory node entry */ - m_node = ipp_find_mem_node(c_node, &buf); - if (!m_node) { - DRM_ERROR("empty list.\n"); - return; - } - - q_buf_id[EXYNOS_DRM_OPS_DST] = m_node->buf_id; - - /* free memory node to ippdrv */ - ret = ipp_free_mem_node(drm_dev, ippdrv, m_node); - if (ret) - DRM_ERROR("failed to free m node.\n"); - break; - case IPP_CMD_OUTPUT: - /* source memory list */ - head = &c_node->mem_list[EXYNOS_DRM_OPS_SRC]; - - /* get first entry */ - m_node = list_first_entry(head, - struct drm_exynos_ipp_mem_node, list); - if (!m_node) { - DRM_ERROR("empty list.\n"); - return; - } - - q_buf_id[EXYNOS_DRM_OPS_SRC] = m_node->buf_id; - - /* free memory node to ippdrv */ - ret = ipp_free_mem_node(drm_dev, ippdrv, m_node); - if (ret) - DRM_ERROR("failed to free m node.\n"); - break; - default: - DRM_ERROR("invalid operations.\n"); - return; - } - - /* ToDo: Fix buffer id */ - if (q_buf_id[EXYNOS_DRM_OPS_DST] != buf_id) - DRM_ERROR("failed to match buffer id %d, %d.\n", - q_buf_id[EXYNOS_DRM_OPS_DST], buf_id); - - /* get first event entry */ - e = list_first_entry(&ippdrv->event_list, - struct drm_exynos_ipp_send_event, base.link); - - do_gettimeofday(&now); - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; - e->event.prop_id = property->prop_id; - - /* set buffer id about source destination */ - for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) { - /* ToDo: compare index. If needed */ - e->event.buf_id[i] = q_buf_id[i]; - } - - spin_lock_irqsave(&drm_dev->event_lock, flags); - list_move_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); - spin_unlock_irqrestore(&drm_dev->event_lock, flags); - - /* ToDo: Need to handle the property queue */ - - switch (property->cmd) { - case IPP_CMD_M2M: - for (i = 0; i < EXYNOS_DRM_OPS_MAX; i++) { - head = &c_node->mem_list[i]; - if (list_empty(head)) - return; - } - - ret = ipp_start_property(drm_dev, ippdrv, property->prop_id); - if (ret) { - DRM_ERROR("failed to start property.\n"); - return; - } - break; - case IPP_CMD_WB: - case IPP_CMD_OUTPUT: - default: - break; - } - - DRM_DEBUG_KMS("%s:finish cmd[%d]\n", __func__, property->cmd); -} - -static void ipp_sched_event(struct work_struct *sched_event) -{ - struct ipp_context *ctx = container_of(sched_event, - struct ipp_context, sched_event); - - DRM_DEBUG_KMS("%s\n", __func__); - /* ToDo:send event handler */ -} - -static void ipp_sched_cmd(struct work_struct *sched_cmd) -{ - struct ipp_context *ctx = container_of(sched_cmd, - struct ipp_context, sched_cmd); - - DRM_DEBUG_KMS("%s\n", __func__); - /* ToDo: schedule next work */ -} - -static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev) -{ - struct exynos_drm_ippdrv *ippdrv; - struct exynos_drm_private *drm_priv = drm_dev->dev_private; - int ret; - - DRM_DEBUG_KMS("%s\n", __func__); - - /* get ipp driver entry */ - list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, list) { - ippdrv->drm_dev = drm_dev; - - /* ToDo: need move open ? */ - - /* init prop idr */ - idr_init(&ippdrv->prop_idr); - - /* check iommu use case */ - if (ippdrv->iommu_used) { - ret = exynos_drm_iommu_activate(drm_priv->vmm, - ippdrv->dev); - if (ret) { - DRM_ERROR("failed to activate iommu\n"); - goto err_clear; - } - } - } - - return 0; - -err_clear: - /* get ipp driver entry */ - list_for_each_entry_reverse(ippdrv, &exynos_drm_ippdrv_list, list) - if ((ippdrv->iommu_used) && (drm_priv->vmm)) - exynos_drm_iommu_deactivate(drm_priv->vmm, ippdrv->dev); - - return ret; -} - -static void ipp_subdrv_remove(struct drm_device *drm_dev, struct device *dev) -{ - struct exynos_drm_ippdrv *ippdrv; - struct exynos_drm_private *drm_priv = drm_dev->dev_private; - - DRM_DEBUG_KMS("%s\n", __func__); - - /* get ipp driver entry */ - list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, list) { - - /* ToDo: need move close ? */ - - /* remove,destroy property idr */ - idr_remove_all(&ippdrv->prop_idr); - idr_destroy(&ippdrv->prop_idr); - - if (drm_priv->vmm) - exynos_drm_iommu_deactivate(drm_priv->vmm, ippdrv->dev); - - ippdrv->drm_dev = NULL; - exynos_drm_ippdrv_unregister(ippdrv); - } - - /* ToDo: free notifier callback list if needed */ -} - -static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev, - struct drm_file *file) -{ - struct drm_exynos_file_private *file_priv = file->driver_priv; - struct exynos_drm_ipp_private *priv; - struct exynos_drm_ippdrv *ippdrv; - int count = 0; - - DRM_DEBUG_KMS("%s\n", __func__); - - /* ToDo: multi device open */ - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - DRM_ERROR("failed to allocate priv.\n"); - return -ENOMEM; - } - - priv->dev = dev; - file_priv->ipp_priv = priv; - INIT_LIST_HEAD(&priv->event_list); - - /* get ipp driver entry */ - list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, list) { - DRM_DEBUG_KMS("%s:count[%d]ippdrv[0x%x]\n", __func__, - count++, (int)ippdrv); - - /* check idle state */ - if (ippdrv->state != IPP_STATE_IDLE) - continue; - - INIT_LIST_HEAD(&ippdrv->event_list); - INIT_LIST_HEAD(&ippdrv->cmd_list); - list_splice_init(&priv->event_list, &ippdrv->event_list); - } - - return 0; -} - -static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev, - struct drm_file *file) -{ - struct drm_exynos_file_private *file_priv = file->driver_priv; - struct exynos_drm_ipp_private *priv = file_priv->ipp_priv; - struct exynos_drm_ippdrv *ippdrv_cur = priv->ippdrv; - struct exynos_drm_ippdrv *ippdrv; - struct drm_exynos_ipp_send_event *e, *te; - int count; - - DRM_DEBUG_KMS("%s\n", __func__); - - /* ToDo: for multi device close */ - - /* get ipp driver entry */ - list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, list) { - DRM_DEBUG_KMS("%s:ippdrv_cur[0x%x]ippdrv[0x%x]\n", - __func__, (int)ippdrv_cur, (int)ippdrv); - - DRM_DEBUG_KMS("%s:state[%d]dedicated[%d]\n", __func__, - ippdrv->state, ippdrv->dedicated); - - /* current used ippdrv stop needed */ - if (ippdrv_cur && ippdrv_cur == ippdrv) { - if (ippdrv->state == IPP_STATE_START) { - if (ippdrv->stop) - ippdrv->stop(ippdrv->dev, ippdrv->cmd); - - if (!pm_runtime_suspended(ippdrv->dev)) - pm_runtime_put_sync(ippdrv->dev); - } - - ippdrv->state = IPP_STATE_IDLE; - ippdrv->dedicated = false; - } - - /* check idle state */ - if (ippdrv->state != IPP_STATE_IDLE) - continue; - - /* free event */ - count = 0; - list_for_each_entry_safe(e, te, - &ippdrv->event_list, base.link) { - DRM_DEBUG_KMS("%s:count[%d]e[0x%x]\n", - __func__, count++, (int)e); - - /* delete list */ - list_del(&e->base.link); - kfree(e); - } - - /* free property list */ - ipp_free_cmd_list(drm_dev, ippdrv); - /* ToDo: How can get current fd property ? */ - } - - kfree(file_priv->ipp_priv); - - return; -} - -static int __devinit ipp_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct ipp_context *ctx; - struct exynos_drm_subdrv *subdrv; - struct exynos_drm_ippdrv *tippdrv; - int ret = -EINVAL; - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - DRM_DEBUG_KMS("%s\n", __func__); - - /* init ioctl lock */ - mutex_init(&ctx->lock); - /* init event, cmd work thread */ - INIT_WORK(&ctx->sched_event, ipp_sched_event); - INIT_WORK(&ctx->sched_cmd, ipp_sched_cmd); - /* init ipp driver idr */ - idr_init(&ctx->ipp_idr); - - /* get ipp driver entry */ - list_for_each_entry(tippdrv, &exynos_drm_ippdrv_list, list) { - /* create ipp id */ - ret = ipp_create_id(&ctx->ipp_idr, tippdrv, &tippdrv->ipp_id); - if (ret) { - DRM_ERROR("failed to create id.\n"); - goto err_clear; - } - - DRM_DEBUG_KMS("%s:ipp_id[%d]\n", __func__, tippdrv->ipp_id); - - if (tippdrv->ipp_id == 0) - DRM_ERROR("failed to get ipp_id[%d]\n", - tippdrv->ipp_id); - } - - /* set sub driver informations */ - subdrv = &ctx->subdrv; - subdrv->dev = dev; - subdrv->probe = ipp_subdrv_probe; - subdrv->remove = ipp_subdrv_remove; - subdrv->open = ipp_subdrv_open; - subdrv->close = ipp_subdrv_close; - - /* set driver data */ - platform_set_drvdata(pdev, ctx); - - /* register sub driver */ - ret = exynos_drm_subdrv_register(subdrv); - if (ret < 0) { - DRM_ERROR("failed to register drm ipp device.\n"); - goto err_clear; - } - - dev_info(&pdev->dev, "drm ipp registered successfully.\n"); - - return 0; - -err_clear: - kfree(ctx); - - return ret; -} - -static int __devexit ipp_remove(struct platform_device *pdev) -{ - struct ipp_context *ctx = platform_get_drvdata(pdev); - - DRM_DEBUG_KMS("%s\n", __func__); - - /* unregister sub driver */ - exynos_drm_subdrv_unregister(&ctx->subdrv); - - /* remove,destroy ipp idr */ - idr_remove_all(&ctx->ipp_idr); - idr_destroy(&ctx->ipp_idr); - - kfree(ctx); - - return 0; -} - - -struct platform_driver ipp_driver = { - .probe = ipp_probe, - .remove = __devexit_p(ipp_remove), - .driver = { - .name = "exynos-drm-ipp", - .owner = THIS_MODULE, - }, -}; - diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.h b/drivers/gpu/drm/exynos/exynos_drm_ipp.h deleted file mode 100644 index 458f747..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * - * Authors: - * Eunchul Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_IPP_H_ -#define _EXYNOS_DRM_IPP_H_ - -#define IPP_GET_LCD_WIDTH _IOR('F', 302, int) -#define IPP_GET_LCD_HEIGHT _IOR('F', 303, int) -#define IPP_SET_WRITEBACK _IOW('F', 304, u32) - -/* definition of state */ -enum drm_exynos_ipp_state { - IPP_STATE_IDLE, - IPP_STATE_START, - IPP_STATE_STOP, -}; - -/* - * A structure of buffer information. - * - * @gem_objs: Y, Cb, Cr each gem object. - * @base: Y, Cb, Cr each planar address. - * @size: Y, Cb, Cr each planar size. - */ -struct drm_exynos_ipp_buf_info { - void *gem_objs[EXYNOS_DRM_PLANAR_MAX]; - dma_addr_t base[EXYNOS_DRM_PLANAR_MAX]; - uint64_t size[EXYNOS_DRM_PLANAR_MAX]; -}; - -/* - * A structure of source,destination operations. - * - * @set_fmt: set format of image. - * @set_transf: set transform(rotations, flip). - * @set_size: set size of region. - * @set_addr: set address for dma. - */ -struct exynos_drm_ipp_ops { - int (*set_fmt)(struct device *dev, u32 fmt); - int (*set_transf)(struct device *dev, - enum drm_exynos_degree degree, - enum drm_exynos_flip flip); - int (*set_size)(struct device *dev, int swap, - struct drm_exynos_pos *pos, struct drm_exynos_sz *sz); - int (*set_addr)(struct device *dev, - struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id, - enum drm_exynos_ipp_buf_ctrl buf_ctrl); -}; - -/* - * A structure of ipp driver. - * - * @list: list head. - * @dev: platform device. - * @drm_dev: drm device. - * @state: state of ipp drivers. - * @ipp_id: id of ipp driver. - * @dedicated: dedicated ipp device. - * @iommu_used: iommu used status. - * @cmd: used command. - * @ops: source, destination operations. - * @property: current property. - * @prop_idr: property idr. - * @cmd_list: list head to command information. - * @event_list: list head to event information. - * @reset: reset ipp block. - * @check_property: check property about format, size, buffer. - * @start: ipp each device start. - * @stop: ipp each device stop. - */ -struct exynos_drm_ippdrv { - struct list_head list; - struct device *dev; - struct drm_device *drm_dev; - enum drm_exynos_ipp_state state; - u32 ipp_id; - bool dedicated; - bool iommu_used; - enum drm_exynos_ipp_cmd cmd; - struct exynos_drm_ipp_ops *ops[EXYNOS_DRM_OPS_MAX]; - struct drm_exynos_ipp_property *property; - struct idr prop_idr; - struct list_head cmd_list; - struct list_head event_list; - - int (*check_property)(struct device *dev, - struct drm_exynos_ipp_property *property); - int (*reset)(struct device *dev); - int (*start)(struct device *dev, enum drm_exynos_ipp_cmd cmd); - void (*stop)(struct device *dev, enum drm_exynos_ipp_cmd cmd); -}; - -#ifdef CONFIG_DRM_EXYNOS_IPP -extern int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv); -extern int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv); -extern int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data, - struct drm_file *file); -extern int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data, - struct drm_file *file); -extern int exynos_drm_ipp_buf(struct drm_device *drm_dev, void *data, - struct drm_file *file); -extern int exynos_drm_ipp_ctrl(struct drm_device *drm_dev, void *data, - struct drm_file *file); -extern int exynos_drm_ippnb_register(struct notifier_block *nb); -extern int exynos_drm_ippnb_unregister(struct notifier_block *nb); -extern int exynos_drm_ippnb_send_event(unsigned long val, void *v); -#else -static inline int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv) -{ - return -ENODEV; -} - -static inline int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv) -{ - return -ENODEV; -} - -static inline int exynos_drm_ipp_get_property(struct drm_device *drm_dev, - void *data, - struct drm_file *file_priv) -{ - return -ENOTTY; -} - -static inline int exynos_drm_ipp_set_property(struct drm_device *drm_dev, - void *data, - struct drm_file *file_priv) -{ - return -ENOTTY; -} - -static inline int exynos_drm_ipp_buf(struct drm_device *drm_dev, - void *data, - struct drm_file *file) -{ - return -ENOTTY; -} - -static inline int exynos_drm_ipp_ctrl(struct drm_device *drm_dev, - void *data, - struct drm_file *file) -{ - return -ENOTTY; -} - -static inline int exynos_drm_ippnb_register(struct notifier_block *nb) -{ - return -ENODEV; -} - -static inline int exynos_drm_ippnb_unregister(struct notifier_block *nb) -{ - return -ENODEV; -} - -static inline int exynos_drm_ippnb_send_event(unsigned long val, void *v) -{ - return -ENOTTY; -} -#endif - -/* ToDo: Must be change to queue_work */ -void ipp_send_event_handler(struct exynos_drm_ippdrv *ippdrv, - int buf_idx); - -#endif /* _EXYNOS_DRM_IPP_H_ */ - diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c deleted file mode 100644 index b89829e..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics Co.Ltd - * Authors: Joonyoung Shim - * - * 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 "drmP.h" - -#include "exynos_drm.h" -#include "exynos_drm_drv.h" -#include "exynos_drm_encoder.h" -#include "exynos_drm_fb.h" -#include "exynos_drm_gem.h" - -#define to_exynos_plane(x) container_of(x, struct exynos_plane, base) - -struct exynos_plane { - struct drm_plane base; - struct exynos_drm_overlay overlay; - bool enabled; -}; - -static const uint32_t formats[] = { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_ARGB8888, - DRM_FORMAT_NV12, - DRM_FORMAT_NV12M, - DRM_FORMAT_NV12MT, -}; - -int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) -{ - struct exynos_plane *exynos_plane = to_exynos_plane(plane); - struct exynos_drm_overlay *overlay = &exynos_plane->overlay; - unsigned int actual_w; - unsigned int actual_h; - int nr; - int i; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - nr = exynos_drm_format_num_buffers(fb->pixel_format); - for (i = 0; i < nr; i++) { - struct exynos_drm_gem_buf *buffer = exynos_drm_fb_buffer(fb, i); - - if (!buffer) { - DRM_LOG_KMS("buffer is null\n"); - return -EFAULT; - } - - overlay->dma_addr[i] = buffer->dma_addr; - overlay->vaddr[i] = buffer->kvaddr; - - DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n", - i, (unsigned long)overlay->vaddr[i], - (unsigned long)overlay->dma_addr[i]); - } - - actual_w = min((unsigned)(crtc->mode.hdisplay - crtc_x), crtc_w); - actual_h = min((unsigned)(crtc->mode.vdisplay - crtc_y), crtc_h); - - /* set drm framebuffer data. */ - overlay->fb_x = src_x; - overlay->fb_y = src_y; - overlay->fb_width = fb->width; - overlay->fb_height = fb->height; - overlay->src_width = src_w; - overlay->src_height = src_h; - overlay->bpp = fb->bits_per_pixel; - overlay->pitch = fb->pitches[0]; - overlay->pixel_format = fb->pixel_format; - - /* set overlay range to be displayed. */ - overlay->crtc_x = crtc_x; - overlay->crtc_y = crtc_y; - overlay->crtc_width = actual_w; - overlay->crtc_height = actual_h; - - /* set drm mode data. */ - overlay->mode_width = crtc->mode.hdisplay; - overlay->mode_height = crtc->mode.vdisplay; - overlay->refresh = crtc->mode.vrefresh; - overlay->scan_flag = crtc->mode.flags; - - DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)", - overlay->crtc_x, overlay->crtc_y, - overlay->crtc_width, overlay->crtc_height); - - exynos_drm_fn_encoder(crtc, overlay, exynos_drm_encoder_plane_mode_set); - - return 0; -} - -void exynos_plane_commit(struct drm_plane *plane) -{ - struct exynos_plane *exynos_plane = to_exynos_plane(plane); - struct exynos_drm_overlay *overlay = &exynos_plane->overlay; - - exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, - exynos_drm_encoder_plane_commit); -} - -void exynos_plane_dpms(struct drm_plane *plane, int mode) -{ - struct exynos_plane *exynos_plane = to_exynos_plane(plane); - struct exynos_drm_overlay *overlay = &exynos_plane->overlay; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - if (mode == DRM_MODE_DPMS_ON) { - if (exynos_plane->enabled) - return; - - exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, - exynos_drm_encoder_plane_enable); - - exynos_plane->enabled = true; - } else { - if (!exynos_plane->enabled) - return; - - exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, - exynos_drm_encoder_plane_disable); - - exynos_plane->enabled = false; - } -} - -static int -exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) -{ - int ret; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - ret = exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, - crtc_w, crtc_h, src_x >> 16, src_y >> 16, - src_w >> 16, src_h >> 16); - if (ret < 0) - return ret; - - plane->crtc = crtc; - plane->fb = crtc->fb; - - exynos_plane_commit(plane); - exynos_plane_dpms(plane, DRM_MODE_DPMS_ON); - - return 0; -} - -static int exynos_disable_plane(struct drm_plane *plane) -{ - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - exynos_plane_dpms(plane, DRM_MODE_DPMS_OFF); - - return 0; -} - -static void exynos_plane_destroy(struct drm_plane *plane) -{ - struct exynos_plane *exynos_plane = to_exynos_plane(plane); - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - exynos_disable_plane(plane); - drm_plane_cleanup(plane); - kfree(exynos_plane); -} - -static int exynos_plane_set_property(struct drm_plane *plane, - struct drm_property *property, - uint64_t val) -{ - struct drm_device *dev = plane->dev; - struct exynos_plane *exynos_plane = to_exynos_plane(plane); - struct exynos_drm_private *dev_priv = dev->dev_private; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - if (property == dev_priv->plane_zpos_property) { - exynos_plane->overlay.zpos = val; - return 0; - } - - return -EINVAL; -} - -static struct drm_plane_funcs exynos_plane_funcs = { - .update_plane = exynos_update_plane, - .disable_plane = exynos_disable_plane, - .destroy = exynos_plane_destroy, - .set_property = exynos_plane_set_property, -}; - -static void exynos_plane_attach_zpos_property(struct drm_plane *plane) -{ - struct drm_device *dev = plane->dev; - struct exynos_drm_private *dev_priv = dev->dev_private; - struct drm_property *prop; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - prop = dev_priv->plane_zpos_property; - if (!prop) { - prop = drm_property_create_range(dev, 0, "zpos", 0, - MAX_PLANE - 1); - if (!prop) - return; - - dev_priv->plane_zpos_property = prop; - } - - drm_object_attach_property(&plane->base, prop, 0); -} - -struct drm_plane *exynos_plane_init(struct drm_device *dev, - unsigned int possible_crtcs, bool priv) -{ - struct exynos_plane *exynos_plane; - int err; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL); - if (!exynos_plane) { - DRM_ERROR("failed to allocate plane\n"); - return NULL; - } - - err = drm_plane_init(dev, &exynos_plane->base, possible_crtcs, - &exynos_plane_funcs, formats, ARRAY_SIZE(formats), - priv); - if (err) { - DRM_ERROR("failed to initialize plane\n"); - kfree(exynos_plane); - return NULL; - } - - if (priv) - exynos_plane->overlay.zpos = DEFAULT_ZPOS; - else - exynos_plane_attach_zpos_property(&exynos_plane->base); - - return &exynos_plane->base; -} diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h deleted file mode 100644 index 8831245..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics Co.Ltd - * Authors: Joonyoung Shim - * - * 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. - * - */ - -int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h); -void exynos_plane_commit(struct drm_plane *plane); -void exynos_plane_dpms(struct drm_plane *plane, int mode); -struct drm_plane *exynos_plane_init(struct drm_device *dev, - unsigned int possible_crtcs, bool priv); diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c deleted file mode 100644 index 9e40790..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ /dev/null @@ -1,879 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Authors: YoungJun Cho - * - * 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 Foundationr - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "drmP.h" -#include "exynos_drm.h" -#include "exynos_drm_drv.h" -#include "exynos_drm_iommu.h" -#include "exynos_drm_ipp.h" - -/* Configuration */ -#define ROT_CONFIG 0x00 -#define ROT_CONFIG_IRQ (3 << 8) - -/* Image Control */ -#define ROT_CONTROL 0x10 -#define ROT_CONTROL_PATTERN_WRITE (1 << 16) -#define ROT_CONTROL_FMT_YCBCR420_2P (1 << 8) -#define ROT_CONTROL_FMT_RGB888 (6 << 8) -#define ROT_CONTROL_FMT_MASK (7 << 8) -#define ROT_CONTROL_FLIP_VERTICAL (2 << 6) -#define ROT_CONTROL_FLIP_HORIZONTAL (3 << 6) -#define ROT_CONTROL_FLIP_MASK (3 << 6) -#define ROT_CONTROL_ROT_90 (1 << 4) -#define ROT_CONTROL_ROT_180 (2 << 4) -#define ROT_CONTROL_ROT_270 (3 << 4) -#define ROT_CONTROL_ROT_MASK (3 << 4) -#define ROT_CONTROL_START (1 << 0) - -/* Status */ -#define ROT_STATUS 0x20 -#define ROT_STATUS_IRQ_PENDING(x) (1 << (x)) -#define ROT_STATUS_IRQ(x) (((x) >> 8) & 0x3) -#define ROT_STATUS_IRQ_VAL_COMPLETE 1 -#define ROT_STATUS_IRQ_VAL_ILLEGAL 2 - -/* Buffer Address */ -#define ROT_SRC_BUF_ADDR(n) (0x30 + ((n) << 2)) -#define ROT_DST_BUF_ADDR(n) (0x50 + ((n) << 2)) - -/* Buffer Size */ -#define ROT_SRC_BUF_SIZE 0x3c -#define ROT_DST_BUF_SIZE 0x5c -#define ROT_SET_BUF_SIZE_H(x) ((x) << 16) -#define ROT_SET_BUF_SIZE_W(x) ((x) << 0) -#define ROT_GET_BUF_SIZE_H(x) ((x) >> 16) -#define ROT_GET_BUF_SIZE_W(x) ((x) & 0xffff) - -/* Crop Position */ -#define ROT_SRC_CROP_POS 0x40 -#define ROT_DST_CROP_POS 0x60 -#define ROT_CROP_POS_Y(x) ((x) << 16) -#define ROT_CROP_POS_X(x) ((x) << 0) - -/* Source Crop Size */ -#define ROT_SRC_CROP_SIZE 0x44 -#define ROT_SRC_CROP_SIZE_H(x) ((x) << 16) -#define ROT_SRC_CROP_SIZE_W(x) ((x) << 0) - -/* Round to nearest aligned value */ -#define ROT_ALIGN(x, align, mask) (((x) + (1 << ((align) - 1))) & (mask)) -/* Minimum limit value */ -#define ROT_MIN(min, mask) (((min) + ~(mask)) & (mask)) -/* Maximum limit value */ -#define ROT_MAX(max, mask) ((max) & (mask)) - -enum rot_irq_status { - ROT_IRQ_STATUS_COMPLETE = 8, - ROT_IRQ_STATUS_ILLEGAL = 9, -}; - -struct rot_limit { - u32 min_w; - u32 min_h; - u32 max_w; - u32 max_h; - u32 align; -}; - -struct rot_limit_table { - struct rot_limit ycbcr420_2p; - struct rot_limit rgb888; -}; - -struct rot_context { - struct rot_limit_table *limit_tbl; - struct clk *clock; - struct resource *regs_res; - void __iomem *regs; - int irq; - struct exynos_drm_ippdrv ippdrv; - int cur_buf_id[EXYNOS_DRM_OPS_MAX]; - bool suspended; -}; - -static void rotator_reg_set_irq(struct rot_context *rot, bool enable) -{ - u32 value = readl(rot->regs + ROT_CONFIG); - - if (enable == true) - value |= ROT_CONFIG_IRQ; - else - value &= ~ROT_CONFIG_IRQ; - - writel(value, rot->regs + ROT_CONFIG); -} - -static u32 rotator_reg_get_format(struct rot_context *rot) -{ - u32 value = readl(rot->regs + ROT_CONTROL); - value &= ROT_CONTROL_FMT_MASK; - - return value; -} - -static void rotator_reg_set_format(struct rot_context *rot, u32 img_fmt) -{ - u32 value = readl(rot->regs + ROT_CONTROL); - value &= ~ROT_CONTROL_FMT_MASK; - - switch (img_fmt) { - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12M: - value |= ROT_CONTROL_FMT_YCBCR420_2P; - break; - case DRM_FORMAT_XRGB8888: - value |= ROT_CONTROL_FMT_RGB888; - break; - default: - DRM_ERROR("invalid image format\n"); - return; - } - - writel(value, rot->regs + ROT_CONTROL); -} - -static void rotator_reg_set_flip(struct rot_context *rot, - enum drm_exynos_flip flip) -{ - u32 value = readl(rot->regs + ROT_CONTROL); - value &= ~ROT_CONTROL_FLIP_MASK; - - switch (flip) { - case EXYNOS_DRM_FLIP_VERTICAL: - value |= ROT_CONTROL_FLIP_VERTICAL; - break; - case EXYNOS_DRM_FLIP_HORIZONTAL: - value |= ROT_CONTROL_FLIP_HORIZONTAL; - break; - default: - /* Flip None */ - break; - } - - writel(value, rot->regs + ROT_CONTROL); -} - -static void rotator_reg_set_rotation(struct rot_context *rot, - enum drm_exynos_degree degree) -{ - u32 value = readl(rot->regs + ROT_CONTROL); - value &= ~ROT_CONTROL_ROT_MASK; - - switch (degree) { - case EXYNOS_DRM_DEGREE_90: - value |= ROT_CONTROL_ROT_90; - break; - case EXYNOS_DRM_DEGREE_180: - value |= ROT_CONTROL_ROT_180; - break; - case EXYNOS_DRM_DEGREE_270: - value |= ROT_CONTROL_ROT_270; - break; - default: - /* Rotation 0 Degree */ - break; - } - - writel(value, rot->regs + ROT_CONTROL); -} - -static void rotator_reg_set_start(struct rot_context *rot) -{ - u32 value = readl(rot->regs + ROT_CONTROL); - - value |= ROT_CONTROL_START; - - writel(value, rot->regs + ROT_CONTROL); -} - -static enum rot_irq_status rotator_reg_get_irq_status(struct rot_context *rot) -{ - u32 value = readl(rot->regs + ROT_STATUS); - value = ROT_STATUS_IRQ(value); - - if (value == ROT_STATUS_IRQ_VAL_COMPLETE) - return ROT_IRQ_STATUS_COMPLETE; - else - return ROT_IRQ_STATUS_ILLEGAL; -} - -static void rotator_reg_set_irq_status_clear(struct rot_context *rot, - enum rot_irq_status status) -{ - u32 value = readl(rot->regs + ROT_STATUS); - - value |= ROT_STATUS_IRQ_PENDING((u32)status); - - writel(value, rot->regs + ROT_STATUS); -} - -static void rotator_reg_set_src_buf_addr(struct rot_context *rot, - dma_addr_t addr, int i) -{ - writel(addr, rot->regs + ROT_SRC_BUF_ADDR(i)); -} - -static void rotator_reg_get_src_buf_size(struct rot_context *rot, u32 *w, - u32 *h) -{ - u32 value = readl(rot->regs + ROT_SRC_BUF_SIZE); - - *w = ROT_GET_BUF_SIZE_W(value); - *h = ROT_GET_BUF_SIZE_H(value); -} - -static void rotator_reg_set_src_buf_size(struct rot_context *rot, u32 w, u32 h) -{ - u32 value = ROT_SET_BUF_SIZE_H(h) | ROT_SET_BUF_SIZE_W(w); - - writel(value, rot->regs + ROT_SRC_BUF_SIZE); -} - -static void rotator_reg_set_src_crop_pos(struct rot_context *rot, u32 x, u32 y) -{ - u32 value = ROT_CROP_POS_Y(y) | ROT_CROP_POS_X(x); - - writel(value, rot->regs + ROT_SRC_CROP_POS); -} - -static void rotator_reg_set_src_crop_size(struct rot_context *rot, u32 w, u32 h) -{ - u32 value = ROT_SRC_CROP_SIZE_H(h) | ROT_SRC_CROP_SIZE_W(w); - - writel(value, rot->regs + ROT_SRC_CROP_SIZE); -} - -static void rotator_reg_set_dst_buf_addr(struct rot_context *rot, - dma_addr_t addr, int i) -{ - writel(addr, rot->regs + ROT_DST_BUF_ADDR(i)); -} - -static void rotator_reg_get_dst_buf_size(struct rot_context *rot, u32 *w, - u32 *h) -{ - u32 value = readl(rot->regs + ROT_DST_BUF_SIZE); - - *w = ROT_GET_BUF_SIZE_W(value); - *h = ROT_GET_BUF_SIZE_H(value); -} - -static void rotator_reg_set_dst_buf_size(struct rot_context *rot, u32 w, u32 h) -{ - u32 value = ROT_SET_BUF_SIZE_H(h) | ROT_SET_BUF_SIZE_W(w); - - writel(value, rot->regs + ROT_DST_BUF_SIZE); -} - -static void rotator_reg_set_dst_crop_pos(struct rot_context *rot, u32 x, u32 y) -{ - u32 value = ROT_CROP_POS_Y(y) | ROT_CROP_POS_X(x); - - writel(value, rot->regs + ROT_DST_CROP_POS); -} - -static void rotator_reg_get_dump(struct rot_context *rot) -{ - u32 value, i; - - for (i = 0; i <= ROT_DST_CROP_POS; i += 0x4) { - value = readl(rot->regs + i); - DRM_INFO("[%s] [0x%x] : 0x%x\n", __func__, i, value); - } -} - -static irqreturn_t rotator_irq_handler(int irq, void *arg) -{ - struct rot_context *rot = arg; - struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv; - enum rot_irq_status irq_status; - - /* Get execution result */ - irq_status = rotator_reg_get_irq_status(rot); - rotator_reg_set_irq_status_clear(rot, irq_status); - - if (irq_status == ROT_IRQ_STATUS_COMPLETE) - ipp_send_event_handler(ippdrv, - rot->cur_buf_id[EXYNOS_DRM_OPS_DST]); - else { - DRM_ERROR("the SFR is set illegally\n"); - rotator_reg_get_dump(rot); - } - - return IRQ_HANDLED; -} - -static void rotator_align_size(struct rot_context *rot, u32 fmt, u32 *hsize, - u32 *vsize) -{ - struct rot_limit_table *limit_tbl = rot->limit_tbl; - struct rot_limit *limit; - u32 mask, value; - - /* Get size limit */ - if (fmt == ROT_CONTROL_FMT_RGB888) - limit = &limit_tbl->rgb888; - else - limit = &limit_tbl->ycbcr420_2p; - - /* Get mask for rounding to nearest aligned value */ - mask = ~((1 << limit->align) - 1); - - /* Set aligned width */ - value = ROT_ALIGN(*hsize, limit->align, mask); - if (value < limit->min_w) - *hsize = ROT_MIN(limit->min_w, mask); - else if (value > limit->max_w) - *hsize = ROT_MAX(limit->max_w, mask); - else - *hsize = value; - - /* Set aligned height */ - value = ROT_ALIGN(*vsize, limit->align, mask); - if (value < limit->min_h) - *vsize = ROT_MIN(limit->min_h, mask); - else if (value > limit->max_h) - *vsize = ROT_MAX(limit->max_h, mask); - else - *vsize = value; -} - -static int rotator_src_set_fmt(struct device *dev, u32 fmt) -{ - struct rot_context *rot = dev_get_drvdata(dev); - - /* Set format configuration */ - rotator_reg_set_format(rot, fmt); - - return 0; -} - -static int rotator_src_set_size(struct device *dev, int swap, - struct drm_exynos_pos *pos, - struct drm_exynos_sz *sz) -{ - struct rot_context *rot = dev_get_drvdata(dev); - u32 fmt, hsize, vsize; - - /* Get format */ - fmt = rotator_reg_get_format(rot); - - /* Align buffer size */ - hsize = sz->hsize; - vsize = sz->vsize; - rotator_align_size(rot, fmt, &hsize, &vsize); - - /* Set buffer size configuration */ - rotator_reg_set_src_buf_size(rot, hsize, vsize); - - /* Set crop image position configuration */ - rotator_reg_set_src_crop_pos(rot, pos->x, pos->y); - rotator_reg_set_src_crop_size(rot, pos->w, pos->h); - - return 0; -} - -static int rotator_src_set_addr(struct device *dev, - struct drm_exynos_ipp_buf_info *buf_info, - u32 buf_id, enum drm_exynos_ipp_buf_ctrl ctrl) -{ - struct rot_context *rot = dev_get_drvdata(dev); - dma_addr_t addr[EXYNOS_DRM_PLANAR_MAX]; - u32 fmt, hsize, vsize; - int i; - - /* Set current buf_id */ - rot->cur_buf_id[EXYNOS_DRM_OPS_SRC] = buf_id; - - switch (ctrl) { - case IPP_BUF_CTRL_QUEUE: - /* Set address configuration */ - for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) - addr[i] = buf_info->base[i]; - - /* Get format */ - fmt = rotator_reg_get_format(rot); - - /* Re-set cb planar for NV12 format */ - if ((fmt == ROT_CONTROL_FMT_YCBCR420_2P) && - (addr[EXYNOS_DRM_PLANAR_CB] == 0x00)) { - /* Get buf size */ - rotator_reg_get_src_buf_size(rot, &hsize, &vsize); - - /* Set cb planar */ - addr[EXYNOS_DRM_PLANAR_CB] = - addr[EXYNOS_DRM_PLANAR_Y] + hsize * vsize; - } - - for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) - rotator_reg_set_src_buf_addr(rot, addr[i], i); - break; - case IPP_BUF_CTRL_DEQUEUE: - for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) - rotator_reg_set_src_buf_addr(rot, buf_info->base[i], i); - break; - default: - /* Nothing to do */ - break; - } - - return 0; -} - -static int rotator_dst_set_transf(struct device *dev, - enum drm_exynos_degree degree, - enum drm_exynos_flip flip) -{ - struct rot_context *rot = dev_get_drvdata(dev); - - /* Set transform configuration */ - rotator_reg_set_flip(rot, flip); - rotator_reg_set_rotation(rot, degree); - - /* Check degree for setting buffer size swap */ - if ((degree == EXYNOS_DRM_DEGREE_90) || - (degree == EXYNOS_DRM_DEGREE_270)) - return 1; - else - return 0; -} - -static int rotator_dst_set_size(struct device *dev, int swap, - struct drm_exynos_pos *pos, - struct drm_exynos_sz *sz) -{ - struct rot_context *rot = dev_get_drvdata(dev); - u32 fmt, hsize, vsize; - - /* Get format */ - fmt = rotator_reg_get_format(rot); - - /* Align buffer size */ - hsize = sz->hsize; - vsize = sz->vsize; - rotator_align_size(rot, fmt, &hsize, &vsize); - - /* Set buffer size configuration */ - rotator_reg_set_dst_buf_size(rot, hsize, vsize); - - /* Set crop image position configuration */ - rotator_reg_set_dst_crop_pos(rot, pos->x, pos->y); - - return 0; -} - -static int rotator_dst_set_addr(struct device *dev, - struct drm_exynos_ipp_buf_info *buf_info, - u32 buf_id, enum drm_exynos_ipp_buf_ctrl ctrl) -{ - struct rot_context *rot = dev_get_drvdata(dev); - dma_addr_t addr[EXYNOS_DRM_PLANAR_MAX]; - u32 fmt, hsize, vsize; - int i; - - /* Set current buf_id */ - rot->cur_buf_id[EXYNOS_DRM_OPS_DST] = buf_id; - - switch (ctrl) { - case IPP_BUF_CTRL_QUEUE: - /* Set address configuration */ - for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) - addr[i] = buf_info->base[i]; - - /* Get format */ - fmt = rotator_reg_get_format(rot); - - /* Re-set cb planar for NV12 format */ - if ((fmt == ROT_CONTROL_FMT_YCBCR420_2P) && - (addr[EXYNOS_DRM_PLANAR_CB] == 0x00)) { - /* Get buf size */ - rotator_reg_get_dst_buf_size(rot, &hsize, &vsize); - - /* Set cb planar */ - addr[EXYNOS_DRM_PLANAR_CB] = - addr[EXYNOS_DRM_PLANAR_Y] + hsize * vsize; - } - - for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) - rotator_reg_set_dst_buf_addr(rot, addr[i], i); - break; - case IPP_BUF_CTRL_DEQUEUE: - for (i = 0; i < EXYNOS_DRM_PLANAR_MAX; i++) - rotator_reg_set_dst_buf_addr(rot, buf_info->base[i], i); - break; - default: - /* Nothing to do */ - break; - } - - return 0; -} - -static struct exynos_drm_ipp_ops rot_src_ops = { - .set_fmt = rotator_src_set_fmt, - .set_size = rotator_src_set_size, - .set_addr = rotator_src_set_addr, -}; - -static struct exynos_drm_ipp_ops rot_dst_ops = { - .set_transf = rotator_dst_set_transf, - .set_size = rotator_dst_set_size, - .set_addr = rotator_dst_set_addr, -}; - -static int rotator_ippdrv_check_property(struct device *dev, - struct drm_exynos_ipp_property *property) -{ - struct drm_exynos_ipp_config *src_config = - &property->config[EXYNOS_DRM_OPS_SRC]; - struct drm_exynos_ipp_config *dst_config = - &property->config[EXYNOS_DRM_OPS_DST]; - struct drm_exynos_pos *src_pos = &src_config->pos; - struct drm_exynos_pos *dst_pos = &dst_config->pos; - struct drm_exynos_sz *src_sz = &src_config->sz; - struct drm_exynos_sz *dst_sz = &dst_config->sz; - bool swap = false; - - /* Check format configuration */ - if (src_config->fmt != dst_config->fmt) { - DRM_DEBUG_KMS("[%s]not support csc feature\n", __func__); - return -EINVAL; - } - - switch (src_config->fmt) { - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12M: - /* No problem */ - break; - default: - DRM_DEBUG_KMS("[%s]not support format\n", __func__); - return -EINVAL; - } - - /* Check transform configuration */ - if (src_config->degree != EXYNOS_DRM_DEGREE_0) { - DRM_DEBUG_KMS("[%s]not support source-side rotation\n", - __func__); - return -EINVAL; - } - - switch (dst_config->degree) { - case EXYNOS_DRM_DEGREE_90: - case EXYNOS_DRM_DEGREE_270: - swap = true; - case EXYNOS_DRM_DEGREE_0: - case EXYNOS_DRM_DEGREE_180: - /* No problem */ - break; - default: - DRM_DEBUG_KMS("[%s]invalid degree\n", __func__); - return -EINVAL; - } - - if (src_config->flip != EXYNOS_DRM_FLIP_NONE) { - DRM_DEBUG_KMS("[%s]not support source-side flip\n", __func__); - return -EINVAL; - } - - switch (dst_config->flip) { - case EXYNOS_DRM_FLIP_NONE: - case EXYNOS_DRM_FLIP_VERTICAL: - case EXYNOS_DRM_FLIP_HORIZONTAL: - /* No problem */ - break; - default: - DRM_DEBUG_KMS("[%s]invalid flip\n", __func__); - return -EINVAL; - } - - /* Check size configuration */ - if ((src_pos->x + src_pos->w > src_sz->hsize) || - (src_pos->y + src_pos->h > src_sz->vsize)) { - DRM_DEBUG_KMS("[%s]out of source buffer bound\n", __func__); - return -EINVAL; - } - - if (swap) { - if ((dst_pos->x + dst_pos->h > dst_sz->vsize) || - (dst_pos->y + dst_pos->w > dst_sz->hsize)) { - DRM_DEBUG_KMS("[%s]out of destination buffer bound\n", - __func__); - return -EINVAL; - } - - if ((src_pos->w != dst_pos->h) || (src_pos->h != dst_pos->w)) { - DRM_DEBUG_KMS("[%s]not support scale feature\n", - __func__); - return -EINVAL; - } - } else { - if ((dst_pos->x + dst_pos->w > dst_sz->hsize) || - (dst_pos->y + dst_pos->h > dst_sz->vsize)) { - DRM_DEBUG_KMS("[%s]out of destination buffer bound\n", - __func__); - return -EINVAL; - } - - if ((src_pos->w != dst_pos->w) || (src_pos->h != dst_pos->h)) { - DRM_DEBUG_KMS("[%s]not support scale feature\n", - __func__); - return -EINVAL; - } - } - - return 0; -} - -static int rotator_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd) -{ - struct rot_context *rot = dev_get_drvdata(dev); - - if (rot->suspended) { - DRM_ERROR("suspended state\n"); - return -EPERM; - } - - if (cmd != IPP_CMD_M2M) { - DRM_ERROR("not support cmd: %d\n", cmd); - return -EINVAL; - } - - /* Set interrupt enable */ - rotator_reg_set_irq(rot, true); - - /* start rotator operation */ - rotator_reg_set_start(rot); - - return 0; -} - -static int __devinit rotator_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct rot_context *rot; - struct resource *res; - struct exynos_drm_ippdrv *ippdrv; - int ret; - - rot = kzalloc(sizeof(*rot), GFP_KERNEL); - if (!rot) { - dev_err(dev, "failed to allocate rot\n"); - return -ENOMEM; - } - - rot->limit_tbl = (struct rot_limit_table *) - platform_get_device_id(pdev)->driver_data; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "failed to find registers\n"); - ret = -ENOENT; - goto err_get_resource; - } - - rot->regs_res = request_mem_region(res->start, resource_size(res), - dev_name(dev)); - if (!rot->regs_res) { - dev_err(dev, "failed to claim register region\n"); - ret = -ENOENT; - goto err_get_resource; - } - - rot->regs = ioremap(res->start, resource_size(res)); - if (!rot->regs) { - dev_err(dev, "failed to map register\n"); - ret = -ENXIO; - goto err_ioremap; - } - - rot->irq = platform_get_irq(pdev, 0); - if (rot->irq < 0) { - dev_err(dev, "faild to get irq\n"); - ret = rot->irq; - goto err_get_irq; - } - - ret = request_threaded_irq(rot->irq, NULL, rotator_irq_handler, - IRQF_ONESHOT, "drm_rotator", rot); - if (ret < 0) { - dev_err(dev, "failed to request irq\n"); - goto err_get_irq; - } - - rot->clock = clk_get(dev, "rotator"); - if (IS_ERR_OR_NULL(rot->clock)) { - dev_err(dev, "faild to get clock\n"); - ret = PTR_ERR(rot->clock); - goto err_clk_get; - } - - pm_runtime_enable(dev); - - ippdrv = &rot->ippdrv; - ippdrv->dev = dev; - ippdrv->iommu_used = true; - ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &rot_src_ops; - ippdrv->ops[EXYNOS_DRM_OPS_DST] = &rot_dst_ops; - ippdrv->check_property = rotator_ippdrv_check_property; - ippdrv->start = rotator_ippdrv_start; - - platform_set_drvdata(pdev, rot); - - ret = exynos_drm_ippdrv_register(ippdrv); - if (ret < 0) { - dev_err(dev, "failed to register drm rotator device\n"); - goto err_ippdrv_register; - } - - dev_info(dev, "The exynos rotator is probed successfully\n"); - - return 0; - -err_ippdrv_register: - pm_runtime_disable(dev); - clk_put(rot->clock); -err_clk_get: - free_irq(rot->irq, rot); -err_get_irq: - iounmap(rot->regs); -err_ioremap: - release_resource(rot->regs_res); - kfree(rot->regs_res); -err_get_resource: - kfree(rot); - return ret; -} - -static int __devexit rotator_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct rot_context *rot = dev_get_drvdata(dev); - - exynos_drm_ippdrv_unregister(&rot->ippdrv); - - pm_runtime_disable(dev); - clk_put(rot->clock); - - free_irq(rot->irq, rot); - - iounmap(rot->regs); - - release_resource(rot->regs_res); - kfree(rot->regs_res); - - kfree(rot); - - return 0; -} - -struct rot_limit_table rot_limit_tbl = { - .ycbcr420_2p = { - .min_w = 32, - .min_h = 32, - .max_w = SZ_32K, - .max_h = SZ_32K, - .align = 3, - }, - .rgb888 = { - .min_w = 8, - .min_h = 8, - .max_w = SZ_8K, - .max_h = SZ_8K, - .align = 2, - }, -}; - -struct platform_device_id rotator_driver_ids[] = { - { - .name = "exynos-rot", - .driver_data = (unsigned long)&rot_limit_tbl, - }, - {}, -}; - -#ifdef CONFIG_PM_SLEEP -static int rotator_suspend(struct device *dev) -{ - struct rot_context *rot = dev_get_drvdata(dev); - struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv; - struct drm_device *drm_dev = ippdrv->drm_dev; - struct exynos_drm_private *drm_priv = drm_dev->dev_private; - - rot->suspended = true; - - exynos_drm_iommu_deactivate(drm_priv->vmm, dev); - - return 0; -} - -static int rotator_resume(struct device *dev) -{ - struct rot_context *rot = dev_get_drvdata(dev); - struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv; - struct drm_device *drm_dev = ippdrv->drm_dev; - struct exynos_drm_private *drm_priv = drm_dev->dev_private; - int ret; - - ret = exynos_drm_iommu_activate(drm_priv->vmm, dev); - if (ret) - DRM_ERROR("failed to activate iommu\n"); - - rot->suspended = false; - - return ret; -} -#endif - -#ifdef CONFIG_PM_RUNTIME -static int rotator_runtime_suspend(struct device *dev) -{ - struct rot_context *rot = dev_get_drvdata(dev); - - clk_disable(rot->clock); - - return 0; -} - -static int rotator_runtime_resume(struct device *dev) -{ - struct rot_context *rot = dev_get_drvdata(dev); - - clk_enable(rot->clock); - - return 0; -} -#endif - -static const struct dev_pm_ops rotator_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(rotator_suspend, rotator_resume) - SET_RUNTIME_PM_OPS(rotator_runtime_suspend, rotator_runtime_resume, - NULL) -}; - -struct platform_driver rotator_driver = { - .probe = rotator_probe, - .remove = __devexit_p(rotator_remove), - .id_table = rotator_driver_ids, - .driver = { - .name = "exynos-rot", - .owner = THIS_MODULE, - .pm = &rotator_pm_ops, - }, -}; diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.h b/drivers/gpu/drm/exynos/exynos_drm_rotator.h deleted file mode 100644 index fe929c9..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Authors: YoungJun Cho - * - * 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 Foundationr - */ - -#ifndef _EXYNOS_DRM_ROTATOR_H_ -#define _EXYNOS_DRM_ROTATOR_H_ - -#endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_ump.c b/drivers/gpu/drm/exynos/exynos_drm_ump.c deleted file mode 100644 index f92759f..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_ump.c +++ /dev/null @@ -1,144 +0,0 @@ -/* exynos_drm_ump.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Author: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm.h" - -#include - -#include "exynos_drm_gem.h" -#include "ump_kernel_interface_ref_drv.h" - -static unsigned int exynos_drm_ump_get_handle(unsigned int id) -{ - return (unsigned int)ump_dd_handle_get((ump_secure_id)id); -} - -static int exynos_drm_ump_add_buffer(void *obj, - unsigned int *handle, unsigned int *id) -{ - struct exynos_drm_gem_obj *gem_obj = obj; - struct exynos_drm_gem_buf *buf = gem_obj->buffer; - ump_dd_physical_block *ump_mem_desc; - unsigned int nblocks; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (IS_NONCONTIG_BUFFER(gem_obj->flags)) { - unsigned int i = 0; - - if (!buf->pages) - return -EFAULT; - - nblocks = gem_obj->size >> PAGE_SHIFT; - ump_mem_desc = kzalloc(sizeof(*ump_mem_desc) * nblocks, - GFP_KERNEL); - if (!ump_mem_desc) { - DRM_ERROR("failed to alloc ump_mem_desc.\n"); - return -ENOMEM; - } - - /* - * if EXYNOS_BO_NONCONTIG type, gem object would already - * have pages allocated by gem creation so contain page - * frame numbers of all pages into ump descriptors. - */ - while (i < nblocks) { - ump_mem_desc[i].addr = - page_to_pfn(buf->pages[i]) << PAGE_SHIFT; - ump_mem_desc[i].size = PAGE_SIZE; - i++; - } - } else { - nblocks = 1; - - ump_mem_desc = kzalloc(sizeof(*ump_mem_desc), GFP_KERNEL); - if (!ump_mem_desc) { - DRM_ERROR("failed to alloc ump_mem_desc.\n"); - return -ENOMEM; - } - - /* - * it EXYNOS_DRM_GEM_PC type, gem would have just one - * physically continuous buffer so let a ump descriptor - * have one buffer address. - */ - ump_mem_desc[0].addr = (unsigned long)buf->paddr; - ump_mem_desc[0].size = buf->size; - } - - /* - * register memory information to ump descriptor table through - * the ump descriptor data and then return ump handle to it so that - * user can access the memory region through it. - */ - *handle = (unsigned int) - ump_dd_handle_create_from_phys_blocks(ump_mem_desc, nblocks); - if (!(*handle)) { - DRM_ERROR("failed to create ump handle.\n"); - kfree(ump_mem_desc); - return -EINVAL; - } - - *id = ump_dd_secure_id_get((ump_dd_handle)*handle); - - kfree(ump_mem_desc); - - DRM_DEBUG_KMS("ump handle : 0x%x, secure id = %d\n", *handle, *id); - DRM_INFO("ump handle : 0x%x, secure id = %d\n", *handle, *id); - - return 0; -} - -static void exynos_drm_ump_release_buffer(unsigned int handle) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); -} - -static struct exynos_drm_private_cb ump_callback = { - .get_handle = exynos_drm_ump_get_handle, - .add_buffer = exynos_drm_ump_add_buffer, - .release_buffer = exynos_drm_ump_release_buffer, -}; - -static int exynos_drm_ump_init(void) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_drm_priv_cb_register(&ump_callback); - - return 0; -} - -static void exynos_drm_ump_exit(void) -{ -} - -subsys_initcall(exynos_drm_ump_init); -module_exit(exynos_drm_ump_exit); - -MODULE_AUTHOR("Inki Dae "); -MODULE_DESCRIPTION("Samsung SoC DRM UMP Backend Module"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c deleted file mode 100644 index 44bcdc8..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ /dev/null @@ -1,693 +0,0 @@ -/* exynos_drm_vidi.c - * - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * Authors: - * Inki Dae - * - * 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 "drmP.h" - -#include -#include -#include - -#include - -#include "drm_edid.h" -#include "drm_crtc_helper.h" - -#include "exynos_drm_drv.h" -#include "exynos_drm_crtc.h" -#include "exynos_drm_encoder.h" - -/* vidi has totally three virtual windows. */ -#define WINDOWS_NR 3 - -#define get_vidi_context(dev) platform_get_drvdata(to_platform_device(dev)) - -struct vidi_win_data { - unsigned int offset_x; - unsigned int offset_y; - unsigned int ovl_width; - unsigned int ovl_height; - unsigned int fb_width; - unsigned int fb_height; - unsigned int bpp; - dma_addr_t dma_addr; - void __iomem *vaddr; - unsigned int buf_offsize; - unsigned int line_size; /* bytes */ - bool enabled; -}; - -struct vidi_context { - struct exynos_drm_subdrv subdrv; - struct drm_crtc *crtc; - struct vidi_win_data win_data[WINDOWS_NR]; - struct edid *raw_edid; - unsigned int clkdiv; - unsigned int default_win; - unsigned long irq_flags; - unsigned int connected; - bool vblank_on; - bool suspended; - struct work_struct work; - struct mutex lock; -}; - -static const char fake_edid_info[] = { - 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x05, 0x05, - 0x00, 0x00, 0x00, 0x00, 0x30, 0x12, 0x01, 0x03, 0x80, 0x10, 0x09, 0x78, - 0x0a, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0xbd, - 0xee, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x66, 0x21, 0x50, 0xb0, 0x51, 0x00, - 0x1b, 0x30, 0x40, 0x70, 0x36, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, - 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, - 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, - 0x4b, 0x1a, 0x44, 0x17, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x00, 0x00, 0x00, 0xfc, 0x00, 0x53, 0x41, 0x4d, 0x53, 0x55, 0x4e, 0x47, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xbc, 0x02, 0x03, 0x1e, 0xf1, - 0x46, 0x84, 0x05, 0x03, 0x10, 0x20, 0x22, 0x23, 0x09, 0x07, 0x07, 0x83, - 0x01, 0x00, 0x00, 0xe2, 0x00, 0x0f, 0x67, 0x03, 0x0c, 0x00, 0x10, 0x00, - 0xb8, 0x2d, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c, - 0x25, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x9e, 0x8c, 0x0a, 0xd0, 0x8a, - 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xa0, 0x5a, 0x00, 0x00, - 0x00, 0x18, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, - 0x45, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06 -}; - -static void vidi_fake_vblank_handler(struct work_struct *work); - -static bool vidi_display_is_connected(struct device *dev) -{ - struct vidi_context *ctx = get_vidi_context(dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* - * connection request would come from user side - * to do hotplug through specific ioctl. - */ - return ctx->connected ? true : false; -} - -static int vidi_get_edid(struct device *dev, struct drm_connector *connector, - u8 *edid, int len) -{ - struct vidi_context *ctx = get_vidi_context(dev); - struct edid *raw_edid; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* - * the edid data comes from user side and it would be set - * to ctx->raw_edid through specific ioctl. - */ - if (!ctx->raw_edid) { - DRM_DEBUG_KMS("raw_edid is null.\n"); - return -EFAULT; - } - - raw_edid = kzalloc(len, GFP_KERNEL); - if (!raw_edid) { - DRM_DEBUG_KMS("failed to allocate raw_edid.\n"); - return -ENOMEM; - } - - memcpy(raw_edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions) - * EDID_LENGTH, len)); - - /* attach the edid data to connector. */ - connector->display_info.raw_edid = (char *)raw_edid; - - memcpy(edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions) - * EDID_LENGTH, len)); - - return 0; -} - -static void *vidi_get_panel(struct device *dev) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* TODO. */ - - return NULL; -} - -static int vidi_check_timing(struct device *dev, void *timing) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* TODO. */ - - return 0; -} - -static int vidi_display_power_on(struct device *dev, int mode) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* TODO */ - - return 0; -} - -static struct exynos_drm_display_ops vidi_display_ops = { - .type = EXYNOS_DISPLAY_TYPE_VIDI, - .is_connected = vidi_display_is_connected, - .get_edid = vidi_get_edid, - .get_panel = vidi_get_panel, - .check_timing = vidi_check_timing, - .power_on = vidi_display_power_on, -}; - -static void vidi_dpms(struct device *subdrv_dev, int mode) -{ - struct vidi_context *ctx = get_vidi_context(subdrv_dev); - - DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode); - - mutex_lock(&ctx->lock); - - switch (mode) { - case DRM_MODE_DPMS_ON: - /* TODO. */ - break; - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: - /* TODO. */ - break; - default: - DRM_DEBUG_KMS("unspecified mode %d\n", mode); - break; - } - - mutex_unlock(&ctx->lock); -} - -static void vidi_apply(struct device *subdrv_dev) -{ - struct vidi_context *ctx = get_vidi_context(subdrv_dev); - struct exynos_drm_manager *mgr = ctx->subdrv.manager; - struct exynos_drm_manager_ops *mgr_ops = mgr->ops; - struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops; - struct vidi_win_data *win_data; - int i; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - for (i = 0; i < WINDOWS_NR; i++) { - win_data = &ctx->win_data[i]; - if (win_data->enabled && (ovl_ops && ovl_ops->commit)) - ovl_ops->commit(subdrv_dev, i); - } - - if (mgr_ops && mgr_ops->commit) - mgr_ops->commit(subdrv_dev); -} - -static void vidi_commit(struct device *dev) -{ - struct vidi_context *ctx = get_vidi_context(dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (ctx->suspended) - return; -} - -static int vidi_enable_vblank(struct device *dev) -{ - struct vidi_context *ctx = get_vidi_context(dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (ctx->suspended) - return -EPERM; - - if (!test_and_set_bit(0, &ctx->irq_flags)) - ctx->vblank_on = true; - - return 0; -} - -static void vidi_disable_vblank(struct device *dev) -{ - struct vidi_context *ctx = get_vidi_context(dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (ctx->suspended) - return; - - if (test_and_clear_bit(0, &ctx->irq_flags)) - ctx->vblank_on = false; -} - -static struct exynos_drm_manager_ops vidi_manager_ops = { - .dpms = vidi_dpms, - .apply = vidi_apply, - .commit = vidi_commit, - .enable_vblank = vidi_enable_vblank, - .disable_vblank = vidi_disable_vblank, -}; - -static void vidi_win_mode_set(struct device *dev, - struct exynos_drm_overlay *overlay) -{ - struct vidi_context *ctx = get_vidi_context(dev); - struct vidi_win_data *win_data; - int win; - unsigned long offset; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!overlay) { - dev_err(dev, "overlay is NULL\n"); - return; - } - - win = overlay->zpos; - if (win == DEFAULT_ZPOS) - win = ctx->default_win; - - if (win < 0 || win > WINDOWS_NR) - return; - - offset = overlay->fb_x * (overlay->bpp >> 3); - offset += overlay->fb_y * overlay->pitch; - - DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch); - - win_data = &ctx->win_data[win]; - - win_data->offset_x = overlay->crtc_x; - win_data->offset_y = overlay->crtc_y; - win_data->ovl_width = overlay->crtc_width; - win_data->ovl_height = overlay->crtc_height; - win_data->fb_width = overlay->fb_width; - win_data->fb_height = overlay->fb_height; - win_data->dma_addr = overlay->dma_addr[0] + offset; - win_data->vaddr = overlay->vaddr[0] + offset; - win_data->bpp = overlay->bpp; - win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * - (overlay->bpp >> 3); - win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3); - - /* - * some parts of win_data should be transferred to user side - * through specific ioctl. - */ - - DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n", - win_data->offset_x, win_data->offset_y); - DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", - win_data->ovl_width, win_data->ovl_height); - DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n", - (unsigned long)win_data->dma_addr, - (unsigned long)win_data->vaddr); - DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", - overlay->fb_width, overlay->crtc_width); -} - -static void vidi_win_commit(struct device *dev, int zpos) -{ - struct vidi_context *ctx = get_vidi_context(dev); - struct vidi_win_data *win_data; - int win = zpos; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (ctx->suspended) - return; - - if (win == DEFAULT_ZPOS) - win = ctx->default_win; - - if (win < 0 || win > WINDOWS_NR) - return; - - win_data = &ctx->win_data[win]; - - win_data->enabled = true; - - DRM_DEBUG_KMS("dma_addr = 0x%x\n", win_data->dma_addr); - - if (ctx->vblank_on) - schedule_work(&ctx->work); -} - -static void vidi_win_disable(struct device *dev, int zpos) -{ - struct vidi_context *ctx = get_vidi_context(dev); - struct vidi_win_data *win_data; - int win = zpos; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (win == DEFAULT_ZPOS) - win = ctx->default_win; - - if (win < 0 || win > WINDOWS_NR) - return; - - win_data = &ctx->win_data[win]; - win_data->enabled = false; - - /* TODO. */ -} - -static struct exynos_drm_overlay_ops vidi_overlay_ops = { - .mode_set = vidi_win_mode_set, - .commit = vidi_win_commit, - .disable = vidi_win_disable, -}; - -static struct exynos_drm_manager vidi_manager = { - .pipe = -1, - .ops = &vidi_manager_ops, - .overlay_ops = &vidi_overlay_ops, - .display_ops = &vidi_display_ops, -}; - -static void vidi_finish_pageflip(struct drm_device *drm_dev, int crtc) -{ - struct exynos_drm_private *dev_priv = drm_dev->dev_private; - struct drm_pending_vblank_event *e, *t; - struct timeval now; - unsigned long flags; - bool is_checked = false; - - spin_lock_irqsave(&drm_dev->event_lock, flags); - - list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list, - base.link) { - /* if event's pipe isn't same as crtc then ignore it. */ - if (crtc != e->pipe) - continue; - - is_checked = true; - - do_gettimeofday(&now); - e->event.sequence = 0; - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; - - list_move_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); - } - - if (is_checked) { - /* - * call drm_vblank_put only in case that drm_vblank_get was - * called. - */ - if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0) - drm_vblank_put(drm_dev, crtc); - - /* - * don't off vblank if vblank_disable_allowed is 1, - * because vblank would be off by timer handler. - */ - if (!drm_dev->vblank_disable_allowed) - drm_vblank_off(drm_dev, crtc); - } - - spin_unlock_irqrestore(&drm_dev->event_lock, flags); -} - -static void vidi_fake_vblank_handler(struct work_struct *work) -{ - struct vidi_context *ctx = container_of(work, struct vidi_context, - work); - struct exynos_drm_subdrv *subdrv = &ctx->subdrv; - struct exynos_drm_manager *manager = subdrv->manager; - - if (manager->pipe < 0) - return; - - /* FIXME!!! */ - msleep(20); - - drm_handle_vblank(subdrv->drm_dev, manager->pipe); - vidi_finish_pageflip(subdrv->drm_dev, manager->pipe); -} - -static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* - * enable drm irq mode. - * - with irq_enabled = 1, we can use the vblank feature. - * - * P.S. note that we wouldn't use drm irq handler but - * just specific driver own one instead because - * drm framework supports only one irq handler. - */ - drm_dev->irq_enabled = 1; - - /* - * with vblank_disable_allowed = 1, vblank interrupt will be disabled - * by drm timer once a current process gives up ownership of - * vblank event.(after drm_vblank_put function is called) - */ - drm_dev->vblank_disable_allowed = 1; - - return 0; -} - -static void vidi_subdrv_remove(struct drm_device *drm_dev, struct device *dev) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* TODO. */ -} - -static int vidi_power_on(struct vidi_context *ctx, bool enable) -{ - struct exynos_drm_subdrv *subdrv = &ctx->subdrv; - struct device *dev = subdrv->dev; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (enable != false && enable != true) - return -EINVAL; - - if (enable) { - ctx->suspended = false; - - /* if vblank was enabled status, enable it again. */ - if (test_and_clear_bit(0, &ctx->irq_flags)) - vidi_enable_vblank(dev); - - vidi_apply(dev); - } else { - ctx->suspended = true; - } - - return 0; -} - -static int vidi_show_connection(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int rc; - struct vidi_context *ctx = get_vidi_context(dev); - - mutex_lock(&ctx->lock); - - rc = sprintf(buf, "%d\n", ctx->connected); - - mutex_unlock(&ctx->lock); - - return rc; -} - -static int vidi_store_connection(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct vidi_context *ctx = get_vidi_context(dev); - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - ret = kstrtoint(buf, 0, &ctx->connected); - if (ret) - return ret; - - if (ctx->connected > 1) - return -EINVAL; - - DRM_DEBUG_KMS("requested connection.\n"); - - drm_helper_hpd_irq_event(ctx->subdrv.drm_dev); - - return len; -} - -static DEVICE_ATTR(connection, 0644, vidi_show_connection, - vidi_store_connection); - -int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, - struct drm_file *file_priv) -{ - struct vidi_context *ctx = NULL; - struct drm_encoder *encoder; - struct exynos_drm_manager *manager; - struct exynos_drm_display_ops *display_ops; - struct drm_exynos_vidi_connection *vidi = data; - struct edid *raw_edid; - int edid_len; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!vidi) { - DRM_DEBUG_KMS("user data for vidi is null.\n"); - return -EINVAL; - } - - if (vidi->connection > 1) { - DRM_DEBUG_KMS("connection should be 0 or 1.\n"); - return -EINVAL; - } - - list_for_each_entry(encoder, &drm_dev->mode_config.encoder_list, - head) { - manager = exynos_drm_get_manager(encoder); - display_ops = manager->display_ops; - - if (display_ops->type == EXYNOS_DISPLAY_TYPE_VIDI) { - ctx = get_vidi_context(manager->dev); - break; - } - } - - if (!ctx) { - DRM_DEBUG_KMS("not found virtual device type encoder.\n"); - return -EINVAL; - } - - if (ctx->connected == vidi->connection) { - DRM_DEBUG_KMS("same connection request.\n"); - return -EINVAL; - } - - if (vidi->connection) { - if (!vidi->edid) { - DRM_DEBUG_KMS("edid data is null.\n"); - return -EINVAL; - } - raw_edid = (struct edid *)vidi->edid; - edid_len = (1 + raw_edid->extensions) * EDID_LENGTH; - ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL); - if (!ctx->raw_edid) { - DRM_DEBUG_KMS("failed to allocate raw_edid.\n"); - return -ENOMEM; - } - memcpy(ctx->raw_edid, raw_edid, edid_len); - } else { - kfree(ctx->raw_edid); - ctx->raw_edid = NULL; - } - - ctx->connected = vidi->connection; - drm_helper_hpd_irq_event(ctx->subdrv.drm_dev); - - return 0; -} - -static int __devinit vidi_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct vidi_context *ctx; - struct exynos_drm_subdrv *subdrv; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - ctx->default_win = 0; - - INIT_WORK(&ctx->work, vidi_fake_vblank_handler); - - /* for test */ - ctx->raw_edid = (struct edid *)fake_edid_info; - - subdrv = &ctx->subdrv; - subdrv->dev = dev; - subdrv->manager = &vidi_manager; - subdrv->probe = vidi_subdrv_probe; - subdrv->remove = vidi_subdrv_remove; - - mutex_init(&ctx->lock); - - platform_set_drvdata(pdev, ctx); - - ret = device_create_file(&pdev->dev, &dev_attr_connection); - if (ret < 0) - DRM_INFO("failed to create connection sysfs.\n"); - - exynos_drm_subdrv_register(subdrv); - - return 0; -} - -static int __devexit vidi_remove(struct platform_device *pdev) -{ - struct vidi_context *ctx = platform_get_drvdata(pdev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_drm_subdrv_unregister(&ctx->subdrv); - - kfree(ctx->raw_edid); - kfree(ctx); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int vidi_suspend(struct device *dev) -{ - struct vidi_context *ctx = get_vidi_context(dev); - - return vidi_power_on(ctx, false); -} - -static int vidi_resume(struct device *dev) -{ - struct vidi_context *ctx = get_vidi_context(dev); - - return vidi_power_on(ctx, true); -} -#endif - -static const struct dev_pm_ops vidi_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(vidi_suspend, vidi_resume) -}; - -struct platform_driver vidi_driver = { - .probe = vidi_probe, - .remove = __devexit_p(vidi_remove), - .driver = { - .name = "exynos-drm-vidi", - .owner = THIS_MODULE, - .pm = &vidi_pm_ops, - }, -}; diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.h b/drivers/gpu/drm/exynos/exynos_drm_vidi.h deleted file mode 100644 index a4babe4..0000000 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.h +++ /dev/null @@ -1,36 +0,0 @@ -/* exynos_drm_vidi.h - * - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * Author: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_VIDI_H_ -#define _EXYNOS_DRM_VIDI_H_ - -#ifdef CONFIG_DRM_EXYNOS_VIDI -int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, - struct drm_file *file_priv); -#else -#define vidi_connection_ioctl NULL -#endif - -#endif diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c deleted file mode 100644 index 48d7f98..0000000 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ /dev/null @@ -1,2681 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics Co.Ltd - * Authors: - * Seung-Woo Kim - * Inki Dae - * Joonyoung Shim - * - * Based on drivers/media/video/s5p-tv/hdmi_drv.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 "drmP.h" -#include "drm_edid.h" -#include "drm_crtc_helper.h" - -#include "regs-hdmi.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "exynos_drm_drv.h" -#include "exynos_drm_hdmi.h" -#include "exynos_drm_iommu.h" - -#include "exynos_hdmi.h" - -#define MAX_WIDTH 1920 -#define MAX_HEIGHT 1080 -#define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev)) - -struct hdmi_resources { - struct clk *hdmi; - struct clk *sclk_hdmi; - struct clk *sclk_pixel; - struct clk *sclk_hdmiphy; - struct clk *hdmiphy; - struct regulator_bulk_data *regul_bulk; - int regul_count; -}; - -struct hdmi_context { - struct device *dev; - struct drm_device *drm_dev; - bool hpd; - bool powered; - bool is_v13; - bool dvi_mode; - bool iommu_on; - struct mutex hdmi_mutex; - - struct resource *regs_res; - void __iomem *regs; - unsigned int external_irq; - unsigned int internal_irq; - - struct i2c_client *ddc_port; - struct i2c_client *hdmiphy_port; - - /* current hdmiphy conf index */ - int cur_conf; - - struct hdmi_resources res; - void *parent_ctx; - - void (*cfg_hpd)(bool external); - int (*get_hpd)(void); -}; - -/* HDMI Version 1.3 */ -static const u8 hdmiphy_v13_conf27[32] = { - 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, - 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87, - 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0, - 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00, -}; - -static const u8 hdmiphy_v13_conf27_027[32] = { - 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64, - 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87, - 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0, - 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00, -}; - -static const u8 hdmiphy_v13_conf74_175[32] = { - 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B, - 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9, - 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0, - 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00, -}; - -static const u8 hdmiphy_v13_conf74_25[32] = { - 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40, - 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba, - 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0, - 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00, -}; - -static const u8 hdmiphy_v13_conf148_5[32] = { - 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40, - 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba, - 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0, - 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00, -}; - -struct hdmi_v13_tg_regs { - u8 cmd; - u8 h_fsz_l; - u8 h_fsz_h; - u8 hact_st_l; - u8 hact_st_h; - u8 hact_sz_l; - u8 hact_sz_h; - u8 v_fsz_l; - u8 v_fsz_h; - u8 vsync_l; - u8 vsync_h; - u8 vsync2_l; - u8 vsync2_h; - u8 vact_st_l; - u8 vact_st_h; - u8 vact_sz_l; - u8 vact_sz_h; - u8 field_chg_l; - u8 field_chg_h; - u8 vact_st2_l; - u8 vact_st2_h; - u8 vsync_top_hdmi_l; - u8 vsync_top_hdmi_h; - u8 vsync_bot_hdmi_l; - u8 vsync_bot_hdmi_h; - u8 field_top_hdmi_l; - u8 field_top_hdmi_h; - u8 field_bot_hdmi_l; - u8 field_bot_hdmi_h; -}; - -struct hdmi_v13_core_regs { - u8 h_blank[2]; - u8 v_blank[3]; - u8 h_v_line[3]; - u8 vsync_pol[1]; - u8 int_pro_mode[1]; - u8 v_blank_f[3]; - u8 h_sync_gen[3]; - u8 v_sync_gen1[3]; - u8 v_sync_gen2[3]; - u8 v_sync_gen3[3]; -}; - -struct hdmi_v13_preset_conf { - struct hdmi_v13_core_regs core; - struct hdmi_v13_tg_regs tg; -}; - -struct hdmi_v13_conf { - int width; - int height; - int vrefresh; - bool interlace; - const u8 *hdmiphy_data; - const struct hdmi_v13_preset_conf *conf; -}; - -static const struct hdmi_v13_preset_conf hdmi_v13_conf_480p = { - .core = { - .h_blank = {0x8a, 0x00}, - .v_blank = {0x0d, 0x6a, 0x01}, - .h_v_line = {0x0d, 0xa2, 0x35}, - .vsync_pol = {0x01}, - .int_pro_mode = {0x00}, - .v_blank_f = {0x00, 0x00, 0x00}, - .h_sync_gen = {0x0e, 0x30, 0x11}, - .v_sync_gen1 = {0x0f, 0x90, 0x00}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x5a, 0x03, /* h_fsz */ - 0x8a, 0x00, 0xd0, 0x02, /* hact */ - 0x0d, 0x02, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x2d, 0x00, 0xe0, 0x01, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x49, 0x02, /* vact_st2 */ - 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - }, -}; - -static const struct hdmi_v13_preset_conf hdmi_v13_conf_720p60 = { - .core = { - .h_blank = {0x72, 0x01}, - .v_blank = {0xee, 0xf2, 0x00}, - .h_v_line = {0xee, 0x22, 0x67}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x00}, - .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */ - .h_sync_gen = {0x6c, 0x50, 0x02}, - .v_sync_gen1 = {0x0a, 0x50, 0x00}, - .v_sync_gen2 = {0x01, 0x10, 0x00}, - .v_sync_gen3 = {0x01, 0x10, 0x00}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x72, 0x06, /* h_fsz */ - 0x71, 0x01, 0x01, 0x05, /* hact */ - 0xee, 0x02, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x1e, 0x00, 0xd0, 0x02, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x49, 0x02, /* vact_st2 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - }, -}; - -static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i50 = { - .core = { - .h_blank = {0xd0, 0x02}, - .v_blank = {0x32, 0xB2, 0x00}, - .h_v_line = {0x65, 0x04, 0xa5}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x01}, - .v_blank_f = {0x49, 0x2A, 0x23}, - .h_sync_gen = {0x0E, 0xEA, 0x08}, - .v_sync_gen1 = {0x07, 0x20, 0x00}, - .v_sync_gen2 = {0x39, 0x42, 0x23}, - .v_sync_gen3 = {0x38, 0x87, 0x73}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x50, 0x0A, /* h_fsz */ - 0xCF, 0x02, 0x81, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x16, 0x00, 0x1c, 0x02, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x49, 0x02, /* vact_st2 */ - 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - }, -}; - -static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p50 = { - .core = { - .h_blank = {0xd0, 0x02}, - .v_blank = {0x65, 0x6c, 0x01}, - .h_v_line = {0x65, 0x04, 0xa5}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x00}, - .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */ - .h_sync_gen = {0x0e, 0xea, 0x08}, - .v_sync_gen1 = {0x09, 0x40, 0x00}, - .v_sync_gen2 = {0x01, 0x10, 0x00}, - .v_sync_gen3 = {0x01, 0x10, 0x00}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x50, 0x0A, /* h_fsz */ - 0xCF, 0x02, 0x81, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x2d, 0x00, 0x38, 0x04, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - }, -}; - -static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i60 = { - .core = { - .h_blank = {0x18, 0x01}, - .v_blank = {0x32, 0xB2, 0x00}, - .h_v_line = {0x65, 0x84, 0x89}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x01}, - .v_blank_f = {0x49, 0x2A, 0x23}, - .h_sync_gen = {0x56, 0x08, 0x02}, - .v_sync_gen1 = {0x07, 0x20, 0x00}, - .v_sync_gen2 = {0x39, 0x42, 0x23}, - .v_sync_gen3 = {0xa4, 0x44, 0x4a}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x98, 0x08, /* h_fsz */ - 0x17, 0x01, 0x81, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x16, 0x00, 0x1c, 0x02, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x49, 0x02, /* vact_st2 */ - 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - }, -}; - -static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p60 = { - .core = { - .h_blank = {0x18, 0x01}, - .v_blank = {0x65, 0x6c, 0x01}, - .h_v_line = {0x65, 0x84, 0x89}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x00}, - .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */ - .h_sync_gen = {0x56, 0x08, 0x02}, - .v_sync_gen1 = {0x09, 0x40, 0x00}, - .v_sync_gen2 = {0x01, 0x10, 0x00}, - .v_sync_gen3 = {0x01, 0x10, 0x00}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x98, 0x08, /* h_fsz */ - 0x17, 0x01, 0x81, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x2d, 0x00, 0x38, 0x04, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - }, -}; - -static const struct hdmi_v13_conf hdmi_v13_confs[] = { - { 1280, 720, 60, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 }, - { 1280, 720, 50, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 }, - { 720, 480, 60, false, hdmiphy_v13_conf27_027, &hdmi_v13_conf_480p }, - { 1920, 1080, 50, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i50 }, - { 1920, 1080, 50, false, hdmiphy_v13_conf148_5, - &hdmi_v13_conf_1080p50 }, - { 1920, 1080, 60, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i60 }, - { 1920, 1080, 60, false, hdmiphy_v13_conf148_5, - &hdmi_v13_conf_1080p60 }, -}; - -/* HDMI Version 1.4 */ -static const u8 hdmiphy_conf27_027[32] = { - 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08, - 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80, - 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, -}; - -static const u8 hdmiphy_conf74_176[32] = { - 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x5b, 0xef, 0x08, - 0x81, 0xa0, 0xb9, 0xd8, 0x45, 0xa0, 0xac, 0x80, - 0x5a, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, -}; - -static const u8 hdmiphy_conf74_25[32] = { - 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08, - 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, - 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, -}; - -static const u8 hdmiphy_conf148_5[32] = { - 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08, - 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, - 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00, -}; - -struct hdmi_tg_regs { - u8 cmd; - u8 h_fsz_l; - u8 h_fsz_h; - u8 hact_st_l; - u8 hact_st_h; - u8 hact_sz_l; - u8 hact_sz_h; - u8 v_fsz_l; - u8 v_fsz_h; - u8 vsync_l; - u8 vsync_h; - u8 vsync2_l; - u8 vsync2_h; - u8 vact_st_l; - u8 vact_st_h; - u8 vact_sz_l; - u8 vact_sz_h; - u8 field_chg_l; - u8 field_chg_h; - u8 vact_st2_l; - u8 vact_st2_h; - u8 vact_st3_l; - u8 vact_st3_h; - u8 vact_st4_l; - u8 vact_st4_h; - u8 vsync_top_hdmi_l; - u8 vsync_top_hdmi_h; - u8 vsync_bot_hdmi_l; - u8 vsync_bot_hdmi_h; - u8 field_top_hdmi_l; - u8 field_top_hdmi_h; - u8 field_bot_hdmi_l; - u8 field_bot_hdmi_h; - u8 tg_3d; -}; - -struct hdmi_core_regs { - u8 h_blank[2]; - u8 v2_blank[2]; - u8 v1_blank[2]; - u8 v_line[2]; - u8 h_line[2]; - u8 hsync_pol[1]; - u8 vsync_pol[1]; - u8 int_pro_mode[1]; - u8 v_blank_f0[2]; - u8 v_blank_f1[2]; - u8 h_sync_start[2]; - u8 h_sync_end[2]; - u8 v_sync_line_bef_2[2]; - u8 v_sync_line_bef_1[2]; - u8 v_sync_line_aft_2[2]; - u8 v_sync_line_aft_1[2]; - u8 v_sync_line_aft_pxl_2[2]; - u8 v_sync_line_aft_pxl_1[2]; - u8 v_blank_f2[2]; /* for 3D mode */ - u8 v_blank_f3[2]; /* for 3D mode */ - u8 v_blank_f4[2]; /* for 3D mode */ - u8 v_blank_f5[2]; /* for 3D mode */ - u8 v_sync_line_aft_3[2]; - u8 v_sync_line_aft_4[2]; - u8 v_sync_line_aft_5[2]; - u8 v_sync_line_aft_6[2]; - u8 v_sync_line_aft_pxl_3[2]; - u8 v_sync_line_aft_pxl_4[2]; - u8 v_sync_line_aft_pxl_5[2]; - u8 v_sync_line_aft_pxl_6[2]; - u8 vact_space_1[2]; - u8 vact_space_2[2]; - u8 vact_space_3[2]; - u8 vact_space_4[2]; - u8 vact_space_5[2]; - u8 vact_space_6[2]; -}; - -struct hdmi_preset_conf { - struct hdmi_core_regs core; - struct hdmi_tg_regs tg; -}; - -struct hdmi_conf { - int width; - int height; - int vrefresh; - bool interlace; - const u8 *hdmiphy_data; - const struct hdmi_preset_conf *conf; -}; - -static const struct hdmi_preset_conf hdmi_conf_480p60 = { - .core = { - .h_blank = {0x8a, 0x00}, - .v2_blank = {0x0d, 0x02}, - .v1_blank = {0x2d, 0x00}, - .v_line = {0x0d, 0x02}, - .h_line = {0x5a, 0x03}, - .hsync_pol = {0x01}, - .vsync_pol = {0x01}, - .int_pro_mode = {0x00}, - .v_blank_f0 = {0xff, 0xff}, - .v_blank_f1 = {0xff, 0xff}, - .h_sync_start = {0x0e, 0x00}, - .h_sync_end = {0x4c, 0x00}, - .v_sync_line_bef_2 = {0x0f, 0x00}, - .v_sync_line_bef_1 = {0x09, 0x00}, - .v_sync_line_aft_2 = {0xff, 0xff}, - .v_sync_line_aft_1 = {0xff, 0xff}, - .v_sync_line_aft_pxl_2 = {0xff, 0xff}, - .v_sync_line_aft_pxl_1 = {0xff, 0xff}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x5a, 0x03, /* h_fsz */ - 0x8a, 0x00, 0xd0, 0x02, /* hact */ - 0x0d, 0x02, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x2d, 0x00, 0xe0, 0x01, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ - }, -}; - -static const struct hdmi_preset_conf hdmi_conf_720p50 = { - .core = { - .h_blank = {0xbc, 0x02}, - .v2_blank = {0xee, 0x02}, - .v1_blank = {0x1e, 0x00}, - .v_line = {0xee, 0x02}, - .h_line = {0xbc, 0x07}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x00}, - .v_blank_f0 = {0xff, 0xff}, - .v_blank_f1 = {0xff, 0xff}, - .h_sync_start = {0xb6, 0x01}, - .h_sync_end = {0xde, 0x01}, - .v_sync_line_bef_2 = {0x0a, 0x00}, - .v_sync_line_bef_1 = {0x05, 0x00}, - .v_sync_line_aft_2 = {0xff, 0xff}, - .v_sync_line_aft_1 = {0xff, 0xff}, - .v_sync_line_aft_pxl_2 = {0xff, 0xff}, - .v_sync_line_aft_pxl_1 = {0xff, 0xff}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0xbc, 0x07, /* h_fsz */ - 0xbc, 0x02, 0x00, 0x05, /* hact */ - 0xee, 0x02, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x1e, 0x00, 0xd0, 0x02, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ - }, -}; - -static const struct hdmi_preset_conf hdmi_conf_720p60 = { - .core = { - .h_blank = {0x72, 0x01}, - .v2_blank = {0xee, 0x02}, - .v1_blank = {0x1e, 0x00}, - .v_line = {0xee, 0x02}, - .h_line = {0x72, 0x06}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x00}, - .v_blank_f0 = {0xff, 0xff}, - .v_blank_f1 = {0xff, 0xff}, - .h_sync_start = {0x6c, 0x00}, - .h_sync_end = {0x94, 0x00}, - .v_sync_line_bef_2 = {0x0a, 0x00}, - .v_sync_line_bef_1 = {0x05, 0x00}, - .v_sync_line_aft_2 = {0xff, 0xff}, - .v_sync_line_aft_1 = {0xff, 0xff}, - .v_sync_line_aft_pxl_2 = {0xff, 0xff}, - .v_sync_line_aft_pxl_1 = {0xff, 0xff}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x72, 0x06, /* h_fsz */ - 0x72, 0x01, 0x00, 0x05, /* hact */ - 0xee, 0x02, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x1e, 0x00, 0xd0, 0x02, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ - }, -}; - -static const struct hdmi_preset_conf hdmi_conf_1080i50 = { - .core = { - .h_blank = {0xd0, 0x02}, - .v2_blank = {0x32, 0x02}, - .v1_blank = {0x16, 0x00}, - .v_line = {0x65, 0x04}, - .h_line = {0x50, 0x0a}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x01}, - .v_blank_f0 = {0x49, 0x02}, - .v_blank_f1 = {0x65, 0x04}, - .h_sync_start = {0x0e, 0x02}, - .h_sync_end = {0x3a, 0x02}, - .v_sync_line_bef_2 = {0x07, 0x00}, - .v_sync_line_bef_1 = {0x02, 0x00}, - .v_sync_line_aft_2 = {0x39, 0x02}, - .v_sync_line_aft_1 = {0x34, 0x02}, - .v_sync_line_aft_pxl_2 = {0x38, 0x07}, - .v_sync_line_aft_pxl_1 = {0x38, 0x07}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x50, 0x0a, /* h_fsz */ - 0xd0, 0x02, 0x80, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x16, 0x00, 0x1c, 0x02, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x49, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ - }, -}; - -static const struct hdmi_preset_conf hdmi_conf_1080i60 = { - .core = { - .h_blank = {0x18, 0x01}, - .v2_blank = {0x32, 0x02}, - .v1_blank = {0x16, 0x00}, - .v_line = {0x65, 0x04}, - .h_line = {0x98, 0x08}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x01}, - .v_blank_f0 = {0x49, 0x02}, - .v_blank_f1 = {0x65, 0x04}, - .h_sync_start = {0x56, 0x00}, - .h_sync_end = {0x82, 0x00}, - .v_sync_line_bef_2 = {0x07, 0x00}, - .v_sync_line_bef_1 = {0x02, 0x00}, - .v_sync_line_aft_2 = {0x39, 0x02}, - .v_sync_line_aft_1 = {0x34, 0x02}, - .v_sync_line_aft_pxl_2 = {0xa4, 0x04}, - .v_sync_line_aft_pxl_1 = {0xa4, 0x04}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x98, 0x08, /* h_fsz */ - 0x18, 0x01, 0x80, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x16, 0x00, 0x1c, 0x02, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x49, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ - }, -}; - -static const struct hdmi_preset_conf hdmi_conf_1080p30 = { - .core = { - .h_blank = {0x18, 0x01}, - .v2_blank = {0x65, 0x04}, - .v1_blank = {0x2d, 0x00}, - .v_line = {0x65, 0x04}, - .h_line = {0x98, 0x08}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x00}, - .v_blank_f0 = {0xff, 0xff}, - .v_blank_f1 = {0xff, 0xff}, - .h_sync_start = {0x56, 0x00}, - .h_sync_end = {0x82, 0x00}, - .v_sync_line_bef_2 = {0x09, 0x00}, - .v_sync_line_bef_1 = {0x04, 0x00}, - .v_sync_line_aft_2 = {0xff, 0xff}, - .v_sync_line_aft_1 = {0xff, 0xff}, - .v_sync_line_aft_pxl_2 = {0xff, 0xff}, - .v_sync_line_aft_pxl_1 = {0xff, 0xff}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x98, 0x08, /* h_fsz */ - 0x18, 0x01, 0x80, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x2d, 0x00, 0x38, 0x04, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ - }, -}; - -static const struct hdmi_preset_conf hdmi_conf_1080p50 = { - .core = { - .h_blank = {0xd0, 0x02}, - .v2_blank = {0x65, 0x04}, - .v1_blank = {0x2d, 0x00}, - .v_line = {0x65, 0x04}, - .h_line = {0x50, 0x0a}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x00}, - .v_blank_f0 = {0xff, 0xff}, - .v_blank_f1 = {0xff, 0xff}, - .h_sync_start = {0x0e, 0x02}, - .h_sync_end = {0x3a, 0x02}, - .v_sync_line_bef_2 = {0x09, 0x00}, - .v_sync_line_bef_1 = {0x04, 0x00}, - .v_sync_line_aft_2 = {0xff, 0xff}, - .v_sync_line_aft_1 = {0xff, 0xff}, - .v_sync_line_aft_pxl_2 = {0xff, 0xff}, - .v_sync_line_aft_pxl_1 = {0xff, 0xff}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x50, 0x0a, /* h_fsz */ - 0xd0, 0x02, 0x80, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x2d, 0x00, 0x38, 0x04, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ - }, -}; - -static const struct hdmi_preset_conf hdmi_conf_1080p60 = { - .core = { - .h_blank = {0x18, 0x01}, - .v2_blank = {0x65, 0x04}, - .v1_blank = {0x2d, 0x00}, - .v_line = {0x65, 0x04}, - .h_line = {0x98, 0x08}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x00}, - .v_blank_f0 = {0xff, 0xff}, - .v_blank_f1 = {0xff, 0xff}, - .h_sync_start = {0x56, 0x00}, - .h_sync_end = {0x82, 0x00}, - .v_sync_line_bef_2 = {0x09, 0x00}, - .v_sync_line_bef_1 = {0x04, 0x00}, - .v_sync_line_aft_2 = {0xff, 0xff}, - .v_sync_line_aft_1 = {0xff, 0xff}, - .v_sync_line_aft_pxl_2 = {0xff, 0xff}, - .v_sync_line_aft_pxl_1 = {0xff, 0xff}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x98, 0x08, /* h_fsz */ - 0x18, 0x01, 0x80, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x2d, 0x00, 0x38, 0x04, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ - }, -}; - -static const struct hdmi_conf hdmi_confs[] = { - { 720, 480, 60, false, hdmiphy_conf27_027, &hdmi_conf_480p60 }, - { 1280, 720, 50, false, hdmiphy_conf74_25, &hdmi_conf_720p50 }, - { 1280, 720, 60, false, hdmiphy_conf74_25, &hdmi_conf_720p60 }, - { 1920, 1080, 30, false, hdmiphy_conf74_176, &hdmi_conf_1080p30 }, -}; - - -static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id) -{ - return readl(hdata->regs + reg_id); -} - -static inline void hdmi_reg_writeb(struct hdmi_context *hdata, - u32 reg_id, u8 value) -{ - writeb(value, hdata->regs + reg_id); -} - -static inline void hdmi_reg_writemask(struct hdmi_context *hdata, - u32 reg_id, u32 value, u32 mask) -{ - u32 old = readl(hdata->regs + reg_id); - value = (value & mask) | (old & ~mask); - writel(value, hdata->regs + reg_id); -} - -static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix) -{ -#define DUMPREG(reg_id) \ - DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \ - readl(hdata->regs + reg_id)) - DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix); - DUMPREG(HDMI_INTC_FLAG); - DUMPREG(HDMI_INTC_CON); - DUMPREG(HDMI_HPD_STATUS); - DUMPREG(HDMI_V13_PHY_RSTOUT); - DUMPREG(HDMI_V13_PHY_VPLL); - DUMPREG(HDMI_V13_PHY_CMU); - DUMPREG(HDMI_V13_CORE_RSTOUT); - - DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix); - DUMPREG(HDMI_CON_0); - DUMPREG(HDMI_CON_1); - DUMPREG(HDMI_CON_2); - DUMPREG(HDMI_SYS_STATUS); - DUMPREG(HDMI_V13_PHY_STATUS); - DUMPREG(HDMI_STATUS_EN); - DUMPREG(HDMI_HPD); - DUMPREG(HDMI_MODE_SEL); - DUMPREG(HDMI_V13_HPD_GEN); - DUMPREG(HDMI_V13_DC_CONTROL); - DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN); - - DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix); - DUMPREG(HDMI_H_BLANK_0); - DUMPREG(HDMI_H_BLANK_1); - DUMPREG(HDMI_V13_V_BLANK_0); - DUMPREG(HDMI_V13_V_BLANK_1); - DUMPREG(HDMI_V13_V_BLANK_2); - DUMPREG(HDMI_V13_H_V_LINE_0); - DUMPREG(HDMI_V13_H_V_LINE_1); - DUMPREG(HDMI_V13_H_V_LINE_2); - DUMPREG(HDMI_VSYNC_POL); - DUMPREG(HDMI_INT_PRO_MODE); - DUMPREG(HDMI_V13_V_BLANK_F_0); - DUMPREG(HDMI_V13_V_BLANK_F_1); - DUMPREG(HDMI_V13_V_BLANK_F_2); - DUMPREG(HDMI_V13_H_SYNC_GEN_0); - DUMPREG(HDMI_V13_H_SYNC_GEN_1); - DUMPREG(HDMI_V13_H_SYNC_GEN_2); - DUMPREG(HDMI_V13_V_SYNC_GEN_1_0); - DUMPREG(HDMI_V13_V_SYNC_GEN_1_1); - DUMPREG(HDMI_V13_V_SYNC_GEN_1_2); - DUMPREG(HDMI_V13_V_SYNC_GEN_2_0); - DUMPREG(HDMI_V13_V_SYNC_GEN_2_1); - DUMPREG(HDMI_V13_V_SYNC_GEN_2_2); - DUMPREG(HDMI_V13_V_SYNC_GEN_3_0); - DUMPREG(HDMI_V13_V_SYNC_GEN_3_1); - DUMPREG(HDMI_V13_V_SYNC_GEN_3_2); - - DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix); - DUMPREG(HDMI_TG_CMD); - DUMPREG(HDMI_TG_H_FSZ_L); - DUMPREG(HDMI_TG_H_FSZ_H); - DUMPREG(HDMI_TG_HACT_ST_L); - DUMPREG(HDMI_TG_HACT_ST_H); - DUMPREG(HDMI_TG_HACT_SZ_L); - DUMPREG(HDMI_TG_HACT_SZ_H); - DUMPREG(HDMI_TG_V_FSZ_L); - DUMPREG(HDMI_TG_V_FSZ_H); - DUMPREG(HDMI_TG_VSYNC_L); - DUMPREG(HDMI_TG_VSYNC_H); - DUMPREG(HDMI_TG_VSYNC2_L); - DUMPREG(HDMI_TG_VSYNC2_H); - DUMPREG(HDMI_TG_VACT_ST_L); - DUMPREG(HDMI_TG_VACT_ST_H); - DUMPREG(HDMI_TG_VACT_SZ_L); - DUMPREG(HDMI_TG_VACT_SZ_H); - DUMPREG(HDMI_TG_FIELD_CHG_L); - DUMPREG(HDMI_TG_FIELD_CHG_H); - DUMPREG(HDMI_TG_VACT_ST2_L); - DUMPREG(HDMI_TG_VACT_ST2_H); - DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L); - DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H); - DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L); - DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H); - DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L); - DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H); - DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L); - DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H); -#undef DUMPREG -} - -static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix) -{ - int i; - -#define DUMPREG(reg_id) \ - DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \ - readl(hdata->regs + reg_id)) - - DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix); - DUMPREG(HDMI_INTC_CON); - DUMPREG(HDMI_INTC_FLAG); - DUMPREG(HDMI_HPD_STATUS); - DUMPREG(HDMI_INTC_CON_1); - DUMPREG(HDMI_INTC_FLAG_1); - DUMPREG(HDMI_PHY_STATUS_0); - DUMPREG(HDMI_PHY_STATUS_PLL); - DUMPREG(HDMI_PHY_CON_0); - DUMPREG(HDMI_PHY_RSTOUT); - DUMPREG(HDMI_PHY_VPLL); - DUMPREG(HDMI_PHY_CMU); - DUMPREG(HDMI_CORE_RSTOUT); - - DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix); - DUMPREG(HDMI_CON_0); - DUMPREG(HDMI_CON_1); - DUMPREG(HDMI_CON_2); - DUMPREG(HDMI_SYS_STATUS); - DUMPREG(HDMI_PHY_STATUS_0); - DUMPREG(HDMI_STATUS_EN); - DUMPREG(HDMI_HPD); - DUMPREG(HDMI_MODE_SEL); - DUMPREG(HDMI_ENC_EN); - DUMPREG(HDMI_DC_CONTROL); - DUMPREG(HDMI_VIDEO_PATTERN_GEN); - - DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix); - DUMPREG(HDMI_H_BLANK_0); - DUMPREG(HDMI_H_BLANK_1); - DUMPREG(HDMI_V2_BLANK_0); - DUMPREG(HDMI_V2_BLANK_1); - DUMPREG(HDMI_V1_BLANK_0); - DUMPREG(HDMI_V1_BLANK_1); - DUMPREG(HDMI_V_LINE_0); - DUMPREG(HDMI_V_LINE_1); - DUMPREG(HDMI_H_LINE_0); - DUMPREG(HDMI_H_LINE_1); - DUMPREG(HDMI_HSYNC_POL); - - DUMPREG(HDMI_VSYNC_POL); - DUMPREG(HDMI_INT_PRO_MODE); - DUMPREG(HDMI_V_BLANK_F0_0); - DUMPREG(HDMI_V_BLANK_F0_1); - DUMPREG(HDMI_V_BLANK_F1_0); - DUMPREG(HDMI_V_BLANK_F1_1); - - DUMPREG(HDMI_H_SYNC_START_0); - DUMPREG(HDMI_H_SYNC_START_1); - DUMPREG(HDMI_H_SYNC_END_0); - DUMPREG(HDMI_H_SYNC_END_1); - - DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0); - DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1); - DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0); - DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1); - - DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0); - DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1); - DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0); - DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1); - - DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0); - DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1); - DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0); - DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1); - - DUMPREG(HDMI_V_BLANK_F2_0); - DUMPREG(HDMI_V_BLANK_F2_1); - DUMPREG(HDMI_V_BLANK_F3_0); - DUMPREG(HDMI_V_BLANK_F3_1); - DUMPREG(HDMI_V_BLANK_F4_0); - DUMPREG(HDMI_V_BLANK_F4_1); - DUMPREG(HDMI_V_BLANK_F5_0); - DUMPREG(HDMI_V_BLANK_F5_1); - - DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0); - DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1); - DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0); - DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1); - DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0); - DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1); - DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0); - DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1); - - DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0); - DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1); - DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0); - DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1); - DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0); - DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1); - DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0); - DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1); - - DUMPREG(HDMI_VACT_SPACE_1_0); - DUMPREG(HDMI_VACT_SPACE_1_1); - DUMPREG(HDMI_VACT_SPACE_2_0); - DUMPREG(HDMI_VACT_SPACE_2_1); - DUMPREG(HDMI_VACT_SPACE_3_0); - DUMPREG(HDMI_VACT_SPACE_3_1); - DUMPREG(HDMI_VACT_SPACE_4_0); - DUMPREG(HDMI_VACT_SPACE_4_1); - DUMPREG(HDMI_VACT_SPACE_5_0); - DUMPREG(HDMI_VACT_SPACE_5_1); - DUMPREG(HDMI_VACT_SPACE_6_0); - DUMPREG(HDMI_VACT_SPACE_6_1); - - DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix); - DUMPREG(HDMI_TG_CMD); - DUMPREG(HDMI_TG_H_FSZ_L); - DUMPREG(HDMI_TG_H_FSZ_H); - DUMPREG(HDMI_TG_HACT_ST_L); - DUMPREG(HDMI_TG_HACT_ST_H); - DUMPREG(HDMI_TG_HACT_SZ_L); - DUMPREG(HDMI_TG_HACT_SZ_H); - DUMPREG(HDMI_TG_V_FSZ_L); - DUMPREG(HDMI_TG_V_FSZ_H); - DUMPREG(HDMI_TG_VSYNC_L); - DUMPREG(HDMI_TG_VSYNC_H); - DUMPREG(HDMI_TG_VSYNC2_L); - DUMPREG(HDMI_TG_VSYNC2_H); - DUMPREG(HDMI_TG_VACT_ST_L); - DUMPREG(HDMI_TG_VACT_ST_H); - DUMPREG(HDMI_TG_VACT_SZ_L); - DUMPREG(HDMI_TG_VACT_SZ_H); - DUMPREG(HDMI_TG_FIELD_CHG_L); - DUMPREG(HDMI_TG_FIELD_CHG_H); - DUMPREG(HDMI_TG_VACT_ST2_L); - DUMPREG(HDMI_TG_VACT_ST2_H); - DUMPREG(HDMI_TG_VACT_ST3_L); - DUMPREG(HDMI_TG_VACT_ST3_H); - DUMPREG(HDMI_TG_VACT_ST4_L); - DUMPREG(HDMI_TG_VACT_ST4_H); - DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L); - DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H); - DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L); - DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H); - DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L); - DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H); - DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L); - DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H); - DUMPREG(HDMI_TG_3D); - - DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix); - DUMPREG(HDMI_AVI_CON); - DUMPREG(HDMI_AVI_HEADER0); - DUMPREG(HDMI_AVI_HEADER1); - DUMPREG(HDMI_AVI_HEADER2); - DUMPREG(HDMI_AVI_CHECK_SUM); - DUMPREG(HDMI_VSI_CON); - DUMPREG(HDMI_VSI_HEADER0); - DUMPREG(HDMI_VSI_HEADER1); - DUMPREG(HDMI_VSI_HEADER2); - for (i = 0; i < 7; ++i) - DUMPREG(HDMI_VSI_DATA(i)); - -#undef DUMPREG -} - -static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix) -{ - if (hdata->is_v13) - hdmi_v13_regs_dump(hdata, prefix); - else - hdmi_v14_regs_dump(hdata, prefix); -} - -static int hdmi_v13_conf_index(struct drm_display_mode *mode) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i) - if (hdmi_v13_confs[i].width == mode->hdisplay && - hdmi_v13_confs[i].height == mode->vdisplay && - hdmi_v13_confs[i].vrefresh == mode->vrefresh && - hdmi_v13_confs[i].interlace == - ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? - true : false)) - return i; - - return -EINVAL; -} - -static int hdmi_v14_conf_index(struct drm_display_mode *mode) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(hdmi_confs); ++i) - if (hdmi_confs[i].width == mode->hdisplay && - hdmi_confs[i].height == mode->vdisplay && - hdmi_confs[i].vrefresh == mode->vrefresh && - hdmi_confs[i].interlace == - ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? - true : false)) - return i; - - return -EINVAL; -} - -static int hdmi_conf_index(struct hdmi_context *hdata, - struct drm_display_mode *mode) -{ - if (hdata->is_v13) - return hdmi_v13_conf_index(mode); - - return hdmi_v14_conf_index(mode); -} - -static bool hdmi_is_connected(void *ctx) -{ - struct hdmi_context *hdata = ctx; - - return hdata->hpd; -} - -static int hdmi_get_edid(void *ctx, struct drm_connector *connector, - u8 *edid, int len) -{ - struct edid *raw_edid; - struct hdmi_context *hdata = ctx; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - if (!hdata->ddc_port) - return -ENODEV; - - raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); - if (raw_edid) { - hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); - memcpy(edid, raw_edid, min((1 + raw_edid->extensions) - * EDID_LENGTH, len)); - DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", - (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"), - raw_edid->width_cm, raw_edid->height_cm); - } else { - return -ENODEV; - } - - return 0; -} - -static int hdmi_v13_check_timing(struct fb_videomode *check_timing) -{ - int i; - - DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n", - check_timing->xres, check_timing->yres, - check_timing->refresh, (check_timing->vmode & - FB_VMODE_INTERLACED) ? true : false); - - for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i) - if (hdmi_v13_confs[i].width == check_timing->xres && - hdmi_v13_confs[i].height == check_timing->yres && - hdmi_v13_confs[i].vrefresh == check_timing->refresh && - hdmi_v13_confs[i].interlace == - ((check_timing->vmode & FB_VMODE_INTERLACED) ? - true : false)) - return 0; - - /* TODO */ - - return -EINVAL; -} - -static int hdmi_v14_check_timing(struct fb_videomode *check_timing) -{ - int i; - - DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n", - check_timing->xres, check_timing->yres, - check_timing->refresh, (check_timing->vmode & - FB_VMODE_INTERLACED) ? true : false); - - for (i = 0; i < ARRAY_SIZE(hdmi_confs); i++) - if (hdmi_confs[i].width == check_timing->xres && - hdmi_confs[i].height == check_timing->yres && - hdmi_confs[i].vrefresh == check_timing->refresh && - hdmi_confs[i].interlace == - ((check_timing->vmode & FB_VMODE_INTERLACED) ? - true : false)) - return 0; - - /* TODO */ - - return -EINVAL; -} - -static int hdmi_check_timing(void *ctx, void *timing) -{ - struct hdmi_context *hdata = ctx; - struct fb_videomode *check_timing = timing; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", check_timing->xres, - check_timing->yres, check_timing->refresh, - check_timing->vmode); - - if (hdata->is_v13) - return hdmi_v13_check_timing(check_timing); - else - return hdmi_v14_check_timing(check_timing); -} - -static void hdmi_set_acr(u32 freq, u8 *acr) -{ - u32 n, cts; - - switch (freq) { - case 32000: - n = 4096; - cts = 27000; - break; - case 44100: - n = 6272; - cts = 30000; - break; - case 88200: - n = 12544; - cts = 30000; - break; - case 176400: - n = 25088; - cts = 30000; - break; - case 48000: - n = 6144; - cts = 27000; - break; - case 96000: - n = 12288; - cts = 27000; - break; - case 192000: - n = 24576; - cts = 27000; - break; - default: - n = 0; - cts = 0; - break; - } - - acr[1] = cts >> 16; - acr[2] = cts >> 8 & 0xff; - acr[3] = cts & 0xff; - - acr[4] = n >> 16; - acr[5] = n >> 8 & 0xff; - acr[6] = n & 0xff; -} - -static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr) -{ - hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]); - hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]); - hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]); - hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]); - hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]); - hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]); - hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]); - hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]); - hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]); - - if (hdata->is_v13) - hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4); - else - hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4); -} - -static void hdmi_audio_init(struct hdmi_context *hdata) -{ - u32 sample_rate, bits_per_sample, frame_size_code; - u32 data_num, bit_ch, sample_frq; - u32 val; - u8 acr[7]; - - sample_rate = 44100; - bits_per_sample = 16; - frame_size_code = 0; - - switch (bits_per_sample) { - case 20: - data_num = 2; - bit_ch = 1; - break; - case 24: - data_num = 3; - bit_ch = 1; - break; - default: - data_num = 1; - bit_ch = 0; - break; - } - - hdmi_set_acr(sample_rate, acr); - hdmi_reg_acr(hdata, acr); - - hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE - | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE - | HDMI_I2S_MUX_ENABLE); - - hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN - | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN); - - hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN); - - sample_frq = (sample_rate == 44100) ? 0 : - (sample_rate == 48000) ? 2 : - (sample_rate == 32000) ? 3 : - (sample_rate == 96000) ? 0xa : 0x0; - - hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS); - hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN); - - val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01; - hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val); - - /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */ - hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5) - | HDMI_I2S_SEL_LRCK(6)); - hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1) - | HDMI_I2S_SEL_SDATA2(4)); - hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1) - | HDMI_I2S_SEL_SDATA2(2)); - hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0)); - - /* I2S_CON_1 & 2 */ - hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE - | HDMI_I2S_L_CH_LOW_POL); - hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE - | HDMI_I2S_SET_BIT_CH(bit_ch) - | HDMI_I2S_SET_SDATA_BIT(data_num) - | HDMI_I2S_BASIC_FORMAT); - - /* Configure register related to CUV information */ - hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0 - | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH - | HDMI_I2S_COPYRIGHT - | HDMI_I2S_LINEAR_PCM - | HDMI_I2S_CONSUMER_FORMAT); - hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER); - hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0)); - hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2 - | HDMI_I2S_SET_SMP_FREQ(sample_frq)); - hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4, - HDMI_I2S_ORG_SMP_FREQ_44_1 - | HDMI_I2S_WORD_LEN_MAX24_24BITS - | HDMI_I2S_WORD_LEN_MAX_24BITS); - - hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD); -} - -static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff) -{ - if (hdata->dvi_mode) - return; - - hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0); - hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ? - HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK); -} - -static void hdmi_conf_reset(struct hdmi_context *hdata) -{ - u32 reg; - - if (hdata->is_v13) - reg = HDMI_V13_CORE_RSTOUT; - else - reg = HDMI_CORE_RSTOUT; - - /* resetting HDMI core */ - hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT); - mdelay(10); - hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT); - mdelay(10); -} - -static void hdmi_conf_init(struct hdmi_context *hdata) -{ - /* enable HPD interrupts */ - hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | - HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); - mdelay(10); - hdmi_reg_writemask(hdata, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL | - HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); - - /* choose HDMI mode */ - hdmi_reg_writemask(hdata, HDMI_MODE_SEL, - HDMI_MODE_HDMI_EN, HDMI_MODE_MASK); - /* disable bluescreen */ - hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN); - - if (hdata->dvi_mode) { - /* choose DVI mode */ - hdmi_reg_writemask(hdata, HDMI_MODE_SEL, - HDMI_MODE_DVI_EN, HDMI_MODE_MASK); - hdmi_reg_writeb(hdata, HDMI_CON_2, - HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS); - } - - if (hdata->is_v13) { - /* choose bluescreen (fecal) color */ - hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12); - hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34); - hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56); - - /* enable AVI packet every vsync, fixes purple line problem */ - hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02); - /* force RGB, look to CEA-861-D, table 7 for more detail */ - hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5); - hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5); - - hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02); - hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02); - hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04); - } else { - /* enable AVI packet every vsync, fixes purple line problem */ - hdmi_reg_writeb(hdata, HDMI_AVI_CON, 0x02); - hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 2 << 5); - hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5); - } -} - -static void hdmi_v13_timing_apply(struct hdmi_context *hdata) -{ - const struct hdmi_v13_preset_conf *conf = - hdmi_v13_confs[hdata->cur_conf].conf; - const struct hdmi_v13_core_regs *core = &conf->core; - const struct hdmi_v13_tg_regs *tg = &conf->tg; - int tries; - - /* setting core registers */ - hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]); - hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]); - hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]); - hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]); - hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]); - hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]); - hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]); - hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]); - hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]); - hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]); - hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]); - hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]); - hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]); - hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]); - hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]); - hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]); - hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]); - hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]); - hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]); - hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]); - hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]); - hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]); - hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]); - hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]); - hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]); - /* Timing generator registers */ - hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l); - hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h); - hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l); - hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h); - - /* waiting for HDMIPHY's PLL to get to steady state */ - for (tries = 100; tries; --tries) { - u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS); - if (val & HDMI_PHY_STATUS_READY) - break; - mdelay(1); - } - /* steady state not achieved */ - if (tries == 0) { - DRM_ERROR("hdmiphy's pll could not reach steady state.\n"); - hdmi_regs_dump(hdata, "timing apply"); - } - - clk_disable(hdata->res.sclk_hdmi); - clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy); - clk_enable(hdata->res.sclk_hdmi); - - /* enable HDMI and timing generator */ - hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN); - if (core->int_pro_mode[0]) - hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN | - HDMI_FIELD_EN); - else - hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN); -} - -static void hdmi_v14_timing_apply(struct hdmi_context *hdata) -{ - const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf; - const struct hdmi_core_regs *core = &conf->core; - const struct hdmi_tg_regs *tg = &conf->tg; - int tries; - - /* setting core registers */ - hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]); - hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]); - hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]); - hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]); - hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]); - hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]); - hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]); - hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]); - hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]); - hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]); - hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]); - hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]); - hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]); - hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]); - hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]); - hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]); - hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]); - hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]); - hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]); - hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]); - hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0, - core->v_sync_line_bef_2[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1, - core->v_sync_line_bef_2[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0, - core->v_sync_line_bef_1[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1, - core->v_sync_line_bef_1[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0, - core->v_sync_line_aft_2[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1, - core->v_sync_line_aft_2[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0, - core->v_sync_line_aft_1[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1, - core->v_sync_line_aft_1[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, - core->v_sync_line_aft_pxl_2[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1, - core->v_sync_line_aft_pxl_2[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, - core->v_sync_line_aft_pxl_1[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1, - core->v_sync_line_aft_pxl_1[1]); - hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]); - hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]); - hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]); - hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]); - hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]); - hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]); - hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]); - hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0, - core->v_sync_line_aft_3[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1, - core->v_sync_line_aft_3[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0, - core->v_sync_line_aft_4[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1, - core->v_sync_line_aft_4[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0, - core->v_sync_line_aft_5[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1, - core->v_sync_line_aft_5[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0, - core->v_sync_line_aft_6[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1, - core->v_sync_line_aft_6[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0, - core->v_sync_line_aft_pxl_3[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1, - core->v_sync_line_aft_pxl_3[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0, - core->v_sync_line_aft_pxl_4[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1, - core->v_sync_line_aft_pxl_4[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0, - core->v_sync_line_aft_pxl_5[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1, - core->v_sync_line_aft_pxl_5[1]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0, - core->v_sync_line_aft_pxl_6[0]); - hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1, - core->v_sync_line_aft_pxl_6[1]); - hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]); - hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]); - hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]); - hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]); - hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]); - hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]); - hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]); - hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]); - hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]); - hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]); - hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]); - hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]); - - /* Timing generator registers */ - hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l); - hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h); - hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l); - hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h); - hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d); - - /* waiting for HDMIPHY's PLL to get to steady state */ - for (tries = 100; tries; --tries) { - u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0); - if (val & HDMI_PHY_STATUS_READY) - break; - mdelay(1); - } - /* steady state not achieved */ - if (tries == 0) { - DRM_ERROR("hdmiphy's pll could not reach steady state.\n"); - hdmi_regs_dump(hdata, "timing apply"); - } - - clk_disable(hdata->res.sclk_hdmi); - clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy); - clk_enable(hdata->res.sclk_hdmi); - - /* enable HDMI and timing generator */ - hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN); - if (core->int_pro_mode[0]) - hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN | - HDMI_FIELD_EN); - else - hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN); -} - -static void hdmi_timing_apply(struct hdmi_context *hdata) -{ - if (hdata->is_v13) - hdmi_v13_timing_apply(hdata); - else - hdmi_v14_timing_apply(hdata); -} - -static int hdmi_phy_ctrl(struct i2c_client *client, u8 reg, u8 bit, - u8 *read_buffer, bool enable) -{ - int ret; - u8 operation[2]; - - operation[0] = reg; - operation[1] = enable ? (read_buffer[reg] & (~(1 << bit))) : - (read_buffer[reg] | (1 << bit)); - read_buffer[reg] = operation[1]; - - ret = i2c_master_send(client, operation, 2); - if (ret != 2) { - DRM_ERROR("failed to turn %s HDMIPHY via I2C\n", - enable ? "enable" : "disable"); - return -EIO; - } - - return 0; -} - -static int hdmi_phy_power_ctrl(struct hdmi_context *hdata, bool enable) -{ - struct hdmi_resources *res = &hdata->res; - u8 operation[2]; - u8 read_buffer[32]; - int ret = 0, i; - - DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable); - - clk_enable(res->hdmiphy); - - /* read full register */ - operation[0] = 0x1; - i2c_master_send(hdata->hdmiphy_port, operation, 1); - - memset(read_buffer, 0x0, sizeof(read_buffer)); - ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32); - if (ret < 0) { - DRM_ERROR("failed to read hdmiphy config\n"); - goto err_clear; - } - - for (i = 0; i < ret; i++) - DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - " - "recv [0x%02x]\n", i, operation[i], read_buffer[i]); - - /* ocspad control */ - operation[0] = 0x0b; - if (enable) - operation[1] = 0xd8; - else - operation[1] = 0x18; - read_buffer[0x0b] = operation[1]; - - ret = i2c_master_send(hdata->hdmiphy_port, operation, 2); - if (ret != 2) { - DRM_ERROR("failed to %s osc pad\n", - enable ? "enable" : "disable"); - goto err_clear; - } - - hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x7, read_buffer, enable); - hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x0, read_buffer, enable); - hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x1, read_buffer, enable); - hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x2, read_buffer, enable); - hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x4, read_buffer, enable); - hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x5, read_buffer, enable); - hdmi_phy_ctrl(hdata->hdmiphy_port, 0x1d, 0x6, read_buffer, enable); - - if (!enable) - hdmi_phy_ctrl(hdata->hdmiphy_port, 0x4, 0x3, read_buffer, 0); - - /* read full register */ - operation[0] = 0x1; - i2c_master_send(hdata->hdmiphy_port, operation, 1); - - memset(read_buffer, 0x0, sizeof(read_buffer)); - ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32); - if (ret < 0) { - DRM_ERROR("failed to read hdmiphy config\n"); - goto err_clear; - } - - for (i = 0; i < ret; i++) - DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - " - "recv [0x%02x]\n", i, operation[i], read_buffer[i]); - - clk_disable(res->hdmiphy); - - return 0; - -err_clear: - clk_disable(res->hdmiphy); - - return ret; -} - -static void hdmiphy_conf_reset(struct hdmi_context *hdata) -{ - u8 buffer[2]; - u32 reg; - - clk_disable(hdata->res.sclk_hdmi); - clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel); - clk_enable(hdata->res.sclk_hdmi); - - /* operation mode */ - buffer[0] = 0x1f; - buffer[1] = 0x00; - - if (hdata->hdmiphy_port) - i2c_master_send(hdata->hdmiphy_port, buffer, 2); - - if (hdata->is_v13) - reg = HDMI_V13_PHY_RSTOUT; - else - reg = HDMI_PHY_RSTOUT; - - /* reset hdmiphy */ - hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT); - mdelay(10); - hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT); - mdelay(10); -} - -static void hdmiphy_conf_apply(struct hdmi_context *hdata) -{ - const u8 *hdmiphy_data; - u8 buffer[32]; - u8 operation[2]; - u8 read_buffer[32] = {0, }; - int ret; - int i; - - if (!hdata->hdmiphy_port) { - DRM_ERROR("hdmiphy is not attached\n"); - return; - } - - /* pixel clock */ - if (hdata->is_v13) - hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data; - else - hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data; - - memcpy(buffer, hdmiphy_data, 32); - ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32); - if (ret != 32) { - DRM_ERROR("failed to configure HDMIPHY via I2C\n"); - return; - } - - mdelay(10); - - /* operation mode */ - operation[0] = 0x1f; - operation[1] = 0x80; - - ret = i2c_master_send(hdata->hdmiphy_port, operation, 2); - if (ret != 2) { - DRM_ERROR("failed to enable hdmiphy\n"); - return; - } - - ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32); - if (ret < 0) { - DRM_ERROR("failed to read hdmiphy config\n"); - return; - } - - for (i = 0; i < ret; i++) - DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - " - "recv [0x%02x]\n", i, buffer[i], read_buffer[i]); -} - -static void hdmi_conf_apply(struct hdmi_context *hdata) -{ - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - hdmiphy_conf_reset(hdata); - hdmiphy_conf_apply(hdata); - - mutex_lock(&hdata->hdmi_mutex); - hdmi_conf_reset(hdata); - hdmi_conf_init(hdata); - mutex_unlock(&hdata->hdmi_mutex); - - hdmi_audio_init(hdata); - - /* setting core registers */ - hdmi_timing_apply(hdata); - hdmi_audio_control(hdata, true); - - hdmi_regs_dump(hdata, "start"); -} - -static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_display_mode *m; - struct hdmi_context *hdata = ctx; - int index; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - drm_mode_set_crtcinfo(adjusted_mode, 0); - - if (hdata->is_v13) - index = hdmi_v13_conf_index(adjusted_mode); - else - index = hdmi_v14_conf_index(adjusted_mode); - - /* just return if user desired mode exists. */ - if (index >= 0) - return; - - /* - * otherwise, find the most suitable mode among modes and change it - * to adjusted_mode. - */ - list_for_each_entry(m, &connector->modes, head) { - if (hdata->is_v13) - index = hdmi_v13_conf_index(m); - else - index = hdmi_v14_conf_index(m); - - if (index >= 0) { - DRM_INFO("desired mode doesn't exist so\n"); - DRM_INFO("use the most suitable mode among modes.\n"); - memcpy(adjusted_mode, m, sizeof(*m)); - break; - } - } -} - -static void hdmi_mode_set(void *ctx, void *mode) -{ - struct hdmi_context *hdata = ctx; - int conf_idx; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - conf_idx = hdmi_conf_index(hdata, mode); - if (conf_idx >= 0) - hdata->cur_conf = conf_idx; - else - DRM_DEBUG_KMS("not supported mode\n"); -} - -static void hdmi_get_max_resol(void *ctx, unsigned int *width, - unsigned int *height) -{ - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - *width = MAX_WIDTH; - *height = MAX_HEIGHT; -} - -static void hdmi_commit(void *ctx) -{ - struct hdmi_context *hdata = ctx; - struct exynos_drm_private *drm_priv; - struct exynos_drm_hdmi_context *drm_hdmi_ctx; - struct drm_device *drm_dev; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - hdmi_conf_apply(hdata); - - /* - * parent_ctx is created at hdmi_probe() and - * parent_ctx->drm_dev is set at hdmi_subdrv_probe() - */ - drm_hdmi_ctx = hdata->parent_ctx; - drm_dev = drm_hdmi_ctx->drm_dev; - if (drm_dev) - drm_priv = drm_dev->dev_private; - else - return; - - /* - * if iommu support for exynos drm was enabled, this function is - * called first time(!hdata->iommu_on) then enable iommu unit. - */ - if (drm_priv->vmm && !hdata->iommu_on) { - int ret; - - ret = exynos_drm_iommu_activate(drm_priv->vmm, hdata->dev); - if (ret < 0) { - DRM_ERROR("failed to activate iommu.\n"); - return; - } - - hdata->iommu_on = true; - } -} - -static void hdmi_poweron(struct hdmi_context *hdata) -{ - struct hdmi_resources *res = &hdata->res; - int ret; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - mutex_lock(&hdata->hdmi_mutex); - if (hdata->powered) { - mutex_unlock(&hdata->hdmi_mutex); - return; - } - - hdata->powered = true; - - if (hdata->cfg_hpd) - hdata->cfg_hpd(true); - mutex_unlock(&hdata->hdmi_mutex); - - pm_runtime_get_sync(hdata->dev); - - ret = hdmi_phy_power_ctrl(hdata, true); - if (ret) { - DRM_ERROR("failed to control phy power\n"); - return; - } - - if (hdata->iommu_on) { - struct exynos_drm_private *drm_priv; - struct exynos_drm_hdmi_context *drm_hdmi_ctx; - struct drm_device *drm_dev; - - drm_hdmi_ctx = hdata->parent_ctx; - drm_dev = drm_hdmi_ctx->drm_dev; - - if (drm_dev) - drm_priv = drm_dev->dev_private; - else - return; - - ret = exynos_drm_iommu_activate(drm_priv->vmm, hdata->dev); - if (ret < 0) { - DRM_ERROR("failed to activate iommu.\n"); - return; - } - } - - regulator_bulk_enable(res->regul_count, res->regul_bulk); - clk_enable(res->hdmiphy); - clk_enable(res->hdmi); - clk_enable(res->sclk_hdmi); -} - -static void hdmi_poweroff(struct hdmi_context *hdata) -{ - struct hdmi_resources *res = &hdata->res; - int ret; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - mutex_lock(&hdata->hdmi_mutex); - if (!hdata->powered) - goto out; - mutex_unlock(&hdata->hdmi_mutex); - - /* - * The TV power domain needs any condition of hdmiphy to turn off and - * its reset state seems to meet the condition. - */ - hdmiphy_conf_reset(hdata); - - clk_disable(res->sclk_hdmi); - clk_disable(res->hdmi); - clk_disable(res->hdmiphy); - regulator_bulk_disable(res->regul_count, res->regul_bulk); - - mutex_lock(&hdata->hdmi_mutex); - if (hdata->cfg_hpd) - hdata->cfg_hpd(false); - - ret = hdmi_phy_power_ctrl(hdata, false); - if (ret) { - DRM_ERROR("failed to control phy power\n"); - return; - } - - if (hdata->iommu_on) { - struct exynos_drm_private *drm_priv; - struct exynos_drm_hdmi_context *drm_hdmi_ctx; - struct drm_device *drm_dev; - - drm_hdmi_ctx = hdata->parent_ctx; - drm_dev = drm_hdmi_ctx->drm_dev; - if (drm_dev) - drm_priv = drm_dev->dev_private; - else { - if (hdata->cfg_hpd) - hdata->cfg_hpd(true); - - regulator_bulk_enable(res->regul_count, - res->regul_bulk); - - clk_enable(res->hdmiphy); - clk_enable(res->hdmi); - clk_enable(res->sclk_hdmi); - - mutex_unlock(&hdata->hdmi_mutex); - return; - } - - exynos_drm_iommu_deactivate(drm_priv->vmm, hdata->dev); - } - - hdata->powered = false; - -out: - mutex_unlock(&hdata->hdmi_mutex); - pm_runtime_put_sync(hdata->dev); -} - -static void hdmi_dpms(void *ctx, int mode) -{ - struct hdmi_context *hdata = ctx; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - switch (mode) { - case DRM_MODE_DPMS_ON: - hdmi_poweron(hdata); - break; - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: - hdmi_poweroff(hdata); - break; - default: - DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); - break; - } -} - -static struct exynos_hdmi_ops hdmi_ops = { - /* display */ - .is_connected = hdmi_is_connected, - .get_edid = hdmi_get_edid, - .check_timing = hdmi_check_timing, - - /* manager */ - .mode_fixup = hdmi_mode_fixup, - .mode_set = hdmi_mode_set, - .get_max_resol = hdmi_get_max_resol, - .commit = hdmi_commit, - .dpms = hdmi_dpms, -}; - -static irqreturn_t hdmi_external_irq_thread(int irq, void *arg) -{ - struct exynos_drm_hdmi_context *ctx = arg; - struct hdmi_context *hdata = ctx->ctx; - - if (!hdata->get_hpd) - goto out; - - mutex_lock(&hdata->hdmi_mutex); - hdata->hpd = hdata->get_hpd(); - mutex_unlock(&hdata->hdmi_mutex); - - if (ctx->drm_dev) - drm_helper_hpd_irq_event(ctx->drm_dev); - -out: - return IRQ_HANDLED; -} - -static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg) -{ - struct exynos_drm_hdmi_context *ctx = arg; - struct hdmi_context *hdata = ctx->ctx; - u32 intc_flag; - - intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG); - /* clearing flags for HPD plug/unplug */ - if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) { - DRM_DEBUG_KMS("unplugged\n"); - hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, - HDMI_INTC_FLAG_HPD_UNPLUG); - } - if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) { - DRM_DEBUG_KMS("plugged\n"); - hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, - HDMI_INTC_FLAG_HPD_PLUG); - } - - mutex_lock(&hdata->hdmi_mutex); - hdata->hpd = hdmi_reg_read(hdata, HDMI_HPD_STATUS); - if (hdata->powered && hdata->hpd) { - mutex_unlock(&hdata->hdmi_mutex); - goto out; - } - mutex_unlock(&hdata->hdmi_mutex); - - if (ctx->drm_dev) - drm_helper_hpd_irq_event(ctx->drm_dev); - -out: - return IRQ_HANDLED; -} - -static int __devinit hdmi_resources_init(struct hdmi_context *hdata) -{ - struct device *dev = hdata->dev; - struct hdmi_resources *res = &hdata->res; - static char *supply[] = { - /* FIXME: control HDMI_EN gpio using fixed regulator */ - /* "hdmi-en", */ - "vdd", - "vdd_osc", - "vdd_pll", - }; - int i, ret; - - DRM_DEBUG_KMS("HDMI resource init\n"); - - memset(res, 0, sizeof *res); - - /* get clocks, power */ - res->hdmi = clk_get(dev, "hdmi"); - if (IS_ERR_OR_NULL(res->hdmi)) { - DRM_ERROR("failed to get clock 'hdmi'\n"); - goto fail; - } - res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); - if (IS_ERR_OR_NULL(res->sclk_hdmi)) { - DRM_ERROR("failed to get clock 'sclk_hdmi'\n"); - goto fail; - } - res->sclk_pixel = clk_get(dev, "sclk_pixel"); - if (IS_ERR_OR_NULL(res->sclk_pixel)) { - DRM_ERROR("failed to get clock 'sclk_pixel'\n"); - goto fail; - } - res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy"); - if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) { - DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n"); - goto fail; - } - res->hdmiphy = clk_get(dev, "hdmiphy"); - if (IS_ERR_OR_NULL(res->hdmiphy)) { - DRM_ERROR("failed to get clock 'hdmiphy'\n"); - goto fail; - } - - clk_set_parent(res->sclk_hdmi, res->sclk_pixel); - - res->regul_bulk = kzalloc(ARRAY_SIZE(supply) * - sizeof res->regul_bulk[0], GFP_KERNEL); - if (!res->regul_bulk) { - DRM_ERROR("failed to get memory for regulators\n"); - goto fail; - } - for (i = 0; i < ARRAY_SIZE(supply); ++i) { - res->regul_bulk[i].supply = supply[i]; - res->regul_bulk[i].consumer = NULL; - } - ret = regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk); - if (ret) { - DRM_ERROR("failed to get regulators\n"); - goto fail; - } - res->regul_count = ARRAY_SIZE(supply); - - return 0; -fail: - DRM_ERROR("HDMI resource init - failed\n"); - return -ENODEV; -} - -static int hdmi_resources_cleanup(struct hdmi_context *hdata) -{ - struct hdmi_resources *res = &hdata->res; - - regulator_bulk_free(res->regul_count, res->regul_bulk); - /* kfree is NULL-safe */ - kfree(res->regul_bulk); - if (!IS_ERR_OR_NULL(res->hdmiphy)) - clk_put(res->hdmiphy); - if (!IS_ERR_OR_NULL(res->sclk_hdmiphy)) - clk_put(res->sclk_hdmiphy); - if (!IS_ERR_OR_NULL(res->sclk_pixel)) - clk_put(res->sclk_pixel); - if (!IS_ERR_OR_NULL(res->sclk_hdmi)) - clk_put(res->sclk_hdmi); - if (!IS_ERR_OR_NULL(res->hdmi)) - clk_put(res->hdmi); - memset(res, 0, sizeof *res); - - return 0; -} - -static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy; - -void hdmi_attach_ddc_client(struct i2c_client *ddc) -{ - if (ddc) - hdmi_ddc = ddc; -} - -void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy) -{ - if (hdmiphy) - hdmi_hdmiphy = hdmiphy; -} - -static int __devinit hdmi_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct exynos_drm_hdmi_context *drm_hdmi_ctx; - struct hdmi_context *hdata; - struct exynos_drm_hdmi_pdata *pdata; - struct resource *res; - int ret; - - DRM_DEBUG_KMS("[%d]\n", __LINE__); - - pdata = pdev->dev.platform_data; - if (!pdata) { - DRM_ERROR("no platform data specified\n"); - return -EINVAL; - } - - drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL); - if (!drm_hdmi_ctx) { - DRM_ERROR("failed to allocate common hdmi context.\n"); - return -ENOMEM; - } - - hdata = kzalloc(sizeof(struct hdmi_context), GFP_KERNEL); - if (!hdata) { - DRM_ERROR("out of memory\n"); - kfree(drm_hdmi_ctx); - return -ENOMEM; - } - - mutex_init(&hdata->hdmi_mutex); - - drm_hdmi_ctx->ctx = (void *)hdata; - hdata->parent_ctx = (void *)drm_hdmi_ctx; - - platform_set_drvdata(pdev, drm_hdmi_ctx); - - hdata->is_v13 = pdata->is_v13; - hdata->cfg_hpd = pdata->cfg_hpd; - hdata->get_hpd = pdata->get_hpd; - hdata->dev = dev; - - ret = hdmi_resources_init(hdata); - if (ret) { - ret = -EINVAL; - goto err_data; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - DRM_ERROR("failed to find registers\n"); - ret = -ENOENT; - goto err_resource; - } - - hdata->regs_res = request_mem_region(res->start, resource_size(res), - dev_name(dev)); - if (!hdata->regs_res) { - DRM_ERROR("failed to claim register region\n"); - ret = -ENOENT; - goto err_resource; - } - - hdata->regs = ioremap(res->start, resource_size(res)); - if (!hdata->regs) { - DRM_ERROR("failed to map registers\n"); - ret = -ENXIO; - goto err_req_region; - } - - /* DDC i2c driver */ - if (i2c_add_driver(&ddc_driver)) { - DRM_ERROR("failed to register ddc i2c driver\n"); - ret = -ENOENT; - goto err_iomap; - } - - hdata->ddc_port = hdmi_ddc; - - /* hdmiphy i2c driver */ - if (i2c_add_driver(&hdmiphy_driver)) { - DRM_ERROR("failed to register hdmiphy i2c driver\n"); - ret = -ENOENT; - goto err_ddc; - } - - hdata->hdmiphy_port = hdmi_hdmiphy; - - /* - * HDMI PHY power off - * HDMI PHY is on as default configuration - * So, HDMI PHY must be turned off if it's not used - */ - ret = hdmi_phy_power_ctrl(hdata, false); - if (ret) { - DRM_ERROR("failed to control phy power\n"); - goto err_hdmiphy; - } - - hdata->external_irq = platform_get_irq_byname(pdev, "external_irq"); - if (hdata->external_irq < 0) { - DRM_ERROR("failed to get platform irq\n"); - ret = hdata->external_irq; - goto err_hdmiphy; - } - - hdata->internal_irq = platform_get_irq_byname(pdev, "internal_irq"); - if (hdata->internal_irq < 0) { - DRM_ERROR("failed to get platform internal irq\n"); - ret = hdata->internal_irq; - goto err_hdmiphy; - } - - ret = request_threaded_irq(hdata->external_irq, NULL, - hdmi_external_irq_thread, IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "hdmi_external", drm_hdmi_ctx); - if (ret) { - DRM_ERROR("failed to register hdmi internal interrupt\n"); - goto err_hdmiphy; - } - - if (hdata->cfg_hpd) - hdata->cfg_hpd(false); - - ret = request_threaded_irq(hdata->internal_irq, NULL, - hdmi_internal_irq_thread, IRQF_ONESHOT, - "hdmi_internal", drm_hdmi_ctx); - if (ret) { - DRM_ERROR("failed to register hdmi internal interrupt\n"); - goto err_free_irq; - } - - /* register specific callbacks to common hdmi. */ - exynos_hdmi_ops_register(&hdmi_ops); - - pm_runtime_enable(dev); - - return 0; - -err_free_irq: - free_irq(hdata->external_irq, drm_hdmi_ctx); -err_hdmiphy: - i2c_del_driver(&hdmiphy_driver); -err_ddc: - i2c_del_driver(&ddc_driver); -err_iomap: - iounmap(hdata->regs); -err_req_region: - release_mem_region(hdata->regs_res->start, - resource_size(hdata->regs_res)); -err_resource: - hdmi_resources_cleanup(hdata); -err_data: - kfree(hdata); - kfree(drm_hdmi_ctx); - return ret; -} - -static int __devexit hdmi_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev); - struct hdmi_context *hdata = ctx->ctx; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - pm_runtime_disable(dev); - - free_irq(hdata->internal_irq, hdata); - - hdmi_resources_cleanup(hdata); - - iounmap(hdata->regs); - - release_mem_region(hdata->regs_res->start, - resource_size(hdata->regs_res)); - - /* hdmiphy i2c driver */ - i2c_del_driver(&hdmiphy_driver); - /* DDC i2c driver */ - i2c_del_driver(&ddc_driver); - - kfree(hdata); - kfree(ctx); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int hdmi_suspend(struct device *dev) -{ - struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev); - struct hdmi_context *hdata = ctx->ctx; - - disable_irq(hdata->internal_irq); - disable_irq(hdata->external_irq); - - hdata->hpd = false; - if (ctx->drm_dev) - drm_helper_hpd_irq_event(ctx->drm_dev); - - hdmi_poweroff(hdata); - - return 0; -} - -static int hdmi_resume(struct device *dev) -{ - struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev); - struct hdmi_context *hdata = ctx->ctx; - - enable_irq(hdata->external_irq); - enable_irq(hdata->internal_irq); - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(hdmi_pm_ops, hdmi_suspend, hdmi_resume); - -struct platform_driver hdmi_driver = { - .probe = hdmi_probe, - .remove = __devexit_p(hdmi_remove), - .driver = { - .name = "exynos4-hdmi", - .owner = THIS_MODULE, - .pm = &hdmi_pm_ops, - }, -}; diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.h b/drivers/gpu/drm/exynos/exynos_hdmi.h deleted file mode 100644 index 1c3b6d8..0000000 --- a/drivers/gpu/drm/exynos/exynos_hdmi.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_HDMI_H_ -#define _EXYNOS_HDMI_H_ - -void hdmi_attach_ddc_client(struct i2c_client *ddc); -void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy); - -extern struct i2c_driver hdmiphy_driver; -extern struct i2c_driver ddc_driver; - -#endif diff --git a/drivers/gpu/drm/exynos/exynos_hdmiphy.c b/drivers/gpu/drm/exynos/exynos_hdmiphy.c deleted file mode 100644 index 9fe2995..0000000 --- a/drivers/gpu/drm/exynos/exynos_hdmiphy.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics Co.Ltd - * Authors: - * Seung-Woo Kim - * Inki Dae - * - * 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 "drmP.h" - -#include -#include -#include - -#include "exynos_drm_drv.h" -#include "exynos_hdmi.h" - - -static int hdmiphy_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - hdmi_attach_hdmiphy_client(client); - - dev_info(&client->adapter->dev, "attached s5p_hdmiphy " - "into i2c adapter successfully\n"); - - return 0; -} - -static int hdmiphy_remove(struct i2c_client *client) -{ - dev_info(&client->adapter->dev, "detached s5p_hdmiphy " - "from i2c adapter successfully\n"); - - return 0; -} - -static const struct i2c_device_id hdmiphy_id[] = { - { "s5p_hdmiphy", 0 }, - { }, -}; - -struct i2c_driver hdmiphy_driver = { - .driver = { - .name = "s5p-hdmiphy", - .owner = THIS_MODULE, - }, - .id_table = hdmiphy_id, - .probe = hdmiphy_probe, - .remove = __devexit_p(hdmiphy_remove), - .command = NULL, -}; -EXPORT_SYMBOL(hdmiphy_driver); diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c deleted file mode 100644 index 206cbbc..0000000 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ /dev/null @@ -1,1111 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics Co.Ltd - * Authors: - * Seung-Woo Kim - * Inki Dae - * Joonyoung Shim - * - * Based on drivers/media/video/s5p-tv/mixer_reg.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 "drmP.h" - -#include "regs-mixer.h" -#include "regs-vp.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "exynos_drm_drv.h" -#include "exynos_drm_hdmi.h" - -#define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev)) - -struct hdmi_win_data { - dma_addr_t dma_addr; - void __iomem *vaddr; - dma_addr_t chroma_dma_addr; - void __iomem *chroma_vaddr; - uint32_t pixel_format; - unsigned int bpp; - unsigned int crtc_x; - unsigned int crtc_y; - unsigned int crtc_width; - unsigned int crtc_height; - unsigned int fb_x; - unsigned int fb_y; - unsigned int fb_width; - unsigned int fb_height; - unsigned int src_width; - unsigned int src_height; - unsigned int mode_width; - unsigned int mode_height; - unsigned int scan_flags; -}; - -struct mixer_resources { - int irq; - void __iomem *mixer_regs; - void __iomem *vp_regs; - spinlock_t reg_slock; - struct clk *mixer; - struct clk *vp; - struct clk *sclk_mixer; - struct clk *sclk_hdmi; - struct clk *sclk_dac; -}; - -struct mixer_context { - struct device *dev; - int pipe; - bool interlace; - bool powered; - u32 int_en; - - struct mutex mixer_mutex; - struct mixer_resources mixer_res; - struct hdmi_win_data win_data[MIXER_WIN_NR]; -}; - -static const u8 filter_y_horiz_tap8[] = { - 0, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 0, 0, 0, - 0, 2, 4, 5, 6, 6, 6, 6, - 6, 5, 5, 4, 3, 2, 1, 1, - 0, -6, -12, -16, -18, -20, -21, -20, - -20, -18, -16, -13, -10, -8, -5, -2, - 127, 126, 125, 121, 114, 107, 99, 89, - 79, 68, 57, 46, 35, 25, 16, 8, -}; - -static const u8 filter_y_vert_tap4[] = { - 0, -3, -6, -8, -8, -8, -8, -7, - -6, -5, -4, -3, -2, -1, -1, 0, - 127, 126, 124, 118, 111, 102, 92, 81, - 70, 59, 48, 37, 27, 19, 11, 5, - 0, 5, 11, 19, 27, 37, 48, 59, - 70, 81, 92, 102, 111, 118, 124, 126, - 0, 0, -1, -1, -2, -3, -4, -5, - -6, -7, -8, -8, -8, -8, -6, -3, -}; - -static const u8 filter_cr_horiz_tap4[] = { - 0, -3, -6, -8, -8, -8, -8, -7, - -6, -5, -4, -3, -2, -1, -1, 0, - 127, 126, 124, 118, 111, 102, 92, 81, - 70, 59, 48, 37, 27, 19, 11, 5, -}; - -static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id) -{ - return readl(res->vp_regs + reg_id); -} - -static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id, - u32 val) -{ - writel(val, res->vp_regs + reg_id); -} - -static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id, - u32 val, u32 mask) -{ - u32 old = vp_reg_read(res, reg_id); - - val = (val & mask) | (old & ~mask); - writel(val, res->vp_regs + reg_id); -} - -static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id) -{ - return readl(res->mixer_regs + reg_id); -} - -static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id, - u32 val) -{ - writel(val, res->mixer_regs + reg_id); -} - -static inline void mixer_reg_writemask(struct mixer_resources *res, - u32 reg_id, u32 val, u32 mask) -{ - u32 old = mixer_reg_read(res, reg_id); - - val = (val & mask) | (old & ~mask); - writel(val, res->mixer_regs + reg_id); -} - -static void mixer_regs_dump(struct mixer_context *ctx) -{ -#define DUMPREG(reg_id) \ -do { \ - DRM_DEBUG_KMS(#reg_id " = %08x\n", \ - (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \ -} while (0) - - DUMPREG(MXR_STATUS); - DUMPREG(MXR_CFG); - DUMPREG(MXR_INT_EN); - DUMPREG(MXR_INT_STATUS); - - DUMPREG(MXR_LAYER_CFG); - DUMPREG(MXR_VIDEO_CFG); - - DUMPREG(MXR_GRAPHIC0_CFG); - DUMPREG(MXR_GRAPHIC0_BASE); - DUMPREG(MXR_GRAPHIC0_SPAN); - DUMPREG(MXR_GRAPHIC0_WH); - DUMPREG(MXR_GRAPHIC0_SXY); - DUMPREG(MXR_GRAPHIC0_DXY); - - DUMPREG(MXR_GRAPHIC1_CFG); - DUMPREG(MXR_GRAPHIC1_BASE); - DUMPREG(MXR_GRAPHIC1_SPAN); - DUMPREG(MXR_GRAPHIC1_WH); - DUMPREG(MXR_GRAPHIC1_SXY); - DUMPREG(MXR_GRAPHIC1_DXY); -#undef DUMPREG -} - -static void vp_regs_dump(struct mixer_context *ctx) -{ -#define DUMPREG(reg_id) \ -do { \ - DRM_DEBUG_KMS(#reg_id " = %08x\n", \ - (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \ -} while (0) - - DUMPREG(VP_ENABLE); - DUMPREG(VP_SRESET); - DUMPREG(VP_SHADOW_UPDATE); - DUMPREG(VP_FIELD_ID); - DUMPREG(VP_MODE); - DUMPREG(VP_IMG_SIZE_Y); - DUMPREG(VP_IMG_SIZE_C); - DUMPREG(VP_PER_RATE_CTRL); - DUMPREG(VP_TOP_Y_PTR); - DUMPREG(VP_BOT_Y_PTR); - DUMPREG(VP_TOP_C_PTR); - DUMPREG(VP_BOT_C_PTR); - DUMPREG(VP_ENDIAN_MODE); - DUMPREG(VP_SRC_H_POSITION); - DUMPREG(VP_SRC_V_POSITION); - DUMPREG(VP_SRC_WIDTH); - DUMPREG(VP_SRC_HEIGHT); - DUMPREG(VP_DST_H_POSITION); - DUMPREG(VP_DST_V_POSITION); - DUMPREG(VP_DST_WIDTH); - DUMPREG(VP_DST_HEIGHT); - DUMPREG(VP_H_RATIO); - DUMPREG(VP_V_RATIO); - -#undef DUMPREG -} - -static inline void vp_filter_set(struct mixer_resources *res, - int reg_id, const u8 *data, unsigned int size) -{ - /* assure 4-byte align */ - BUG_ON(size & 3); - for (; size; size -= 4, reg_id += 4, data += 4) { - u32 val = (data[0] << 24) | (data[1] << 16) | - (data[2] << 8) | data[3]; - vp_reg_write(res, reg_id, val); - } -} - -static void vp_default_filter(struct mixer_resources *res) -{ - vp_filter_set(res, VP_POLY8_Y0_LL, - filter_y_horiz_tap8, sizeof filter_y_horiz_tap8); - vp_filter_set(res, VP_POLY4_Y0_LL, - filter_y_vert_tap4, sizeof filter_y_vert_tap4); - vp_filter_set(res, VP_POLY4_C0_LL, - filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4); -} - -static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) -{ - struct mixer_resources *res = &ctx->mixer_res; - - /* block update on vsync */ - mixer_reg_writemask(res, MXR_STATUS, enable ? - MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE); - - vp_reg_write(res, VP_SHADOW_UPDATE, enable ? - VP_SHADOW_UPDATE_ENABLE : 0); -} - -static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height) -{ - struct mixer_resources *res = &ctx->mixer_res; - u32 val; - - /* choosing between interlace and progressive mode */ - val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE : - MXR_CFG_SCAN_PROGRASSIVE); - - /* choosing between porper HD and SD mode */ - if (height == 480) - val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD; - else if (height == 576) - val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD; - else if (height == 720) - val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD; - else if (height == 1080) - val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD; - else - val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD; - - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK); -} - -static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) -{ - struct mixer_resources *res = &ctx->mixer_res; - u32 val; - - if (height == 480) { - val = MXR_CFG_RGB601_0_255; - } else if (height == 576) { - val = MXR_CFG_RGB601_0_255; - } else if (height == 720) { - val = MXR_CFG_RGB709_16_235; - mixer_reg_write(res, MXR_CM_COEFF_Y, - (1 << 30) | (94 << 20) | (314 << 10) | - (32 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CB, - (972 << 20) | (851 << 10) | (225 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CR, - (225 << 20) | (820 << 10) | (1004 << 0)); - } else if (height == 1080) { - val = MXR_CFG_RGB709_16_235; - mixer_reg_write(res, MXR_CM_COEFF_Y, - (1 << 30) | (94 << 20) | (314 << 10) | - (32 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CB, - (972 << 20) | (851 << 10) | (225 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CR, - (225 << 20) | (820 << 10) | (1004 << 0)); - } else { - val = MXR_CFG_RGB709_16_235; - mixer_reg_write(res, MXR_CM_COEFF_Y, - (1 << 30) | (94 << 20) | (314 << 10) | - (32 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CB, - (972 << 20) | (851 << 10) | (225 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CR, - (225 << 20) | (820 << 10) | (1004 << 0)); - } - - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); -} - -static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable) -{ - struct mixer_resources *res = &ctx->mixer_res; - u32 val = enable ? ~0 : 0; - - switch (win) { - case 0: - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); - break; - case 1: - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); - break; - case 2: - vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE); - break; - } -} - -static void mixer_run(struct mixer_context *ctx) -{ - struct mixer_resources *res = &ctx->mixer_res; - - mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN); - - mixer_regs_dump(ctx); -} - -static void vp_video_buffer(struct mixer_context *ctx, int win) -{ - struct mixer_resources *res = &ctx->mixer_res; - unsigned long flags; - struct hdmi_win_data *win_data; - unsigned int x_ratio, y_ratio; - unsigned int buf_num; - dma_addr_t luma_addr[2], chroma_addr[2]; - bool tiled_mode = false; - bool crcb_mode = false; - u32 val; - - win_data = &ctx->win_data[win]; - - switch (win_data->pixel_format) { - case DRM_FORMAT_NV12MT: - tiled_mode = true; - case DRM_FORMAT_NV12M: - crcb_mode = false; - buf_num = 2; - break; - /* TODO: single buffer format NV12, NV21 */ - default: - /* ignore pixel format at disable time */ - if (!win_data->dma_addr) - break; - - DRM_ERROR("pixel format for vp is wrong [%d].\n", - win_data->pixel_format); - return; - } - - /* scaling feature: (src << 16) / dst */ - x_ratio = (win_data->src_width << 16) / win_data->crtc_width; - y_ratio = (win_data->src_height << 16) / win_data->crtc_height; - - if (buf_num == 2) { - luma_addr[0] = win_data->dma_addr; - chroma_addr[0] = win_data->chroma_dma_addr; - } else { - luma_addr[0] = win_data->dma_addr; - chroma_addr[0] = win_data->dma_addr - + (win_data->fb_width * win_data->fb_height); - } - - if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) { - ctx->interlace = true; - if (tiled_mode) { - luma_addr[1] = luma_addr[0] + 0x40; - chroma_addr[1] = chroma_addr[0] + 0x40; - } else { - luma_addr[1] = luma_addr[0] + win_data->fb_width; - chroma_addr[1] = chroma_addr[0] + win_data->fb_width; - } - } else { - ctx->interlace = false; - luma_addr[1] = 0; - chroma_addr[1] = 0; - } - - spin_lock_irqsave(&res->reg_slock, flags); - mixer_vsync_set_update(ctx, false); - - /* interlace or progressive scan mode */ - val = (ctx->interlace ? ~0 : 0); - vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP); - - /* setup format */ - val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12); - val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR); - vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK); - - /* setting size of input image */ - vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) | - VP_IMG_VSIZE(win_data->fb_height)); - /* chroma height has to reduced by 2 to avoid chroma distorions */ - vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) | - VP_IMG_VSIZE(win_data->fb_height / 2)); - - vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width); - vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height); - vp_reg_write(res, VP_SRC_H_POSITION, - VP_SRC_H_POSITION_VAL(win_data->fb_x)); - vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y); - - vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width); - vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x); - if (ctx->interlace) { - vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2); - vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2); - } else { - vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height); - vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y); - } - - vp_reg_write(res, VP_H_RATIO, x_ratio); - vp_reg_write(res, VP_V_RATIO, y_ratio); - - vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE); - - /* set buffer address to vp */ - vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]); - vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]); - vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]); - vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]); - - mixer_cfg_scan(ctx, win_data->mode_height); - mixer_cfg_rgb_fmt(ctx, win_data->mode_height); - mixer_cfg_layer(ctx, win, true); - mixer_run(ctx); - - mixer_vsync_set_update(ctx, true); - spin_unlock_irqrestore(&res->reg_slock, flags); - - vp_regs_dump(ctx); -} - -static void mixer_graph_buffer(struct mixer_context *ctx, int win) -{ - struct mixer_resources *res = &ctx->mixer_res; - unsigned long flags; - struct hdmi_win_data *win_data; - unsigned int x_ratio, y_ratio; - unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; - dma_addr_t dma_addr; - unsigned int fmt; - u32 val; - - win_data = &ctx->win_data[win]; - - #define RGB565 4 - #define ARGB1555 5 - #define ARGB4444 6 - #define ARGB8888 7 - - switch (win_data->bpp) { - case 16: - fmt = ARGB4444; - break; - case 32: - fmt = ARGB8888; - break; - default: - fmt = ARGB8888; - } - - /* 2x scaling feature */ - x_ratio = 0; - y_ratio = 0; - - dst_x_offset = win_data->crtc_x; - dst_y_offset = win_data->crtc_y; - - /* converting dma address base and source offset */ - dma_addr = win_data->dma_addr - + (win_data->fb_x * win_data->bpp >> 3) - + (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3); - src_x_offset = 0; - src_y_offset = 0; - - if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) - ctx->interlace = true; - else - ctx->interlace = false; - - spin_lock_irqsave(&res->reg_slock, flags); - mixer_vsync_set_update(ctx, false); - - /* setup format */ - mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win), - MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK); - - /* setup geometry */ - mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width); - - val = MXR_GRP_WH_WIDTH(win_data->crtc_width); - val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height); - val |= MXR_GRP_WH_H_SCALE(x_ratio); - val |= MXR_GRP_WH_V_SCALE(y_ratio); - mixer_reg_write(res, MXR_GRAPHIC_WH(win), val); - - /* setup offsets in source image */ - val = MXR_GRP_SXY_SX(src_x_offset); - val |= MXR_GRP_SXY_SY(src_y_offset); - mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val); - - /* setup offsets in display image */ - val = MXR_GRP_DXY_DX(dst_x_offset); - val |= MXR_GRP_DXY_DY(dst_y_offset); - mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val); - - /* set buffer address to mixer */ - mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr); - - mixer_cfg_scan(ctx, win_data->mode_height); - mixer_cfg_rgb_fmt(ctx, win_data->mode_height); - mixer_cfg_layer(ctx, win, true); - mixer_run(ctx); - - mixer_vsync_set_update(ctx, true); - spin_unlock_irqrestore(&res->reg_slock, flags); -} - -static void vp_win_reset(struct mixer_context *ctx) -{ - struct mixer_resources *res = &ctx->mixer_res; - int tries = 100; - - vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING); - for (tries = 100; tries; --tries) { - /* waiting until VP_SRESET_PROCESSING is 0 */ - if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING) - break; - mdelay(10); - } - WARN(tries == 0, "failed to reset Video Processor\n"); -} - -static void mixer_win_reset(struct mixer_context *ctx) -{ - struct mixer_resources *res = &ctx->mixer_res; - unsigned long flags; - u32 val; /* value stored to register */ - - spin_lock_irqsave(&res->reg_slock, flags); - mixer_vsync_set_update(ctx, false); - - mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK); - - /* set output in RGB888 mode */ - mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK); - - /* 16 beat burst in DMA */ - mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST, - MXR_STATUS_BURST_MASK); - - /* setting default layer priority: layer1 > layer0 > video - * because typical usage scenario would be - * layer1 - OSD - * layer0 - framebuffer - * video - video overlay - */ - val = MXR_LAYER_CFG_GRP1_VAL(3); - val |= MXR_LAYER_CFG_GRP0_VAL(2); - val |= MXR_LAYER_CFG_VP_VAL(1); - mixer_reg_write(res, MXR_LAYER_CFG, val); - - /* setting background color */ - mixer_reg_write(res, MXR_BG_COLOR0, 0x008080); - mixer_reg_write(res, MXR_BG_COLOR1, 0x008080); - mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); - - /* setting graphical layers */ - val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */ - val |= MXR_GRP_CFG_WIN_BLEND_EN; - val |= MXR_GRP_CFG_BLEND_PRE_MUL; - val |= MXR_GRP_CFG_PIXEL_BLEND_EN; - val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */ - - /* the same configuration for both layers */ - mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val); - mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val); - - /* setting video layers */ - val = MXR_GRP_CFG_ALPHA_VAL(0); - mixer_reg_write(res, MXR_VIDEO_CFG, val); - - /* configuration of Video Processor Registers */ - vp_win_reset(ctx); - vp_default_filter(res); - - /* disable all layers */ - mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE); - mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE); - mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE); - - mixer_vsync_set_update(ctx, true); - spin_unlock_irqrestore(&res->reg_slock, flags); -} - -static void mixer_poweron(struct mixer_context *ctx) -{ - struct mixer_resources *res = &ctx->mixer_res; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - mutex_lock(&ctx->mixer_mutex); - if (ctx->powered) { - mutex_unlock(&ctx->mixer_mutex); - return; - } - ctx->powered = true; - mutex_unlock(&ctx->mixer_mutex); - - pm_runtime_get_sync(ctx->dev); - - clk_enable(res->mixer); - clk_enable(res->vp); - clk_enable(res->sclk_mixer); - - mixer_reg_write(res, MXR_INT_EN, ctx->int_en); - mixer_win_reset(ctx); -} - -static void mixer_poweroff(struct mixer_context *ctx) -{ - struct mixer_resources *res = &ctx->mixer_res; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - mutex_lock(&ctx->mixer_mutex); - if (!ctx->powered) - goto out; - mutex_unlock(&ctx->mixer_mutex); - - ctx->int_en = mixer_reg_read(res, MXR_INT_EN); - - clk_disable(res->mixer); - clk_disable(res->vp); - clk_disable(res->sclk_mixer); - - pm_runtime_put_sync(ctx->dev); - - mutex_lock(&ctx->mixer_mutex); - ctx->powered = false; - -out: - mutex_unlock(&ctx->mixer_mutex); -} - -static int mixer_enable_vblank(void *ctx, int pipe) -{ - struct mixer_context *mixer_ctx = ctx; - struct mixer_resources *res = &mixer_ctx->mixer_res; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - mixer_ctx->pipe = pipe; - - /* enable vsync interrupt */ - mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC, - MXR_INT_EN_VSYNC); - - return 0; -} - -static void mixer_disable_vblank(void *ctx) -{ - struct mixer_context *mixer_ctx = ctx; - struct mixer_resources *res = &mixer_ctx->mixer_res; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - /* disable vsync interrupt */ - mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); -} - -static void mixer_dpms(void *ctx, int mode) -{ - struct mixer_context *mixer_ctx = ctx; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - switch (mode) { - case DRM_MODE_DPMS_ON: - mixer_poweron(mixer_ctx); - break; - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: - mixer_poweroff(mixer_ctx); - break; - default: - DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); - break; - } -} - -static void mixer_win_mode_set(void *ctx, - struct exynos_drm_overlay *overlay) -{ - struct mixer_context *mixer_ctx = ctx; - struct hdmi_win_data *win_data; - int win; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - if (!overlay) { - DRM_ERROR("overlay is NULL\n"); - return; - } - - DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n", - overlay->fb_width, overlay->fb_height, - overlay->fb_x, overlay->fb_y, - overlay->crtc_width, overlay->crtc_height, - overlay->crtc_x, overlay->crtc_y); - - win = overlay->zpos; - if (win == DEFAULT_ZPOS) - win = MIXER_DEFAULT_WIN; - - if (win < 0 || win > MIXER_WIN_NR) { - DRM_ERROR("mixer window[%d] is wrong\n", win); - return; - } - - win_data = &mixer_ctx->win_data[win]; - - win_data->dma_addr = overlay->dma_addr[0]; - win_data->vaddr = overlay->vaddr[0]; - win_data->chroma_dma_addr = overlay->dma_addr[1]; - win_data->chroma_vaddr = overlay->vaddr[1]; - win_data->pixel_format = overlay->pixel_format; - win_data->bpp = overlay->bpp; - - win_data->crtc_x = overlay->crtc_x; - win_data->crtc_y = overlay->crtc_y; - win_data->crtc_width = overlay->crtc_width; - win_data->crtc_height = overlay->crtc_height; - - win_data->fb_x = overlay->fb_x; - win_data->fb_y = overlay->fb_y; - win_data->fb_width = overlay->fb_width; - win_data->fb_height = overlay->fb_height; - win_data->src_width = overlay->src_width; - win_data->src_height = overlay->src_height; - - win_data->mode_width = overlay->mode_width; - win_data->mode_height = overlay->mode_height; - - win_data->scan_flags = overlay->scan_flag; -} - -static void mixer_win_commit(void *ctx, int win) -{ - struct mixer_context *mixer_ctx = ctx; - - DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); - - if (win > 1) - vp_video_buffer(mixer_ctx, win); - else - mixer_graph_buffer(mixer_ctx, win); -} - -static void mixer_win_disable(void *ctx, int win) -{ - struct mixer_context *mixer_ctx = ctx; - struct mixer_resources *res = &mixer_ctx->mixer_res; - unsigned long flags; - - DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); - - spin_lock_irqsave(&res->reg_slock, flags); - mixer_vsync_set_update(mixer_ctx, false); - - mixer_cfg_layer(mixer_ctx, win, false); - - mixer_vsync_set_update(mixer_ctx, true); - spin_unlock_irqrestore(&res->reg_slock, flags); -} - -static struct exynos_mixer_ops mixer_ops = { - /* manager */ - .enable_vblank = mixer_enable_vblank, - .disable_vblank = mixer_disable_vblank, - .dpms = mixer_dpms, - - /* overlay */ - .win_mode_set = mixer_win_mode_set, - .win_commit = mixer_win_commit, - .win_disable = mixer_win_disable, -}; - -/* for pageflip event */ -static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc) -{ - struct exynos_drm_private *dev_priv = drm_dev->dev_private; - struct drm_pending_vblank_event *e, *t; - struct timeval now; - unsigned long flags; - bool is_checked = false; - - spin_lock_irqsave(&drm_dev->event_lock, flags); - - list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list, - base.link) { - /* if event's pipe isn't same as crtc then ignore it. */ - if (crtc != e->pipe) - continue; - - is_checked = true; - do_gettimeofday(&now); - e->event.sequence = 0; - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; - - list_move_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); - } - - if (is_checked) - /* - * call drm_vblank_put only in case that drm_vblank_get was - * called. - */ - if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0) - drm_vblank_put(drm_dev, crtc); - - spin_unlock_irqrestore(&drm_dev->event_lock, flags); -} - -static irqreturn_t mixer_irq_handler(int irq, void *arg) -{ - struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg; - struct mixer_context *ctx = drm_hdmi_ctx->ctx; - struct mixer_resources *res = &ctx->mixer_res; - u32 val, base, shadow; - - spin_lock(&res->reg_slock); - - /* read interrupt status for handling and clearing flags for VSYNC */ - val = mixer_reg_read(res, MXR_INT_STATUS); - - /* handling VSYNC */ - if (val & MXR_INT_STATUS_VSYNC) { - /* interlace scan need to check shadow register */ - if (ctx->interlace) { - base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0)); - shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0)); - if (base != shadow) - goto out; - - base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1)); - shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1)); - if (base != shadow) - goto out; - } - - drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe); - mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe); - } - -out: - /* clear interrupts */ - if (~val & MXR_INT_EN_VSYNC) { - /* vsync interrupt use different bit for read and clear */ - val &= ~MXR_INT_EN_VSYNC; - val |= MXR_INT_CLEAR_VSYNC; - } - mixer_reg_write(res, MXR_INT_STATUS, val); - - spin_unlock(&res->reg_slock); - - return IRQ_HANDLED; -} - -static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx, - struct platform_device *pdev) -{ - struct mixer_context *mixer_ctx = ctx->ctx; - struct device *dev = &pdev->dev; - struct mixer_resources *mixer_res = &mixer_ctx->mixer_res; - struct resource *res; - int ret; - - spin_lock_init(&mixer_res->reg_slock); - - mixer_res->mixer = clk_get(dev, "mixer"); - if (IS_ERR_OR_NULL(mixer_res->mixer)) { - dev_err(dev, "failed to get clock 'mixer'\n"); - ret = -ENODEV; - goto fail; - } - mixer_res->vp = clk_get(dev, "vp"); - if (IS_ERR_OR_NULL(mixer_res->vp)) { - dev_err(dev, "failed to get clock 'vp'\n"); - ret = -ENODEV; - goto fail; - } - mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer"); - if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) { - dev_err(dev, "failed to get clock 'sclk_mixer'\n"); - ret = -ENODEV; - goto fail; - } - mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); - if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) { - dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); - ret = -ENODEV; - goto fail; - } - mixer_res->sclk_dac = clk_get(dev, "sclk_dac"); - if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) { - dev_err(dev, "failed to get clock 'sclk_dac'\n"); - ret = -ENODEV; - goto fail; - } - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr"); - if (res == NULL) { - dev_err(dev, "get memory resource failed.\n"); - ret = -ENXIO; - goto fail; - } - - clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi); - - mixer_res->mixer_regs = ioremap(res->start, resource_size(res)); - if (mixer_res->mixer_regs == NULL) { - dev_err(dev, "register mapping failed.\n"); - ret = -ENXIO; - goto fail; - } - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp"); - if (res == NULL) { - dev_err(dev, "get memory resource failed.\n"); - ret = -ENXIO; - goto fail_mixer_regs; - } - - mixer_res->vp_regs = ioremap(res->start, resource_size(res)); - if (mixer_res->vp_regs == NULL) { - dev_err(dev, "register mapping failed.\n"); - ret = -ENXIO; - goto fail_mixer_regs; - } - - res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq"); - if (res == NULL) { - dev_err(dev, "get interrupt resource failed.\n"); - ret = -ENXIO; - goto fail_vp_regs; - } - - ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx); - if (ret) { - dev_err(dev, "request interrupt failed.\n"); - goto fail_vp_regs; - } - mixer_res->irq = res->start; - - return 0; - -fail_vp_regs: - iounmap(mixer_res->vp_regs); - -fail_mixer_regs: - iounmap(mixer_res->mixer_regs); - -fail: - if (!IS_ERR_OR_NULL(mixer_res->sclk_dac)) - clk_put(mixer_res->sclk_dac); - if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) - clk_put(mixer_res->sclk_hdmi); - if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer)) - clk_put(mixer_res->sclk_mixer); - if (!IS_ERR_OR_NULL(mixer_res->vp)) - clk_put(mixer_res->vp); - if (!IS_ERR_OR_NULL(mixer_res->mixer)) - clk_put(mixer_res->mixer); - return ret; -} - -static void mixer_resources_cleanup(struct mixer_context *ctx) -{ - struct mixer_resources *res = &ctx->mixer_res; - - free_irq(res->irq, ctx); - - iounmap(res->vp_regs); - iounmap(res->mixer_regs); -} - -static int __devinit mixer_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct exynos_drm_hdmi_context *drm_hdmi_ctx; - struct mixer_context *ctx; - int ret; - - dev_info(dev, "probe start\n"); - - drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL); - if (!drm_hdmi_ctx) { - DRM_ERROR("failed to allocate common hdmi context.\n"); - return -ENOMEM; - } - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) { - DRM_ERROR("failed to alloc mixer context.\n"); - kfree(drm_hdmi_ctx); - return -ENOMEM; - } - - mutex_init(&ctx->mixer_mutex); - - ctx->dev = &pdev->dev; - drm_hdmi_ctx->ctx = (void *)ctx; - - platform_set_drvdata(pdev, drm_hdmi_ctx); - - /* acquire resources: regs, irqs, clocks */ - ret = mixer_resources_init(drm_hdmi_ctx, pdev); - if (ret) - goto fail; - - /* register specific callback point to common hdmi. */ - exynos_mixer_ops_register(&mixer_ops); - - pm_runtime_enable(dev); - - return 0; - - -fail: - dev_info(dev, "probe failed\n"); - return ret; -} - -static int mixer_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct exynos_drm_hdmi_context *drm_hdmi_ctx = - platform_get_drvdata(pdev); - struct mixer_context *ctx = drm_hdmi_ctx->ctx; - - dev_info(dev, "remove successful\n"); - - pm_runtime_disable(&pdev->dev); - - mixer_resources_cleanup(ctx); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int mixer_suspend(struct device *dev) -{ - struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev); - struct mixer_context *ctx = drm_hdmi_ctx->ctx; - - mixer_poweroff(ctx); - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL); - -struct platform_driver mixer_driver = { - .driver = { - .name = "s5p-mixer", - .owner = THIS_MODULE, - .pm = &mixer_pm_ops, - }, - .probe = mixer_probe, - .remove = __devexit_p(mixer_remove), -}; diff --git a/drivers/gpu/drm/exynos/regs-fimc.h b/drivers/gpu/drm/exynos/regs-fimc.h deleted file mode 100644 index be014b3..0000000 --- a/drivers/gpu/drm/exynos/regs-fimc.h +++ /dev/null @@ -1,669 +0,0 @@ -/* drivers/gpu/drm/exynos/regs-fimc.h - * - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * Register definition file for Samsung Camera Interface (FIMC) driver - * - * 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. -*/ - -#ifndef SAMSUNG_REGS_FIMC_H -#define SAMSUNG_REGS_FIMC_H - -/* - * Register part -*/ -/* Input source format */ -#define EXYNOS_CISRCFMT (0x00) -/* Window offset */ -#define EXYNOS_CIWDOFST (0x04) -/* Global control */ -#define EXYNOS_CIGCTRL (0x08) -/* Window offset 2 */ -#define EXYNOS_CIWDOFST2 (0x14) -/* Y 1st frame start address for output DMA */ -#define EXYNOS_CIOYSA1 (0x18) -/* Y 2nd frame start address for output DMA */ -#define EXYNOS_CIOYSA2 (0x1c) -/* Y 3rd frame start address for output DMA */ -#define EXYNOS_CIOYSA3 (0x20) -/* Y 4th frame start address for output DMA */ -#define EXYNOS_CIOYSA4 (0x24) -/* Cb 1st frame start address for output DMA */ -#define EXYNOS_CIOCBSA1 (0x28) -/* Cb 2nd frame start address for output DMA */ -#define EXYNOS_CIOCBSA2 (0x2c) -/* Cb 3rd frame start address for output DMA */ -#define EXYNOS_CIOCBSA3 (0x30) -/* Cb 4th frame start address for output DMA */ -#define EXYNOS_CIOCBSA4 (0x34) -/* Cr 1st frame start address for output DMA */ -#define EXYNOS_CIOCRSA1 (0x38) -/* Cr 2nd frame start address for output DMA */ -#define EXYNOS_CIOCRSA2 (0x3c) -/* Cr 3rd frame start address for output DMA */ -#define EXYNOS_CIOCRSA3 (0x40) -/* Cr 4th frame start address for output DMA */ -#define EXYNOS_CIOCRSA4 (0x44) -/* Target image format */ -#define EXYNOS_CITRGFMT (0x48) -/* Output DMA control */ -#define EXYNOS_CIOCTRL (0x4c) -/* Pre-scaler control 1 */ -#define EXYNOS_CISCPRERATIO (0x50) -/* Pre-scaler control 2 */ -#define EXYNOS_CISCPREDST (0x54) -/* Main scaler control */ -#define EXYNOS_CISCCTRL (0x58) -/* Target area */ -#define EXYNOS_CITAREA (0x5c) -/* Status */ -#define EXYNOS_CISTATUS (0x64) -/* Status2 */ -#define EXYNOS_CISTATUS2 (0x68) -/* Image capture enable command */ -#define EXYNOS_CIIMGCPT (0xc0) -/* Capture sequence */ -#define EXYNOS_CICPTSEQ (0xc4) -/* Image effects */ -#define EXYNOS_CIIMGEFF (0xd0) -/* Y frame start address for input DMA */ -#define EXYNOS_CIIYSA0 (0xd4) -/* Cb frame start address for input DMA */ -#define EXYNOS_CIICBSA0 (0xd8) -/* Cr frame start address for input DMA */ -#define EXYNOS_CIICRSA0 (0xdc) -/* Input DMA Y Line Skip */ -#define EXYNOS_CIILINESKIP_Y (0xec) -/* Input DMA Cb Line Skip */ -#define EXYNOS_CIILINESKIP_CB (0xf0) -/* Input DMA Cr Line Skip */ -#define EXYNOS_CIILINESKIP_CR (0xf4) -/* Real input DMA image size */ -#define EXYNOS_CIREAL_ISIZE (0xf8) -/* Input DMA control */ -#define EXYNOS_MSCTRL (0xfc) -/* Y frame start address for input DMA */ -#define EXYNOS_CIIYSA1 (0x144) -/* Cb frame start address for input DMA */ -#define EXYNOS_CIICBSA1 (0x148) -/* Cr frame start address for input DMA */ -#define EXYNOS_CIICRSA1 (0x14c) -/* Output DMA Y offset */ -#define EXYNOS_CIOYOFF (0x168) -/* Output DMA CB offset */ -#define EXYNOS_CIOCBOFF (0x16c) -/* Output DMA CR offset */ -#define EXYNOS_CIOCROFF (0x170) -/* Input DMA Y offset */ -#define EXYNOS_CIIYOFF (0x174) -/* Input DMA CB offset */ -#define EXYNOS_CIICBOFF (0x178) -/* Input DMA CR offset */ -#define EXYNOS_CIICROFF (0x17c) -/* Input DMA original image size */ -#define EXYNOS_ORGISIZE (0x180) -/* Output DMA original image size */ -#define EXYNOS_ORGOSIZE (0x184) -/* Real output DMA image size */ -#define EXYNOS_CIEXTEN (0x188) -/* DMA parameter */ -#define EXYNOS_CIDMAPARAM (0x18c) -/* MIPI CSI image format */ -#define EXYNOS_CSIIMGFMT (0x194) -/* FIMC Clock Source Select */ -#define EXYNOS_MISC_FIMC (0x198) - -/* Add for FIMC v5.1 */ -/* Output Frame Buffer Sequence */ -#define EXYNOS_CIFCNTSEQ (0x1fc) -/* Y 5th frame start address for output DMA */ -#define EXYNOS_CIOYSA5 (0x200) -/* Y 6th frame start address for output DMA */ -#define EXYNOS_CIOYSA6 (0x204) -/* Y 7th frame start address for output DMA */ -#define EXYNOS_CIOYSA7 (0x208) -/* Y 8th frame start address for output DMA */ -#define EXYNOS_CIOYSA8 (0x20c) -/* Y 9th frame start address for output DMA */ -#define EXYNOS_CIOYSA9 (0x210) -/* Y 10th frame start address for output DMA */ -#define EXYNOS_CIOYSA10 (0x214) -/* Y 11th frame start address for output DMA */ -#define EXYNOS_CIOYSA11 (0x218) -/* Y 12th frame start address for output DMA */ -#define EXYNOS_CIOYSA12 (0x21c) -/* Y 13th frame start address for output DMA */ -#define EXYNOS_CIOYSA13 (0x220) -/* Y 14th frame start address for output DMA */ -#define EXYNOS_CIOYSA14 (0x224) -/* Y 15th frame start address for output DMA */ -#define EXYNOS_CIOYSA15 (0x228) -/* Y 16th frame start address for output DMA */ -#define EXYNOS_CIOYSA16 (0x22c) -/* Y 17th frame start address for output DMA */ -#define EXYNOS_CIOYSA17 (0x230) -/* Y 18th frame start address for output DMA */ -#define EXYNOS_CIOYSA18 (0x234) -/* Y 19th frame start address for output DMA */ -#define EXYNOS_CIOYSA19 (0x238) -/* Y 20th frame start address for output DMA */ -#define EXYNOS_CIOYSA20 (0x23c) -/* Y 21th frame start address for output DMA */ -#define EXYNOS_CIOYSA21 (0x240) -/* Y 22th frame start address for output DMA */ -#define EXYNOS_CIOYSA22 (0x244) -/* Y 23th frame start address for output DMA */ -#define EXYNOS_CIOYSA23 (0x248) -/* Y 24th frame start address for output DMA */ -#define EXYNOS_CIOYSA24 (0x24c) -/* Y 25th frame start address for output DMA */ -#define EXYNOS_CIOYSA25 (0x250) -/* Y 26th frame start address for output DMA */ -#define EXYNOS_CIOYSA26 (0x254) -/* Y 27th frame start address for output DMA */ -#define EXYNOS_CIOYSA27 (0x258) -/* Y 28th frame start address for output DMA */ -#define EXYNOS_CIOYSA28 (0x25c) -/* Y 29th frame start address for output DMA */ -#define EXYNOS_CIOYSA29 (0x260) -/* Y 30th frame start address for output DMA */ -#define EXYNOS_CIOYSA30 (0x264) -/* Y 31th frame start address for output DMA */ -#define EXYNOS_CIOYSA31 (0x268) -/* Y 32th frame start address for output DMA */ -#define EXYNOS_CIOYSA32 (0x26c) - -/* CB 5th frame start address for output DMA */ -#define EXYNOS_CIOCBSA5 (0x270) -/* CB 6th frame start address for output DMA */ -#define EXYNOS_CIOCBSA6 (0x274) -/* CB 7th frame start address for output DMA */ -#define EXYNOS_CIOCBSA7 (0x278) -/* CB 8th frame start address for output DMA */ -#define EXYNOS_CIOCBSA8 (0x27c) -/* CB 9th frame start address for output DMA */ -#define EXYNOS_CIOCBSA9 (0x280) -/* CB 10th frame start address for output DMA */ -#define EXYNOS_CIOCBSA10 (0x284) -/* CB 11th frame start address for output DMA */ -#define EXYNOS_CIOCBSA11 (0x288) -/* CB 12th frame start address for output DMA */ -#define EXYNOS_CIOCBSA12 (0x28c) -/* CB 13th frame start address for output DMA */ -#define EXYNOS_CIOCBSA13 (0x290) -/* CB 14th frame start address for output DMA */ -#define EXYNOS_CIOCBSA14 (0x294) -/* CB 15th frame start address for output DMA */ -#define EXYNOS_CIOCBSA15 (0x298) -/* CB 16th frame start address for output DMA */ -#define EXYNOS_CIOCBSA16 (0x29c) -/* CB 17th frame start address for output DMA */ -#define EXYNOS_CIOCBSA17 (0x2a0) -/* CB 18th frame start address for output DMA */ -#define EXYNOS_CIOCBSA18 (0x2a4) -/* CB 19th frame start address for output DMA */ -#define EXYNOS_CIOCBSA19 (0x2a8) -/* CB 20th frame start address for output DMA */ -#define EXYNOS_CIOCBSA20 (0x2ac) -/* CB 21th frame start address for output DMA */ -#define EXYNOS_CIOCBSA21 (0x2b0) -/* CB 22th frame start address for output DMA */ -#define EXYNOS_CIOCBSA22 (0x2b4) -/* CB 23th frame start address for output DMA */ -#define EXYNOS_CIOCBSA23 (0x2b8) -/* CB 24th frame start address for output DMA */ -#define EXYNOS_CIOCBSA24 (0x2bc) -/* CB 25th frame start address for output DMA */ -#define EXYNOS_CIOCBSA25 (0x2c0) -/* CB 26th frame start address for output DMA */ -#define EXYNOS_CIOCBSA26 (0x2c4) -/* CB 27th frame start address for output DMA */ -#define EXYNOS_CIOCBSA27 (0x2c8) -/* CB 28th frame start address for output DMA */ -#define EXYNOS_CIOCBSA28 (0x2cc) -/* CB 29th frame start address for output DMA */ -#define EXYNOS_CIOCBSA29 (0x2d0) -/* CB 30th frame start address for output DMA */ -#define EXYNOS_CIOCBSA30 (0x2d4) -/* CB 31th frame start address for output DMA */ -#define EXYNOS_CIOCBSA31 (0x2d8) -/* CB 32th frame start address for output DMA */ -#define EXYNOS_CIOCBSA32 (0x2dc) - -/* CR 5th frame start address for output DMA */ -#define EXYNOS_CIOCRSA5 (0x2e0) -/* CR 6th frame start address for output DMA */ -#define EXYNOS_CIOCRSA6 (0x2e4) -/* CR 7th frame start address for output DMA */ -#define EXYNOS_CIOCRSA7 (0x2e8) -/* CR 8th frame start address for output DMA */ -#define EXYNOS_CIOCRSA8 (0x2ec) -/* CR 9th frame start address for output DMA */ -#define EXYNOS_CIOCRSA9 (0x2f0) -/* CR 10th frame start address for output DMA */ -#define EXYNOS_CIOCRSA10 (0x2f4) -/* CR 11th frame start address for output DMA */ -#define EXYNOS_CIOCRSA11 (0x2f8) -/* CR 12th frame start address for output DMA */ -#define EXYNOS_CIOCRSA12 (0x2fc) -/* CR 13th frame start address for output DMA */ -#define EXYNOS_CIOCRSA13 (0x300) -/* CR 14th frame start address for output DMA */ -#define EXYNOS_CIOCRSA14 (0x304) -/* CR 15th frame start address for output DMA */ -#define EXYNOS_CIOCRSA15 (0x308) -/* CR 16th frame start address for output DMA */ -#define EXYNOS_CIOCRSA16 (0x30c) -/* CR 17th frame start address for output DMA */ -#define EXYNOS_CIOCRSA17 (0x310) -/* CR 18th frame start address for output DMA */ -#define EXYNOS_CIOCRSA18 (0x314) -/* CR 19th frame start address for output DMA */ -#define EXYNOS_CIOCRSA19 (0x318) -/* CR 20th frame start address for output DMA */ -#define EXYNOS_CIOCRSA20 (0x31c) -/* CR 21th frame start address for output DMA */ -#define EXYNOS_CIOCRSA21 (0x320) -/* CR 22th frame start address for output DMA */ -#define EXYNOS_CIOCRSA22 (0x324) -/* CR 23th frame start address for output DMA */ -#define EXYNOS_CIOCRSA23 (0x328) -/* CR 24th frame start address for output DMA */ -#define EXYNOS_CIOCRSA24 (0x32c) -/* CR 25th frame start address for output DMA */ -#define EXYNOS_CIOCRSA25 (0x330) -/* CR 26th frame start address for output DMA */ -#define EXYNOS_CIOCRSA26 (0x334) -/* CR 27th frame start address for output DMA */ -#define EXYNOS_CIOCRSA27 (0x338) -/* CR 28th frame start address for output DMA */ -#define EXYNOS_CIOCRSA28 (0x33c) -/* CR 29th frame start address for output DMA */ -#define EXYNOS_CIOCRSA29 (0x340) -/* CR 30th frame start address for output DMA */ -#define EXYNOS_CIOCRSA30 (0x344) -/* CR 31th frame start address for output DMA */ -#define EXYNOS_CIOCRSA31 (0x348) -/* CR 32th frame start address for output DMA */ -#define EXYNOS_CIOCRSA32 (0x34c) - -/* - * Macro part -*/ -/* frame start address 1 ~ 4, 5 ~ 32 */ -/* Number of Default PingPong Memory */ -#define DEF_PP 4 -#define EXYNOS_CIOYSA(__x) \ - (((__x) < DEF_PP) ? \ - (EXYNOS_CIOYSA1 + (__x) * 4) : \ - (EXYNOS_CIOYSA5 + ((__x) - DEF_PP) * 4)) -#define EXYNOS_CIOCBSA(__x) \ - (((__x) < DEF_PP) ? \ - (EXYNOS_CIOCBSA1 + (__x) * 4) : \ - (EXYNOS_CIOCBSA5 + ((__x) - DEF_PP) * 4)) -#define EXYNOS_CIOCRSA(__x) \ - (((__x) < DEF_PP) ? \ - (EXYNOS_CIOCRSA1 + (__x) * 4) : \ - (EXYNOS_CIOCRSA5 + ((__x) - DEF_PP) * 4)) -/* Number of Default PingPong Memory */ -#define DEF_IPP 1 -#define EXYNOS_CIIYSA(__x) \ - (((__x) < DEF_IPP) ? \ - (EXYNOS_CIIYSA0) : (EXYNOS_CIIYSA1)) -#define EXYNOS_CIICBSA(__x) \ - (((__x) < DEF_IPP) ? \ - (EXYNOS_CIICBSA0) : (EXYNOS_CIICBSA1)) -#define EXYNOS_CIICRSA(__x) \ - (((__x) < DEF_IPP) ? \ - (EXYNOS_CIICRSA0) : (EXYNOS_CIICRSA1)) - -#define EXYNOS_CISRCFMT_SOURCEHSIZE(x) ((x) << 16) -#define EXYNOS_CISRCFMT_SOURCEVSIZE(x) ((x) << 0) - -#define EXYNOS_CIWDOFST_WINHOROFST(x) ((x) << 16) -#define EXYNOS_CIWDOFST_WINVEROFST(x) ((x) << 0) - -#define EXYNOS_CIWDOFST2_WINHOROFST2(x) ((x) << 16) -#define EXYNOS_CIWDOFST2_WINVEROFST2(x) ((x) << 0) - -#define EXYNOS_CITRGFMT_TARGETHSIZE(x) (((x) & 0x1fff) << 16) -#define EXYNOS_CITRGFMT_TARGETVSIZE(x) (((x) & 0x1fff) << 0) - -#define EXYNOS_CISCPRERATIO_SHFACTOR(x) ((x) << 28) -#define EXYNOS_CISCPRERATIO_PREHORRATIO(x) ((x) << 16) -#define EXYNOS_CISCPRERATIO_PREVERRATIO(x) ((x) << 0) - -#define EXYNOS_CISCPREDST_PREDSTWIDTH(x) ((x) << 16) -#define EXYNOS_CISCPREDST_PREDSTHEIGHT(x) ((x) << 0) - -#define EXYNOS_CISCCTRL_MAINHORRATIO(x) ((x) << 16) -#define EXYNOS_CISCCTRL_MAINVERRATIO(x) ((x) << 0) - -#define EXYNOS_CITAREA_TARGET_AREA(x) ((x) << 0) - -#define EXYNOS_CISTATUS_GET_FRAME_COUNT(x) (((x) >> 26) & 0x3) -#define EXYNOS_CISTATUS_GET_FRAME_END(x) (((x) >> 17) & 0x1) -#define EXYNOS_CISTATUS_GET_LAST_CAPTURE_END(x) (((x) >> 16) & 0x1) -#define EXYNOS_CISTATUS_GET_LCD_STATUS(x) (((x) >> 9) & 0x1) -#define EXYNOS_CISTATUS_GET_ENVID_STATUS(x) (((x) >> 8) & 0x1) - -#define EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(x) (((x) >> 7) & 0x3f) -#define EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(x) ((x) & 0x3f) - -#define EXYNOS_CIIMGEFF_FIN(x) ((x & 0x7) << 26) -#define EXYNOS_CIIMGEFF_PAT_CB(x) ((x) << 13) -#define EXYNOS_CIIMGEFF_PAT_CR(x) ((x) << 0) - -#define EXYNOS_CIILINESKIP(x) (((x) & 0xf) << 24) - -#define EXYNOS_CIREAL_ISIZE_HEIGHT(x) ((x) << 16) -#define EXYNOS_CIREAL_ISIZE_WIDTH(x) ((x) << 0) - -#define EXYNOS_MSCTRL_SUCCESSIVE_COUNT(x) ((x) << 24) -#define EXYNOS_MSCTRL_GET_INDMA_STATUS(x) ((x) & 0x1) - -#define EXYNOS_CIOYOFF_VERTICAL(x) ((x) << 16) -#define EXYNOS_CIOYOFF_HORIZONTAL(x) ((x) << 0) - -#define EXYNOS_CIOCBOFF_VERTICAL(x) ((x) << 16) -#define EXYNOS_CIOCBOFF_HORIZONTAL(x) ((x) << 0) - -#define EXYNOS_CIOCROFF_VERTICAL(x) ((x) << 16) -#define EXYNOS_CIOCROFF_HORIZONTAL(x) ((x) << 0) - -#define EXYNOS_CIIYOFF_VERTICAL(x) ((x) << 16) -#define EXYNOS_CIIYOFF_HORIZONTAL(x) ((x) << 0) - -#define EXYNOS_CIICBOFF_VERTICAL(x) ((x) << 16) -#define EXYNOS_CIICBOFF_HORIZONTAL(x) ((x) << 0) - -#define EXYNOS_CIICROFF_VERTICAL(x) ((x) << 16) -#define EXYNOS_CIICROFF_HORIZONTAL(x) ((x) << 0) - -#define EXYNOS_ORGISIZE_VERTICAL(x) ((x) << 16) -#define EXYNOS_ORGISIZE_HORIZONTAL(x) ((x) << 0) - -#define EXYNOS_ORGOSIZE_VERTICAL(x) ((x) << 16) -#define EXYNOS_ORGOSIZE_HORIZONTAL(x) ((x) << 0) - -#define EXYNOS_CIEXTEN_TARGETH_EXT(x) ((((x) & 0x2000) >> 13) << 26) -#define EXYNOS_CIEXTEN_TARGETV_EXT(x) ((((x) & 0x2000) >> 13) << 24) -#define EXYNOS_CIEXTEN_MAINHORRATIO_EXT(x) (((x) & 0x3F) << 10) -#define EXYNOS_CIEXTEN_MAINVERRATIO_EXT(x) ((x) & 0x3F) - -/* - * Bit definition part -*/ -/* Source format register */ -#define EXYNOS_CISRCFMT_ITU601_8BIT (1 << 31) -#define EXYNOS_CISRCFMT_ITU656_8BIT (0 << 31) -#define EXYNOS_CISRCFMT_ITU601_16BIT (1 << 29) -#define EXYNOS_CISRCFMT_ORDER422_YCBYCR (0 << 14) -#define EXYNOS_CISRCFMT_ORDER422_YCRYCB (1 << 14) -#define EXYNOS_CISRCFMT_ORDER422_CBYCRY (2 << 14) -#define EXYNOS_CISRCFMT_ORDER422_CRYCBY (3 << 14) -/* ITU601 16bit only */ -#define EXYNOS_CISRCFMT_ORDER422_Y4CBCRCBCR (0 << 14) -/* ITU601 16bit only */ -#define EXYNOS_CISRCFMT_ORDER422_Y4CRCBCRCB (1 << 14) - -/* Window offset register */ -#define EXYNOS_CIWDOFST_WINOFSEN (1 << 31) -#define EXYNOS_CIWDOFST_CLROVFIY (1 << 30) -#define EXYNOS_CIWDOFST_CLROVRLB (1 << 29) -#define EXYNOS_CIWDOFST_WINHOROFST_MASK (0x7ff << 16) -#define EXYNOS_CIWDOFST_CLROVFICB (1 << 15) -#define EXYNOS_CIWDOFST_CLROVFICR (1 << 14) -#define EXYNOS_CIWDOFST_WINVEROFST_MASK (0xfff << 0) - -/* Global control register */ -#define EXYNOS_CIGCTRL_SWRST (1 << 31) -#define EXYNOS_CIGCTRL_CAMRST_A (1 << 30) -#define EXYNOS_CIGCTRL_SELCAM_ITU_B (0 << 29) -#define EXYNOS_CIGCTRL_SELCAM_ITU_A (1 << 29) -#define EXYNOS_CIGCTRL_SELCAM_ITU_MASK (1 << 29) -#define EXYNOS_CIGCTRL_TESTPATTERN_NORMAL (0 << 27) -#define EXYNOS_CIGCTRL_TESTPATTERN_COLOR_BAR (1 << 27) -#define EXYNOS_CIGCTRL_TESTPATTERN_HOR_INC (2 << 27) -#define EXYNOS_CIGCTRL_TESTPATTERN_VER_INC (3 << 27) -#define EXYNOS_CIGCTRL_TESTPATTERN_MASK (3 << 27) -#define EXYNOS_CIGCTRL_TESTPATTERN_SHIFT (27) -#define EXYNOS_CIGCTRL_INVPOLPCLK (1 << 26) -#define EXYNOS_CIGCTRL_INVPOLVSYNC (1 << 25) -#define EXYNOS_CIGCTRL_INVPOLHREF (1 << 24) -#define EXYNOS_CIGCTRL_IRQ_OVFEN (1 << 22) -#define EXYNOS_CIGCTRL_HREF_MASK (1 << 21) -#define EXYNOS_CIGCTRL_IRQ_EDGE (0 << 20) -#define EXYNOS_CIGCTRL_IRQ_LEVEL (1 << 20) -#define EXYNOS_CIGCTRL_IRQ_CLR (1 << 19) -#define EXYNOS_CIGCTRL_IRQ_END_DISABLE (1 << 18) -#define EXYNOS_CIGCTRL_IRQ_DISABLE (0 << 16) -#define EXYNOS_CIGCTRL_IRQ_ENABLE (1 << 16) -#define EXYNOS_CIGCTRL_SHADOW_DISABLE (1 << 12) -#define EXYNOS_CIGCTRL_CAM_JPEG (1 << 8) -#define EXYNOS_CIGCTRL_SELCAM_MIPI_B (0 << 7) -#define EXYNOS_CIGCTRL_SELCAM_MIPI_A (1 << 7) -#define EXYNOS_CIGCTRL_SELCAM_MIPI_MASK (1 << 7) -#define EXYNOS_CIGCTRL_SELWB_CAMIF_CAMERA (0 << 6) -#define EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK (1 << 6) -#define EXYNOS_CIGCTRL_SELWRITEBACK_MASK (1 << 10) -#define EXYNOS_CIGCTRL_SELWRITEBACK_A (1 << 10) -#define EXYNOS_CIGCTRL_SELWRITEBACK_B (0 << 10) -#define EXYNOS_CIGCTRL_SELWB_CAMIF_MASK (1 << 6) -#define EXYNOS_CIGCTRL_CSC_ITU601 (0 << 5) -#define EXYNOS_CIGCTRL_CSC_ITU709 (1 << 5) -#define EXYNOS_CIGCTRL_CSC_MASK (1 << 5) -#define EXYNOS_CIGCTRL_INVPOLHSYNC (1 << 4) -#define EXYNOS_CIGCTRL_SELCAM_FIMC_ITU (0 << 3) -#define EXYNOS_CIGCTRL_SELCAM_FIMC_MIPI (1 << 3) -#define EXYNOS_CIGCTRL_SELCAM_FIMC_MASK (1 << 3) -#define EXYNOS_CIGCTRL_PROGRESSIVE (0 << 0) -#define EXYNOS_CIGCTRL_INTERLACE (1 << 0) - -/* Window offset2 register */ -#define EXYNOS_CIWDOFST_WINHOROFST2_MASK (0xfff << 16) -#define EXYNOS_CIWDOFST_WINVEROFST2_MASK (0xfff << 16) - -/* Target format register */ -#define EXYNOS_CITRGFMT_INROT90_CLOCKWISE (1 << 31) -#define EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420 (0 << 29) -#define EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422 (1 << 29) -#define EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE (2 << 29) -#define EXYNOS_CITRGFMT_OUTFORMAT_RGB (3 << 29) -#define EXYNOS_CITRGFMT_OUTFORMAT_MASK (3 << 29) -#define EXYNOS_CITRGFMT_FLIP_SHIFT (14) -#define EXYNOS_CITRGFMT_FLIP_NORMAL (0 << 14) -#define EXYNOS_CITRGFMT_FLIP_X_MIRROR (1 << 14) -#define EXYNOS_CITRGFMT_FLIP_Y_MIRROR (2 << 14) -#define EXYNOS_CITRGFMT_FLIP_180 (3 << 14) -#define EXYNOS_CITRGFMT_FLIP_MASK (3 << 14) -#define EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE (1 << 13) -#define EXYNOS_CITRGFMT_TARGETV_MASK (0x1fff << 0) -#define EXYNOS_CITRGFMT_TARGETH_MASK (0x1fff << 16) - -/* Output DMA control register */ -#define EXYNOS_CIOCTRL_WEAVE_OUT (1 << 31) -#define EXYNOS_CIOCTRL_WEAVE_MASK (1 << 31) -#define EXYNOS_CIOCTRL_LASTENDEN (1 << 30) -#define EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR (0 << 24) -#define EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB (1 << 24) -#define EXYNOS_CIOCTRL_ORDER2P_MSB_CRCB (2 << 24) -#define EXYNOS_CIOCTRL_ORDER2P_MSB_CBCR (3 << 24) -#define EXYNOS_CIOCTRL_ORDER2P_SHIFT (24) -#define EXYNOS_CIOCTRL_ORDER2P_MASK (3 << 24) -#define EXYNOS_CIOCTRL_YCBCR_3PLANE (0 << 3) -#define EXYNOS_CIOCTRL_YCBCR_2PLANE (1 << 3) -#define EXYNOS_CIOCTRL_YCBCR_PLANE_MASK (1 << 3) -#define EXYNOS_CIOCTRL_LASTIRQ_ENABLE (1 << 2) -#define EXYNOS_CIOCTRL_ALPHA_OUT (0xff << 4) -#define EXYNOS_CIOCTRL_ORDER422_YCBYCR (0 << 0) -#define EXYNOS_CIOCTRL_ORDER422_YCRYCB (1 << 0) -#define EXYNOS_CIOCTRL_ORDER422_CBYCRY (2 << 0) -#define EXYNOS_CIOCTRL_ORDER422_CRYCBY (3 << 0) -#define EXYNOS_CIOCTRL_ORDER422_MASK (3 << 0) - -/* Main scaler control register */ -#define EXYNOS_CISCCTRL_SCALERBYPASS (1 << 31) -#define EXYNOS_CISCCTRL_SCALEUP_H (1 << 30) -#define EXYNOS_CISCCTRL_SCALEUP_V (1 << 29) -#define EXYNOS_CISCCTRL_CSCR2Y_NARROW (0 << 28) -#define EXYNOS_CISCCTRL_CSCR2Y_WIDE (1 << 28) -#define EXYNOS_CISCCTRL_CSCY2R_NARROW (0 << 27) -#define EXYNOS_CISCCTRL_CSCY2R_WIDE (1 << 27) -#define EXYNOS_CISCCTRL_LCDPATHEN_FIFO (1 << 26) -#define EXYNOS_CISCCTRL_PROGRESSIVE (0 << 25) -#define EXYNOS_CISCCTRL_INTERLACE (1 << 25) -#define EXYNOS_CISCCTRL_SCAN_MASK (1 << 25) -#define EXYNOS_CISCCTRL_SCALERSTART (1 << 15) -#define EXYNOS_CISCCTRL_INRGB_FMT_RGB565 (0 << 13) -#define EXYNOS_CISCCTRL_INRGB_FMT_RGB666 (1 << 13) -#define EXYNOS_CISCCTRL_INRGB_FMT_RGB888 (2 << 13) -#define EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK (3 << 13) -#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565 (0 << 11) -#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB666 (1 << 11) -#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 (2 << 11) -#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK (3 << 11) -#define EXYNOS_CISCCTRL_EXTRGB_NORMAL (0 << 10) -#define EXYNOS_CISCCTRL_EXTRGB_EXTENSION (1 << 10) -#define EXYNOS_CISCCTRL_ONE2ONE (1 << 9) -#define EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK (0x1ff << 0) -#define EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK (0x1ff << 16) - -/* Status register */ -#define EXYNOS_CISTATUS_OVFIY (1 << 31) -#define EXYNOS_CISTATUS_OVFICB (1 << 30) -#define EXYNOS_CISTATUS_OVFICR (1 << 29) -#define EXYNOS_CISTATUS_VSYNC (1 << 28) -#define EXYNOS_CISTATUS_SCALERSTART (1 << 26) -#define EXYNOS_CISTATUS_WINOFSTEN (1 << 25) -#define EXYNOS_CISTATUS_IMGCPTEN (1 << 22) -#define EXYNOS_CISTATUS_IMGCPTENSC (1 << 21) -#define EXYNOS_CISTATUS_VSYNC_A (1 << 20) -#define EXYNOS_CISTATUS_VSYNC_B (1 << 19) -#define EXYNOS_CISTATUS_OVRLB (1 << 18) -#define EXYNOS_CISTATUS_FRAMEEND (1 << 17) -#define EXYNOS_CISTATUS_LASTCAPTUREEND (1 << 16) -#define EXYNOS_CISTATUS_VVALID_A (1 << 15) -#define EXYNOS_CISTATUS_VVALID_B (1 << 14) - -/* Image capture enable register */ -#define EXYNOS_CIIMGCPT_IMGCPTEN (1 << 31) -#define EXYNOS_CIIMGCPT_IMGCPTEN_SC (1 << 30) -#define EXYNOS_CIIMGCPT_CPT_FREN_ENABLE (1 << 25) -#define EXYNOS_CIIMGCPT_CPT_FRMOD_EN (0 << 18) -#define EXYNOS_CIIMGCPT_CPT_FRMOD_CNT (1 << 18) - -/* Image effects register */ -#define EXYNOS_CIIMGEFF_IE_DISABLE (0 << 30) -#define EXYNOS_CIIMGEFF_IE_ENABLE (1 << 30) -#define EXYNOS_CIIMGEFF_IE_SC_BEFORE (0 << 29) -#define EXYNOS_CIIMGEFF_IE_SC_AFTER (1 << 29) -#define EXYNOS_CIIMGEFF_FIN_BYPASS (0 << 26) -#define EXYNOS_CIIMGEFF_FIN_ARBITRARY (1 << 26) -#define EXYNOS_CIIMGEFF_FIN_NEGATIVE (2 << 26) -#define EXYNOS_CIIMGEFF_FIN_ARTFREEZE (3 << 26) -#define EXYNOS_CIIMGEFF_FIN_EMBOSSING (4 << 26) -#define EXYNOS_CIIMGEFF_FIN_SILHOUETTE (5 << 26) -#define EXYNOS_CIIMGEFF_FIN_MASK (7 << 26) -#define EXYNOS_CIIMGEFF_PAT_CBCR_MASK ((0xff < 13) | (0xff < 0)) - -/* Real input DMA size register */ -#define EXYNOS_CIREAL_ISIZE_AUTOLOAD_ENABLE (1 << 31) -#define EXYNOS_CIREAL_ISIZE_ADDR_CH_DISABLE (1 << 30) -#define EXYNOS_CIREAL_ISIZE_HEIGHT_MASK (0x3FFF << 16) -#define EXYNOS_CIREAL_ISIZE_WIDTH_MASK (0x3FFF << 0) - -/* Input DMA control register */ -#define EXYNOS_MSCTRL_FIELD_MASK (1 << 31) -#define EXYNOS_MSCTRL_FIELD_WEAVE (1 << 31) -#define EXYNOS_MSCTRL_FIELD_NORMAL (0 << 31) -#define EXYNOS_MSCTRL_BURST_CNT (24) -#define EXYNOS_MSCTRL_BURST_CNT_MASK (0xf << 24) -#define EXYNOS_MSCTRL_ORDER2P_LSB_CBCR (0 << 16) -#define EXYNOS_MSCTRL_ORDER2P_LSB_CRCB (1 << 16) -#define EXYNOS_MSCTRL_ORDER2P_MSB_CRCB (2 << 16) -#define EXYNOS_MSCTRL_ORDER2P_MSB_CBCR (3 << 16) -#define EXYNOS_MSCTRL_ORDER2P_SHIFT (16) -#define EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK (0x3 << 16) -#define EXYNOS_MSCTRL_C_INT_IN_3PLANE (0 << 15) -#define EXYNOS_MSCTRL_C_INT_IN_2PLANE (1 << 15) -#define EXYNOS_MSCTRL_FLIP_SHIFT (13) -#define EXYNOS_MSCTRL_FLIP_NORMAL (0 << 13) -#define EXYNOS_MSCTRL_FLIP_X_MIRROR (1 << 13) -#define EXYNOS_MSCTRL_FLIP_Y_MIRROR (2 << 13) -#define EXYNOS_MSCTRL_FLIP_180 (3 << 13) -#define EXYNOS_MSCTRL_FLIP_MASK (3 << 13) -#define EXYNOS_MSCTRL_ORDER422_CRYCBY (0 << 4) -#define EXYNOS_MSCTRL_ORDER422_YCRYCB (1 << 4) -#define EXYNOS_MSCTRL_ORDER422_CBYCRY (2 << 4) -#define EXYNOS_MSCTRL_ORDER422_YCBYCR (3 << 4) -#define EXYNOS_MSCTRL_INPUT_EXTCAM (0 << 3) -#define EXYNOS_MSCTRL_INPUT_MEMORY (1 << 3) -#define EXYNOS_MSCTRL_INPUT_MASK (1 << 3) -#define EXYNOS_MSCTRL_INFORMAT_YCBCR420 (0 << 1) -#define EXYNOS_MSCTRL_INFORMAT_YCBCR422 (1 << 1) -#define EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE (2 << 1) -#define EXYNOS_MSCTRL_INFORMAT_RGB (3 << 1) -#define EXYNOS_MSCTRL_ENVID (1 << 0) - -/* DMA parameter register */ -#define EXYNOS_CIDMAPARAM_R_MODE_LINEAR (0 << 29) -#define EXYNOS_CIDMAPARAM_R_MODE_CONFTILE (1 << 29) -#define EXYNOS_CIDMAPARAM_R_MODE_16X16 (2 << 29) -#define EXYNOS_CIDMAPARAM_R_MODE_64X32 (3 << 29) -#define EXYNOS_CIDMAPARAM_R_MODE_MASK (3 << 29) -#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_64 (0 << 24) -#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_128 (1 << 24) -#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_256 (2 << 24) -#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_512 (3 << 24) -#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_1024 (4 << 24) -#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_2048 (5 << 24) -#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_4096 (6 << 24) -#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_1 (0 << 20) -#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_2 (1 << 20) -#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_4 (2 << 20) -#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_8 (3 << 20) -#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_16 (4 << 20) -#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_32 (5 << 20) -#define EXYNOS_CIDMAPARAM_W_MODE_LINEAR (0 << 13) -#define EXYNOS_CIDMAPARAM_W_MODE_CONFTILE (1 << 13) -#define EXYNOS_CIDMAPARAM_W_MODE_16X16 (2 << 13) -#define EXYNOS_CIDMAPARAM_W_MODE_64X32 (3 << 13) -#define EXYNOS_CIDMAPARAM_W_MODE_MASK (3 << 13) -#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_64 (0 << 8) -#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_128 (1 << 8) -#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_256 (2 << 8) -#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_512 (3 << 8) -#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_1024 (4 << 8) -#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_2048 (5 << 8) -#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_4096 (6 << 8) -#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_1 (0 << 4) -#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_2 (1 << 4) -#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_4 (2 << 4) -#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_8 (3 << 4) -#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_16 (4 << 4) -#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_32 (5 << 4) - -/* Gathering Extension register */ -#define EXYNOS_CIEXTEN_TARGETH_EXT_MASK (1 << 26) -#define EXYNOS_CIEXTEN_TARGETV_EXT_MASK (1 << 24) -#define EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK (0x3F << 10) -#define EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK (0x3F) -#define EXYNOS_CIEXTEN_YUV444_OUT (1 << 22) - -/* FIMC Clock Source Select register */ -#define EXYNOS_CLKSRC_HCLK (0 << 1) -#define EXYNOS_CLKSRC_HCLK_MASK (1 << 1) -#define EXYNOS_CLKSRC_SCLK (1 << 1) - -/* SYSREG for FIMC writeback */ -#define SYSREG_CAMERA_BLK (S3C_VA_SYS + 0x0218) -#define SYSREG_ISP_BLK (S3C_VA_SYS + 0x020c) -#define SYSREG_FIMD0WB_DEST_MASK (0x3 << 23) -#define SYSREG_FIMD0WB_DEST_SHIFT 23 - -#endif /* SAMSUNG_REGS_FIMC_H */ diff --git a/drivers/gpu/drm/exynos/regs-gsc.h b/drivers/gpu/drm/exynos/regs-gsc.h deleted file mode 100644 index 8ec160b..0000000 --- a/drivers/gpu/drm/exynos/regs-gsc.h +++ /dev/null @@ -1,295 +0,0 @@ -/* linux/drivers/gpu/drm/exynos/regs-gsc.h - * - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Register definition file for Samsung G-Scaler driver - * - * 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. - */ - -#ifndef REGS_GSC_H_ -#define REGS_GSC_H_ - -/* SYSCON. GSCBLK_CFG */ -#include -#include -#define SYSREG_DISP1BLK_CFG (S3C_VA_SYS + 0x0214) -#define FIFORST_DISP1 (1 << 23) -#define GSC_OUT_MIXER0 (1 << 7) -#define GSC_OUT_MIXER0_GSC3 (3 << 5) -#define SYSREG_GSCBLK_CFG0 (S3C_VA_SYS + 0x0220) -#define GSC_OUT_DST_FIMD_SEL(x) (1 << (8 + 2 * (x))) -#define GSC_OUT_DST_MXR_SEL(x) (2 << (8 + 2 * (x))) -#define GSC_PXLASYNC_RST(x) (1 << (x)) -#define PXLASYNC_LO_MASK_CAMIF_TOP (1 << 20) -#define SYSREG_GSCBLK_CFG1 (S3C_VA_SYS + 0x0224) -#define GSC_BLK_DISP1WB_DEST(x) (x << 10) -#define GSC_BLK_SW_RESET_WB_DEST(x) (1 << (18 + x)) -#define GSC_BLK_PXLASYNC_LO_MASK_WB(x) (0 << (14 + x)) -#define GSC_BLK_GSCL_WB_IN_SRC_SEL(x) (1 << (2 * x)) -#define SYSREG_GSCBLK_CFG2 (S3C_VA_SYS + 0x2000) -#define PXLASYNC_LO_MASK_CAMIF_GSCL(x) (1 << (x)) - -/* G-Scaler enable */ -#define GSC_ENABLE 0x00 -#define GSC_ENABLE_PP_UPDATE_TIME_MASK (1 << 9) -#define GSC_ENABLE_PP_UPDATE_TIME_CURR (0 << 9) -#define GSC_ENABLE_PP_UPDATE_TIME_EOPAS (1 << 9) -#define GSC_ENABLE_CLK_GATE_MODE_MASK (1 << 8) -#define GSC_ENABLE_CLK_GATE_MODE_FREE (1 << 8) -#define GSC_ENABLE_IPC_MODE_MASK (1 << 7) -#define GSC_ENABLE_NORM_MODE (0 << 7) -#define GSC_ENABLE_IPC_MODE (1 << 7) -#define GSC_ENABLE_PP_UPDATE_MODE_MASK (1 << 6) -#define GSC_ENABLE_PP_UPDATE_FIRE_MODE (1 << 6) -#define GSC_ENABLE_IN_PP_UPDATE (1 << 5) -#define GSC_ENABLE_ON_CLEAR_MASK (1 << 4) -#define GSC_ENABLE_ON_CLEAR_ONESHOT (1 << 4) -#define GSC_ENABLE_QOS_ENABLE (1 << 3) -#define GSC_ENABLE_OP_STATUS (1 << 2) -#define GSC_ENABLE_SFR_UPDATE (1 << 1) -#define GSC_ENABLE_ON (1 << 0) - -/* G-Scaler S/W reset */ -#define GSC_SW_RESET 0x04 -#define GSC_SW_RESET_SRESET (1 << 0) - -/* G-Scaler IRQ */ -#define GSC_IRQ 0x08 -#define GSC_IRQ_STATUS_OR_IRQ (1 << 17) -#define GSC_IRQ_STATUS_OR_FRM_DONE (1 << 16) -#define GSC_IRQ_OR_MASK (1 << 2) -#define GSC_IRQ_FRMDONE_MASK (1 << 1) -#define GSC_IRQ_ENABLE (1 << 0) - -/* G-Scaler input control */ -#define GSC_IN_CON 0x10 -#define GSC_IN_CHROM_STRIDE_SEL_MASK (1 << 20) -#define GSC_IN_CHROM_STRIDE_SEPAR (1 << 20) -#define GSC_IN_RB_SWAP_MASK (1 << 19) -#define GSC_IN_RB_SWAP (1 << 19) -#define GSC_IN_ROT_MASK (7 << 16) -#define GSC_IN_ROT_270 (7 << 16) -#define GSC_IN_ROT_90_YFLIP (6 << 16) -#define GSC_IN_ROT_90_XFLIP (5 << 16) -#define GSC_IN_ROT_90 (4 << 16) -#define GSC_IN_ROT_180 (3 << 16) -#define GSC_IN_ROT_YFLIP (2 << 16) -#define GSC_IN_ROT_XFLIP (1 << 16) -#define GSC_IN_RGB_TYPE_MASK (3 << 14) -#define GSC_IN_RGB_HD_WIDE (3 << 14) -#define GSC_IN_RGB_HD_NARROW (2 << 14) -#define GSC_IN_RGB_SD_WIDE (1 << 14) -#define GSC_IN_RGB_SD_NARROW (0 << 14) -#define GSC_IN_YUV422_1P_ORDER_MASK (1 << 13) -#define GSC_IN_YUV422_1P_ORDER_LSB_Y (0 << 13) -#define GSC_IN_YUV422_1P_OEDER_LSB_C (1 << 13) -#define GSC_IN_CHROMA_ORDER_MASK (1 << 12) -#define GSC_IN_CHROMA_ORDER_CBCR (0 << 12) -#define GSC_IN_CHROMA_ORDER_CRCB (1 << 12) -#define GSC_IN_FORMAT_MASK (7 << 8) -#define GSC_IN_XRGB8888 (0 << 8) -#define GSC_IN_RGB565 (1 << 8) -#define GSC_IN_YUV420_2P (2 << 8) -#define GSC_IN_YUV420_3P (3 << 8) -#define GSC_IN_YUV422_1P (4 << 8) -#define GSC_IN_YUV422_2P (5 << 8) -#define GSC_IN_YUV422_3P (6 << 8) -#define GSC_IN_TILE_TYPE_MASK (1 << 4) -#define GSC_IN_TILE_C_16x8 (0 << 4) -#define GSC_IN_TILE_C_16x16 (1 << 4) -#define GSC_IN_TILE_MODE (1 << 3) -#define GSC_IN_LOCAL_SEL_MASK (3 << 1) -#define GSC_IN_LOCAL_CAM3 (3 << 1) -#define GSC_IN_LOCAL_FIMD_WB (2 << 1) -#define GSC_IN_LOCAL_CAM1 (1 << 1) -#define GSC_IN_LOCAL_CAM0 (0 << 1) -#define GSC_IN_PATH_MASK (1 << 0) -#define GSC_IN_PATH_LOCAL (1 << 0) -#define GSC_IN_PATH_MEMORY (0 << 0) - -/* G-Scaler source image size */ -#define GSC_SRCIMG_SIZE 0x14 -#define GSC_SRCIMG_HEIGHT_MASK (0x1fff << 16) -#define GSC_SRCIMG_HEIGHT(x) ((x) << 16) -#define GSC_SRCIMG_WIDTH_MASK (0x3fff << 0) -#define GSC_SRCIMG_WIDTH(x) ((x) << 0) - -/* G-Scaler source image offset */ -#define GSC_SRCIMG_OFFSET 0x18 -#define GSC_SRCIMG_OFFSET_Y_MASK (0x1fff << 16) -#define GSC_SRCIMG_OFFSET_Y(x) ((x) << 16) -#define GSC_SRCIMG_OFFSET_X_MASK (0x1fff << 0) -#define GSC_SRCIMG_OFFSET_X(x) ((x) << 0) - -/* G-Scaler cropped source image size */ -#define GSC_CROPPED_SIZE 0x1C -#define GSC_CROPPED_HEIGHT_MASK (0x1fff << 16) -#define GSC_CROPPED_HEIGHT(x) ((x) << 16) -#define GSC_CROPPED_WIDTH_MASK (0x1fff << 0) -#define GSC_CROPPED_WIDTH(x) ((x) << 0) - -/* G-Scaler output control */ -#define GSC_OUT_CON 0x20 -#define GSC_OUT_GLOBAL_ALPHA_MASK (0xff << 24) -#define GSC_OUT_GLOBAL_ALPHA(x) ((x) << 24) -#define GSC_OUT_CHROM_STRIDE_SEL_MASK (1 << 13) -#define GSC_OUT_CHROM_STRIDE_SEPAR (1 << 13) -#define GSC_OUT_RB_SWAP_MASK (1 << 12) -#define GSC_OUT_RB_SWAP (1 << 12) -#define GSC_OUT_RGB_TYPE_MASK (3 << 10) -#define GSC_OUT_RGB_HD_NARROW (3 << 10) -#define GSC_OUT_RGB_HD_WIDE (2 << 10) -#define GSC_OUT_RGB_SD_NARROW (1 << 10) -#define GSC_OUT_RGB_SD_WIDE (0 << 10) -#define GSC_OUT_YUV422_1P_ORDER_MASK (1 << 9) -#define GSC_OUT_YUV422_1P_ORDER_LSB_Y (0 << 9) -#define GSC_OUT_YUV422_1P_OEDER_LSB_C (1 << 9) -#define GSC_OUT_CHROMA_ORDER_MASK (1 << 8) -#define GSC_OUT_CHROMA_ORDER_CBCR (0 << 8) -#define GSC_OUT_CHROMA_ORDER_CRCB (1 << 8) -#define GSC_OUT_FORMAT_MASK (7 << 4) -#define GSC_OUT_XRGB8888 (0 << 4) -#define GSC_OUT_RGB565 (1 << 4) -#define GSC_OUT_YUV420_2P (2 << 4) -#define GSC_OUT_YUV420_3P (3 << 4) -#define GSC_OUT_YUV422_1P (4 << 4) -#define GSC_OUT_YUV422_2P (5 << 4) -#define GSC_OUT_YUV444 (7 << 4) -#define GSC_OUT_TILE_TYPE_MASK (1 << 2) -#define GSC_OUT_TILE_C_16x8 (0 << 2) -#define GSC_OUT_TILE_C_16x16 (1 << 2) -#define GSC_OUT_TILE_MODE (1 << 1) -#define GSC_OUT_PATH_MASK (1 << 0) -#define GSC_OUT_PATH_LOCAL (1 << 0) -#define GSC_OUT_PATH_MEMORY (0 << 0) - -/* G-Scaler scaled destination image size */ -#define GSC_SCALED_SIZE 0x24 -#define GSC_SCALED_HEIGHT_MASK (0x1fff << 16) -#define GSC_SCALED_HEIGHT(x) ((x) << 16) -#define GSC_SCALED_WIDTH_MASK (0x1fff << 0) -#define GSC_SCALED_WIDTH(x) ((x) << 0) - -/* G-Scaler pre scale ratio */ -#define GSC_PRE_SCALE_RATIO 0x28 -#define GSC_PRESC_SHFACTOR_MASK (7 << 28) -#define GSC_PRESC_SHFACTOR(x) ((x) << 28) -#define GSC_PRESC_V_RATIO_MASK (7 << 16) -#define GSC_PRESC_V_RATIO(x) ((x) << 16) -#define GSC_PRESC_H_RATIO_MASK (7 << 0) -#define GSC_PRESC_H_RATIO(x) ((x) << 0) - -/* G-Scaler main scale horizontal ratio */ -#define GSC_MAIN_H_RATIO 0x2C -#define GSC_MAIN_H_RATIO_MASK (0xfffff << 0) -#define GSC_MAIN_H_RATIO_VALUE(x) ((x) << 0) - -/* G-Scaler main scale vertical ratio */ -#define GSC_MAIN_V_RATIO 0x30 -#define GSC_MAIN_V_RATIO_MASK (0xfffff << 0) -#define GSC_MAIN_V_RATIO_VALUE(x) ((x) << 0) - -/* G-Scaler input chrominance stride */ -#define GSC_IN_CHROM_STRIDE 0x3C -#define GSC_IN_CHROM_STRIDE_MASK (0x3fff << 0) -#define GSC_IN_CHROM_STRIDE_VALUE(x) ((x) << 0) - -/* G-Scaler destination image size */ -#define GSC_DSTIMG_SIZE 0x40 -#define GSC_DSTIMG_HEIGHT_MASK (0x1fff << 16) -#define GSC_DSTIMG_HEIGHT(x) ((x) << 16) -#define GSC_DSTIMG_WIDTH_MASK (0x1fff << 0) -#define GSC_DSTIMG_WIDTH(x) ((x) << 0) - -/* G-Scaler destination image offset */ -#define GSC_DSTIMG_OFFSET 0x44 -#define GSC_DSTIMG_OFFSET_Y_MASK (0x1fff << 16) -#define GSC_DSTIMG_OFFSET_Y(x) ((x) << 16) -#define GSC_DSTIMG_OFFSET_X_MASK (0x1fff << 0) -#define GSC_DSTIMG_OFFSET_X(x) ((x) << 0) - -/* G-Scaler output chrominance stride */ -#define GSC_OUT_CHROM_STRIDE 0x48 -#define GSC_OUT_CHROM_STRIDE_MASK (0x3fff << 0) -#define GSC_OUT_CHROM_STRIDE_VALUE(x) ((x) << 0) - -/* G-Scaler input y address mask */ -#define GSC_IN_BASE_ADDR_Y_MASK 0x4C -/* G-Scaler input y base address */ -#define GSC_IN_BASE_ADDR_Y(n) (0x50 + (n) * 0x4) -/* G-Scaler input y base current address */ -#define GSC_IN_BASE_ADDR_Y_CUR(n) (0x60 + (n) * 0x4) - -/* G-Scaler input cb address mask */ -#define GSC_IN_BASE_ADDR_CB_MASK 0x7C -/* G-Scaler input cb base address */ -#define GSC_IN_BASE_ADDR_CB(n) (0x80 + (n) * 0x4) -/* G-Scaler input cb base current address */ -#define GSC_IN_BASE_ADDR_CB_CUR(n) (0x90 + (n) * 0x4) - -/* G-Scaler input cr address mask */ -#define GSC_IN_BASE_ADDR_CR_MASK 0xAC -/* G-Scaler input cr base address */ -#define GSC_IN_BASE_ADDR_CR(n) (0xB0 + (n) * 0x4) -/* G-Scaler input cr base current address */ -#define GSC_IN_BASE_ADDR_CR_CUR(n) (0xC0 + (n) * 0x4) - -/* G-Scaler input address mask */ -#define GSC_IN_CURR_ADDR_INDEX (0xf << 24) -#define GSC_IN_CURR_GET_INDEX(x) ((x) >> 24) -#define GSC_IN_BASE_ADDR_PINGPONG(x) ((x) << 16) -#define GSC_IN_BASE_ADDR_MASK (0xff << 0) - -/* G-Scaler output y address mask */ -#define GSC_OUT_BASE_ADDR_Y_MASK 0x10C -/* G-Scaler output y base address */ -#define GSC_OUT_BASE_ADDR_Y(n) (0x110 + (n) * 0x4) - -/* G-Scaler output cb address mask */ -#define GSC_OUT_BASE_ADDR_CB_MASK 0x15C -/* G-Scaler output cb base address */ -#define GSC_OUT_BASE_ADDR_CB(n) (0x160 + (n) * 0x4) - -/* G-Scaler output cr address mask */ -#define GSC_OUT_BASE_ADDR_CR_MASK 0x1AC -/* G-Scaler output cr base address */ -#define GSC_OUT_BASE_ADDR_CR(n) (0x1B0 + (n) * 0x4) - -/* G-Scaler output address mask */ -#define GSC_OUT_CURR_ADDR_INDEX (0xf << 24) -#define GSC_OUT_CURR_GET_INDEX(x) ((x) >> 24) -#define GSC_OUT_BASE_ADDR_PINGPONG(x) ((x) << 16) -#define GSC_OUT_BASE_ADDR_MASK (0xffff << 0) - -/* G-Scaler horizontal scaling filter */ -#define GSC_HCOEF(n, s, x) (0x300 + (n) * 0x4 + (s) * 0x30 + (x) * 0x300) - -/* G-Scaler vertical scaling filter */ -#define GSC_VCOEF(n, s, x) (0x200 + (n) * 0x4 + (s) * 0x30 + (x) * 0x300) - -/* G-Scaler BUS control */ -#define GSC_BUSCON 0xA78 -#define GSC_BUSCON_INT_TIME_MASK (1 << 8) -#define GSC_BUSCON_INT_DATA_TRANS (0 << 8) -#define GSC_BUSCON_INT_AXI_RESPONSE (1 << 8) -#define GSC_BUSCON_AWCACHE(x) ((x) << 4) -#define GSC_BUSCON_ARCACHE(x) ((x) << 0) - -/* G-Scaler V position */ -#define GSC_VPOSITION 0xA7C -#define GSC_VPOS_F(x) ((x) << 0) - - -/* G-Scaler clock initial count */ -#define GSC_CLK_INIT_COUNT 0xC00 -#define GSC_CLK_GATE_MODE_INIT_CNT(x) ((x) << 0) - -/* G-Scaler clock snoop count */ -#define GSC_CLK_SNOOP_COUNT 0xC04 -#define GSC_CLK_GATE_MODE_SNOOP_CNT(x) ((x) << 0) - -#endif /* REGS_GSC_H_ */ diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h b/drivers/gpu/drm/exynos/regs-hdmi.h deleted file mode 100644 index 93576a0..0000000 --- a/drivers/gpu/drm/exynos/regs-hdmi.h +++ /dev/null @@ -1,723 +0,0 @@ -/* - * - * Cloned from drivers/media/video/s5p-tv/regs-hdmi.h - * - * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * HDMI register header file for Samsung TVOUT driver - * - * 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. -*/ - -#ifndef SAMSUNG_REGS_HDMI_H -#define SAMSUNG_REGS_HDMI_H - -/* - * Register part -*/ - -/* HDMI Version 1.3 & Common */ -#define HDMI_CTRL_BASE(x) ((x) + 0x00000000) -#define HDMI_CORE_BASE(x) ((x) + 0x00010000) -#define HDMI_I2S_BASE(x) ((x) + 0x00040000) -#define HDMI_TG_BASE(x) ((x) + 0x00050000) - -/* Control registers */ -#define HDMI_INTC_CON HDMI_CTRL_BASE(0x0000) -#define HDMI_INTC_FLAG HDMI_CTRL_BASE(0x0004) -#define HDMI_HPD_STATUS HDMI_CTRL_BASE(0x000C) -#define HDMI_V13_PHY_RSTOUT HDMI_CTRL_BASE(0x0014) -#define HDMI_V13_PHY_VPLL HDMI_CTRL_BASE(0x0018) -#define HDMI_V13_PHY_CMU HDMI_CTRL_BASE(0x001C) -#define HDMI_V13_CORE_RSTOUT HDMI_CTRL_BASE(0x0020) - -/* Core registers */ -#define HDMI_CON_0 HDMI_CORE_BASE(0x0000) -#define HDMI_CON_1 HDMI_CORE_BASE(0x0004) -#define HDMI_CON_2 HDMI_CORE_BASE(0x0008) -#define HDMI_SYS_STATUS HDMI_CORE_BASE(0x0010) -#define HDMI_V13_PHY_STATUS HDMI_CORE_BASE(0x0014) -#define HDMI_STATUS_EN HDMI_CORE_BASE(0x0020) -#define HDMI_HPD HDMI_CORE_BASE(0x0030) -#define HDMI_MODE_SEL HDMI_CORE_BASE(0x0040) -#define HDMI_ENC_EN HDMI_CORE_BASE(0x0044) -#define HDMI_V13_BLUE_SCREEN_0 HDMI_CORE_BASE(0x0050) -#define HDMI_V13_BLUE_SCREEN_1 HDMI_CORE_BASE(0x0054) -#define HDMI_V13_BLUE_SCREEN_2 HDMI_CORE_BASE(0x0058) -#define HDMI_H_BLANK_0 HDMI_CORE_BASE(0x00A0) -#define HDMI_H_BLANK_1 HDMI_CORE_BASE(0x00A4) -#define HDMI_V13_V_BLANK_0 HDMI_CORE_BASE(0x00B0) -#define HDMI_V13_V_BLANK_1 HDMI_CORE_BASE(0x00B4) -#define HDMI_V13_V_BLANK_2 HDMI_CORE_BASE(0x00B8) -#define HDMI_V13_H_V_LINE_0 HDMI_CORE_BASE(0x00C0) -#define HDMI_V13_H_V_LINE_1 HDMI_CORE_BASE(0x00C4) -#define HDMI_V13_H_V_LINE_2 HDMI_CORE_BASE(0x00C8) -#define HDMI_VSYNC_POL HDMI_CORE_BASE(0x00E4) -#define HDMI_INT_PRO_MODE HDMI_CORE_BASE(0x00E8) -#define HDMI_V13_V_BLANK_F_0 HDMI_CORE_BASE(0x0110) -#define HDMI_V13_V_BLANK_F_1 HDMI_CORE_BASE(0x0114) -#define HDMI_V13_V_BLANK_F_2 HDMI_CORE_BASE(0x0118) -#define HDMI_V13_H_SYNC_GEN_0 HDMI_CORE_BASE(0x0120) -#define HDMI_V13_H_SYNC_GEN_1 HDMI_CORE_BASE(0x0124) -#define HDMI_V13_H_SYNC_GEN_2 HDMI_CORE_BASE(0x0128) -#define HDMI_V13_V_SYNC_GEN_1_0 HDMI_CORE_BASE(0x0130) -#define HDMI_V13_V_SYNC_GEN_1_1 HDMI_CORE_BASE(0x0134) -#define HDMI_V13_V_SYNC_GEN_1_2 HDMI_CORE_BASE(0x0138) -#define HDMI_V13_V_SYNC_GEN_2_0 HDMI_CORE_BASE(0x0140) -#define HDMI_V13_V_SYNC_GEN_2_1 HDMI_CORE_BASE(0x0144) -#define HDMI_V13_V_SYNC_GEN_2_2 HDMI_CORE_BASE(0x0148) -#define HDMI_V13_V_SYNC_GEN_3_0 HDMI_CORE_BASE(0x0150) -#define HDMI_V13_V_SYNC_GEN_3_1 HDMI_CORE_BASE(0x0154) -#define HDMI_V13_V_SYNC_GEN_3_2 HDMI_CORE_BASE(0x0158) -#define HDMI_V13_ACR_CON HDMI_CORE_BASE(0x0180) -#define HDMI_V13_ACR_CTS0 HDMI_CORE_BASE(0x0190) -#define HDMI_V13_AVI_CON HDMI_CORE_BASE(0x0300) -#define HDMI_V13_AVI_BYTE(n) HDMI_CORE_BASE(0x0320 + 4 * (n)) -#define HDMI_V13_DC_CONTROL HDMI_CORE_BASE(0x05C0) -#define HDMI_V13_VIDEO_PATTERN_GEN HDMI_CORE_BASE(0x05C4) -#define HDMI_V13_HPD_GEN HDMI_CORE_BASE(0x05C8) -#define HDMI_V13_AUI_CON HDMI_CORE_BASE(0x0360) -#define HDMI_V13_SPD_CON HDMI_CORE_BASE(0x0400) - -/* Timing generator registers */ -#define HDMI_TG_CMD HDMI_TG_BASE(0x0000) -#define HDMI_TG_H_FSZ_L HDMI_TG_BASE(0x0018) -#define HDMI_TG_H_FSZ_H HDMI_TG_BASE(0x001C) -#define HDMI_TG_HACT_ST_L HDMI_TG_BASE(0x0020) -#define HDMI_TG_HACT_ST_H HDMI_TG_BASE(0x0024) -#define HDMI_TG_HACT_SZ_L HDMI_TG_BASE(0x0028) -#define HDMI_TG_HACT_SZ_H HDMI_TG_BASE(0x002C) -#define HDMI_TG_V_FSZ_L HDMI_TG_BASE(0x0030) -#define HDMI_TG_V_FSZ_H HDMI_TG_BASE(0x0034) -#define HDMI_TG_VSYNC_L HDMI_TG_BASE(0x0038) -#define HDMI_TG_VSYNC_H HDMI_TG_BASE(0x003C) -#define HDMI_TG_VSYNC2_L HDMI_TG_BASE(0x0040) -#define HDMI_TG_VSYNC2_H HDMI_TG_BASE(0x0044) -#define HDMI_TG_VACT_ST_L HDMI_TG_BASE(0x0048) -#define HDMI_TG_VACT_ST_H HDMI_TG_BASE(0x004C) -#define HDMI_TG_VACT_SZ_L HDMI_TG_BASE(0x0050) -#define HDMI_TG_VACT_SZ_H HDMI_TG_BASE(0x0054) -#define HDMI_TG_FIELD_CHG_L HDMI_TG_BASE(0x0058) -#define HDMI_TG_FIELD_CHG_H HDMI_TG_BASE(0x005C) -#define HDMI_TG_VACT_ST2_L HDMI_TG_BASE(0x0060) -#define HDMI_TG_VACT_ST2_H HDMI_TG_BASE(0x0064) -#define HDMI_TG_VSYNC_TOP_HDMI_L HDMI_TG_BASE(0x0078) -#define HDMI_TG_VSYNC_TOP_HDMI_H HDMI_TG_BASE(0x007C) -#define HDMI_TG_VSYNC_BOT_HDMI_L HDMI_TG_BASE(0x0080) -#define HDMI_TG_VSYNC_BOT_HDMI_H HDMI_TG_BASE(0x0084) -#define HDMI_TG_FIELD_TOP_HDMI_L HDMI_TG_BASE(0x0088) -#define HDMI_TG_FIELD_TOP_HDMI_H HDMI_TG_BASE(0x008C) -#define HDMI_TG_FIELD_BOT_HDMI_L HDMI_TG_BASE(0x0090) -#define HDMI_TG_FIELD_BOT_HDMI_H HDMI_TG_BASE(0x0094) - -/* - * Bit definition part - */ - -/* HDMI_INTC_CON */ -#define HDMI_INTC_EN_GLOBAL (1 << 6) -#define HDMI_INTC_EN_HPD_PLUG (1 << 3) -#define HDMI_INTC_EN_HPD_UNPLUG (1 << 2) - -/* HDMI_INTC_FLAG */ -#define HDMI_INTC_FLAG_HPD_PLUG (1 << 3) -#define HDMI_INTC_FLAG_HPD_UNPLUG (1 << 2) - -/* HDMI_PHY_RSTOUT */ -#define HDMI_PHY_SW_RSTOUT (1 << 0) - -/* HDMI_CORE_RSTOUT */ -#define HDMI_CORE_SW_RSTOUT (1 << 0) - -/* HDMI_CON_0 */ -#define HDMI_BLUE_SCR_EN (1 << 5) -#define HDMI_ASP_EN (1 << 2) -#define HDMI_ASP_DIS (0 << 2) -#define HDMI_ASP_MASK (1 << 2) -#define HDMI_EN (1 << 0) - -/* HDMI_CON_2 */ -#define HDMI_VID_PREAMBLE_DIS (1 << 5) -#define HDMI_GUARD_BAND_DIS (1 << 1) - -/* HDMI_PHY_STATUS */ -#define HDMI_PHY_STATUS_READY (1 << 0) - -/* HDMI_MODE_SEL */ -#define HDMI_MODE_HDMI_EN (1 << 1) -#define HDMI_MODE_DVI_EN (1 << 0) -#define HDMI_MODE_MASK (3 << 0) - -/* HDMI_TG_CMD */ -#define HDMI_TG_EN (1 << 0) -#define HDMI_FIELD_EN (1 << 1) - - -/* HDMI Version 1.4 */ -/* Control registers */ -/* #define HDMI_INTC_CON HDMI_CTRL_BASE(0x0000) */ -/* #define HDMI_INTC_FLAG HDMI_CTRL_BASE(0x0004) */ -#define HDMI_HDCP_KEY_LOAD HDMI_CTRL_BASE(0x0008) -/* #define HDMI_HPD_STATUS HDMI_CTRL_BASE(0x000C) */ -#define HDMI_INTC_CON_1 HDMI_CTRL_BASE(0x0010) -#define HDMI_INTC_FLAG_1 HDMI_CTRL_BASE(0x0014) -#define HDMI_PHY_STATUS_0 HDMI_CTRL_BASE(0x0020) -#define HDMI_PHY_STATUS_CMU HDMI_CTRL_BASE(0x0024) -#define HDMI_PHY_STATUS_PLL HDMI_CTRL_BASE(0x0028) -#define HDMI_PHY_CON_0 HDMI_CTRL_BASE(0x0030) -#define HDMI_HPD_CTRL HDMI_CTRL_BASE(0x0040) -#define HDMI_HPD_ST HDMI_CTRL_BASE(0x0044) -#define HDMI_HPD_TH_X HDMI_CTRL_BASE(0x0050) -#define HDMI_AUDIO_CLKSEL HDMI_CTRL_BASE(0x0070) -#define HDMI_PHY_RSTOUT HDMI_CTRL_BASE(0x0074) -#define HDMI_PHY_VPLL HDMI_CTRL_BASE(0x0078) -#define HDMI_PHY_CMU HDMI_CTRL_BASE(0x007C) -#define HDMI_CORE_RSTOUT HDMI_CTRL_BASE(0x0080) - -/* Video related registers */ -#define HDMI_YMAX HDMI_CORE_BASE(0x0060) -#define HDMI_YMIN HDMI_CORE_BASE(0x0064) -#define HDMI_CMAX HDMI_CORE_BASE(0x0068) -#define HDMI_CMIN HDMI_CORE_BASE(0x006C) - -#define HDMI_V2_BLANK_0 HDMI_CORE_BASE(0x00B0) -#define HDMI_V2_BLANK_1 HDMI_CORE_BASE(0x00B4) -#define HDMI_V1_BLANK_0 HDMI_CORE_BASE(0x00B8) -#define HDMI_V1_BLANK_1 HDMI_CORE_BASE(0x00BC) - -#define HDMI_V_LINE_0 HDMI_CORE_BASE(0x00C0) -#define HDMI_V_LINE_1 HDMI_CORE_BASE(0x00C4) -#define HDMI_H_LINE_0 HDMI_CORE_BASE(0x00C8) -#define HDMI_H_LINE_1 HDMI_CORE_BASE(0x00CC) - -#define HDMI_HSYNC_POL HDMI_CORE_BASE(0x00E0) - -#define HDMI_V_BLANK_F0_0 HDMI_CORE_BASE(0x0110) -#define HDMI_V_BLANK_F0_1 HDMI_CORE_BASE(0x0114) -#define HDMI_V_BLANK_F1_0 HDMI_CORE_BASE(0x0118) -#define HDMI_V_BLANK_F1_1 HDMI_CORE_BASE(0x011C) - -#define HDMI_H_SYNC_START_0 HDMI_CORE_BASE(0x0120) -#define HDMI_H_SYNC_START_1 HDMI_CORE_BASE(0x0124) -#define HDMI_H_SYNC_END_0 HDMI_CORE_BASE(0x0128) -#define HDMI_H_SYNC_END_1 HDMI_CORE_BASE(0x012C) - -#define HDMI_V_SYNC_LINE_BEF_2_0 HDMI_CORE_BASE(0x0130) -#define HDMI_V_SYNC_LINE_BEF_2_1 HDMI_CORE_BASE(0x0134) -#define HDMI_V_SYNC_LINE_BEF_1_0 HDMI_CORE_BASE(0x0138) -#define HDMI_V_SYNC_LINE_BEF_1_1 HDMI_CORE_BASE(0x013C) - -#define HDMI_V_SYNC_LINE_AFT_2_0 HDMI_CORE_BASE(0x0140) -#define HDMI_V_SYNC_LINE_AFT_2_1 HDMI_CORE_BASE(0x0144) -#define HDMI_V_SYNC_LINE_AFT_1_0 HDMI_CORE_BASE(0x0148) -#define HDMI_V_SYNC_LINE_AFT_1_1 HDMI_CORE_BASE(0x014C) - -#define HDMI_V_SYNC_LINE_AFT_PXL_2_0 HDMI_CORE_BASE(0x0150) -#define HDMI_V_SYNC_LINE_AFT_PXL_2_1 HDMI_CORE_BASE(0x0154) -#define HDMI_V_SYNC_LINE_AFT_PXL_1_0 HDMI_CORE_BASE(0x0158) -#define HDMI_V_SYNC_LINE_AFT_PXL_1_1 HDMI_CORE_BASE(0x015C) - -#define HDMI_V_BLANK_F2_0 HDMI_CORE_BASE(0x0160) -#define HDMI_V_BLANK_F2_1 HDMI_CORE_BASE(0x0164) -#define HDMI_V_BLANK_F3_0 HDMI_CORE_BASE(0x0168) -#define HDMI_V_BLANK_F3_1 HDMI_CORE_BASE(0x016C) -#define HDMI_V_BLANK_F4_0 HDMI_CORE_BASE(0x0170) -#define HDMI_V_BLANK_F4_1 HDMI_CORE_BASE(0x0174) -#define HDMI_V_BLANK_F5_0 HDMI_CORE_BASE(0x0178) -#define HDMI_V_BLANK_F5_1 HDMI_CORE_BASE(0x017C) - -#define HDMI_V_SYNC_LINE_AFT_3_0 HDMI_CORE_BASE(0x0180) -#define HDMI_V_SYNC_LINE_AFT_3_1 HDMI_CORE_BASE(0x0184) -#define HDMI_V_SYNC_LINE_AFT_4_0 HDMI_CORE_BASE(0x0188) -#define HDMI_V_SYNC_LINE_AFT_4_1 HDMI_CORE_BASE(0x018C) -#define HDMI_V_SYNC_LINE_AFT_5_0 HDMI_CORE_BASE(0x0190) -#define HDMI_V_SYNC_LINE_AFT_5_1 HDMI_CORE_BASE(0x0194) -#define HDMI_V_SYNC_LINE_AFT_6_0 HDMI_CORE_BASE(0x0198) -#define HDMI_V_SYNC_LINE_AFT_6_1 HDMI_CORE_BASE(0x019C) - -#define HDMI_V_SYNC_LINE_AFT_PXL_3_0 HDMI_CORE_BASE(0x01A0) -#define HDMI_V_SYNC_LINE_AFT_PXL_3_1 HDMI_CORE_BASE(0x01A4) -#define HDMI_V_SYNC_LINE_AFT_PXL_4_0 HDMI_CORE_BASE(0x01A8) -#define HDMI_V_SYNC_LINE_AFT_PXL_4_1 HDMI_CORE_BASE(0x01AC) -#define HDMI_V_SYNC_LINE_AFT_PXL_5_0 HDMI_CORE_BASE(0x01B0) -#define HDMI_V_SYNC_LINE_AFT_PXL_5_1 HDMI_CORE_BASE(0x01B4) -#define HDMI_V_SYNC_LINE_AFT_PXL_6_0 HDMI_CORE_BASE(0x01B8) -#define HDMI_V_SYNC_LINE_AFT_PXL_6_1 HDMI_CORE_BASE(0x01BC) - -#define HDMI_VACT_SPACE_1_0 HDMI_CORE_BASE(0x01C0) -#define HDMI_VACT_SPACE_1_1 HDMI_CORE_BASE(0x01C4) -#define HDMI_VACT_SPACE_2_0 HDMI_CORE_BASE(0x01C8) -#define HDMI_VACT_SPACE_2_1 HDMI_CORE_BASE(0x01CC) -#define HDMI_VACT_SPACE_3_0 HDMI_CORE_BASE(0x01D0) -#define HDMI_VACT_SPACE_3_1 HDMI_CORE_BASE(0x01D4) -#define HDMI_VACT_SPACE_4_0 HDMI_CORE_BASE(0x01D8) -#define HDMI_VACT_SPACE_4_1 HDMI_CORE_BASE(0x01DC) -#define HDMI_VACT_SPACE_5_0 HDMI_CORE_BASE(0x01E0) -#define HDMI_VACT_SPACE_5_1 HDMI_CORE_BASE(0x01E4) -#define HDMI_VACT_SPACE_6_0 HDMI_CORE_BASE(0x01E8) -#define HDMI_VACT_SPACE_6_1 HDMI_CORE_BASE(0x01EC) - -#define HDMI_GCP_CON HDMI_CORE_BASE(0x0200) -#define HDMI_GCP_BYTE1 HDMI_CORE_BASE(0x0210) -#define HDMI_GCP_BYTE2 HDMI_CORE_BASE(0x0214) -#define HDMI_GCP_BYTE3 HDMI_CORE_BASE(0x0218) - -/* Audio related registers */ -#define HDMI_ASP_CON HDMI_CORE_BASE(0x0300) -#define HDMI_ASP_SP_FLAT HDMI_CORE_BASE(0x0304) -#define HDMI_ASP_CHCFG0 HDMI_CORE_BASE(0x0310) -#define HDMI_ASP_CHCFG1 HDMI_CORE_BASE(0x0314) -#define HDMI_ASP_CHCFG2 HDMI_CORE_BASE(0x0318) -#define HDMI_ASP_CHCFG3 HDMI_CORE_BASE(0x031C) - -#define HDMI_ACR_CON HDMI_CORE_BASE(0x0400) -#define HDMI_ACR_MCTS0 HDMI_CORE_BASE(0x0410) -#define HDMI_ACR_MCTS1 HDMI_CORE_BASE(0x0414) -#define HDMI_ACR_MCTS2 HDMI_CORE_BASE(0x0418) -#define HDMI_ACR_CTS0 HDMI_CORE_BASE(0x0420) -#define HDMI_ACR_CTS1 HDMI_CORE_BASE(0x0424) -#define HDMI_ACR_CTS2 HDMI_CORE_BASE(0x0428) -#define HDMI_ACR_N0 HDMI_CORE_BASE(0x0430) -#define HDMI_ACR_N1 HDMI_CORE_BASE(0x0434) -#define HDMI_ACR_N2 HDMI_CORE_BASE(0x0438) - -/* Packet related registers */ -#define HDMI_ACP_CON HDMI_CORE_BASE(0x0500) -#define HDMI_ACP_TYPE HDMI_CORE_BASE(0x0514) -#define HDMI_ACP_DATA(n) HDMI_CORE_BASE(0x0520 + 4 * (n)) - -#define HDMI_ISRC_CON HDMI_CORE_BASE(0x0600) -#define HDMI_ISRC1_HEADER1 HDMI_CORE_BASE(0x0614) -#define HDMI_ISRC1_DATA(n) HDMI_CORE_BASE(0x0620 + 4 * (n)) -#define HDMI_ISRC2_DATA(n) HDMI_CORE_BASE(0x06A0 + 4 * (n)) - -#define HDMI_AVI_CON HDMI_CORE_BASE(0x0700) -#define HDMI_AVI_HEADER0 HDMI_CORE_BASE(0x0710) -#define HDMI_AVI_HEADER1 HDMI_CORE_BASE(0x0714) -#define HDMI_AVI_HEADER2 HDMI_CORE_BASE(0x0718) -#define HDMI_AVI_CHECK_SUM HDMI_CORE_BASE(0x071C) -#define HDMI_AVI_BYTE(n) HDMI_CORE_BASE(0x0720 + 4 * (n)) - -#define HDMI_AUI_CON HDMI_CORE_BASE(0x0800) -#define HDMI_AUI_HEADER0 HDMI_CORE_BASE(0x0810) -#define HDMI_AUI_HEADER1 HDMI_CORE_BASE(0x0814) -#define HDMI_AUI_HEADER2 HDMI_CORE_BASE(0x0818) -#define HDMI_AUI_CHECK_SUM HDMI_CORE_BASE(0x081C) -#define HDMI_AUI_BYTE(n) HDMI_CORE_BASE(0x0820 + 4 * (n)) - -#define HDMI_MPG_CON HDMI_CORE_BASE(0x0900) -#define HDMI_MPG_CHECK_SUM HDMI_CORE_BASE(0x091C) -#define HDMI_MPG_DATA(n) HDMI_CORE_BASE(0x0920 + 4 * (n)) - -#define HDMI_SPD_CON HDMI_CORE_BASE(0x0A00) -#define HDMI_SPD_HEADER0 HDMI_CORE_BASE(0x0A10) -#define HDMI_SPD_HEADER1 HDMI_CORE_BASE(0x0A14) -#define HDMI_SPD_HEADER2 HDMI_CORE_BASE(0x0A18) -#define HDMI_SPD_DATA(n) HDMI_CORE_BASE(0x0A20 + 4 * (n)) - -#define HDMI_GAMUT_CON HDMI_CORE_BASE(0x0B00) -#define HDMI_GAMUT_HEADER0 HDMI_CORE_BASE(0x0B10) -#define HDMI_GAMUT_HEADER1 HDMI_CORE_BASE(0x0B14) -#define HDMI_GAMUT_HEADER2 HDMI_CORE_BASE(0x0B18) -#define HDMI_GAMUT_METADATA(n) HDMI_CORE_BASE(0x0B20 + 4 * (n)) - -#define HDMI_VSI_CON HDMI_CORE_BASE(0x0C00) -#define HDMI_VSI_HEADER0 HDMI_CORE_BASE(0x0C10) -#define HDMI_VSI_HEADER1 HDMI_CORE_BASE(0x0C14) -#define HDMI_VSI_HEADER2 HDMI_CORE_BASE(0x0C18) -#define HDMI_VSI_DATA(n) HDMI_CORE_BASE(0x0C20 + 4 * (n)) - -#define HDMI_DC_CONTROL HDMI_CORE_BASE(0x0D00) -#define HDMI_VIDEO_PATTERN_GEN HDMI_CORE_BASE(0x0D04) - -#define HDMI_AN_SEED_SEL HDMI_CORE_BASE(0x0E48) -#define HDMI_AN_SEED_0 HDMI_CORE_BASE(0x0E58) -#define HDMI_AN_SEED_1 HDMI_CORE_BASE(0x0E5C) -#define HDMI_AN_SEED_2 HDMI_CORE_BASE(0x0E60) -#define HDMI_AN_SEED_3 HDMI_CORE_BASE(0x0E64) - -/* HDCP related registers */ -#define HDMI_HDCP_SHA1(n) HDMI_CORE_BASE(0x7000 + 4 * (n)) -#define HDMI_HDCP_KSV_LIST(n) HDMI_CORE_BASE(0x7050 + 4 * (n)) - -#define HDMI_HDCP_KSV_LIST_CON HDMI_CORE_BASE(0x7064) -#define HDMI_HDCP_SHA_RESULT HDMI_CORE_BASE(0x7070) -#define HDMI_HDCP_CTRL1 HDMI_CORE_BASE(0x7080) -#define HDMI_HDCP_CTRL2 HDMI_CORE_BASE(0x7084) -#define HDMI_HDCP_CHECK_RESULT HDMI_CORE_BASE(0x7090) -#define HDMI_HDCP_BKSV(n) HDMI_CORE_BASE(0x70A0 + 4 * (n)) -#define HDMI_HDCP_AKSV(n) HDMI_CORE_BASE(0x70C0 + 4 * (n)) -#define HDMI_HDCP_AN(n) HDMI_CORE_BASE(0x70E0 + 4 * (n)) - -#define HDMI_HDCP_BCAPS HDMI_CORE_BASE(0x7100) -#define HDMI_HDCP_BSTATUS_0 HDMI_CORE_BASE(0x7110) -#define HDMI_HDCP_BSTATUS_1 HDMI_CORE_BASE(0x7114) -#define HDMI_HDCP_RI_0 HDMI_CORE_BASE(0x7140) -#define HDMI_HDCP_RI_1 HDMI_CORE_BASE(0x7144) -#define HDMI_HDCP_I2C_INT HDMI_CORE_BASE(0x7180) -#define HDMI_HDCP_AN_INT HDMI_CORE_BASE(0x7190) -#define HDMI_HDCP_WDT_INT HDMI_CORE_BASE(0x71A0) -#define HDMI_HDCP_RI_INT HDMI_CORE_BASE(0x71B0) -#define HDMI_HDCP_RI_COMPARE_0 HDMI_CORE_BASE(0x71D0) -#define HDMI_HDCP_RI_COMPARE_1 HDMI_CORE_BASE(0x71D4) -#define HDMI_HDCP_FRAME_COUNT HDMI_CORE_BASE(0x71E0) - -#define HDMI_RGB_ROUND_EN HDMI_CORE_BASE(0xD500) -#define HDMI_VACT_SPACE_R_0 HDMI_CORE_BASE(0xD504) -#define HDMI_VACT_SPACE_R_1 HDMI_CORE_BASE(0xD508) -#define HDMI_VACT_SPACE_G_0 HDMI_CORE_BASE(0xD50C) -#define HDMI_VACT_SPACE_G_1 HDMI_CORE_BASE(0xD510) -#define HDMI_VACT_SPACE_B_0 HDMI_CORE_BASE(0xD514) -#define HDMI_VACT_SPACE_B_1 HDMI_CORE_BASE(0xD518) - -#define HDMI_BLUE_SCREEN_B_0 HDMI_CORE_BASE(0xD520) -#define HDMI_BLUE_SCREEN_B_1 HDMI_CORE_BASE(0xD524) -#define HDMI_BLUE_SCREEN_G_0 HDMI_CORE_BASE(0xD528) -#define HDMI_BLUE_SCREEN_G_1 HDMI_CORE_BASE(0xD52C) -#define HDMI_BLUE_SCREEN_R_0 HDMI_CORE_BASE(0xD530) -#define HDMI_BLUE_SCREEN_R_1 HDMI_CORE_BASE(0xD534) - -/* HDMI I2S register */ -#define HDMI_I2S_CLK_CON HDMI_I2S_BASE(0x000) -#define HDMI_I2S_CON_1 HDMI_I2S_BASE(0x004) -#define HDMI_I2S_CON_2 HDMI_I2S_BASE(0x008) -#define HDMI_I2S_PIN_SEL_0 HDMI_I2S_BASE(0x00c) -#define HDMI_I2S_PIN_SEL_1 HDMI_I2S_BASE(0x010) -#define HDMI_I2S_PIN_SEL_2 HDMI_I2S_BASE(0x014) -#define HDMI_I2S_PIN_SEL_3 HDMI_I2S_BASE(0x018) -#define HDMI_I2S_DSD_CON HDMI_I2S_BASE(0x01c) -#define HDMI_I2S_MUX_CON HDMI_I2S_BASE(0x020) -#define HDMI_I2S_CH_ST_CON HDMI_I2S_BASE(0x024) -#define HDMI_I2S_CH_ST_0 HDMI_I2S_BASE(0x028) -#define HDMI_I2S_CH_ST_1 HDMI_I2S_BASE(0x02c) -#define HDMI_I2S_CH_ST_2 HDMI_I2S_BASE(0x030) -#define HDMI_I2S_CH_ST_3 HDMI_I2S_BASE(0x034) -#define HDMI_I2S_CH_ST_4 HDMI_I2S_BASE(0x038) -#define HDMI_I2S_CH_ST_SH_0 HDMI_I2S_BASE(0x03c) -#define HDMI_I2S_CH_ST_SH_1 HDMI_I2S_BASE(0x040) -#define HDMI_I2S_CH_ST_SH_2 HDMI_I2S_BASE(0x044) -#define HDMI_I2S_CH_ST_SH_3 HDMI_I2S_BASE(0x048) -#define HDMI_I2S_CH_ST_SH_4 HDMI_I2S_BASE(0x04c) -#define HDMI_I2S_VD_DATA HDMI_I2S_BASE(0x050) -#define HDMI_I2S_MUX_CH HDMI_I2S_BASE(0x054) -#define HDMI_I2S_MUX_CUV HDMI_I2S_BASE(0x058) -#define HDMI_I2S_IRQ_MASK HDMI_I2S_BASE(0x05c) -#define HDMI_I2S_IRQ_STATUS HDMI_I2S_BASE(0x060) - -/* I2S bit definition */ - -/* I2S_CLK_CON */ -#define HDMI_I2S_CLK_DIS (0) -#define HDMI_I2S_CLK_EN (1) - -/* I2S_CON_1 */ -#define HDMI_I2S_SCLK_FALLING_EDGE (0 << 1) -#define HDMI_I2S_SCLK_RISING_EDGE (1 << 1) -#define HDMI_I2S_L_CH_LOW_POL (0) -#define HDMI_I2S_L_CH_HIGH_POL (1) - -/* I2S_CON_2 */ -#define HDMI_I2S_MSB_FIRST_MODE (0 << 6) -#define HDMI_I2S_LSB_FIRST_MODE (1 << 6) -#define HDMI_I2S_BIT_CH_32FS (0 << 4) -#define HDMI_I2S_BIT_CH_48FS (1 << 4) -#define HDMI_I2S_BIT_CH_RESERVED (2 << 4) -#define HDMI_I2S_SDATA_16BIT (1 << 2) -#define HDMI_I2S_SDATA_20BIT (2 << 2) -#define HDMI_I2S_SDATA_24BIT (3 << 2) -#define HDMI_I2S_BASIC_FORMAT (0) -#define HDMI_I2S_L_JUST_FORMAT (2) -#define HDMI_I2S_R_JUST_FORMAT (3) -#define HDMI_I2S_CON_2_CLR (~(0xFF)) -#define HDMI_I2S_SET_BIT_CH(x) (((x) & 0x7) << 4) -#define HDMI_I2S_SET_SDATA_BIT(x) (((x) & 0x7) << 2) - -/* I2S_PIN_SEL_0 */ -#define HDMI_I2S_SEL_SCLK(x) (((x) & 0x7) << 4) -#define HDMI_I2S_SEL_SCLK_DEFAULT_1 (0x7 << 4) -#define HDMI_I2S_SEL_LRCK(x) ((x) & 0x7) -#define HDMI_I2S_SEL_LRCK_DEFAULT_0 (0x7) - -/* I2S_PIN_SEL_1 */ -#define HDMI_I2S_SEL_SDATA1(x) (((x) & 0x7) << 4) -#define HDMI_I2S_SEL_SDATA1_DEFAULT_3 (0x7 << 4) -#define HDMI_I2S_SEL_SDATA2(x) ((x) & 0x7) -#define HDMI_I2S_SEL_SDATA2_DEFAULT_2 (0x7) - -/* I2S_PIN_SEL_2 */ -#define HDMI_I2S_SEL_SDATA3(x) (((x) & 0x7) << 4) -#define HDMI_I2S_SEL_SDATA3_DEFAULT_5 (0x7 << 4) -#define HDMI_I2S_SEL_SDATA2(x) ((x) & 0x7) -#define HDMI_I2S_SEL_SDATA2_DEFAULT_4 (0x7) - -/* I2S_PIN_SEL_3 */ -#define HDMI_I2S_SEL_DSD(x) ((x) & 0x7) -#define HDMI_I2S_SEL_DSD_DEFAULT_6 (0x7) - -/* I2S_DSD_CON */ -#define HDMI_I2S_DSD_CLK_RI_EDGE (1 << 1) -#define HDMI_I2S_DSD_CLK_FA_EDGE (0 << 1) -#define HDMI_I2S_DSD_ENABLE (1) -#define HDMI_I2S_DSD_DISABLE (0) - -/* I2S_MUX_CON */ -#define HDMI_I2S_NOISE_FILTER_ZERO (0 << 5) -#define HDMI_I2S_NOISE_FILTER_2_STAGE (1 << 5) -#define HDMI_I2S_NOISE_FILTER_3_STAGE (2 << 5) -#define HDMI_I2S_NOISE_FILTER_4_STAGE (3 << 5) -#define HDMI_I2S_NOISE_FILTER_5_STAGE (4 << 5) -#define HDMI_I2S_IN_DISABLE (1 << 4) -#define HDMI_I2S_IN_ENABLE (0 << 4) -#define HDMI_I2S_AUD_SPDIF (0 << 2) -#define HDMI_I2S_AUD_I2S (1 << 2) -#define HDMI_I2S_AUD_DSD (2 << 2) -#define HDMI_I2S_CUV_SPDIF_ENABLE (0 << 1) -#define HDMI_I2S_CUV_I2S_ENABLE (1 << 1) -#define HDMI_I2S_MUX_DISABLE (0) -#define HDMI_I2S_MUX_ENABLE (1) -#define HDMI_I2S_MUX_CON_CLR (~(0xFF)) - -/* I2S_CH_ST_CON */ -#define HDMI_I2S_CH_STATUS_RELOAD (1) -#define HDMI_I2S_CH_ST_CON_CLR (~(1)) - -/* I2S_CH_ST_0 / I2S_CH_ST_SH_0 */ -#define HDMI_I2S_CH_STATUS_MODE_0 (0 << 6) -#define HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH (0 << 3) -#define HDMI_I2S_2AUD_CH_WITH_PREEMPH (1 << 3) -#define HDMI_I2S_DEFAULT_EMPHASIS (0 << 3) -#define HDMI_I2S_COPYRIGHT (0 << 2) -#define HDMI_I2S_NO_COPYRIGHT (1 << 2) -#define HDMI_I2S_LINEAR_PCM (0 << 1) -#define HDMI_I2S_NO_LINEAR_PCM (1 << 1) -#define HDMI_I2S_CONSUMER_FORMAT (0) -#define HDMI_I2S_PROF_FORMAT (1) -#define HDMI_I2S_CH_ST_0_CLR (~(0xFF)) - -/* I2S_CH_ST_1 / I2S_CH_ST_SH_1 */ -#define HDMI_I2S_CD_PLAYER (0x00) -#define HDMI_I2S_DAT_PLAYER (0x03) -#define HDMI_I2S_DCC_PLAYER (0x43) -#define HDMI_I2S_MINI_DISC_PLAYER (0x49) - -/* I2S_CH_ST_2 / I2S_CH_ST_SH_2 */ -#define HDMI_I2S_CHANNEL_NUM_MASK (0xF << 4) -#define HDMI_I2S_SOURCE_NUM_MASK (0xF) -#define HDMI_I2S_SET_CHANNEL_NUM(x) (((x) & (0xF)) << 4) -#define HDMI_I2S_SET_SOURCE_NUM(x) ((x) & (0xF)) - -/* I2S_CH_ST_3 / I2S_CH_ST_SH_3 */ -#define HDMI_I2S_CLK_ACCUR_LEVEL_1 (1 << 4) -#define HDMI_I2S_CLK_ACCUR_LEVEL_2 (0 << 4) -#define HDMI_I2S_CLK_ACCUR_LEVEL_3 (2 << 4) -#define HDMI_I2S_SMP_FREQ_44_1 (0x0) -#define HDMI_I2S_SMP_FREQ_48 (0x2) -#define HDMI_I2S_SMP_FREQ_32 (0x3) -#define HDMI_I2S_SMP_FREQ_96 (0xA) -#define HDMI_I2S_SET_SMP_FREQ(x) ((x) & (0xF)) - -/* I2S_CH_ST_4 / I2S_CH_ST_SH_4 */ -#define HDMI_I2S_ORG_SMP_FREQ_44_1 (0xF << 4) -#define HDMI_I2S_ORG_SMP_FREQ_88_2 (0x7 << 4) -#define HDMI_I2S_ORG_SMP_FREQ_22_05 (0xB << 4) -#define HDMI_I2S_ORG_SMP_FREQ_176_4 (0x3 << 4) -#define HDMI_I2S_WORD_LEN_NOT_DEFINE (0x0 << 1) -#define HDMI_I2S_WORD_LEN_MAX24_20BITS (0x1 << 1) -#define HDMI_I2S_WORD_LEN_MAX24_22BITS (0x2 << 1) -#define HDMI_I2S_WORD_LEN_MAX24_23BITS (0x4 << 1) -#define HDMI_I2S_WORD_LEN_MAX24_24BITS (0x5 << 1) -#define HDMI_I2S_WORD_LEN_MAX24_21BITS (0x6 << 1) -#define HDMI_I2S_WORD_LEN_MAX20_16BITS (0x1 << 1) -#define HDMI_I2S_WORD_LEN_MAX20_18BITS (0x2 << 1) -#define HDMI_I2S_WORD_LEN_MAX20_19BITS (0x4 << 1) -#define HDMI_I2S_WORD_LEN_MAX20_20BITS (0x5 << 1) -#define HDMI_I2S_WORD_LEN_MAX20_17BITS (0x6 << 1) -#define HDMI_I2S_WORD_LEN_MAX_24BITS (1) -#define HDMI_I2S_WORD_LEN_MAX_20BITS (0) - -/* I2S_VD_DATA */ -#define HDMI_I2S_VD_AUD_SMP_RELIABLE (0) -#define HDMI_I2S_VD_AUD_SMP_UNRELIABLE (1) - -/* I2S_MUX_CH */ -#define HDMI_I2S_CH3_R_EN (1 << 7) -#define HDMI_I2S_CH3_L_EN (1 << 6) -#define HDMI_I2S_CH3_EN (3 << 6) -#define HDMI_I2S_CH2_R_EN (1 << 5) -#define HDMI_I2S_CH2_L_EN (1 << 4) -#define HDMI_I2S_CH2_EN (3 << 4) -#define HDMI_I2S_CH1_R_EN (1 << 3) -#define HDMI_I2S_CH1_L_EN (1 << 2) -#define HDMI_I2S_CH1_EN (3 << 2) -#define HDMI_I2S_CH0_R_EN (1 << 1) -#define HDMI_I2S_CH0_L_EN (1) -#define HDMI_I2S_CH0_EN (3) -#define HDMI_I2S_CH_ALL_EN (0xFF) -#define HDMI_I2S_MUX_CH_CLR (~HDMI_I2S_CH_ALL_EN) - -/* I2S_MUX_CUV */ -#define HDMI_I2S_CUV_R_EN (1 << 1) -#define HDMI_I2S_CUV_L_EN (1) -#define HDMI_I2S_CUV_RL_EN (0x03) - -/* I2S_IRQ_MASK */ -#define HDMI_I2S_INT2_DIS (0 << 1) -#define HDMI_I2S_INT2_EN (1 << 1) - -/* I2S_IRQ_STATUS */ -#define HDMI_I2S_INT2_STATUS (1 << 1) - -/* I2S_CUV_L_R */ -#define HDMI_I2S_CUV_R_DATA_MASK (0x7 << 4) -#define HDMI_I2S_CUV_L_DATA_MASK (0x7) - -/* Audio Related Packet bit definition */ - -/* ASP_CON */ -#define HDMI_AUD_DST_DOUBLE (1 << 7) -#define HDMI_AUD_NO_DST_DOUBLE (0 << 7) -#define HDMI_AUD_TYPE_SAMPLE (0 << 5) -#define HDMI_AUD_TYPE_ONE_BIT (1 << 5) -#define HDMI_AUD_TYPE_HBR (2 << 5) -#define HDMI_AUD_TYPE_DST (3 << 5) -#define HDMI_AUD_MODE_TWO_CH (0 << 4) -#define HDMI_AUD_MODE_MULTI_CH (1 << 4) -#define HDMI_AUD_SP_AUD3_EN (1 << 3) -#define HDMI_AUD_SP_AUD2_EN (1 << 2) -#define HDMI_AUD_SP_AUD1_EN (1 << 1) -#define HDMI_AUD_SP_AUD0_EN (1 << 0) -#define HDMI_AUD_SP_ALL_DIS (0 << 0) - -#define HDMI_AUD_SET_SP_PRE(x) ((x) & 0xF) - -/* ASP_SP_FLAT */ -#define HDMI_ASP_SP_FLAT_AUD_SAMPLE (0) - -/* ASP_CHCFG0/1/2/3 */ -#define HDMI_SPK3R_SEL_I_PCM0L (0 << 27) -#define HDMI_SPK3R_SEL_I_PCM0R (1 << 27) -#define HDMI_SPK3R_SEL_I_PCM1L (2 << 27) -#define HDMI_SPK3R_SEL_I_PCM1R (3 << 27) -#define HDMI_SPK3R_SEL_I_PCM2L (4 << 27) -#define HDMI_SPK3R_SEL_I_PCM2R (5 << 27) -#define HDMI_SPK3R_SEL_I_PCM3L (6 << 27) -#define HDMI_SPK3R_SEL_I_PCM3R (7 << 27) -#define HDMI_SPK3L_SEL_I_PCM0L (0 << 24) -#define HDMI_SPK3L_SEL_I_PCM0R (1 << 24) -#define HDMI_SPK3L_SEL_I_PCM1L (2 << 24) -#define HDMI_SPK3L_SEL_I_PCM1R (3 << 24) -#define HDMI_SPK3L_SEL_I_PCM2L (4 << 24) -#define HDMI_SPK3L_SEL_I_PCM2R (5 << 24) -#define HDMI_SPK3L_SEL_I_PCM3L (6 << 24) -#define HDMI_SPK3L_SEL_I_PCM3R (7 << 24) -#define HDMI_SPK2R_SEL_I_PCM0L (0 << 19) -#define HDMI_SPK2R_SEL_I_PCM0R (1 << 19) -#define HDMI_SPK2R_SEL_I_PCM1L (2 << 19) -#define HDMI_SPK2R_SEL_I_PCM1R (3 << 19) -#define HDMI_SPK2R_SEL_I_PCM2L (4 << 19) -#define HDMI_SPK2R_SEL_I_PCM2R (5 << 19) -#define HDMI_SPK2R_SEL_I_PCM3L (6 << 19) -#define HDMI_SPK2R_SEL_I_PCM3R (7 << 19) -#define HDMI_SPK2L_SEL_I_PCM0L (0 << 16) -#define HDMI_SPK2L_SEL_I_PCM0R (1 << 16) -#define HDMI_SPK2L_SEL_I_PCM1L (2 << 16) -#define HDMI_SPK2L_SEL_I_PCM1R (3 << 16) -#define HDMI_SPK2L_SEL_I_PCM2L (4 << 16) -#define HDMI_SPK2L_SEL_I_PCM2R (5 << 16) -#define HDMI_SPK2L_SEL_I_PCM3L (6 << 16) -#define HDMI_SPK2L_SEL_I_PCM3R (7 << 16) -#define HDMI_SPK1R_SEL_I_PCM0L (0 << 11) -#define HDMI_SPK1R_SEL_I_PCM0R (1 << 11) -#define HDMI_SPK1R_SEL_I_PCM1L (2 << 11) -#define HDMI_SPK1R_SEL_I_PCM1R (3 << 11) -#define HDMI_SPK1R_SEL_I_PCM2L (4 << 11) -#define HDMI_SPK1R_SEL_I_PCM2R (5 << 11) -#define HDMI_SPK1R_SEL_I_PCM3L (6 << 11) -#define HDMI_SPK1R_SEL_I_PCM3R (7 << 11) -#define HDMI_SPK1L_SEL_I_PCM0L (0 << 8) -#define HDMI_SPK1L_SEL_I_PCM0R (1 << 8) -#define HDMI_SPK1L_SEL_I_PCM1L (2 << 8) -#define HDMI_SPK1L_SEL_I_PCM1R (3 << 8) -#define HDMI_SPK1L_SEL_I_PCM2L (4 << 8) -#define HDMI_SPK1L_SEL_I_PCM2R (5 << 8) -#define HDMI_SPK1L_SEL_I_PCM3L (6 << 8) -#define HDMI_SPK1L_SEL_I_PCM3R (7 << 8) -#define HDMI_SPK0R_SEL_I_PCM0L (0 << 3) -#define HDMI_SPK0R_SEL_I_PCM0R (1 << 3) -#define HDMI_SPK0R_SEL_I_PCM1L (2 << 3) -#define HDMI_SPK0R_SEL_I_PCM1R (3 << 3) -#define HDMI_SPK0R_SEL_I_PCM2L (4 << 3) -#define HDMI_SPK0R_SEL_I_PCM2R (5 << 3) -#define HDMI_SPK0R_SEL_I_PCM3L (6 << 3) -#define HDMI_SPK0R_SEL_I_PCM3R (7 << 3) -#define HDMI_SPK0L_SEL_I_PCM0L (0) -#define HDMI_SPK0L_SEL_I_PCM0R (1) -#define HDMI_SPK0L_SEL_I_PCM1L (2) -#define HDMI_SPK0L_SEL_I_PCM1R (3) -#define HDMI_SPK0L_SEL_I_PCM2L (4) -#define HDMI_SPK0L_SEL_I_PCM2R (5) -#define HDMI_SPK0L_SEL_I_PCM3L (6) -#define HDMI_SPK0L_SEL_I_PCM3R (7) - -/* ACR_CON */ -#define HDMI_ALT_CTS_RATE_CTS_1 (0 << 3) -#define HDMI_ALT_CTS_RATE_CTS_11 (1 << 3) -#define HDMI_ALT_CTS_RATE_CTS_21 (2 << 3) -#define HDMI_ALT_CTS_RATE_CTS_31 (3 << 3) -#define HDMI_ACR_TX_MODE_NO_TX (0) -#define HDMI_ACR_TX_MODE_TX_ONCE (1) -#define HDMI_ACR_TX_MODE_TXCNT_VBI (2) -#define HDMI_ACR_TX_MODE_TX_VPC (3) -#define HDMI_ACR_TX_MODE_MESURE_CTS (4) - -/* ACR_MCTS0/1/2 */ - -/* ACR_CTS0/1/2 */ - -/* ACR_N0/1/2 */ - -/* ACR_LSB2 */ -#define HDMI_ACR_LSB2_MASK (0xFF) - -/* ACR_TXCNT */ -#define HDMI_ACR_TXCNT_MASK (0x1F) - -/* ACR_TXINTERNAL */ -#define HDMI_ACR_TX_INTERNAL_MASK (0xFF) - -/* ACR_CTS_OFFSET */ -#define HDMI_ACR_CTS_OFFSET_MASK (0xFF) - -/* GCP_CON */ -#define HDMI_GCP_CON_EN_1ST_VSYNC (1 << 3) -#define HDMI_GCP_CON_EN_2ST_VSYNC (1 << 2) -#define HDMI_GCP_CON_TRANS_EVERY_VSYNC (2) -#define HDMI_GCP_CON_NO_TRAN (0) -#define HDMI_GCP_CON_TRANS_ONCE (1) -#define HDMI_GCP_CON_TRANS_EVERY_VSYNC (2) - -/* GCP_BYTE1 */ -#define HDMI_GCP_BYTE1_MASK (0xFF) - -/* GCP_BYTE2 */ -#define HDMI_GCP_BYTE2_PP_MASK (0xF << 4) -#define HDMI_GCP_24BPP (1 << 2) -#define HDMI_GCP_30BPP (1 << 0 | 1 << 2) -#define HDMI_GCP_36BPP (1 << 1 | 1 << 2) -#define HDMI_GCP_48BPP (1 << 0 | 1 << 1 | 1 << 2) - -/* GCP_BYTE3 */ -#define HDMI_GCP_BYTE3_MASK (0xFF) - -/* Timing generator registers */ -/* TG configure/status registers */ -#define HDMI_TG_VACT_ST3_L HDMI_TG_BASE(0x0068) -#define HDMI_TG_VACT_ST3_H HDMI_TG_BASE(0x006c) -#define HDMI_TG_VACT_ST4_L HDMI_TG_BASE(0x0070) -#define HDMI_TG_VACT_ST4_H HDMI_TG_BASE(0x0074) -#define HDMI_TG_3D HDMI_TG_BASE(0x00F0) - -#endif /* SAMSUNG_REGS_HDMI_H */ diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h deleted file mode 100644 index fd2f4d1..0000000 --- a/drivers/gpu/drm/exynos/regs-mixer.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * - * Cloned from drivers/media/video/s5p-tv/regs-mixer.h - * - * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * Mixer register header file for Samsung Mixer driver - * - * 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. -*/ -#ifndef SAMSUNG_REGS_MIXER_H -#define SAMSUNG_REGS_MIXER_H - -/* - * Register part - */ -#define MXR_STATUS 0x0000 -#define MXR_CFG 0x0004 -#define MXR_INT_EN 0x0008 -#define MXR_INT_STATUS 0x000C -#define MXR_LAYER_CFG 0x0010 -#define MXR_VIDEO_CFG 0x0014 -#define MXR_GRAPHIC0_CFG 0x0020 -#define MXR_GRAPHIC0_BASE 0x0024 -#define MXR_GRAPHIC0_SPAN 0x0028 -#define MXR_GRAPHIC0_SXY 0x002C -#define MXR_GRAPHIC0_WH 0x0030 -#define MXR_GRAPHIC0_DXY 0x0034 -#define MXR_GRAPHIC0_BLANK 0x0038 -#define MXR_GRAPHIC1_CFG 0x0040 -#define MXR_GRAPHIC1_BASE 0x0044 -#define MXR_GRAPHIC1_SPAN 0x0048 -#define MXR_GRAPHIC1_SXY 0x004C -#define MXR_GRAPHIC1_WH 0x0050 -#define MXR_GRAPHIC1_DXY 0x0054 -#define MXR_GRAPHIC1_BLANK 0x0058 -#define MXR_BG_CFG 0x0060 -#define MXR_BG_COLOR0 0x0064 -#define MXR_BG_COLOR1 0x0068 -#define MXR_BG_COLOR2 0x006C -#define MXR_CM_COEFF_Y 0x0080 -#define MXR_CM_COEFF_CB 0x0084 -#define MXR_CM_COEFF_CR 0x0088 -#define MXR_GRAPHIC0_BASE_S 0x2024 -#define MXR_GRAPHIC1_BASE_S 0x2044 - -/* for parametrized access to layer registers */ -#define MXR_GRAPHIC_CFG(i) (0x0020 + (i) * 0x20) -#define MXR_GRAPHIC_BASE(i) (0x0024 + (i) * 0x20) -#define MXR_GRAPHIC_SPAN(i) (0x0028 + (i) * 0x20) -#define MXR_GRAPHIC_SXY(i) (0x002C + (i) * 0x20) -#define MXR_GRAPHIC_WH(i) (0x0030 + (i) * 0x20) -#define MXR_GRAPHIC_DXY(i) (0x0034 + (i) * 0x20) -#define MXR_GRAPHIC_BLANK(i) (0x0038 + (i) * 0x20) -#define MXR_GRAPHIC_BASE_S(i) (0x2024 + (i) * 0x20) - -/* - * Bit definition part - */ - -/* generates mask for range of bits */ -#define MXR_MASK(high_bit, low_bit) \ - (((2 << ((high_bit) - (low_bit))) - 1) << (low_bit)) - -#define MXR_MASK_VAL(val, high_bit, low_bit) \ - (((val) << (low_bit)) & MXR_MASK(high_bit, low_bit)) - -/* bits for MXR_STATUS */ -#define MXR_STATUS_16_BURST (1 << 7) -#define MXR_STATUS_BURST_MASK (1 << 7) -#define MXR_STATUS_BIG_ENDIAN (1 << 3) -#define MXR_STATUS_ENDIAN_MASK (1 << 3) -#define MXR_STATUS_SYNC_ENABLE (1 << 2) -#define MXR_STATUS_REG_RUN (1 << 0) - -/* bits for MXR_CFG */ -#define MXR_CFG_RGB601_0_255 (0 << 9) -#define MXR_CFG_RGB601_16_235 (1 << 9) -#define MXR_CFG_RGB709_0_255 (2 << 9) -#define MXR_CFG_RGB709_16_235 (3 << 9) -#define MXR_CFG_RGB_FMT_MASK 0x600 -#define MXR_CFG_OUT_YUV444 (0 << 8) -#define MXR_CFG_OUT_RGB888 (1 << 8) -#define MXR_CFG_OUT_MASK (1 << 8) -#define MXR_CFG_DST_SDO (0 << 7) -#define MXR_CFG_DST_HDMI (1 << 7) -#define MXR_CFG_DST_MASK (1 << 7) -#define MXR_CFG_SCAN_HD_720 (0 << 6) -#define MXR_CFG_SCAN_HD_1080 (1 << 6) -#define MXR_CFG_GRP1_ENABLE (1 << 5) -#define MXR_CFG_GRP0_ENABLE (1 << 4) -#define MXR_CFG_VP_ENABLE (1 << 3) -#define MXR_CFG_SCAN_INTERLACE (0 << 2) -#define MXR_CFG_SCAN_PROGRASSIVE (1 << 2) -#define MXR_CFG_SCAN_NTSC (0 << 1) -#define MXR_CFG_SCAN_PAL (1 << 1) -#define MXR_CFG_SCAN_SD (0 << 0) -#define MXR_CFG_SCAN_HD (1 << 0) -#define MXR_CFG_SCAN_MASK 0x47 - -/* bits for MXR_GRAPHICn_CFG */ -#define MXR_GRP_CFG_COLOR_KEY_DISABLE (1 << 21) -#define MXR_GRP_CFG_BLEND_PRE_MUL (1 << 20) -#define MXR_GRP_CFG_WIN_BLEND_EN (1 << 17) -#define MXR_GRP_CFG_PIXEL_BLEND_EN (1 << 16) -#define MXR_GRP_CFG_FORMAT_VAL(x) MXR_MASK_VAL(x, 11, 8) -#define MXR_GRP_CFG_FORMAT_MASK MXR_GRP_CFG_FORMAT_VAL(~0) -#define MXR_GRP_CFG_ALPHA_VAL(x) MXR_MASK_VAL(x, 7, 0) - -/* bits for MXR_GRAPHICn_WH */ -#define MXR_GRP_WH_H_SCALE(x) MXR_MASK_VAL(x, 28, 28) -#define MXR_GRP_WH_V_SCALE(x) MXR_MASK_VAL(x, 12, 12) -#define MXR_GRP_WH_WIDTH(x) MXR_MASK_VAL(x, 26, 16) -#define MXR_GRP_WH_HEIGHT(x) MXR_MASK_VAL(x, 10, 0) - -/* bits for MXR_GRAPHICn_SXY */ -#define MXR_GRP_SXY_SX(x) MXR_MASK_VAL(x, 26, 16) -#define MXR_GRP_SXY_SY(x) MXR_MASK_VAL(x, 10, 0) - -/* bits for MXR_GRAPHICn_DXY */ -#define MXR_GRP_DXY_DX(x) MXR_MASK_VAL(x, 26, 16) -#define MXR_GRP_DXY_DY(x) MXR_MASK_VAL(x, 10, 0) - -/* bits for MXR_INT_EN */ -#define MXR_INT_EN_VSYNC (1 << 11) -#define MXR_INT_EN_ALL (0x0f << 8) - -/* bit for MXR_INT_STATUS */ -#define MXR_INT_CLEAR_VSYNC (1 << 11) -#define MXR_INT_STATUS_VSYNC (1 << 0) - -/* bit for MXR_LAYER_CFG */ -#define MXR_LAYER_CFG_GRP1_VAL(x) MXR_MASK_VAL(x, 11, 8) -#define MXR_LAYER_CFG_GRP0_VAL(x) MXR_MASK_VAL(x, 7, 4) -#define MXR_LAYER_CFG_VP_VAL(x) MXR_MASK_VAL(x, 3, 0) - -#endif /* SAMSUNG_REGS_MIXER_H */ - diff --git a/drivers/gpu/drm/exynos/regs-vp.h b/drivers/gpu/drm/exynos/regs-vp.h deleted file mode 100644 index 10b737a..0000000 --- a/drivers/gpu/drm/exynos/regs-vp.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * Cloned from drivers/media/video/s5p-tv/regs-vp.h - * - * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * Video processor register header file for Samsung Mixer driver - * - * 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. - */ - -#ifndef SAMSUNG_REGS_VP_H -#define SAMSUNG_REGS_VP_H - -/* - * Register part - */ - -#define VP_ENABLE 0x0000 -#define VP_SRESET 0x0004 -#define VP_SHADOW_UPDATE 0x0008 -#define VP_FIELD_ID 0x000C -#define VP_MODE 0x0010 -#define VP_IMG_SIZE_Y 0x0014 -#define VP_IMG_SIZE_C 0x0018 -#define VP_PER_RATE_CTRL 0x001C -#define VP_TOP_Y_PTR 0x0028 -#define VP_BOT_Y_PTR 0x002C -#define VP_TOP_C_PTR 0x0030 -#define VP_BOT_C_PTR 0x0034 -#define VP_ENDIAN_MODE 0x03CC -#define VP_SRC_H_POSITION 0x0044 -#define VP_SRC_V_POSITION 0x0048 -#define VP_SRC_WIDTH 0x004C -#define VP_SRC_HEIGHT 0x0050 -#define VP_DST_H_POSITION 0x0054 -#define VP_DST_V_POSITION 0x0058 -#define VP_DST_WIDTH 0x005C -#define VP_DST_HEIGHT 0x0060 -#define VP_H_RATIO 0x0064 -#define VP_V_RATIO 0x0068 -#define VP_POLY8_Y0_LL 0x006C -#define VP_POLY4_Y0_LL 0x00EC -#define VP_POLY4_C0_LL 0x012C - -/* - * Bit definition part - */ - -/* generates mask for range of bits */ - -#define VP_MASK(high_bit, low_bit) \ - (((2 << ((high_bit) - (low_bit))) - 1) << (low_bit)) - -#define VP_MASK_VAL(val, high_bit, low_bit) \ - (((val) << (low_bit)) & VP_MASK(high_bit, low_bit)) - - /* VP_ENABLE */ -#define VP_ENABLE_ON (1 << 0) - -/* VP_SRESET */ -#define VP_SRESET_PROCESSING (1 << 0) - -/* VP_SHADOW_UPDATE */ -#define VP_SHADOW_UPDATE_ENABLE (1 << 0) - -/* VP_MODE */ -#define VP_MODE_NV12 (0 << 6) -#define VP_MODE_NV21 (1 << 6) -#define VP_MODE_LINE_SKIP (1 << 5) -#define VP_MODE_MEM_LINEAR (0 << 4) -#define VP_MODE_MEM_TILED (1 << 4) -#define VP_MODE_FMT_MASK (5 << 4) -#define VP_MODE_FIELD_ID_AUTO_TOGGLING (1 << 2) -#define VP_MODE_2D_IPC (1 << 1) - -/* VP_IMG_SIZE_Y */ -/* VP_IMG_SIZE_C */ -#define VP_IMG_HSIZE(x) VP_MASK_VAL(x, 29, 16) -#define VP_IMG_VSIZE(x) VP_MASK_VAL(x, 13, 0) - -/* VP_SRC_H_POSITION */ -#define VP_SRC_H_POSITION_VAL(x) VP_MASK_VAL(x, 14, 4) - -/* VP_ENDIAN_MODE */ -#define VP_ENDIAN_MODE_LITTLE (1 << 0) - -#endif /* SAMSUNG_REGS_VP_H */ diff --git a/drivers/gpu/drm/gma500/Kconfig b/drivers/gpu/drm/gma500/Kconfig deleted file mode 100644 index 42e665c..0000000 --- a/drivers/gpu/drm/gma500/Kconfig +++ /dev/null @@ -1,33 +0,0 @@ -config DRM_GMA500 - tristate "Intel GMA5/600 KMS Framebuffer" - depends on DRM && PCI && X86 && EXPERIMENTAL - select FB_CFB_COPYAREA - select FB_CFB_FILLRECT - select FB_CFB_IMAGEBLIT - select DRM_KMS_HELPER - select DRM_TTM - help - Say yes for an experimental 2D KMS framebuffer driver for the - Intel GMA500 ('Poulsbo') and other Intel IMG based graphics - devices. - -config DRM_GMA600 - bool "Intel GMA600 support (Experimental)" - depends on DRM_GMA500 - help - Say yes to include support for GMA600 (Intel Moorestown/Oaktrail) - platforms with LVDS ports. MIPI is not currently supported. - -config DRM_GMA3600 - bool "Intel GMA3600/3650 support (Experimental)" - depends on DRM_GMA500 - help - Say yes to include basic support for Intel GMA3600/3650 (Intel - Cedar Trail) platforms. - -config DRM_MEDFIELD - bool "Intel Medfield support (Experimental)" - depends on DRM_GMA500 && X86_INTEL_MID - help - Say yes to include support for the Intel Medfield platform. - diff --git a/drivers/gpu/drm/gma500/Makefile b/drivers/gpu/drm/gma500/Makefile deleted file mode 100644 index 1583982..0000000 --- a/drivers/gpu/drm/gma500/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# -# KMS driver for the GMA500 -# -ccflags-y += -Iinclude/drm - -gma500_gfx-y += gem_glue.o \ - accel_2d.o \ - backlight.o \ - framebuffer.o \ - gem.o \ - gtt.o \ - intel_bios.o \ - intel_i2c.o \ - intel_gmbus.o \ - intel_opregion.o \ - mmu.o \ - power.o \ - psb_drv.o \ - psb_intel_display.o \ - psb_intel_lvds.o \ - psb_intel_modes.o \ - psb_intel_sdvo.o \ - psb_lid.o \ - psb_irq.o \ - psb_device.o \ - mid_bios.o - -gma500_gfx-$(CONFIG_DRM_GMA3600) += cdv_device.o \ - cdv_intel_crt.o \ - cdv_intel_display.o \ - cdv_intel_hdmi.o \ - cdv_intel_lvds.o - -gma500_gfx-$(CONFIG_DRM_GMA600) += oaktrail_device.o \ - oaktrail_crtc.o \ - oaktrail_lvds.o \ - oaktrail_hdmi.o \ - oaktrail_hdmi_i2c.o - -gma500_gfx-$(CONFIG_DRM_MEDFIELD) += mdfld_device.o \ - mdfld_output.o \ - mdfld_intel_display.o \ - mdfld_dsi_output.o \ - mdfld_dsi_dpi.o \ - mdfld_dsi_pkg_sender.o \ - mdfld_tpo_vid.o \ - mdfld_tmd_vid.o \ - tc35876x-dsi-lvds.o - -obj-$(CONFIG_DRM_GMA500) += gma500_gfx.o diff --git a/drivers/gpu/drm/gma500/accel_2d.c b/drivers/gpu/drm/gma500/accel_2d.c deleted file mode 100644 index d5ef1a5..0000000 --- a/drivers/gpu/drm/gma500/accel_2d.c +++ /dev/null @@ -1,364 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to - * develop this driver. - * - **************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "psb_drv.h" -#include "psb_reg.h" -#include "framebuffer.h" - -/** - * psb_spank - reset the 2D engine - * @dev_priv: our PSB DRM device - * - * Soft reset the graphics engine and then reload the necessary registers. - * We use this at initialisation time but it will become relevant for - * accelerated X later - */ -void psb_spank(struct drm_psb_private *dev_priv) -{ - PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET | - _PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET | - _PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET | - _PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET); - PSB_RSGX32(PSB_CR_SOFT_RESET); - - msleep(1); - - PSB_WSGX32(0, PSB_CR_SOFT_RESET); - wmb(); - PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT, - PSB_CR_BIF_CTRL); - wmb(); - (void) PSB_RSGX32(PSB_CR_BIF_CTRL); - - msleep(1); - PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT, - PSB_CR_BIF_CTRL); - (void) PSB_RSGX32(PSB_CR_BIF_CTRL); - PSB_WSGX32(dev_priv->gtt.gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); -} - -/** - * psb2_2d_wait_available - wait for FIFO room - * @dev_priv: our DRM device - * @size: size (in dwords) of the command we want to issue - * - * Wait until there is room to load the FIFO with our data. If the - * device is not responding then reset it - */ -static int psb_2d_wait_available(struct drm_psb_private *dev_priv, - unsigned size) -{ - uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF); - unsigned long t = jiffies + HZ; - - while (avail < size) { - avail = PSB_RSGX32(PSB_CR_2D_SOCIF); - if (time_after(jiffies, t)) { - psb_spank(dev_priv); - return -EIO; - } - } - return 0; -} - -/** - * psb_2d_submit - submit a 2D command - * @dev_priv: our DRM device - * @cmdbuf: command to issue - * @size: length (in dwords) - * - * Issue one or more 2D commands to the accelerator. This needs to be - * serialized later when we add the GEM interfaces for acceleration - */ -static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf, - unsigned size) -{ - int ret = 0; - int i; - unsigned submit_size; - unsigned long flags; - - spin_lock_irqsave(&dev_priv->lock_2d, flags); - while (size > 0) { - submit_size = (size < 0x60) ? size : 0x60; - size -= submit_size; - ret = psb_2d_wait_available(dev_priv, submit_size); - if (ret) - break; - - submit_size <<= 2; - - for (i = 0; i < submit_size; i += 4) - PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i); - - (void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4); - } - spin_unlock_irqrestore(&dev_priv->lock_2d, flags); - return ret; -} - - -/** - * psb_accel_2d_copy_direction - compute blit order - * @xdir: X direction of move - * @ydir: Y direction of move - * - * Compute the correct order setings to ensure that an overlapping blit - * correctly copies all the pixels. - */ -static u32 psb_accel_2d_copy_direction(int xdir, int ydir) -{ - if (xdir < 0) - return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL : - PSB_2D_COPYORDER_TR2BL; - else - return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR : - PSB_2D_COPYORDER_TL2BR; -} - -/** - * psb_accel_2d_copy - accelerated 2D copy - * @dev_priv: our DRM device - * @src_offset in bytes - * @src_stride in bytes - * @src_format psb 2D format defines - * @dst_offset in bytes - * @dst_stride in bytes - * @dst_format psb 2D format defines - * @src_x offset in pixels - * @src_y offset in pixels - * @dst_x offset in pixels - * @dst_y offset in pixels - * @size_x of the copied area - * @size_y of the copied area - * - * Format and issue a 2D accelerated copy command. - */ -static int psb_accel_2d_copy(struct drm_psb_private *dev_priv, - uint32_t src_offset, uint32_t src_stride, - uint32_t src_format, uint32_t dst_offset, - uint32_t dst_stride, uint32_t dst_format, - uint16_t src_x, uint16_t src_y, - uint16_t dst_x, uint16_t dst_y, - uint16_t size_x, uint16_t size_y) -{ - uint32_t blit_cmd; - uint32_t buffer[10]; - uint32_t *buf; - uint32_t direction; - - buf = buffer; - - direction = - psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y); - - if (direction == PSB_2D_COPYORDER_BR2TL || - direction == PSB_2D_COPYORDER_TR2BL) { - src_x += size_x - 1; - dst_x += size_x - 1; - } - if (direction == PSB_2D_COPYORDER_BR2TL || - direction == PSB_2D_COPYORDER_BL2TR) { - src_y += size_y - 1; - dst_y += size_y - 1; - } - - blit_cmd = - PSB_2D_BLIT_BH | - PSB_2D_ROT_NONE | - PSB_2D_DSTCK_DISABLE | - PSB_2D_SRCCK_DISABLE | - PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction; - - *buf++ = PSB_2D_FENCE_BH; - *buf++ = - PSB_2D_DST_SURF_BH | dst_format | (dst_stride << - PSB_2D_DST_STRIDE_SHIFT); - *buf++ = dst_offset; - *buf++ = - PSB_2D_SRC_SURF_BH | src_format | (src_stride << - PSB_2D_SRC_STRIDE_SHIFT); - *buf++ = src_offset; - *buf++ = - PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) | - (src_y << PSB_2D_SRCOFF_YSTART_SHIFT); - *buf++ = blit_cmd; - *buf++ = - (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y << - PSB_2D_DST_YSTART_SHIFT); - *buf++ = - (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y << - PSB_2D_DST_YSIZE_SHIFT); - *buf++ = PSB_2D_FLUSH_BH; - - return psbfb_2d_submit(dev_priv, buffer, buf - buffer); -} - -/** - * psbfb_copyarea_accel - copyarea acceleration for /dev/fb - * @info: our framebuffer - * @a: copyarea parameters from the framebuffer core - * - * Perform a 2D copy via the accelerator - */ -static void psbfb_copyarea_accel(struct fb_info *info, - const struct fb_copyarea *a) -{ - struct psb_fbdev *fbdev = info->par; - struct psb_framebuffer *psbfb = &fbdev->pfb; - struct drm_device *dev = psbfb->base.dev; - struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb; - struct drm_psb_private *dev_priv = dev->dev_private; - uint32_t offset; - uint32_t stride; - uint32_t src_format; - uint32_t dst_format; - - if (!fb) - return; - - offset = psbfb->gtt->offset; - stride = fb->pitches[0]; - - switch (fb->depth) { - case 8: - src_format = PSB_2D_SRC_332RGB; - dst_format = PSB_2D_DST_332RGB; - break; - case 15: - src_format = PSB_2D_SRC_555RGB; - dst_format = PSB_2D_DST_555RGB; - break; - case 16: - src_format = PSB_2D_SRC_565RGB; - dst_format = PSB_2D_DST_565RGB; - break; - case 24: - case 32: - /* this is wrong but since we don't do blending its okay */ - src_format = PSB_2D_SRC_8888ARGB; - dst_format = PSB_2D_DST_8888ARGB; - break; - default: - /* software fallback */ - cfb_copyarea(info, a); - return; - } - - if (!gma_power_begin(dev, false)) { - cfb_copyarea(info, a); - return; - } - psb_accel_2d_copy(dev_priv, - offset, stride, src_format, - offset, stride, dst_format, - a->sx, a->sy, a->dx, a->dy, a->width, a->height); - gma_power_end(dev); -} - -/** - * psbfb_copyarea - 2D copy interface - * @info: our framebuffer - * @region: region to copy - * - * Copy an area of the framebuffer console either by the accelerator - * or directly using the cfb helpers according to the request - */ -void psbfb_copyarea(struct fb_info *info, - const struct fb_copyarea *region) -{ - if (unlikely(info->state != FBINFO_STATE_RUNNING)) - return; - - /* Avoid the 8 pixel erratum */ - if (region->width == 8 || region->height == 8 || - (info->flags & FBINFO_HWACCEL_DISABLED)) - return cfb_copyarea(info, region); - - psbfb_copyarea_accel(info, region); -} - -/** - * psbfb_sync - synchronize 2D - * @info: our framebuffer - * - * Wait for the 2D engine to quiesce so that we can do CPU - * access to the framebuffer again - */ -int psbfb_sync(struct fb_info *info) -{ - struct psb_fbdev *fbdev = info->par; - struct psb_framebuffer *psbfb = &fbdev->pfb; - struct drm_device *dev = psbfb->base.dev; - struct drm_psb_private *dev_priv = dev->dev_private; - unsigned long _end = jiffies + DRM_HZ; - int busy = 0; - unsigned long flags; - - spin_lock_irqsave(&dev_priv->lock_2d, flags); - /* - * First idle the 2D engine. - */ - - if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) && - ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0)) - goto out; - - do { - busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY); - cpu_relax(); - } while (busy && !time_after_eq(jiffies, _end)); - - if (busy) - busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY); - if (busy) - goto out; - - do { - busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & - _PSB_C2B_STATUS_BUSY) != 0); - cpu_relax(); - } while (busy && !time_after_eq(jiffies, _end)); - if (busy) - busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & - _PSB_C2B_STATUS_BUSY) != 0); - -out: - spin_unlock_irqrestore(&dev_priv->lock_2d, flags); - return (busy) ? -EBUSY : 0; -} diff --git a/drivers/gpu/drm/gma500/backlight.c b/drivers/gpu/drm/gma500/backlight.c deleted file mode 100644 index 2079395..0000000 --- a/drivers/gpu/drm/gma500/backlight.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * GMA500 Backlight Interface - * - * Copyright (c) 2009-2011, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: Eric Knopp - * - */ - -#include "psb_drv.h" -#include "psb_intel_reg.h" -#include "psb_intel_drv.h" -#include "intel_bios.h" -#include "power.h" - -int gma_backlight_init(struct drm_device *dev) -{ -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - struct drm_psb_private *dev_priv = dev->dev_private; - return dev_priv->ops->backlight_init(dev); -#else - return 0; -#endif -} - -void gma_backlight_exit(struct drm_device *dev) -{ -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - struct drm_psb_private *dev_priv = dev->dev_private; - if (dev_priv->backlight_device) { - dev_priv->backlight_device->props.brightness = 0; - backlight_update_status(dev_priv->backlight_device); - backlight_device_unregister(dev_priv->backlight_device); - } -#endif -} diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c deleted file mode 100644 index a54cc73..0000000 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ /dev/null @@ -1,484 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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 "gma_drm.h" -#include "psb_drv.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include "intel_bios.h" -#include "cdv_device.h" - -#define VGA_SR_INDEX 0x3c4 -#define VGA_SR_DATA 0x3c5 - -static void cdv_disable_vga(struct drm_device *dev) -{ - u8 sr1; - u32 vga_reg; - - vga_reg = VGACNTRL; - - outb(1, VGA_SR_INDEX); - sr1 = inb(VGA_SR_DATA); - outb(sr1 | 1<<5, VGA_SR_DATA); - udelay(300); - - REG_WRITE(vga_reg, VGA_DISP_DISABLE); - REG_READ(vga_reg); -} - -static int cdv_output_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - cdv_disable_vga(dev); - - cdv_intel_crt_init(dev, &dev_priv->mode_dev); - cdv_intel_lvds_init(dev, &dev_priv->mode_dev); - - /* These bits indicate HDMI not SDVO on CDV, but we don't yet support - the HDMI interface */ - if (REG_READ(SDVOB) & SDVO_DETECTED) - cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB); - if (REG_READ(SDVOC) & SDVO_DETECTED) - cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOC); - return 0; -} - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - -/* - * Poulsbo Backlight Interfaces - */ - -#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ -#define BLC_PWM_FREQ_CALC_CONSTANT 32 -#define MHz 1000000 - -#define PSB_BLC_PWM_PRECISION_FACTOR 10 -#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE -#define PSB_BLC_MIN_PWM_REG_FREQ 0x2 - -#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) -#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) - -static int cdv_brightness; -static struct backlight_device *cdv_backlight_device; - -static int cdv_get_brightness(struct backlight_device *bd) -{ - /* return locally cached var instead of HW read (due to DPST etc.) */ - /* FIXME: ideally return actual value in case firmware fiddled with - it */ - return cdv_brightness; -} - - -static int cdv_backlight_setup(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - unsigned long core_clock; - /* u32 bl_max_freq; */ - /* unsigned long value; */ - u16 bl_max_freq; - uint32_t value; - uint32_t blc_pwm_precision_factor; - - /* get bl_max_freq and pol from dev_priv*/ - if (!dev_priv->lvds_bl) { - dev_err(dev->dev, "Has no valid LVDS backlight info\n"); - return -ENOENT; - } - bl_max_freq = dev_priv->lvds_bl->freq; - blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; - - core_clock = dev_priv->core_freq; - - value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; - value *= blc_pwm_precision_factor; - value /= bl_max_freq; - value /= blc_pwm_precision_factor; - - if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || - value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) - return -ERANGE; - else { - /* FIXME */ - } - return 0; -} - -static int cdv_set_brightness(struct backlight_device *bd) -{ - int level = bd->props.brightness; - - /* Percentage 1-100% being valid */ - if (level < 1) - level = 1; - - /*cdv_intel_lvds_set_brightness(dev, level); FIXME */ - cdv_brightness = level; - return 0; -} - -static const struct backlight_ops cdv_ops = { - .get_brightness = cdv_get_brightness, - .update_status = cdv_set_brightness, -}; - -static int cdv_backlight_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - int ret; - struct backlight_properties props; - - memset(&props, 0, sizeof(struct backlight_properties)); - props.max_brightness = 100; - props.type = BACKLIGHT_PLATFORM; - - cdv_backlight_device = backlight_device_register("psb-bl", - NULL, (void *)dev, &cdv_ops, &props); - if (IS_ERR(cdv_backlight_device)) - return PTR_ERR(cdv_backlight_device); - - ret = cdv_backlight_setup(dev); - if (ret < 0) { - backlight_device_unregister(cdv_backlight_device); - cdv_backlight_device = NULL; - return ret; - } - cdv_backlight_device->props.brightness = 100; - cdv_backlight_device->props.max_brightness = 100; - backlight_update_status(cdv_backlight_device); - dev_priv->backlight_device = cdv_backlight_device; - return 0; -} - -#endif - -/* - * Provide the Cedarview specific chip logic and low level methods - * for power management - * - * FIXME: we need to implement the apm/ospm base management bits - * for this and the MID devices. - */ - -static inline u32 CDV_MSG_READ32(uint port, uint offset) -{ - int mcr = (0x10<<24) | (port << 16) | (offset << 8); - uint32_t ret_val = 0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); - pci_write_config_dword(pci_root, 0xD0, mcr); - pci_read_config_dword(pci_root, 0xD4, &ret_val); - pci_dev_put(pci_root); - return ret_val; -} - -static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value) -{ - int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); - pci_write_config_dword(pci_root, 0xD4, value); - pci_write_config_dword(pci_root, 0xD0, mcr); - pci_dev_put(pci_root); -} - -#define PSB_PM_SSC 0x20 -#define PSB_PM_SSS 0x30 -#define PSB_PWRGT_GFX_ON 0x02 -#define PSB_PWRGT_GFX_OFF 0x01 -#define PSB_PWRGT_GFX_D0 0x00 -#define PSB_PWRGT_GFX_D3 0x03 - -static void cdv_init_pm(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 pwr_cnt; - int i; - - dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, - PSB_APMBA) & 0xFFFF; - dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, - PSB_OSPMBA) & 0xFFFF; - - /* Power status */ - pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD); - - /* Enable the GPU */ - pwr_cnt &= ~PSB_PWRGT_GFX_MASK; - pwr_cnt |= PSB_PWRGT_GFX_ON; - outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD); - - /* Wait for the GPU power */ - for (i = 0; i < 5; i++) { - u32 pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS); - if ((pwr_sts & PSB_PWRGT_GFX_MASK) == 0) - return; - udelay(10); - } - dev_err(dev->dev, "GPU: power management timed out.\n"); -} - -/** - * cdv_save_display_registers - save registers lost on suspend - * @dev: our DRM device - * - * Save the state we need in order to be able to restore the interface - * upon resume from suspend - */ -static int cdv_save_display_registers(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_save_area *regs = &dev_priv->regs; - struct drm_connector *connector; - - dev_info(dev->dev, "Saving GPU registers.\n"); - - pci_read_config_byte(dev->pdev, 0xF4, ®s->cdv.saveLBB); - - regs->cdv.saveDSPCLK_GATE_D = REG_READ(DSPCLK_GATE_D); - regs->cdv.saveRAMCLK_GATE_D = REG_READ(RAMCLK_GATE_D); - - regs->cdv.saveDSPARB = REG_READ(DSPARB); - regs->cdv.saveDSPFW[0] = REG_READ(DSPFW1); - regs->cdv.saveDSPFW[1] = REG_READ(DSPFW2); - regs->cdv.saveDSPFW[2] = REG_READ(DSPFW3); - regs->cdv.saveDSPFW[3] = REG_READ(DSPFW4); - regs->cdv.saveDSPFW[4] = REG_READ(DSPFW5); - regs->cdv.saveDSPFW[5] = REG_READ(DSPFW6); - - regs->cdv.saveADPA = REG_READ(ADPA); - - regs->cdv.savePP_CONTROL = REG_READ(PP_CONTROL); - regs->cdv.savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS); - regs->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); - regs->saveBLC_PWM_CTL2 = REG_READ(BLC_PWM_CTL2); - regs->cdv.saveLVDS = REG_READ(LVDS); - - regs->cdv.savePFIT_CONTROL = REG_READ(PFIT_CONTROL); - - regs->cdv.savePP_ON_DELAYS = REG_READ(PP_ON_DELAYS); - regs->cdv.savePP_OFF_DELAYS = REG_READ(PP_OFF_DELAYS); - regs->cdv.savePP_CYCLE = REG_READ(PP_CYCLE); - - regs->cdv.saveVGACNTRL = REG_READ(VGACNTRL); - - regs->cdv.saveIER = REG_READ(PSB_INT_ENABLE_R); - regs->cdv.saveIMR = REG_READ(PSB_INT_MASK_R); - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) - connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF); - - return 0; -} - -/** - * cdv_restore_display_registers - restore lost register state - * @dev: our DRM device - * - * Restore register state that was lost during suspend and resume. - * - * FIXME: review - */ -static int cdv_restore_display_registers(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_save_area *regs = &dev_priv->regs; - struct drm_connector *connector; - u32 temp; - - pci_write_config_byte(dev->pdev, 0xF4, regs->cdv.saveLBB); - - REG_WRITE(DSPCLK_GATE_D, regs->cdv.saveDSPCLK_GATE_D); - REG_WRITE(RAMCLK_GATE_D, regs->cdv.saveRAMCLK_GATE_D); - - /* BIOS does below anyway */ - REG_WRITE(DPIO_CFG, 0); - REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N); - - temp = REG_READ(DPLL_A); - if ((temp & DPLL_SYNCLOCK_ENABLE) == 0) { - REG_WRITE(DPLL_A, temp | DPLL_SYNCLOCK_ENABLE); - REG_READ(DPLL_A); - } - - temp = REG_READ(DPLL_B); - if ((temp & DPLL_SYNCLOCK_ENABLE) == 0) { - REG_WRITE(DPLL_B, temp | DPLL_SYNCLOCK_ENABLE); - REG_READ(DPLL_B); - } - - udelay(500); - - REG_WRITE(DSPFW1, regs->cdv.saveDSPFW[0]); - REG_WRITE(DSPFW2, regs->cdv.saveDSPFW[1]); - REG_WRITE(DSPFW3, regs->cdv.saveDSPFW[2]); - REG_WRITE(DSPFW4, regs->cdv.saveDSPFW[3]); - REG_WRITE(DSPFW5, regs->cdv.saveDSPFW[4]); - REG_WRITE(DSPFW6, regs->cdv.saveDSPFW[5]); - - REG_WRITE(DSPARB, regs->cdv.saveDSPARB); - REG_WRITE(ADPA, regs->cdv.saveADPA); - - REG_WRITE(BLC_PWM_CTL2, regs->saveBLC_PWM_CTL2); - REG_WRITE(LVDS, regs->cdv.saveLVDS); - REG_WRITE(PFIT_CONTROL, regs->cdv.savePFIT_CONTROL); - REG_WRITE(PFIT_PGM_RATIOS, regs->cdv.savePFIT_PGM_RATIOS); - REG_WRITE(BLC_PWM_CTL, regs->saveBLC_PWM_CTL); - REG_WRITE(PP_ON_DELAYS, regs->cdv.savePP_ON_DELAYS); - REG_WRITE(PP_OFF_DELAYS, regs->cdv.savePP_OFF_DELAYS); - REG_WRITE(PP_CYCLE, regs->cdv.savePP_CYCLE); - REG_WRITE(PP_CONTROL, regs->cdv.savePP_CONTROL); - - REG_WRITE(VGACNTRL, regs->cdv.saveVGACNTRL); - - REG_WRITE(PSB_INT_ENABLE_R, regs->cdv.saveIER); - REG_WRITE(PSB_INT_MASK_R, regs->cdv.saveIMR); - - /* Fix arbitration bug */ - CDV_MSG_WRITE32(3, 0x30, 0x08027108); - - drm_mode_config_reset(dev); - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) - connector->funcs->dpms(connector, DRM_MODE_DPMS_ON); - - /* Resume the modeset for every activated CRTC */ - drm_helper_resume_force_mode(dev); - return 0; -} - -static int cdv_power_down(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 pwr_cnt, pwr_mask, pwr_sts; - int tries = 5; - - pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD); - pwr_cnt &= ~PSB_PWRGT_GFX_MASK; - pwr_cnt |= PSB_PWRGT_GFX_OFF; - pwr_mask = PSB_PWRGT_GFX_MASK; - - outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD); - - while (tries--) { - pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS); - if ((pwr_sts & pwr_mask) == PSB_PWRGT_GFX_D3) - return 0; - udelay(10); - } - return 0; -} - -static int cdv_power_up(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 pwr_cnt, pwr_mask, pwr_sts; - int tries = 5; - - pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD); - pwr_cnt &= ~PSB_PWRGT_GFX_MASK; - pwr_cnt |= PSB_PWRGT_GFX_ON; - pwr_mask = PSB_PWRGT_GFX_MASK; - - outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD); - - while (tries--) { - pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS); - if ((pwr_sts & pwr_mask) == PSB_PWRGT_GFX_D0) - return 0; - udelay(10); - } - return 0; -} - -/* FIXME ? - shared with Poulsbo */ -static void cdv_get_core_freq(struct drm_device *dev) -{ - uint32_t clock; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); - struct drm_psb_private *dev_priv = dev->dev_private; - - pci_write_config_dword(pci_root, 0xD0, 0xD0050300); - pci_read_config_dword(pci_root, 0xD4, &clock); - pci_dev_put(pci_root); - - switch (clock & 0x07) { - case 0: - dev_priv->core_freq = 100; - break; - case 1: - dev_priv->core_freq = 133; - break; - case 2: - dev_priv->core_freq = 150; - break; - case 3: - dev_priv->core_freq = 178; - break; - case 4: - dev_priv->core_freq = 200; - break; - case 5: - case 6: - case 7: - dev_priv->core_freq = 266; - default: - dev_priv->core_freq = 0; - } -} - -static int cdv_chip_setup(struct drm_device *dev) -{ - cdv_get_core_freq(dev); - gma_intel_opregion_init(dev); - psb_intel_init_bios(dev); - REG_WRITE(PORT_HOTPLUG_EN, 0); - REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT)); - return 0; -} - -/* CDV is much like Poulsbo but has MID like SGX offsets and PM */ - -const struct psb_ops cdv_chip_ops = { - .name = "GMA3600/3650", - .accel_2d = 0, - .pipes = 2, - .crtcs = 2, - .sgx_offset = MRST_SGX_OFFSET, - .chip_setup = cdv_chip_setup, - - .crtc_helper = &cdv_intel_helper_funcs, - .crtc_funcs = &cdv_intel_crtc_funcs, - - .output_init = cdv_output_init, - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - .backlight_init = cdv_backlight_init, -#endif - - .init_pm = cdv_init_pm, - .save_regs = cdv_save_display_registers, - .restore_regs = cdv_restore_display_registers, - .power_down = cdv_power_down, - .power_up = cdv_power_up, -}; diff --git a/drivers/gpu/drm/gma500/cdv_device.h b/drivers/gpu/drm/gma500/cdv_device.h deleted file mode 100644 index 9561e17..0000000 --- a/drivers/gpu/drm/gma500/cdv_device.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright © 2011 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - */ - -extern const struct drm_crtc_helper_funcs cdv_intel_helper_funcs; -extern const struct drm_crtc_funcs cdv_intel_crtc_funcs; -extern void cdv_intel_crt_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev); -extern void cdv_intel_lvds_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev); -extern void cdv_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, - int reg); -extern struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev, - struct drm_crtc *crtc); - -static inline void cdv_intel_wait_for_vblank(struct drm_device *dev) -{ - /* Wait for 20ms, i.e. one cycle at 50hz. */ - /* FIXME: msleep ?? */ - mdelay(20); -} - - diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c deleted file mode 100644 index a71a6cd..0000000 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright © 2006-2007 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Eric Anholt - */ - -#include -#include - -#include "intel_bios.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "power.h" -#include "cdv_device.h" -#include - - -static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode) -{ - struct drm_device *dev = encoder->dev; - u32 temp, reg; - reg = ADPA; - - temp = REG_READ(reg); - temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); - temp &= ~ADPA_DAC_ENABLE; - - switch (mode) { - case DRM_MODE_DPMS_ON: - temp |= ADPA_DAC_ENABLE; - break; - case DRM_MODE_DPMS_STANDBY: - temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE; - break; - case DRM_MODE_DPMS_SUSPEND: - temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE; - break; - case DRM_MODE_DPMS_OFF: - temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE; - break; - } - - REG_WRITE(reg, temp); -} - -static int cdv_intel_crt_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct drm_psb_private *dev_priv = connector->dev->dev_private; - int max_clock = 0; - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - - /* The lowest clock for CDV is 20000KHz */ - if (mode->clock < 20000) - return MODE_CLOCK_LOW; - - /* The max clock for CDV is 355 instead of 400 */ - max_clock = 355000; - if (mode->clock > max_clock) - return MODE_CLOCK_HIGH; - - if (mode->hdisplay > 1680 || mode->vdisplay > 1050) - return MODE_PANEL; - - /* We assume worst case scenario of 32 bpp here, since we don't know */ - if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) > - dev_priv->vram_stolen_size) - return MODE_MEM; - - return MODE_OK; -} - -static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static void cdv_intel_crt_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - - struct drm_device *dev = encoder->dev; - struct drm_crtc *crtc = encoder->crtc; - struct psb_intel_crtc *psb_intel_crtc = - to_psb_intel_crtc(crtc); - int dpll_md_reg; - u32 adpa, dpll_md; - u32 adpa_reg; - - if (psb_intel_crtc->pipe == 0) - dpll_md_reg = DPLL_A_MD; - else - dpll_md_reg = DPLL_B_MD; - - adpa_reg = ADPA; - - /* - * Disable separate mode multiplier used when cloning SDVO to CRT - * XXX this needs to be adjusted when we really are cloning - */ - { - dpll_md = REG_READ(dpll_md_reg); - REG_WRITE(dpll_md_reg, - dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); - } - - adpa = 0; - if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) - adpa |= ADPA_HSYNC_ACTIVE_HIGH; - if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) - adpa |= ADPA_VSYNC_ACTIVE_HIGH; - - if (psb_intel_crtc->pipe == 0) - adpa |= ADPA_PIPE_A_SELECT; - else - adpa |= ADPA_PIPE_B_SELECT; - - REG_WRITE(adpa_reg, adpa); -} - - -/** - * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. - * - * \return true if CRT is connected. - * \return false if CRT is disconnected. - */ -static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector, - bool force) -{ - struct drm_device *dev = connector->dev; - u32 hotplug_en; - int i, tries = 0, ret = false; - u32 adpa_orig; - - /* disable the DAC when doing the hotplug detection */ - - adpa_orig = REG_READ(ADPA); - - REG_WRITE(ADPA, adpa_orig & ~(ADPA_DAC_ENABLE)); - - /* - * On a CDV thep, CRT detect sequence need to be done twice - * to get a reliable result. - */ - tries = 2; - - hotplug_en = REG_READ(PORT_HOTPLUG_EN); - hotplug_en &= ~(CRT_HOTPLUG_DETECT_MASK); - hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; - - hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; - hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; - - for (i = 0; i < tries ; i++) { - unsigned long timeout; - /* turn on the FORCE_DETECT */ - REG_WRITE(PORT_HOTPLUG_EN, hotplug_en); - timeout = jiffies + msecs_to_jiffies(1000); - /* wait for FORCE_DETECT to go off */ - do { - if (!(REG_READ(PORT_HOTPLUG_EN) & - CRT_HOTPLUG_FORCE_DETECT)) - break; - msleep(1); - } while (time_after(timeout, jiffies)); - } - - if ((REG_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) != - CRT_HOTPLUG_MONITOR_NONE) - ret = true; - - /* Restore the saved ADPA */ - REG_WRITE(ADPA, adpa_orig); - return ret; -} - -static enum drm_connector_status cdv_intel_crt_detect( - struct drm_connector *connector, bool force) -{ - if (cdv_intel_crt_detect_hotplug(connector, force)) - return connector_status_connected; - else - return connector_status_disconnected; -} - -static void cdv_intel_crt_destroy(struct drm_connector *connector) -{ - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - - psb_intel_i2c_destroy(psb_intel_encoder->ddc_bus); - drm_sysfs_connector_remove(connector); - drm_connector_cleanup(connector); - kfree(connector); -} - -static int cdv_intel_crt_get_modes(struct drm_connector *connector) -{ - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - return psb_intel_ddc_get_modes(connector, &psb_intel_encoder->ddc_bus->adapter); -} - -static int cdv_intel_crt_set_property(struct drm_connector *connector, - struct drm_property *property, - uint64_t value) -{ - return 0; -} - -/* - * Routines for controlling stuff on the analog port - */ - -static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = { - .dpms = cdv_intel_crt_dpms, - .mode_fixup = cdv_intel_crt_mode_fixup, - .prepare = psb_intel_encoder_prepare, - .commit = psb_intel_encoder_commit, - .mode_set = cdv_intel_crt_mode_set, -}; - -static const struct drm_connector_funcs cdv_intel_crt_connector_funcs = { - .dpms = drm_helper_connector_dpms, - .detect = cdv_intel_crt_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = cdv_intel_crt_destroy, - .set_property = cdv_intel_crt_set_property, -}; - -static const struct drm_connector_helper_funcs - cdv_intel_crt_connector_helper_funcs = { - .mode_valid = cdv_intel_crt_mode_valid, - .get_modes = cdv_intel_crt_get_modes, - .best_encoder = psb_intel_best_encoder, -}; - -static void cdv_intel_crt_enc_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); -} - -static const struct drm_encoder_funcs cdv_intel_crt_enc_funcs = { - .destroy = cdv_intel_crt_enc_destroy, -}; - -void cdv_intel_crt_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev) -{ - - struct psb_intel_connector *psb_intel_connector; - struct psb_intel_encoder *psb_intel_encoder; - struct drm_connector *connector; - struct drm_encoder *encoder; - - u32 i2c_reg; - - psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); - if (!psb_intel_encoder) - return; - - psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL); - if (!psb_intel_connector) - goto failed_connector; - - connector = &psb_intel_connector->base; - drm_connector_init(dev, connector, - &cdv_intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); - - encoder = &psb_intel_encoder->base; - drm_encoder_init(dev, encoder, - &cdv_intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC); - - psb_intel_connector_attach_encoder(psb_intel_connector, - psb_intel_encoder); - - /* Set up the DDC bus. */ - i2c_reg = GPIOA; - /* Remove the following code for CDV */ - /* - if (dev_priv->crt_ddc_bus != 0) - i2c_reg = dev_priv->crt_ddc_bus; - }*/ - psb_intel_encoder->ddc_bus = psb_intel_i2c_create(dev, - i2c_reg, "CRTDDC_A"); - if (!psb_intel_encoder->ddc_bus) { - dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " - "failed.\n"); - goto failed_ddc; - } - - psb_intel_encoder->type = INTEL_OUTPUT_ANALOG; - /* - psb_intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT); - psb_intel_output->crtc_mask = (1 << 0) | (1 << 1); - */ - connector->interlace_allowed = 0; - connector->doublescan_allowed = 0; - - drm_encoder_helper_add(encoder, &cdv_intel_crt_helper_funcs); - drm_connector_helper_add(connector, - &cdv_intel_crt_connector_helper_funcs); - - drm_sysfs_connector_add(connector); - - return; -failed_ddc: - drm_encoder_cleanup(&psb_intel_encoder->base); - drm_connector_cleanup(&psb_intel_connector->base); - kfree(psb_intel_connector); -failed_connector: - kfree(psb_intel_encoder); - return; -} diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c deleted file mode 100644 index be84559..0000000 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ /dev/null @@ -1,1459 +0,0 @@ -/* - * Copyright © 2006-2011 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: - * Eric Anholt - */ - -#include -#include - -#include -#include "framebuffer.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "psb_intel_display.h" -#include "power.h" -#include "cdv_device.h" - - -struct cdv_intel_range_t { - int min, max; -}; - -struct cdv_intel_p2_t { - int dot_limit; - int p2_slow, p2_fast; -}; - -struct cdv_intel_clock_t { - /* given values */ - int n; - int m1, m2; - int p1, p2; - /* derived values */ - int dot; - int vco; - int m; - int p; -}; - -#define INTEL_P2_NUM 2 - -struct cdv_intel_limit_t { - struct cdv_intel_range_t dot, vco, n, m, m1, m2, p, p1; - struct cdv_intel_p2_t p2; -}; - -#define CDV_LIMIT_SINGLE_LVDS_96 0 -#define CDV_LIMIT_SINGLE_LVDS_100 1 -#define CDV_LIMIT_DAC_HDMI_27 2 -#define CDV_LIMIT_DAC_HDMI_96 3 - -static const struct cdv_intel_limit_t cdv_intel_limits[] = { - { /* CDV_SIGNLE_LVDS_96MHz */ - .dot = {.min = 20000, .max = 115500}, - .vco = {.min = 1800000, .max = 3600000}, - .n = {.min = 2, .max = 6}, - .m = {.min = 60, .max = 160}, - .m1 = {.min = 0, .max = 0}, - .m2 = {.min = 58, .max = 158}, - .p = {.min = 28, .max = 140}, - .p1 = {.min = 2, .max = 10}, - .p2 = {.dot_limit = 200000, - .p2_slow = 14, .p2_fast = 14}, - }, - { /* CDV_SINGLE_LVDS_100MHz */ - .dot = {.min = 20000, .max = 115500}, - .vco = {.min = 1800000, .max = 3600000}, - .n = {.min = 2, .max = 6}, - .m = {.min = 60, .max = 160}, - .m1 = {.min = 0, .max = 0}, - .m2 = {.min = 58, .max = 158}, - .p = {.min = 28, .max = 140}, - .p1 = {.min = 2, .max = 10}, - /* The single-channel range is 25-112Mhz, and dual-channel - * is 80-224Mhz. Prefer single channel as much as possible. - */ - .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14}, - }, - { /* CDV_DAC_HDMI_27MHz */ - .dot = {.min = 20000, .max = 400000}, - .vco = {.min = 1809000, .max = 3564000}, - .n = {.min = 1, .max = 1}, - .m = {.min = 67, .max = 132}, - .m1 = {.min = 0, .max = 0}, - .m2 = {.min = 65, .max = 130}, - .p = {.min = 5, .max = 90}, - .p1 = {.min = 1, .max = 9}, - .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5}, - }, - { /* CDV_DAC_HDMI_96MHz */ - .dot = {.min = 20000, .max = 400000}, - .vco = {.min = 1800000, .max = 3600000}, - .n = {.min = 2, .max = 6}, - .m = {.min = 60, .max = 160}, - .m1 = {.min = 0, .max = 0}, - .m2 = {.min = 58, .max = 158}, - .p = {.min = 5, .max = 100}, - .p1 = {.min = 1, .max = 10}, - .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5}, - }, -}; - -#define _wait_for(COND, MS, W) ({ \ - unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ - int ret__ = 0; \ - while (!(COND)) { \ - if (time_after(jiffies, timeout__)) { \ - ret__ = -ETIMEDOUT; \ - break; \ - } \ - if (W && !in_dbg_master()) \ - msleep(W); \ - } \ - ret__; \ -}) - -#define wait_for(COND, MS) _wait_for(COND, MS, 1) - - -static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val) -{ - int ret; - - ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); - if (ret) { - DRM_ERROR("timeout waiting for SB to idle before read\n"); - return ret; - } - - REG_WRITE(SB_ADDR, reg); - REG_WRITE(SB_PCKT, - SET_FIELD(SB_OPCODE_READ, SB_OPCODE) | - SET_FIELD(SB_DEST_DPLL, SB_DEST) | - SET_FIELD(0xf, SB_BYTE_ENABLE)); - - ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); - if (ret) { - DRM_ERROR("timeout waiting for SB to idle after read\n"); - return ret; - } - - *val = REG_READ(SB_DATA); - - return 0; -} - -static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val) -{ - int ret; - static bool dpio_debug = true; - u32 temp; - - if (dpio_debug) { - if (cdv_sb_read(dev, reg, &temp) == 0) - DRM_DEBUG_KMS("0x%08x: 0x%08x (before)\n", reg, temp); - DRM_DEBUG_KMS("0x%08x: 0x%08x\n", reg, val); - } - - ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); - if (ret) { - DRM_ERROR("timeout waiting for SB to idle before write\n"); - return ret; - } - - REG_WRITE(SB_ADDR, reg); - REG_WRITE(SB_DATA, val); - REG_WRITE(SB_PCKT, - SET_FIELD(SB_OPCODE_WRITE, SB_OPCODE) | - SET_FIELD(SB_DEST_DPLL, SB_DEST) | - SET_FIELD(0xf, SB_BYTE_ENABLE)); - - ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); - if (ret) { - DRM_ERROR("timeout waiting for SB to idle after write\n"); - return ret; - } - - if (dpio_debug) { - if (cdv_sb_read(dev, reg, &temp) == 0) - DRM_DEBUG_KMS("0x%08x: 0x%08x (after)\n", reg, temp); - } - - return 0; -} - -/* Reset the DPIO configuration register. The BIOS does this at every - * mode set. - */ -static void cdv_sb_reset(struct drm_device *dev) -{ - - REG_WRITE(DPIO_CFG, 0); - REG_READ(DPIO_CFG); - REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N); -} - -/* Unlike most Intel display engines, on Cedarview the DPLL registers - * are behind this sideband bus. They must be programmed while the - * DPLL reference clock is on in the DPLL control register, but before - * the DPLL is enabled in the DPLL control register. - */ -static int -cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, - struct cdv_intel_clock_t *clock) -{ - struct psb_intel_crtc *psb_crtc = - to_psb_intel_crtc(crtc); - int pipe = psb_crtc->pipe; - u32 m, n_vco, p; - int ret = 0; - int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; - u32 ref_value; - - cdv_sb_reset(dev); - - if ((REG_READ(dpll_reg) & DPLL_SYNCLOCK_ENABLE) == 0) { - DRM_ERROR("Attempting to set DPLL with refclk disabled\n"); - return -EBUSY; - } - - /* Follow the BIOS and write the REF/SFR Register. Hardcoded value */ - ref_value = 0x68A701; - - cdv_sb_write(dev, SB_REF_SFR(pipe), ref_value); - - /* We don't know what the other fields of these regs are, so - * leave them in place. - */ - ret = cdv_sb_read(dev, SB_M(pipe), &m); - if (ret) - return ret; - m &= ~SB_M_DIVIDER_MASK; - m |= ((clock->m2) << SB_M_DIVIDER_SHIFT); - ret = cdv_sb_write(dev, SB_M(pipe), m); - if (ret) - return ret; - - ret = cdv_sb_read(dev, SB_N_VCO(pipe), &n_vco); - if (ret) - return ret; - - /* Follow the BIOS to program the N_DIVIDER REG */ - n_vco &= 0xFFFF; - n_vco |= 0x107; - n_vco &= ~(SB_N_VCO_SEL_MASK | - SB_N_DIVIDER_MASK | - SB_N_CB_TUNE_MASK); - - n_vco |= ((clock->n) << SB_N_DIVIDER_SHIFT); - - if (clock->vco < 2250000) { - n_vco |= (2 << SB_N_CB_TUNE_SHIFT); - n_vco |= (0 << SB_N_VCO_SEL_SHIFT); - } else if (clock->vco < 2750000) { - n_vco |= (1 << SB_N_CB_TUNE_SHIFT); - n_vco |= (1 << SB_N_VCO_SEL_SHIFT); - } else if (clock->vco < 3300000) { - n_vco |= (0 << SB_N_CB_TUNE_SHIFT); - n_vco |= (2 << SB_N_VCO_SEL_SHIFT); - } else { - n_vco |= (0 << SB_N_CB_TUNE_SHIFT); - n_vco |= (3 << SB_N_VCO_SEL_SHIFT); - } - - ret = cdv_sb_write(dev, SB_N_VCO(pipe), n_vco); - if (ret) - return ret; - - ret = cdv_sb_read(dev, SB_P(pipe), &p); - if (ret) - return ret; - p &= ~(SB_P2_DIVIDER_MASK | SB_P1_DIVIDER_MASK); - p |= SET_FIELD(clock->p1, SB_P1_DIVIDER); - switch (clock->p2) { - case 5: - p |= SET_FIELD(SB_P2_5, SB_P2_DIVIDER); - break; - case 10: - p |= SET_FIELD(SB_P2_10, SB_P2_DIVIDER); - break; - case 14: - p |= SET_FIELD(SB_P2_14, SB_P2_DIVIDER); - break; - case 7: - p |= SET_FIELD(SB_P2_7, SB_P2_DIVIDER); - break; - default: - DRM_ERROR("Bad P2 clock: %d\n", clock->p2); - return -EINVAL; - } - ret = cdv_sb_write(dev, SB_P(pipe), p); - if (ret) - return ret; - - /* always Program the Lane Register for the Pipe A*/ - if (pipe == 0) { - /* Program the Lane0/1 for HDMI B */ - u32 lane_reg, lane_value; - - lane_reg = PSB_LANE0; - cdv_sb_read(dev, lane_reg, &lane_value); - lane_value &= ~(LANE_PLL_MASK); - lane_value |= LANE_PLL_ENABLE; - cdv_sb_write(dev, lane_reg, lane_value); - - lane_reg = PSB_LANE1; - cdv_sb_read(dev, lane_reg, &lane_value); - lane_value &= ~(LANE_PLL_MASK); - lane_value |= LANE_PLL_ENABLE; - cdv_sb_write(dev, lane_reg, lane_value); - - /* Program the Lane2/3 for HDMI C */ - lane_reg = PSB_LANE2; - cdv_sb_read(dev, lane_reg, &lane_value); - lane_value &= ~(LANE_PLL_MASK); - lane_value |= LANE_PLL_ENABLE; - cdv_sb_write(dev, lane_reg, lane_value); - - lane_reg = PSB_LANE3; - cdv_sb_read(dev, lane_reg, &lane_value); - lane_value &= ~(LANE_PLL_MASK); - lane_value |= LANE_PLL_ENABLE; - cdv_sb_write(dev, lane_reg, lane_value); - } - - return 0; -} - -/* - * Returns whether any encoder on the specified pipe is of the specified type - */ -static bool cdv_intel_pipe_has_type(struct drm_crtc *crtc, int type) -{ - struct drm_device *dev = crtc->dev; - struct drm_mode_config *mode_config = &dev->mode_config; - struct drm_connector *l_entry; - - list_for_each_entry(l_entry, &mode_config->connector_list, head) { - if (l_entry->encoder && l_entry->encoder->crtc == crtc) { - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(l_entry); - if (psb_intel_encoder->type == type) - return true; - } - } - return false; -} - -static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc, - int refclk) -{ - const struct cdv_intel_limit_t *limit; - if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - /* - * Now only single-channel LVDS is supported on CDV. If it is - * incorrect, please add the dual-channel LVDS. - */ - if (refclk == 96000) - limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96]; - else - limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100]; - } else { - if (refclk == 27000) - limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27]; - else - limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_96]; - } - return limit; -} - -/* m1 is reserved as 0 in CDV, n is a ring counter */ -static void cdv_intel_clock(struct drm_device *dev, - int refclk, struct cdv_intel_clock_t *clock) -{ - clock->m = clock->m2 + 2; - clock->p = clock->p1 * clock->p2; - clock->vco = (refclk * clock->m) / clock->n; - clock->dot = clock->vco / clock->p; -} - - -#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } -static bool cdv_intel_PLL_is_valid(struct drm_crtc *crtc, - const struct cdv_intel_limit_t *limit, - struct cdv_intel_clock_t *clock) -{ - if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) - INTELPllInvalid("p1 out of range\n"); - if (clock->p < limit->p.min || limit->p.max < clock->p) - INTELPllInvalid("p out of range\n"); - /* unnecessary to check the range of m(m1/M2)/n again */ - if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) - INTELPllInvalid("vco out of range\n"); - /* XXX: We may need to be checking "Dot clock" - * depending on the multiplier, connector, etc., - * rather than just a single range. - */ - if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) - INTELPllInvalid("dot out of range\n"); - - return true; -} - -static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target, - int refclk, - struct cdv_intel_clock_t *best_clock) -{ - struct drm_device *dev = crtc->dev; - struct cdv_intel_clock_t clock; - const struct cdv_intel_limit_t *limit = cdv_intel_limit(crtc, refclk); - int err = target; - - - if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && - (REG_READ(LVDS) & LVDS_PORT_EN) != 0) { - /* - * For LVDS, if the panel is on, just rely on its current - * settings for dual-channel. We haven't figured out how to - * reliably set up different single/dual channel state, if we - * even can. - */ - if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) - clock.p2 = limit->p2.p2_fast; - else - clock.p2 = limit->p2.p2_slow; - } else { - if (target < limit->p2.dot_limit) - clock.p2 = limit->p2.p2_slow; - else - clock.p2 = limit->p2.p2_fast; - } - - memset(best_clock, 0, sizeof(*best_clock)); - clock.m1 = 0; - /* m1 is reserved as 0 in CDV, n is a ring counter. - So skip the m1 loop */ - for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) { - for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; - clock.m2++) { - for (clock.p1 = limit->p1.min; - clock.p1 <= limit->p1.max; - clock.p1++) { - int this_err; - - cdv_intel_clock(dev, refclk, &clock); - - if (!cdv_intel_PLL_is_valid(crtc, - limit, &clock)) - continue; - - this_err = abs(clock.dot - target); - if (this_err < err) { - *best_clock = clock; - err = this_err; - } - } - } - } - - return err != target; -} - -static int cdv_intel_pipe_set_base(struct drm_crtc *crtc, - int x, int y, struct drm_framebuffer *old_fb) -{ - struct drm_device *dev = crtc->dev; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); - int pipe = psb_intel_crtc->pipe; - unsigned long start, offset; - int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); - int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); - int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; - int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; - u32 dspcntr; - int ret = 0; - - if (!gma_power_begin(dev, true)) - return 0; - - /* no fb bound */ - if (!crtc->fb) { - dev_err(dev->dev, "No FB bound\n"); - goto psb_intel_pipe_cleaner; - } - - - /* We are displaying this buffer, make sure it is actually loaded - into the GTT */ - ret = psb_gtt_pin(psbfb->gtt); - if (ret < 0) - goto psb_intel_pipe_set_base_exit; - start = psbfb->gtt->offset; - offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); - - REG_WRITE(dspstride, crtc->fb->pitches[0]); - - dspcntr = REG_READ(dspcntr_reg); - dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - - switch (crtc->fb->bits_per_pixel) { - case 8: - dspcntr |= DISPPLANE_8BPP; - break; - case 16: - if (crtc->fb->depth == 15) - dspcntr |= DISPPLANE_15_16BPP; - else - dspcntr |= DISPPLANE_16BPP; - break; - case 24: - case 32: - dspcntr |= DISPPLANE_32BPP_NO_ALPHA; - break; - default: - dev_err(dev->dev, "Unknown color depth\n"); - ret = -EINVAL; - goto psb_intel_pipe_set_base_exit; - } - REG_WRITE(dspcntr_reg, dspcntr); - - dev_dbg(dev->dev, - "Writing base %08lX %08lX %d %d\n", start, offset, x, y); - - REG_WRITE(dspbase, offset); - REG_READ(dspbase); - REG_WRITE(dspsurf, start); - REG_READ(dspsurf); - -psb_intel_pipe_cleaner: - /* If there was a previous display we can now unpin it */ - if (old_fb) - psb_gtt_unpin(to_psb_fb(old_fb)->gtt); - -psb_intel_pipe_set_base_exit: - gma_power_end(dev); - return ret; -} - -/** - * Sets the power management mode of the pipe and plane. - * - * This code should probably grow support for turning the cursor off and back - * on appropriately at the same time as we're turning the pipe off/on. - */ -static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode) -{ - struct drm_device *dev = crtc->dev; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int pipe = psb_intel_crtc->pipe; - int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; - int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; - int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; - int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; - u32 temp; - - /* XXX: When our outputs are all unaware of DPMS modes other than off - * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. - */ - switch (mode) { - case DRM_MODE_DPMS_ON: - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - /* Enable the DPLL */ - temp = REG_READ(dpll_reg); - if ((temp & DPLL_VCO_ENABLE) == 0) { - REG_WRITE(dpll_reg, temp); - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - } - - /* Jim Bish - switch plan and pipe per scott */ - /* Enable the plane */ - temp = REG_READ(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) == 0) { - REG_WRITE(dspcntr_reg, - temp | DISPLAY_PLANE_ENABLE); - /* Flush the plane changes */ - REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); - } - - udelay(150); - - /* Enable the pipe */ - temp = REG_READ(pipeconf_reg); - if ((temp & PIPEACONF_ENABLE) == 0) - REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); - - psb_intel_crtc_load_lut(crtc); - - /* Give the overlay scaler a chance to enable - * if it's on this pipe */ - /* psb_intel_crtc_dpms_video(crtc, true); TODO */ - break; - case DRM_MODE_DPMS_OFF: - /* Give the overlay scaler a chance to disable - * if it's on this pipe */ - /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ - - /* Disable the VGA plane that we never use */ - REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); - - /* Jim Bish - changed pipe/plane here as well. */ - - /* Wait for vblank for the disable to take effect */ - cdv_intel_wait_for_vblank(dev); - - /* Next, disable display pipes */ - temp = REG_READ(pipeconf_reg); - if ((temp & PIPEACONF_ENABLE) != 0) { - REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); - REG_READ(pipeconf_reg); - } - - /* Wait for vblank for the disable to take effect. */ - cdv_intel_wait_for_vblank(dev); - - udelay(150); - - /* Disable display plane */ - temp = REG_READ(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) != 0) { - REG_WRITE(dspcntr_reg, - temp & ~DISPLAY_PLANE_ENABLE); - /* Flush the plane changes */ - REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); - REG_READ(dspbase_reg); - } - - temp = REG_READ(dpll_reg); - if ((temp & DPLL_VCO_ENABLE) != 0) { - REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); - REG_READ(dpll_reg); - } - - /* Wait for the clocks to turn off. */ - udelay(150); - break; - } - /*Set FIFO Watermarks*/ - REG_WRITE(DSPARB, 0x3F3E); -} - -static void cdv_intel_crtc_prepare(struct drm_crtc *crtc) -{ - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); -} - -static void cdv_intel_crtc_commit(struct drm_crtc *crtc) -{ - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); -} - -static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - - -/** - * Return the pipe currently connected to the panel fitter, - * or -1 if the panel fitter is not present or not in use - */ -static int cdv_intel_panel_fitter_pipe(struct drm_device *dev) -{ - u32 pfit_control; - - pfit_control = REG_READ(PFIT_CONTROL); - - /* See if the panel fitter is in use */ - if ((pfit_control & PFIT_ENABLE) == 0) - return -1; - return (pfit_control >> 29) & 0x3; -} - -static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - int x, int y, - struct drm_framebuffer *old_fb) -{ - struct drm_device *dev = crtc->dev; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int pipe = psb_intel_crtc->pipe; - int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; - int dpll_md_reg = (psb_intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; - int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; - int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; - int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; - int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; - int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; - int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; - int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; - int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; - int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; - int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; - int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; - int refclk; - struct cdv_intel_clock_t clock; - u32 dpll = 0, dspcntr, pipeconf; - bool ok; - bool is_crt = false, is_lvds = false, is_tv = false; - bool is_hdmi = false; - struct drm_mode_config *mode_config = &dev->mode_config; - struct drm_connector *connector; - - list_for_each_entry(connector, &mode_config->connector_list, head) { - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - - if (!connector->encoder - || connector->encoder->crtc != crtc) - continue; - - switch (psb_intel_encoder->type) { - case INTEL_OUTPUT_LVDS: - is_lvds = true; - break; - case INTEL_OUTPUT_TVOUT: - is_tv = true; - break; - case INTEL_OUTPUT_ANALOG: - is_crt = true; - break; - case INTEL_OUTPUT_HDMI: - is_hdmi = true; - break; - } - } - - refclk = 96000; - - /* Hack selection about ref clk for CRT */ - /* Select 27MHz as the reference clk for HDMI */ - if (is_crt || is_hdmi) - refclk = 27000; - - drm_mode_debug_printmodeline(adjusted_mode); - - ok = cdv_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, - &clock); - if (!ok) { - dev_err(dev->dev, "Couldn't find PLL settings for mode!\n"); - return 0; - } - - dpll = DPLL_VGA_MODE_DIS; - if (is_tv) { - /* XXX: just matching BIOS for now */ -/* dpll |= PLL_REF_INPUT_TVCLKINBC; */ - dpll |= 3; - } - dpll |= PLL_REF_INPUT_DREFCLK; - - dpll |= DPLL_SYNCLOCK_ENABLE; - dpll |= DPLL_VGA_MODE_DIS; - if (is_lvds) - dpll |= DPLLB_MODE_LVDS; - else - dpll |= DPLLB_MODE_DAC_SERIAL; - /* dpll |= (2 << 11); */ - - /* setup pipeconf */ - pipeconf = REG_READ(pipeconf_reg); - - /* Set up the display plane register */ - dspcntr = DISPPLANE_GAMMA_ENABLE; - - if (pipe == 0) - dspcntr |= DISPPLANE_SEL_PIPE_A; - else - dspcntr |= DISPPLANE_SEL_PIPE_B; - - dspcntr |= DISPLAY_PLANE_ENABLE; - pipeconf |= PIPEACONF_ENABLE; - - REG_WRITE(dpll_reg, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE); - REG_READ(dpll_reg); - - cdv_dpll_set_clock_cdv(dev, crtc, &clock); - - udelay(150); - - - /* The LVDS pin pair needs to be on before the DPLLs are enabled. - * This is an exception to the general rule that mode_set doesn't turn - * things on. - */ - if (is_lvds) { - u32 lvds = REG_READ(LVDS); - - lvds |= - LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | - LVDS_PIPEB_SELECT; - /* Set the B0-B3 data pairs corresponding to - * whether we're going to - * set the DPLLs for dual-channel mode or not. - */ - if (clock.p2 == 7) - lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; - else - lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); - - /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) - * appropriately here, but we need to look more - * thoroughly into how panels behave in the two modes. - */ - - REG_WRITE(LVDS, lvds); - REG_READ(LVDS); - } - - dpll |= DPLL_VCO_ENABLE; - - /* Disable the panel fitter if it was on our pipe */ - if (cdv_intel_panel_fitter_pipe(dev) == pipe) - REG_WRITE(PFIT_CONTROL, 0); - - DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); - drm_mode_debug_printmodeline(mode); - - REG_WRITE(dpll_reg, - (REG_READ(dpll_reg) & ~DPLL_LOCK) | DPLL_VCO_ENABLE); - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); /* 42 usec w/o calibration, 110 with. rounded up. */ - - if (!(REG_READ(dpll_reg) & DPLL_LOCK)) { - dev_err(dev->dev, "Failed to get DPLL lock\n"); - return -EBUSY; - } - - { - int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; - REG_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); - } - - REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | - ((adjusted_mode->crtc_htotal - 1) << 16)); - REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | - ((adjusted_mode->crtc_hblank_end - 1) << 16)); - REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | - ((adjusted_mode->crtc_hsync_end - 1) << 16)); - REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | - ((adjusted_mode->crtc_vtotal - 1) << 16)); - REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | - ((adjusted_mode->crtc_vblank_end - 1) << 16)); - REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | - ((adjusted_mode->crtc_vsync_end - 1) << 16)); - /* pipesrc and dspsize control the size that is scaled from, - * which should always be the user's requested size. - */ - REG_WRITE(dspsize_reg, - ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); - REG_WRITE(dsppos_reg, 0); - REG_WRITE(pipesrc_reg, - ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); - REG_WRITE(pipeconf_reg, pipeconf); - REG_READ(pipeconf_reg); - - cdv_intel_wait_for_vblank(dev); - - REG_WRITE(dspcntr_reg, dspcntr); - - /* Flush the plane changes */ - { - struct drm_crtc_helper_funcs *crtc_funcs = - crtc->helper_private; - crtc_funcs->mode_set_base(crtc, x, y, old_fb); - } - - cdv_intel_wait_for_vblank(dev); - - return 0; -} - -/** Loads the palette/gamma unit for the CRTC with the prepared values */ -static void cdv_intel_crtc_load_lut(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_psb_private *dev_priv = - (struct drm_psb_private *)dev->dev_private; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int palreg = PALETTE_A; - int i; - - /* The clocks have to be on to load the palette. */ - if (!crtc->enabled) - return; - - switch (psb_intel_crtc->pipe) { - case 0: - break; - case 1: - palreg = PALETTE_B; - break; - case 2: - palreg = PALETTE_C; - break; - default: - dev_err(dev->dev, "Illegal Pipe Number.\n"); - return; - } - - if (gma_power_begin(dev, false)) { - for (i = 0; i < 256; i++) { - REG_WRITE(palreg + 4 * i, - ((psb_intel_crtc->lut_r[i] + - psb_intel_crtc->lut_adj[i]) << 16) | - ((psb_intel_crtc->lut_g[i] + - psb_intel_crtc->lut_adj[i]) << 8) | - (psb_intel_crtc->lut_b[i] + - psb_intel_crtc->lut_adj[i])); - } - gma_power_end(dev); - } else { - for (i = 0; i < 256; i++) { - dev_priv->regs.psb.save_palette_a[i] = - ((psb_intel_crtc->lut_r[i] + - psb_intel_crtc->lut_adj[i]) << 16) | - ((psb_intel_crtc->lut_g[i] + - psb_intel_crtc->lut_adj[i]) << 8) | - (psb_intel_crtc->lut_b[i] + - psb_intel_crtc->lut_adj[i]); - } - - } -} - -/** - * Save HW states of giving crtc - */ -static void cdv_intel_crtc_save(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - /* struct drm_psb_private *dev_priv = - (struct drm_psb_private *)dev->dev_private; */ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; - int pipeA = (psb_intel_crtc->pipe == 0); - uint32_t paletteReg; - int i; - - if (!crtc_state) { - dev_dbg(dev->dev, "No CRTC state found\n"); - return; - } - - crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR); - crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF); - crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC); - crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0); - crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1); - crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B); - crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B); - crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B); - crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B); - crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B); - crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B); - crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B); - crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE); - - /*NOTE: DSPSIZE DSPPOS only for psb*/ - crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE); - crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS); - - crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE); - - DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n", - crtc_state->saveDSPCNTR, - crtc_state->savePIPECONF, - crtc_state->savePIPESRC, - crtc_state->saveFP0, - crtc_state->saveFP1, - crtc_state->saveDPLL, - crtc_state->saveHTOTAL, - crtc_state->saveHBLANK, - crtc_state->saveHSYNC, - crtc_state->saveVTOTAL, - crtc_state->saveVBLANK, - crtc_state->saveVSYNC, - crtc_state->saveDSPSTRIDE, - crtc_state->saveDSPSIZE, - crtc_state->saveDSPPOS, - crtc_state->saveDSPBASE - ); - - paletteReg = pipeA ? PALETTE_A : PALETTE_B; - for (i = 0; i < 256; ++i) - crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2)); -} - -/** - * Restore HW states of giving crtc - */ -static void cdv_intel_crtc_restore(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - /* struct drm_psb_private * dev_priv = - (struct drm_psb_private *)dev->dev_private; */ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; - /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */ - int pipeA = (psb_intel_crtc->pipe == 0); - uint32_t paletteReg; - int i; - - if (!crtc_state) { - dev_dbg(dev->dev, "No crtc state\n"); - return; - } - - DRM_DEBUG( - "current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n", - REG_READ(pipeA ? DSPACNTR : DSPBCNTR), - REG_READ(pipeA ? PIPEACONF : PIPEBCONF), - REG_READ(pipeA ? PIPEASRC : PIPEBSRC), - REG_READ(pipeA ? FPA0 : FPB0), - REG_READ(pipeA ? FPA1 : FPB1), - REG_READ(pipeA ? DPLL_A : DPLL_B), - REG_READ(pipeA ? HTOTAL_A : HTOTAL_B), - REG_READ(pipeA ? HBLANK_A : HBLANK_B), - REG_READ(pipeA ? HSYNC_A : HSYNC_B), - REG_READ(pipeA ? VTOTAL_A : VTOTAL_B), - REG_READ(pipeA ? VBLANK_A : VBLANK_B), - REG_READ(pipeA ? VSYNC_A : VSYNC_B), - REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE), - REG_READ(pipeA ? DSPASIZE : DSPBSIZE), - REG_READ(pipeA ? DSPAPOS : DSPBPOS), - REG_READ(pipeA ? DSPABASE : DSPBBASE) - ); - - DRM_DEBUG( - "saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n", - crtc_state->saveDSPCNTR, - crtc_state->savePIPECONF, - crtc_state->savePIPESRC, - crtc_state->saveFP0, - crtc_state->saveFP1, - crtc_state->saveDPLL, - crtc_state->saveHTOTAL, - crtc_state->saveHBLANK, - crtc_state->saveHSYNC, - crtc_state->saveVTOTAL, - crtc_state->saveVBLANK, - crtc_state->saveVSYNC, - crtc_state->saveDSPSTRIDE, - crtc_state->saveDSPSIZE, - crtc_state->saveDSPPOS, - crtc_state->saveDSPBASE - ); - - - if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) { - REG_WRITE(pipeA ? DPLL_A : DPLL_B, - crtc_state->saveDPLL & ~DPLL_VCO_ENABLE); - REG_READ(pipeA ? DPLL_A : DPLL_B); - DRM_DEBUG("write dpll: %x\n", - REG_READ(pipeA ? DPLL_A : DPLL_B)); - udelay(150); - } - - REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0); - REG_READ(pipeA ? FPA0 : FPB0); - - REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1); - REG_READ(pipeA ? FPA1 : FPB1); - - REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL); - REG_READ(pipeA ? DPLL_A : DPLL_B); - udelay(150); - - REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL); - REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK); - REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC); - REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL); - REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK); - REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC); - REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE); - - REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE); - REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS); - - REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC); - REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); - REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF); - - cdv_intel_wait_for_vblank(dev); - - REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR); - REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); - - cdv_intel_wait_for_vblank(dev); - - paletteReg = pipeA ? PALETTE_A : PALETTE_B; - for (i = 0; i < 256; ++i) - REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]); -} - -static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, - uint32_t width, uint32_t height) -{ - struct drm_device *dev = crtc->dev; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int pipe = psb_intel_crtc->pipe; - uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; - uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; - uint32_t temp; - size_t addr = 0; - struct gtt_range *gt; - struct drm_gem_object *obj; - int ret; - - /* if we want to turn of the cursor ignore width and height */ - if (!handle) { - /* turn off the cursor */ - temp = CURSOR_MODE_DISABLE; - - if (gma_power_begin(dev, false)) { - REG_WRITE(control, temp); - REG_WRITE(base, 0); - gma_power_end(dev); - } - - /* unpin the old GEM object */ - if (psb_intel_crtc->cursor_obj) { - gt = container_of(psb_intel_crtc->cursor_obj, - struct gtt_range, gem); - psb_gtt_unpin(gt); - drm_gem_object_unreference(psb_intel_crtc->cursor_obj); - psb_intel_crtc->cursor_obj = NULL; - } - - return 0; - } - - /* Currently we only support 64x64 cursors */ - if (width != 64 || height != 64) { - dev_dbg(dev->dev, "we currently only support 64x64 cursors\n"); - return -EINVAL; - } - - obj = drm_gem_object_lookup(dev, file_priv, handle); - if (!obj) - return -ENOENT; - - if (obj->size < width * height * 4) { - dev_dbg(dev->dev, "buffer is to small\n"); - return -ENOMEM; - } - - gt = container_of(obj, struct gtt_range, gem); - - /* Pin the memory into the GTT */ - ret = psb_gtt_pin(gt); - if (ret) { - dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); - return ret; - } - - addr = gt->offset; /* Or resource.start ??? */ - - psb_intel_crtc->cursor_addr = addr; - - temp = 0; - /* set the pipe for the cursor */ - temp |= (pipe << 28); - temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; - - if (gma_power_begin(dev, false)) { - REG_WRITE(control, temp); - REG_WRITE(base, addr); - gma_power_end(dev); - } - - /* unpin the old GEM object */ - if (psb_intel_crtc->cursor_obj) { - gt = container_of(psb_intel_crtc->cursor_obj, - struct gtt_range, gem); - psb_gtt_unpin(gt); - drm_gem_object_unreference(psb_intel_crtc->cursor_obj); - psb_intel_crtc->cursor_obj = obj; - } - return 0; -} - -static int cdv_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) -{ - struct drm_device *dev = crtc->dev; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int pipe = psb_intel_crtc->pipe; - uint32_t temp = 0; - uint32_t adder; - - - if (x < 0) { - temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); - x = -x; - } - if (y < 0) { - temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); - y = -y; - } - - temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); - temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); - - adder = psb_intel_crtc->cursor_addr; - - if (gma_power_begin(dev, false)) { - REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); - REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder); - gma_power_end(dev); - } - return 0; -} - -static void cdv_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, - u16 *green, u16 *blue, uint32_t start, uint32_t size) -{ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int i; - int end = (start + size > 256) ? 256 : start + size; - - for (i = start; i < end; i++) { - psb_intel_crtc->lut_r[i] = red[i] >> 8; - psb_intel_crtc->lut_g[i] = green[i] >> 8; - psb_intel_crtc->lut_b[i] = blue[i] >> 8; - } - - cdv_intel_crtc_load_lut(crtc); -} - -static int cdv_crtc_set_config(struct drm_mode_set *set) -{ - int ret = 0; - struct drm_device *dev = set->crtc->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - - if (!dev_priv->rpm_enabled) - return drm_crtc_helper_set_config(set); - - pm_runtime_forbid(&dev->pdev->dev); - - ret = drm_crtc_helper_set_config(set); - - pm_runtime_allow(&dev->pdev->dev); - - return ret; -} - -/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ - -/* FIXME: why are we using this, should it be cdv_ in this tree ? */ - -static void i8xx_clock(int refclk, struct cdv_intel_clock_t *clock) -{ - clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); - clock->p = clock->p1 * clock->p2; - clock->vco = refclk * clock->m / (clock->n + 2); - clock->dot = clock->vco / clock->p; -} - -/* Returns the clock of the currently programmed mode of the given pipe. */ -static int cdv_intel_crtc_clock_get(struct drm_device *dev, - struct drm_crtc *crtc) -{ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int pipe = psb_intel_crtc->pipe; - u32 dpll; - u32 fp; - struct cdv_intel_clock_t clock; - bool is_lvds; - struct drm_psb_private *dev_priv = dev->dev_private; - - if (gma_power_begin(dev, false)) { - dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B); - if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) - fp = REG_READ((pipe == 0) ? FPA0 : FPB0); - else - fp = REG_READ((pipe == 0) ? FPA1 : FPB1); - is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN); - gma_power_end(dev); - } else { - dpll = (pipe == 0) ? - dev_priv->regs.psb.saveDPLL_A : - dev_priv->regs.psb.saveDPLL_B; - - if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) - fp = (pipe == 0) ? - dev_priv->regs.psb.saveFPA0 : - dev_priv->regs.psb.saveFPB0; - else - fp = (pipe == 0) ? - dev_priv->regs.psb.saveFPA1 : - dev_priv->regs.psb.saveFPB1; - - is_lvds = (pipe == 1) && - (dev_priv->regs.psb.saveLVDS & LVDS_PORT_EN); - } - - clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; - clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; - clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; - - if (is_lvds) { - clock.p1 = - ffs((dpll & - DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> - DPLL_FPA01_P1_POST_DIV_SHIFT); - if (clock.p1 == 0) { - clock.p1 = 4; - dev_err(dev->dev, "PLL %d\n", dpll); - } - clock.p2 = 14; - - if ((dpll & PLL_REF_INPUT_MASK) == - PLLB_REF_INPUT_SPREADSPECTRUMIN) { - /* XXX: might not be 66MHz */ - i8xx_clock(66000, &clock); - } else - i8xx_clock(48000, &clock); - } else { - if (dpll & PLL_P1_DIVIDE_BY_TWO) - clock.p1 = 2; - else { - clock.p1 = - ((dpll & - DPLL_FPA01_P1_POST_DIV_MASK_I830) >> - DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; - } - if (dpll & PLL_P2_DIVIDE_BY_4) - clock.p2 = 4; - else - clock.p2 = 2; - - i8xx_clock(48000, &clock); - } - - /* XXX: It would be nice to validate the clocks, but we can't reuse - * i830PllIsValid() because it relies on the xf86_config connector - * configuration being accurate, which it isn't necessarily. - */ - - return clock.dot; -} - -/** Returns the currently programmed mode of the given pipe. */ -struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev, - struct drm_crtc *crtc) -{ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int pipe = psb_intel_crtc->pipe; - struct drm_display_mode *mode; - int htot; - int hsync; - int vtot; - int vsync; - struct drm_psb_private *dev_priv = dev->dev_private; - - if (gma_power_begin(dev, false)) { - htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); - hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B); - vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); - vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B); - gma_power_end(dev); - } else { - htot = (pipe == 0) ? - dev_priv->regs.psb.saveHTOTAL_A : - dev_priv->regs.psb.saveHTOTAL_B; - hsync = (pipe == 0) ? - dev_priv->regs.psb.saveHSYNC_A : - dev_priv->regs.psb.saveHSYNC_B; - vtot = (pipe == 0) ? - dev_priv->regs.psb.saveVTOTAL_A : - dev_priv->regs.psb.saveVTOTAL_B; - vsync = (pipe == 0) ? - dev_priv->regs.psb.saveVSYNC_A : - dev_priv->regs.psb.saveVSYNC_B; - } - - mode = kzalloc(sizeof(*mode), GFP_KERNEL); - if (!mode) - return NULL; - - mode->clock = cdv_intel_crtc_clock_get(dev, crtc); - mode->hdisplay = (htot & 0xffff) + 1; - mode->htotal = ((htot & 0xffff0000) >> 16) + 1; - mode->hsync_start = (hsync & 0xffff) + 1; - mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; - mode->vdisplay = (vtot & 0xffff) + 1; - mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; - mode->vsync_start = (vsync & 0xffff) + 1; - mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; - - drm_mode_set_name(mode); - drm_mode_set_crtcinfo(mode, 0); - - return mode; -} - -static void cdv_intel_crtc_destroy(struct drm_crtc *crtc) -{ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - - kfree(psb_intel_crtc->crtc_state); - drm_crtc_cleanup(crtc); - kfree(psb_intel_crtc); -} - -const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = { - .dpms = cdv_intel_crtc_dpms, - .mode_fixup = cdv_intel_crtc_mode_fixup, - .mode_set = cdv_intel_crtc_mode_set, - .mode_set_base = cdv_intel_pipe_set_base, - .prepare = cdv_intel_crtc_prepare, - .commit = cdv_intel_crtc_commit, -}; - -const struct drm_crtc_funcs cdv_intel_crtc_funcs = { - .save = cdv_intel_crtc_save, - .restore = cdv_intel_crtc_restore, - .cursor_set = cdv_intel_crtc_cursor_set, - .cursor_move = cdv_intel_crtc_cursor_move, - .gamma_set = cdv_intel_crtc_gamma_set, - .set_config = cdv_crtc_set_config, - .destroy = cdv_intel_crtc_destroy, -}; diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c deleted file mode 100644 index 8d52695..0000000 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright © 2006-2011 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * jim liu - * - * FIXME: - * We should probably make this generic and share it with Medfield - */ - -#include -#include -#include -#include -#include "psb_intel_drv.h" -#include "psb_drv.h" -#include "psb_intel_reg.h" -#include "cdv_device.h" -#include - -/* hdmi control bits */ -#define HDMI_NULL_PACKETS_DURING_VSYNC (1 << 9) -#define HDMI_BORDER_ENABLE (1 << 7) -#define HDMI_AUDIO_ENABLE (1 << 6) -#define HDMI_VSYNC_ACTIVE_HIGH (1 << 4) -#define HDMI_HSYNC_ACTIVE_HIGH (1 << 3) -/* hdmi-b control bits */ -#define HDMIB_PIPE_B_SELECT (1 << 30) - - -struct mid_intel_hdmi_priv { - u32 hdmi_reg; - u32 save_HDMIB; - bool has_hdmi_sink; - bool has_hdmi_audio; - /* Should set this when detect hotplug */ - bool hdmi_device_connected; - struct mdfld_hdmi_i2c *i2c_bus; - struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */ - struct drm_device *dev; -}; - -static void cdv_hdmi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_device *dev = encoder->dev; - struct psb_intel_encoder *psb_intel_encoder = to_psb_intel_encoder(encoder); - struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv; - u32 hdmib; - struct drm_crtc *crtc = encoder->crtc; - struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); - - hdmib = (2 << 10); - - if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) - hdmib |= HDMI_VSYNC_ACTIVE_HIGH; - if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) - hdmib |= HDMI_HSYNC_ACTIVE_HIGH; - - if (intel_crtc->pipe == 1) - hdmib |= HDMIB_PIPE_B_SELECT; - - if (hdmi_priv->has_hdmi_audio) { - hdmib |= HDMI_AUDIO_ENABLE; - hdmib |= HDMI_NULL_PACKETS_DURING_VSYNC; - } - - REG_WRITE(hdmi_priv->hdmi_reg, hdmib); - REG_READ(hdmi_priv->hdmi_reg); -} - -static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode) -{ - struct drm_device *dev = encoder->dev; - struct psb_intel_encoder *psb_intel_encoder = - to_psb_intel_encoder(encoder); - struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv; - u32 hdmib; - - hdmib = REG_READ(hdmi_priv->hdmi_reg); - - if (mode != DRM_MODE_DPMS_ON) - REG_WRITE(hdmi_priv->hdmi_reg, hdmib & ~HDMIB_PORT_EN); - else - REG_WRITE(hdmi_priv->hdmi_reg, hdmib | HDMIB_PORT_EN); - REG_READ(hdmi_priv->hdmi_reg); -} - -static void cdv_hdmi_save(struct drm_connector *connector) -{ - struct drm_device *dev = connector->dev; - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv; - - hdmi_priv->save_HDMIB = REG_READ(hdmi_priv->hdmi_reg); -} - -static void cdv_hdmi_restore(struct drm_connector *connector) -{ - struct drm_device *dev = connector->dev; - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv; - - REG_WRITE(hdmi_priv->hdmi_reg, hdmi_priv->save_HDMIB); - REG_READ(hdmi_priv->hdmi_reg); -} - -static enum drm_connector_status cdv_hdmi_detect( - struct drm_connector *connector, bool force) -{ - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - struct psb_intel_connector *psb_intel_connector = - to_psb_intel_connector(connector); - struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv; - struct edid *edid = NULL; - enum drm_connector_status status = connector_status_disconnected; - - edid = drm_get_edid(connector, &psb_intel_encoder->i2c_bus->adapter); - - hdmi_priv->has_hdmi_sink = false; - hdmi_priv->has_hdmi_audio = false; - if (edid) { - if (edid->input & DRM_EDID_INPUT_DIGITAL) { - status = connector_status_connected; - hdmi_priv->has_hdmi_sink = - drm_detect_hdmi_monitor(edid); - hdmi_priv->has_hdmi_audio = - drm_detect_monitor_audio(edid); - } - - psb_intel_connector->base.display_info.raw_edid = NULL; - kfree(edid); - } - return status; -} - -static int cdv_hdmi_set_property(struct drm_connector *connector, - struct drm_property *property, - uint64_t value) -{ - struct drm_encoder *encoder = connector->encoder; - - if (!strcmp(property->name, "scaling mode") && encoder) { - struct psb_intel_crtc *crtc = to_psb_intel_crtc(encoder->crtc); - bool centre; - uint64_t curValue; - - if (!crtc) - return -1; - - switch (value) { - case DRM_MODE_SCALE_FULLSCREEN: - break; - case DRM_MODE_SCALE_NO_SCALE: - break; - case DRM_MODE_SCALE_ASPECT: - break; - default: - return -1; - } - - if (drm_connector_property_get_value(connector, - property, &curValue)) - return -1; - - if (curValue == value) - return 0; - - if (drm_connector_property_set_value(connector, - property, value)) - return -1; - - centre = (curValue == DRM_MODE_SCALE_NO_SCALE) || - (value == DRM_MODE_SCALE_NO_SCALE); - - if (crtc->saved_mode.hdisplay != 0 && - crtc->saved_mode.vdisplay != 0) { - if (centre) { - if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode, - encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb)) - return -1; - } else { - struct drm_encoder_helper_funcs *helpers - = encoder->helper_private; - helpers->mode_set(encoder, &crtc->saved_mode, - &crtc->saved_adjusted_mode); - } - } - } - return 0; -} - -/* - * Return the list of HDMI DDC modes if available. - */ -static int cdv_hdmi_get_modes(struct drm_connector *connector) -{ - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - struct edid *edid = NULL; - int ret = 0; - - edid = drm_get_edid(connector, &psb_intel_encoder->i2c_bus->adapter); - if (edid) { - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - kfree(edid); - } - return ret; -} - -static int cdv_hdmi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct drm_psb_private *dev_priv = connector->dev->dev_private; - - if (mode->clock > 165000) - return MODE_CLOCK_HIGH; - if (mode->clock < 20000) - return MODE_CLOCK_HIGH; - - /* just in case */ - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - - /* just in case */ - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - return MODE_NO_INTERLACE; - - /* We assume worst case scenario of 32 bpp here, since we don't know */ - if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) > - dev_priv->vram_stolen_size) - return MODE_MEM; - - return MODE_OK; -} - -static void cdv_hdmi_destroy(struct drm_connector *connector) -{ - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - - if (psb_intel_encoder->i2c_bus) - psb_intel_i2c_destroy(psb_intel_encoder->i2c_bus); - drm_sysfs_connector_remove(connector); - drm_connector_cleanup(connector); - kfree(connector); -} - -static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = { - .dpms = cdv_hdmi_dpms, - .mode_fixup = cdv_hdmi_mode_fixup, - .prepare = psb_intel_encoder_prepare, - .mode_set = cdv_hdmi_mode_set, - .commit = psb_intel_encoder_commit, -}; - -static const struct drm_connector_helper_funcs - cdv_hdmi_connector_helper_funcs = { - .get_modes = cdv_hdmi_get_modes, - .mode_valid = cdv_hdmi_mode_valid, - .best_encoder = psb_intel_best_encoder, -}; - -static const struct drm_connector_funcs cdv_hdmi_connector_funcs = { - .dpms = drm_helper_connector_dpms, - .save = cdv_hdmi_save, - .restore = cdv_hdmi_restore, - .detect = cdv_hdmi_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .set_property = cdv_hdmi_set_property, - .destroy = cdv_hdmi_destroy, -}; - -void cdv_hdmi_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev, int reg) -{ - struct psb_intel_encoder *psb_intel_encoder; - struct psb_intel_connector *psb_intel_connector; - struct drm_connector *connector; - struct drm_encoder *encoder; - struct mid_intel_hdmi_priv *hdmi_priv; - int ddc_bus; - - psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), - GFP_KERNEL); - - if (!psb_intel_encoder) - return; - - psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), - GFP_KERNEL); - - if (!psb_intel_connector) - goto err_connector; - - hdmi_priv = kzalloc(sizeof(struct mid_intel_hdmi_priv), GFP_KERNEL); - - if (!hdmi_priv) - goto err_priv; - - connector = &psb_intel_connector->base; - encoder = &psb_intel_encoder->base; - drm_connector_init(dev, connector, - &cdv_hdmi_connector_funcs, - DRM_MODE_CONNECTOR_DVID); - - drm_encoder_init(dev, encoder, &psb_intel_lvds_enc_funcs, - DRM_MODE_ENCODER_TMDS); - - psb_intel_connector_attach_encoder(psb_intel_connector, - psb_intel_encoder); - psb_intel_encoder->type = INTEL_OUTPUT_HDMI; - hdmi_priv->hdmi_reg = reg; - hdmi_priv->has_hdmi_sink = false; - psb_intel_encoder->dev_priv = hdmi_priv; - - drm_encoder_helper_add(encoder, &cdv_hdmi_helper_funcs); - drm_connector_helper_add(connector, - &cdv_hdmi_connector_helper_funcs); - connector->display_info.subpixel_order = SubPixelHorizontalRGB; - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - - drm_connector_attach_property(connector, - dev->mode_config.scaling_mode_property, - DRM_MODE_SCALE_FULLSCREEN); - - switch (reg) { - case SDVOB: - ddc_bus = GPIOE; - break; - case SDVOC: - ddc_bus = GPIOD; - break; - default: - DRM_ERROR("unknown reg 0x%x for HDMI\n", reg); - goto failed_ddc; - break; - } - - psb_intel_encoder->i2c_bus = psb_intel_i2c_create(dev, - ddc_bus, (reg == SDVOB) ? "HDMIB" : "HDMIC"); - - if (!psb_intel_encoder->i2c_bus) { - dev_err(dev->dev, "No ddc adapter available!\n"); - goto failed_ddc; - } - - hdmi_priv->hdmi_i2c_adapter = - &(psb_intel_encoder->i2c_bus->adapter); - hdmi_priv->dev = dev; - drm_sysfs_connector_add(connector); - return; - -failed_ddc: - drm_encoder_cleanup(encoder); - drm_connector_cleanup(connector); -err_priv: - kfree(psb_intel_connector); -err_connector: - kfree(psb_intel_encoder); -} diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c deleted file mode 100644 index 8359c1a..0000000 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ /dev/null @@ -1,734 +0,0 @@ -/* - * Copyright © 2006-2011 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: - * Eric Anholt - * Dave Airlie - * Jesse Barnes - */ - -#include -#include -#include - -#include "intel_bios.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "power.h" -#include -#include "cdv_device.h" - -/** - * LVDS I2C backlight control macros - */ -#define BRIGHTNESS_MAX_LEVEL 100 -#define BRIGHTNESS_MASK 0xFF -#define BLC_I2C_TYPE 0x01 -#define BLC_PWM_TYPT 0x02 - -#define BLC_POLARITY_NORMAL 0 -#define BLC_POLARITY_INVERSE 1 - -#define PSB_BLC_MAX_PWM_REG_FREQ (0xFFFE) -#define PSB_BLC_MIN_PWM_REG_FREQ (0x2) -#define PSB_BLC_PWM_PRECISION_FACTOR (10) -#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) -#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) - -struct cdv_intel_lvds_priv { - /** - * Saved LVDO output states - */ - uint32_t savePP_ON; - uint32_t savePP_OFF; - uint32_t saveLVDS; - uint32_t savePP_CONTROL; - uint32_t savePP_CYCLE; - uint32_t savePFIT_CONTROL; - uint32_t savePFIT_PGM_RATIOS; - uint32_t saveBLC_PWM_CTL; -}; - -/* - * Returns the maximum level of the backlight duty cycle field. - */ -static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 retval; - - if (gma_power_begin(dev, false)) { - retval = ((REG_READ(BLC_PWM_CTL) & - BACKLIGHT_MODULATION_FREQ_MASK) >> - BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; - - gma_power_end(dev); - } else - retval = ((dev_priv->regs.saveBLC_PWM_CTL & - BACKLIGHT_MODULATION_FREQ_MASK) >> - BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; - - return retval; -} - -#if 0 -/* - * Set LVDS backlight level by I2C command - */ -static int cdv_lvds_i2c_set_brightness(struct drm_device *dev, - unsigned int level) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus; - u8 out_buf[2]; - unsigned int blc_i2c_brightness; - - struct i2c_msg msgs[] = { - { - .addr = lvds_i2c_bus->slave_addr, - .flags = 0, - .len = 2, - .buf = out_buf, - } - }; - - blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level * - BRIGHTNESS_MASK / - BRIGHTNESS_MAX_LEVEL); - - if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) - blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness; - - out_buf[0] = dev_priv->lvds_bl->brightnesscmd; - out_buf[1] = (u8)blc_i2c_brightness; - - if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) - return 0; - - DRM_ERROR("I2C transfer error\n"); - return -1; -} - - -static int cdv_lvds_pwm_set_brightness(struct drm_device *dev, int level) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - - u32 max_pwm_blc; - u32 blc_pwm_duty_cycle; - - max_pwm_blc = cdv_intel_lvds_get_max_backlight(dev); - - /*BLC_PWM_CTL Should be initiated while backlight device init*/ - BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0); - - blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL; - - if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) - blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle; - - blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; - REG_WRITE(BLC_PWM_CTL, - (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | - (blc_pwm_duty_cycle)); - - return 0; -} - -/* - * Set LVDS backlight level either by I2C or PWM - */ -void cdv_intel_lvds_set_brightness(struct drm_device *dev, int level) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - - if (!dev_priv->lvds_bl) { - DRM_ERROR("NO LVDS Backlight Info\n"); - return; - } - - if (dev_priv->lvds_bl->type == BLC_I2C_TYPE) - cdv_lvds_i2c_set_brightness(dev, level); - else - cdv_lvds_pwm_set_brightness(dev, level); -} -#endif - -/** - * Sets the backlight level. - * - * level backlight level, from 0 to cdv_intel_lvds_get_max_backlight(). - */ -static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 blc_pwm_ctl; - - if (gma_power_begin(dev, false)) { - blc_pwm_ctl = - REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; - REG_WRITE(BLC_PWM_CTL, - (blc_pwm_ctl | - (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); - gma_power_end(dev); - } else { - blc_pwm_ctl = dev_priv->regs.saveBLC_PWM_CTL & - ~BACKLIGHT_DUTY_CYCLE_MASK; - dev_priv->regs.saveBLC_PWM_CTL = (blc_pwm_ctl | - (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); - } -} - -/** - * Sets the power state for the panel. - */ -static void cdv_intel_lvds_set_power(struct drm_device *dev, - struct drm_encoder *encoder, bool on) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 pp_status; - - if (!gma_power_begin(dev, true)) - return; - - if (on) { - REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | - POWER_TARGET_ON); - do { - pp_status = REG_READ(PP_STATUS); - } while ((pp_status & PP_ON) == 0); - - cdv_intel_lvds_set_backlight(dev, - dev_priv->mode_dev.backlight_duty_cycle); - } else { - cdv_intel_lvds_set_backlight(dev, 0); - - REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & - ~POWER_TARGET_ON); - do { - pp_status = REG_READ(PP_STATUS); - } while (pp_status & PP_ON); - } - gma_power_end(dev); -} - -static void cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - struct drm_device *dev = encoder->dev; - if (mode == DRM_MODE_DPMS_ON) - cdv_intel_lvds_set_power(dev, encoder, true); - else - cdv_intel_lvds_set_power(dev, encoder, false); - /* XXX: We never power down the LVDS pairs. */ -} - -static void cdv_intel_lvds_save(struct drm_connector *connector) -{ -} - -static void cdv_intel_lvds_restore(struct drm_connector *connector) -{ -} - -static int cdv_intel_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct drm_device *dev = connector->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct drm_display_mode *fixed_mode = - dev_priv->mode_dev.panel_fixed_mode; - - /* just in case */ - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - - /* just in case */ - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - return MODE_NO_INTERLACE; - - if (fixed_mode) { - if (mode->hdisplay > fixed_mode->hdisplay) - return MODE_PANEL; - if (mode->vdisplay > fixed_mode->vdisplay) - return MODE_PANEL; - } - return MODE_OK; -} - -static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_device *dev = encoder->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - struct drm_encoder *tmp_encoder; - struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode; - - /* Should never happen!! */ - list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, - head) { - if (tmp_encoder != encoder - && tmp_encoder->crtc == encoder->crtc) { - printk(KERN_ERR "Can't enable LVDS and another " - "encoder on the same pipe\n"); - return false; - } - } - - /* - * If we have timings from the BIOS for the panel, put them in - * to the adjusted mode. The CRTC will be set up for this mode, - * with the panel scaling set up to source from the H/VDisplay - * of the original mode. - */ - if (panel_fixed_mode != NULL) { - adjusted_mode->hdisplay = panel_fixed_mode->hdisplay; - adjusted_mode->hsync_start = panel_fixed_mode->hsync_start; - adjusted_mode->hsync_end = panel_fixed_mode->hsync_end; - adjusted_mode->htotal = panel_fixed_mode->htotal; - adjusted_mode->vdisplay = panel_fixed_mode->vdisplay; - adjusted_mode->vsync_start = panel_fixed_mode->vsync_start; - adjusted_mode->vsync_end = panel_fixed_mode->vsync_end; - adjusted_mode->vtotal = panel_fixed_mode->vtotal; - adjusted_mode->clock = panel_fixed_mode->clock; - drm_mode_set_crtcinfo(adjusted_mode, - CRTC_INTERLACE_HALVE_V); - } - - /* - * XXX: It would be nice to support lower refresh rates on the - * panels to reduce power consumption, and perhaps match the - * user's requested refresh rate. - */ - - return true; -} - -static void cdv_intel_lvds_prepare(struct drm_encoder *encoder) -{ - struct drm_device *dev = encoder->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - - if (!gma_power_begin(dev, true)) - return; - - mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); - mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & - BACKLIGHT_DUTY_CYCLE_MASK); - - cdv_intel_lvds_set_power(dev, encoder, false); - - gma_power_end(dev); -} - -static void cdv_intel_lvds_commit(struct drm_encoder *encoder) -{ - struct drm_device *dev = encoder->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - - if (mode_dev->backlight_duty_cycle == 0) - mode_dev->backlight_duty_cycle = - cdv_intel_lvds_get_max_backlight(dev); - - cdv_intel_lvds_set_power(dev, encoder, true); -} - -static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_device *dev = encoder->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - u32 pfit_control; - - /* - * The LVDS pin pair will already have been turned on in the - * cdv_intel_crtc_mode_set since it has a large impact on the DPLL - * settings. - */ - - /* - * Enable automatic panel scaling so that non-native modes fill the - * screen. Should be enabled before the pipe is enabled, according to - * register description and PRM. - */ - if (mode->hdisplay != adjusted_mode->hdisplay || - mode->vdisplay != adjusted_mode->vdisplay) - pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | - HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | - HORIZ_INTERP_BILINEAR); - else - pfit_control = 0; - - if (dev_priv->lvds_dither) - pfit_control |= PANEL_8TO6_DITHER_ENABLE; - - REG_WRITE(PFIT_CONTROL, pfit_control); -} - -/** - * Detect the LVDS connection. - * - * This always returns CONNECTOR_STATUS_CONNECTED. - * This connector should only have - * been set up if the LVDS was actually connected anyway. - */ -static enum drm_connector_status cdv_intel_lvds_detect( - struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - -/** - * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. - */ -static int cdv_intel_lvds_get_modes(struct drm_connector *connector) -{ - struct drm_device *dev = connector->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - int ret; - - ret = psb_intel_ddc_get_modes(connector, &psb_intel_encoder->i2c_bus->adapter); - - if (ret) - return ret; - - /* Didn't get an EDID, so - * Set wide sync ranges so we get all modes - * handed to valid_mode for checking - */ - connector->display_info.min_vfreq = 0; - connector->display_info.max_vfreq = 200; - connector->display_info.min_hfreq = 0; - connector->display_info.max_hfreq = 200; - if (mode_dev->panel_fixed_mode != NULL) { - struct drm_display_mode *mode = - drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); - drm_mode_probed_add(connector, mode); - return 1; - } - - return 0; -} - -/** - * cdv_intel_lvds_destroy - unregister and free LVDS structures - * @connector: connector to free - * - * Unregister the DDC bus for this connector then free the driver private - * structure. - */ -static void cdv_intel_lvds_destroy(struct drm_connector *connector) -{ - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - - if (psb_intel_encoder->i2c_bus) - psb_intel_i2c_destroy(psb_intel_encoder->i2c_bus); - drm_sysfs_connector_remove(connector); - drm_connector_cleanup(connector); - kfree(connector); -} - -static int cdv_intel_lvds_set_property(struct drm_connector *connector, - struct drm_property *property, - uint64_t value) -{ - struct drm_encoder *encoder = connector->encoder; - - if (!strcmp(property->name, "scaling mode") && encoder) { - struct psb_intel_crtc *crtc = - to_psb_intel_crtc(encoder->crtc); - uint64_t curValue; - - if (!crtc) - return -1; - - switch (value) { - case DRM_MODE_SCALE_FULLSCREEN: - break; - case DRM_MODE_SCALE_NO_SCALE: - break; - case DRM_MODE_SCALE_ASPECT: - break; - default: - return -1; - } - - if (drm_connector_property_get_value(connector, - property, - &curValue)) - return -1; - - if (curValue == value) - return 0; - - if (drm_connector_property_set_value(connector, - property, - value)) - return -1; - - if (crtc->saved_mode.hdisplay != 0 && - crtc->saved_mode.vdisplay != 0) { - if (!drm_crtc_helper_set_mode(encoder->crtc, - &crtc->saved_mode, - encoder->crtc->x, - encoder->crtc->y, - encoder->crtc->fb)) - return -1; - } - } else if (!strcmp(property->name, "backlight") && encoder) { - if (drm_connector_property_set_value(connector, - property, - value)) - return -1; - else { -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - struct drm_psb_private *dev_priv = - encoder->dev->dev_private; - struct backlight_device *bd = - dev_priv->backlight_device; - bd->props.brightness = value; - backlight_update_status(bd); -#endif - } - } else if (!strcmp(property->name, "DPMS") && encoder) { - struct drm_encoder_helper_funcs *helpers = - encoder->helper_private; - helpers->dpms(encoder, value); - } - return 0; -} - -static const struct drm_encoder_helper_funcs - cdv_intel_lvds_helper_funcs = { - .dpms = cdv_intel_lvds_encoder_dpms, - .mode_fixup = cdv_intel_lvds_mode_fixup, - .prepare = cdv_intel_lvds_prepare, - .mode_set = cdv_intel_lvds_mode_set, - .commit = cdv_intel_lvds_commit, -}; - -static const struct drm_connector_helper_funcs - cdv_intel_lvds_connector_helper_funcs = { - .get_modes = cdv_intel_lvds_get_modes, - .mode_valid = cdv_intel_lvds_mode_valid, - .best_encoder = psb_intel_best_encoder, -}; - -static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = { - .dpms = drm_helper_connector_dpms, - .save = cdv_intel_lvds_save, - .restore = cdv_intel_lvds_restore, - .detect = cdv_intel_lvds_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .set_property = cdv_intel_lvds_set_property, - .destroy = cdv_intel_lvds_destroy, -}; - - -static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); -} - -const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = { - .destroy = cdv_intel_lvds_enc_destroy, -}; - -/** - * cdv_intel_lvds_init - setup LVDS connectors on this device - * @dev: drm device - * - * Create the connector, register the LVDS DDC bus, and try to figure out what - * modes we can display on the LVDS panel (if present). - */ -void cdv_intel_lvds_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev) -{ - struct psb_intel_encoder *psb_intel_encoder; - struct psb_intel_connector *psb_intel_connector; - struct cdv_intel_lvds_priv *lvds_priv; - struct drm_connector *connector; - struct drm_encoder *encoder; - struct drm_display_mode *scan; - struct drm_crtc *crtc; - struct drm_psb_private *dev_priv = dev->dev_private; - u32 lvds; - int pipe; - - psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), - GFP_KERNEL); - if (!psb_intel_encoder) - return; - - psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), - GFP_KERNEL); - if (!psb_intel_connector) - goto failed_connector; - - lvds_priv = kzalloc(sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL); - if (!lvds_priv) - goto failed_lvds_priv; - - psb_intel_encoder->dev_priv = lvds_priv; - - connector = &psb_intel_connector->base; - encoder = &psb_intel_encoder->base; - - - drm_connector_init(dev, connector, - &cdv_intel_lvds_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - - drm_encoder_init(dev, encoder, - &cdv_intel_lvds_enc_funcs, - DRM_MODE_ENCODER_LVDS); - - - psb_intel_connector_attach_encoder(psb_intel_connector, - psb_intel_encoder); - psb_intel_encoder->type = INTEL_OUTPUT_LVDS; - - drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs); - drm_connector_helper_add(connector, - &cdv_intel_lvds_connector_helper_funcs); - connector->display_info.subpixel_order = SubPixelHorizontalRGB; - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - - /*Attach connector properties*/ - drm_connector_attach_property(connector, - dev->mode_config.scaling_mode_property, - DRM_MODE_SCALE_FULLSCREEN); - drm_connector_attach_property(connector, - dev_priv->backlight_property, - BRIGHTNESS_MAX_LEVEL); - - /** - * Set up I2C bus - * FIXME: distroy i2c_bus when exit - */ - psb_intel_encoder->i2c_bus = psb_intel_i2c_create(dev, - GPIOB, - "LVDSBLC_B"); - if (!psb_intel_encoder->i2c_bus) { - dev_printk(KERN_ERR, - &dev->pdev->dev, "I2C bus registration failed.\n"); - goto failed_blc_i2c; - } - psb_intel_encoder->i2c_bus->slave_addr = 0x2C; - dev_priv->lvds_i2c_bus = psb_intel_encoder->i2c_bus; - - /* - * LVDS discovery: - * 1) check for EDID on DDC - * 2) check for VBT data - * 3) check to see if LVDS is already on - * if none of the above, no panel - * 4) make sure lid is open - * if closed, act like it's not there for now - */ - - /* Set up the DDC bus. */ - psb_intel_encoder->ddc_bus = psb_intel_i2c_create(dev, - GPIOC, - "LVDSDDC_C"); - if (!psb_intel_encoder->ddc_bus) { - dev_printk(KERN_ERR, &dev->pdev->dev, - "DDC bus registration " "failed.\n"); - goto failed_ddc; - } - - /* - * Attempt to get the fixed panel mode from DDC. Assume that the - * preferred mode is the right one. - */ - psb_intel_ddc_get_modes(connector, - &psb_intel_encoder->ddc_bus->adapter); - list_for_each_entry(scan, &connector->probed_modes, head) { - if (scan->type & DRM_MODE_TYPE_PREFERRED) { - mode_dev->panel_fixed_mode = - drm_mode_duplicate(dev, scan); - goto out; /* FIXME: check for quirks */ - } - } - - /* Failed to get EDID, what about VBT? do we need this?*/ - if (dev_priv->lfp_lvds_vbt_mode) { - mode_dev->panel_fixed_mode = - drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); - if (mode_dev->panel_fixed_mode) { - mode_dev->panel_fixed_mode->type |= - DRM_MODE_TYPE_PREFERRED; - goto out; /* FIXME: check for quirks */ - } - } - /* - * If we didn't get EDID, try checking if the panel is already turned - * on. If so, assume that whatever is currently programmed is the - * correct mode. - */ - lvds = REG_READ(LVDS); - pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; - crtc = psb_intel_get_crtc_from_pipe(dev, pipe); - - if (crtc && (lvds & LVDS_PORT_EN)) { - mode_dev->panel_fixed_mode = - cdv_intel_crtc_mode_get(dev, crtc); - if (mode_dev->panel_fixed_mode) { - mode_dev->panel_fixed_mode->type |= - DRM_MODE_TYPE_PREFERRED; - goto out; /* FIXME: check for quirks */ - } - } - - /* If we still don't have a mode after all that, give up. */ - if (!mode_dev->panel_fixed_mode) { - DRM_DEBUG - ("Found no modes on the lvds, ignoring the LVDS\n"); - goto failed_find; - } - -out: - drm_sysfs_connector_add(connector); - return; - -failed_find: - printk(KERN_ERR "Failed find\n"); - if (psb_intel_encoder->ddc_bus) - psb_intel_i2c_destroy(psb_intel_encoder->ddc_bus); -failed_ddc: - printk(KERN_ERR "Failed DDC\n"); - if (psb_intel_encoder->i2c_bus) - psb_intel_i2c_destroy(psb_intel_encoder->i2c_bus); -failed_blc_i2c: - printk(KERN_ERR "Failed BLC\n"); - drm_encoder_cleanup(encoder); - drm_connector_cleanup(connector); - kfree(lvds_priv); -failed_lvds_priv: - kfree(psb_intel_connector); -failed_connector: - kfree(psb_intel_encoder); -} diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c deleted file mode 100644 index 8ea202f..0000000 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ /dev/null @@ -1,800 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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 -#include -#include - -#include -#include -#include -#include - -#include "psb_drv.h" -#include "psb_intel_reg.h" -#include "psb_intel_drv.h" -#include "framebuffer.h" -#include "gtt.h" - -static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb); -static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb, - struct drm_file *file_priv, - unsigned int *handle); - -static const struct drm_framebuffer_funcs psb_fb_funcs = { - .destroy = psb_user_framebuffer_destroy, - .create_handle = psb_user_framebuffer_create_handle, -}; - -#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16) - -static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info) -{ - struct psb_fbdev *fbdev = info->par; - struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb; - uint32_t v; - - if (!fb) - return -ENOMEM; - - if (regno > 255) - return 1; - - red = CMAP_TOHW(red, info->var.red.length); - blue = CMAP_TOHW(blue, info->var.blue.length); - green = CMAP_TOHW(green, info->var.green.length); - transp = CMAP_TOHW(transp, info->var.transp.length); - - v = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset) | - (transp << info->var.transp.offset); - - if (regno < 16) { - switch (fb->bits_per_pixel) { - case 16: - ((uint32_t *) info->pseudo_palette)[regno] = v; - break; - case 24: - case 32: - ((uint32_t *) info->pseudo_palette)[regno] = v; - break; - } - } - - return 0; -} - -static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info) -{ - struct psb_fbdev *fbdev = info->par; - struct psb_framebuffer *psbfb = &fbdev->pfb; - struct drm_device *dev = psbfb->base.dev; - - /* - * We have to poke our nose in here. The core fb code assumes - * panning is part of the hardware that can be invoked before - * the actual fb is mapped. In our case that isn't quite true. - */ - if (psbfb->gtt->npage) { - /* GTT roll shifts in 4K pages, we need to shift the right - number of pages */ - int pages = info->fix.line_length >> 12; - psb_gtt_roll(dev, psbfb->gtt, var->yoffset * pages); - } - return 0; -} - -static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - struct psb_framebuffer *psbfb = vma->vm_private_data; - struct drm_device *dev = psbfb->base.dev; - struct drm_psb_private *dev_priv = dev->dev_private; - int page_num; - int i; - unsigned long address; - int ret; - unsigned long pfn; - /* FIXME: assumes fb at stolen base which may not be true */ - unsigned long phys_addr = (unsigned long)dev_priv->stolen_base; - - page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; - address = (unsigned long)vmf->virtual_address - (vmf->pgoff << PAGE_SHIFT); - - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - for (i = 0; i < page_num; i++) { - pfn = (phys_addr >> PAGE_SHIFT); - - ret = vm_insert_mixed(vma, address, pfn); - if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0))) - break; - else if (unlikely(ret != 0)) { - ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; - return ret; - } - address += PAGE_SIZE; - phys_addr += PAGE_SIZE; - } - return VM_FAULT_NOPAGE; -} - -static void psbfb_vm_open(struct vm_area_struct *vma) -{ -} - -static void psbfb_vm_close(struct vm_area_struct *vma) -{ -} - -static struct vm_operations_struct psbfb_vm_ops = { - .fault = psbfb_vm_fault, - .open = psbfb_vm_open, - .close = psbfb_vm_close -}; - -static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ - struct psb_fbdev *fbdev = info->par; - struct psb_framebuffer *psbfb = &fbdev->pfb; - - if (vma->vm_pgoff != 0) - return -EINVAL; - if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) - return -EINVAL; - - if (!psbfb->addr_space) - psbfb->addr_space = vma->vm_file->f_mapping; - /* - * If this is a GEM object then info->screen_base is the virtual - * kernel remapping of the object. FIXME: Review if this is - * suitable for our mmap work - */ - vma->vm_ops = &psbfb_vm_ops; - vma->vm_private_data = (void *)psbfb; - vma->vm_flags |= VM_RESERVED | VM_IO | - VM_MIXEDMAP | VM_DONTEXPAND; - return 0; -} - -static int psbfb_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) -{ - return -ENOTTY; -} - -static struct fb_ops psbfb_ops = { - .owner = THIS_MODULE, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, - .fb_blank = drm_fb_helper_blank, - .fb_setcolreg = psbfb_setcolreg, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = psbfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_mmap = psbfb_mmap, - .fb_sync = psbfb_sync, - .fb_ioctl = psbfb_ioctl, -}; - -static struct fb_ops psbfb_roll_ops = { - .owner = THIS_MODULE, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, - .fb_blank = drm_fb_helper_blank, - .fb_setcolreg = psbfb_setcolreg, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_pan_display = psbfb_pan, - .fb_mmap = psbfb_mmap, - .fb_ioctl = psbfb_ioctl, -}; - -static struct fb_ops psbfb_unaccel_ops = { - .owner = THIS_MODULE, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, - .fb_blank = drm_fb_helper_blank, - .fb_setcolreg = psbfb_setcolreg, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_mmap = psbfb_mmap, - .fb_ioctl = psbfb_ioctl, -}; - -/** - * psb_framebuffer_init - initialize a framebuffer - * @dev: our DRM device - * @fb: framebuffer to set up - * @mode_cmd: mode description - * @gt: backing object - * - * Configure and fill in the boilerplate for our frame buffer. Return - * 0 on success or an error code if we fail. - */ -static int psb_framebuffer_init(struct drm_device *dev, - struct psb_framebuffer *fb, - struct drm_mode_fb_cmd2 *mode_cmd, - struct gtt_range *gt) -{ - u32 bpp, depth; - int ret; - - drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); - - if (mode_cmd->pitches[0] & 63) - return -EINVAL; - switch (bpp) { - case 8: - case 16: - case 24: - case 32: - break; - default: - return -EINVAL; - } - ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs); - if (ret) { - dev_err(dev->dev, "framebuffer init failed: %d\n", ret); - return ret; - } - drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); - fb->gtt = gt; - return 0; -} - -/** - * psb_framebuffer_create - create a framebuffer backed by gt - * @dev: our DRM device - * @mode_cmd: the description of the requested mode - * @gt: the backing object - * - * Create a framebuffer object backed by the gt, and fill in the - * boilerplate required - * - * TODO: review object references - */ - -static struct drm_framebuffer *psb_framebuffer_create - (struct drm_device *dev, - struct drm_mode_fb_cmd2 *mode_cmd, - struct gtt_range *gt) -{ - struct psb_framebuffer *fb; - int ret; - - fb = kzalloc(sizeof(*fb), GFP_KERNEL); - if (!fb) - return ERR_PTR(-ENOMEM); - - ret = psb_framebuffer_init(dev, fb, mode_cmd, gt); - if (ret) { - kfree(fb); - return ERR_PTR(ret); - } - return &fb->base; -} - -/** - * psbfb_alloc - allocate frame buffer memory - * @dev: the DRM device - * @aligned_size: space needed - * @force: fall back to GEM buffers if need be - * - * Allocate the frame buffer. In the usual case we get a GTT range that - * is stolen memory backed and life is simple. If there isn't sufficient - * we fail as we don't have the virtual mapping space to really vmap it - * and the kernel console code can't handle non linear framebuffers. - * - * Re-address this as and if the framebuffer layer grows this ability. - */ -static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size) -{ - struct gtt_range *backing; - /* Begin by trying to use stolen memory backing */ - backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1); - if (backing) { - if (drm_gem_private_object_init(dev, - &backing->gem, aligned_size) == 0) - return backing; - psb_gtt_free_range(dev, backing); - } - return NULL; -} - -/** - * psbfb_create - create a framebuffer - * @fbdev: the framebuffer device - * @sizes: specification of the layout - * - * Create a framebuffer to the specifications provided - */ -static int psbfb_create(struct psb_fbdev *fbdev, - struct drm_fb_helper_surface_size *sizes) -{ - struct drm_device *dev = fbdev->psb_fb_helper.dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct fb_info *info; - struct drm_framebuffer *fb; - struct psb_framebuffer *psbfb = &fbdev->pfb; - struct drm_mode_fb_cmd2 mode_cmd; - struct device *device = &dev->pdev->dev; - int size; - int ret; - struct gtt_range *backing; - u32 bpp, depth; - int gtt_roll = 0; - int pitch_lines = 0; - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - bpp = sizes->surface_bpp; - depth = sizes->surface_depth; - - /* No 24bit packed */ - if (bpp == 24) - bpp = 32; - - do { - /* - * Acceleration via the GTT requires pitch to be - * power of two aligned. Preferably page but less - * is ok with some fonts - */ - mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096 >> pitch_lines); - - size = mode_cmd.pitches[0] * mode_cmd.height; - size = ALIGN(size, PAGE_SIZE); - - /* Allocate the fb in the GTT with stolen page backing */ - backing = psbfb_alloc(dev, size); - - if (pitch_lines) - pitch_lines *= 2; - else - pitch_lines = 1; - gtt_roll++; - } while (backing == NULL && pitch_lines <= 16); - - /* The final pitch we accepted if we succeeded */ - pitch_lines /= 2; - - if (backing == NULL) { - /* - * We couldn't get the space we wanted, fall back to the - * display engine requirement instead. The HW requires - * the pitch to be 64 byte aligned - */ - - gtt_roll = 0; /* Don't use GTT accelerated scrolling */ - pitch_lines = 64; - - mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64); - - size = mode_cmd.pitches[0] * mode_cmd.height; - size = ALIGN(size, PAGE_SIZE); - - /* Allocate the framebuffer in the GTT with stolen page backing */ - backing = psbfb_alloc(dev, size); - if (backing == NULL) - return -ENOMEM; - } - - mutex_lock(&dev->struct_mutex); - - info = framebuffer_alloc(0, device); - if (!info) { - ret = -ENOMEM; - goto out_err1; - } - info->par = fbdev; - - mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); - - ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing); - if (ret) - goto out_unref; - - fb = &psbfb->base; - psbfb->fbdev = info; - - fbdev->psb_fb_helper.fb = fb; - fbdev->psb_fb_helper.fbdev = info; - - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); - strcpy(info->fix.id, "psbfb"); - - info->flags = FBINFO_DEFAULT; - if (dev_priv->ops->accel_2d && pitch_lines > 8) /* 2D engine */ - info->fbops = &psbfb_ops; - else if (gtt_roll) { /* GTT rolling seems best */ - info->fbops = &psbfb_roll_ops; - info->flags |= FBINFO_HWACCEL_YPAN; - } else /* Software */ - info->fbops = &psbfb_unaccel_ops; - - ret = fb_alloc_cmap(&info->cmap, 256, 0); - if (ret) { - ret = -ENOMEM; - goto out_unref; - } - - info->fix.smem_start = dev->mode_config.fb_base; - info->fix.smem_len = size; - info->fix.ywrapstep = gtt_roll; - info->fix.ypanstep = 0; - - /* Accessed stolen memory directly */ - info->screen_base = (char *)dev_priv->vram_addr + - backing->offset; - info->screen_size = size; - - if (dev_priv->gtt.stolen_size) { - info->apertures = alloc_apertures(1); - if (!info->apertures) { - ret = -ENOMEM; - goto out_unref; - } - info->apertures->ranges[0].base = dev->mode_config.fb_base; - info->apertures->ranges[0].size = dev_priv->gtt.stolen_size; - } - - drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper, - sizes->fb_width, sizes->fb_height); - - info->fix.mmio_start = pci_resource_start(dev->pdev, 0); - info->fix.mmio_len = pci_resource_len(dev->pdev, 0); - - /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ - - dev_info(dev->dev, "allocated %dx%d fb\n", - psbfb->base.width, psbfb->base.height); - - mutex_unlock(&dev->struct_mutex); - return 0; -out_unref: - if (backing->stolen) - psb_gtt_free_range(dev, backing); - else - drm_gem_object_unreference(&backing->gem); -out_err1: - mutex_unlock(&dev->struct_mutex); - psb_gtt_free_range(dev, backing); - return ret; -} - -/** - * psb_user_framebuffer_create - create framebuffer - * @dev: our DRM device - * @filp: client file - * @cmd: mode request - * - * Create a new framebuffer backed by a userspace GEM object - */ -static struct drm_framebuffer *psb_user_framebuffer_create - (struct drm_device *dev, struct drm_file *filp, - struct drm_mode_fb_cmd2 *cmd) -{ - struct gtt_range *r; - struct drm_gem_object *obj; - - /* - * Find the GEM object and thus the gtt range object that is - * to back this space - */ - obj = drm_gem_object_lookup(dev, filp, cmd->handles[0]); - if (obj == NULL) - return ERR_PTR(-ENOENT); - - /* Let the core code do all the work */ - r = container_of(obj, struct gtt_range, gem); - return psb_framebuffer_create(dev, cmd, r); -} - -static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno) -{ - struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); - - intel_crtc->lut_r[regno] = red >> 8; - intel_crtc->lut_g[regno] = green >> 8; - intel_crtc->lut_b[regno] = blue >> 8; -} - -static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red, - u16 *green, u16 *blue, int regno) -{ - struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); - - *red = intel_crtc->lut_r[regno] << 8; - *green = intel_crtc->lut_g[regno] << 8; - *blue = intel_crtc->lut_b[regno] << 8; -} - -static int psbfb_probe(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper; - int new_fb = 0; - int ret; - - if (!helper->fb) { - ret = psbfb_create(psb_fbdev, sizes); - if (ret) - return ret; - new_fb = 1; - } - return new_fb; -} - -struct drm_fb_helper_funcs psb_fb_helper_funcs = { - .gamma_set = psbfb_gamma_set, - .gamma_get = psbfb_gamma_get, - .fb_probe = psbfb_probe, -}; - -static int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev) -{ - struct fb_info *info; - struct psb_framebuffer *psbfb = &fbdev->pfb; - - if (fbdev->psb_fb_helper.fbdev) { - info = fbdev->psb_fb_helper.fbdev; - unregister_framebuffer(info); - if (info->cmap.len) - fb_dealloc_cmap(&info->cmap); - framebuffer_release(info); - } - drm_fb_helper_fini(&fbdev->psb_fb_helper); - drm_framebuffer_cleanup(&psbfb->base); - - if (psbfb->gtt) - drm_gem_object_unreference(&psbfb->gtt->gem); - return 0; -} - -int psb_fbdev_init(struct drm_device *dev) -{ - struct psb_fbdev *fbdev; - struct drm_psb_private *dev_priv = dev->dev_private; - - fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL); - if (!fbdev) { - dev_err(dev->dev, "no memory\n"); - return -ENOMEM; - } - - dev_priv->fbdev = fbdev; - fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs; - - drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs, - INTELFB_CONN_LIMIT); - - drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper); - drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32); - return 0; -} - -static void psb_fbdev_fini(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - - if (!dev_priv->fbdev) - return; - - psb_fbdev_destroy(dev, dev_priv->fbdev); - kfree(dev_priv->fbdev); - dev_priv->fbdev = NULL; -} - -static void psbfb_output_poll_changed(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev; - drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper); -} - -/** - * psb_user_framebuffer_create_handle - add hamdle to a framebuffer - * @fb: framebuffer - * @file_priv: our DRM file - * @handle: returned handle - * - * Our framebuffer object is a GTT range which also contains a GEM - * object. We need to turn it into a handle for userspace. GEM will do - * the work for us - */ -static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb, - struct drm_file *file_priv, - unsigned int *handle) -{ - struct psb_framebuffer *psbfb = to_psb_fb(fb); - struct gtt_range *r = psbfb->gtt; - return drm_gem_handle_create(file_priv, &r->gem, handle); -} - -/** - * psb_user_framebuffer_destroy - destruct user created fb - * @fb: framebuffer - * - * User framebuffers are backed by GEM objects so all we have to do is - * clean up a bit and drop the reference, GEM will handle the fallout - */ -static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb) -{ - struct psb_framebuffer *psbfb = to_psb_fb(fb); - struct gtt_range *r = psbfb->gtt; - struct drm_device *dev = fb->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_fbdev *fbdev = dev_priv->fbdev; - struct drm_crtc *crtc; - int reset = 0; - - /* Should never get stolen memory for a user fb */ - WARN_ON(r->stolen); - - /* Check if we are erroneously live */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - if (crtc->fb == fb) - reset = 1; - - if (reset) - /* - * Now force a sane response before we permit the DRM CRTC - * layer to do stupid things like blank the display. Instead - * we reset this framebuffer as if the user had forced a reset. - * We must do this before the cleanup so that the DRM layer - * doesn't get a chance to stick its oar in where it isn't - * wanted. - */ - drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper); - - /* Let DRM do its clean up */ - drm_framebuffer_cleanup(fb); - /* We are no longer using the resource in GEM */ - drm_gem_object_unreference_unlocked(&r->gem); - kfree(fb); -} - -static const struct drm_mode_config_funcs psb_mode_funcs = { - .fb_create = psb_user_framebuffer_create, - .output_poll_changed = psbfb_output_poll_changed, -}; - -static int psb_create_backlight_property(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct drm_property *backlight; - - if (dev_priv->backlight_property) - return 0; - - backlight = drm_property_create_range(dev, 0, "backlight", 0, 100); - - dev_priv->backlight_property = backlight; - - return 0; -} - -static void psb_setup_outputs(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct drm_connector *connector; - - drm_mode_create_scaling_mode_property(dev); - psb_create_backlight_property(dev); - - dev_priv->ops->output_init(dev); - - list_for_each_entry(connector, &dev->mode_config.connector_list, - head) { - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - struct drm_encoder *encoder = &psb_intel_encoder->base; - int crtc_mask = 0, clone_mask = 0; - - /* valid crtcs */ - switch (psb_intel_encoder->type) { - case INTEL_OUTPUT_ANALOG: - crtc_mask = (1 << 0); - clone_mask = (1 << INTEL_OUTPUT_ANALOG); - break; - case INTEL_OUTPUT_SDVO: - crtc_mask = ((1 << 0) | (1 << 1)); - clone_mask = (1 << INTEL_OUTPUT_SDVO); - break; - case INTEL_OUTPUT_LVDS: - if (IS_MRST(dev)) - crtc_mask = (1 << 0); - else - crtc_mask = (1 << 1); - clone_mask = (1 << INTEL_OUTPUT_LVDS); - break; - case INTEL_OUTPUT_MIPI: - crtc_mask = (1 << 0); - clone_mask = (1 << INTEL_OUTPUT_MIPI); - break; - case INTEL_OUTPUT_MIPI2: - crtc_mask = (1 << 2); - clone_mask = (1 << INTEL_OUTPUT_MIPI2); - break; - case INTEL_OUTPUT_HDMI: - if (IS_MFLD(dev)) - crtc_mask = (1 << 1); - else - crtc_mask = (1 << 0); - clone_mask = (1 << INTEL_OUTPUT_HDMI); - break; - } - encoder->possible_crtcs = crtc_mask; - encoder->possible_clones = - psb_intel_connector_clones(dev, clone_mask); - } -} - -void psb_modeset_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - int i; - - drm_mode_config_init(dev); - - dev->mode_config.min_width = 0; - dev->mode_config.min_height = 0; - - dev->mode_config.funcs = (void *) &psb_mode_funcs; - - /* set memory base */ - /* Oaktrail and Poulsbo should use BAR 2*/ - pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *) - &(dev->mode_config.fb_base)); - - /* num pipes is 2 for PSB but 1 for Mrst */ - for (i = 0; i < dev_priv->num_pipe; i++) - psb_intel_crtc_init(dev, i, mode_dev); - - dev->mode_config.max_width = 2048; - dev->mode_config.max_height = 2048; - - psb_setup_outputs(dev); -} - -void psb_modeset_cleanup(struct drm_device *dev) -{ - mutex_lock(&dev->struct_mutex); - - drm_kms_helper_poll_fini(dev); - psb_fbdev_fini(dev); - drm_mode_config_cleanup(dev); - - mutex_unlock(&dev->struct_mutex); -} diff --git a/drivers/gpu/drm/gma500/framebuffer.h b/drivers/gpu/drm/gma500/framebuffer.h deleted file mode 100644 index 989558a..0000000 --- a/drivers/gpu/drm/gma500/framebuffer.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2008-2011, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: - * Eric Anholt - * - */ - -#ifndef _FRAMEBUFFER_H_ -#define _FRAMEBUFFER_H_ - -#include -#include - -#include "psb_drv.h" - -struct psb_framebuffer { - struct drm_framebuffer base; - struct address_space *addr_space; - struct fb_info *fbdev; - struct gtt_range *gtt; -}; - -struct psb_fbdev { - struct drm_fb_helper psb_fb_helper; - struct psb_framebuffer pfb; -}; - -#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base) - -extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask); - -#endif - diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c deleted file mode 100644 index 9fbb868..0000000 --- a/drivers/gpu/drm/gma500/gem.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * psb GEM interface - * - * Copyright (c) 2011, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: Alan Cox - * - * TODO: - * - we need to work out if the MMU is relevant (eg for - * accelerated operations on a GEM object) - */ - -#include -#include -#include "gma_drm.h" -#include "psb_drv.h" - -int psb_gem_init_object(struct drm_gem_object *obj) -{ - return -EINVAL; -} - -void psb_gem_free_object(struct drm_gem_object *obj) -{ - struct gtt_range *gtt = container_of(obj, struct gtt_range, gem); - drm_gem_object_release_wrap(obj); - /* This must occur last as it frees up the memory of the GEM object */ - psb_gtt_free_range(obj->dev, gtt); -} - -int psb_gem_get_aperture(struct drm_device *dev, void *data, - struct drm_file *file) -{ - return -EINVAL; -} - -/** - * psb_gem_dumb_map_gtt - buffer mapping for dumb interface - * @file: our drm client file - * @dev: drm device - * @handle: GEM handle to the object (from dumb_create) - * - * Do the necessary setup to allow the mapping of the frame buffer - * into user memory. We don't have to do much here at the moment. - */ -int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, - uint32_t handle, uint64_t *offset) -{ - int ret = 0; - struct drm_gem_object *obj; - - if (!(dev->driver->driver_features & DRIVER_GEM)) - return -ENODEV; - - mutex_lock(&dev->struct_mutex); - - /* GEM does all our handle to object mapping */ - obj = drm_gem_object_lookup(dev, file, handle); - if (obj == NULL) { - ret = -ENOENT; - goto unlock; - } - /* What validation is needed here ? */ - - /* Make it mmapable */ - if (!obj->map_list.map) { - ret = gem_create_mmap_offset(obj); - if (ret) - goto out; - } - /* GEM should really work out the hash offsets for us */ - *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT; -out: - drm_gem_object_unreference(obj); -unlock: - mutex_unlock(&dev->struct_mutex); - return ret; -} - -/** - * psb_gem_create - create a mappable object - * @file: the DRM file of the client - * @dev: our device - * @size: the size requested - * @handlep: returned handle (opaque number) - * - * Create a GEM object, fill in the boilerplate and attach a handle to - * it so that userspace can speak about it. This does the core work - * for the various methods that do/will create GEM objects for things - */ -static int psb_gem_create(struct drm_file *file, - struct drm_device *dev, uint64_t size, uint32_t *handlep) -{ - struct gtt_range *r; - int ret; - u32 handle; - - size = roundup(size, PAGE_SIZE); - - /* Allocate our object - for now a direct gtt range which is not - stolen memory backed */ - r = psb_gtt_alloc_range(dev, size, "gem", 0); - if (r == NULL) { - dev_err(dev->dev, "no memory for %lld byte GEM object\n", size); - return -ENOSPC; - } - /* Initialize the extra goodies GEM needs to do all the hard work */ - if (drm_gem_object_init(dev, &r->gem, size) != 0) { - psb_gtt_free_range(dev, r); - /* GEM doesn't give an error code so use -ENOMEM */ - dev_err(dev->dev, "GEM init failed for %lld\n", size); - return -ENOMEM; - } - /* Give the object a handle so we can carry it more easily */ - ret = drm_gem_handle_create(file, &r->gem, &handle); - if (ret) { - dev_err(dev->dev, "GEM handle failed for %p, %lld\n", - &r->gem, size); - drm_gem_object_release(&r->gem); - psb_gtt_free_range(dev, r); - return ret; - } - /* We have the initial and handle reference but need only one now */ - drm_gem_object_unreference(&r->gem); - *handlep = handle; - return 0; -} - -/** - * psb_gem_dumb_create - create a dumb buffer - * @drm_file: our client file - * @dev: our device - * @args: the requested arguments copied from userspace - * - * Allocate a buffer suitable for use for a frame buffer of the - * form described by user space. Give userspace a handle by which - * to reference it. - */ -int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev, - struct drm_mode_create_dumb *args) -{ - args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64); - args->size = args->pitch * args->height; - return psb_gem_create(file, dev, args->size, &args->handle); -} - -/** - * psb_gem_dumb_destroy - destroy a dumb buffer - * @file: client file - * @dev: our DRM device - * @handle: the object handle - * - * Destroy a handle that was created via psb_gem_dumb_create, at least - * we hope it was created that way. i915 seems to assume the caller - * does the checking but that might be worth review ! FIXME - */ -int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, - uint32_t handle) -{ - /* No special work needed, drop the reference and see what falls out */ - return drm_gem_handle_delete(file, handle); -} - -/** - * psb_gem_fault - pagefault handler for GEM objects - * @vma: the VMA of the GEM object - * @vmf: fault detail - * - * Invoked when a fault occurs on an mmap of a GEM managed area. GEM - * does most of the work for us including the actual map/unmap calls - * but we need to do the actual page work. - * - * This code eventually needs to handle faulting objects in and out - * of the GTT and repacking it when we run out of space. We can put - * that off for now and for our simple uses - * - * The VMA was set up by GEM. In doing so it also ensured that the - * vma->vm_private_data points to the GEM object that is backing this - * mapping. - */ -int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - struct drm_gem_object *obj; - struct gtt_range *r; - int ret; - unsigned long pfn; - pgoff_t page_offset; - struct drm_device *dev; - struct drm_psb_private *dev_priv; - - obj = vma->vm_private_data; /* GEM object */ - dev = obj->dev; - dev_priv = dev->dev_private; - - r = container_of(obj, struct gtt_range, gem); /* Get the gtt range */ - - /* Make sure we don't parallel update on a fault, nor move or remove - something from beneath our feet */ - mutex_lock(&dev->struct_mutex); - - /* For now the mmap pins the object and it stays pinned. As things - stand that will do us no harm */ - if (r->mmapping == 0) { - ret = psb_gtt_pin(r); - if (ret < 0) { - dev_err(dev->dev, "gma500: pin failed: %d\n", ret); - goto fail; - } - r->mmapping = 1; - } - - /* Page relative to the VMA start - we must calculate this ourselves - because vmf->pgoff is the fake GEM offset */ - page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start) - >> PAGE_SHIFT; - - /* CPU view of the page, don't go via the GART for CPU writes */ - if (r->stolen) - pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT; - else - pfn = page_to_pfn(r->pages[page_offset]); - ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); - -fail: - mutex_unlock(&dev->struct_mutex); - switch (ret) { - case 0: - case -ERESTARTSYS: - case -EINTR: - return VM_FAULT_NOPAGE; - case -ENOMEM: - return VM_FAULT_OOM; - default: - return VM_FAULT_SIGBUS; - } -} - -static int psb_gem_create_stolen(struct drm_file *file, struct drm_device *dev, - int size, u32 *handle) -{ - struct gtt_range *gtt = psb_gtt_alloc_range(dev, size, "gem", 1); - if (gtt == NULL) - return -ENOMEM; - if (drm_gem_private_object_init(dev, >t->gem, size) != 0) - goto free_gtt; - if (drm_gem_handle_create(file, >t->gem, handle) == 0) - return 0; -free_gtt: - psb_gtt_free_range(dev, gtt); - return -ENOMEM; -} - -/* - * GEM interfaces for our specific client - */ -int psb_gem_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file) -{ - struct drm_psb_gem_create *args = data; - int ret; - if (args->flags & GMA_GEM_CREATE_STOLEN) { - ret = psb_gem_create_stolen(file, dev, args->size, - &args->handle); - if (ret == 0) - return 0; - /* Fall throguh */ - args->flags &= ~GMA_GEM_CREATE_STOLEN; - } - return psb_gem_create(file, dev, args->size, &args->handle); -} - -int psb_gem_mmap_ioctl(struct drm_device *dev, void *data, - struct drm_file *file) -{ - struct drm_psb_gem_mmap *args = data; - return dev->driver->dumb_map_offset(file, dev, - args->handle, &args->offset); -} - diff --git a/drivers/gpu/drm/gma500/gem_glue.c b/drivers/gpu/drm/gma500/gem_glue.c deleted file mode 100644 index 3c17634..0000000 --- a/drivers/gpu/drm/gma500/gem_glue.c +++ /dev/null @@ -1,90 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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 "gem_glue.h" - -void drm_gem_object_release_wrap(struct drm_gem_object *obj) -{ - /* Remove the list map if one is present */ - if (obj->map_list.map) { - struct drm_gem_mm *mm = obj->dev->mm_private; - struct drm_map_list *list = &obj->map_list; - drm_ht_remove_item(&mm->offset_hash, &list->hash); - drm_mm_put_block(list->file_offset_node); - kfree(list->map); - list->map = NULL; - } - drm_gem_object_release(obj); -} - -/** - * gem_create_mmap_offset - invent an mmap offset - * @obj: our object - * - * Standard implementation of offset generation for mmap as is - * duplicated in several drivers. This belongs in GEM. - */ -int gem_create_mmap_offset(struct drm_gem_object *obj) -{ - struct drm_device *dev = obj->dev; - struct drm_gem_mm *mm = dev->mm_private; - struct drm_map_list *list; - struct drm_local_map *map; - int ret; - - list = &obj->map_list; - list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL); - if (list->map == NULL) - return -ENOMEM; - map = list->map; - map->type = _DRM_GEM; - map->size = obj->size; - map->handle = obj; - - list->file_offset_node = drm_mm_search_free(&mm->offset_manager, - obj->size / PAGE_SIZE, 0, 0); - if (!list->file_offset_node) { - dev_err(dev->dev, "failed to allocate offset for bo %d\n", - obj->name); - ret = -ENOSPC; - goto free_it; - } - list->file_offset_node = drm_mm_get_block(list->file_offset_node, - obj->size / PAGE_SIZE, 0); - if (!list->file_offset_node) { - ret = -ENOMEM; - goto free_it; - } - list->hash.key = list->file_offset_node->start; - ret = drm_ht_insert_item(&mm->offset_hash, &list->hash); - if (ret) { - dev_err(dev->dev, "failed to add to map hash\n"); - goto free_mm; - } - return 0; - -free_mm: - drm_mm_put_block(list->file_offset_node); -free_it: - kfree(list->map); - list->map = NULL; - return ret; -} diff --git a/drivers/gpu/drm/gma500/gem_glue.h b/drivers/gpu/drm/gma500/gem_glue.h deleted file mode 100644 index ce5ce30..0000000 --- a/drivers/gpu/drm/gma500/gem_glue.h +++ /dev/null @@ -1,2 +0,0 @@ -extern void drm_gem_object_release_wrap(struct drm_gem_object *obj); -extern int gem_create_mmap_offset(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c deleted file mode 100644 index c6465b4..0000000 --- a/drivers/gpu/drm/gma500/gtt.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright (c) 2007, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: Thomas Hellstrom - * Alan Cox - */ - -#include -#include -#include "psb_drv.h" - - -/* - * GTT resource allocator - manage page mappings in GTT space - */ - -/** - * psb_gtt_mask_pte - generate GTT pte entry - * @pfn: page number to encode - * @type: type of memory in the GTT - * - * Set the GTT entry for the appropriate memory type. - */ -static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type) -{ - uint32_t mask = PSB_PTE_VALID; - - if (type & PSB_MMU_CACHED_MEMORY) - mask |= PSB_PTE_CACHED; - if (type & PSB_MMU_RO_MEMORY) - mask |= PSB_PTE_RO; - if (type & PSB_MMU_WO_MEMORY) - mask |= PSB_PTE_WO; - - return (pfn << PAGE_SHIFT) | mask; -} - -/** - * psb_gtt_entry - find the GTT entries for a gtt_range - * @dev: our DRM device - * @r: our GTT range - * - * Given a gtt_range object return the GTT offset of the page table - * entries for this gtt_range - */ -static u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - unsigned long offset; - - offset = r->resource.start - dev_priv->gtt_mem->start; - - return dev_priv->gtt_map + (offset >> PAGE_SHIFT); -} - -/** - * psb_gtt_insert - put an object into the GTT - * @dev: our DRM device - * @r: our GTT range - * - * Take our preallocated GTT range and insert the GEM object into - * the GTT. This is protected via the gtt mutex which the caller - * must hold. - */ -static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r) -{ - u32 *gtt_slot, pte; - struct page **pages; - int i; - - if (r->pages == NULL) { - WARN_ON(1); - return -EINVAL; - } - - WARN_ON(r->stolen); /* refcount these maybe ? */ - - gtt_slot = psb_gtt_entry(dev, r); - pages = r->pages; - - /* Make sure changes are visible to the GPU */ - set_pages_array_uc(pages, r->npage); - - /* Write our page entries into the GTT itself */ - for (i = r->roll; i < r->npage; i++) { - pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); - iowrite32(pte, gtt_slot++); - } - for (i = 0; i < r->roll; i++) { - pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); - iowrite32(pte, gtt_slot++); - } - /* Make sure all the entries are set before we return */ - ioread32(gtt_slot - 1); - - return 0; -} - -/** - * psb_gtt_remove - remove an object from the GTT - * @dev: our DRM device - * @r: our GTT range - * - * Remove a preallocated GTT range from the GTT. Overwrite all the - * page table entries with the dummy page. This is protected via the gtt - * mutex which the caller must hold. - */ -static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 *gtt_slot, pte; - int i; - - WARN_ON(r->stolen); - - gtt_slot = psb_gtt_entry(dev, r); - pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0); - - for (i = 0; i < r->npage; i++) - iowrite32(pte, gtt_slot++); - ioread32(gtt_slot - 1); - set_pages_array_wb(r->pages, r->npage); -} - -/** - * psb_gtt_roll - set scrolling position - * @dev: our DRM device - * @r: the gtt mapping we are using - * @roll: roll offset - * - * Roll an existing pinned mapping by moving the pages through the GTT. - * This allows us to implement hardware scrolling on the consoles without - * a 2D engine - */ -void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll) -{ - u32 *gtt_slot, pte; - int i; - - if (roll >= r->npage) { - WARN_ON(1); - return; - } - - r->roll = roll; - - /* Not currently in the GTT - no worry we will write the mapping at - the right position when it gets pinned */ - if (!r->stolen && !r->in_gart) - return; - - gtt_slot = psb_gtt_entry(dev, r); - - for (i = r->roll; i < r->npage; i++) { - pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); - iowrite32(pte, gtt_slot++); - } - for (i = 0; i < r->roll; i++) { - pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); - iowrite32(pte, gtt_slot++); - } - ioread32(gtt_slot - 1); -} - -/** - * psb_gtt_attach_pages - attach and pin GEM pages - * @gt: the gtt range - * - * Pin and build an in kernel list of the pages that back our GEM object. - * While we hold this the pages cannot be swapped out. This is protected - * via the gtt mutex which the caller must hold. - */ -static int psb_gtt_attach_pages(struct gtt_range *gt) -{ - struct inode *inode; - struct address_space *mapping; - int i; - struct page *p; - int pages = gt->gem.size / PAGE_SIZE; - - WARN_ON(gt->pages); - - /* This is the shared memory object that backs the GEM resource */ - inode = gt->gem.filp->f_path.dentry->d_inode; - mapping = inode->i_mapping; - - gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL); - if (gt->pages == NULL) - return -ENOMEM; - gt->npage = pages; - - for (i = 0; i < pages; i++) { - p = shmem_read_mapping_page(mapping, i); - if (IS_ERR(p)) - goto err; - gt->pages[i] = p; - } - return 0; - -err: - while (i--) - page_cache_release(gt->pages[i]); - kfree(gt->pages); - gt->pages = NULL; - return PTR_ERR(p); -} - -/** - * psb_gtt_detach_pages - attach and pin GEM pages - * @gt: the gtt range - * - * Undo the effect of psb_gtt_attach_pages. At this point the pages - * must have been removed from the GTT as they could now be paged out - * and move bus address. This is protected via the gtt mutex which the - * caller must hold. - */ -static void psb_gtt_detach_pages(struct gtt_range *gt) -{ - int i; - for (i = 0; i < gt->npage; i++) { - /* FIXME: do we need to force dirty */ - set_page_dirty(gt->pages[i]); - page_cache_release(gt->pages[i]); - } - kfree(gt->pages); - gt->pages = NULL; -} - -/** - * psb_gtt_pin - pin pages into the GTT - * @gt: range to pin - * - * Pin a set of pages into the GTT. The pins are refcounted so that - * multiple pins need multiple unpins to undo. - * - * Non GEM backed objects treat this as a no-op as they are always GTT - * backed objects. - */ -int psb_gtt_pin(struct gtt_range *gt) -{ - int ret = 0; - struct drm_device *dev = gt->gem.dev; - struct drm_psb_private *dev_priv = dev->dev_private; - - mutex_lock(&dev_priv->gtt_mutex); - - if (gt->in_gart == 0 && gt->stolen == 0) { - ret = psb_gtt_attach_pages(gt); - if (ret < 0) - goto out; - ret = psb_gtt_insert(dev, gt); - if (ret < 0) { - psb_gtt_detach_pages(gt); - goto out; - } - } - gt->in_gart++; -out: - mutex_unlock(&dev_priv->gtt_mutex); - return ret; -} - -/** - * psb_gtt_unpin - Drop a GTT pin requirement - * @gt: range to pin - * - * Undoes the effect of psb_gtt_pin. On the last drop the GEM object - * will be removed from the GTT which will also drop the page references - * and allow the VM to clean up or page stuff. - * - * Non GEM backed objects treat this as a no-op as they are always GTT - * backed objects. - */ -void psb_gtt_unpin(struct gtt_range *gt) -{ - struct drm_device *dev = gt->gem.dev; - struct drm_psb_private *dev_priv = dev->dev_private; - - mutex_lock(&dev_priv->gtt_mutex); - - WARN_ON(!gt->in_gart); - - gt->in_gart--; - if (gt->in_gart == 0 && gt->stolen == 0) { - psb_gtt_remove(dev, gt); - psb_gtt_detach_pages(gt); - } - mutex_unlock(&dev_priv->gtt_mutex); -} - -/* - * GTT resource allocator - allocate and manage GTT address space - */ - -/** - * psb_gtt_alloc_range - allocate GTT address space - * @dev: Our DRM device - * @len: length (bytes) of address space required - * @name: resource name - * @backed: resource should be backed by stolen pages - * - * Ask the kernel core to find us a suitable range of addresses - * to use for a GTT mapping. - * - * Returns a gtt_range structure describing the object, or NULL on - * error. On successful return the resource is both allocated and marked - * as in use. - */ -struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, - const char *name, int backed) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct gtt_range *gt; - struct resource *r = dev_priv->gtt_mem; - int ret; - unsigned long start, end; - - if (backed) { - /* The start of the GTT is the stolen pages */ - start = r->start; - end = r->start + dev_priv->gtt.stolen_size - 1; - } else { - /* The rest we will use for GEM backed objects */ - start = r->start + dev_priv->gtt.stolen_size; - end = r->end; - } - - gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL); - if (gt == NULL) - return NULL; - gt->resource.name = name; - gt->stolen = backed; - gt->in_gart = backed; - gt->roll = 0; - /* Ensure this is set for non GEM objects */ - gt->gem.dev = dev; - ret = allocate_resource(dev_priv->gtt_mem, >->resource, - len, start, end, PAGE_SIZE, NULL, NULL); - if (ret == 0) { - gt->offset = gt->resource.start - r->start; - return gt; - } - kfree(gt); - return NULL; -} - -/** - * psb_gtt_free_range - release GTT address space - * @dev: our DRM device - * @gt: a mapping created with psb_gtt_alloc_range - * - * Release a resource that was allocated with psb_gtt_alloc_range. If the - * object has been pinned by mmap users we clean this up here currently. - */ -void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt) -{ - /* Undo the mmap pin if we are destroying the object */ - if (gt->mmapping) { - psb_gtt_unpin(gt); - gt->mmapping = 0; - } - WARN_ON(gt->in_gart && !gt->stolen); - release_resource(>->resource); - kfree(gt); -} - -static void psb_gtt_alloc(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - init_rwsem(&dev_priv->gtt.sem); -} - -void psb_gtt_takedown(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - - if (dev_priv->gtt_map) { - iounmap(dev_priv->gtt_map); - dev_priv->gtt_map = NULL; - } - if (dev_priv->gtt_initialized) { - pci_write_config_word(dev->pdev, PSB_GMCH_CTRL, - dev_priv->gmch_ctrl); - PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); - (void) PSB_RVDC32(PSB_PGETBL_CTL); - } - if (dev_priv->vram_addr) - iounmap(dev_priv->gtt_map); -} - -int psb_gtt_init(struct drm_device *dev, int resume) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - unsigned gtt_pages; - unsigned long stolen_size, vram_stolen_size; - unsigned i, num_pages; - unsigned pfn_base; - uint32_t vram_pages; - uint32_t dvmt_mode = 0; - struct psb_gtt *pg; - - int ret = 0; - uint32_t pte; - - mutex_init(&dev_priv->gtt_mutex); - - psb_gtt_alloc(dev); - pg = &dev_priv->gtt; - - /* Enable the GTT */ - pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl); - pci_write_config_word(dev->pdev, PSB_GMCH_CTRL, - dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); - - dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL); - PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); - (void) PSB_RVDC32(PSB_PGETBL_CTL); - - /* The root resource we allocate address space from */ - dev_priv->gtt_initialized = 1; - - pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; - - /* - * The video mmu has a hw bug when accessing 0x0D0000000. - * Make gatt start at 0x0e000,0000. This doesn't actually - * matter for us but may do if the video acceleration ever - * gets opened up. - */ - pg->mmu_gatt_start = 0xE0000000; - - pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE); - gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) - >> PAGE_SHIFT; - /* CDV doesn't report this. In which case the system has 64 gtt pages */ - if (pg->gtt_start == 0 || gtt_pages == 0) { - dev_dbg(dev->dev, "GTT PCI BAR not initialized.\n"); - gtt_pages = 64; - pg->gtt_start = dev_priv->pge_ctl; - } - - pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE); - pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE) - >> PAGE_SHIFT; - dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE]; - - if (pg->gatt_pages == 0 || pg->gatt_start == 0) { - static struct resource fudge; /* Preferably peppermint */ - /* This can occur on CDV systems. Fudge it in this case. - We really don't care what imaginary space is being allocated - at this point */ - dev_dbg(dev->dev, "GATT PCI BAR not initialized.\n"); - pg->gatt_start = 0x40000000; - pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT; - /* This is a little confusing but in fact the GTT is providing - a view from the GPU into memory and not vice versa. As such - this is really allocating space that is not the same as the - CPU address space on CDV */ - fudge.start = 0x40000000; - fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1; - fudge.name = "fudge"; - fudge.flags = IORESOURCE_MEM; - dev_priv->gtt_mem = &fudge; - } - - pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base); - vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - - PAGE_SIZE; - - stolen_size = vram_stolen_size; - - printk(KERN_INFO "Stolen memory information\n"); - printk(KERN_INFO " base in RAM: 0x%x\n", dev_priv->stolen_base); - printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n", - vram_stolen_size/1024); - dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7; - printk(KERN_INFO " the correct size should be: %dM(dvmt mode=%d)\n", - (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode); - - if (resume && (gtt_pages != pg->gtt_pages) && - (stolen_size != pg->stolen_size)) { - dev_err(dev->dev, "GTT resume error.\n"); - ret = -EINVAL; - goto out_err; - } - - pg->gtt_pages = gtt_pages; - pg->stolen_size = stolen_size; - dev_priv->vram_stolen_size = vram_stolen_size; - - /* - * Map the GTT and the stolen memory area - */ - dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start, - gtt_pages << PAGE_SHIFT); - if (!dev_priv->gtt_map) { - dev_err(dev->dev, "Failure to map gtt.\n"); - ret = -ENOMEM; - goto out_err; - } - - dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size); - if (!dev_priv->vram_addr) { - dev_err(dev->dev, "Failure to map stolen base.\n"); - ret = -ENOMEM; - goto out_err; - } - - /* - * Insert vram stolen pages into the GTT - */ - - pfn_base = dev_priv->stolen_base >> PAGE_SHIFT; - vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT; - printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n", - num_pages, pfn_base << PAGE_SHIFT, 0); - for (i = 0; i < num_pages; ++i) { - pte = psb_gtt_mask_pte(pfn_base + i, 0); - iowrite32(pte, dev_priv->gtt_map + i); - } - - /* - * Init rest of GTT to the scratch page to avoid accidents or scribbles - */ - - pfn_base = page_to_pfn(dev_priv->scratch_page); - pte = psb_gtt_mask_pte(pfn_base, 0); - for (; i < gtt_pages; ++i) - iowrite32(pte, dev_priv->gtt_map + i); - - (void) ioread32(dev_priv->gtt_map + i - 1); - return 0; - -out_err: - psb_gtt_takedown(dev); - return ret; -} diff --git a/drivers/gpu/drm/gma500/gtt.h b/drivers/gpu/drm/gma500/gtt.h deleted file mode 100644 index aa17423..0000000 --- a/drivers/gpu/drm/gma500/gtt.h +++ /dev/null @@ -1,64 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2008, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - **************************************************************************/ - -#ifndef _PSB_GTT_H_ -#define _PSB_GTT_H_ - -#include - -/* This wants cleaning up with respect to the psb_dev and un-needed stuff */ -struct psb_gtt { - uint32_t gatt_start; - uint32_t mmu_gatt_start; - uint32_t gtt_start; - uint32_t gtt_phys_start; - unsigned gtt_pages; - unsigned gatt_pages; - unsigned long stolen_size; - unsigned long vram_stolen_size; - struct rw_semaphore sem; -}; - -/* Exported functions */ -extern int psb_gtt_init(struct drm_device *dev, int resume); -extern void psb_gtt_takedown(struct drm_device *dev); - -/* Each gtt_range describes an allocation in the GTT area */ -struct gtt_range { - struct resource resource; /* Resource for our allocation */ - u32 offset; /* GTT offset of our object */ - struct drm_gem_object gem; /* GEM high level stuff */ - int in_gart; /* Currently in the GART (ref ct) */ - bool stolen; /* Backed from stolen RAM */ - bool mmapping; /* Is mmappable */ - struct page **pages; /* Backing pages if present */ - int npage; /* Number of backing pages */ - int roll; /* Roll applied to the GTT entries */ -}; - -extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, - const char *name, int backed); -extern void psb_gtt_kref_put(struct gtt_range *gt); -extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt); -extern int psb_gtt_pin(struct gtt_range *gt); -extern void psb_gtt_unpin(struct gtt_range *gt); -extern void psb_gtt_roll(struct drm_device *dev, - struct gtt_range *gt, int roll); - -#endif diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c deleted file mode 100644 index d4d0c5b..0000000 --- a/drivers/gpu/drm/gma500/intel_bios.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 2006 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: - * Eric Anholt - * - */ -#include -#include -#include "gma_drm.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "intel_bios.h" - - -static void *find_section(struct bdb_header *bdb, int section_id) -{ - u8 *base = (u8 *)bdb; - int index = 0; - u16 total, current_size; - u8 current_id; - - /* skip to first section */ - index += bdb->header_size; - total = bdb->bdb_size; - - /* walk the sections looking for section_id */ - while (index < total) { - current_id = *(base + index); - index++; - current_size = *((u16 *)(base + index)); - index += 2; - if (current_id == section_id) - return base + index; - index += current_size; - } - - return NULL; -} - -static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, - struct lvds_dvo_timing *dvo_timing) -{ - panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | - dvo_timing->hactive_lo; - panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + - ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); - panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + - dvo_timing->hsync_pulse_width; - panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + - ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); - - panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | - dvo_timing->vactive_lo; - panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + - dvo_timing->vsync_off; - panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + - dvo_timing->vsync_pulse_width; - panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + - ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); - panel_fixed_mode->clock = dvo_timing->clock * 10; - panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; - - /* Some VBTs have bogus h/vtotal values */ - if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) - panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; - if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) - panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; - - drm_mode_set_name(panel_fixed_mode); -} - -static void parse_backlight_data(struct drm_psb_private *dev_priv, - struct bdb_header *bdb) -{ - struct bdb_lvds_backlight *vbt_lvds_bl = NULL; - struct bdb_lvds_backlight *lvds_bl; - u8 p_type = 0; - void *bl_start = NULL; - struct bdb_lvds_options *lvds_opts - = find_section(bdb, BDB_LVDS_OPTIONS); - - dev_priv->lvds_bl = NULL; - - if (lvds_opts) - p_type = lvds_opts->panel_type; - else - return; - - bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT); - vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type; - - lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL); - if (!lvds_bl) { - dev_err(dev_priv->dev->dev, "out of memory for backlight data\n"); - return; - } - memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl)); - dev_priv->lvds_bl = lvds_bl; -} - -/* Try to find integrated panel data */ -static void parse_lfp_panel_data(struct drm_psb_private *dev_priv, - struct bdb_header *bdb) -{ - struct bdb_lvds_options *lvds_options; - struct bdb_lvds_lfp_data *lvds_lfp_data; - struct bdb_lvds_lfp_data_entry *entry; - struct lvds_dvo_timing *dvo_timing; - struct drm_display_mode *panel_fixed_mode; - - /* Defaults if we can't find VBT info */ - dev_priv->lvds_dither = 0; - dev_priv->lvds_vbt = 0; - - lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); - if (!lvds_options) - return; - - dev_priv->lvds_dither = lvds_options->pixel_dither; - if (lvds_options->panel_type == 0xff) - return; - - lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); - if (!lvds_lfp_data) - return; - - - entry = &lvds_lfp_data->data[lvds_options->panel_type]; - dvo_timing = &entry->dvo_timing; - - panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), - GFP_KERNEL); - if (panel_fixed_mode == NULL) { - dev_err(dev_priv->dev->dev, "out of memory for fixed panel mode\n"); - return; - } - - dev_priv->lvds_vbt = 1; - fill_detail_timing_data(panel_fixed_mode, dvo_timing); - - if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) { - dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; - drm_mode_debug_printmodeline(panel_fixed_mode); - } else { - dev_dbg(dev_priv->dev->dev, "ignoring invalid LVDS VBT\n"); - dev_priv->lvds_vbt = 0; - kfree(panel_fixed_mode); - } - return; -} - -/* Try to find sdvo panel data */ -static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv, - struct bdb_header *bdb) -{ - struct bdb_sdvo_lvds_options *sdvo_lvds_options; - struct lvds_dvo_timing *dvo_timing; - struct drm_display_mode *panel_fixed_mode; - - dev_priv->sdvo_lvds_vbt_mode = NULL; - - sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); - if (!sdvo_lvds_options) - return; - - dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); - if (!dvo_timing) - return; - - panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); - - if (!panel_fixed_mode) - return; - - fill_detail_timing_data(panel_fixed_mode, - dvo_timing + sdvo_lvds_options->panel_type); - - dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; - - return; -} - -static void parse_general_features(struct drm_psb_private *dev_priv, - struct bdb_header *bdb) -{ - struct bdb_general_features *general; - - /* Set sensible defaults in case we can't find the general block */ - dev_priv->int_tv_support = 1; - dev_priv->int_crt_support = 1; - - general = find_section(bdb, BDB_GENERAL_FEATURES); - if (general) { - dev_priv->int_tv_support = general->int_tv_support; - dev_priv->int_crt_support = general->int_crt_support; - dev_priv->lvds_use_ssc = general->enable_ssc; - - if (dev_priv->lvds_use_ssc) { - dev_priv->lvds_ssc_freq - = general->ssc_freq ? 100 : 96; - } - } -} - -/** - * psb_intel_init_bios - initialize VBIOS settings & find VBT - * @dev: DRM device - * - * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers - * to appropriate values. - * - * VBT existence is a sanity check that is relied on by other i830_bios.c code. - * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may - * feed an updated VBT back through that, compared to what we'll fetch using - * this method of groping around in the BIOS data. - * - * Returns 0 on success, nonzero on failure. - */ -bool psb_intel_init_bios(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct pci_dev *pdev = dev->pdev; - struct vbt_header *vbt = NULL; - struct bdb_header *bdb; - u8 __iomem *bios; - size_t size; - int i; - - bios = pci_map_rom(pdev, &size); - if (!bios) - return -1; - - /* Scour memory looking for the VBT signature */ - for (i = 0; i + 4 < size; i++) { - if (!memcmp(bios + i, "$VBT", 4)) { - vbt = (struct vbt_header *)(bios + i); - break; - } - } - - if (!vbt) { - dev_err(dev->dev, "VBT signature missing\n"); - pci_unmap_rom(pdev, bios); - return -1; - } - - bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); - - /* Grab useful general definitions */ - parse_general_features(dev_priv, bdb); - parse_lfp_panel_data(dev_priv, bdb); - parse_sdvo_panel_data(dev_priv, bdb); - parse_backlight_data(dev_priv, bdb); - - pci_unmap_rom(pdev, bios); - - return 0; -} - -/** - * Destroy and free VBT data - */ -void psb_intel_destroy_bios(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct drm_display_mode *sdvo_lvds_vbt_mode = - dev_priv->sdvo_lvds_vbt_mode; - struct drm_display_mode *lfp_lvds_vbt_mode = - dev_priv->lfp_lvds_vbt_mode; - struct bdb_lvds_backlight *lvds_bl = - dev_priv->lvds_bl; - - /*free sdvo panel mode*/ - if (sdvo_lvds_vbt_mode) { - dev_priv->sdvo_lvds_vbt_mode = NULL; - kfree(sdvo_lvds_vbt_mode); - } - - if (lfp_lvds_vbt_mode) { - dev_priv->lfp_lvds_vbt_mode = NULL; - kfree(lfp_lvds_vbt_mode); - } - - if (lvds_bl) { - dev_priv->lvds_bl = NULL; - kfree(lvds_bl); - } -} diff --git a/drivers/gpu/drm/gma500/intel_bios.h b/drivers/gpu/drm/gma500/intel_bios.h deleted file mode 100644 index 70f1bf0..0000000 --- a/drivers/gpu/drm/gma500/intel_bios.h +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright (c) 2006 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: - * Eric Anholt - * - */ - -#ifndef _I830_BIOS_H_ -#define _I830_BIOS_H_ - -#include - -struct vbt_header { - u8 signature[20]; /**< Always starts with 'VBT$' */ - u16 version; /**< decimal */ - u16 header_size; /**< in bytes */ - u16 vbt_size; /**< in bytes */ - u8 vbt_checksum; - u8 reserved0; - u32 bdb_offset; /**< from beginning of VBT */ - u32 aim_offset[4]; /**< from beginning of VBT */ -} __attribute__((packed)); - - -struct bdb_header { - u8 signature[16]; /**< Always 'BIOS_DATA_BLOCK' */ - u16 version; /**< decimal */ - u16 header_size; /**< in bytes */ - u16 bdb_size; /**< in bytes */ -}; - -/* strictly speaking, this is a "skip" block, but it has interesting info */ -struct vbios_data { - u8 type; /* 0 == desktop, 1 == mobile */ - u8 relstage; - u8 chipset; - u8 lvds_present:1; - u8 tv_present:1; - u8 rsvd2:6; /* finish byte */ - u8 rsvd3[4]; - u8 signon[155]; - u8 copyright[61]; - u16 code_segment; - u8 dos_boot_mode; - u8 bandwidth_percent; - u8 rsvd4; /* popup memory size */ - u8 resize_pci_bios; - u8 rsvd5; /* is crt already on ddc2 */ -} __attribute__((packed)); - -/* - * There are several types of BIOS data blocks (BDBs), each block has - * an ID and size in the first 3 bytes (ID in first, size in next 2). - * Known types are listed below. - */ -#define BDB_GENERAL_FEATURES 1 -#define BDB_GENERAL_DEFINITIONS 2 -#define BDB_OLD_TOGGLE_LIST 3 -#define BDB_MODE_SUPPORT_LIST 4 -#define BDB_GENERIC_MODE_TABLE 5 -#define BDB_EXT_MMIO_REGS 6 -#define BDB_SWF_IO 7 -#define BDB_SWF_MMIO 8 -#define BDB_DOT_CLOCK_TABLE 9 -#define BDB_MODE_REMOVAL_TABLE 10 -#define BDB_CHILD_DEVICE_TABLE 11 -#define BDB_DRIVER_FEATURES 12 -#define BDB_DRIVER_PERSISTENCE 13 -#define BDB_EXT_TABLE_PTRS 14 -#define BDB_DOT_CLOCK_OVERRIDE 15 -#define BDB_DISPLAY_SELECT 16 -/* 17 rsvd */ -#define BDB_DRIVER_ROTATION 18 -#define BDB_DISPLAY_REMOVE 19 -#define BDB_OEM_CUSTOM 20 -#define BDB_EFP_LIST 21 /* workarounds for VGA hsync/vsync */ -#define BDB_SDVO_LVDS_OPTIONS 22 -#define BDB_SDVO_PANEL_DTDS 23 -#define BDB_SDVO_LVDS_PNP_IDS 24 -#define BDB_SDVO_LVDS_POWER_SEQ 25 -#define BDB_TV_OPTIONS 26 -#define BDB_LVDS_OPTIONS 40 -#define BDB_LVDS_LFP_DATA_PTRS 41 -#define BDB_LVDS_LFP_DATA 42 -#define BDB_LVDS_BACKLIGHT 43 -#define BDB_LVDS_POWER 44 -#define BDB_SKIP 254 /* VBIOS private block, ignore */ - -struct bdb_general_features { - /* bits 1 */ - u8 panel_fitting:2; - u8 flexaim:1; - u8 msg_enable:1; - u8 clear_screen:3; - u8 color_flip:1; - - /* bits 2 */ - u8 download_ext_vbt:1; - u8 enable_ssc:1; - u8 ssc_freq:1; - u8 enable_lfp_on_override:1; - u8 disable_ssc_ddt:1; - u8 rsvd8:3; /* finish byte */ - - /* bits 3 */ - u8 disable_smooth_vision:1; - u8 single_dvi:1; - u8 rsvd9:6; /* finish byte */ - - /* bits 4 */ - u8 legacy_monitor_detect; - - /* bits 5 */ - u8 int_crt_support:1; - u8 int_tv_support:1; - u8 rsvd11:6; /* finish byte */ -} __attribute__((packed)); - -struct bdb_general_definitions { - /* DDC GPIO */ - u8 crt_ddc_gmbus_pin; - - /* DPMS bits */ - u8 dpms_acpi:1; - u8 skip_boot_crt_detect:1; - u8 dpms_aim:1; - u8 rsvd1:5; /* finish byte */ - - /* boot device bits */ - u8 boot_display[2]; - u8 child_dev_size; - - /* device info */ - u8 tv_or_lvds_info[33]; - u8 dev1[33]; - u8 dev2[33]; - u8 dev3[33]; - u8 dev4[33]; - /* may be another device block here on some platforms */ -}; - -struct bdb_lvds_options { - u8 panel_type; - u8 rsvd1; - /* LVDS capabilities, stored in a dword */ - u8 pfit_mode:2; - u8 pfit_text_mode_enhanced:1; - u8 pfit_gfx_mode_enhanced:1; - u8 pfit_ratio_auto:1; - u8 pixel_dither:1; - u8 lvds_edid:1; - u8 rsvd2:1; - u8 rsvd4; -} __attribute__((packed)); - -struct bdb_lvds_backlight { - u8 type:2; - u8 pol:1; - u8 gpio:3; - u8 gmbus:2; - u16 freq; - u8 minbrightness; - u8 i2caddr; - u8 brightnesscmd; - /*FIXME: more...*/ -} __attribute__((packed)); - -/* LFP pointer table contains entries to the struct below */ -struct bdb_lvds_lfp_data_ptr { - u16 fp_timing_offset; /* offsets are from start of bdb */ - u8 fp_table_size; - u16 dvo_timing_offset; - u8 dvo_table_size; - u16 panel_pnp_id_offset; - u8 pnp_table_size; -} __attribute__((packed)); - -struct bdb_lvds_lfp_data_ptrs { - u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */ - struct bdb_lvds_lfp_data_ptr ptr[16]; -} __attribute__((packed)); - -/* LFP data has 3 blocks per entry */ -struct lvds_fp_timing { - u16 x_res; - u16 y_res; - u32 lvds_reg; - u32 lvds_reg_val; - u32 pp_on_reg; - u32 pp_on_reg_val; - u32 pp_off_reg; - u32 pp_off_reg_val; - u32 pp_cycle_reg; - u32 pp_cycle_reg_val; - u32 pfit_reg; - u32 pfit_reg_val; - u16 terminator; -} __attribute__((packed)); - -struct lvds_dvo_timing { - u16 clock; /**< In 10khz */ - u8 hactive_lo; - u8 hblank_lo; - u8 hblank_hi:4; - u8 hactive_hi:4; - u8 vactive_lo; - u8 vblank_lo; - u8 vblank_hi:4; - u8 vactive_hi:4; - u8 hsync_off_lo; - u8 hsync_pulse_width; - u8 vsync_pulse_width:4; - u8 vsync_off:4; - u8 rsvd0:6; - u8 hsync_off_hi:2; - u8 h_image; - u8 v_image; - u8 max_hv; - u8 h_border; - u8 v_border; - u8 rsvd1:3; - u8 digital:2; - u8 vsync_positive:1; - u8 hsync_positive:1; - u8 rsvd2:1; -} __attribute__((packed)); - -struct lvds_pnp_id { - u16 mfg_name; - u16 product_code; - u32 serial; - u8 mfg_week; - u8 mfg_year; -} __attribute__((packed)); - -struct bdb_lvds_lfp_data_entry { - struct lvds_fp_timing fp_timing; - struct lvds_dvo_timing dvo_timing; - struct lvds_pnp_id pnp_id; -} __attribute__((packed)); - -struct bdb_lvds_lfp_data { - struct bdb_lvds_lfp_data_entry data[16]; -} __attribute__((packed)); - -struct aimdb_header { - char signature[16]; - char oem_device[20]; - u16 aimdb_version; - u16 aimdb_header_size; - u16 aimdb_size; -} __attribute__((packed)); - -struct aimdb_block { - u8 aimdb_id; - u16 aimdb_size; -} __attribute__((packed)); - -struct vch_panel_data { - u16 fp_timing_offset; - u8 fp_timing_size; - u16 dvo_timing_offset; - u8 dvo_timing_size; - u16 text_fitting_offset; - u8 text_fitting_size; - u16 graphics_fitting_offset; - u8 graphics_fitting_size; -} __attribute__((packed)); - -struct vch_bdb_22 { - struct aimdb_block aimdb_block; - struct vch_panel_data panels[16]; -} __attribute__((packed)); - -struct bdb_sdvo_lvds_options { - u8 panel_backlight; - u8 h40_set_panel_type; - u8 panel_type; - u8 ssc_clk_freq; - u16 als_low_trip; - u16 als_high_trip; - u8 sclalarcoeff_tab_row_num; - u8 sclalarcoeff_tab_row_size; - u8 coefficient[8]; - u8 panel_misc_bits_1; - u8 panel_misc_bits_2; - u8 panel_misc_bits_3; - u8 panel_misc_bits_4; -} __attribute__((packed)); - - -extern bool psb_intel_init_bios(struct drm_device *dev); -extern void psb_intel_destroy_bios(struct drm_device *dev); - -/* - * Driver<->VBIOS interaction occurs through scratch bits in - * GR18 & SWF*. - */ - -/* GR18 bits are set on display switch and hotkey events */ -#define GR18_DRIVER_SWITCH_EN (1<<7) /* 0: VBIOS control, 1: driver control */ -#define GR18_HOTKEY_MASK 0x78 /* See also SWF4 15:0 */ -#define GR18_HK_NONE (0x0<<3) -#define GR18_HK_LFP_STRETCH (0x1<<3) -#define GR18_HK_TOGGLE_DISP (0x2<<3) -#define GR18_HK_DISP_SWITCH (0x4<<3) /* see SWF14 15:0 for what to enable */ -#define GR18_HK_POPUP_DISABLED (0x6<<3) -#define GR18_HK_POPUP_ENABLED (0x7<<3) -#define GR18_HK_PFIT (0x8<<3) -#define GR18_HK_APM_CHANGE (0xa<<3) -#define GR18_HK_MULTIPLE (0xc<<3) -#define GR18_USER_INT_EN (1<<2) -#define GR18_A0000_FLUSH_EN (1<<1) -#define GR18_SMM_EN (1<<0) - -/* Set by driver, cleared by VBIOS */ -#define SWF00_YRES_SHIFT 16 -#define SWF00_XRES_SHIFT 0 -#define SWF00_RES_MASK 0xffff - -/* Set by VBIOS at boot time and driver at runtime */ -#define SWF01_TV2_FORMAT_SHIFT 8 -#define SWF01_TV1_FORMAT_SHIFT 0 -#define SWF01_TV_FORMAT_MASK 0xffff - -#define SWF10_VBIOS_BLC_I2C_EN (1<<29) -#define SWF10_GTT_OVERRIDE_EN (1<<28) -#define SWF10_LFP_DPMS_OVR (1<<27) /* override DPMS on display switch */ -#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24) -#define SWF10_OLD_TOGGLE 0x0 -#define SWF10_TOGGLE_LIST_1 0x1 -#define SWF10_TOGGLE_LIST_2 0x2 -#define SWF10_TOGGLE_LIST_3 0x3 -#define SWF10_TOGGLE_LIST_4 0x4 -#define SWF10_PANNING_EN (1<<23) -#define SWF10_DRIVER_LOADED (1<<22) -#define SWF10_EXTENDED_DESKTOP (1<<21) -#define SWF10_EXCLUSIVE_MODE (1<<20) -#define SWF10_OVERLAY_EN (1<<19) -#define SWF10_PLANEB_HOLDOFF (1<<18) -#define SWF10_PLANEA_HOLDOFF (1<<17) -#define SWF10_VGA_HOLDOFF (1<<16) -#define SWF10_ACTIVE_DISP_MASK 0xffff -#define SWF10_PIPEB_LFP2 (1<<15) -#define SWF10_PIPEB_EFP2 (1<<14) -#define SWF10_PIPEB_TV2 (1<<13) -#define SWF10_PIPEB_CRT2 (1<<12) -#define SWF10_PIPEB_LFP (1<<11) -#define SWF10_PIPEB_EFP (1<<10) -#define SWF10_PIPEB_TV (1<<9) -#define SWF10_PIPEB_CRT (1<<8) -#define SWF10_PIPEA_LFP2 (1<<7) -#define SWF10_PIPEA_EFP2 (1<<6) -#define SWF10_PIPEA_TV2 (1<<5) -#define SWF10_PIPEA_CRT2 (1<<4) -#define SWF10_PIPEA_LFP (1<<3) -#define SWF10_PIPEA_EFP (1<<2) -#define SWF10_PIPEA_TV (1<<1) -#define SWF10_PIPEA_CRT (1<<0) - -#define SWF11_MEMORY_SIZE_SHIFT 16 -#define SWF11_SV_TEST_EN (1<<15) -#define SWF11_IS_AGP (1<<14) -#define SWF11_DISPLAY_HOLDOFF (1<<13) -#define SWF11_DPMS_REDUCED (1<<12) -#define SWF11_IS_VBE_MODE (1<<11) -#define SWF11_PIPEB_ACCESS (1<<10) /* 0 here means pipe a */ -#define SWF11_DPMS_MASK 0x07 -#define SWF11_DPMS_OFF (1<<2) -#define SWF11_DPMS_SUSPEND (1<<1) -#define SWF11_DPMS_STANDBY (1<<0) -#define SWF11_DPMS_ON 0 - -#define SWF14_GFX_PFIT_EN (1<<31) -#define SWF14_TEXT_PFIT_EN (1<<30) -#define SWF14_LID_STATUS_CLOSED (1<<29) /* 0 here means open */ -#define SWF14_POPUP_EN (1<<28) -#define SWF14_DISPLAY_HOLDOFF (1<<27) -#define SWF14_DISP_DETECT_EN (1<<26) -#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */ -#define SWF14_DRIVER_STATUS (1<<24) -#define SWF14_OS_TYPE_WIN9X (1<<23) -#define SWF14_OS_TYPE_WINNT (1<<22) -/* 21:19 rsvd */ -#define SWF14_PM_TYPE_MASK 0x00070000 -#define SWF14_PM_ACPI_VIDEO (0x4 << 16) -#define SWF14_PM_ACPI (0x3 << 16) -#define SWF14_PM_APM_12 (0x2 << 16) -#define SWF14_PM_APM_11 (0x1 << 16) -#define SWF14_HK_REQUEST_MASK 0x0000ffff /* see GR18 6:3 for event type */ - /* if GR18 indicates a display switch */ -#define SWF14_DS_PIPEB_LFP2_EN (1<<15) -#define SWF14_DS_PIPEB_EFP2_EN (1<<14) -#define SWF14_DS_PIPEB_TV2_EN (1<<13) -#define SWF14_DS_PIPEB_CRT2_EN (1<<12) -#define SWF14_DS_PIPEB_LFP_EN (1<<11) -#define SWF14_DS_PIPEB_EFP_EN (1<<10) -#define SWF14_DS_PIPEB_TV_EN (1<<9) -#define SWF14_DS_PIPEB_CRT_EN (1<<8) -#define SWF14_DS_PIPEA_LFP2_EN (1<<7) -#define SWF14_DS_PIPEA_EFP2_EN (1<<6) -#define SWF14_DS_PIPEA_TV2_EN (1<<5) -#define SWF14_DS_PIPEA_CRT2_EN (1<<4) -#define SWF14_DS_PIPEA_LFP_EN (1<<3) -#define SWF14_DS_PIPEA_EFP_EN (1<<2) -#define SWF14_DS_PIPEA_TV_EN (1<<1) -#define SWF14_DS_PIPEA_CRT_EN (1<<0) - /* if GR18 indicates a panel fitting request */ -#define SWF14_PFIT_EN (1<<0) /* 0 means disable */ - /* if GR18 indicates an APM change request */ -#define SWF14_APM_HIBERNATE 0x4 -#define SWF14_APM_SUSPEND 0x3 -#define SWF14_APM_STANDBY 0x1 -#define SWF14_APM_RESTORE 0x0 - -#endif /* _I830_BIOS_H_ */ diff --git a/drivers/gpu/drm/gma500/intel_gmbus.c b/drivers/gpu/drm/gma500/intel_gmbus.c deleted file mode 100644 index 9db9052..0000000 --- a/drivers/gpu/drm/gma500/intel_gmbus.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright (c) 2006 Dave Airlie - * Copyright © 2006-2008,2010 Intel Corporation - * Jesse Barnes - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Eric Anholt - * Chris Wilson - */ -#include -#include -#include -#include "drmP.h" -#include "drm.h" -#include "psb_intel_drv.h" -#include "gma_drm.h" -#include "psb_drv.h" -#include "psb_intel_reg.h" - -#define _wait_for(COND, MS, W) ({ \ - unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ - int ret__ = 0; \ - while (! (COND)) { \ - if (time_after(jiffies, timeout__)) { \ - ret__ = -ETIMEDOUT; \ - break; \ - } \ - if (W && !(in_atomic() || in_dbg_master())) msleep(W); \ - } \ - ret__; \ -}) - -#define wait_for(COND, MS) _wait_for(COND, MS, 1) -#define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0) - -/* Intel GPIO access functions */ - -#define I2C_RISEFALL_TIME 20 - -static inline struct intel_gmbus * -to_intel_gmbus(struct i2c_adapter *i2c) -{ - return container_of(i2c, struct intel_gmbus, adapter); -} - -struct intel_gpio { - struct i2c_adapter adapter; - struct i2c_algo_bit_data algo; - struct drm_psb_private *dev_priv; - u32 reg; -}; - -void -gma_intel_i2c_reset(struct drm_device *dev) -{ - REG_WRITE(GMBUS0, 0); -} - -static void intel_i2c_quirk_set(struct drm_psb_private *dev_priv, bool enable) -{ - /* When using bit bashing for I2C, this bit needs to be set to 1 */ - /* FIXME: We are never Pineview, right? - - u32 val; - - if (!IS_PINEVIEW(dev_priv->dev)) - return; - - val = REG_READ(DSPCLK_GATE_D); - if (enable) - val |= DPCUNIT_CLOCK_GATE_DISABLE; - else - val &= ~DPCUNIT_CLOCK_GATE_DISABLE; - REG_WRITE(DSPCLK_GATE_D, val); - - return; - */ -} - -static u32 get_reserved(struct intel_gpio *gpio) -{ - struct drm_psb_private *dev_priv = gpio->dev_priv; - struct drm_device *dev = dev_priv->dev; - u32 reserved = 0; - - /* On most chips, these bits must be preserved in software. */ - reserved = REG_READ(gpio->reg) & - (GPIO_DATA_PULLUP_DISABLE | - GPIO_CLOCK_PULLUP_DISABLE); - - return reserved; -} - -static int get_clock(void *data) -{ - struct intel_gpio *gpio = data; - struct drm_psb_private *dev_priv = gpio->dev_priv; - struct drm_device *dev = dev_priv->dev; - u32 reserved = get_reserved(gpio); - REG_WRITE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK); - REG_WRITE(gpio->reg, reserved); - return (REG_READ(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0; -} - -static int get_data(void *data) -{ - struct intel_gpio *gpio = data; - struct drm_psb_private *dev_priv = gpio->dev_priv; - struct drm_device *dev = dev_priv->dev; - u32 reserved = get_reserved(gpio); - REG_WRITE(gpio->reg, reserved | GPIO_DATA_DIR_MASK); - REG_WRITE(gpio->reg, reserved); - return (REG_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0; -} - -static void set_clock(void *data, int state_high) -{ - struct intel_gpio *gpio = data; - struct drm_psb_private *dev_priv = gpio->dev_priv; - struct drm_device *dev = dev_priv->dev; - u32 reserved = get_reserved(gpio); - u32 clock_bits; - - if (state_high) - clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; - else - clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | - GPIO_CLOCK_VAL_MASK; - - REG_WRITE(gpio->reg, reserved | clock_bits); - REG_READ(gpio->reg); /* Posting */ -} - -static void set_data(void *data, int state_high) -{ - struct intel_gpio *gpio = data; - struct drm_psb_private *dev_priv = gpio->dev_priv; - struct drm_device *dev = dev_priv->dev; - u32 reserved = get_reserved(gpio); - u32 data_bits; - - if (state_high) - data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; - else - data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | - GPIO_DATA_VAL_MASK; - - REG_WRITE(gpio->reg, reserved | data_bits); - REG_READ(gpio->reg); -} - -static struct i2c_adapter * -intel_gpio_create(struct drm_psb_private *dev_priv, u32 pin) -{ - static const int map_pin_to_reg[] = { - 0, - GPIOB, - GPIOA, - GPIOC, - GPIOD, - GPIOE, - 0, - GPIOF, - }; - struct intel_gpio *gpio; - - if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin]) - return NULL; - - gpio = kzalloc(sizeof(struct intel_gpio), GFP_KERNEL); - if (gpio == NULL) - return NULL; - - gpio->reg = map_pin_to_reg[pin]; - gpio->dev_priv = dev_priv; - - snprintf(gpio->adapter.name, sizeof(gpio->adapter.name), - "gma500 GPIO%c", "?BACDE?F"[pin]); - gpio->adapter.owner = THIS_MODULE; - gpio->adapter.algo_data = &gpio->algo; - gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev; - gpio->algo.setsda = set_data; - gpio->algo.setscl = set_clock; - gpio->algo.getsda = get_data; - gpio->algo.getscl = get_clock; - gpio->algo.udelay = I2C_RISEFALL_TIME; - gpio->algo.timeout = usecs_to_jiffies(2200); - gpio->algo.data = gpio; - - if (i2c_bit_add_bus(&gpio->adapter)) - goto out_free; - - return &gpio->adapter; - -out_free: - kfree(gpio); - return NULL; -} - -static int -intel_i2c_quirk_xfer(struct drm_psb_private *dev_priv, - struct i2c_adapter *adapter, - struct i2c_msg *msgs, - int num) -{ - struct intel_gpio *gpio = container_of(adapter, - struct intel_gpio, - adapter); - int ret; - - gma_intel_i2c_reset(dev_priv->dev); - - intel_i2c_quirk_set(dev_priv, true); - set_data(gpio, 1); - set_clock(gpio, 1); - udelay(I2C_RISEFALL_TIME); - - ret = adapter->algo->master_xfer(adapter, msgs, num); - - set_data(gpio, 1); - set_clock(gpio, 1); - intel_i2c_quirk_set(dev_priv, false); - - return ret; -} - -static int -gmbus_xfer(struct i2c_adapter *adapter, - struct i2c_msg *msgs, - int num) -{ - struct intel_gmbus *bus = container_of(adapter, - struct intel_gmbus, - adapter); - struct drm_psb_private *dev_priv = adapter->algo_data; - struct drm_device *dev = dev_priv->dev; - int i, reg_offset; - - if (bus->force_bit) - return intel_i2c_quirk_xfer(dev_priv, - bus->force_bit, msgs, num); - - reg_offset = 0; - - REG_WRITE(GMBUS0 + reg_offset, bus->reg0); - - for (i = 0; i < num; i++) { - u16 len = msgs[i].len; - u8 *buf = msgs[i].buf; - - if (msgs[i].flags & I2C_M_RD) { - REG_WRITE(GMBUS1 + reg_offset, - GMBUS_CYCLE_WAIT | (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | - (len << GMBUS_BYTE_COUNT_SHIFT) | - (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | - GMBUS_SLAVE_READ | GMBUS_SW_RDY); - REG_READ(GMBUS2+reg_offset); - do { - u32 val, loop = 0; - - if (wait_for(REG_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) - goto timeout; - if (REG_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) - goto clear_err; - - val = REG_READ(GMBUS3 + reg_offset); - do { - *buf++ = val & 0xff; - val >>= 8; - } while (--len && ++loop < 4); - } while (len); - } else { - u32 val, loop; - - val = loop = 0; - do { - val |= *buf++ << (8 * loop); - } while (--len && ++loop < 4); - - REG_WRITE(GMBUS3 + reg_offset, val); - REG_WRITE(GMBUS1 + reg_offset, - (i + 1 == num ? GMBUS_CYCLE_STOP : GMBUS_CYCLE_WAIT) | - (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) | - (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | - GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); - REG_READ(GMBUS2+reg_offset); - - while (len) { - if (wait_for(REG_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) - goto timeout; - if (REG_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) - goto clear_err; - - val = loop = 0; - do { - val |= *buf++ << (8 * loop); - } while (--len && ++loop < 4); - - REG_WRITE(GMBUS3 + reg_offset, val); - REG_READ(GMBUS2+reg_offset); - } - } - - if (i + 1 < num && wait_for(REG_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50)) - goto timeout; - if (REG_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) - goto clear_err; - } - - goto done; - -clear_err: - /* Toggle the Software Clear Interrupt bit. This has the effect - * of resetting the GMBUS controller and so clearing the - * BUS_ERROR raised by the slave's NAK. - */ - REG_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT); - REG_WRITE(GMBUS1 + reg_offset, 0); - -done: - /* Mark the GMBUS interface as disabled. We will re-enable it at the - * start of the next xfer, till then let it sleep. - */ - REG_WRITE(GMBUS0 + reg_offset, 0); - return i; - -timeout: - DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n", - bus->reg0 & 0xff, bus->adapter.name); - REG_WRITE(GMBUS0 + reg_offset, 0); - - /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ - bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff); - if (!bus->force_bit) - return -ENOMEM; - - return intel_i2c_quirk_xfer(dev_priv, bus->force_bit, msgs, num); -} - -static u32 gmbus_func(struct i2c_adapter *adapter) -{ - struct intel_gmbus *bus = container_of(adapter, - struct intel_gmbus, - adapter); - - if (bus->force_bit) - bus->force_bit->algo->functionality(bus->force_bit); - - return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | - /* I2C_FUNC_10BIT_ADDR | */ - I2C_FUNC_SMBUS_READ_BLOCK_DATA | - I2C_FUNC_SMBUS_BLOCK_PROC_CALL); -} - -static const struct i2c_algorithm gmbus_algorithm = { - .master_xfer = gmbus_xfer, - .functionality = gmbus_func -}; - -/** - * intel_gmbus_setup - instantiate all Intel i2c GMBuses - * @dev: DRM device - */ -int gma_intel_setup_gmbus(struct drm_device *dev) -{ - static const char *names[GMBUS_NUM_PORTS] = { - "disabled", - "ssc", - "vga", - "panel", - "dpc", - "dpb", - "reserved", - "dpd", - }; - struct drm_psb_private *dev_priv = dev->dev_private; - int ret, i; - - dev_priv->gmbus = kcalloc(GMBUS_NUM_PORTS, sizeof(struct intel_gmbus), - GFP_KERNEL); - if (dev_priv->gmbus == NULL) - return -ENOMEM; - - for (i = 0; i < GMBUS_NUM_PORTS; i++) { - struct intel_gmbus *bus = &dev_priv->gmbus[i]; - - bus->adapter.owner = THIS_MODULE; - bus->adapter.class = I2C_CLASS_DDC; - snprintf(bus->adapter.name, - sizeof(bus->adapter.name), - "gma500 gmbus %s", - names[i]); - - bus->adapter.dev.parent = &dev->pdev->dev; - bus->adapter.algo_data = dev_priv; - - bus->adapter.algo = &gmbus_algorithm; - ret = i2c_add_adapter(&bus->adapter); - if (ret) - goto err; - - /* By default use a conservative clock rate */ - bus->reg0 = i | GMBUS_RATE_100KHZ; - - /* XXX force bit banging until GMBUS is fully debugged */ - bus->force_bit = intel_gpio_create(dev_priv, i); - } - - gma_intel_i2c_reset(dev_priv->dev); - - return 0; - -err: - while (--i) { - struct intel_gmbus *bus = &dev_priv->gmbus[i]; - i2c_del_adapter(&bus->adapter); - } - kfree(dev_priv->gmbus); - dev_priv->gmbus = NULL; - return ret; -} - -void gma_intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed) -{ - struct intel_gmbus *bus = to_intel_gmbus(adapter); - - /* speed: - * 0x0 = 100 KHz - * 0x1 = 50 KHz - * 0x2 = 400 KHz - * 0x3 = 1000 Khz - */ - bus->reg0 = (bus->reg0 & ~(0x3 << 8)) | (speed << 8); -} - -void gma_intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) -{ - struct intel_gmbus *bus = to_intel_gmbus(adapter); - - if (force_bit) { - if (bus->force_bit == NULL) { - struct drm_psb_private *dev_priv = adapter->algo_data; - bus->force_bit = intel_gpio_create(dev_priv, - bus->reg0 & 0xff); - } - } else { - if (bus->force_bit) { - i2c_del_adapter(bus->force_bit); - kfree(bus->force_bit); - bus->force_bit = NULL; - } - } -} - -void gma_intel_teardown_gmbus(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - int i; - - if (dev_priv->gmbus == NULL) - return; - - for (i = 0; i < GMBUS_NUM_PORTS; i++) { - struct intel_gmbus *bus = &dev_priv->gmbus[i]; - if (bus->force_bit) { - i2c_del_adapter(bus->force_bit); - kfree(bus->force_bit); - } - i2c_del_adapter(&bus->adapter); - } - - kfree(dev_priv->gmbus); - dev_priv->gmbus = NULL; -} diff --git a/drivers/gpu/drm/gma500/intel_i2c.c b/drivers/gpu/drm/gma500/intel_i2c.c deleted file mode 100644 index 57514ec..0000000 --- a/drivers/gpu/drm/gma500/intel_i2c.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright © 2006-2007 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: - * Eric Anholt - */ -#include -#include - -#include "psb_drv.h" -#include "psb_intel_reg.h" - -/* - * Intel GPIO access functions - */ - -#define I2C_RISEFALL_TIME 20 - -static int get_clock(void *data) -{ - struct psb_intel_i2c_chan *chan = data; - struct drm_device *dev = chan->drm_dev; - u32 val; - - val = REG_READ(chan->reg); - return (val & GPIO_CLOCK_VAL_IN) != 0; -} - -static int get_data(void *data) -{ - struct psb_intel_i2c_chan *chan = data; - struct drm_device *dev = chan->drm_dev; - u32 val; - - val = REG_READ(chan->reg); - return (val & GPIO_DATA_VAL_IN) != 0; -} - -static void set_clock(void *data, int state_high) -{ - struct psb_intel_i2c_chan *chan = data; - struct drm_device *dev = chan->drm_dev; - u32 reserved = 0, clock_bits; - - /* On most chips, these bits must be preserved in software. */ - reserved = - REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | - GPIO_CLOCK_PULLUP_DISABLE); - - if (state_high) - clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; - else - clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | - GPIO_CLOCK_VAL_MASK; - REG_WRITE(chan->reg, reserved | clock_bits); - udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ -} - -static void set_data(void *data, int state_high) -{ - struct psb_intel_i2c_chan *chan = data; - struct drm_device *dev = chan->drm_dev; - u32 reserved = 0, data_bits; - - /* On most chips, these bits must be preserved in software. */ - reserved = - REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | - GPIO_CLOCK_PULLUP_DISABLE); - - if (state_high) - data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; - else - data_bits = - GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | - GPIO_DATA_VAL_MASK; - - REG_WRITE(chan->reg, reserved | data_bits); - udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ -} - -/** - * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg - * @dev: DRM device - * @output: driver specific output device - * @reg: GPIO reg to use - * @name: name for this bus - * - * Creates and registers a new i2c bus with the Linux i2c layer, for use - * in output probing and control (e.g. DDC or SDVO control functions). - * - * Possible values for @reg include: - * %GPIOA - * %GPIOB - * %GPIOC - * %GPIOD - * %GPIOE - * %GPIOF - * %GPIOG - * %GPIOH - * see PRM for details on how these different busses are used. - */ -struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev, - const u32 reg, const char *name) -{ - struct psb_intel_i2c_chan *chan; - - chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL); - if (!chan) - goto out_free; - - chan->drm_dev = dev; - chan->reg = reg; - snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name); - chan->adapter.owner = THIS_MODULE; - chan->adapter.algo_data = &chan->algo; - chan->adapter.dev.parent = &dev->pdev->dev; - chan->algo.setsda = set_data; - chan->algo.setscl = set_clock; - chan->algo.getsda = get_data; - chan->algo.getscl = get_clock; - chan->algo.udelay = 20; - chan->algo.timeout = usecs_to_jiffies(2200); - chan->algo.data = chan; - - i2c_set_adapdata(&chan->adapter, chan); - - if (i2c_bit_add_bus(&chan->adapter)) - goto out_free; - - /* JJJ: raise SCL and SDA? */ - set_data(chan, 1); - set_clock(chan, 1); - udelay(20); - - return chan; - -out_free: - kfree(chan); - return NULL; -} - -/** - * psb_intel_i2c_destroy - unregister and free i2c bus resources - * @output: channel to free - * - * Unregister the adapter from the i2c layer, then free the structure. - */ -void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan) -{ - if (!chan) - return; - - i2c_del_adapter(&chan->adapter); - kfree(chan); -} diff --git a/drivers/gpu/drm/gma500/intel_opregion.c b/drivers/gpu/drm/gma500/intel_opregion.c deleted file mode 100644 index d946bc1..0000000 --- a/drivers/gpu/drm/gma500/intel_opregion.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * FIXME: resolve with the i915 version - */ - -#include "psb_drv.h" - -struct opregion_header { - u8 signature[16]; - u32 size; - u32 opregion_ver; - u8 bios_ver[32]; - u8 vbios_ver[16]; - u8 driver_ver[16]; - u32 mboxes; - u8 reserved[164]; -} __packed; - -struct opregion_apci { - /*FIXME: add it later*/ -} __packed; - -struct opregion_swsci { - /*FIXME: add it later*/ -} __packed; - -struct opregion_acpi { - /*FIXME: add it later*/ -} __packed; - -int gma_intel_opregion_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 opregion_phy; - void *base; - u32 *lid_state; - - dev_priv->lid_state = NULL; - - pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy); - if (opregion_phy == 0) - return -ENOTSUPP; - - base = ioremap(opregion_phy, 8*1024); - if (!base) - return -ENOMEM; - - lid_state = base + 0x01ac; - - dev_priv->lid_state = lid_state; - dev_priv->lid_last_state = readl(lid_state); - return 0; -} - -int gma_intel_opregion_exit(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - if (dev_priv->lid_state) - iounmap(dev_priv->lid_state); - return 0; -} diff --git a/drivers/gpu/drm/gma500/mdfld_device.c b/drivers/gpu/drm/gma500/mdfld_device.c deleted file mode 100644 index af65678..0000000 --- a/drivers/gpu/drm/gma500/mdfld_device.c +++ /dev/null @@ -1,691 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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 "psb_drv.h" -#include "mid_bios.h" -#include "mdfld_output.h" -#include "mdfld_dsi_output.h" -#include "tc35876x-dsi-lvds.h" - -#include - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - -#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF -#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ -#define BLC_PWM_FREQ_CALC_CONSTANT 32 -#define MHz 1000000 -#define BRIGHTNESS_MIN_LEVEL 1 -#define BRIGHTNESS_MAX_LEVEL 100 -#define BRIGHTNESS_MASK 0xFF -#define BLC_POLARITY_NORMAL 0 -#define BLC_POLARITY_INVERSE 1 -#define BLC_ADJUSTMENT_MAX 100 - -#define MDFLD_BLC_PWM_PRECISION_FACTOR 10 -#define MDFLD_BLC_MAX_PWM_REG_FREQ 0xFFFE -#define MDFLD_BLC_MIN_PWM_REG_FREQ 0x2 - -#define MDFLD_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) -#define MDFLD_BACKLIGHT_PWM_CTL_SHIFT (16) - -static struct backlight_device *mdfld_backlight_device; - -int mdfld_set_brightness(struct backlight_device *bd) -{ - struct drm_device *dev = - (struct drm_device *)bl_get_data(mdfld_backlight_device); - struct drm_psb_private *dev_priv = dev->dev_private; - int level = bd->props.brightness; - - DRM_DEBUG_DRIVER("backlight level set to %d\n", level); - - /* Perform value bounds checking */ - if (level < BRIGHTNESS_MIN_LEVEL) - level = BRIGHTNESS_MIN_LEVEL; - - if (gma_power_begin(dev, false)) { - u32 adjusted_level = 0; - - /* - * Adjust the backlight level with the percent in - * dev_priv->blc_adj2 - */ - adjusted_level = level * dev_priv->blc_adj2; - adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX; - dev_priv->brightness_adjusted = adjusted_level; - - if (mdfld_get_panel_type(dev, 0) == TC35876X) { - if (dev_priv->dpi_panel_on[0] || - dev_priv->dpi_panel_on[2]) - tc35876x_brightness_control(dev, - dev_priv->brightness_adjusted); - } else { - if (dev_priv->dpi_panel_on[0]) - mdfld_dsi_brightness_control(dev, 0, - dev_priv->brightness_adjusted); - } - - if (dev_priv->dpi_panel_on[2]) - mdfld_dsi_brightness_control(dev, 2, - dev_priv->brightness_adjusted); - gma_power_end(dev); - } - - /* cache the brightness for later use */ - dev_priv->brightness = level; - return 0; -} - -static int mdfld_get_brightness(struct backlight_device *bd) -{ - struct drm_device *dev = - (struct drm_device *)bl_get_data(mdfld_backlight_device); - struct drm_psb_private *dev_priv = dev->dev_private; - - DRM_DEBUG_DRIVER("brightness = 0x%x \n", dev_priv->brightness); - - /* return locally cached var instead of HW read (due to DPST etc.) */ - return dev_priv->brightness; -} - -static const struct backlight_ops mdfld_ops = { - .get_brightness = mdfld_get_brightness, - .update_status = mdfld_set_brightness, -}; - -static int device_backlight_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = (struct drm_psb_private *) - dev->dev_private; - - dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX; - dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX; - - return 0; -} - -static int mdfld_backlight_init(struct drm_device *dev) -{ - struct backlight_properties props; - int ret = 0; - - memset(&props, 0, sizeof(struct backlight_properties)); - props.max_brightness = BRIGHTNESS_MAX_LEVEL; - props.type = BACKLIGHT_PLATFORM; - mdfld_backlight_device = backlight_device_register("mdfld-bl", - NULL, (void *)dev, &mdfld_ops, &props); - - if (IS_ERR(mdfld_backlight_device)) - return PTR_ERR(mdfld_backlight_device); - - ret = device_backlight_init(dev); - if (ret) - return ret; - - mdfld_backlight_device->props.brightness = BRIGHTNESS_MAX_LEVEL; - mdfld_backlight_device->props.max_brightness = BRIGHTNESS_MAX_LEVEL; - backlight_update_status(mdfld_backlight_device); - return 0; -} -#endif - -struct backlight_device *mdfld_get_backlight_device(void) -{ -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - return mdfld_backlight_device; -#else - return NULL; -#endif -} - -/* - * mdfld_save_display_registers - * - * Description: We are going to suspend so save current display - * register state. - * - * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio - */ -static int mdfld_save_display_registers(struct drm_device *dev, int pipe) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct medfield_state *regs = &dev_priv->regs.mdfld; - int i; - - /* register */ - u32 dpll_reg = MRST_DPLL_A; - u32 fp_reg = MRST_FPA0; - u32 pipeconf_reg = PIPEACONF; - u32 htot_reg = HTOTAL_A; - u32 hblank_reg = HBLANK_A; - u32 hsync_reg = HSYNC_A; - u32 vtot_reg = VTOTAL_A; - u32 vblank_reg = VBLANK_A; - u32 vsync_reg = VSYNC_A; - u32 pipesrc_reg = PIPEASRC; - u32 dspstride_reg = DSPASTRIDE; - u32 dsplinoff_reg = DSPALINOFF; - u32 dsptileoff_reg = DSPATILEOFF; - u32 dspsize_reg = DSPASIZE; - u32 dsppos_reg = DSPAPOS; - u32 dspsurf_reg = DSPASURF; - u32 mipi_reg = MIPI; - u32 dspcntr_reg = DSPACNTR; - u32 dspstatus_reg = PIPEASTAT; - u32 palette_reg = PALETTE_A; - - /* pointer to values */ - u32 *dpll_val = ®s->saveDPLL_A; - u32 *fp_val = ®s->saveFPA0; - u32 *pipeconf_val = ®s->savePIPEACONF; - u32 *htot_val = ®s->saveHTOTAL_A; - u32 *hblank_val = ®s->saveHBLANK_A; - u32 *hsync_val = ®s->saveHSYNC_A; - u32 *vtot_val = ®s->saveVTOTAL_A; - u32 *vblank_val = ®s->saveVBLANK_A; - u32 *vsync_val = ®s->saveVSYNC_A; - u32 *pipesrc_val = ®s->savePIPEASRC; - u32 *dspstride_val = ®s->saveDSPASTRIDE; - u32 *dsplinoff_val = ®s->saveDSPALINOFF; - u32 *dsptileoff_val = ®s->saveDSPATILEOFF; - u32 *dspsize_val = ®s->saveDSPASIZE; - u32 *dsppos_val = ®s->saveDSPAPOS; - u32 *dspsurf_val = ®s->saveDSPASURF; - u32 *mipi_val = ®s->saveMIPI; - u32 *dspcntr_val = ®s->saveDSPACNTR; - u32 *dspstatus_val = ®s->saveDSPASTATUS; - u32 *palette_val = regs->save_palette_a; - - switch (pipe) { - case 0: - break; - case 1: - /* regester */ - dpll_reg = MDFLD_DPLL_B; - fp_reg = MDFLD_DPLL_DIV0; - pipeconf_reg = PIPEBCONF; - htot_reg = HTOTAL_B; - hblank_reg = HBLANK_B; - hsync_reg = HSYNC_B; - vtot_reg = VTOTAL_B; - vblank_reg = VBLANK_B; - vsync_reg = VSYNC_B; - pipesrc_reg = PIPEBSRC; - dspstride_reg = DSPBSTRIDE; - dsplinoff_reg = DSPBLINOFF; - dsptileoff_reg = DSPBTILEOFF; - dspsize_reg = DSPBSIZE; - dsppos_reg = DSPBPOS; - dspsurf_reg = DSPBSURF; - dspcntr_reg = DSPBCNTR; - dspstatus_reg = PIPEBSTAT; - palette_reg = PALETTE_B; - - /* values */ - dpll_val = ®s->saveDPLL_B; - fp_val = ®s->saveFPB0; - pipeconf_val = ®s->savePIPEBCONF; - htot_val = ®s->saveHTOTAL_B; - hblank_val = ®s->saveHBLANK_B; - hsync_val = ®s->saveHSYNC_B; - vtot_val = ®s->saveVTOTAL_B; - vblank_val = ®s->saveVBLANK_B; - vsync_val = ®s->saveVSYNC_B; - pipesrc_val = ®s->savePIPEBSRC; - dspstride_val = ®s->saveDSPBSTRIDE; - dsplinoff_val = ®s->saveDSPBLINOFF; - dsptileoff_val = ®s->saveDSPBTILEOFF; - dspsize_val = ®s->saveDSPBSIZE; - dsppos_val = ®s->saveDSPBPOS; - dspsurf_val = ®s->saveDSPBSURF; - dspcntr_val = ®s->saveDSPBCNTR; - dspstatus_val = ®s->saveDSPBSTATUS; - palette_val = regs->save_palette_b; - break; - case 2: - /* register */ - pipeconf_reg = PIPECCONF; - htot_reg = HTOTAL_C; - hblank_reg = HBLANK_C; - hsync_reg = HSYNC_C; - vtot_reg = VTOTAL_C; - vblank_reg = VBLANK_C; - vsync_reg = VSYNC_C; - pipesrc_reg = PIPECSRC; - dspstride_reg = DSPCSTRIDE; - dsplinoff_reg = DSPCLINOFF; - dsptileoff_reg = DSPCTILEOFF; - dspsize_reg = DSPCSIZE; - dsppos_reg = DSPCPOS; - dspsurf_reg = DSPCSURF; - mipi_reg = MIPI_C; - dspcntr_reg = DSPCCNTR; - dspstatus_reg = PIPECSTAT; - palette_reg = PALETTE_C; - - /* pointer to values */ - pipeconf_val = ®s->savePIPECCONF; - htot_val = ®s->saveHTOTAL_C; - hblank_val = ®s->saveHBLANK_C; - hsync_val = ®s->saveHSYNC_C; - vtot_val = ®s->saveVTOTAL_C; - vblank_val = ®s->saveVBLANK_C; - vsync_val = ®s->saveVSYNC_C; - pipesrc_val = ®s->savePIPECSRC; - dspstride_val = ®s->saveDSPCSTRIDE; - dsplinoff_val = ®s->saveDSPCLINOFF; - dsptileoff_val = ®s->saveDSPCTILEOFF; - dspsize_val = ®s->saveDSPCSIZE; - dsppos_val = ®s->saveDSPCPOS; - dspsurf_val = ®s->saveDSPCSURF; - mipi_val = ®s->saveMIPI_C; - dspcntr_val = ®s->saveDSPCCNTR; - dspstatus_val = ®s->saveDSPCSTATUS; - palette_val = regs->save_palette_c; - break; - default: - DRM_ERROR("%s, invalid pipe number.\n", __func__); - return -EINVAL; - } - - /* Pipe & plane A info */ - *dpll_val = PSB_RVDC32(dpll_reg); - *fp_val = PSB_RVDC32(fp_reg); - *pipeconf_val = PSB_RVDC32(pipeconf_reg); - *htot_val = PSB_RVDC32(htot_reg); - *hblank_val = PSB_RVDC32(hblank_reg); - *hsync_val = PSB_RVDC32(hsync_reg); - *vtot_val = PSB_RVDC32(vtot_reg); - *vblank_val = PSB_RVDC32(vblank_reg); - *vsync_val = PSB_RVDC32(vsync_reg); - *pipesrc_val = PSB_RVDC32(pipesrc_reg); - *dspstride_val = PSB_RVDC32(dspstride_reg); - *dsplinoff_val = PSB_RVDC32(dsplinoff_reg); - *dsptileoff_val = PSB_RVDC32(dsptileoff_reg); - *dspsize_val = PSB_RVDC32(dspsize_reg); - *dsppos_val = PSB_RVDC32(dsppos_reg); - *dspsurf_val = PSB_RVDC32(dspsurf_reg); - *dspcntr_val = PSB_RVDC32(dspcntr_reg); - *dspstatus_val = PSB_RVDC32(dspstatus_reg); - - /*save palette (gamma) */ - for (i = 0; i < 256; i++) - palette_val[i] = PSB_RVDC32(palette_reg + (i << 2)); - - if (pipe == 1) { - regs->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL); - regs->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS); - - regs->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL); - regs->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL); - return 0; - } - - *mipi_val = PSB_RVDC32(mipi_reg); - return 0; -} - -/* - * mdfld_restore_display_registers - * - * Description: We are going to resume so restore display register state. - * - * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio - */ -static int mdfld_restore_display_registers(struct drm_device *dev, int pipe) -{ - /* To get panel out of ULPS mode. */ - u32 temp = 0; - u32 device_ready_reg = DEVICE_READY_REG; - struct drm_psb_private *dev_priv = dev->dev_private; - struct mdfld_dsi_config *dsi_config = NULL; - struct medfield_state *regs = &dev_priv->regs.mdfld; - u32 i = 0; - u32 dpll = 0; - u32 timeout = 0; - - /* regester */ - u32 dpll_reg = MRST_DPLL_A; - u32 fp_reg = MRST_FPA0; - u32 pipeconf_reg = PIPEACONF; - u32 htot_reg = HTOTAL_A; - u32 hblank_reg = HBLANK_A; - u32 hsync_reg = HSYNC_A; - u32 vtot_reg = VTOTAL_A; - u32 vblank_reg = VBLANK_A; - u32 vsync_reg = VSYNC_A; - u32 pipesrc_reg = PIPEASRC; - u32 dspstride_reg = DSPASTRIDE; - u32 dsplinoff_reg = DSPALINOFF; - u32 dsptileoff_reg = DSPATILEOFF; - u32 dspsize_reg = DSPASIZE; - u32 dsppos_reg = DSPAPOS; - u32 dspsurf_reg = DSPASURF; - u32 dspstatus_reg = PIPEASTAT; - u32 mipi_reg = MIPI; - u32 dspcntr_reg = DSPACNTR; - u32 palette_reg = PALETTE_A; - - /* values */ - u32 dpll_val = regs->saveDPLL_A & ~DPLL_VCO_ENABLE; - u32 fp_val = regs->saveFPA0; - u32 pipeconf_val = regs->savePIPEACONF; - u32 htot_val = regs->saveHTOTAL_A; - u32 hblank_val = regs->saveHBLANK_A; - u32 hsync_val = regs->saveHSYNC_A; - u32 vtot_val = regs->saveVTOTAL_A; - u32 vblank_val = regs->saveVBLANK_A; - u32 vsync_val = regs->saveVSYNC_A; - u32 pipesrc_val = regs->savePIPEASRC; - u32 dspstride_val = regs->saveDSPASTRIDE; - u32 dsplinoff_val = regs->saveDSPALINOFF; - u32 dsptileoff_val = regs->saveDSPATILEOFF; - u32 dspsize_val = regs->saveDSPASIZE; - u32 dsppos_val = regs->saveDSPAPOS; - u32 dspsurf_val = regs->saveDSPASURF; - u32 dspstatus_val = regs->saveDSPASTATUS; - u32 mipi_val = regs->saveMIPI; - u32 dspcntr_val = regs->saveDSPACNTR; - u32 *palette_val = regs->save_palette_a; - - switch (pipe) { - case 0: - dsi_config = dev_priv->dsi_configs[0]; - break; - case 1: - /* regester */ - dpll_reg = MDFLD_DPLL_B; - fp_reg = MDFLD_DPLL_DIV0; - pipeconf_reg = PIPEBCONF; - htot_reg = HTOTAL_B; - hblank_reg = HBLANK_B; - hsync_reg = HSYNC_B; - vtot_reg = VTOTAL_B; - vblank_reg = VBLANK_B; - vsync_reg = VSYNC_B; - pipesrc_reg = PIPEBSRC; - dspstride_reg = DSPBSTRIDE; - dsplinoff_reg = DSPBLINOFF; - dsptileoff_reg = DSPBTILEOFF; - dspsize_reg = DSPBSIZE; - dsppos_reg = DSPBPOS; - dspsurf_reg = DSPBSURF; - dspcntr_reg = DSPBCNTR; - dspstatus_reg = PIPEBSTAT; - palette_reg = PALETTE_B; - - /* values */ - dpll_val = regs->saveDPLL_B & ~DPLL_VCO_ENABLE; - fp_val = regs->saveFPB0; - pipeconf_val = regs->savePIPEBCONF; - htot_val = regs->saveHTOTAL_B; - hblank_val = regs->saveHBLANK_B; - hsync_val = regs->saveHSYNC_B; - vtot_val = regs->saveVTOTAL_B; - vblank_val = regs->saveVBLANK_B; - vsync_val = regs->saveVSYNC_B; - pipesrc_val = regs->savePIPEBSRC; - dspstride_val = regs->saveDSPBSTRIDE; - dsplinoff_val = regs->saveDSPBLINOFF; - dsptileoff_val = regs->saveDSPBTILEOFF; - dspsize_val = regs->saveDSPBSIZE; - dsppos_val = regs->saveDSPBPOS; - dspsurf_val = regs->saveDSPBSURF; - dspcntr_val = regs->saveDSPBCNTR; - dspstatus_val = regs->saveDSPBSTATUS; - palette_val = regs->save_palette_b; - break; - case 2: - /* regester */ - pipeconf_reg = PIPECCONF; - htot_reg = HTOTAL_C; - hblank_reg = HBLANK_C; - hsync_reg = HSYNC_C; - vtot_reg = VTOTAL_C; - vblank_reg = VBLANK_C; - vsync_reg = VSYNC_C; - pipesrc_reg = PIPECSRC; - dspstride_reg = DSPCSTRIDE; - dsplinoff_reg = DSPCLINOFF; - dsptileoff_reg = DSPCTILEOFF; - dspsize_reg = DSPCSIZE; - dsppos_reg = DSPCPOS; - dspsurf_reg = DSPCSURF; - mipi_reg = MIPI_C; - dspcntr_reg = DSPCCNTR; - dspstatus_reg = PIPECSTAT; - palette_reg = PALETTE_C; - - /* values */ - pipeconf_val = regs->savePIPECCONF; - htot_val = regs->saveHTOTAL_C; - hblank_val = regs->saveHBLANK_C; - hsync_val = regs->saveHSYNC_C; - vtot_val = regs->saveVTOTAL_C; - vblank_val = regs->saveVBLANK_C; - vsync_val = regs->saveVSYNC_C; - pipesrc_val = regs->savePIPECSRC; - dspstride_val = regs->saveDSPCSTRIDE; - dsplinoff_val = regs->saveDSPCLINOFF; - dsptileoff_val = regs->saveDSPCTILEOFF; - dspsize_val = regs->saveDSPCSIZE; - dsppos_val = regs->saveDSPCPOS; - dspsurf_val = regs->saveDSPCSURF; - mipi_val = regs->saveMIPI_C; - dspcntr_val = regs->saveDSPCCNTR; - dspstatus_val = regs->saveDSPCSTATUS; - palette_val = regs->save_palette_c; - - dsi_config = dev_priv->dsi_configs[1]; - break; - default: - DRM_ERROR("%s, invalid pipe number.\n", __func__); - return -EINVAL; - } - - /*make sure VGA plane is off. it initializes to on after reset!*/ - PSB_WVDC32(0x80000000, VGACNTRL); - - if (pipe == 1) { - PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg); - PSB_RVDC32(dpll_reg); - - PSB_WVDC32(fp_val, fp_reg); - } else { - - dpll = PSB_RVDC32(dpll_reg); - - if (!(dpll & DPLL_VCO_ENABLE)) { - - /* When ungating power of DPLL, needs to wait 0.5us - before enable the VCO */ - if (dpll & MDFLD_PWR_GATE_EN) { - dpll &= ~MDFLD_PWR_GATE_EN; - PSB_WVDC32(dpll, dpll_reg); - /* FIXME_MDFLD PO - change 500 to 1 after PO */ - udelay(500); - } - - PSB_WVDC32(fp_val, fp_reg); - PSB_WVDC32(dpll_val, dpll_reg); - /* FIXME_MDFLD PO - change 500 to 1 after PO */ - udelay(500); - - dpll_val |= DPLL_VCO_ENABLE; - PSB_WVDC32(dpll_val, dpll_reg); - PSB_RVDC32(dpll_reg); - - /* wait for DSI PLL to lock */ - while (timeout < 20000 && - !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { - udelay(150); - timeout++; - } - - if (timeout == 20000) { - DRM_ERROR("%s, can't lock DSIPLL.\n", - __func__); - return -EINVAL; - } - } - } - /* Restore mode */ - PSB_WVDC32(htot_val, htot_reg); - PSB_WVDC32(hblank_val, hblank_reg); - PSB_WVDC32(hsync_val, hsync_reg); - PSB_WVDC32(vtot_val, vtot_reg); - PSB_WVDC32(vblank_val, vblank_reg); - PSB_WVDC32(vsync_val, vsync_reg); - PSB_WVDC32(pipesrc_val, pipesrc_reg); - PSB_WVDC32(dspstatus_val, dspstatus_reg); - - /*set up the plane*/ - PSB_WVDC32(dspstride_val, dspstride_reg); - PSB_WVDC32(dsplinoff_val, dsplinoff_reg); - PSB_WVDC32(dsptileoff_val, dsptileoff_reg); - PSB_WVDC32(dspsize_val, dspsize_reg); - PSB_WVDC32(dsppos_val, dsppos_reg); - PSB_WVDC32(dspsurf_val, dspsurf_reg); - - if (pipe == 1) { - /* restore palette (gamma) */ - /*DRM_UDELAY(50000); */ - for (i = 0; i < 256; i++) - PSB_WVDC32(palette_val[i], palette_reg + (i << 2)); - - PSB_WVDC32(regs->savePFIT_CONTROL, PFIT_CONTROL); - PSB_WVDC32(regs->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); - - /*TODO: resume HDMI port */ - - /*TODO: resume pipe*/ - - /*enable the plane*/ - PSB_WVDC32(dspcntr_val & ~DISPLAY_PLANE_ENABLE, dspcntr_reg); - - return 0; - } - - /*set up pipe related registers*/ - PSB_WVDC32(mipi_val, mipi_reg); - - /*setup MIPI adapter + MIPI IP registers*/ - if (dsi_config) - mdfld_dsi_controller_init(dsi_config, pipe); - - if (in_atomic() || in_interrupt()) - mdelay(20); - else - msleep(20); - - /*enable the plane*/ - PSB_WVDC32(dspcntr_val, dspcntr_reg); - - if (in_atomic() || in_interrupt()) - mdelay(20); - else - msleep(20); - - /* LP Hold Release */ - temp = REG_READ(mipi_reg); - temp |= LP_OUTPUT_HOLD_RELEASE; - REG_WRITE(mipi_reg, temp); - mdelay(1); - - - /* Set DSI host to exit from Utra Low Power State */ - temp = REG_READ(device_ready_reg); - temp &= ~ULPS_MASK; - temp |= 0x3; - temp |= EXIT_ULPS_DEV_READY; - REG_WRITE(device_ready_reg, temp); - mdelay(1); - - temp = REG_READ(device_ready_reg); - temp &= ~ULPS_MASK; - temp |= EXITING_ULPS; - REG_WRITE(device_ready_reg, temp); - mdelay(1); - - /*enable the pipe*/ - PSB_WVDC32(pipeconf_val, pipeconf_reg); - - /* restore palette (gamma) */ - /*DRM_UDELAY(50000); */ - for (i = 0; i < 256; i++) - PSB_WVDC32(palette_val[i], palette_reg + (i << 2)); - - return 0; -} - -static int mdfld_save_registers(struct drm_device *dev) -{ - /* mdfld_save_cursor_overlay_registers(dev); */ - mdfld_save_display_registers(dev, 0); - mdfld_save_display_registers(dev, 2); - mdfld_disable_crtc(dev, 0); - mdfld_disable_crtc(dev, 2); - - return 0; -} - -static int mdfld_restore_registers(struct drm_device *dev) -{ - mdfld_restore_display_registers(dev, 2); - mdfld_restore_display_registers(dev, 0); - /* mdfld_restore_cursor_overlay_registers(dev); */ - - return 0; -} - -static int mdfld_power_down(struct drm_device *dev) -{ - /* FIXME */ - return 0; -} - -static int mdfld_power_up(struct drm_device *dev) -{ - /* FIXME */ - return 0; -} - -const struct psb_ops mdfld_chip_ops = { - .name = "mdfld", - .accel_2d = 0, - .pipes = 3, - .crtcs = 3, - .sgx_offset = MRST_SGX_OFFSET, - - .chip_setup = mid_chip_setup, - .crtc_helper = &mdfld_helper_funcs, - .crtc_funcs = &psb_intel_crtc_funcs, - - .output_init = mdfld_output_init, - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - .backlight_init = mdfld_backlight_init, -#endif - - .save_regs = mdfld_save_registers, - .restore_regs = mdfld_restore_registers, - .power_down = mdfld_power_down, - .power_up = mdfld_power_up, -}; diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c deleted file mode 100644 index d52358b..0000000 --- a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c +++ /dev/null @@ -1,1017 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * jim liu - * Jackie Li - */ - -#include "mdfld_dsi_dpi.h" -#include "mdfld_output.h" -#include "mdfld_dsi_pkg_sender.h" -#include "psb_drv.h" -#include "tc35876x-dsi-lvds.h" - -static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, - int pipe); - -static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe) -{ - u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe); - int timeout = 0; - - udelay(500); - - /* This will time out after approximately 2+ seconds */ - while ((timeout < 20000) && - (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) { - udelay(100); - timeout++; - } - - if (timeout == 20000) - DRM_INFO("MIPI: HS Data FIFO was never cleared!\n"); -} - -static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe) -{ - u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe); - int timeout = 0; - - udelay(500); - - /* This will time out after approximately 2+ seconds */ - while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) - & DSI_FIFO_GEN_HS_CTRL_FULL)) { - udelay(100); - timeout++; - } - if (timeout == 20000) - DRM_INFO("MIPI: HS CMD FIFO was never cleared!\n"); -} - -static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe) -{ - u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe); - int timeout = 0; - - udelay(500); - - /* This will time out after approximately 2+ seconds */ - while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) & - DPI_FIFO_EMPTY) != DPI_FIFO_EMPTY)) { - udelay(100); - timeout++; - } - - if (timeout == 20000) - DRM_ERROR("MIPI: DPI FIFO was never cleared\n"); -} - -static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe) -{ - u32 intr_stat_reg = MIPI_INTR_STAT_REG(pipe); - int timeout = 0; - - udelay(500); - - /* This will time out after approximately 2+ seconds */ - while ((timeout < 20000) && (!(REG_READ(intr_stat_reg) - & DSI_INTR_STATE_SPL_PKG_SENT))) { - udelay(100); - timeout++; - } - - if (timeout == 20000) - DRM_ERROR("MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n"); -} - -/* For TC35876X */ - -static void dsi_set_device_ready_state(struct drm_device *dev, int state, - int pipe) -{ - REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), !!state, 0, 0); -} - -static void dsi_set_pipe_plane_enable_state(struct drm_device *dev, - int state, int pipe) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 pipeconf_reg = PIPEACONF; - u32 dspcntr_reg = DSPACNTR; - - u32 dspcntr = dev_priv->dspcntr[pipe]; - u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; - - if (pipe) { - pipeconf_reg = PIPECCONF; - dspcntr_reg = DSPCCNTR; - } else - mipi &= (~0x03); - - if (state) { - /*Set up pipe */ - REG_WRITE(pipeconf_reg, BIT(31)); - - if (REG_BIT_WAIT(pipeconf_reg, 1, 30)) - dev_err(&dev->pdev->dev, "%s: Pipe enable timeout\n", - __func__); - - /*Set up display plane */ - REG_WRITE(dspcntr_reg, dspcntr); - } else { - u32 dspbase_reg = pipe ? MDFLD_DSPCBASE : MRST_DSPABASE; - - /* Put DSI lanes to ULPS to disable pipe */ - REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 2, 2, 1); - REG_READ(MIPI_DEVICE_READY_REG(pipe)); /* posted write? */ - - /* LP Hold */ - REG_FLD_MOD(MIPI_PORT_CONTROL(pipe), 0, 16, 16); - REG_READ(MIPI_PORT_CONTROL(pipe)); /* posted write? */ - - /* Disable display plane */ - REG_FLD_MOD(dspcntr_reg, 0, 31, 31); - - /* Flush the plane changes ??? posted write? */ - REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); - REG_READ(dspbase_reg); - - /* Disable PIPE */ - REG_FLD_MOD(pipeconf_reg, 0, 31, 31); - - if (REG_BIT_WAIT(pipeconf_reg, 0, 30)) - dev_err(&dev->pdev->dev, "%s: Pipe disable timeout\n", - __func__); - - if (REG_BIT_WAIT(MIPI_GEN_FIFO_STAT_REG(pipe), 1, 28)) - dev_err(&dev->pdev->dev, "%s: FIFO not empty\n", - __func__); - } -} - -static void mdfld_dsi_configure_down(struct mdfld_dsi_encoder *dsi_encoder, - int pipe) -{ - struct mdfld_dsi_dpi_output *dpi_output = - MDFLD_DSI_DPI_OUTPUT(dsi_encoder); - struct mdfld_dsi_config *dsi_config = - mdfld_dsi_encoder_get_config(dsi_encoder); - struct drm_device *dev = dsi_config->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - - if (!dev_priv->dpi_panel_on[pipe]) { - dev_err(dev->dev, "DPI panel is already off\n"); - return; - } - tc35876x_toshiba_bridge_panel_off(dev); - tc35876x_set_bridge_reset_state(dev, 1); - dsi_set_pipe_plane_enable_state(dev, 0, pipe); - mdfld_dsi_dpi_shut_down(dpi_output, pipe); - dsi_set_device_ready_state(dev, 0, pipe); -} - -static void mdfld_dsi_configure_up(struct mdfld_dsi_encoder *dsi_encoder, - int pipe) -{ - struct mdfld_dsi_dpi_output *dpi_output = - MDFLD_DSI_DPI_OUTPUT(dsi_encoder); - struct mdfld_dsi_config *dsi_config = - mdfld_dsi_encoder_get_config(dsi_encoder); - struct drm_device *dev = dsi_config->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - - if (dev_priv->dpi_panel_on[pipe]) { - dev_err(dev->dev, "DPI panel is already on\n"); - return; - } - - /* For resume path sequence */ - mdfld_dsi_dpi_shut_down(dpi_output, pipe); - dsi_set_device_ready_state(dev, 0, pipe); - - dsi_set_device_ready_state(dev, 1, pipe); - tc35876x_set_bridge_reset_state(dev, 0); - tc35876x_configure_lvds_bridge(dev); - mdfld_dsi_dpi_turn_on(dpi_output, pipe); /* Send turn on command */ - dsi_set_pipe_plane_enable_state(dev, 1, pipe); -} -/* End for TC35876X */ - -/* ************************************************************************* *\ - * FUNCTION: mdfld_dsi_tpo_ic_init - * - * DESCRIPTION: This function is called only by mrst_dsi_mode_set and - * restore_display_registers. since this function does not - * acquire the mutex, it is important that the calling function - * does! -\* ************************************************************************* */ -static void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe) -{ - struct drm_device *dev = dsi_config->dev; - u32 dcsChannelNumber = dsi_config->channel_num; - u32 gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe); - u32 gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe); - u32 gen_ctrl_val = GEN_LONG_WRITE; - - DRM_INFO("Enter mrst init TPO MIPI display.\n"); - - gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS; - - /* Flip page order */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x00008036); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS)); - - /* 0xF0 */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x005a5af0); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); - - /* Write protection key */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x005a5af1); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); - - /* 0xFC */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x005a5afc); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); - - /* 0xB7 */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x770000b7); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x00000044); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS)); - - /* 0xB6 */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x000a0ab6); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); - - /* 0xF2 */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x081010f2); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x4a070708); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x000000c5); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); - - /* 0xF8 */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x024003f8); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x01030a04); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x0e020220); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x00000004); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS)); - - /* 0xE2 */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x398fc3e2); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x0000916f); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS)); - - /* 0xB0 */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x000000b0); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS)); - - /* 0xF4 */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x240242f4); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x78ee2002); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x2a071050); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x507fee10); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x10300710); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS)); - - /* 0xBA */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x19fe07ba); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x101c0a31); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x00000010); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); - - /* 0xBB */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x28ff07bb); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x24280a31); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x00000034); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); - - /* 0xFB */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x535d05fb); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x1b1a2130); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x221e180e); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x131d2120); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x535d0508); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x1c1a2131); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x231f160d); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x111b2220); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x535c2008); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x1f1d2433); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x2c251a10); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x2c34372d); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x00000023); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS)); - - /* 0xFA */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x525c0bfa); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x1c1c232f); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x2623190e); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x18212625); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x545d0d0e); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x1e1d2333); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x26231a10); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x1a222725); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x545d280f); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x21202635); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x31292013); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x31393d33); - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x00000029); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS)); - - /* Set DM */ - mdfld_wait_for_HS_DATA_FIFO(dev, pipe); - REG_WRITE(gen_data_reg, 0x000100f7); - mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); - REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); -} - -static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count, - int num_lane, int bpp) -{ - return (u16)((pixel_clock_count * bpp) / (num_lane * 8)); -} - -/* - * Calculate the dpi time basing on a given drm mode @mode - * return 0 on success. - * FIXME: I was using proposed mode value for calculation, may need to - * use crtc mode values later - */ -int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode, - struct mdfld_dsi_dpi_timing *dpi_timing, - int num_lane, int bpp) -{ - int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive; - int pclk_vsync, pclk_vfp, pclk_vbp; - - pclk_hactive = mode->hdisplay; - pclk_hfp = mode->hsync_start - mode->hdisplay; - pclk_hsync = mode->hsync_end - mode->hsync_start; - pclk_hbp = mode->htotal - mode->hsync_end; - - pclk_vfp = mode->vsync_start - mode->vdisplay; - pclk_vsync = mode->vsync_end - mode->vsync_start; - pclk_vbp = mode->vtotal - mode->vsync_end; - - /* - * byte clock counts were calculated by following formula - * bclock_count = pclk_count * bpp / num_lane / 8 - */ - dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count( - pclk_hsync, num_lane, bpp); - dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count( - pclk_hbp, num_lane, bpp); - dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count( - pclk_hfp, num_lane, bpp); - dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count( - pclk_hactive, num_lane, bpp); - dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count( - pclk_vsync, num_lane, bpp); - dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count( - pclk_vbp, num_lane, bpp); - dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count( - pclk_vfp, num_lane, bpp); - - return 0; -} - -void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, - int pipe) -{ - struct drm_device *dev = dsi_config->dev; - int lane_count = dsi_config->lane_count; - struct mdfld_dsi_dpi_timing dpi_timing; - struct drm_display_mode *mode = dsi_config->mode; - u32 val; - - /*un-ready device*/ - REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 0, 0, 0); - - /*init dsi adapter before kicking off*/ - REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018); - - /*enable all interrupts*/ - REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff); - - /*set up func_prg*/ - val = lane_count; - val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET; - - switch (dsi_config->bpp) { - case 16: - val |= DSI_DPI_COLOR_FORMAT_RGB565; - break; - case 18: - val |= DSI_DPI_COLOR_FORMAT_RGB666; - break; - case 24: - val |= DSI_DPI_COLOR_FORMAT_RGB888; - break; - default: - DRM_ERROR("unsupported color format, bpp = %d\n", - dsi_config->bpp); - } - REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), val); - - REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), - (mode->vtotal * mode->htotal * dsi_config->bpp / - (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK); - REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), - 0xffff & DSI_LP_RX_TIMEOUT_MASK); - - /*max value: 20 clock cycles of txclkesc*/ - REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), - 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK); - - /*min 21 txclkesc, max: ffffh*/ - REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), - 0xffff & DSI_RESET_TIMER_MASK); - - REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe), - mode->vdisplay << 16 | mode->hdisplay); - - /*set DPI timing registers*/ - mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, - dsi_config->lane_count, dsi_config->bpp); - - REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe), - dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); - REG_WRITE(MIPI_HBP_COUNT_REG(pipe), - dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); - REG_WRITE(MIPI_HFP_COUNT_REG(pipe), - dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); - REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe), - dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); - REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe), - dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); - REG_WRITE(MIPI_VBP_COUNT_REG(pipe), - dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); - REG_WRITE(MIPI_VFP_COUNT_REG(pipe), - dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); - - REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x46); - - /*min: 7d0 max: 4e20*/ - REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0x000007d0); - - /*set up video mode*/ - val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE; - REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), val); - - REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000); - - REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004); - - /*TODO: figure out how to setup these registers*/ - if (mdfld_get_panel_type(dev, pipe) == TC35876X) - REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008); - else - REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150c3408); - - REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14); - - if (mdfld_get_panel_type(dev, pipe) == TC35876X) - tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */ - - /*set device ready*/ - REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 1, 0, 0); -} - -void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe) -{ - struct drm_device *dev = output->dev; - - /* clear special packet sent bit */ - if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT) - REG_WRITE(MIPI_INTR_STAT_REG(pipe), - DSI_INTR_STATE_SPL_PKG_SENT); - - /*send turn on package*/ - REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_TURN_ON); - - /*wait for SPL_PKG_SENT interrupt*/ - mdfld_wait_for_SPL_PKG_SENT(dev, pipe); - - if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT) - REG_WRITE(MIPI_INTR_STAT_REG(pipe), - DSI_INTR_STATE_SPL_PKG_SENT); - - output->panel_on = 1; - - /* FIXME the following is disabled to WA the X slow start issue - for TMD panel - if (pipe == 2) - dev_priv->dpi_panel_on2 = true; - else if (pipe == 0) - dev_priv->dpi_panel_on = true; */ -} - -static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, - int pipe) -{ - struct drm_device *dev = output->dev; - - /*if output is on, or mode setting didn't happen, ignore this*/ - if ((!output->panel_on) || output->first_boot) { - output->first_boot = 0; - return; - } - - /* Wait for dpi fifo to empty */ - mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe); - - /* Clear the special packet interrupt bit if set */ - if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT) - REG_WRITE(MIPI_INTR_STAT_REG(pipe), - DSI_INTR_STATE_SPL_PKG_SENT); - - if (REG_READ(MIPI_DPI_CONTROL_REG(pipe)) == DSI_DPI_CTRL_HS_SHUTDOWN) - goto shutdown_out; - - REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_SHUTDOWN); - -shutdown_out: - output->panel_on = 0; - output->first_boot = 0; - - /* FIXME the following is disabled to WA the X slow start issue - for TMD panel - if (pipe == 2) - dev_priv->dpi_panel_on2 = false; - else if (pipe == 0) - dev_priv->dpi_panel_on = false; */ -} - -static void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) -{ - struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); - struct mdfld_dsi_dpi_output *dpi_output = - MDFLD_DSI_DPI_OUTPUT(dsi_encoder); - struct mdfld_dsi_config *dsi_config = - mdfld_dsi_encoder_get_config(dsi_encoder); - int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); - struct drm_device *dev = dsi_config->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - - /*start up display island if it was shutdown*/ - if (!gma_power_begin(dev, true)) - return; - - if (on) { - if (mdfld_get_panel_type(dev, pipe) == TMD_VID) - mdfld_dsi_dpi_turn_on(dpi_output, pipe); - else if (mdfld_get_panel_type(dev, pipe) == TC35876X) - mdfld_dsi_configure_up(dsi_encoder, pipe); - else { - /*enable mipi port*/ - REG_WRITE(MIPI_PORT_CONTROL(pipe), - REG_READ(MIPI_PORT_CONTROL(pipe)) | BIT(31)); - REG_READ(MIPI_PORT_CONTROL(pipe)); - - mdfld_dsi_dpi_turn_on(dpi_output, pipe); - mdfld_dsi_tpo_ic_init(dsi_config, pipe); - } - dev_priv->dpi_panel_on[pipe] = true; - } else { - if (mdfld_get_panel_type(dev, pipe) == TMD_VID) - mdfld_dsi_dpi_shut_down(dpi_output, pipe); - else if (mdfld_get_panel_type(dev, pipe) == TC35876X) - mdfld_dsi_configure_down(dsi_encoder, pipe); - else { - mdfld_dsi_dpi_shut_down(dpi_output, pipe); - - /*disable mipi port*/ - REG_WRITE(MIPI_PORT_CONTROL(pipe), - REG_READ(MIPI_PORT_CONTROL(pipe)) & ~BIT(31)); - REG_READ(MIPI_PORT_CONTROL(pipe)); - } - dev_priv->dpi_panel_on[pipe] = false; - } - gma_power_end(dev); -} - -void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode) -{ - mdfld_dsi_dpi_set_power(encoder, mode == DRM_MODE_DPMS_ON); -} - -bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); - struct mdfld_dsi_config *dsi_config = - mdfld_dsi_encoder_get_config(dsi_encoder); - struct drm_display_mode *fixed_mode = dsi_config->fixed_mode; - - if (fixed_mode) { - adjusted_mode->hdisplay = fixed_mode->hdisplay; - adjusted_mode->hsync_start = fixed_mode->hsync_start; - adjusted_mode->hsync_end = fixed_mode->hsync_end; - adjusted_mode->htotal = fixed_mode->htotal; - adjusted_mode->vdisplay = fixed_mode->vdisplay; - adjusted_mode->vsync_start = fixed_mode->vsync_start; - adjusted_mode->vsync_end = fixed_mode->vsync_end; - adjusted_mode->vtotal = fixed_mode->vtotal; - adjusted_mode->clock = fixed_mode->clock; - drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); - } - return true; -} - -void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder) -{ - mdfld_dsi_dpi_set_power(encoder, false); -} - -void mdfld_dsi_dpi_commit(struct drm_encoder *encoder) -{ - mdfld_dsi_dpi_set_power(encoder, true); -} - -/* For TC35876X */ -/* This functionality was implemented in FW in iCDK */ -/* But removed in DV0 and later. So need to add here. */ -static void mipi_set_properties(struct mdfld_dsi_config *dsi_config, int pipe) -{ - struct drm_device *dev = dsi_config->dev; - - REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018); - REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff); - REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), 0xffffff); - REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffffff); - REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x14); - REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0xff); - REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x25); - REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0xf0); - REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000); - REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004); - REG_WRITE(MIPI_DBI_BW_CTRL_REG(pipe), 0x00000820); - REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14); -} - -static void mdfld_mipi_set_video_timing(struct mdfld_dsi_config *dsi_config, - int pipe) -{ - struct drm_device *dev = dsi_config->dev; - struct mdfld_dsi_dpi_timing dpi_timing; - struct drm_display_mode *mode = dsi_config->mode; - - mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, - dsi_config->lane_count, - dsi_config->bpp); - - REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe), - mode->vdisplay << 16 | mode->hdisplay); - REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe), - dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); - REG_WRITE(MIPI_HBP_COUNT_REG(pipe), - dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); - REG_WRITE(MIPI_HFP_COUNT_REG(pipe), - dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); - REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe), - dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); - REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe), - dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); - REG_WRITE(MIPI_VBP_COUNT_REG(pipe), - dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); - REG_WRITE(MIPI_VFP_COUNT_REG(pipe), - dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); -} - -static void mdfld_mipi_config(struct mdfld_dsi_config *dsi_config, int pipe) -{ - struct drm_device *dev = dsi_config->dev; - int lane_count = dsi_config->lane_count; - - if (pipe) { - REG_WRITE(MIPI_PORT_CONTROL(0), 0x00000002); - REG_WRITE(MIPI_PORT_CONTROL(2), 0x80000000); - } else { - REG_WRITE(MIPI_PORT_CONTROL(0), 0x80010000); - REG_WRITE(MIPI_PORT_CONTROL(2), 0x00); - } - - REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150A600F); - REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), 0x0000000F); - - /* lane_count = 3 */ - REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), 0x00000200 | lane_count); - - mdfld_mipi_set_video_timing(dsi_config, pipe); -} - -static void mdfld_set_pipe_timing(struct mdfld_dsi_config *dsi_config, int pipe) -{ - struct drm_device *dev = dsi_config->dev; - struct drm_display_mode *mode = dsi_config->mode; - - REG_WRITE(HTOTAL_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1)); - REG_WRITE(HBLANK_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1)); - REG_WRITE(HSYNC_A, - ((mode->hsync_end - 1) << 16) | (mode->hsync_start - 1)); - - REG_WRITE(VTOTAL_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1)); - REG_WRITE(VBLANK_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1)); - REG_WRITE(VSYNC_A, - ((mode->vsync_end - 1) << 16) | (mode->vsync_start - 1)); - - REG_WRITE(PIPEASRC, - ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); -} -/* End for TC35876X */ - -void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); - struct mdfld_dsi_dpi_output *dpi_output = - MDFLD_DSI_DPI_OUTPUT(dsi_encoder); - struct mdfld_dsi_config *dsi_config = - mdfld_dsi_encoder_get_config(dsi_encoder); - struct drm_device *dev = dsi_config->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); - - u32 pipeconf_reg = PIPEACONF; - u32 dspcntr_reg = DSPACNTR; - - u32 pipeconf = dev_priv->pipeconf[pipe]; - u32 dspcntr = dev_priv->dspcntr[pipe]; - u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; - - if (pipe) { - pipeconf_reg = PIPECCONF; - dspcntr_reg = DSPCCNTR; - } else { - if (mdfld_get_panel_type(dev, pipe) == TC35876X) - mipi &= (~0x03); /* Use all four lanes */ - else - mipi |= 2; - } - - /*start up display island if it was shutdown*/ - if (!gma_power_begin(dev, true)) - return; - - if (mdfld_get_panel_type(dev, pipe) == TC35876X) { - /* - * The following logic is required to reset the bridge and - * configure. This also starts the DSI clock at 200MHz. - */ - tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */ - tc35876x_toshiba_bridge_panel_on(dev); - udelay(100); - /* Now start the DSI clock */ - REG_WRITE(MRST_DPLL_A, 0x00); - REG_WRITE(MRST_FPA0, 0xC1); - REG_WRITE(MRST_DPLL_A, 0x00800000); - udelay(500); - REG_WRITE(MRST_DPLL_A, 0x80800000); - - if (REG_BIT_WAIT(pipeconf_reg, 1, 29)) - dev_err(&dev->pdev->dev, "%s: DSI PLL lock timeout\n", - __func__); - - REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008); - - mipi_set_properties(dsi_config, pipe); - mdfld_mipi_config(dsi_config, pipe); - mdfld_set_pipe_timing(dsi_config, pipe); - - REG_WRITE(DSPABASE, 0x00); - REG_WRITE(DSPASTRIDE, (mode->hdisplay * 4)); - REG_WRITE(DSPASIZE, - ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); - - REG_WRITE(DSPACNTR, 0x98000000); - REG_WRITE(DSPASURF, 0x00); - - REG_WRITE(VGACNTRL, 0x80000000); - REG_WRITE(DEVICE_READY_REG, 0x00000001); - - REG_WRITE(MIPI_PORT_CONTROL(pipe), 0x80810000); - } else { - /*set up mipi port FIXME: do at init time */ - REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi); - } - REG_READ(MIPI_PORT_CONTROL(pipe)); - - if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { - /* NOP */ - } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) { - /* set up DSI controller DPI interface */ - mdfld_dsi_dpi_controller_init(dsi_config, pipe); - - /* Configure MIPI Bridge and Panel */ - tc35876x_configure_lvds_bridge(dev); - dev_priv->dpi_panel_on[pipe] = true; - } else { - /*turn on DPI interface*/ - mdfld_dsi_dpi_turn_on(dpi_output, pipe); - } - - /*set up pipe*/ - REG_WRITE(pipeconf_reg, pipeconf); - REG_READ(pipeconf_reg); - - /*set up display plane*/ - REG_WRITE(dspcntr_reg, dspcntr); - REG_READ(dspcntr_reg); - - msleep(20); /* FIXME: this should wait for vblank */ - - if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { - /* NOP */ - } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) { - mdfld_dsi_dpi_turn_on(dpi_output, pipe); - } else { - /* init driver ic */ - mdfld_dsi_tpo_ic_init(dsi_config, pipe); - /*init backlight*/ - mdfld_dsi_brightness_init(dsi_config, pipe); - } - - gma_power_end(dev); -} - -/* - * Init DSI DPI encoder. - * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector - * return pointer of newly allocated DPI encoder, NULL on error - */ -struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, - struct mdfld_dsi_connector *dsi_connector, - const struct panel_funcs *p_funcs) -{ - struct mdfld_dsi_dpi_output *dpi_output = NULL; - struct mdfld_dsi_config *dsi_config; - struct drm_connector *connector = NULL; - struct drm_encoder *encoder = NULL; - int pipe; - u32 data; - int ret; - - pipe = dsi_connector->pipe; - - if (mdfld_get_panel_type(dev, pipe) != TC35876X) { - dsi_config = mdfld_dsi_get_config(dsi_connector); - - /* panel hard-reset */ - if (p_funcs->reset) { - ret = p_funcs->reset(pipe); - if (ret) { - DRM_ERROR("Panel %d hard-reset failed\n", pipe); - return NULL; - } - } - - /* panel drvIC init */ - if (p_funcs->drv_ic_init) - p_funcs->drv_ic_init(dsi_config, pipe); - - /* panel power mode detect */ - ret = mdfld_dsi_get_power_mode(dsi_config, &data, false); - if (ret) { - DRM_ERROR("Panel %d get power mode failed\n", pipe); - dsi_connector->status = connector_status_disconnected; - } else { - DRM_INFO("pipe %d power mode 0x%x\n", pipe, data); - dsi_connector->status = connector_status_connected; - } - } - - dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL); - if (!dpi_output) { - DRM_ERROR("No memory\n"); - return NULL; - } - - if (dsi_connector->pipe) - dpi_output->panel_on = 0; - else - dpi_output->panel_on = 0; - - dpi_output->dev = dev; - if (mdfld_get_panel_type(dev, pipe) != TC35876X) - dpi_output->p_funcs = p_funcs; - dpi_output->first_boot = 1; - - /*get fixed mode*/ - dsi_config = mdfld_dsi_get_config(dsi_connector); - - /*create drm encoder object*/ - connector = &dsi_connector->base.base; - encoder = &dpi_output->base.base.base; - drm_encoder_init(dev, - encoder, - p_funcs->encoder_funcs, - DRM_MODE_ENCODER_LVDS); - drm_encoder_helper_add(encoder, - p_funcs->encoder_helper_funcs); - - /*attach to given connector*/ - drm_mode_connector_attach_encoder(connector, encoder); - - /*set possible crtcs and clones*/ - if (dsi_connector->pipe) { - encoder->possible_crtcs = (1 << 2); - encoder->possible_clones = (1 << 1); - } else { - encoder->possible_crtcs = (1 << 0); - encoder->possible_clones = (1 << 0); - } - - dsi_connector->base.encoder = &dpi_output->base.base; - - return &dpi_output->base; -} diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h deleted file mode 100644 index 6f76247..0000000 --- a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * jim liu - * Jackie Li - */ - -#ifndef __MDFLD_DSI_DPI_H__ -#define __MDFLD_DSI_DPI_H__ - -#include "mdfld_dsi_output.h" -#include "mdfld_output.h" - -struct mdfld_dsi_dpi_timing { - u16 hsync_count; - u16 hbp_count; - u16 hfp_count; - u16 hactive_count; - u16 vsync_count; - u16 vbp_count; - u16 vfp_count; -}; - -struct mdfld_dsi_dpi_output { - struct mdfld_dsi_encoder base; - struct drm_device *dev; - - int panel_on; - int first_boot; - - const struct panel_funcs *p_funcs; -}; - -#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder)\ - container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base) - -/* Export functions */ -extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode, - struct mdfld_dsi_dpi_timing *dpi_timing, - int num_lane, int bpp); -extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, - struct mdfld_dsi_connector *dsi_connector, - const struct panel_funcs *p_funcs); - -/* MDFLD DPI helper functions */ -extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode); -extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); -extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder); -extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder); -extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); -extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, - int pipe); -extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, - int pipe); -#endif /*__MDFLD_DSI_DPI_H__*/ diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c deleted file mode 100644 index 4c2cb4a..0000000 --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * jim liu - * Jackie Li - */ - -#include - -#include "mdfld_dsi_output.h" -#include "mdfld_dsi_dpi.h" -#include "mdfld_output.h" -#include "mdfld_dsi_pkg_sender.h" -#include "tc35876x-dsi-lvds.h" -#include -#include - -/* get the LABC from command line. */ -static int LABC_control = 1; - -#ifdef MODULE -module_param(LABC_control, int, 0644); -#else - -static int __init parse_LABC_control(char *arg) -{ - /* LABC control can be passed in as a cmdline parameter */ - /* to enable this feature add LABC=1 to cmdline */ - /* to disable this feature add LABC=0 to cmdline */ - if (!arg) - return -EINVAL; - - if (!strcasecmp(arg, "0")) - LABC_control = 0; - else if (!strcasecmp(arg, "1")) - LABC_control = 1; - - return 0; -} -early_param("LABC", parse_LABC_control); -#endif - -/** - * Check and see if the generic control or data buffer is empty and ready. - */ -void mdfld_dsi_gen_fifo_ready(struct drm_device *dev, u32 gen_fifo_stat_reg, - u32 fifo_stat) -{ - u32 GEN_BF_time_out_count; - - /* Check MIPI Adatper command registers */ - for (GEN_BF_time_out_count = 0; - GEN_BF_time_out_count < GEN_FB_TIME_OUT; - GEN_BF_time_out_count++) { - if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat) - break; - udelay(100); - } - - if (GEN_BF_time_out_count == GEN_FB_TIME_OUT) - DRM_ERROR("mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x.\n", - gen_fifo_stat_reg); -} - -/** - * Manage the DSI MIPI keyboard and display brightness. - * FIXME: this is exported to OSPM code. should work out an specific - * display interface to OSPM. - */ - -void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe) -{ - struct mdfld_dsi_pkg_sender *sender = - mdfld_dsi_get_pkg_sender(dsi_config); - struct drm_device *dev = sender->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - u32 gen_ctrl_val; - - if (!sender) { - DRM_ERROR("No sender found\n"); - return; - } - - /* Set default display backlight value to 85% (0xd8)*/ - mdfld_dsi_send_mcs_short(sender, write_display_brightness, 0xd8, 1, - true); - - /* Set minimum brightness setting of CABC function to 20% (0x33)*/ - mdfld_dsi_send_mcs_short(sender, write_cabc_min_bright, 0x33, 1, true); - - /* Enable backlight or/and LABC */ - gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON | - BACKLIGHT_ON; - if (LABC_control == 1) - gen_ctrl_val |= DISPLAY_DIMMING_ON | DISPLAY_BRIGHTNESS_AUTO - | GAMMA_AUTO; - - if (LABC_control == 1) - gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON; - - dev_priv->mipi_ctrl_display = gen_ctrl_val; - - mdfld_dsi_send_mcs_short(sender, write_ctrl_display, (u8)gen_ctrl_val, - 1, true); - - mdfld_dsi_send_mcs_short(sender, write_ctrl_cabc, UI_IMAGE, 1, true); -} - -void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level) -{ - struct mdfld_dsi_pkg_sender *sender; - struct drm_psb_private *dev_priv; - struct mdfld_dsi_config *dsi_config; - u32 gen_ctrl_val = 0; - int p_type = TMD_VID; - - if (!dev || (pipe != 0 && pipe != 2)) { - DRM_ERROR("Invalid parameter\n"); - return; - } - - p_type = mdfld_get_panel_type(dev, 0); - - dev_priv = dev->dev_private; - - if (pipe) - dsi_config = dev_priv->dsi_configs[1]; - else - dsi_config = dev_priv->dsi_configs[0]; - - sender = mdfld_dsi_get_pkg_sender(dsi_config); - - if (!sender) { - DRM_ERROR("No sender found\n"); - return; - } - - gen_ctrl_val = (level * 0xff / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff; - - dev_dbg(sender->dev->dev, "pipe = %d, gen_ctrl_val = %d.\n", - pipe, gen_ctrl_val); - - if (p_type == TMD_VID) { - /* Set display backlight value */ - mdfld_dsi_send_mcs_short(sender, tmd_write_display_brightness, - (u8)gen_ctrl_val, 1, true); - } else { - /* Set display backlight value */ - mdfld_dsi_send_mcs_short(sender, write_display_brightness, - (u8)gen_ctrl_val, 1, true); - - /* Enable backlight control */ - if (level == 0) - gen_ctrl_val = 0; - else - gen_ctrl_val = dev_priv->mipi_ctrl_display; - - mdfld_dsi_send_mcs_short(sender, write_ctrl_display, - (u8)gen_ctrl_val, 1, true); - } -} - -static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config, - u8 dcs, u32 *data, bool hs) -{ - struct mdfld_dsi_pkg_sender *sender - = mdfld_dsi_get_pkg_sender(dsi_config); - - if (!sender || !data) { - DRM_ERROR("Invalid parameter\n"); - return -EINVAL; - } - - return mdfld_dsi_read_mcs(sender, dcs, data, 1, hs); -} - -int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, u32 *mode, - bool hs) -{ - if (!dsi_config || !mode) { - DRM_ERROR("Invalid parameter\n"); - return -EINVAL; - } - - return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, hs); -} - -/* - * NOTE: this function was used by OSPM. - * TODO: will be removed later, should work out display interfaces for OSPM - */ -void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe) -{ - if (!dsi_config || ((pipe != 0) && (pipe != 2))) { - DRM_ERROR("Invalid parameters\n"); - return; - } - - mdfld_dsi_dpi_controller_init(dsi_config, pipe); -} - -static void mdfld_dsi_connector_save(struct drm_connector *connector) -{ -} - -static void mdfld_dsi_connector_restore(struct drm_connector *connector) -{ -} - -/* FIXME: start using the force parameter */ -static enum drm_connector_status -mdfld_dsi_connector_detect(struct drm_connector *connector, bool force) -{ - struct mdfld_dsi_connector *dsi_connector - = mdfld_dsi_connector(connector); - - dsi_connector->status = connector_status_connected; - - return dsi_connector->status; -} - -static int mdfld_dsi_connector_set_property(struct drm_connector *connector, - struct drm_property *property, - uint64_t value) -{ - struct drm_encoder *encoder = connector->encoder; - struct backlight_device *psb_bd; - - if (!strcmp(property->name, "scaling mode") && encoder) { - struct psb_intel_crtc *psb_crtc = - to_psb_intel_crtc(encoder->crtc); - bool centerechange; - uint64_t val; - - if (!psb_crtc) - goto set_prop_error; - - switch (value) { - case DRM_MODE_SCALE_FULLSCREEN: - break; - case DRM_MODE_SCALE_NO_SCALE: - break; - case DRM_MODE_SCALE_ASPECT: - break; - default: - goto set_prop_error; - } - - if (drm_connector_property_get_value(connector, property, &val)) - goto set_prop_error; - - if (val == value) - goto set_prop_done; - - if (drm_connector_property_set_value(connector, - property, value)) - goto set_prop_error; - - centerechange = (val == DRM_MODE_SCALE_NO_SCALE) || - (value == DRM_MODE_SCALE_NO_SCALE); - - if (psb_crtc->saved_mode.hdisplay != 0 && - psb_crtc->saved_mode.vdisplay != 0) { - if (centerechange) { - if (!drm_crtc_helper_set_mode(encoder->crtc, - &psb_crtc->saved_mode, - encoder->crtc->x, - encoder->crtc->y, - encoder->crtc->fb)) - goto set_prop_error; - } else { - struct drm_encoder_helper_funcs *funcs = - encoder->helper_private; - funcs->mode_set(encoder, - &psb_crtc->saved_mode, - &psb_crtc->saved_adjusted_mode); - } - } - } else if (!strcmp(property->name, "backlight") && encoder) { - if (drm_connector_property_set_value(connector, property, - value)) - goto set_prop_error; - else { - psb_bd = mdfld_get_backlight_device(); - if (psb_bd) { - psb_bd->props.brightness = value; - mdfld_set_brightness(psb_bd); - } - } - } -set_prop_done: - return 0; -set_prop_error: - return -1; -} - -static void mdfld_dsi_connector_destroy(struct drm_connector *connector) -{ - struct mdfld_dsi_connector *dsi_connector = - mdfld_dsi_connector(connector); - struct mdfld_dsi_pkg_sender *sender; - - if (!dsi_connector) - return; - drm_sysfs_connector_remove(connector); - drm_connector_cleanup(connector); - sender = dsi_connector->pkg_sender; - mdfld_dsi_pkg_sender_destroy(sender); - kfree(dsi_connector); -} - -static int mdfld_dsi_connector_get_modes(struct drm_connector *connector) -{ - struct mdfld_dsi_connector *dsi_connector = - mdfld_dsi_connector(connector); - struct mdfld_dsi_config *dsi_config = - mdfld_dsi_get_config(dsi_connector); - struct drm_display_mode *fixed_mode = dsi_config->fixed_mode; - struct drm_display_mode *dup_mode = NULL; - struct drm_device *dev = connector->dev; - - connector->display_info.min_vfreq = 0; - connector->display_info.max_vfreq = 200; - connector->display_info.min_hfreq = 0; - connector->display_info.max_hfreq = 200; - - if (fixed_mode) { - dev_dbg(dev->dev, "fixed_mode %dx%d\n", - fixed_mode->hdisplay, fixed_mode->vdisplay); - dup_mode = drm_mode_duplicate(dev, fixed_mode); - drm_mode_probed_add(connector, dup_mode); - return 1; - } - DRM_ERROR("Didn't get any modes!\n"); - return 0; -} - -static int mdfld_dsi_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct mdfld_dsi_connector *dsi_connector = - mdfld_dsi_connector(connector); - struct mdfld_dsi_config *dsi_config = - mdfld_dsi_get_config(dsi_connector); - struct drm_display_mode *fixed_mode = dsi_config->fixed_mode; - - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - return MODE_NO_INTERLACE; - - /** - * FIXME: current DC has no fitting unit, reject any mode setting - * request - * Will figure out a way to do up-scaling(pannel fitting) later. - **/ - if (fixed_mode) { - if (mode->hdisplay != fixed_mode->hdisplay) - return MODE_PANEL; - - if (mode->vdisplay != fixed_mode->vdisplay) - return MODE_PANEL; - } - - return MODE_OK; -} - -static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode) -{ - if (mode == connector->dpms) - return; - - /*first, execute dpms*/ - - drm_helper_connector_dpms(connector, mode); -} - -static struct drm_encoder *mdfld_dsi_connector_best_encoder( - struct drm_connector *connector) -{ - struct mdfld_dsi_connector *dsi_connector = - mdfld_dsi_connector(connector); - struct mdfld_dsi_config *dsi_config = - mdfld_dsi_get_config(dsi_connector); - return &dsi_config->encoder->base.base; -} - -/*DSI connector funcs*/ -static const struct drm_connector_funcs mdfld_dsi_connector_funcs = { - .dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms, - .save = mdfld_dsi_connector_save, - .restore = mdfld_dsi_connector_restore, - .detect = mdfld_dsi_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .set_property = mdfld_dsi_connector_set_property, - .destroy = mdfld_dsi_connector_destroy, -}; - -/*DSI connector helper funcs*/ -static const struct drm_connector_helper_funcs - mdfld_dsi_connector_helper_funcs = { - .get_modes = mdfld_dsi_connector_get_modes, - .mode_valid = mdfld_dsi_connector_mode_valid, - .best_encoder = mdfld_dsi_connector_best_encoder, -}; - -static int mdfld_dsi_get_default_config(struct drm_device *dev, - struct mdfld_dsi_config *config, int pipe) -{ - if (!dev || !config) { - DRM_ERROR("Invalid parameters"); - return -EINVAL; - } - - config->bpp = 24; - if (mdfld_get_panel_type(dev, pipe) == TC35876X) - config->lane_count = 4; - else - config->lane_count = 2; - config->channel_num = 0; - - if (mdfld_get_panel_type(dev, pipe) == TMD_VID) - config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE; - else if (mdfld_get_panel_type(dev, pipe) == TC35876X) - config->video_mode = - MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS; - else - config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE; - - return 0; -} - -int mdfld_dsi_panel_reset(int pipe) -{ - unsigned gpio; - int ret = 0; - - switch (pipe) { - case 0: - gpio = 128; - break; - case 2: - gpio = 34; - break; - default: - DRM_ERROR("Invalid output\n"); - return -EINVAL; - } - - ret = gpio_request(gpio, "gfx"); - if (ret) { - DRM_ERROR("gpio_rqueset failed\n"); - return ret; - } - - ret = gpio_direction_output(gpio, 1); - if (ret) { - DRM_ERROR("gpio_direction_output failed\n"); - goto gpio_error; - } - - gpio_get_value(128); - -gpio_error: - if (gpio_is_valid(gpio)) - gpio_free(gpio); - - return ret; -} - -/* - * MIPI output init - * @dev drm device - * @pipe pipe number. 0 or 2 - * @config - * - * Do the initialization of a MIPI output, including create DRM mode objects - * initialization of DSI output on @pipe - */ -void mdfld_dsi_output_init(struct drm_device *dev, - int pipe, - const struct panel_funcs *p_vid_funcs) -{ - struct mdfld_dsi_config *dsi_config; - struct mdfld_dsi_connector *dsi_connector; - struct drm_connector *connector; - struct mdfld_dsi_encoder *encoder; - struct drm_psb_private *dev_priv = dev->dev_private; - struct panel_info dsi_panel_info; - u32 width_mm, height_mm; - - dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe); - - if (!dev || ((pipe != 0) && (pipe != 2))) { - DRM_ERROR("Invalid parameter\n"); - return; - } - - /*create a new connetor*/ - dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL); - if (!dsi_connector) { - DRM_ERROR("No memory"); - return; - } - - dsi_connector->pipe = pipe; - - dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), - GFP_KERNEL); - if (!dsi_config) { - DRM_ERROR("cannot allocate memory for DSI config\n"); - goto dsi_init_err0; - } - mdfld_dsi_get_default_config(dev, dsi_config, pipe); - - dsi_connector->private = dsi_config; - - dsi_config->changed = 1; - dsi_config->dev = dev; - - dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev); - if (p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info)) - goto dsi_init_err0; - - width_mm = dsi_panel_info.width_mm; - height_mm = dsi_panel_info.height_mm; - - dsi_config->mode = dsi_config->fixed_mode; - dsi_config->connector = dsi_connector; - - if (!dsi_config->fixed_mode) { - DRM_ERROR("No pannel fixed mode was found\n"); - goto dsi_init_err0; - } - - if (pipe && dev_priv->dsi_configs[0]) { - dsi_config->dvr_ic_inited = 0; - dev_priv->dsi_configs[1] = dsi_config; - } else if (pipe == 0) { - dsi_config->dvr_ic_inited = 1; - dev_priv->dsi_configs[0] = dsi_config; - } else { - DRM_ERROR("Trying to init MIPI1 before MIPI0\n"); - goto dsi_init_err0; - } - - - connector = &dsi_connector->base.base; - drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs); - - connector->display_info.subpixel_order = SubPixelHorizontalRGB; - connector->display_info.width_mm = width_mm; - connector->display_info.height_mm = height_mm; - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - - /*attach properties*/ - drm_connector_attach_property(connector, - dev->mode_config.scaling_mode_property, - DRM_MODE_SCALE_FULLSCREEN); - drm_connector_attach_property(connector, - dev_priv->backlight_property, - MDFLD_DSI_BRIGHTNESS_MAX_LEVEL); - - /*init DSI package sender on this output*/ - if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) { - DRM_ERROR("Package Sender initialization failed on pipe %d\n", - pipe); - goto dsi_init_err0; - } - - encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs); - if (!encoder) { - DRM_ERROR("Create DPI encoder failed\n"); - goto dsi_init_err1; - } - encoder->private = dsi_config; - dsi_config->encoder = encoder; - encoder->base.type = (pipe == 0) ? INTEL_OUTPUT_MIPI : - INTEL_OUTPUT_MIPI2; - drm_sysfs_connector_add(connector); - return; - - /*TODO: add code to destroy outputs on error*/ -dsi_init_err1: - /*destroy sender*/ - mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender); - - drm_connector_cleanup(connector); - - kfree(dsi_config->fixed_mode); - kfree(dsi_config); -dsi_init_err0: - kfree(dsi_connector); -} diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.h b/drivers/gpu/drm/gma500/mdfld_dsi_output.h deleted file mode 100644 index 21071ce..0000000 --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.h +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * jim liu - * Jackie Li - */ - -#ifndef __MDFLD_DSI_OUTPUT_H__ -#define __MDFLD_DSI_OUTPUT_H__ - -#include -#include -#include -#include -#include -#include - -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "mdfld_output.h" - -#include - -#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end)) -#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end)) -#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end)) -#define FLD_MOD(orig, val, start, end) \ - (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) - -#define REG_FLD_MOD(reg, val, start, end) \ - REG_WRITE(reg, FLD_MOD(REG_READ(reg), val, start, end)) - -static inline int REGISTER_FLD_WAIT(struct drm_device *dev, u32 reg, - u32 val, int start, int end) -{ - int t = 100000; - - while (FLD_GET(REG_READ(reg), start, end) != val) { - if (--t == 0) - return 1; - } - - return 0; -} - -#define REG_FLD_WAIT(reg, val, start, end) \ - REGISTER_FLD_WAIT(dev, reg, val, start, end) - -#define REG_BIT_WAIT(reg, val, bitnum) \ - REGISTER_FLD_WAIT(dev, reg, val, bitnum, bitnum) - -#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100 - -#ifdef DEBUG -#define CHECK_PIPE(pipe) ({ \ - const typeof(pipe) __pipe = (pipe); \ - BUG_ON(__pipe != 0 && __pipe != 2); \ - __pipe; }) -#else -#define CHECK_PIPE(pipe) (pipe) -#endif - -/* - * Actual MIPIA->MIPIC reg offset is 0x800, value 0x400 is valid for 0 and 2 - */ -#define REG_OFFSET(pipe) (CHECK_PIPE(pipe) * 0x400) - -/* mdfld DSI controller registers */ -#define MIPI_DEVICE_READY_REG(pipe) (0xb000 + REG_OFFSET(pipe)) -#define MIPI_INTR_STAT_REG(pipe) (0xb004 + REG_OFFSET(pipe)) -#define MIPI_INTR_EN_REG(pipe) (0xb008 + REG_OFFSET(pipe)) -#define MIPI_DSI_FUNC_PRG_REG(pipe) (0xb00c + REG_OFFSET(pipe)) -#define MIPI_HS_TX_TIMEOUT_REG(pipe) (0xb010 + REG_OFFSET(pipe)) -#define MIPI_LP_RX_TIMEOUT_REG(pipe) (0xb014 + REG_OFFSET(pipe)) -#define MIPI_TURN_AROUND_TIMEOUT_REG(pipe) (0xb018 + REG_OFFSET(pipe)) -#define MIPI_DEVICE_RESET_TIMER_REG(pipe) (0xb01c + REG_OFFSET(pipe)) -#define MIPI_DPI_RESOLUTION_REG(pipe) (0xb020 + REG_OFFSET(pipe)) -#define MIPI_DBI_FIFO_THROTTLE_REG(pipe) (0xb024 + REG_OFFSET(pipe)) -#define MIPI_HSYNC_COUNT_REG(pipe) (0xb028 + REG_OFFSET(pipe)) -#define MIPI_HBP_COUNT_REG(pipe) (0xb02c + REG_OFFSET(pipe)) -#define MIPI_HFP_COUNT_REG(pipe) (0xb030 + REG_OFFSET(pipe)) -#define MIPI_HACTIVE_COUNT_REG(pipe) (0xb034 + REG_OFFSET(pipe)) -#define MIPI_VSYNC_COUNT_REG(pipe) (0xb038 + REG_OFFSET(pipe)) -#define MIPI_VBP_COUNT_REG(pipe) (0xb03c + REG_OFFSET(pipe)) -#define MIPI_VFP_COUNT_REG(pipe) (0xb040 + REG_OFFSET(pipe)) -#define MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe) (0xb044 + REG_OFFSET(pipe)) -#define MIPI_DPI_CONTROL_REG(pipe) (0xb048 + REG_OFFSET(pipe)) -#define MIPI_DPI_DATA_REG(pipe) (0xb04c + REG_OFFSET(pipe)) -#define MIPI_INIT_COUNT_REG(pipe) (0xb050 + REG_OFFSET(pipe)) -#define MIPI_MAX_RETURN_PACK_SIZE_REG(pipe) (0xb054 + REG_OFFSET(pipe)) -#define MIPI_VIDEO_MODE_FORMAT_REG(pipe) (0xb058 + REG_OFFSET(pipe)) -#define MIPI_EOT_DISABLE_REG(pipe) (0xb05c + REG_OFFSET(pipe)) -#define MIPI_LP_BYTECLK_REG(pipe) (0xb060 + REG_OFFSET(pipe)) -#define MIPI_LP_GEN_DATA_REG(pipe) (0xb064 + REG_OFFSET(pipe)) -#define MIPI_HS_GEN_DATA_REG(pipe) (0xb068 + REG_OFFSET(pipe)) -#define MIPI_LP_GEN_CTRL_REG(pipe) (0xb06c + REG_OFFSET(pipe)) -#define MIPI_HS_GEN_CTRL_REG(pipe) (0xb070 + REG_OFFSET(pipe)) -#define MIPI_GEN_FIFO_STAT_REG(pipe) (0xb074 + REG_OFFSET(pipe)) -#define MIPI_HS_LS_DBI_ENABLE_REG(pipe) (0xb078 + REG_OFFSET(pipe)) -#define MIPI_DPHY_PARAM_REG(pipe) (0xb080 + REG_OFFSET(pipe)) -#define MIPI_DBI_BW_CTRL_REG(pipe) (0xb084 + REG_OFFSET(pipe)) -#define MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe) (0xb088 + REG_OFFSET(pipe)) - -#define MIPI_CTRL_REG(pipe) (0xb104 + REG_OFFSET(pipe)) -#define MIPI_DATA_ADD_REG(pipe) (0xb108 + REG_OFFSET(pipe)) -#define MIPI_DATA_LEN_REG(pipe) (0xb10c + REG_OFFSET(pipe)) -#define MIPI_CMD_ADD_REG(pipe) (0xb110 + REG_OFFSET(pipe)) -#define MIPI_CMD_LEN_REG(pipe) (0xb114 + REG_OFFSET(pipe)) - -/* non-uniform reg offset */ -#define MIPI_PORT_CONTROL(pipe) (CHECK_PIPE(pipe) ? MIPI_C : MIPI) - -#define DSI_DEVICE_READY (0x1) -#define DSI_POWER_STATE_ULPS_ENTER (0x2 << 1) -#define DSI_POWER_STATE_ULPS_EXIT (0x1 << 1) -#define DSI_POWER_STATE_ULPS_OFFSET (0x1) - - -#define DSI_ONE_DATA_LANE (0x1) -#define DSI_TWO_DATA_LANE (0x2) -#define DSI_THREE_DATA_LANE (0X3) -#define DSI_FOUR_DATA_LANE (0x4) -#define DSI_DPI_VIRT_CHANNEL_OFFSET (0x3) -#define DSI_DBI_VIRT_CHANNEL_OFFSET (0x5) -#define DSI_DPI_COLOR_FORMAT_RGB565 (0x01 << 7) -#define DSI_DPI_COLOR_FORMAT_RGB666 (0x02 << 7) -#define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK (0x03 << 7) -#define DSI_DPI_COLOR_FORMAT_RGB888 (0x04 << 7) -#define DSI_DBI_COLOR_FORMAT_OPTION2 (0x05 << 13) - -#define DSI_INTR_STATE_RXSOTERROR BIT(0) - -#define DSI_INTR_STATE_SPL_PKG_SENT BIT(30) -#define DSI_INTR_STATE_TE BIT(31) - -#define DSI_HS_TX_TIMEOUT_MASK (0xffffff) - -#define DSI_LP_RX_TIMEOUT_MASK (0xffffff) - -#define DSI_TURN_AROUND_TIMEOUT_MASK (0x3f) - -#define DSI_RESET_TIMER_MASK (0xffff) - -#define DSI_DBI_FIFO_WM_HALF (0x0) -#define DSI_DBI_FIFO_WM_QUARTER (0x1) -#define DSI_DBI_FIFO_WM_LOW (0x2) - -#define DSI_DPI_TIMING_MASK (0xffff) - -#define DSI_INIT_TIMER_MASK (0xffff) - -#define DSI_DBI_RETURN_PACK_SIZE_MASK (0x3ff) - -#define DSI_LP_BYTECLK_MASK (0x0ffff) - -#define DSI_HS_CTRL_GEN_SHORT_W0 (0x03) -#define DSI_HS_CTRL_GEN_SHORT_W1 (0x13) -#define DSI_HS_CTRL_GEN_SHORT_W2 (0x23) -#define DSI_HS_CTRL_GEN_R0 (0x04) -#define DSI_HS_CTRL_GEN_R1 (0x14) -#define DSI_HS_CTRL_GEN_R2 (0x24) -#define DSI_HS_CTRL_GEN_LONG_W (0x29) -#define DSI_HS_CTRL_MCS_SHORT_W0 (0x05) -#define DSI_HS_CTRL_MCS_SHORT_W1 (0x15) -#define DSI_HS_CTRL_MCS_R0 (0x06) -#define DSI_HS_CTRL_MCS_LONG_W (0x39) -#define DSI_HS_CTRL_VC_OFFSET (0x06) -#define DSI_HS_CTRL_WC_OFFSET (0x08) - -#define DSI_FIFO_GEN_HS_DATA_FULL BIT(0) -#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY BIT(1) -#define DSI_FIFO_GEN_HS_DATA_EMPTY BIT(2) -#define DSI_FIFO_GEN_LP_DATA_FULL BIT(8) -#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY BIT(9) -#define DSI_FIFO_GEN_LP_DATA_EMPTY BIT(10) -#define DSI_FIFO_GEN_HS_CTRL_FULL BIT(16) -#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY BIT(17) -#define DSI_FIFO_GEN_HS_CTRL_EMPTY BIT(18) -#define DSI_FIFO_GEN_LP_CTRL_FULL BIT(24) -#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY BIT(25) -#define DSI_FIFO_GEN_LP_CTRL_EMPTY BIT(26) -#define DSI_FIFO_DBI_EMPTY BIT(27) -#define DSI_FIFO_DPI_EMPTY BIT(28) - -#define DSI_DBI_HS_LP_SWITCH_MASK (0x1) - -#define DSI_HS_LP_SWITCH_COUNTER_OFFSET (0x0) -#define DSI_LP_HS_SWITCH_COUNTER_OFFSET (0x16) - -#define DSI_DPI_CTRL_HS_SHUTDOWN (0x00000001) -#define DSI_DPI_CTRL_HS_TURN_ON (0x00000002) - -/*dsi power modes*/ -#define DSI_POWER_MODE_DISPLAY_ON BIT(2) -#define DSI_POWER_MODE_NORMAL_ON BIT(3) -#define DSI_POWER_MODE_SLEEP_OUT BIT(4) -#define DSI_POWER_MODE_PARTIAL_ON BIT(5) -#define DSI_POWER_MODE_IDLE_ON BIT(6) - -enum { - MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1, - MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2, - MDFLD_DSI_VIDEO_BURST_MODE = 3, -}; - -#define DSI_DPI_COMPLETE_LAST_LINE BIT(2) -#define DSI_DPI_DISABLE_BTA BIT(3) - -struct mdfld_dsi_connector { - struct psb_intel_connector base; - - int pipe; - void *private; - void *pkg_sender; - - /* Connection status */ - enum drm_connector_status status; -}; - -struct mdfld_dsi_encoder { - struct psb_intel_encoder base; - void *private; -}; - -/* - * DSI config, consists of one DSI connector, two DSI encoders. - * DRM will pick up on DSI encoder basing on differents configs. - */ -struct mdfld_dsi_config { - struct drm_device *dev; - struct drm_display_mode *fixed_mode; - struct drm_display_mode *mode; - - struct mdfld_dsi_connector *connector; - struct mdfld_dsi_encoder *encoder; - - int changed; - - int bpp; - int lane_count; - /*Virtual channel number for this encoder*/ - int channel_num; - /*video mode configure*/ - int video_mode; - - int dvr_ic_inited; -}; - -static inline struct mdfld_dsi_connector *mdfld_dsi_connector( - struct drm_connector *connector) -{ - struct psb_intel_connector *psb_connector; - - psb_connector = to_psb_intel_connector(connector); - - return container_of(psb_connector, struct mdfld_dsi_connector, base); -} - -static inline struct mdfld_dsi_encoder *mdfld_dsi_encoder( - struct drm_encoder *encoder) -{ - struct psb_intel_encoder *psb_encoder; - - psb_encoder = to_psb_intel_encoder(encoder); - - return container_of(psb_encoder, struct mdfld_dsi_encoder, base); -} - -static inline struct mdfld_dsi_config * - mdfld_dsi_get_config(struct mdfld_dsi_connector *connector) -{ - if (!connector) - return NULL; - return (struct mdfld_dsi_config *)connector->private; -} - -static inline void *mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config *config) -{ - struct mdfld_dsi_connector *dsi_connector; - - if (!config) - return NULL; - - dsi_connector = config->connector; - - if (!dsi_connector) - return NULL; - - return dsi_connector->pkg_sender; -} - -static inline struct mdfld_dsi_config * - mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder *encoder) -{ - if (!encoder) - return NULL; - return (struct mdfld_dsi_config *)encoder->private; -} - -static inline struct mdfld_dsi_connector * - mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder *encoder) -{ - struct mdfld_dsi_config *config; - - if (!encoder) - return NULL; - - config = mdfld_dsi_encoder_get_config(encoder); - if (!config) - return NULL; - - return config->connector; -} - -static inline void *mdfld_dsi_encoder_get_pkg_sender( - struct mdfld_dsi_encoder *encoder) -{ - struct mdfld_dsi_config *dsi_config; - - dsi_config = mdfld_dsi_encoder_get_config(encoder); - if (!dsi_config) - return NULL; - - return mdfld_dsi_get_pkg_sender(dsi_config); -} - -static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder *encoder) -{ - struct mdfld_dsi_connector *connector; - - if (!encoder) - return -1; - - connector = mdfld_dsi_encoder_get_connector(encoder); - if (!connector) - return -1; - return connector->pipe; -} - -/* Export functions */ -extern void mdfld_dsi_gen_fifo_ready(struct drm_device *dev, - u32 gen_fifo_stat_reg, u32 fifo_stat); -extern void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, - int pipe); -extern void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, - int level); -extern void mdfld_dsi_output_init(struct drm_device *dev, - int pipe, - const struct panel_funcs *p_vid_funcs); -extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config, - int pipe); - -extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, - u32 *mode, bool hs); -extern int mdfld_dsi_panel_reset(int pipe); - -#endif /*__MDFLD_DSI_OUTPUT_H__*/ diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c deleted file mode 100644 index baa0e14..0000000 --- a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c +++ /dev/null @@ -1,694 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Jackie Li - */ - -#include - -#include "mdfld_dsi_output.h" -#include "mdfld_dsi_pkg_sender.h" -#include "mdfld_dsi_dpi.h" - -#define MDFLD_DSI_READ_MAX_COUNT 5000 - -enum data_type { - DSI_DT_GENERIC_SHORT_WRITE_0 = 0x03, - DSI_DT_GENERIC_SHORT_WRITE_1 = 0x13, - DSI_DT_GENERIC_SHORT_WRITE_2 = 0x23, - DSI_DT_GENERIC_READ_0 = 0x04, - DSI_DT_GENERIC_READ_1 = 0x14, - DSI_DT_GENERIC_READ_2 = 0x24, - DSI_DT_GENERIC_LONG_WRITE = 0x29, - DSI_DT_DCS_SHORT_WRITE_0 = 0x05, - DSI_DT_DCS_SHORT_WRITE_1 = 0x15, - DSI_DT_DCS_READ = 0x06, - DSI_DT_DCS_LONG_WRITE = 0x39, -}; - -enum { - MDFLD_DSI_PANEL_MODE_SLEEP = 0x1, -}; - -enum { - MDFLD_DSI_PKG_SENDER_FREE = 0x0, - MDFLD_DSI_PKG_SENDER_BUSY = 0x1, -}; - -static const char *const dsi_errors[] = { - "RX SOT Error", - "RX SOT Sync Error", - "RX EOT Sync Error", - "RX Escape Mode Entry Error", - "RX LP TX Sync Error", - "RX HS Receive Timeout Error", - "RX False Control Error", - "RX ECC Single Bit Error", - "RX ECC Multibit Error", - "RX Checksum Error", - "RX DSI Data Type Not Recognised", - "RX DSI VC ID Invalid", - "TX False Control Error", - "TX ECC Single Bit Error", - "TX ECC Multibit Error", - "TX Checksum Error", - "TX DSI Data Type Not Recognised", - "TX DSI VC ID invalid", - "High Contention", - "Low contention", - "DPI FIFO Under run", - "HS TX Timeout", - "LP RX Timeout", - "Turn Around ACK Timeout", - "ACK With No Error", - "RX Invalid TX Length", - "RX Prot Violation", - "HS Generic Write FIFO Full", - "LP Generic Write FIFO Full", - "Generic Read Data Avail" - "Special Packet Sent", - "Tearing Effect", -}; - -static inline int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender, - u32 mask) -{ - struct drm_device *dev = sender->dev; - u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg; - int retry = 0xffff; - - while (retry--) { - if ((mask & REG_READ(gen_fifo_stat_reg)) == mask) - return 0; - udelay(100); - } - DRM_ERROR("fifo is NOT empty 0x%08x\n", REG_READ(gen_fifo_stat_reg)); - return -EIO; -} - -static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender) -{ - return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(10) | BIT(18) | - BIT(26) | BIT(27) | BIT(28))); -} - -static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender) -{ - return wait_for_gen_fifo_empty(sender, (BIT(10) | BIT(26))); -} - -static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender) -{ - return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(18))); -} - -static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask) -{ - u32 intr_stat_reg = sender->mipi_intr_stat_reg; - struct drm_device *dev = sender->dev; - - dev_dbg(sender->dev->dev, "Handling error 0x%08x\n", mask); - - switch (mask) { - case BIT(0): - case BIT(1): - case BIT(2): - case BIT(3): - case BIT(4): - case BIT(5): - case BIT(6): - case BIT(7): - case BIT(8): - case BIT(9): - case BIT(10): - case BIT(11): - case BIT(12): - case BIT(13): - dev_dbg(sender->dev->dev, "No Action required\n"); - break; - case BIT(14): - /*wait for all fifo empty*/ - /*wait_for_all_fifos_empty(sender)*/; - break; - case BIT(15): - dev_dbg(sender->dev->dev, "No Action required\n"); - break; - case BIT(16): - break; - case BIT(17): - break; - case BIT(18): - case BIT(19): - dev_dbg(sender->dev->dev, "High/Low contention detected\n"); - /*wait for contention recovery time*/ - /*mdelay(10);*/ - /*wait for all fifo empty*/ - if (0) - wait_for_all_fifos_empty(sender); - break; - case BIT(20): - dev_dbg(sender->dev->dev, "No Action required\n"); - break; - case BIT(21): - /*wait for all fifo empty*/ - /*wait_for_all_fifos_empty(sender);*/ - break; - case BIT(22): - break; - case BIT(23): - case BIT(24): - case BIT(25): - case BIT(26): - case BIT(27): - dev_dbg(sender->dev->dev, "HS Gen fifo full\n"); - REG_WRITE(intr_stat_reg, mask); - wait_for_hs_fifos_empty(sender); - break; - case BIT(28): - dev_dbg(sender->dev->dev, "LP Gen fifo full\n"); - REG_WRITE(intr_stat_reg, mask); - wait_for_lp_fifos_empty(sender); - break; - case BIT(29): - case BIT(30): - case BIT(31): - dev_dbg(sender->dev->dev, "No Action required\n"); - break; - } - - if (mask & REG_READ(intr_stat_reg)) - dev_dbg(sender->dev->dev, - "Cannot clean interrupt 0x%08x\n", mask); - return 0; -} - -static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender) -{ - struct drm_device *dev = sender->dev; - u32 intr_stat_reg = sender->mipi_intr_stat_reg; - u32 mask; - u32 intr_stat; - int i; - int err = 0; - - intr_stat = REG_READ(intr_stat_reg); - - for (i = 0; i < 32; i++) { - mask = (0x00000001UL) << i; - if (intr_stat & mask) { - dev_dbg(sender->dev->dev, "[DSI]: %s\n", dsi_errors[i]); - err = handle_dsi_error(sender, mask); - if (err) - DRM_ERROR("Cannot handle error\n"); - } - } - return err; -} - -static int send_short_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type, - u8 cmd, u8 param, bool hs) -{ - struct drm_device *dev = sender->dev; - u32 ctrl_reg; - u32 val; - u8 virtual_channel = 0; - - if (hs) { - ctrl_reg = sender->mipi_hs_gen_ctrl_reg; - - /* FIXME: wait_for_hs_fifos_empty(sender); */ - } else { - ctrl_reg = sender->mipi_lp_gen_ctrl_reg; - - /* FIXME: wait_for_lp_fifos_empty(sender); */ - } - - val = FLD_VAL(param, 23, 16) | FLD_VAL(cmd, 15, 8) | - FLD_VAL(virtual_channel, 7, 6) | FLD_VAL(data_type, 5, 0); - - REG_WRITE(ctrl_reg, val); - - return 0; -} - -static int send_long_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type, - u8 *data, int len, bool hs) -{ - struct drm_device *dev = sender->dev; - u32 ctrl_reg; - u32 data_reg; - u32 val; - u8 *p; - u8 b1, b2, b3, b4; - u8 virtual_channel = 0; - int i; - - if (hs) { - ctrl_reg = sender->mipi_hs_gen_ctrl_reg; - data_reg = sender->mipi_hs_gen_data_reg; - - /* FIXME: wait_for_hs_fifos_empty(sender); */ - } else { - ctrl_reg = sender->mipi_lp_gen_ctrl_reg; - data_reg = sender->mipi_lp_gen_data_reg; - - /* FIXME: wait_for_lp_fifos_empty(sender); */ - } - - p = data; - for (i = 0; i < len / 4; i++) { - b1 = *p++; - b2 = *p++; - b3 = *p++; - b4 = *p++; - - REG_WRITE(data_reg, b4 << 24 | b3 << 16 | b2 << 8 | b1); - } - - i = len % 4; - if (i) { - b1 = 0; b2 = 0; b3 = 0; - - switch (i) { - case 3: - b1 = *p++; - b2 = *p++; - b3 = *p++; - break; - case 2: - b1 = *p++; - b2 = *p++; - break; - case 1: - b1 = *p++; - break; - } - - REG_WRITE(data_reg, b3 << 16 | b2 << 8 | b1); - } - - val = FLD_VAL(len, 23, 8) | FLD_VAL(virtual_channel, 7, 6) | - FLD_VAL(data_type, 5, 0); - - REG_WRITE(ctrl_reg, val); - - return 0; -} - -static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender, u8 data_type, - u8 *data, u16 len) -{ - u8 cmd; - - switch (data_type) { - case DSI_DT_DCS_SHORT_WRITE_0: - case DSI_DT_DCS_SHORT_WRITE_1: - case DSI_DT_DCS_LONG_WRITE: - cmd = *data; - break; - default: - return 0; - } - - /*this prevents other package sending while doing msleep*/ - sender->status = MDFLD_DSI_PKG_SENDER_BUSY; - - /*wait for 120 milliseconds in case exit_sleep_mode just be sent*/ - if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) { - /*TODO: replace it with msleep later*/ - mdelay(120); - } - - if (unlikely(cmd == DCS_EXIT_SLEEP_MODE)) { - /*TODO: replace it with msleep later*/ - mdelay(120); - } - return 0; -} - -static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender, u8 data_type, - u8 *data, u16 len) -{ - u8 cmd; - - switch (data_type) { - case DSI_DT_DCS_SHORT_WRITE_0: - case DSI_DT_DCS_SHORT_WRITE_1: - case DSI_DT_DCS_LONG_WRITE: - cmd = *data; - break; - default: - return 0; - } - - /*update panel status*/ - if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) { - sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP; - /*TODO: replace it with msleep later*/ - mdelay(120); - } else if (unlikely(cmd == DCS_EXIT_SLEEP_MODE)) { - sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP; - /*TODO: replace it with msleep later*/ - mdelay(120); - } else if (unlikely(cmd == DCS_SOFT_RESET)) { - /*TODO: replace it with msleep later*/ - mdelay(5); - } - - sender->status = MDFLD_DSI_PKG_SENDER_FREE; - - return 0; -} - -static int send_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type, - u8 *data, u16 len, bool hs) -{ - int ret; - - /*handle DSI error*/ - ret = dsi_error_handler(sender); - if (ret) { - DRM_ERROR("Error handling failed\n"); - return -EAGAIN; - } - - /* send pkg */ - if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) { - DRM_ERROR("sender is busy\n"); - return -EAGAIN; - } - - ret = send_pkg_prepare(sender, data_type, data, len); - if (ret) { - DRM_ERROR("send_pkg_prepare error\n"); - return ret; - } - - switch (data_type) { - case DSI_DT_GENERIC_SHORT_WRITE_0: - case DSI_DT_GENERIC_SHORT_WRITE_1: - case DSI_DT_GENERIC_SHORT_WRITE_2: - case DSI_DT_GENERIC_READ_0: - case DSI_DT_GENERIC_READ_1: - case DSI_DT_GENERIC_READ_2: - case DSI_DT_DCS_SHORT_WRITE_0: - case DSI_DT_DCS_SHORT_WRITE_1: - case DSI_DT_DCS_READ: - ret = send_short_pkg(sender, data_type, data[0], data[1], hs); - break; - case DSI_DT_GENERIC_LONG_WRITE: - case DSI_DT_DCS_LONG_WRITE: - ret = send_long_pkg(sender, data_type, data, len, hs); - break; - } - - send_pkg_done(sender, data_type, data, len); - - /*FIXME: should I query complete and fifo empty here?*/ - - return ret; -} - -int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data, - u32 len, bool hs) -{ - unsigned long flags; - - if (!sender || !data || !len) { - DRM_ERROR("Invalid parameters\n"); - return -EINVAL; - } - - spin_lock_irqsave(&sender->lock, flags); - send_pkg(sender, DSI_DT_DCS_LONG_WRITE, data, len, hs); - spin_unlock_irqrestore(&sender->lock, flags); - - return 0; -} - -int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd, - u8 param, u8 param_num, bool hs) -{ - u8 data[2]; - unsigned long flags; - u8 data_type; - - if (!sender) { - DRM_ERROR("Invalid parameter\n"); - return -EINVAL; - } - - data[0] = cmd; - - if (param_num) { - data_type = DSI_DT_DCS_SHORT_WRITE_1; - data[1] = param; - } else { - data_type = DSI_DT_DCS_SHORT_WRITE_0; - data[1] = 0; - } - - spin_lock_irqsave(&sender->lock, flags); - send_pkg(sender, data_type, data, sizeof(data), hs); - spin_unlock_irqrestore(&sender->lock, flags); - - return 0; -} - -int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0, - u8 param1, u8 param_num, bool hs) -{ - u8 data[2]; - unsigned long flags; - u8 data_type; - - if (!sender || param_num > 2) { - DRM_ERROR("Invalid parameter\n"); - return -EINVAL; - } - - switch (param_num) { - case 0: - data_type = DSI_DT_GENERIC_SHORT_WRITE_0; - data[0] = 0; - data[1] = 0; - break; - case 1: - data_type = DSI_DT_GENERIC_SHORT_WRITE_1; - data[0] = param0; - data[1] = 0; - break; - case 2: - data_type = DSI_DT_GENERIC_SHORT_WRITE_2; - data[0] = param0; - data[1] = param1; - break; - } - - spin_lock_irqsave(&sender->lock, flags); - send_pkg(sender, data_type, data, sizeof(data), hs); - spin_unlock_irqrestore(&sender->lock, flags); - - return 0; -} - -int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data, - u32 len, bool hs) -{ - unsigned long flags; - - if (!sender || !data || !len) { - DRM_ERROR("Invalid parameters\n"); - return -EINVAL; - } - - spin_lock_irqsave(&sender->lock, flags); - send_pkg(sender, DSI_DT_GENERIC_LONG_WRITE, data, len, hs); - spin_unlock_irqrestore(&sender->lock, flags); - - return 0; -} - -static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type, - u8 *data, u16 len, u32 *data_out, u16 len_out, bool hs) -{ - unsigned long flags; - struct drm_device *dev = sender->dev; - int i; - u32 gen_data_reg; - int retry = MDFLD_DSI_READ_MAX_COUNT; - - if (!sender || !data_out || !len_out) { - DRM_ERROR("Invalid parameters\n"); - return -EINVAL; - } - - /** - * do reading. - * 0) send out generic read request - * 1) polling read data avail interrupt - * 2) read data - */ - spin_lock_irqsave(&sender->lock, flags); - - REG_WRITE(sender->mipi_intr_stat_reg, BIT(29)); - - if ((REG_READ(sender->mipi_intr_stat_reg) & BIT(29))) - DRM_ERROR("Can NOT clean read data valid interrupt\n"); - - /*send out read request*/ - send_pkg(sender, data_type, data, len, hs); - - /*polling read data avail interrupt*/ - while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & BIT(29))) { - udelay(100); - retry--; - } - - if (!retry) { - spin_unlock_irqrestore(&sender->lock, flags); - return -ETIMEDOUT; - } - - REG_WRITE(sender->mipi_intr_stat_reg, BIT(29)); - - /*read data*/ - if (hs) - gen_data_reg = sender->mipi_hs_gen_data_reg; - else - gen_data_reg = sender->mipi_lp_gen_data_reg; - - for (i = 0; i < len_out; i++) - *(data_out + i) = REG_READ(gen_data_reg); - - spin_unlock_irqrestore(&sender->lock, flags); - - return 0; -} - -int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd, - u32 *data, u16 len, bool hs) -{ - if (!sender || !data || !len) { - DRM_ERROR("Invalid parameters\n"); - return -EINVAL; - } - - return __read_panel_data(sender, DSI_DT_DCS_READ, &cmd, 1, - data, len, hs); -} - -int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector, - int pipe) -{ - struct mdfld_dsi_pkg_sender *pkg_sender; - struct mdfld_dsi_config *dsi_config = - mdfld_dsi_get_config(dsi_connector); - struct drm_device *dev = dsi_config->dev; - u32 mipi_val = 0; - - if (!dsi_connector) { - DRM_ERROR("Invalid parameter\n"); - return -EINVAL; - } - - pkg_sender = dsi_connector->pkg_sender; - - if (!pkg_sender || IS_ERR(pkg_sender)) { - pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender), - GFP_KERNEL); - if (!pkg_sender) { - DRM_ERROR("Create DSI pkg sender failed\n"); - return -ENOMEM; - } - dsi_connector->pkg_sender = (void *)pkg_sender; - } - - pkg_sender->dev = dev; - pkg_sender->dsi_connector = dsi_connector; - pkg_sender->pipe = pipe; - pkg_sender->pkg_num = 0; - pkg_sender->panel_mode = 0; - pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE; - - /*init regs*/ - if (pipe == 0) { - pkg_sender->dpll_reg = MRST_DPLL_A; - pkg_sender->dspcntr_reg = DSPACNTR; - pkg_sender->pipeconf_reg = PIPEACONF; - pkg_sender->dsplinoff_reg = DSPALINOFF; - pkg_sender->dspsurf_reg = DSPASURF; - pkg_sender->pipestat_reg = PIPEASTAT; - } else if (pipe == 2) { - pkg_sender->dpll_reg = MRST_DPLL_A; - pkg_sender->dspcntr_reg = DSPCCNTR; - pkg_sender->pipeconf_reg = PIPECCONF; - pkg_sender->dsplinoff_reg = DSPCLINOFF; - pkg_sender->dspsurf_reg = DSPCSURF; - pkg_sender->pipestat_reg = PIPECSTAT; - } - - pkg_sender->mipi_intr_stat_reg = MIPI_INTR_STAT_REG(pipe); - pkg_sender->mipi_lp_gen_data_reg = MIPI_LP_GEN_DATA_REG(pipe); - pkg_sender->mipi_hs_gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe); - pkg_sender->mipi_lp_gen_ctrl_reg = MIPI_LP_GEN_CTRL_REG(pipe); - pkg_sender->mipi_hs_gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe); - pkg_sender->mipi_gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe); - pkg_sender->mipi_data_addr_reg = MIPI_DATA_ADD_REG(pipe); - pkg_sender->mipi_data_len_reg = MIPI_DATA_LEN_REG(pipe); - pkg_sender->mipi_cmd_addr_reg = MIPI_CMD_ADD_REG(pipe); - pkg_sender->mipi_cmd_len_reg = MIPI_CMD_LEN_REG(pipe); - - /*init lock*/ - spin_lock_init(&pkg_sender->lock); - - if (mdfld_get_panel_type(dev, pipe) != TC35876X) { - /** - * For video mode, don't enable DPI timing output here, - * will init the DPI timing output during mode setting. - */ - mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; - - if (pipe == 0) - mipi_val |= 0x2; - - REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi_val); - REG_READ(MIPI_PORT_CONTROL(pipe)); - - /* do dsi controller init */ - mdfld_dsi_controller_init(dsi_config, pipe); - } - - return 0; -} - -void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender) -{ - if (!sender || IS_ERR(sender)) - return; - - /*free*/ - kfree(sender); -} - - diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h deleted file mode 100644 index 459cd7e..0000000 --- a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Jackie Li - */ -#ifndef __MDFLD_DSI_PKG_SENDER_H__ -#define __MDFLD_DSI_PKG_SENDER_H__ - -#include - -#define MDFLD_MAX_DCS_PARAM 8 - -struct mdfld_dsi_pkg_sender { - struct drm_device *dev; - struct mdfld_dsi_connector *dsi_connector; - u32 status; - u32 panel_mode; - - int pipe; - - spinlock_t lock; - - u32 pkg_num; - - /* Registers */ - u32 dpll_reg; - u32 dspcntr_reg; - u32 pipeconf_reg; - u32 pipestat_reg; - u32 dsplinoff_reg; - u32 dspsurf_reg; - - u32 mipi_intr_stat_reg; - u32 mipi_lp_gen_data_reg; - u32 mipi_hs_gen_data_reg; - u32 mipi_lp_gen_ctrl_reg; - u32 mipi_hs_gen_ctrl_reg; - u32 mipi_gen_fifo_stat_reg; - u32 mipi_data_addr_reg; - u32 mipi_data_len_reg; - u32 mipi_cmd_addr_reg; - u32 mipi_cmd_len_reg; -}; - -/* DCS definitions */ -#define DCS_SOFT_RESET 0x01 -#define DCS_ENTER_SLEEP_MODE 0x10 -#define DCS_EXIT_SLEEP_MODE 0x11 -#define DCS_SET_DISPLAY_OFF 0x28 -#define DCS_SET_DISPLAY_ON 0x29 -#define DCS_SET_COLUMN_ADDRESS 0x2a -#define DCS_SET_PAGE_ADDRESS 0x2b -#define DCS_WRITE_MEM_START 0x2c -#define DCS_SET_TEAR_OFF 0x34 -#define DCS_SET_TEAR_ON 0x35 - -extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector, - int pipe); -extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender); -int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd, - u8 param, u8 param_num, bool hs); -int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data, - u32 len, bool hs); -int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0, - u8 param1, u8 param_num, bool hs); -int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data, - u32 len, bool hs); -/* Read interfaces */ -int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd, - u32 *data, u16 len, bool hs); - -#endif diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c deleted file mode 100644 index a35a292..0000000 --- a/drivers/gpu/drm/gma500/mdfld_intel_display.c +++ /dev/null @@ -1,1180 +0,0 @@ -/* - * Copyright © 2006-2007 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: - * Eric Anholt - */ - -#include -#include - -#include -#include "psb_intel_reg.h" -#include "psb_intel_display.h" -#include "framebuffer.h" -#include "mdfld_output.h" -#include "mdfld_dsi_output.h" - -/* Hardcoded currently */ -static int ksel = KSEL_CRYSTAL_19; - -struct psb_intel_range_t { - int min, max; -}; - -struct mrst_limit_t { - struct psb_intel_range_t dot, m, p1; -}; - -struct mrst_clock_t { - /* derived values */ - int dot; - int m; - int p1; -}; - -#define COUNT_MAX 0x10000000 - -void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe) -{ - int count, temp; - u32 pipeconf_reg = PIPEACONF; - - switch (pipe) { - case 0: - break; - case 1: - pipeconf_reg = PIPEBCONF; - break; - case 2: - pipeconf_reg = PIPECCONF; - break; - default: - DRM_ERROR("Illegal Pipe Number.\n"); - return; - } - - /* FIXME JLIU7_PO */ - psb_intel_wait_for_vblank(dev); - return; - - /* Wait for for the pipe disable to take effect. */ - for (count = 0; count < COUNT_MAX; count++) { - temp = REG_READ(pipeconf_reg); - if ((temp & PIPEACONF_PIPE_STATE) == 0) - break; - } -} - -void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe) -{ - int count, temp; - u32 pipeconf_reg = PIPEACONF; - - switch (pipe) { - case 0: - break; - case 1: - pipeconf_reg = PIPEBCONF; - break; - case 2: - pipeconf_reg = PIPECCONF; - break; - default: - DRM_ERROR("Illegal Pipe Number.\n"); - return; - } - - /* FIXME JLIU7_PO */ - psb_intel_wait_for_vblank(dev); - return; - - /* Wait for for the pipe enable to take effect. */ - for (count = 0; count < COUNT_MAX; count++) { - temp = REG_READ(pipeconf_reg); - if ((temp & PIPEACONF_PIPE_STATE) == 1) - break; - } -} - -static void psb_intel_crtc_prepare(struct drm_crtc *crtc) -{ - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); -} - -static void psb_intel_crtc_commit(struct drm_crtc *crtc) -{ - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); -} - -static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -/** - * Return the pipe currently connected to the panel fitter, - * or -1 if the panel fitter is not present or not in use - */ -static int psb_intel_panel_fitter_pipe(struct drm_device *dev) -{ - u32 pfit_control; - - pfit_control = REG_READ(PFIT_CONTROL); - - /* See if the panel fitter is in use */ - if ((pfit_control & PFIT_ENABLE) == 0) - return -1; - - /* 965 can place panel fitter on either pipe */ - return (pfit_control >> 29) & 0x3; -} - -static struct drm_device globle_dev; - -void mdfld__intel_plane_set_alpha(int enable) -{ - struct drm_device *dev = &globle_dev; - int dspcntr_reg = DSPACNTR; - u32 dspcntr; - - dspcntr = REG_READ(dspcntr_reg); - - if (enable) { - dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA; - dspcntr |= DISPPLANE_32BPP; - } else { - dspcntr &= ~DISPPLANE_32BPP; - dspcntr |= DISPPLANE_32BPP_NO_ALPHA; - } - - REG_WRITE(dspcntr_reg, dspcntr); -} - -static int check_fb(struct drm_framebuffer *fb) -{ - if (!fb) - return 0; - - switch (fb->bits_per_pixel) { - case 8: - case 16: - case 24: - case 32: - return 0; - default: - DRM_ERROR("Unknown color depth\n"); - return -EINVAL; - } -} - -static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) -{ - struct drm_device *dev = crtc->dev; - /* struct drm_i915_master_private *master_priv; */ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); - int pipe = psb_intel_crtc->pipe; - unsigned long start, offset; - int dsplinoff = DSPALINOFF; - int dspsurf = DSPASURF; - int dspstride = DSPASTRIDE; - int dspcntr_reg = DSPACNTR; - u32 dspcntr; - int ret; - - memcpy(&globle_dev, dev, sizeof(struct drm_device)); - - dev_dbg(dev->dev, "pipe = 0x%x.\n", pipe); - - /* no fb bound */ - if (!crtc->fb) { - dev_dbg(dev->dev, "No FB bound\n"); - return 0; - } - - ret = check_fb(crtc->fb); - if (ret) - return ret; - - switch (pipe) { - case 0: - dsplinoff = DSPALINOFF; - break; - case 1: - dsplinoff = DSPBLINOFF; - dspsurf = DSPBSURF; - dspstride = DSPBSTRIDE; - dspcntr_reg = DSPBCNTR; - break; - case 2: - dsplinoff = DSPCLINOFF; - dspsurf = DSPCSURF; - dspstride = DSPCSTRIDE; - dspcntr_reg = DSPCCNTR; - break; - default: - DRM_ERROR("Illegal Pipe Number.\n"); - return -EINVAL; - } - - if (!gma_power_begin(dev, true)) - return 0; - - start = psbfb->gtt->offset; - offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); - - REG_WRITE(dspstride, crtc->fb->pitches[0]); - dspcntr = REG_READ(dspcntr_reg); - dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - - switch (crtc->fb->bits_per_pixel) { - case 8: - dspcntr |= DISPPLANE_8BPP; - break; - case 16: - if (crtc->fb->depth == 15) - dspcntr |= DISPPLANE_15_16BPP; - else - dspcntr |= DISPPLANE_16BPP; - break; - case 24: - case 32: - dspcntr |= DISPPLANE_32BPP_NO_ALPHA; - break; - } - REG_WRITE(dspcntr_reg, dspcntr); - - dev_dbg(dev->dev, "Writing base %08lX %08lX %d %d\n", - start, offset, x, y); - REG_WRITE(dsplinoff, offset); - REG_READ(dsplinoff); - REG_WRITE(dspsurf, start); - REG_READ(dspsurf); - - gma_power_end(dev); - - return 0; -} - -/* - * Disable the pipe, plane and pll. - * - */ -void mdfld_disable_crtc(struct drm_device *dev, int pipe) -{ - int dpll_reg = MRST_DPLL_A; - int dspcntr_reg = DSPACNTR; - int dspbase_reg = MRST_DSPABASE; - int pipeconf_reg = PIPEACONF; - u32 temp; - - dev_dbg(dev->dev, "pipe = %d\n", pipe); - - - switch (pipe) { - case 0: - break; - case 1: - dpll_reg = MDFLD_DPLL_B; - dspcntr_reg = DSPBCNTR; - dspbase_reg = DSPBSURF; - pipeconf_reg = PIPEBCONF; - break; - case 2: - dpll_reg = MRST_DPLL_A; - dspcntr_reg = DSPCCNTR; - dspbase_reg = MDFLD_DSPCBASE; - pipeconf_reg = PIPECCONF; - break; - default: - DRM_ERROR("Illegal Pipe Number.\n"); - return; - } - - if (pipe != 1) - mdfld_dsi_gen_fifo_ready(dev, MIPI_GEN_FIFO_STAT_REG(pipe), - HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); - - /* Disable display plane */ - temp = REG_READ(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) != 0) { - REG_WRITE(dspcntr_reg, - temp & ~DISPLAY_PLANE_ENABLE); - /* Flush the plane changes */ - REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); - REG_READ(dspbase_reg); - } - - /* FIXME_JLIU7 MDFLD_PO revisit */ - - /* Next, disable display pipes */ - temp = REG_READ(pipeconf_reg); - if ((temp & PIPEACONF_ENABLE) != 0) { - temp &= ~PIPEACONF_ENABLE; - temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF; - REG_WRITE(pipeconf_reg, temp); - REG_READ(pipeconf_reg); - - /* Wait for for the pipe disable to take effect. */ - mdfldWaitForPipeDisable(dev, pipe); - } - - temp = REG_READ(dpll_reg); - if (temp & DPLL_VCO_ENABLE) { - if ((pipe != 1 && - !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) - & PIPEACONF_ENABLE)) || pipe == 1) { - temp &= ~(DPLL_VCO_ENABLE); - REG_WRITE(dpll_reg, temp); - REG_READ(dpll_reg); - /* Wait for the clocks to turn off. */ - /* FIXME_MDFLD PO may need more delay */ - udelay(500); - - if (!(temp & MDFLD_PWR_GATE_EN)) { - /* gating power of DPLL */ - REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN); - /* FIXME_MDFLD PO - change 500 to 1 after PO */ - udelay(5000); - } - } - } - -} - -/** - * Sets the power management mode of the pipe and plane. - * - * This code should probably grow support for turning the cursor off and back - * on appropriately at the same time as we're turning the pipe off/on. - */ -static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode) -{ - struct drm_device *dev = crtc->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int pipe = psb_intel_crtc->pipe; - int dpll_reg = MRST_DPLL_A; - int dspcntr_reg = DSPACNTR; - int dspbase_reg = MRST_DSPABASE; - int pipeconf_reg = PIPEACONF; - u32 pipestat_reg = PIPEASTAT; - u32 pipeconf = dev_priv->pipeconf[pipe]; - u32 temp; - int timeout = 0; - - dev_dbg(dev->dev, "mode = %d, pipe = %d\n", mode, pipe); - -/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */ -/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */ - - switch (pipe) { - case 0: - break; - case 1: - dpll_reg = DPLL_B; - dspcntr_reg = DSPBCNTR; - dspbase_reg = MRST_DSPBBASE; - pipeconf_reg = PIPEBCONF; - dpll_reg = MDFLD_DPLL_B; - break; - case 2: - dpll_reg = MRST_DPLL_A; - dspcntr_reg = DSPCCNTR; - dspbase_reg = MDFLD_DSPCBASE; - pipeconf_reg = PIPECCONF; - pipestat_reg = PIPECSTAT; - break; - default: - DRM_ERROR("Illegal Pipe Number.\n"); - return; - } - - if (!gma_power_begin(dev, true)) - return; - - /* XXX: When our outputs are all unaware of DPMS modes other than off - * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. - */ - switch (mode) { - case DRM_MODE_DPMS_ON: - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - /* Enable the DPLL */ - temp = REG_READ(dpll_reg); - - if ((temp & DPLL_VCO_ENABLE) == 0) { - /* When ungating power of DPLL, needs to wait 0.5us - before enable the VCO */ - if (temp & MDFLD_PWR_GATE_EN) { - temp &= ~MDFLD_PWR_GATE_EN; - REG_WRITE(dpll_reg, temp); - /* FIXME_MDFLD PO - change 500 to 1 after PO */ - udelay(500); - } - - REG_WRITE(dpll_reg, temp); - REG_READ(dpll_reg); - /* FIXME_MDFLD PO - change 500 to 1 after PO */ - udelay(500); - - REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); - REG_READ(dpll_reg); - - /** - * wait for DSI PLL to lock - * NOTE: only need to poll status of pipe 0 and pipe 1, - * since both MIPI pipes share the same PLL. - */ - while ((pipe != 2) && (timeout < 20000) && - !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { - udelay(150); - timeout++; - } - } - - /* Enable the plane */ - temp = REG_READ(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) == 0) { - REG_WRITE(dspcntr_reg, - temp | DISPLAY_PLANE_ENABLE); - /* Flush the plane changes */ - REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); - } - - /* Enable the pipe */ - temp = REG_READ(pipeconf_reg); - if ((temp & PIPEACONF_ENABLE) == 0) { - REG_WRITE(pipeconf_reg, pipeconf); - - /* Wait for for the pipe enable to take effect. */ - mdfldWaitForPipeEnable(dev, pipe); - } - - /*workaround for sighting 3741701 Random X blank display*/ - /*perform w/a in video mode only on pipe A or C*/ - if (pipe == 0 || pipe == 2) { - REG_WRITE(pipestat_reg, REG_READ(pipestat_reg)); - msleep(100); - if (PIPE_VBLANK_STATUS & REG_READ(pipestat_reg)) - dev_dbg(dev->dev, "OK"); - else { - dev_dbg(dev->dev, "STUCK!!!!"); - /*shutdown controller*/ - temp = REG_READ(dspcntr_reg); - REG_WRITE(dspcntr_reg, - temp & ~DISPLAY_PLANE_ENABLE); - REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); - /*mdfld_dsi_dpi_shut_down(dev, pipe);*/ - REG_WRITE(0xb048, 1); - msleep(100); - temp = REG_READ(pipeconf_reg); - temp &= ~PIPEACONF_ENABLE; - REG_WRITE(pipeconf_reg, temp); - msleep(100); /*wait for pipe disable*/ - REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0); - msleep(100); - REG_WRITE(0xb004, REG_READ(0xb004)); - /* try to bring the controller back up again*/ - REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 1); - temp = REG_READ(dspcntr_reg); - REG_WRITE(dspcntr_reg, - temp | DISPLAY_PLANE_ENABLE); - REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); - /*mdfld_dsi_dpi_turn_on(dev, pipe);*/ - REG_WRITE(0xb048, 2); - msleep(100); - temp = REG_READ(pipeconf_reg); - temp |= PIPEACONF_ENABLE; - REG_WRITE(pipeconf_reg, temp); - } - } - - psb_intel_crtc_load_lut(crtc); - - /* Give the overlay scaler a chance to enable - if it's on this pipe */ - /* psb_intel_crtc_dpms_video(crtc, true); TODO */ - - break; - case DRM_MODE_DPMS_OFF: - /* Give the overlay scaler a chance to disable - * if it's on this pipe */ - /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ - if (pipe != 1) - mdfld_dsi_gen_fifo_ready(dev, - MIPI_GEN_FIFO_STAT_REG(pipe), - HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); - - /* Disable the VGA plane that we never use */ - REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); - - /* Disable display plane */ - temp = REG_READ(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) != 0) { - REG_WRITE(dspcntr_reg, - temp & ~DISPLAY_PLANE_ENABLE); - /* Flush the plane changes */ - REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); - REG_READ(dspbase_reg); - } - - /* Next, disable display pipes */ - temp = REG_READ(pipeconf_reg); - if ((temp & PIPEACONF_ENABLE) != 0) { - temp &= ~PIPEACONF_ENABLE; - temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF; - REG_WRITE(pipeconf_reg, temp); - REG_READ(pipeconf_reg); - - /* Wait for for the pipe disable to take effect. */ - mdfldWaitForPipeDisable(dev, pipe); - } - - temp = REG_READ(dpll_reg); - if (temp & DPLL_VCO_ENABLE) { - if ((pipe != 1 && !((REG_READ(PIPEACONF) - | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE)) - || pipe == 1) { - temp &= ~(DPLL_VCO_ENABLE); - REG_WRITE(dpll_reg, temp); - REG_READ(dpll_reg); - /* Wait for the clocks to turn off. */ - /* FIXME_MDFLD PO may need more delay */ - udelay(500); - } - } - break; - } - gma_power_end(dev); -} - - -#define MDFLD_LIMT_DPLL_19 0 -#define MDFLD_LIMT_DPLL_25 1 -#define MDFLD_LIMT_DPLL_83 2 -#define MDFLD_LIMT_DPLL_100 3 -#define MDFLD_LIMT_DSIPLL_19 4 -#define MDFLD_LIMT_DSIPLL_25 5 -#define MDFLD_LIMT_DSIPLL_83 6 -#define MDFLD_LIMT_DSIPLL_100 7 - -#define MDFLD_DOT_MIN 19750 -#define MDFLD_DOT_MAX 120000 -#define MDFLD_DPLL_M_MIN_19 113 -#define MDFLD_DPLL_M_MAX_19 155 -#define MDFLD_DPLL_P1_MIN_19 2 -#define MDFLD_DPLL_P1_MAX_19 10 -#define MDFLD_DPLL_M_MIN_25 101 -#define MDFLD_DPLL_M_MAX_25 130 -#define MDFLD_DPLL_P1_MIN_25 2 -#define MDFLD_DPLL_P1_MAX_25 10 -#define MDFLD_DPLL_M_MIN_83 64 -#define MDFLD_DPLL_M_MAX_83 64 -#define MDFLD_DPLL_P1_MIN_83 2 -#define MDFLD_DPLL_P1_MAX_83 2 -#define MDFLD_DPLL_M_MIN_100 64 -#define MDFLD_DPLL_M_MAX_100 64 -#define MDFLD_DPLL_P1_MIN_100 2 -#define MDFLD_DPLL_P1_MAX_100 2 -#define MDFLD_DSIPLL_M_MIN_19 131 -#define MDFLD_DSIPLL_M_MAX_19 175 -#define MDFLD_DSIPLL_P1_MIN_19 3 -#define MDFLD_DSIPLL_P1_MAX_19 8 -#define MDFLD_DSIPLL_M_MIN_25 97 -#define MDFLD_DSIPLL_M_MAX_25 140 -#define MDFLD_DSIPLL_P1_MIN_25 3 -#define MDFLD_DSIPLL_P1_MAX_25 9 -#define MDFLD_DSIPLL_M_MIN_83 33 -#define MDFLD_DSIPLL_M_MAX_83 92 -#define MDFLD_DSIPLL_P1_MIN_83 2 -#define MDFLD_DSIPLL_P1_MAX_83 3 -#define MDFLD_DSIPLL_M_MIN_100 97 -#define MDFLD_DSIPLL_M_MAX_100 140 -#define MDFLD_DSIPLL_P1_MIN_100 3 -#define MDFLD_DSIPLL_P1_MAX_100 9 - -static const struct mrst_limit_t mdfld_limits[] = { - { /* MDFLD_LIMT_DPLL_19 */ - .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, - .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19}, - .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19}, - }, - { /* MDFLD_LIMT_DPLL_25 */ - .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, - .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25}, - .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25}, - }, - { /* MDFLD_LIMT_DPLL_83 */ - .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, - .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83}, - .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83}, - }, - { /* MDFLD_LIMT_DPLL_100 */ - .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, - .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100}, - .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100}, - }, - { /* MDFLD_LIMT_DSIPLL_19 */ - .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, - .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19}, - .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19}, - }, - { /* MDFLD_LIMT_DSIPLL_25 */ - .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, - .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25}, - .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25}, - }, - { /* MDFLD_LIMT_DSIPLL_83 */ - .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, - .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83}, - .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83}, - }, - { /* MDFLD_LIMT_DSIPLL_100 */ - .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, - .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100}, - .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100}, - }, -}; - -#define MDFLD_M_MIN 21 -#define MDFLD_M_MAX 180 -static const u32 mdfld_m_converts[] = { -/* M configuration table from 9-bit LFSR table */ - 224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */ - 173, 342, 171, 85, 298, 149, 74, 37, 18, 265, /* 31 - 40 */ - 388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */ - 83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */ - 341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */ - 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */ - 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */ - 71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */ - 253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */ - 478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */ - 477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */ - 210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */ - 145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */ - 380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */ - 103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */ - 396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */ -}; - -static const struct mrst_limit_t *mdfld_limit(struct drm_crtc *crtc) -{ - const struct mrst_limit_t *limit = NULL; - struct drm_device *dev = crtc->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - - if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI) - || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) { - if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) - limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19]; - else if (ksel == KSEL_BYPASS_25) - limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25]; - else if ((ksel == KSEL_BYPASS_83_100) && - (dev_priv->core_freq == 166)) - limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83]; - else if ((ksel == KSEL_BYPASS_83_100) && - (dev_priv->core_freq == 100 || - dev_priv->core_freq == 200)) - limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100]; - } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { - if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) - limit = &mdfld_limits[MDFLD_LIMT_DPLL_19]; - else if (ksel == KSEL_BYPASS_25) - limit = &mdfld_limits[MDFLD_LIMT_DPLL_25]; - else if ((ksel == KSEL_BYPASS_83_100) && - (dev_priv->core_freq == 166)) - limit = &mdfld_limits[MDFLD_LIMT_DPLL_83]; - else if ((ksel == KSEL_BYPASS_83_100) && - (dev_priv->core_freq == 100 || - dev_priv->core_freq == 200)) - limit = &mdfld_limits[MDFLD_LIMT_DPLL_100]; - } else { - limit = NULL; - dev_dbg(dev->dev, "mdfld_limit Wrong display type.\n"); - } - - return limit; -} - -/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ -static void mdfld_clock(int refclk, struct mrst_clock_t *clock) -{ - clock->dot = (refclk * clock->m) / clock->p1; -} - -/** - * Returns a set of divisors for the desired target clock with the given refclk, - * or FALSE. Divisor values are the actual divisors for - */ -static bool -mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk, - struct mrst_clock_t *best_clock) -{ - struct mrst_clock_t clock; - const struct mrst_limit_t *limit = mdfld_limit(crtc); - int err = target; - - memset(best_clock, 0, sizeof(*best_clock)); - - for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { - for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; - clock.p1++) { - int this_err; - - mdfld_clock(refclk, &clock); - - this_err = abs(clock.dot - target); - if (this_err < err) { - *best_clock = clock; - err = this_err; - } - } - } - return err != target; -} - -static int mdfld_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - int x, int y, - struct drm_framebuffer *old_fb) -{ - struct drm_device *dev = crtc->dev; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct drm_psb_private *dev_priv = dev->dev_private; - int pipe = psb_intel_crtc->pipe; - int fp_reg = MRST_FPA0; - int dpll_reg = MRST_DPLL_A; - int dspcntr_reg = DSPACNTR; - int pipeconf_reg = PIPEACONF; - int htot_reg = HTOTAL_A; - int hblank_reg = HBLANK_A; - int hsync_reg = HSYNC_A; - int vtot_reg = VTOTAL_A; - int vblank_reg = VBLANK_A; - int vsync_reg = VSYNC_A; - int dspsize_reg = DSPASIZE; - int dsppos_reg = DSPAPOS; - int pipesrc_reg = PIPEASRC; - u32 *pipeconf = &dev_priv->pipeconf[pipe]; - u32 *dspcntr = &dev_priv->dspcntr[pipe]; - int refclk = 0; - int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0, - clk_tmp = 0; - struct mrst_clock_t clock; - bool ok; - u32 dpll = 0, fp = 0; - bool is_mipi = false, is_mipi2 = false, is_hdmi = false; - struct drm_mode_config *mode_config = &dev->mode_config; - struct psb_intel_encoder *psb_intel_encoder = NULL; - uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; - struct drm_encoder *encoder; - struct drm_connector *connector; - int timeout = 0; - int ret; - - dev_dbg(dev->dev, "pipe = 0x%x\n", pipe); - -#if 0 - if (pipe == 1) { - if (!gma_power_begin(dev, true)) - return 0; - android_hdmi_crtc_mode_set(crtc, mode, adjusted_mode, - x, y, old_fb); - goto mrst_crtc_mode_set_exit; - } -#endif - - switch (pipe) { - case 0: - break; - case 1: - fp_reg = FPB0; - dpll_reg = DPLL_B; - dspcntr_reg = DSPBCNTR; - pipeconf_reg = PIPEBCONF; - htot_reg = HTOTAL_B; - hblank_reg = HBLANK_B; - hsync_reg = HSYNC_B; - vtot_reg = VTOTAL_B; - vblank_reg = VBLANK_B; - vsync_reg = VSYNC_B; - dspsize_reg = DSPBSIZE; - dsppos_reg = DSPBPOS; - pipesrc_reg = PIPEBSRC; - fp_reg = MDFLD_DPLL_DIV0; - dpll_reg = MDFLD_DPLL_B; - break; - case 2: - dpll_reg = MRST_DPLL_A; - dspcntr_reg = DSPCCNTR; - pipeconf_reg = PIPECCONF; - htot_reg = HTOTAL_C; - hblank_reg = HBLANK_C; - hsync_reg = HSYNC_C; - vtot_reg = VTOTAL_C; - vblank_reg = VBLANK_C; - vsync_reg = VSYNC_C; - dspsize_reg = DSPCSIZE; - dsppos_reg = DSPCPOS; - pipesrc_reg = PIPECSRC; - break; - default: - DRM_ERROR("Illegal Pipe Number.\n"); - return 0; - } - - ret = check_fb(crtc->fb); - if (ret) - return ret; - - dev_dbg(dev->dev, "adjusted_hdisplay = %d\n", - adjusted_mode->hdisplay); - dev_dbg(dev->dev, "adjusted_vdisplay = %d\n", - adjusted_mode->vdisplay); - dev_dbg(dev->dev, "adjusted_hsync_start = %d\n", - adjusted_mode->hsync_start); - dev_dbg(dev->dev, "adjusted_hsync_end = %d\n", - adjusted_mode->hsync_end); - dev_dbg(dev->dev, "adjusted_htotal = %d\n", - adjusted_mode->htotal); - dev_dbg(dev->dev, "adjusted_vsync_start = %d\n", - adjusted_mode->vsync_start); - dev_dbg(dev->dev, "adjusted_vsync_end = %d\n", - adjusted_mode->vsync_end); - dev_dbg(dev->dev, "adjusted_vtotal = %d\n", - adjusted_mode->vtotal); - dev_dbg(dev->dev, "adjusted_clock = %d\n", - adjusted_mode->clock); - dev_dbg(dev->dev, "hdisplay = %d\n", - mode->hdisplay); - dev_dbg(dev->dev, "vdisplay = %d\n", - mode->vdisplay); - - if (!gma_power_begin(dev, true)) - return 0; - - memcpy(&psb_intel_crtc->saved_mode, mode, - sizeof(struct drm_display_mode)); - memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode, - sizeof(struct drm_display_mode)); - - list_for_each_entry(connector, &mode_config->connector_list, head) { - if (!connector) - continue; - - encoder = connector->encoder; - - if (!encoder) - continue; - - if (encoder->crtc != crtc) - continue; - - psb_intel_encoder = psb_intel_attached_encoder(connector); - - switch (psb_intel_encoder->type) { - case INTEL_OUTPUT_MIPI: - is_mipi = true; - break; - case INTEL_OUTPUT_MIPI2: - is_mipi2 = true; - break; - case INTEL_OUTPUT_HDMI: - is_hdmi = true; - break; - } - } - - /* Disable the VGA plane that we never use */ - REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); - - /* Disable the panel fitter if it was on our pipe */ - if (psb_intel_panel_fitter_pipe(dev) == pipe) - REG_WRITE(PFIT_CONTROL, 0); - - /* pipesrc and dspsize control the size that is scaled from, - * which should always be the user's requested size. - */ - if (pipe == 1) { - /* FIXME: To make HDMI display with 864x480 (TPO), 480x864 - * (PYR) or 480x854 (TMD), set the sprite width/height and - * souce image size registers with the adjusted mode for - * pipe B. - */ - - /* - * The defined sprite rectangle must always be completely - * contained within the displayable area of the screen image - * (frame buffer). - */ - REG_WRITE(dspsize_reg, ((min(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16) - | (min(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1)); - /* Set the CRTC with encoder mode. */ - REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) - | (mode->crtc_vdisplay - 1)); - } else { - REG_WRITE(dspsize_reg, - ((mode->crtc_vdisplay - 1) << 16) | - (mode->crtc_hdisplay - 1)); - REG_WRITE(pipesrc_reg, - ((mode->crtc_hdisplay - 1) << 16) | - (mode->crtc_vdisplay - 1)); - } - - REG_WRITE(dsppos_reg, 0); - - if (psb_intel_encoder) - drm_connector_property_get_value(connector, - dev->mode_config.scaling_mode_property, &scalingType); - - if (scalingType == DRM_MODE_SCALE_NO_SCALE) { - /* Medfield doesn't have register support for centering so we - * need to mess with the h/vblank and h/vsync start and ends - * to get centering - */ - int offsetX = 0, offsetY = 0; - - offsetX = (adjusted_mode->crtc_hdisplay - - mode->crtc_hdisplay) / 2; - offsetY = (adjusted_mode->crtc_vdisplay - - mode->crtc_vdisplay) / 2; - - REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) | - ((adjusted_mode->crtc_htotal - 1) << 16)); - REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) | - ((adjusted_mode->crtc_vtotal - 1) << 16)); - REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - - offsetX - 1) | - ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); - REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - - offsetX - 1) | - ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); - REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - - offsetY - 1) | - ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); - REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - - offsetY - 1) | - ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); - } else { - REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | - ((adjusted_mode->crtc_htotal - 1) << 16)); - REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | - ((adjusted_mode->crtc_vtotal - 1) << 16)); - REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | - ((adjusted_mode->crtc_hblank_end - 1) << 16)); - REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | - ((adjusted_mode->crtc_hsync_end - 1) << 16)); - REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | - ((adjusted_mode->crtc_vblank_end - 1) << 16)); - REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | - ((adjusted_mode->crtc_vsync_end - 1) << 16)); - } - - /* Flush the plane changes */ - { - struct drm_crtc_helper_funcs *crtc_funcs = - crtc->helper_private; - crtc_funcs->mode_set_base(crtc, x, y, old_fb); - } - - /* setup pipeconf */ - *pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */ - - /* Set up the display plane register */ - *dspcntr = REG_READ(dspcntr_reg); - *dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS; - *dspcntr |= DISPLAY_PLANE_ENABLE; - - if (is_mipi2) - goto mrst_crtc_mode_set_exit; - clk = adjusted_mode->clock; - - if (is_hdmi) { - if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) { - refclk = 19200; - - if (is_mipi || is_mipi2) - clk_n = 1, clk_p2 = 8; - else if (is_hdmi) - clk_n = 1, clk_p2 = 10; - } else if (ksel == KSEL_BYPASS_25) { - refclk = 25000; - - if (is_mipi || is_mipi2) - clk_n = 1, clk_p2 = 8; - else if (is_hdmi) - clk_n = 1, clk_p2 = 10; - } else if ((ksel == KSEL_BYPASS_83_100) && - dev_priv->core_freq == 166) { - refclk = 83000; - - if (is_mipi || is_mipi2) - clk_n = 4, clk_p2 = 8; - else if (is_hdmi) - clk_n = 4, clk_p2 = 10; - } else if ((ksel == KSEL_BYPASS_83_100) && - (dev_priv->core_freq == 100 || - dev_priv->core_freq == 200)) { - refclk = 100000; - if (is_mipi || is_mipi2) - clk_n = 4, clk_p2 = 8; - else if (is_hdmi) - clk_n = 4, clk_p2 = 10; - } - - if (is_mipi) - clk_byte = dev_priv->bpp / 8; - else if (is_mipi2) - clk_byte = dev_priv->bpp2 / 8; - - clk_tmp = clk * clk_n * clk_p2 * clk_byte; - - dev_dbg(dev->dev, "clk = %d, clk_n = %d, clk_p2 = %d.\n", - clk, clk_n, clk_p2); - dev_dbg(dev->dev, "adjusted_mode->clock = %d, clk_tmp = %d.\n", - adjusted_mode->clock, clk_tmp); - - ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock); - - if (!ok) { - DRM_ERROR - ("mdfldFindBestPLL fail in mdfld_crtc_mode_set.\n"); - } else { - m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)]; - - dev_dbg(dev->dev, "dot clock = %d," - "m = %d, p1 = %d, m_conv = %d.\n", - clock.dot, clock.m, - clock.p1, m_conv); - } - - dpll = REG_READ(dpll_reg); - - if (dpll & DPLL_VCO_ENABLE) { - dpll &= ~DPLL_VCO_ENABLE; - REG_WRITE(dpll_reg, dpll); - REG_READ(dpll_reg); - - /* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */ - /* FIXME_MDFLD PO - change 500 to 1 after PO */ - udelay(500); - - /* reset M1, N1 & P1 */ - REG_WRITE(fp_reg, 0); - dpll &= ~MDFLD_P1_MASK; - REG_WRITE(dpll_reg, dpll); - /* FIXME_MDFLD PO - change 500 to 1 after PO */ - udelay(500); - } - - /* When ungating power of DPLL, needs to wait 0.5us before - * enable the VCO */ - if (dpll & MDFLD_PWR_GATE_EN) { - dpll &= ~MDFLD_PWR_GATE_EN; - REG_WRITE(dpll_reg, dpll); - /* FIXME_MDFLD PO - change 500 to 1 after PO */ - udelay(500); - } - dpll = 0; - -#if 0 /* FIXME revisit later */ - if (ksel == KSEL_CRYSTAL_19 || ksel == KSEL_BYPASS_19 || - ksel == KSEL_BYPASS_25) - dpll &= ~MDFLD_INPUT_REF_SEL; - else if (ksel == KSEL_BYPASS_83_100) - dpll |= MDFLD_INPUT_REF_SEL; -#endif /* FIXME revisit later */ - - if (is_hdmi) - dpll |= MDFLD_VCO_SEL; - - fp = (clk_n / 2) << 16; - fp |= m_conv; - - /* compute bitmask from p1 value */ - dpll |= (1 << (clock.p1 - 2)) << 17; - -#if 0 /* 1080p30 & 720p */ - dpll = 0x00050000; - fp = 0x000001be; -#endif -#if 0 /* 480p */ - dpll = 0x02010000; - fp = 0x000000d2; -#endif - } else { -#if 0 /*DBI_TPO_480x864*/ - dpll = 0x00020000; - fp = 0x00000156; -#endif /* DBI_TPO_480x864 */ /* get from spec. */ - - dpll = 0x00800000; - fp = 0x000000c1; - } - - REG_WRITE(fp_reg, fp); - REG_WRITE(dpll_reg, dpll); - /* FIXME_MDFLD PO - change 500 to 1 after PO */ - udelay(500); - - dpll |= DPLL_VCO_ENABLE; - REG_WRITE(dpll_reg, dpll); - REG_READ(dpll_reg); - - /* wait for DSI PLL to lock */ - while (timeout < 20000 && - !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { - udelay(150); - timeout++; - } - - if (is_mipi) - goto mrst_crtc_mode_set_exit; - - dev_dbg(dev->dev, "is_mipi = 0x%x\n", is_mipi); - - REG_WRITE(pipeconf_reg, *pipeconf); - REG_READ(pipeconf_reg); - - /* Wait for for the pipe enable to take effect. */ - REG_WRITE(dspcntr_reg, *dspcntr); - psb_intel_wait_for_vblank(dev); - -mrst_crtc_mode_set_exit: - - gma_power_end(dev); - - return 0; -} - -const struct drm_crtc_helper_funcs mdfld_helper_funcs = { - .dpms = mdfld_crtc_dpms, - .mode_fixup = psb_intel_crtc_mode_fixup, - .mode_set = mdfld_crtc_mode_set, - .mode_set_base = mdfld__intel_pipe_set_base, - .prepare = psb_intel_crtc_prepare, - .commit = psb_intel_crtc_commit, -}; - diff --git a/drivers/gpu/drm/gma500/mdfld_output.c b/drivers/gpu/drm/gma500/mdfld_output.c deleted file mode 100644 index c95966b..0000000 --- a/drivers/gpu/drm/gma500/mdfld_output.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicensen - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Eaton - * Scott Rowe -*/ - -#include "mdfld_output.h" -#include "mdfld_dsi_dpi.h" -#include "mdfld_dsi_output.h" - -#include "tc35876x-dsi-lvds.h" - -int mdfld_get_panel_type(struct drm_device *dev, int pipe) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - return dev_priv->mdfld_panel_id; -} - -static void mdfld_init_panel(struct drm_device *dev, int mipi_pipe, - int p_type) -{ - switch (p_type) { - case TPO_VID: - mdfld_dsi_output_init(dev, mipi_pipe, &mdfld_tpo_vid_funcs); - break; - case TC35876X: - tc35876x_init(dev); - mdfld_dsi_output_init(dev, mipi_pipe, &mdfld_tc35876x_funcs); - break; - case TMD_VID: - mdfld_dsi_output_init(dev, mipi_pipe, &mdfld_tmd_vid_funcs); - break; - case HDMI: -/* if (dev_priv->mdfld_hdmi_present) - mdfld_hdmi_init(dev, &dev_priv->mode_dev); */ - break; - } -} - - -int mdfld_output_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - - /* FIXME: hardcoded for now */ - dev_priv->mdfld_panel_id = TC35876X; - /* MIPI panel 1 */ - mdfld_init_panel(dev, 0, dev_priv->mdfld_panel_id); - /* HDMI panel */ - mdfld_init_panel(dev, 1, HDMI); - return 0; -} - diff --git a/drivers/gpu/drm/gma500/mdfld_output.h b/drivers/gpu/drm/gma500/mdfld_output.h deleted file mode 100644 index ab2b27c..0000000 --- a/drivers/gpu/drm/gma500/mdfld_output.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicensen - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Eaton - * Scott Rowe -*/ - -#ifndef MDFLD_OUTPUT_H -#define MDFLD_OUTPUT_H - -#include "psb_drv.h" - -#define TPO_PANEL_WIDTH 84 -#define TPO_PANEL_HEIGHT 46 -#define TMD_PANEL_WIDTH 39 -#define TMD_PANEL_HEIGHT 71 - -struct mdfld_dsi_config; - -enum panel_type { - TPO_VID, - TMD_VID, - HDMI, - TC35876X, -}; - -struct panel_info { - u32 width_mm; - u32 height_mm; - /* Other info */ -}; - -struct panel_funcs { - const struct drm_encoder_funcs *encoder_funcs; - const struct drm_encoder_helper_funcs *encoder_helper_funcs; - struct drm_display_mode * (*get_config_mode)(struct drm_device *); - int (*get_panel_info)(struct drm_device *, int, struct panel_info *); - int (*reset)(int pipe); - void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe); -}; - -int mdfld_output_init(struct drm_device *dev); - -struct backlight_device *mdfld_get_backlight_device(void); -int mdfld_set_brightness(struct backlight_device *bd); - -int mdfld_get_panel_type(struct drm_device *dev, int pipe); - -extern const struct drm_crtc_helper_funcs mdfld_helper_funcs; - -extern const struct panel_funcs mdfld_tmd_vid_funcs; -extern const struct panel_funcs mdfld_tpo_vid_funcs; - -extern void mdfld_disable_crtc(struct drm_device *dev, int pipe); -extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe); -extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe); -#endif diff --git a/drivers/gpu/drm/gma500/mdfld_tmd_vid.c b/drivers/gpu/drm/gma500/mdfld_tmd_vid.c deleted file mode 100644 index dc0c6c3..0000000 --- a/drivers/gpu/drm/gma500/mdfld_tmd_vid.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Jim Liu - * Jackie Li - * Gideon Eaton - */ - -#include "mdfld_dsi_dpi.h" -#include "mdfld_dsi_pkg_sender.h" - -static struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev) -{ - struct drm_display_mode *mode; - struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD; - bool use_gct = false; /*Disable GCT for now*/ - - mode = kzalloc(sizeof(*mode), GFP_KERNEL); - if (!mode) - return NULL; - - if (use_gct) { - mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; - mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; - mode->hsync_start = mode->hdisplay + \ - ((ti->hsync_offset_hi << 8) | \ - ti->hsync_offset_lo); - mode->hsync_end = mode->hsync_start + \ - ((ti->hsync_pulse_width_hi << 8) | \ - ti->hsync_pulse_width_lo); - mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ - ti->hblank_lo); - mode->vsync_start = \ - mode->vdisplay + ((ti->vsync_offset_hi << 8) | \ - ti->vsync_offset_lo); - mode->vsync_end = \ - mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ - ti->vsync_pulse_width_lo); - mode->vtotal = mode->vdisplay + \ - ((ti->vblank_hi << 8) | ti->vblank_lo); - mode->clock = ti->pixel_clock * 10; - - dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); - dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); - dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); - dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); - dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); - dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); - dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); - dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); - dev_dbg(dev->dev, "clock is %d\n", mode->clock); - } else { - mode->hdisplay = 480; - mode->vdisplay = 854; - mode->hsync_start = 487; - mode->hsync_end = 490; - mode->htotal = 499; - mode->vsync_start = 861; - mode->vsync_end = 865; - mode->vtotal = 873; - mode->clock = 33264; - } - - drm_mode_set_name(mode); - drm_mode_set_crtcinfo(mode, 0); - - mode->type |= DRM_MODE_TYPE_PREFERRED; - - return mode; -} - -static int tmd_vid_get_panel_info(struct drm_device *dev, - int pipe, - struct panel_info *pi) -{ - if (!dev || !pi) - return -EINVAL; - - pi->width_mm = TMD_PANEL_WIDTH; - pi->height_mm = TMD_PANEL_HEIGHT; - - return 0; -} - -/* ************************************************************************* *\ - * FUNCTION: mdfld_init_TMD_MIPI - * - * DESCRIPTION: This function is called only by mrst_dsi_mode_set and - * restore_display_registers. since this function does not - * acquire the mutex, it is important that the calling function - * does! -\* ************************************************************************* */ - -/* FIXME: make the below data u8 instead of u32; note byte order! */ -static u32 tmd_cmd_mcap_off[] = {0x000000b2}; -static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef}; -static u32 tmd_cmd_set_lane_num[] = {0x006360ef}; -static u32 tmd_cmd_pushing_clock0[] = {0x00cc2fef}; -static u32 tmd_cmd_pushing_clock1[] = {0x00dd6eef}; -static u32 tmd_cmd_set_mode[] = {0x000000b3}; -static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef}; -static u32 tmd_cmd_set_column[] = {0x0100002a, 0x000000df}; -static u32 tmd_cmd_set_page[] = {0x0300002b, 0x00000055}; -static u32 tmd_cmd_set_video_mode[] = {0x00000153}; -/*no auto_bl,need add in furture*/ -static u32 tmd_cmd_enable_backlight[] = {0x00005ab4}; -static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd}; - -static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config, - int pipe) -{ - struct mdfld_dsi_pkg_sender *sender - = mdfld_dsi_get_pkg_sender(dsi_config); - - DRM_INFO("Enter mdfld init TMD MIPI display.\n"); - - if (!sender) { - DRM_ERROR("Cannot get sender\n"); - return; - } - - if (dsi_config->dvr_ic_inited) - return; - - msleep(3); - - /* FIXME: make the below data u8 instead of u32; note byte order! */ - - mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_mcap_off, - sizeof(tmd_cmd_mcap_off), false); - mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_lane_switch, - sizeof(tmd_cmd_enable_lane_switch), false); - mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_lane_num, - sizeof(tmd_cmd_set_lane_num), false); - mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock0, - sizeof(tmd_cmd_pushing_clock0), false); - mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock1, - sizeof(tmd_cmd_pushing_clock1), false); - mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_mode, - sizeof(tmd_cmd_set_mode), false); - mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_sync_pulse_mode, - sizeof(tmd_cmd_set_sync_pulse_mode), false); - mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_column, - sizeof(tmd_cmd_set_column), false); - mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_page, - sizeof(tmd_cmd_set_page), false); - mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_video_mode, - sizeof(tmd_cmd_set_video_mode), false); - mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_backlight, - sizeof(tmd_cmd_enable_backlight), false); - mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_backlight_dimming, - sizeof(tmd_cmd_set_backlight_dimming), false); - - dsi_config->dvr_ic_inited = 1; -} - -/*TPO DPI encoder helper funcs*/ -static const struct drm_encoder_helper_funcs - mdfld_tpo_dpi_encoder_helper_funcs = { - .dpms = mdfld_dsi_dpi_dpms, - .mode_fixup = mdfld_dsi_dpi_mode_fixup, - .prepare = mdfld_dsi_dpi_prepare, - .mode_set = mdfld_dsi_dpi_mode_set, - .commit = mdfld_dsi_dpi_commit, -}; - -/*TPO DPI encoder funcs*/ -static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = { - .destroy = drm_encoder_cleanup, -}; - -const struct panel_funcs mdfld_tmd_vid_funcs = { - .encoder_funcs = &mdfld_tpo_dpi_encoder_funcs, - .encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs, - .get_config_mode = &tmd_vid_get_config_mode, - .get_panel_info = tmd_vid_get_panel_info, - .reset = mdfld_dsi_panel_reset, - .drv_ic_init = mdfld_dsi_tmd_drv_ic_init, -}; diff --git a/drivers/gpu/drm/gma500/mdfld_tpo_vid.c b/drivers/gpu/drm/gma500/mdfld_tpo_vid.c deleted file mode 100644 index d8d4170..0000000 --- a/drivers/gpu/drm/gma500/mdfld_tpo_vid.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * jim liu - * Jackie Li - */ - -#include "mdfld_dsi_dpi.h" - -static struct drm_display_mode *tpo_vid_get_config_mode(struct drm_device *dev) -{ - struct drm_display_mode *mode; - struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD; - bool use_gct = false; - - mode = kzalloc(sizeof(*mode), GFP_KERNEL); - if (!mode) - return NULL; - - if (use_gct) { - mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; - mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; - mode->hsync_start = mode->hdisplay + - ((ti->hsync_offset_hi << 8) | - ti->hsync_offset_lo); - mode->hsync_end = mode->hsync_start + - ((ti->hsync_pulse_width_hi << 8) | - ti->hsync_pulse_width_lo); - mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | - ti->hblank_lo); - mode->vsync_start = - mode->vdisplay + ((ti->vsync_offset_hi << 8) | - ti->vsync_offset_lo); - mode->vsync_end = - mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | - ti->vsync_pulse_width_lo); - mode->vtotal = mode->vdisplay + - ((ti->vblank_hi << 8) | ti->vblank_lo); - mode->clock = ti->pixel_clock * 10; - - dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); - dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); - dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); - dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); - dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); - dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); - dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); - dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); - dev_dbg(dev->dev, "clock is %d\n", mode->clock); - } else { - mode->hdisplay = 864; - mode->vdisplay = 480; - mode->hsync_start = 873; - mode->hsync_end = 876; - mode->htotal = 887; - mode->vsync_start = 487; - mode->vsync_end = 490; - mode->vtotal = 499; - mode->clock = 33264; - } - - drm_mode_set_name(mode); - drm_mode_set_crtcinfo(mode, 0); - - mode->type |= DRM_MODE_TYPE_PREFERRED; - - return mode; -} - -static int tpo_vid_get_panel_info(struct drm_device *dev, - int pipe, - struct panel_info *pi) -{ - if (!dev || !pi) - return -EINVAL; - - pi->width_mm = TPO_PANEL_WIDTH; - pi->height_mm = TPO_PANEL_HEIGHT; - - return 0; -} - -/*TPO DPI encoder helper funcs*/ -static const struct drm_encoder_helper_funcs - mdfld_tpo_dpi_encoder_helper_funcs = { - .dpms = mdfld_dsi_dpi_dpms, - .mode_fixup = mdfld_dsi_dpi_mode_fixup, - .prepare = mdfld_dsi_dpi_prepare, - .mode_set = mdfld_dsi_dpi_mode_set, - .commit = mdfld_dsi_dpi_commit, -}; - -/*TPO DPI encoder funcs*/ -static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = { - .destroy = drm_encoder_cleanup, -}; - -const struct panel_funcs mdfld_tpo_vid_funcs = { - .encoder_funcs = &mdfld_tpo_dpi_encoder_funcs, - .encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs, - .get_config_mode = &tpo_vid_get_config_mode, - .get_panel_info = tpo_vid_get_panel_info, -}; diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c deleted file mode 100644 index 5eee9ad..0000000 --- a/drivers/gpu/drm/gma500/mid_bios.c +++ /dev/null @@ -1,263 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - **************************************************************************/ - -/* TODO - * - Split functions by vbt type - * - Make them all take drm_device - * - Check ioremap failures - */ - -#include -#include -#include "gma_drm.h" -#include "psb_drv.h" -#include "mid_bios.h" - -static void mid_get_fuse_settings(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); - uint32_t fuse_value = 0; - uint32_t fuse_value_tmp = 0; - -#define FB_REG06 0xD0810600 -#define FB_MIPI_DISABLE (1 << 11) -#define FB_REG09 0xD0810900 -#define FB_REG09 0xD0810900 -#define FB_SKU_MASK 0x7000 -#define FB_SKU_SHIFT 12 -#define FB_SKU_100 0 -#define FB_SKU_100L 1 -#define FB_SKU_83 2 - if (pci_root == NULL) { - WARN_ON(1); - return; - } - - - pci_write_config_dword(pci_root, 0xD0, FB_REG06); - pci_read_config_dword(pci_root, 0xD4, &fuse_value); - - /* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */ - if (IS_MRST(dev)) - dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE; - - DRM_INFO("internal display is %s\n", - dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display"); - - /* Prevent runtime suspend at start*/ - if (dev_priv->iLVDS_enable) { - dev_priv->is_lvds_on = true; - dev_priv->is_mipi_on = false; - } else { - dev_priv->is_mipi_on = true; - dev_priv->is_lvds_on = false; - } - - dev_priv->video_device_fuse = fuse_value; - - pci_write_config_dword(pci_root, 0xD0, FB_REG09); - pci_read_config_dword(pci_root, 0xD4, &fuse_value); - - dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value); - fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT; - - dev_priv->fuse_reg_value = fuse_value; - - switch (fuse_value_tmp) { - case FB_SKU_100: - dev_priv->core_freq = 200; - break; - case FB_SKU_100L: - dev_priv->core_freq = 100; - break; - case FB_SKU_83: - dev_priv->core_freq = 166; - break; - default: - dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n", - fuse_value_tmp); - dev_priv->core_freq = 0; - } - dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq); - pci_dev_put(pci_root); -} - -/* - * Get the revison ID, B0:D2:F0;0x08 - */ -static void mid_get_pci_revID(struct drm_psb_private *dev_priv) -{ - uint32_t platform_rev_id = 0; - struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); - - if (pci_gfx_root == NULL) { - WARN_ON(1); - return; - } - pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id); - dev_priv->platform_rev_id = (uint8_t) platform_rev_id; - pci_dev_put(pci_gfx_root); - dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n", - dev_priv->platform_rev_id); -} - -static void mid_get_vbt_data(struct drm_psb_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - struct oaktrail_vbt *vbt = &dev_priv->vbt_data; - u32 addr; - u16 new_size; - u8 *vbt_virtual; - u8 bpi; - u8 number_desc = 0; - struct oaktrail_timing_info *dp_ti = &dev_priv->gct_data.DTD; - struct gct_r10_timing_info ti; - void *pGCT; - struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); - - /* Get the address of the platform config vbt, B0:D2:F0;0xFC */ - pci_read_config_dword(pci_gfx_root, 0xFC, &addr); - pci_dev_put(pci_gfx_root); - - dev_dbg(dev->dev, "drm platform config address is %x\n", addr); - - /* check for platform config address == 0. */ - /* this means fw doesn't support vbt */ - - if (addr == 0) { - vbt->size = 0; - return; - } - - /* get the virtual address of the vbt */ - vbt_virtual = ioremap(addr, sizeof(*vbt)); - if (vbt_virtual == NULL) { - vbt->size = 0; - return; - } - - memcpy(vbt, vbt_virtual, sizeof(*vbt)); - iounmap(vbt_virtual); /* Free virtual address space */ - - /* No matching signature don't process the data */ - if (memcmp(vbt->signature, "$GCT", 4)) { - vbt->size = 0; - return; - } - - dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision); - - switch (vbt->revision) { - case 0: - vbt->oaktrail_gct = ioremap(addr + sizeof(*vbt) - 4, - vbt->size - sizeof(*vbt) + 4); - pGCT = vbt->oaktrail_gct; - bpi = ((struct oaktrail_gct_v1 *)pGCT)->PD.BootPanelIndex; - dev_priv->gct_data.bpi = bpi; - dev_priv->gct_data.pt = - ((struct oaktrail_gct_v1 *)pGCT)->PD.PanelType; - memcpy(&dev_priv->gct_data.DTD, - &((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].DTD, - sizeof(struct oaktrail_timing_info)); - dev_priv->gct_data.Panel_Port_Control = - ((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control; - dev_priv->gct_data.Panel_MIPI_Display_Descriptor = - ((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; - break; - case 1: - vbt->oaktrail_gct = ioremap(addr + sizeof(*vbt) - 4, - vbt->size - sizeof(*vbt) + 4); - pGCT = vbt->oaktrail_gct; - bpi = ((struct oaktrail_gct_v2 *)pGCT)->PD.BootPanelIndex; - dev_priv->gct_data.bpi = bpi; - dev_priv->gct_data.pt = - ((struct oaktrail_gct_v2 *)pGCT)->PD.PanelType; - memcpy(&dev_priv->gct_data.DTD, - &((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].DTD, - sizeof(struct oaktrail_timing_info)); - dev_priv->gct_data.Panel_Port_Control = - ((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control; - dev_priv->gct_data.Panel_MIPI_Display_Descriptor = - ((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; - break; - case 0x10: - /*header definition changed from rev 01 (v2) to rev 10h. */ - /*so, some values have changed location*/ - new_size = vbt->checksum; /*checksum contains lo size byte*/ - /*LSB of oaktrail_gct contains hi size byte*/ - new_size |= ((0xff & (unsigned int)(long)vbt->oaktrail_gct)) << 8; - - vbt->checksum = vbt->size; /*size contains the checksum*/ - if (new_size > 0xff) - vbt->size = 0xff; /*restrict size to 255*/ - else - vbt->size = new_size; - - /* number of descriptors defined in the GCT */ - number_desc = ((0xff00 & (unsigned int)(long)vbt->oaktrail_gct)) >> 8; - bpi = ((0xff0000 & (unsigned int)(long)vbt->oaktrail_gct)) >> 16; - vbt->oaktrail_gct = ioremap(addr + GCT_R10_HEADER_SIZE, - GCT_R10_DISPLAY_DESC_SIZE * number_desc); - pGCT = vbt->oaktrail_gct; - pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE); - dev_priv->gct_data.bpi = bpi; /*save boot panel id*/ - - /*copy the GCT display timings into a temp structure*/ - memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info)); - - /*now copy the temp struct into the dev_priv->gct_data*/ - dp_ti->pixel_clock = ti.pixel_clock; - dp_ti->hactive_hi = ti.hactive_hi; - dp_ti->hactive_lo = ti.hactive_lo; - dp_ti->hblank_hi = ti.hblank_hi; - dp_ti->hblank_lo = ti.hblank_lo; - dp_ti->hsync_offset_hi = ti.hsync_offset_hi; - dp_ti->hsync_offset_lo = ti.hsync_offset_lo; - dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi; - dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo; - dp_ti->vactive_hi = ti.vactive_hi; - dp_ti->vactive_lo = ti.vactive_lo; - dp_ti->vblank_hi = ti.vblank_hi; - dp_ti->vblank_lo = ti.vblank_lo; - dp_ti->vsync_offset_hi = ti.vsync_offset_hi; - dp_ti->vsync_offset_lo = ti.vsync_offset_lo; - dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi; - dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo; - - /* Move the MIPI_Display_Descriptor data from GCT to dev priv */ - dev_priv->gct_data.Panel_MIPI_Display_Descriptor = - *((u8 *)pGCT + 0x0d); - dev_priv->gct_data.Panel_MIPI_Display_Descriptor |= - (*((u8 *)pGCT + 0x0e)) << 8; - break; - default: - dev_err(dev->dev, "Unknown revision of GCT!\n"); - vbt->size = 0; - } -} - -int mid_chip_setup(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - mid_get_fuse_settings(dev); - mid_get_vbt_data(dev_priv); - mid_get_pci_revID(dev_priv); - return 0; -} diff --git a/drivers/gpu/drm/gma500/mid_bios.h b/drivers/gpu/drm/gma500/mid_bios.h deleted file mode 100644 index 00e7d56..0000000 --- a/drivers/gpu/drm/gma500/mid_bios.h +++ /dev/null @@ -1,21 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - **************************************************************************/ - -extern int mid_chip_setup(struct drm_device *dev); - diff --git a/drivers/gpu/drm/gma500/mmu.c b/drivers/gpu/drm/gma500/mmu.c deleted file mode 100644 index c5dd4d2..0000000 --- a/drivers/gpu/drm/gma500/mmu.c +++ /dev/null @@ -1,849 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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 "psb_drv.h" -#include "psb_reg.h" - -/* - * Code for the SGX MMU: - */ - -/* - * clflush on one processor only: - * clflush should apparently flush the cache line on all processors in an - * SMP system. - */ - -/* - * kmap atomic: - * The usage of the slots must be completely encapsulated within a spinlock, and - * no other functions that may be using the locks for other purposed may be - * called from within the locked region. - * Since the slots are per processor, this will guarantee that we are the only - * user. - */ - -/* - * TODO: Inserting ptes from an interrupt handler: - * This may be desirable for some SGX functionality where the GPU can fault in - * needed pages. For that, we need to make an atomic insert_pages function, that - * may fail. - * If it fails, the caller need to insert the page using a workqueue function, - * but on average it should be fast. - */ - -struct psb_mmu_driver { - /* protects driver- and pd structures. Always take in read mode - * before taking the page table spinlock. - */ - struct rw_semaphore sem; - - /* protects page tables, directory tables and pt tables. - * and pt structures. - */ - spinlock_t lock; - - atomic_t needs_tlbflush; - - uint8_t __iomem *register_map; - struct psb_mmu_pd *default_pd; - /*uint32_t bif_ctrl;*/ - int has_clflush; - int clflush_add; - unsigned long clflush_mask; - - struct drm_psb_private *dev_priv; -}; - -struct psb_mmu_pd; - -struct psb_mmu_pt { - struct psb_mmu_pd *pd; - uint32_t index; - uint32_t count; - struct page *p; - uint32_t *v; -}; - -struct psb_mmu_pd { - struct psb_mmu_driver *driver; - int hw_context; - struct psb_mmu_pt **tables; - struct page *p; - struct page *dummy_pt; - struct page *dummy_page; - uint32_t pd_mask; - uint32_t invalid_pde; - uint32_t invalid_pte; -}; - -static inline uint32_t psb_mmu_pt_index(uint32_t offset) -{ - return (offset >> PSB_PTE_SHIFT) & 0x3FF; -} - -static inline uint32_t psb_mmu_pd_index(uint32_t offset) -{ - return offset >> PSB_PDE_SHIFT; -} - -static inline void psb_clflush(void *addr) -{ - __asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory"); -} - -static inline void psb_mmu_clflush(struct psb_mmu_driver *driver, - void *addr) -{ - if (!driver->has_clflush) - return; - - mb(); - psb_clflush(addr); - mb(); -} - -static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page) -{ - uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT; - uint32_t clflush_count = PAGE_SIZE / clflush_add; - int i; - uint8_t *clf; - - clf = kmap_atomic(page, KM_USER0); - mb(); - for (i = 0; i < clflush_count; ++i) { - psb_clflush(clf); - clf += clflush_add; - } - mb(); - kunmap_atomic(clf, KM_USER0); -} - -static void psb_pages_clflush(struct psb_mmu_driver *driver, - struct page *page[], unsigned long num_pages) -{ - int i; - - if (!driver->has_clflush) - return ; - - for (i = 0; i < num_pages; i++) - psb_page_clflush(driver, *page++); -} - -static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver, - int force) -{ - atomic_set(&driver->needs_tlbflush, 0); -} - -static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force) -{ - down_write(&driver->sem); - psb_mmu_flush_pd_locked(driver, force); - up_write(&driver->sem); -} - -void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot) -{ - if (rc_prot) - down_write(&driver->sem); - if (rc_prot) - up_write(&driver->sem); -} - -void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context) -{ - /*ttm_tt_cache_flush(&pd->p, 1);*/ - psb_pages_clflush(pd->driver, &pd->p, 1); - down_write(&pd->driver->sem); - wmb(); - psb_mmu_flush_pd_locked(pd->driver, 1); - pd->hw_context = hw_context; - up_write(&pd->driver->sem); - -} - -static inline unsigned long psb_pd_addr_end(unsigned long addr, - unsigned long end) -{ - - addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK; - return (addr < end) ? addr : end; -} - -static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type) -{ - uint32_t mask = PSB_PTE_VALID; - - if (type & PSB_MMU_CACHED_MEMORY) - mask |= PSB_PTE_CACHED; - if (type & PSB_MMU_RO_MEMORY) - mask |= PSB_PTE_RO; - if (type & PSB_MMU_WO_MEMORY) - mask |= PSB_PTE_WO; - - return (pfn << PAGE_SHIFT) | mask; -} - -struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver, - int trap_pagefaults, int invalid_type) -{ - struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL); - uint32_t *v; - int i; - - if (!pd) - return NULL; - - pd->p = alloc_page(GFP_DMA32); - if (!pd->p) - goto out_err1; - pd->dummy_pt = alloc_page(GFP_DMA32); - if (!pd->dummy_pt) - goto out_err2; - pd->dummy_page = alloc_page(GFP_DMA32); - if (!pd->dummy_page) - goto out_err3; - - if (!trap_pagefaults) { - pd->invalid_pde = - psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt), - invalid_type); - pd->invalid_pte = - psb_mmu_mask_pte(page_to_pfn(pd->dummy_page), - invalid_type); - } else { - pd->invalid_pde = 0; - pd->invalid_pte = 0; - } - - v = kmap(pd->dummy_pt); - for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) - v[i] = pd->invalid_pte; - - kunmap(pd->dummy_pt); - - v = kmap(pd->p); - for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) - v[i] = pd->invalid_pde; - - kunmap(pd->p); - - clear_page(kmap(pd->dummy_page)); - kunmap(pd->dummy_page); - - pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024); - if (!pd->tables) - goto out_err4; - - pd->hw_context = -1; - pd->pd_mask = PSB_PTE_VALID; - pd->driver = driver; - - return pd; - -out_err4: - __free_page(pd->dummy_page); -out_err3: - __free_page(pd->dummy_pt); -out_err2: - __free_page(pd->p); -out_err1: - kfree(pd); - return NULL; -} - -static void psb_mmu_free_pt(struct psb_mmu_pt *pt) -{ - __free_page(pt->p); - kfree(pt); -} - -void psb_mmu_free_pagedir(struct psb_mmu_pd *pd) -{ - struct psb_mmu_driver *driver = pd->driver; - struct psb_mmu_pt *pt; - int i; - - down_write(&driver->sem); - if (pd->hw_context != -1) - psb_mmu_flush_pd_locked(driver, 1); - - /* Should take the spinlock here, but we don't need to do that - since we have the semaphore in write mode. */ - - for (i = 0; i < 1024; ++i) { - pt = pd->tables[i]; - if (pt) - psb_mmu_free_pt(pt); - } - - vfree(pd->tables); - __free_page(pd->dummy_page); - __free_page(pd->dummy_pt); - __free_page(pd->p); - kfree(pd); - up_write(&driver->sem); -} - -static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd) -{ - struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL); - void *v; - uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT; - uint32_t clflush_count = PAGE_SIZE / clflush_add; - spinlock_t *lock = &pd->driver->lock; - uint8_t *clf; - uint32_t *ptes; - int i; - - if (!pt) - return NULL; - - pt->p = alloc_page(GFP_DMA32); - if (!pt->p) { - kfree(pt); - return NULL; - } - - spin_lock(lock); - - v = kmap_atomic(pt->p, KM_USER0); - clf = (uint8_t *) v; - ptes = (uint32_t *) v; - for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) - *ptes++ = pd->invalid_pte; - - - if (pd->driver->has_clflush && pd->hw_context != -1) { - mb(); - for (i = 0; i < clflush_count; ++i) { - psb_clflush(clf); - clf += clflush_add; - } - mb(); - } - - kunmap_atomic(v, KM_USER0); - spin_unlock(lock); - - pt->count = 0; - pt->pd = pd; - pt->index = 0; - - return pt; -} - -static struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd, - unsigned long addr) -{ - uint32_t index = psb_mmu_pd_index(addr); - struct psb_mmu_pt *pt; - uint32_t *v; - spinlock_t *lock = &pd->driver->lock; - - spin_lock(lock); - pt = pd->tables[index]; - while (!pt) { - spin_unlock(lock); - pt = psb_mmu_alloc_pt(pd); - if (!pt) - return NULL; - spin_lock(lock); - - if (pd->tables[index]) { - spin_unlock(lock); - psb_mmu_free_pt(pt); - spin_lock(lock); - pt = pd->tables[index]; - continue; - } - - v = kmap_atomic(pd->p, KM_USER0); - pd->tables[index] = pt; - v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask; - pt->index = index; - kunmap_atomic((void *) v, KM_USER0); - - if (pd->hw_context != -1) { - psb_mmu_clflush(pd->driver, (void *) &v[index]); - atomic_set(&pd->driver->needs_tlbflush, 1); - } - } - pt->v = kmap_atomic(pt->p, KM_USER0); - return pt; -} - -static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd, - unsigned long addr) -{ - uint32_t index = psb_mmu_pd_index(addr); - struct psb_mmu_pt *pt; - spinlock_t *lock = &pd->driver->lock; - - spin_lock(lock); - pt = pd->tables[index]; - if (!pt) { - spin_unlock(lock); - return NULL; - } - pt->v = kmap_atomic(pt->p, KM_USER0); - return pt; -} - -static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt) -{ - struct psb_mmu_pd *pd = pt->pd; - uint32_t *v; - - kunmap_atomic(pt->v, KM_USER0); - if (pt->count == 0) { - v = kmap_atomic(pd->p, KM_USER0); - v[pt->index] = pd->invalid_pde; - pd->tables[pt->index] = NULL; - - if (pd->hw_context != -1) { - psb_mmu_clflush(pd->driver, - (void *) &v[pt->index]); - atomic_set(&pd->driver->needs_tlbflush, 1); - } - kunmap_atomic(pt->v, KM_USER0); - spin_unlock(&pd->driver->lock); - psb_mmu_free_pt(pt); - return; - } - spin_unlock(&pd->driver->lock); -} - -static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt, - unsigned long addr, uint32_t pte) -{ - pt->v[psb_mmu_pt_index(addr)] = pte; -} - -static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt, - unsigned long addr) -{ - pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte; -} - - -void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, - uint32_t mmu_offset, uint32_t gtt_start, - uint32_t gtt_pages) -{ - uint32_t *v; - uint32_t start = psb_mmu_pd_index(mmu_offset); - struct psb_mmu_driver *driver = pd->driver; - int num_pages = gtt_pages; - - down_read(&driver->sem); - spin_lock(&driver->lock); - - v = kmap_atomic(pd->p, KM_USER0); - v += start; - - while (gtt_pages--) { - *v++ = gtt_start | pd->pd_mask; - gtt_start += PAGE_SIZE; - } - - /*ttm_tt_cache_flush(&pd->p, num_pages);*/ - psb_pages_clflush(pd->driver, &pd->p, num_pages); - kunmap_atomic(v, KM_USER0); - spin_unlock(&driver->lock); - - if (pd->hw_context != -1) - atomic_set(&pd->driver->needs_tlbflush, 1); - - up_read(&pd->driver->sem); - psb_mmu_flush_pd(pd->driver, 0); -} - -struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver) -{ - struct psb_mmu_pd *pd; - - /* down_read(&driver->sem); */ - pd = driver->default_pd; - /* up_read(&driver->sem); */ - - return pd; -} - -void psb_mmu_driver_takedown(struct psb_mmu_driver *driver) -{ - psb_mmu_free_pagedir(driver->default_pd); - kfree(driver); -} - -struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers, - int trap_pagefaults, - int invalid_type, - struct drm_psb_private *dev_priv) -{ - struct psb_mmu_driver *driver; - - driver = kmalloc(sizeof(*driver), GFP_KERNEL); - - if (!driver) - return NULL; - driver->dev_priv = dev_priv; - - driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults, - invalid_type); - if (!driver->default_pd) - goto out_err1; - - spin_lock_init(&driver->lock); - init_rwsem(&driver->sem); - down_write(&driver->sem); - driver->register_map = registers; - atomic_set(&driver->needs_tlbflush, 1); - - driver->has_clflush = 0; - - if (boot_cpu_has(X86_FEATURE_CLFLSH)) { - uint32_t tfms, misc, cap0, cap4, clflush_size; - - /* - * clflush size is determined at kernel setup for x86_64 - * but not for i386. We have to do it here. - */ - - cpuid(0x00000001, &tfms, &misc, &cap0, &cap4); - clflush_size = ((misc >> 8) & 0xff) * 8; - driver->has_clflush = 1; - driver->clflush_add = - PAGE_SIZE * clflush_size / sizeof(uint32_t); - driver->clflush_mask = driver->clflush_add - 1; - driver->clflush_mask = ~driver->clflush_mask; - } - - up_write(&driver->sem); - return driver; - -out_err1: - kfree(driver); - return NULL; -} - -static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd, - unsigned long address, uint32_t num_pages, - uint32_t desired_tile_stride, - uint32_t hw_tile_stride) -{ - struct psb_mmu_pt *pt; - uint32_t rows = 1; - uint32_t i; - unsigned long addr; - unsigned long end; - unsigned long next; - unsigned long add; - unsigned long row_add; - unsigned long clflush_add = pd->driver->clflush_add; - unsigned long clflush_mask = pd->driver->clflush_mask; - - if (!pd->driver->has_clflush) { - /*ttm_tt_cache_flush(&pd->p, num_pages);*/ - psb_pages_clflush(pd->driver, &pd->p, num_pages); - return; - } - - if (hw_tile_stride) - rows = num_pages / desired_tile_stride; - else - desired_tile_stride = num_pages; - - add = desired_tile_stride << PAGE_SHIFT; - row_add = hw_tile_stride << PAGE_SHIFT; - mb(); - for (i = 0; i < rows; ++i) { - - addr = address; - end = addr + add; - - do { - next = psb_pd_addr_end(addr, end); - pt = psb_mmu_pt_map_lock(pd, addr); - if (!pt) - continue; - do { - psb_clflush(&pt->v - [psb_mmu_pt_index(addr)]); - } while (addr += - clflush_add, - (addr & clflush_mask) < next); - - psb_mmu_pt_unmap_unlock(pt); - } while (addr = next, next != end); - address += row_add; - } - mb(); -} - -void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd, - unsigned long address, uint32_t num_pages) -{ - struct psb_mmu_pt *pt; - unsigned long addr; - unsigned long end; - unsigned long next; - unsigned long f_address = address; - - down_read(&pd->driver->sem); - - addr = address; - end = addr + (num_pages << PAGE_SHIFT); - - do { - next = psb_pd_addr_end(addr, end); - pt = psb_mmu_pt_alloc_map_lock(pd, addr); - if (!pt) - goto out; - do { - psb_mmu_invalidate_pte(pt, addr); - --pt->count; - } while (addr += PAGE_SIZE, addr < next); - psb_mmu_pt_unmap_unlock(pt); - - } while (addr = next, next != end); - -out: - if (pd->hw_context != -1) - psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1); - - up_read(&pd->driver->sem); - - if (pd->hw_context != -1) - psb_mmu_flush(pd->driver, 0); - - return; -} - -void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address, - uint32_t num_pages, uint32_t desired_tile_stride, - uint32_t hw_tile_stride) -{ - struct psb_mmu_pt *pt; - uint32_t rows = 1; - uint32_t i; - unsigned long addr; - unsigned long end; - unsigned long next; - unsigned long add; - unsigned long row_add; - unsigned long f_address = address; - - if (hw_tile_stride) - rows = num_pages / desired_tile_stride; - else - desired_tile_stride = num_pages; - - add = desired_tile_stride << PAGE_SHIFT; - row_add = hw_tile_stride << PAGE_SHIFT; - - /* down_read(&pd->driver->sem); */ - - /* Make sure we only need to flush this processor's cache */ - - for (i = 0; i < rows; ++i) { - - addr = address; - end = addr + add; - - do { - next = psb_pd_addr_end(addr, end); - pt = psb_mmu_pt_map_lock(pd, addr); - if (!pt) - continue; - do { - psb_mmu_invalidate_pte(pt, addr); - --pt->count; - - } while (addr += PAGE_SIZE, addr < next); - psb_mmu_pt_unmap_unlock(pt); - - } while (addr = next, next != end); - address += row_add; - } - if (pd->hw_context != -1) - psb_mmu_flush_ptes(pd, f_address, num_pages, - desired_tile_stride, hw_tile_stride); - - /* up_read(&pd->driver->sem); */ - - if (pd->hw_context != -1) - psb_mmu_flush(pd->driver, 0); -} - -int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn, - unsigned long address, uint32_t num_pages, - int type) -{ - struct psb_mmu_pt *pt; - uint32_t pte; - unsigned long addr; - unsigned long end; - unsigned long next; - unsigned long f_address = address; - int ret = 0; - - down_read(&pd->driver->sem); - - addr = address; - end = addr + (num_pages << PAGE_SHIFT); - - do { - next = psb_pd_addr_end(addr, end); - pt = psb_mmu_pt_alloc_map_lock(pd, addr); - if (!pt) { - ret = -ENOMEM; - goto out; - } - do { - pte = psb_mmu_mask_pte(start_pfn++, type); - psb_mmu_set_pte(pt, addr, pte); - pt->count++; - } while (addr += PAGE_SIZE, addr < next); - psb_mmu_pt_unmap_unlock(pt); - - } while (addr = next, next != end); - -out: - if (pd->hw_context != -1) - psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1); - - up_read(&pd->driver->sem); - - if (pd->hw_context != -1) - psb_mmu_flush(pd->driver, 1); - - return ret; -} - -int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages, - unsigned long address, uint32_t num_pages, - uint32_t desired_tile_stride, - uint32_t hw_tile_stride, int type) -{ - struct psb_mmu_pt *pt; - uint32_t rows = 1; - uint32_t i; - uint32_t pte; - unsigned long addr; - unsigned long end; - unsigned long next; - unsigned long add; - unsigned long row_add; - unsigned long f_address = address; - int ret = 0; - - if (hw_tile_stride) { - if (num_pages % desired_tile_stride != 0) - return -EINVAL; - rows = num_pages / desired_tile_stride; - } else { - desired_tile_stride = num_pages; - } - - add = desired_tile_stride << PAGE_SHIFT; - row_add = hw_tile_stride << PAGE_SHIFT; - - down_read(&pd->driver->sem); - - for (i = 0; i < rows; ++i) { - - addr = address; - end = addr + add; - - do { - next = psb_pd_addr_end(addr, end); - pt = psb_mmu_pt_alloc_map_lock(pd, addr); - if (!pt) { - ret = -ENOMEM; - goto out; - } - do { - pte = - psb_mmu_mask_pte(page_to_pfn(*pages++), - type); - psb_mmu_set_pte(pt, addr, pte); - pt->count++; - } while (addr += PAGE_SIZE, addr < next); - psb_mmu_pt_unmap_unlock(pt); - - } while (addr = next, next != end); - - address += row_add; - } -out: - if (pd->hw_context != -1) - psb_mmu_flush_ptes(pd, f_address, num_pages, - desired_tile_stride, hw_tile_stride); - - up_read(&pd->driver->sem); - - if (pd->hw_context != -1) - psb_mmu_flush(pd->driver, 1); - - return ret; -} - -int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual, - unsigned long *pfn) -{ - int ret; - struct psb_mmu_pt *pt; - uint32_t tmp; - spinlock_t *lock = &pd->driver->lock; - - down_read(&pd->driver->sem); - pt = psb_mmu_pt_map_lock(pd, virtual); - if (!pt) { - uint32_t *v; - - spin_lock(lock); - v = kmap_atomic(pd->p, KM_USER0); - tmp = v[psb_mmu_pd_index(virtual)]; - kunmap_atomic(v, KM_USER0); - spin_unlock(lock); - - if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) || - !(pd->invalid_pte & PSB_PTE_VALID)) { - ret = -EINVAL; - goto out; - } - ret = 0; - *pfn = pd->invalid_pte >> PAGE_SHIFT; - goto out; - } - tmp = pt->v[psb_mmu_pt_index(virtual)]; - if (!(tmp & PSB_PTE_VALID)) { - ret = -EINVAL; - } else { - ret = 0; - *pfn = tmp >> PAGE_SHIFT; - } - psb_mmu_pt_unmap_unlock(pt); -out: - up_read(&pd->driver->sem); - return ret; -} diff --git a/drivers/gpu/drm/gma500/oaktrail.h b/drivers/gpu/drm/gma500/oaktrail.h deleted file mode 100644 index 2da1f36..0000000 --- a/drivers/gpu/drm/gma500/oaktrail.h +++ /dev/null @@ -1,252 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - **************************************************************************/ - -/* MID device specific descriptors */ - -struct oaktrail_vbt { - s8 signature[4]; /*4 bytes,"$GCT" */ - u8 revision; - u8 size; - u8 checksum; - void *oaktrail_gct; -} __packed; - -struct oaktrail_timing_info { - u16 pixel_clock; - u8 hactive_lo; - u8 hblank_lo; - u8 hblank_hi:4; - u8 hactive_hi:4; - u8 vactive_lo; - u8 vblank_lo; - u8 vblank_hi:4; - u8 vactive_hi:4; - u8 hsync_offset_lo; - u8 hsync_pulse_width_lo; - u8 vsync_pulse_width_lo:4; - u8 vsync_offset_lo:4; - u8 vsync_pulse_width_hi:2; - u8 vsync_offset_hi:2; - u8 hsync_pulse_width_hi:2; - u8 hsync_offset_hi:2; - u8 width_mm_lo; - u8 height_mm_lo; - u8 height_mm_hi:4; - u8 width_mm_hi:4; - u8 hborder; - u8 vborder; - u8 unknown0:1; - u8 hsync_positive:1; - u8 vsync_positive:1; - u8 separate_sync:2; - u8 stereo:1; - u8 unknown6:1; - u8 interlaced:1; -} __packed; - -struct gct_r10_timing_info { - u16 pixel_clock; - u32 hactive_lo:8; - u32 hactive_hi:4; - u32 hblank_lo:8; - u32 hblank_hi:4; - u32 hsync_offset_lo:8; - u16 hsync_offset_hi:2; - u16 hsync_pulse_width_lo:8; - u16 hsync_pulse_width_hi:2; - u16 hsync_positive:1; - u16 rsvd_1:3; - u8 vactive_lo:8; - u16 vactive_hi:4; - u16 vblank_lo:8; - u16 vblank_hi:4; - u16 vsync_offset_lo:4; - u16 vsync_offset_hi:2; - u16 vsync_pulse_width_lo:4; - u16 vsync_pulse_width_hi:2; - u16 vsync_positive:1; - u16 rsvd_2:3; -} __packed; - -struct oaktrail_panel_descriptor_v1 { - u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */ - /* 0x61190 if MIPI */ - u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/ - u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/ - u32 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 dword */ - /* Register 0x61210 */ - struct oaktrail_timing_info DTD;/*18 bytes, Standard definition */ - u16 Panel_Backlight_Inverter_Descriptor;/* 16 bits, as follows */ - /* Bit 0, Frequency, 15 bits,0 - 32767Hz */ - /* Bit 15, Polarity, 1 bit, 0: Normal, 1: Inverted */ - u16 Panel_MIPI_Display_Descriptor; - /*16 bits, Defined as follows: */ - /* if MIPI, 0x0000 if LVDS */ - /* Bit 0, Type, 2 bits, */ - /* 0: Type-1, */ - /* 1: Type-2, */ - /* 2: Type-3, */ - /* 3: Type-4 */ - /* Bit 2, Pixel Format, 4 bits */ - /* Bit0: 16bpp (not supported in LNC), */ - /* Bit1: 18bpp loosely packed, */ - /* Bit2: 18bpp packed, */ - /* Bit3: 24bpp */ - /* Bit 6, Reserved, 2 bits, 00b */ - /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */ - /* Bit 14, Reserved, 2 bits, 00b */ -} __packed; - -struct oaktrail_panel_descriptor_v2 { - u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */ - /* 0x61190 if MIPI */ - u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/ - u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/ - u8 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 byte */ - /* Register 0x61210 */ - struct oaktrail_timing_info DTD;/*18 bytes, Standard definition */ - u16 Panel_Backlight_Inverter_Descriptor;/*16 bits, as follows*/ - /*Bit 0, Frequency, 16 bits, 0 - 32767Hz*/ - u8 Panel_Initial_Brightness;/* [7:0] 0 - 100% */ - /*Bit 7, Polarity, 1 bit,0: Normal, 1: Inverted*/ - u16 Panel_MIPI_Display_Descriptor; - /*16 bits, Defined as follows: */ - /* if MIPI, 0x0000 if LVDS */ - /* Bit 0, Type, 2 bits, */ - /* 0: Type-1, */ - /* 1: Type-2, */ - /* 2: Type-3, */ - /* 3: Type-4 */ - /* Bit 2, Pixel Format, 4 bits */ - /* Bit0: 16bpp (not supported in LNC), */ - /* Bit1: 18bpp loosely packed, */ - /* Bit2: 18bpp packed, */ - /* Bit3: 24bpp */ - /* Bit 6, Reserved, 2 bits, 00b */ - /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */ - /* Bit 14, Reserved, 2 bits, 00b */ -} __packed; - -union oaktrail_panel_rx { - struct { - u16 NumberOfLanes:2; /*Num of Lanes, 2 bits,0 = 1 lane,*/ - /* 1 = 2 lanes, 2 = 3 lanes, 3 = 4 lanes. */ - u16 MaxLaneFreq:3; /* 0: 100MHz, 1: 200MHz, 2: 300MHz, */ - /*3: 400MHz, 4: 500MHz, 5: 600MHz, 6: 700MHz, 7: 800MHz.*/ - u16 SupportedVideoTransferMode:2; /*0: Non-burst only */ - /* 1: Burst and non-burst */ - /* 2/3: Reserved */ - u16 HSClkBehavior:1; /*0: Continuous, 1: Non-continuous*/ - u16 DuoDisplaySupport:1; /*1 bit,0: No, 1: Yes*/ - u16 ECC_ChecksumCapabilities:1;/*1 bit,0: No, 1: Yes*/ - u16 BidirectionalCommunication:1;/*1 bit,0: No, 1: Yes */ - u16 Rsvd:5;/*5 bits,00000b */ - } panelrx; - u16 panel_receiver; -} __packed; - -struct oaktrail_gct_v1 { - union { /*8 bits,Defined as follows: */ - struct { - u8 PanelType:4; /*4 bits, Bit field for panels*/ - /* 0 - 3: 0 = LVDS, 1 = MIPI*/ - /*2 bits,Specifies which of the*/ - u8 BootPanelIndex:2; - /* 4 panels to use by default*/ - u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/ - /* the 4 MIPI DSI receivers to use*/ - } PD; - u8 PanelDescriptor; - }; - struct oaktrail_panel_descriptor_v1 panel[4];/*panel descrs,38 bytes each*/ - union oaktrail_panel_rx panelrx[4]; /* panel receivers*/ -} __packed; - -struct oaktrail_gct_v2 { - union { /*8 bits,Defined as follows: */ - struct { - u8 PanelType:4; /*4 bits, Bit field for panels*/ - /* 0 - 3: 0 = LVDS, 1 = MIPI*/ - /*2 bits,Specifies which of the*/ - u8 BootPanelIndex:2; - /* 4 panels to use by default*/ - u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/ - /* the 4 MIPI DSI receivers to use*/ - } PD; - u8 PanelDescriptor; - }; - struct oaktrail_panel_descriptor_v2 panel[4];/*panel descrs,38 bytes each*/ - union oaktrail_panel_rx panelrx[4]; /* panel receivers*/ -} __packed; - -struct oaktrail_gct_data { - u8 bpi; /* boot panel index, number of panel used during boot */ - u8 pt; /* panel type, 4 bit field, 0=lvds, 1=mipi */ - struct oaktrail_timing_info DTD; /* timing info for the selected panel */ - u32 Panel_Port_Control; - u32 PP_On_Sequencing;/*1 dword,Register 0x61208,*/ - u32 PP_Off_Sequencing;/*1 dword,Register 0x6120C,*/ - u32 PP_Cycle_Delay; - u16 Panel_Backlight_Inverter_Descriptor; - u16 Panel_MIPI_Display_Descriptor; -} __packed; - -#define MODE_SETTING_IN_CRTC 0x1 -#define MODE_SETTING_IN_ENCODER 0x2 -#define MODE_SETTING_ON_GOING 0x3 -#define MODE_SETTING_IN_DSR 0x4 -#define MODE_SETTING_ENCODER_DONE 0x8 - -#define GCT_R10_HEADER_SIZE 16 -#define GCT_R10_DISPLAY_DESC_SIZE 28 - -/* - * Moorestown HDMI interfaces - */ - -struct oaktrail_hdmi_dev { - struct pci_dev *dev; - void __iomem *regs; - unsigned int mmio, mmio_len; - int dpms_mode; - struct hdmi_i2c_dev *i2c_dev; - - /* register state */ - u32 saveDPLL_CTRL; - u32 saveDPLL_DIV_CTRL; - u32 saveDPLL_ADJUST; - u32 saveDPLL_UPDATE; - u32 saveDPLL_CLK_ENABLE; - u32 savePCH_HTOTAL_B; - u32 savePCH_HBLANK_B; - u32 savePCH_HSYNC_B; - u32 savePCH_VTOTAL_B; - u32 savePCH_VBLANK_B; - u32 savePCH_VSYNC_B; - u32 savePCH_PIPEBCONF; - u32 savePCH_PIPEBSRC; -}; - -extern void oaktrail_hdmi_setup(struct drm_device *dev); -extern void oaktrail_hdmi_teardown(struct drm_device *dev); -extern int oaktrail_hdmi_i2c_init(struct pci_dev *dev); -extern void oaktrail_hdmi_i2c_exit(struct pci_dev *dev); -extern void oaktrail_hdmi_save(struct drm_device *dev); -extern void oaktrail_hdmi_restore(struct drm_device *dev); -extern void oaktrail_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev); diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c deleted file mode 100644 index a39b0d0..0000000 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ /dev/null @@ -1,592 +0,0 @@ -/* - * Copyright © 2009 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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 "framebuffer.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "psb_intel_display.h" -#include "power.h" - -struct psb_intel_range_t { - int min, max; -}; - -struct oaktrail_limit_t { - struct psb_intel_range_t dot, m, p1; -}; - -struct oaktrail_clock_t { - /* derived values */ - int dot; - int m; - int p1; -}; - -#define MRST_LIMIT_LVDS_100L 0 -#define MRST_LIMIT_LVDS_83 1 -#define MRST_LIMIT_LVDS_100 2 - -#define MRST_DOT_MIN 19750 -#define MRST_DOT_MAX 120000 -#define MRST_M_MIN_100L 20 -#define MRST_M_MIN_100 10 -#define MRST_M_MIN_83 12 -#define MRST_M_MAX_100L 34 -#define MRST_M_MAX_100 17 -#define MRST_M_MAX_83 20 -#define MRST_P1_MIN 2 -#define MRST_P1_MAX_0 7 -#define MRST_P1_MAX_1 8 - -static const struct oaktrail_limit_t oaktrail_limits[] = { - { /* MRST_LIMIT_LVDS_100L */ - .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, - .m = {.min = MRST_M_MIN_100L, .max = MRST_M_MAX_100L}, - .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, - }, - { /* MRST_LIMIT_LVDS_83L */ - .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, - .m = {.min = MRST_M_MIN_83, .max = MRST_M_MAX_83}, - .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_0}, - }, - { /* MRST_LIMIT_LVDS_100 */ - .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, - .m = {.min = MRST_M_MIN_100, .max = MRST_M_MAX_100}, - .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, - }, -}; - -#define MRST_M_MIN 10 -static const u32 oaktrail_m_converts[] = { - 0x2B, 0x15, 0x2A, 0x35, 0x1A, 0x0D, 0x26, 0x33, 0x19, 0x2C, - 0x36, 0x3B, 0x1D, 0x2E, 0x37, 0x1B, 0x2D, 0x16, 0x0B, 0x25, - 0x12, 0x09, 0x24, 0x32, 0x39, 0x1c, -}; - -static const struct oaktrail_limit_t *oaktrail_limit(struct drm_crtc *crtc) -{ - const struct oaktrail_limit_t *limit = NULL; - struct drm_device *dev = crtc->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - - if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) - || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) { - switch (dev_priv->core_freq) { - case 100: - limit = &oaktrail_limits[MRST_LIMIT_LVDS_100L]; - break; - case 166: - limit = &oaktrail_limits[MRST_LIMIT_LVDS_83]; - break; - case 200: - limit = &oaktrail_limits[MRST_LIMIT_LVDS_100]; - break; - } - } else { - limit = NULL; - dev_err(dev->dev, "oaktrail_limit Wrong display type.\n"); - } - - return limit; -} - -/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ -static void oaktrail_clock(int refclk, struct oaktrail_clock_t *clock) -{ - clock->dot = (refclk * clock->m) / (14 * clock->p1); -} - -static void mrstPrintPll(char *prefix, struct oaktrail_clock_t *clock) -{ - pr_debug("%s: dotclock = %d, m = %d, p1 = %d.\n", - prefix, clock->dot, clock->m, clock->p1); -} - -/** - * Returns a set of divisors for the desired target clock with the given refclk, - * or FALSE. Divisor values are the actual divisors for - */ -static bool -mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk, - struct oaktrail_clock_t *best_clock) -{ - struct oaktrail_clock_t clock; - const struct oaktrail_limit_t *limit = oaktrail_limit(crtc); - int err = target; - - memset(best_clock, 0, sizeof(*best_clock)); - - for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { - for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; - clock.p1++) { - int this_err; - - oaktrail_clock(refclk, &clock); - - this_err = abs(clock.dot - target); - if (this_err < err) { - *best_clock = clock; - err = this_err; - } - } - } - dev_dbg(crtc->dev->dev, "mrstFindBestPLL err = %d.\n", err); - return err != target; -} - -/** - * Sets the power management mode of the pipe and plane. - * - * This code should probably grow support for turning the cursor off and back - * on appropriately at the same time as we're turning the pipe off/on. - */ -static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode) -{ - struct drm_device *dev = crtc->dev; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int pipe = psb_intel_crtc->pipe; - int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; - int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; - int dspbase_reg = (pipe == 0) ? MRST_DSPABASE : DSPBBASE; - int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; - u32 temp; - - if (!gma_power_begin(dev, true)) - return; - - /* XXX: When our outputs are all unaware of DPMS modes other than off - * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. - */ - switch (mode) { - case DRM_MODE_DPMS_ON: - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - /* Enable the DPLL */ - temp = REG_READ(dpll_reg); - if ((temp & DPLL_VCO_ENABLE) == 0) { - REG_WRITE(dpll_reg, temp); - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - } - /* Enable the pipe */ - temp = REG_READ(pipeconf_reg); - if ((temp & PIPEACONF_ENABLE) == 0) - REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); - /* Enable the plane */ - temp = REG_READ(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) == 0) { - REG_WRITE(dspcntr_reg, - temp | DISPLAY_PLANE_ENABLE); - /* Flush the plane changes */ - REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); - } - - psb_intel_crtc_load_lut(crtc); - - /* Give the overlay scaler a chance to enable - if it's on this pipe */ - /* psb_intel_crtc_dpms_video(crtc, true); TODO */ - break; - case DRM_MODE_DPMS_OFF: - /* Give the overlay scaler a chance to disable - * if it's on this pipe */ - /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ - - /* Disable the VGA plane that we never use */ - REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); - /* Disable display plane */ - temp = REG_READ(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) != 0) { - REG_WRITE(dspcntr_reg, - temp & ~DISPLAY_PLANE_ENABLE); - /* Flush the plane changes */ - REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); - REG_READ(dspbase_reg); - } - - /* Next, disable display pipes */ - temp = REG_READ(pipeconf_reg); - if ((temp & PIPEACONF_ENABLE) != 0) { - REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); - REG_READ(pipeconf_reg); - } - /* Wait for for the pipe disable to take effect. */ - psb_intel_wait_for_vblank(dev); - - temp = REG_READ(dpll_reg); - if ((temp & DPLL_VCO_ENABLE) != 0) { - REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); - REG_READ(dpll_reg); - } - - /* Wait for the clocks to turn off. */ - udelay(150); - break; - } - - /*Set FIFO Watermarks*/ - REG_WRITE(DSPARB, 0x3FFF); - REG_WRITE(DSPFW1, 0x3F88080A); - REG_WRITE(DSPFW2, 0x0b060808); - REG_WRITE(DSPFW3, 0x0); - REG_WRITE(DSPFW4, 0x08030404); - REG_WRITE(DSPFW5, 0x04040404); - REG_WRITE(DSPFW6, 0x78); - REG_WRITE(0x70400, REG_READ(0x70400) | 0x4000); - /* Must write Bit 14 of the Chicken Bit Register */ - - gma_power_end(dev); -} - -/** - * Return the pipe currently connected to the panel fitter, - * or -1 if the panel fitter is not present or not in use - */ -static int oaktrail_panel_fitter_pipe(struct drm_device *dev) -{ - u32 pfit_control; - - pfit_control = REG_READ(PFIT_CONTROL); - - /* See if the panel fitter is in use */ - if ((pfit_control & PFIT_ENABLE) == 0) - return -1; - return (pfit_control >> 29) & 3; -} - -static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - int x, int y, - struct drm_framebuffer *old_fb) -{ - struct drm_device *dev = crtc->dev; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct drm_psb_private *dev_priv = dev->dev_private; - int pipe = psb_intel_crtc->pipe; - int fp_reg = (pipe == 0) ? MRST_FPA0 : FPB0; - int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; - int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; - int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; - int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; - int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; - int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; - int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; - int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; - int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; - int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; - int refclk = 0; - struct oaktrail_clock_t clock; - u32 dpll = 0, fp = 0, dspcntr, pipeconf; - bool ok, is_sdvo = false; - bool is_lvds = false; - bool is_mipi = false; - struct drm_mode_config *mode_config = &dev->mode_config; - struct psb_intel_encoder *psb_intel_encoder = NULL; - uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; - struct drm_connector *connector; - - if (!gma_power_begin(dev, true)) - return 0; - - memcpy(&psb_intel_crtc->saved_mode, - mode, - sizeof(struct drm_display_mode)); - memcpy(&psb_intel_crtc->saved_adjusted_mode, - adjusted_mode, - sizeof(struct drm_display_mode)); - - list_for_each_entry(connector, &mode_config->connector_list, head) { - if (!connector->encoder || connector->encoder->crtc != crtc) - continue; - - psb_intel_encoder = psb_intel_attached_encoder(connector); - - switch (psb_intel_encoder->type) { - case INTEL_OUTPUT_LVDS: - is_lvds = true; - break; - case INTEL_OUTPUT_SDVO: - is_sdvo = true; - break; - case INTEL_OUTPUT_MIPI: - is_mipi = true; - break; - } - } - - /* Disable the VGA plane that we never use */ - REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); - - /* Disable the panel fitter if it was on our pipe */ - if (oaktrail_panel_fitter_pipe(dev) == pipe) - REG_WRITE(PFIT_CONTROL, 0); - - REG_WRITE(pipesrc_reg, - ((mode->crtc_hdisplay - 1) << 16) | - (mode->crtc_vdisplay - 1)); - - if (psb_intel_encoder) - drm_connector_property_get_value(connector, - dev->mode_config.scaling_mode_property, &scalingType); - - if (scalingType == DRM_MODE_SCALE_NO_SCALE) { - /* Moorestown doesn't have register support for centering so - * we need to mess with the h/vblank and h/vsync start and - * ends to get centering */ - int offsetX = 0, offsetY = 0; - - offsetX = (adjusted_mode->crtc_hdisplay - - mode->crtc_hdisplay) / 2; - offsetY = (adjusted_mode->crtc_vdisplay - - mode->crtc_vdisplay) / 2; - - REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) | - ((adjusted_mode->crtc_htotal - 1) << 16)); - REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) | - ((adjusted_mode->crtc_vtotal - 1) << 16)); - REG_WRITE(hblank_reg, - (adjusted_mode->crtc_hblank_start - offsetX - 1) | - ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); - REG_WRITE(hsync_reg, - (adjusted_mode->crtc_hsync_start - offsetX - 1) | - ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); - REG_WRITE(vblank_reg, - (adjusted_mode->crtc_vblank_start - offsetY - 1) | - ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); - REG_WRITE(vsync_reg, - (adjusted_mode->crtc_vsync_start - offsetY - 1) | - ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); - } else { - REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | - ((adjusted_mode->crtc_htotal - 1) << 16)); - REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | - ((adjusted_mode->crtc_vtotal - 1) << 16)); - REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | - ((adjusted_mode->crtc_hblank_end - 1) << 16)); - REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | - ((adjusted_mode->crtc_hsync_end - 1) << 16)); - REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | - ((adjusted_mode->crtc_vblank_end - 1) << 16)); - REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | - ((adjusted_mode->crtc_vsync_end - 1) << 16)); - } - - /* Flush the plane changes */ - { - struct drm_crtc_helper_funcs *crtc_funcs = - crtc->helper_private; - crtc_funcs->mode_set_base(crtc, x, y, old_fb); - } - - /* setup pipeconf */ - pipeconf = REG_READ(pipeconf_reg); - - /* Set up the display plane register */ - dspcntr = REG_READ(dspcntr_reg); - dspcntr |= DISPPLANE_GAMMA_ENABLE; - - if (pipe == 0) - dspcntr |= DISPPLANE_SEL_PIPE_A; - else - dspcntr |= DISPPLANE_SEL_PIPE_B; - - if (is_mipi) - goto oaktrail_crtc_mode_set_exit; - - refclk = dev_priv->core_freq * 1000; - - dpll = 0; /*BIT16 = 0 for 100MHz reference */ - - ok = mrstFindBestPLL(crtc, adjusted_mode->clock, refclk, &clock); - - if (!ok) { - dev_dbg(dev->dev, "mrstFindBestPLL fail in oaktrail_crtc_mode_set.\n"); - } else { - dev_dbg(dev->dev, "oaktrail_crtc_mode_set pixel clock = %d," - "m = %x, p1 = %x.\n", clock.dot, clock.m, - clock.p1); - } - - fp = oaktrail_m_converts[(clock.m - MRST_M_MIN)] << 8; - - dpll |= DPLL_VGA_MODE_DIS; - - - dpll |= DPLL_VCO_ENABLE; - - if (is_lvds) - dpll |= DPLLA_MODE_LVDS; - else - dpll |= DPLLB_MODE_DAC_SERIAL; - - if (is_sdvo) { - int sdvo_pixel_multiply = - adjusted_mode->clock / mode->clock; - - dpll |= DPLL_DVO_HIGH_SPEED; - dpll |= - (sdvo_pixel_multiply - - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; - } - - - /* compute bitmask from p1 value */ - dpll |= (1 << (clock.p1 - 2)) << 17; - - dpll |= DPLL_VCO_ENABLE; - - mrstPrintPll("chosen", &clock); - - if (dpll & DPLL_VCO_ENABLE) { - REG_WRITE(fp_reg, fp); - REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); - REG_READ(dpll_reg); - /* Check the DPLLA lock bit PIPEACONF[29] */ - udelay(150); - } - - REG_WRITE(fp_reg, fp); - REG_WRITE(dpll_reg, dpll); - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - - /* write it again -- the BIOS does, after all */ - REG_WRITE(dpll_reg, dpll); - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - - REG_WRITE(pipeconf_reg, pipeconf); - REG_READ(pipeconf_reg); - psb_intel_wait_for_vblank(dev); - - REG_WRITE(dspcntr_reg, dspcntr); - psb_intel_wait_for_vblank(dev); - -oaktrail_crtc_mode_set_exit: - gma_power_end(dev); - return 0; -} - -static bool oaktrail_crtc_mode_fixup(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static int oaktrail_pipe_set_base(struct drm_crtc *crtc, - int x, int y, struct drm_framebuffer *old_fb) -{ - struct drm_device *dev = crtc->dev; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); - int pipe = psb_intel_crtc->pipe; - unsigned long start, offset; - - int dspbase = (pipe == 0 ? DSPALINOFF : DSPBBASE); - int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); - int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; - int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; - u32 dspcntr; - int ret = 0; - - /* no fb bound */ - if (!crtc->fb) { - dev_dbg(dev->dev, "No FB bound\n"); - return 0; - } - - if (!gma_power_begin(dev, true)) - return 0; - - start = psbfb->gtt->offset; - offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); - - REG_WRITE(dspstride, crtc->fb->pitches[0]); - - dspcntr = REG_READ(dspcntr_reg); - dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - - switch (crtc->fb->bits_per_pixel) { - case 8: - dspcntr |= DISPPLANE_8BPP; - break; - case 16: - if (crtc->fb->depth == 15) - dspcntr |= DISPPLANE_15_16BPP; - else - dspcntr |= DISPPLANE_16BPP; - break; - case 24: - case 32: - dspcntr |= DISPPLANE_32BPP_NO_ALPHA; - break; - default: - dev_err(dev->dev, "Unknown color depth\n"); - ret = -EINVAL; - goto pipe_set_base_exit; - } - REG_WRITE(dspcntr_reg, dspcntr); - - REG_WRITE(dspbase, offset); - REG_READ(dspbase); - REG_WRITE(dspsurf, start); - REG_READ(dspsurf); - -pipe_set_base_exit: - gma_power_end(dev); - return ret; -} - -static void oaktrail_crtc_prepare(struct drm_crtc *crtc) -{ - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); -} - -static void oaktrail_crtc_commit(struct drm_crtc *crtc) -{ - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); -} - -const struct drm_crtc_helper_funcs oaktrail_helper_funcs = { - .dpms = oaktrail_crtc_dpms, - .mode_fixup = oaktrail_crtc_mode_fixup, - .mode_set = oaktrail_crtc_mode_set, - .mode_set_base = oaktrail_pipe_set_base, - .prepare = oaktrail_crtc_prepare, - .commit = oaktrail_crtc_commit, -}; - diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c deleted file mode 100644 index 41d1924..0000000 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ /dev/null @@ -1,509 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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 "gma_drm.h" -#include "psb_drv.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include -#include -#include "mid_bios.h" -#include "intel_bios.h" - -static int oaktrail_output_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - if (dev_priv->iLVDS_enable) - oaktrail_lvds_init(dev, &dev_priv->mode_dev); - else - dev_err(dev->dev, "DSI is not supported\n"); - if (dev_priv->hdmi_priv) - oaktrail_hdmi_init(dev, &dev_priv->mode_dev); - return 0; -} - -/* - * Provide the low level interfaces for the Moorestown backlight - */ - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - -#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF -#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ -#define BLC_PWM_FREQ_CALC_CONSTANT 32 -#define MHz 1000000 -#define BLC_ADJUSTMENT_MAX 100 - -static struct backlight_device *oaktrail_backlight_device; -static int oaktrail_brightness; - -static int oaktrail_set_brightness(struct backlight_device *bd) -{ - struct drm_device *dev = bl_get_data(oaktrail_backlight_device); - struct drm_psb_private *dev_priv = dev->dev_private; - int level = bd->props.brightness; - u32 blc_pwm_ctl; - u32 max_pwm_blc; - - /* Percentage 1-100% being valid */ - if (level < 1) - level = 1; - - if (gma_power_begin(dev, 0)) { - /* Calculate and set the brightness value */ - max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16; - blc_pwm_ctl = level * max_pwm_blc / 100; - - /* Adjust the backlight level with the percent in - * dev_priv->blc_adj1; - */ - blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1; - blc_pwm_ctl = blc_pwm_ctl / 100; - - /* Adjust the backlight level with the percent in - * dev_priv->blc_adj2; - */ - blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2; - blc_pwm_ctl = blc_pwm_ctl / 100; - - /* force PWM bit on */ - REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2))); - REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl); - gma_power_end(dev); - } - oaktrail_brightness = level; - return 0; -} - -static int oaktrail_get_brightness(struct backlight_device *bd) -{ - /* return locally cached var instead of HW read (due to DPST etc.) */ - /* FIXME: ideally return actual value in case firmware fiddled with - it */ - return oaktrail_brightness; -} - -static int device_backlight_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - unsigned long core_clock; - u16 bl_max_freq; - uint32_t value; - uint32_t blc_pwm_precision_factor; - - dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX; - dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX; - bl_max_freq = 256; - /* this needs to be set elsewhere */ - blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR; - - core_clock = dev_priv->core_freq; - - value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; - value *= blc_pwm_precision_factor; - value /= bl_max_freq; - value /= blc_pwm_precision_factor; - - if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ) - return -ERANGE; - - if (gma_power_begin(dev, false)) { - REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2))); - REG_WRITE(BLC_PWM_CTL, value | (value << 16)); - gma_power_end(dev); - } - return 0; -} - -static const struct backlight_ops oaktrail_ops = { - .get_brightness = oaktrail_get_brightness, - .update_status = oaktrail_set_brightness, -}; - -static int oaktrail_backlight_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - int ret; - struct backlight_properties props; - - memset(&props, 0, sizeof(struct backlight_properties)); - props.max_brightness = 100; - props.type = BACKLIGHT_PLATFORM; - - oaktrail_backlight_device = backlight_device_register("oaktrail-bl", - NULL, (void *)dev, &oaktrail_ops, &props); - - if (IS_ERR(oaktrail_backlight_device)) - return PTR_ERR(oaktrail_backlight_device); - - ret = device_backlight_init(dev); - if (ret < 0) { - backlight_device_unregister(oaktrail_backlight_device); - return ret; - } - oaktrail_backlight_device->props.brightness = 100; - oaktrail_backlight_device->props.max_brightness = 100; - backlight_update_status(oaktrail_backlight_device); - dev_priv->backlight_device = oaktrail_backlight_device; - return 0; -} - -#endif - -/* - * Provide the Moorestown specific chip logic and low level methods - * for power management - */ - -/** - * oaktrail_save_display_registers - save registers lost on suspend - * @dev: our DRM device - * - * Save the state we need in order to be able to restore the interface - * upon resume from suspend - */ -static int oaktrail_save_display_registers(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_save_area *regs = &dev_priv->regs; - int i; - u32 pp_stat; - - /* Display arbitration control + watermarks */ - regs->psb.saveDSPARB = PSB_RVDC32(DSPARB); - regs->psb.saveDSPFW1 = PSB_RVDC32(DSPFW1); - regs->psb.saveDSPFW2 = PSB_RVDC32(DSPFW2); - regs->psb.saveDSPFW3 = PSB_RVDC32(DSPFW3); - regs->psb.saveDSPFW4 = PSB_RVDC32(DSPFW4); - regs->psb.saveDSPFW5 = PSB_RVDC32(DSPFW5); - regs->psb.saveDSPFW6 = PSB_RVDC32(DSPFW6); - regs->psb.saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); - - /* Pipe & plane A info */ - regs->psb.savePIPEACONF = PSB_RVDC32(PIPEACONF); - regs->psb.savePIPEASRC = PSB_RVDC32(PIPEASRC); - regs->psb.saveFPA0 = PSB_RVDC32(MRST_FPA0); - regs->psb.saveFPA1 = PSB_RVDC32(MRST_FPA1); - regs->psb.saveDPLL_A = PSB_RVDC32(MRST_DPLL_A); - regs->psb.saveHTOTAL_A = PSB_RVDC32(HTOTAL_A); - regs->psb.saveHBLANK_A = PSB_RVDC32(HBLANK_A); - regs->psb.saveHSYNC_A = PSB_RVDC32(HSYNC_A); - regs->psb.saveVTOTAL_A = PSB_RVDC32(VTOTAL_A); - regs->psb.saveVBLANK_A = PSB_RVDC32(VBLANK_A); - regs->psb.saveVSYNC_A = PSB_RVDC32(VSYNC_A); - regs->psb.saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A); - regs->psb.saveDSPACNTR = PSB_RVDC32(DSPACNTR); - regs->psb.saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE); - regs->psb.saveDSPAADDR = PSB_RVDC32(DSPABASE); - regs->psb.saveDSPASURF = PSB_RVDC32(DSPASURF); - regs->psb.saveDSPALINOFF = PSB_RVDC32(DSPALINOFF); - regs->psb.saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF); - - /* Save cursor regs */ - regs->psb.saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR); - regs->psb.saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE); - regs->psb.saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS); - - /* Save palette (gamma) */ - for (i = 0; i < 256; i++) - regs->psb.save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2)); - - if (dev_priv->hdmi_priv) - oaktrail_hdmi_save(dev); - - /* Save performance state */ - regs->psb.savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE); - - /* LVDS state */ - regs->psb.savePP_CONTROL = PSB_RVDC32(PP_CONTROL); - regs->psb.savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS); - regs->psb.savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS); - regs->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL); - regs->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2); - regs->psb.saveLVDS = PSB_RVDC32(LVDS); - regs->psb.savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL); - regs->psb.savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON); - regs->psb.savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF); - regs->psb.savePP_DIVISOR = PSB_RVDC32(PP_CYCLE); - - /* HW overlay */ - regs->psb.saveOV_OVADD = PSB_RVDC32(OV_OVADD); - regs->psb.saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0); - regs->psb.saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1); - regs->psb.saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2); - regs->psb.saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3); - regs->psb.saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4); - regs->psb.saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5); - - /* DPST registers */ - regs->psb.saveHISTOGRAM_INT_CONTROL_REG = - PSB_RVDC32(HISTOGRAM_INT_CONTROL); - regs->psb.saveHISTOGRAM_LOGIC_CONTROL_REG = - PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL); - regs->psb.savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC); - - if (dev_priv->iLVDS_enable) { - /* Shut down the panel */ - PSB_WVDC32(0, PP_CONTROL); - - do { - pp_stat = PSB_RVDC32(PP_STATUS); - } while (pp_stat & 0x80000000); - - /* Turn off the plane */ - PSB_WVDC32(0x58000000, DSPACNTR); - /* Trigger the plane disable */ - PSB_WVDC32(0, DSPASURF); - - /* Wait ~4 ticks */ - msleep(4); - - /* Turn off pipe */ - PSB_WVDC32(0x0, PIPEACONF); - /* Wait ~8 ticks */ - msleep(8); - - /* Turn off PLLs */ - PSB_WVDC32(0, MRST_DPLL_A); - } - return 0; -} - -/** - * oaktrail_restore_display_registers - restore lost register state - * @dev: our DRM device - * - * Restore register state that was lost during suspend and resume. - */ -static int oaktrail_restore_display_registers(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_save_area *regs = &dev_priv->regs; - u32 pp_stat; - int i; - - /* Display arbitration + watermarks */ - PSB_WVDC32(regs->psb.saveDSPARB, DSPARB); - PSB_WVDC32(regs->psb.saveDSPFW1, DSPFW1); - PSB_WVDC32(regs->psb.saveDSPFW2, DSPFW2); - PSB_WVDC32(regs->psb.saveDSPFW3, DSPFW3); - PSB_WVDC32(regs->psb.saveDSPFW4, DSPFW4); - PSB_WVDC32(regs->psb.saveDSPFW5, DSPFW5); - PSB_WVDC32(regs->psb.saveDSPFW6, DSPFW6); - PSB_WVDC32(regs->psb.saveCHICKENBIT, DSPCHICKENBIT); - - /* Make sure VGA plane is off. it initializes to on after reset!*/ - PSB_WVDC32(0x80000000, VGACNTRL); - - /* set the plls */ - PSB_WVDC32(regs->psb.saveFPA0, MRST_FPA0); - PSB_WVDC32(regs->psb.saveFPA1, MRST_FPA1); - - /* Actually enable it */ - PSB_WVDC32(regs->psb.saveDPLL_A, MRST_DPLL_A); - DRM_UDELAY(150); - - /* Restore mode */ - PSB_WVDC32(regs->psb.saveHTOTAL_A, HTOTAL_A); - PSB_WVDC32(regs->psb.saveHBLANK_A, HBLANK_A); - PSB_WVDC32(regs->psb.saveHSYNC_A, HSYNC_A); - PSB_WVDC32(regs->psb.saveVTOTAL_A, VTOTAL_A); - PSB_WVDC32(regs->psb.saveVBLANK_A, VBLANK_A); - PSB_WVDC32(regs->psb.saveVSYNC_A, VSYNC_A); - PSB_WVDC32(regs->psb.savePIPEASRC, PIPEASRC); - PSB_WVDC32(regs->psb.saveBCLRPAT_A, BCLRPAT_A); - - /* Restore performance mode*/ - PSB_WVDC32(regs->psb.savePERF_MODE, MRST_PERF_MODE); - - /* Enable the pipe*/ - if (dev_priv->iLVDS_enable) - PSB_WVDC32(regs->psb.savePIPEACONF, PIPEACONF); - - /* Set up the plane*/ - PSB_WVDC32(regs->psb.saveDSPALINOFF, DSPALINOFF); - PSB_WVDC32(regs->psb.saveDSPASTRIDE, DSPASTRIDE); - PSB_WVDC32(regs->psb.saveDSPATILEOFF, DSPATILEOFF); - - /* Enable the plane */ - PSB_WVDC32(regs->psb.saveDSPACNTR, DSPACNTR); - PSB_WVDC32(regs->psb.saveDSPASURF, DSPASURF); - - /* Enable Cursor A */ - PSB_WVDC32(regs->psb.saveDSPACURSOR_CTRL, CURACNTR); - PSB_WVDC32(regs->psb.saveDSPACURSOR_POS, CURAPOS); - PSB_WVDC32(regs->psb.saveDSPACURSOR_BASE, CURABASE); - - /* Restore palette (gamma) */ - for (i = 0; i < 256; i++) - PSB_WVDC32(regs->psb.save_palette_a[i], PALETTE_A + (i << 2)); - - if (dev_priv->hdmi_priv) - oaktrail_hdmi_restore(dev); - - if (dev_priv->iLVDS_enable) { - PSB_WVDC32(regs->saveBLC_PWM_CTL2, BLC_PWM_CTL2); - PSB_WVDC32(regs->psb.saveLVDS, LVDS); /*port 61180h*/ - PSB_WVDC32(regs->psb.savePFIT_CONTROL, PFIT_CONTROL); - PSB_WVDC32(regs->psb.savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); - PSB_WVDC32(regs->psb.savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS); - PSB_WVDC32(regs->saveBLC_PWM_CTL, BLC_PWM_CTL); - PSB_WVDC32(regs->psb.savePP_ON_DELAYS, LVDSPP_ON); - PSB_WVDC32(regs->psb.savePP_OFF_DELAYS, LVDSPP_OFF); - PSB_WVDC32(regs->psb.savePP_DIVISOR, PP_CYCLE); - PSB_WVDC32(regs->psb.savePP_CONTROL, PP_CONTROL); - } - - /* Wait for cycle delay */ - do { - pp_stat = PSB_RVDC32(PP_STATUS); - } while (pp_stat & 0x08000000); - - /* Wait for panel power up */ - do { - pp_stat = PSB_RVDC32(PP_STATUS); - } while (pp_stat & 0x10000000); - - /* Restore HW overlay */ - PSB_WVDC32(regs->psb.saveOV_OVADD, OV_OVADD); - PSB_WVDC32(regs->psb.saveOV_OGAMC0, OV_OGAMC0); - PSB_WVDC32(regs->psb.saveOV_OGAMC1, OV_OGAMC1); - PSB_WVDC32(regs->psb.saveOV_OGAMC2, OV_OGAMC2); - PSB_WVDC32(regs->psb.saveOV_OGAMC3, OV_OGAMC3); - PSB_WVDC32(regs->psb.saveOV_OGAMC4, OV_OGAMC4); - PSB_WVDC32(regs->psb.saveOV_OGAMC5, OV_OGAMC5); - - /* DPST registers */ - PSB_WVDC32(regs->psb.saveHISTOGRAM_INT_CONTROL_REG, - HISTOGRAM_INT_CONTROL); - PSB_WVDC32(regs->psb.saveHISTOGRAM_LOGIC_CONTROL_REG, - HISTOGRAM_LOGIC_CONTROL); - PSB_WVDC32(regs->psb.savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC); - - return 0; -} - -/** - * oaktrail_power_down - power down the display island - * @dev: our DRM device - * - * Power down the display interface of our device - */ -static int oaktrail_power_down(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 pwr_mask ; - u32 pwr_sts; - - pwr_mask = PSB_PWRGT_DISPLAY_MASK; - outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC); - - while (true) { - pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); - if ((pwr_sts & pwr_mask) == pwr_mask) - break; - else - udelay(10); - } - return 0; -} - -/* - * oaktrail_power_up - * - * Restore power to the specified island(s) (powergating) - */ -static int oaktrail_power_up(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK; - u32 pwr_sts, pwr_cnt; - - pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC); - pwr_cnt &= ~pwr_mask; - outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC)); - - while (true) { - pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); - if ((pwr_sts & pwr_mask) == 0) - break; - else - udelay(10); - } - return 0; -} - - -static int oaktrail_chip_setup(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_vbt *vbt = &dev_priv->vbt_data; - int ret; - - ret = mid_chip_setup(dev); - if (ret < 0) - return ret; - if (vbt->size == 0) { - /* Now pull the BIOS data */ - gma_intel_opregion_init(dev); - psb_intel_init_bios(dev); - } - return 0; -} - -static void oaktrail_teardown(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_vbt *vbt = &dev_priv->vbt_data; - - oaktrail_hdmi_teardown(dev); - if (vbt->size == 0) - psb_intel_destroy_bios(dev); -} - -const struct psb_ops oaktrail_chip_ops = { - .name = "Oaktrail", - .accel_2d = 1, - .pipes = 2, - .crtcs = 2, - .sgx_offset = MRST_SGX_OFFSET, - - .chip_setup = oaktrail_chip_setup, - .chip_teardown = oaktrail_teardown, - .crtc_helper = &oaktrail_helper_funcs, - .crtc_funcs = &psb_intel_crtc_funcs, - - .output_init = oaktrail_output_init, - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - .backlight_init = oaktrail_backlight_init, -#endif - - .save_regs = oaktrail_save_display_registers, - .restore_regs = oaktrail_restore_display_registers, - .power_down = oaktrail_power_down, - .power_up = oaktrail_power_up, - - .i2c_bus = 1, -}; diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c deleted file mode 100644 index f8b367b..0000000 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Li Peng - */ - -#include -#include -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "psb_drv.h" - -#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg)) -#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg)) - -#define HDMI_HCR 0x1000 -#define HCR_ENABLE_HDCP (1 << 5) -#define HCR_ENABLE_AUDIO (1 << 2) -#define HCR_ENABLE_PIXEL (1 << 1) -#define HCR_ENABLE_TMDS (1 << 0) - -#define HDMI_HICR 0x1004 -#define HDMI_HSR 0x1008 -#define HDMI_HISR 0x100C -#define HDMI_DETECT_HDP (1 << 0) - -#define HDMI_VIDEO_REG 0x3000 -#define HDMI_UNIT_EN (1 << 7) -#define HDMI_MODE_OUTPUT (1 << 0) -#define HDMI_HBLANK_A 0x3100 - -#define HDMI_AUDIO_CTRL 0x4000 -#define HDMI_ENABLE_AUDIO (1 << 0) - -#define PCH_HTOTAL_B 0x3100 -#define PCH_HBLANK_B 0x3104 -#define PCH_HSYNC_B 0x3108 -#define PCH_VTOTAL_B 0x310C -#define PCH_VBLANK_B 0x3110 -#define PCH_VSYNC_B 0x3114 -#define PCH_PIPEBSRC 0x311C - -#define PCH_PIPEB_DSL 0x3800 -#define PCH_PIPEB_SLC 0x3804 -#define PCH_PIPEBCONF 0x3808 -#define PCH_PIPEBSTAT 0x3824 - -#define CDVO_DFT 0x5000 -#define CDVO_SLEWRATE 0x5004 -#define CDVO_STRENGTH 0x5008 -#define CDVO_RCOMP 0x500C - -#define DPLL_CTRL 0x6000 -#define DPLL_PDIV_SHIFT 16 -#define DPLL_PDIV_MASK (0xf << 16) -#define DPLL_PWRDN (1 << 4) -#define DPLL_RESET (1 << 3) -#define DPLL_FASTEN (1 << 2) -#define DPLL_ENSTAT (1 << 1) -#define DPLL_DITHEN (1 << 0) - -#define DPLL_DIV_CTRL 0x6004 -#define DPLL_CLKF_MASK 0xffffffc0 -#define DPLL_CLKR_MASK (0x3f) - -#define DPLL_CLK_ENABLE 0x6008 -#define DPLL_EN_DISP (1 << 31) -#define DPLL_SEL_HDMI (1 << 8) -#define DPLL_EN_HDMI (1 << 1) -#define DPLL_EN_VGA (1 << 0) - -#define DPLL_ADJUST 0x600C -#define DPLL_STATUS 0x6010 -#define DPLL_UPDATE 0x6014 -#define DPLL_DFT 0x6020 - -struct intel_range { - int min, max; -}; - -struct oaktrail_hdmi_limit { - struct intel_range vco, np, nr, nf; -}; - -struct oaktrail_hdmi_clock { - int np; - int nr; - int nf; - int dot; -}; - -#define VCO_MIN 320000 -#define VCO_MAX 1650000 -#define NP_MIN 1 -#define NP_MAX 15 -#define NR_MIN 1 -#define NR_MAX 64 -#define NF_MIN 2 -#define NF_MAX 4095 - -static const struct oaktrail_hdmi_limit oaktrail_hdmi_limit = { - .vco = { .min = VCO_MIN, .max = VCO_MAX }, - .np = { .min = NP_MIN, .max = NP_MAX }, - .nr = { .min = NR_MIN, .max = NR_MAX }, - .nf = { .min = NF_MIN, .max = NF_MAX }, -}; - -static void oaktrail_hdmi_audio_enable(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; - - HDMI_WRITE(HDMI_HCR, 0x67); - HDMI_READ(HDMI_HCR); - - HDMI_WRITE(0x51a8, 0x10); - HDMI_READ(0x51a8); - - HDMI_WRITE(HDMI_AUDIO_CTRL, 0x1); - HDMI_READ(HDMI_AUDIO_CTRL); -} - -static void oaktrail_hdmi_audio_disable(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; - - HDMI_WRITE(0x51a8, 0x0); - HDMI_READ(0x51a8); - - HDMI_WRITE(HDMI_AUDIO_CTRL, 0x0); - HDMI_READ(HDMI_AUDIO_CTRL); - - HDMI_WRITE(HDMI_HCR, 0x47); - HDMI_READ(HDMI_HCR); -} - -static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode) -{ - static int dpms_mode = -1; - - struct drm_device *dev = encoder->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; - u32 temp; - - if (dpms_mode == mode) - return; - - if (mode != DRM_MODE_DPMS_ON) - temp = 0x0; - else - temp = 0x99; - - dpms_mode = mode; - HDMI_WRITE(HDMI_VIDEO_REG, temp); -} - -static int oaktrail_hdmi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct drm_psb_private *dev_priv = connector->dev->dev_private; - if (mode->clock > 165000) - return MODE_CLOCK_HIGH; - if (mode->clock < 20000) - return MODE_CLOCK_LOW; - - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - - /* We assume worst case scenario of 32 bpp here, since we don't know */ - if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) > - dev_priv->vram_stolen_size) - return MODE_MEM; - - return MODE_OK; -} - -static bool oaktrail_hdmi_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static enum drm_connector_status -oaktrail_hdmi_detect(struct drm_connector *connector, bool force) -{ - enum drm_connector_status status; - struct drm_device *dev = connector->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; - u32 temp; - - temp = HDMI_READ(HDMI_HSR); - DRM_DEBUG_KMS("HDMI_HSR %x\n", temp); - - if ((temp & HDMI_DETECT_HDP) != 0) - status = connector_status_connected; - else - status = connector_status_disconnected; - - return status; -} - -static const unsigned char raw_edid[] = { - 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x2f, 0xa0, - 0x53, 0x55, 0x33, 0x30, 0x16, 0x13, 0x01, 0x03, 0x0e, 0x3a, 0x24, 0x78, - 0xea, 0xe9, 0xf5, 0xac, 0x51, 0x30, 0xb4, 0x25, 0x11, 0x50, 0x54, 0xa5, - 0x4b, 0x00, 0x81, 0x80, 0xa9, 0x40, 0x71, 0x4f, 0xb3, 0x00, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0, - 0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x46, 0x6c, 0x21, 0x00, 0x00, 0x1a, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x47, 0x4e, 0x37, 0x32, 0x31, 0x39, 0x35, - 0x52, 0x30, 0x33, 0x55, 0x53, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44, - 0x45, 0x4c, 0x4c, 0x20, 0x32, 0x37, 0x30, 0x39, 0x57, 0x0a, 0x20, 0x20, - 0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x8d -}; - -static int oaktrail_hdmi_get_modes(struct drm_connector *connector) -{ - struct drm_device *dev = connector->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct i2c_adapter *i2c_adap; - struct edid *edid; - struct drm_display_mode *mode, *t; - int i = 0, ret = 0; - - i2c_adap = i2c_get_adapter(3); - if (i2c_adap == NULL) { - DRM_ERROR("No ddc adapter available!\n"); - edid = (struct edid *)raw_edid; - } else { - edid = (struct edid *)raw_edid; - /* FIXME ? edid = drm_get_edid(connector, i2c_adap); */ - } - - if (edid) { - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - connector->display_info.raw_edid = NULL; - } - - /* - * prune modes that require frame buffer bigger than stolen mem - */ - list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { - if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) { - i++; - drm_mode_remove(connector, mode); - } - } - return ret - i; -} - -static void oaktrail_hdmi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_device *dev = encoder->dev; - - oaktrail_hdmi_audio_enable(dev); - return; -} - -static void oaktrail_hdmi_destroy(struct drm_connector *connector) -{ - return; -} - -static const struct drm_encoder_helper_funcs oaktrail_hdmi_helper_funcs = { - .dpms = oaktrail_hdmi_dpms, - .mode_fixup = oaktrail_hdmi_mode_fixup, - .prepare = psb_intel_encoder_prepare, - .mode_set = oaktrail_hdmi_mode_set, - .commit = psb_intel_encoder_commit, -}; - -static const struct drm_connector_helper_funcs - oaktrail_hdmi_connector_helper_funcs = { - .get_modes = oaktrail_hdmi_get_modes, - .mode_valid = oaktrail_hdmi_mode_valid, - .best_encoder = psb_intel_best_encoder, -}; - -static const struct drm_connector_funcs oaktrail_hdmi_connector_funcs = { - .dpms = drm_helper_connector_dpms, - .detect = oaktrail_hdmi_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = oaktrail_hdmi_destroy, -}; - -static void oaktrail_hdmi_enc_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); -} - -static const struct drm_encoder_funcs oaktrail_hdmi_enc_funcs = { - .destroy = oaktrail_hdmi_enc_destroy, -}; - -void oaktrail_hdmi_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev) -{ - struct psb_intel_encoder *psb_intel_encoder; - struct psb_intel_connector *psb_intel_connector; - struct drm_connector *connector; - struct drm_encoder *encoder; - - psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); - if (!psb_intel_encoder) - return; - - psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL); - if (!psb_intel_connector) - goto failed_connector; - - connector = &psb_intel_connector->base; - encoder = &psb_intel_encoder->base; - drm_connector_init(dev, connector, - &oaktrail_hdmi_connector_funcs, - DRM_MODE_CONNECTOR_DVID); - - drm_encoder_init(dev, encoder, - &oaktrail_hdmi_enc_funcs, - DRM_MODE_ENCODER_TMDS); - - psb_intel_connector_attach_encoder(psb_intel_connector, - psb_intel_encoder); - - psb_intel_encoder->type = INTEL_OUTPUT_HDMI; - drm_encoder_helper_add(encoder, &oaktrail_hdmi_helper_funcs); - drm_connector_helper_add(connector, &oaktrail_hdmi_connector_helper_funcs); - - connector->display_info.subpixel_order = SubPixelHorizontalRGB; - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - drm_sysfs_connector_add(connector); - - return; - -failed_connector: - kfree(psb_intel_encoder); -} - -static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) }, - { 0 } -}; - -void oaktrail_hdmi_setup(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct pci_dev *pdev; - struct oaktrail_hdmi_dev *hdmi_dev; - int ret; - - pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x080d, NULL); - if (!pdev) - return; - - hdmi_dev = kzalloc(sizeof(struct oaktrail_hdmi_dev), GFP_KERNEL); - if (!hdmi_dev) { - dev_err(dev->dev, "failed to allocate memory\n"); - goto out; - } - - - ret = pci_enable_device(pdev); - if (ret) { - dev_err(dev->dev, "failed to enable hdmi controller\n"); - goto free; - } - - hdmi_dev->mmio = pci_resource_start(pdev, 0); - hdmi_dev->mmio_len = pci_resource_len(pdev, 0); - hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len); - if (!hdmi_dev->regs) { - dev_err(dev->dev, "failed to map hdmi mmio\n"); - goto free; - } - - hdmi_dev->dev = pdev; - pci_set_drvdata(pdev, hdmi_dev); - - /* Initialize i2c controller */ - ret = oaktrail_hdmi_i2c_init(hdmi_dev->dev); - if (ret) - dev_err(dev->dev, "HDMI I2C initialization failed\n"); - - dev_priv->hdmi_priv = hdmi_dev; - oaktrail_hdmi_audio_disable(dev); - return; - -free: - kfree(hdmi_dev); -out: - return; -} - -void oaktrail_hdmi_teardown(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; - struct pci_dev *pdev; - - if (hdmi_dev) { - pdev = hdmi_dev->dev; - pci_set_drvdata(pdev, NULL); - oaktrail_hdmi_i2c_exit(pdev); - iounmap(hdmi_dev->regs); - kfree(hdmi_dev); - pci_dev_put(pdev); - } -} - -/* save HDMI register state */ -void oaktrail_hdmi_save(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; - struct psb_state *regs = &dev_priv->regs.psb; - int i; - - /* dpll */ - hdmi_dev->saveDPLL_CTRL = PSB_RVDC32(DPLL_CTRL); - hdmi_dev->saveDPLL_DIV_CTRL = PSB_RVDC32(DPLL_DIV_CTRL); - hdmi_dev->saveDPLL_ADJUST = PSB_RVDC32(DPLL_ADJUST); - hdmi_dev->saveDPLL_UPDATE = PSB_RVDC32(DPLL_UPDATE); - hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE); - - /* pipe B */ - regs->savePIPEBCONF = PSB_RVDC32(PIPEBCONF); - regs->savePIPEBSRC = PSB_RVDC32(PIPEBSRC); - regs->saveHTOTAL_B = PSB_RVDC32(HTOTAL_B); - regs->saveHBLANK_B = PSB_RVDC32(HBLANK_B); - regs->saveHSYNC_B = PSB_RVDC32(HSYNC_B); - regs->saveVTOTAL_B = PSB_RVDC32(VTOTAL_B); - regs->saveVBLANK_B = PSB_RVDC32(VBLANK_B); - regs->saveVSYNC_B = PSB_RVDC32(VSYNC_B); - - hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF); - hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC); - hdmi_dev->savePCH_HTOTAL_B = PSB_RVDC32(PCH_HTOTAL_B); - hdmi_dev->savePCH_HBLANK_B = PSB_RVDC32(PCH_HBLANK_B); - hdmi_dev->savePCH_HSYNC_B = PSB_RVDC32(PCH_HSYNC_B); - hdmi_dev->savePCH_VTOTAL_B = PSB_RVDC32(PCH_VTOTAL_B); - hdmi_dev->savePCH_VBLANK_B = PSB_RVDC32(PCH_VBLANK_B); - hdmi_dev->savePCH_VSYNC_B = PSB_RVDC32(PCH_VSYNC_B); - - /* plane */ - regs->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR); - regs->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE); - regs->saveDSPBADDR = PSB_RVDC32(DSPBBASE); - regs->saveDSPBSURF = PSB_RVDC32(DSPBSURF); - regs->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF); - regs->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF); - - /* cursor B */ - regs->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR); - regs->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE); - regs->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS); - - /* save palette */ - for (i = 0; i < 256; i++) - regs->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2)); -} - -/* restore HDMI register state */ -void oaktrail_hdmi_restore(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; - struct psb_state *regs = &dev_priv->regs.psb; - int i; - - /* dpll */ - PSB_WVDC32(hdmi_dev->saveDPLL_CTRL, DPLL_CTRL); - PSB_WVDC32(hdmi_dev->saveDPLL_DIV_CTRL, DPLL_DIV_CTRL); - PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST); - PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE); - PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE); - DRM_UDELAY(150); - - /* pipe */ - PSB_WVDC32(regs->savePIPEBSRC, PIPEBSRC); - PSB_WVDC32(regs->saveHTOTAL_B, HTOTAL_B); - PSB_WVDC32(regs->saveHBLANK_B, HBLANK_B); - PSB_WVDC32(regs->saveHSYNC_B, HSYNC_B); - PSB_WVDC32(regs->saveVTOTAL_B, VTOTAL_B); - PSB_WVDC32(regs->saveVBLANK_B, VBLANK_B); - PSB_WVDC32(regs->saveVSYNC_B, VSYNC_B); - - PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC); - PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B); - PSB_WVDC32(hdmi_dev->savePCH_HBLANK_B, PCH_HBLANK_B); - PSB_WVDC32(hdmi_dev->savePCH_HSYNC_B, PCH_HSYNC_B); - PSB_WVDC32(hdmi_dev->savePCH_VTOTAL_B, PCH_VTOTAL_B); - PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B); - PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B, PCH_VSYNC_B); - - PSB_WVDC32(regs->savePIPEBCONF, PIPEBCONF); - PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF); - - /* plane */ - PSB_WVDC32(regs->saveDSPBLINOFF, DSPBLINOFF); - PSB_WVDC32(regs->saveDSPBSTRIDE, DSPBSTRIDE); - PSB_WVDC32(regs->saveDSPBTILEOFF, DSPBTILEOFF); - PSB_WVDC32(regs->saveDSPBCNTR, DSPBCNTR); - PSB_WVDC32(regs->saveDSPBSURF, DSPBSURF); - - /* cursor B */ - PSB_WVDC32(regs->saveDSPBCURSOR_CTRL, CURBCNTR); - PSB_WVDC32(regs->saveDSPBCURSOR_POS, CURBPOS); - PSB_WVDC32(regs->saveDSPBCURSOR_BASE, CURBBASE); - - /* restore palette */ - for (i = 0; i < 256; i++) - PSB_WVDC32(regs->save_palette_b[i], PALETTE_B + (i << 2)); -} diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c deleted file mode 100644 index 8bb6bdc..0000000 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Li Peng - */ - -#include -#include -#include -#include -#include -#include "psb_drv.h" - -#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg)) -#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg)) - -#define HDMI_HCR 0x1000 -#define HCR_DETECT_HDP (1 << 6) -#define HCR_ENABLE_HDCP (1 << 5) -#define HCR_ENABLE_AUDIO (1 << 2) -#define HCR_ENABLE_PIXEL (1 << 1) -#define HCR_ENABLE_TMDS (1 << 0) -#define HDMI_HICR 0x1004 -#define HDMI_INTR_I2C_ERROR (1 << 4) -#define HDMI_INTR_I2C_FULL (1 << 3) -#define HDMI_INTR_I2C_DONE (1 << 2) -#define HDMI_INTR_HPD (1 << 0) -#define HDMI_HSR 0x1008 -#define HDMI_HISR 0x100C -#define HDMI_HI2CRDB0 0x1200 -#define HDMI_HI2CHCR 0x1240 -#define HI2C_HDCP_WRITE (0 << 2) -#define HI2C_HDCP_RI_READ (1 << 2) -#define HI2C_HDCP_READ (2 << 2) -#define HI2C_EDID_READ (3 << 2) -#define HI2C_READ_CONTINUE (1 << 1) -#define HI2C_ENABLE_TRANSACTION (1 << 0) - -#define HDMI_ICRH 0x1100 -#define HDMI_HI2CTDR0 0x1244 -#define HDMI_HI2CTDR1 0x1248 - -#define I2C_STAT_INIT 0 -#define I2C_READ_DONE 1 -#define I2C_TRANSACTION_DONE 2 - -struct hdmi_i2c_dev { - struct i2c_adapter *adap; - struct mutex i2c_lock; - struct completion complete; - int status; - struct i2c_msg *msg; - int buf_offset; -}; - -static void hdmi_i2c_irq_enable(struct oaktrail_hdmi_dev *hdmi_dev) -{ - u32 temp; - - temp = HDMI_READ(HDMI_HICR); - temp |= (HDMI_INTR_I2C_ERROR | HDMI_INTR_I2C_FULL | HDMI_INTR_I2C_DONE); - HDMI_WRITE(HDMI_HICR, temp); - HDMI_READ(HDMI_HICR); -} - -static void hdmi_i2c_irq_disable(struct oaktrail_hdmi_dev *hdmi_dev) -{ - HDMI_WRITE(HDMI_HICR, 0x0); - HDMI_READ(HDMI_HICR); -} - -static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg) -{ - struct oaktrail_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap); - struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; - u32 temp; - - i2c_dev->status = I2C_STAT_INIT; - i2c_dev->msg = pmsg; - i2c_dev->buf_offset = 0; - INIT_COMPLETION(i2c_dev->complete); - - /* Enable I2C transaction */ - temp = ((pmsg->len) << 20) | HI2C_EDID_READ | HI2C_ENABLE_TRANSACTION; - HDMI_WRITE(HDMI_HI2CHCR, temp); - HDMI_READ(HDMI_HI2CHCR); - - while (i2c_dev->status != I2C_TRANSACTION_DONE) - wait_for_completion_interruptible_timeout(&i2c_dev->complete, - 10 * HZ); - - return 0; -} - -static int xfer_write(struct i2c_adapter *adap, struct i2c_msg *pmsg) -{ - /* - * XXX: i2c write seems isn't useful for EDID probe, don't do anything - */ - return 0; -} - -static int oaktrail_hdmi_i2c_access(struct i2c_adapter *adap, - struct i2c_msg *pmsg, - int num) -{ - struct oaktrail_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap); - struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; - int i; - - mutex_lock(&i2c_dev->i2c_lock); - - /* Enable i2c unit */ - HDMI_WRITE(HDMI_ICRH, 0x00008760); - - /* Enable irq */ - hdmi_i2c_irq_enable(hdmi_dev); - for (i = 0; i < num; i++) { - if (pmsg->len && pmsg->buf) { - if (pmsg->flags & I2C_M_RD) - xfer_read(adap, pmsg); - else - xfer_write(adap, pmsg); - } - pmsg++; /* next message */ - } - - /* Disable irq */ - hdmi_i2c_irq_disable(hdmi_dev); - - mutex_unlock(&i2c_dev->i2c_lock); - - return i; -} - -static u32 oaktrail_hdmi_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; -} - -static const struct i2c_algorithm oaktrail_hdmi_i2c_algorithm = { - .master_xfer = oaktrail_hdmi_i2c_access, - .functionality = oaktrail_hdmi_i2c_func, -}; - -static struct i2c_adapter oaktrail_hdmi_i2c_adapter = { - .name = "oaktrail_hdmi_i2c", - .nr = 3, - .owner = THIS_MODULE, - .class = I2C_CLASS_DDC, - .algo = &oaktrail_hdmi_i2c_algorithm, -}; - -static void hdmi_i2c_read(struct oaktrail_hdmi_dev *hdmi_dev) -{ - struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; - struct i2c_msg *msg = i2c_dev->msg; - u8 *buf = msg->buf; - u32 temp; - int i, offset; - - offset = i2c_dev->buf_offset; - for (i = 0; i < 0x10; i++) { - temp = HDMI_READ(HDMI_HI2CRDB0 + (i * 4)); - memcpy(buf + (offset + i * 4), &temp, 4); - } - i2c_dev->buf_offset += (0x10 * 4); - - /* clearing read buffer full intr */ - temp = HDMI_READ(HDMI_HISR); - HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_FULL); - HDMI_READ(HDMI_HISR); - - /* continue read transaction */ - temp = HDMI_READ(HDMI_HI2CHCR); - HDMI_WRITE(HDMI_HI2CHCR, temp | HI2C_READ_CONTINUE); - HDMI_READ(HDMI_HI2CHCR); - - i2c_dev->status = I2C_READ_DONE; - return; -} - -static void hdmi_i2c_transaction_done(struct oaktrail_hdmi_dev *hdmi_dev) -{ - struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; - u32 temp; - - /* clear transaction done intr */ - temp = HDMI_READ(HDMI_HISR); - HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_DONE); - HDMI_READ(HDMI_HISR); - - - temp = HDMI_READ(HDMI_HI2CHCR); - HDMI_WRITE(HDMI_HI2CHCR, temp & ~HI2C_ENABLE_TRANSACTION); - HDMI_READ(HDMI_HI2CHCR); - - i2c_dev->status = I2C_TRANSACTION_DONE; - return; -} - -static irqreturn_t oaktrail_hdmi_i2c_handler(int this_irq, void *dev) -{ - struct oaktrail_hdmi_dev *hdmi_dev = dev; - struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; - u32 stat; - - stat = HDMI_READ(HDMI_HISR); - - if (stat & HDMI_INTR_HPD) { - HDMI_WRITE(HDMI_HISR, stat | HDMI_INTR_HPD); - HDMI_READ(HDMI_HISR); - } - - if (stat & HDMI_INTR_I2C_FULL) - hdmi_i2c_read(hdmi_dev); - - if (stat & HDMI_INTR_I2C_DONE) - hdmi_i2c_transaction_done(hdmi_dev); - - complete(&i2c_dev->complete); - - return IRQ_HANDLED; -} - -/* - * choose alternate function 2 of GPIO pin 52, 53, - * which is used by HDMI I2C logic - */ -static void oaktrail_hdmi_i2c_gpio_fix(void) -{ - void *base; - unsigned int gpio_base = 0xff12c000; - int gpio_len = 0x1000; - u32 temp; - - base = ioremap((resource_size_t)gpio_base, gpio_len); - if (base == NULL) { - DRM_ERROR("gpio ioremap fail\n"); - return; - } - - temp = readl(base + 0x44); - DRM_DEBUG_DRIVER("old gpio val %x\n", temp); - writel((temp | 0x00000a00), (base + 0x44)); - temp = readl(base + 0x44); - DRM_DEBUG_DRIVER("new gpio val %x\n", temp); - - iounmap(base); -} - -int oaktrail_hdmi_i2c_init(struct pci_dev *dev) -{ - struct oaktrail_hdmi_dev *hdmi_dev; - struct hdmi_i2c_dev *i2c_dev; - int ret; - - hdmi_dev = pci_get_drvdata(dev); - - i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL); - if (i2c_dev == NULL) { - DRM_ERROR("Can't allocate interface\n"); - ret = -ENOMEM; - goto exit; - } - - i2c_dev->adap = &oaktrail_hdmi_i2c_adapter; - i2c_dev->status = I2C_STAT_INIT; - init_completion(&i2c_dev->complete); - mutex_init(&i2c_dev->i2c_lock); - i2c_set_adapdata(&oaktrail_hdmi_i2c_adapter, hdmi_dev); - hdmi_dev->i2c_dev = i2c_dev; - - /* Enable HDMI I2C function on gpio */ - oaktrail_hdmi_i2c_gpio_fix(); - - /* request irq */ - ret = request_irq(dev->irq, oaktrail_hdmi_i2c_handler, IRQF_SHARED, - oaktrail_hdmi_i2c_adapter.name, hdmi_dev); - if (ret) { - DRM_ERROR("Failed to request IRQ for I2C controller\n"); - goto err; - } - - /* Adapter registration */ - ret = i2c_add_numbered_adapter(&oaktrail_hdmi_i2c_adapter); - return ret; - -err: - kfree(i2c_dev); -exit: - return ret; -} - -void oaktrail_hdmi_i2c_exit(struct pci_dev *dev) -{ - struct oaktrail_hdmi_dev *hdmi_dev; - struct hdmi_i2c_dev *i2c_dev; - - hdmi_dev = pci_get_drvdata(dev); - if (i2c_del_adapter(&oaktrail_hdmi_i2c_adapter)) - DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n"); - - i2c_dev = hdmi_dev->i2c_dev; - kfree(i2c_dev); - free_irq(dev->irq, hdmi_dev); -} diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c deleted file mode 100644 index 654f32b..0000000 --- a/drivers/gpu/drm/gma500/oaktrail_lvds.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright © 2006-2009 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: - * Eric Anholt - * Dave Airlie - * Jesse Barnes - */ - -#include -#include -#include - -#include "intel_bios.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "power.h" -#include - -/* The max/min PWM frequency in BPCR[31:17] - */ -/* The smallest number is 1 (not 0) that can fit in the - * 15-bit field of the and then*/ -/* shifts to the left by one bit to get the actual 16-bit - * value that the 15-bits correspond to.*/ -#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF -#define BRIGHTNESS_MAX_LEVEL 100 - -/** - * Sets the power state for the panel. - */ -static void oaktrail_lvds_set_power(struct drm_device *dev, - struct psb_intel_encoder *psb_intel_encoder, - bool on) -{ - u32 pp_status; - struct drm_psb_private *dev_priv = dev->dev_private; - - if (!gma_power_begin(dev, true)) - return; - - if (on) { - REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | - POWER_TARGET_ON); - do { - pp_status = REG_READ(PP_STATUS); - } while ((pp_status & (PP_ON | PP_READY)) == PP_READY); - dev_priv->is_lvds_on = true; - if (dev_priv->ops->lvds_bl_power) - dev_priv->ops->lvds_bl_power(dev, true); - } else { - if (dev_priv->ops->lvds_bl_power) - dev_priv->ops->lvds_bl_power(dev, false); - REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & - ~POWER_TARGET_ON); - do { - pp_status = REG_READ(PP_STATUS); - } while (pp_status & PP_ON); - dev_priv->is_lvds_on = false; - pm_request_idle(&dev->pdev->dev); - } - gma_power_end(dev); -} - -static void oaktrail_lvds_dpms(struct drm_encoder *encoder, int mode) -{ - struct drm_device *dev = encoder->dev; - struct psb_intel_encoder *psb_intel_encoder = - to_psb_intel_encoder(encoder); - - if (mode == DRM_MODE_DPMS_ON) - oaktrail_lvds_set_power(dev, psb_intel_encoder, true); - else - oaktrail_lvds_set_power(dev, psb_intel_encoder, false); - - /* XXX: We never power down the LVDS pairs. */ -} - -static void oaktrail_lvds_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_device *dev = encoder->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - struct drm_mode_config *mode_config = &dev->mode_config; - struct drm_connector *connector = NULL; - struct drm_crtc *crtc = encoder->crtc; - u32 lvds_port; - uint64_t v = DRM_MODE_SCALE_FULLSCREEN; - - if (!gma_power_begin(dev, true)) - return; - - /* - * The LVDS pin pair will already have been turned on in the - * psb_intel_crtc_mode_set since it has a large impact on the DPLL - * settings. - */ - lvds_port = (REG_READ(LVDS) & - (~LVDS_PIPEB_SELECT)) | - LVDS_PORT_EN | - LVDS_BORDER_EN; - - /* If the firmware says dither on Moorestown, or the BIOS does - on Oaktrail then enable dithering */ - if (mode_dev->panel_wants_dither || dev_priv->lvds_dither) - lvds_port |= MRST_PANEL_8TO6_DITHER_ENABLE; - - REG_WRITE(LVDS, lvds_port); - - /* Find the connector we're trying to set up */ - list_for_each_entry(connector, &mode_config->connector_list, head) { - if (!connector->encoder || connector->encoder->crtc != crtc) - continue; - } - - if (!connector) { - DRM_ERROR("Couldn't find connector when setting mode"); - return; - } - - drm_connector_property_get_value( - connector, - dev->mode_config.scaling_mode_property, - &v); - - if (v == DRM_MODE_SCALE_NO_SCALE) - REG_WRITE(PFIT_CONTROL, 0); - else if (v == DRM_MODE_SCALE_ASPECT) { - if ((mode->vdisplay != adjusted_mode->crtc_vdisplay) || - (mode->hdisplay != adjusted_mode->crtc_hdisplay)) { - if ((adjusted_mode->crtc_hdisplay * mode->vdisplay) == - (mode->hdisplay * adjusted_mode->crtc_vdisplay)) - REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); - else if ((adjusted_mode->crtc_hdisplay * - mode->vdisplay) > (mode->hdisplay * - adjusted_mode->crtc_vdisplay)) - REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | - PFIT_SCALING_MODE_PILLARBOX); - else - REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | - PFIT_SCALING_MODE_LETTERBOX); - } else - REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); - } else /*(v == DRM_MODE_SCALE_FULLSCREEN)*/ - REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); - - gma_power_end(dev); -} - -static void oaktrail_lvds_prepare(struct drm_encoder *encoder) -{ - struct drm_device *dev = encoder->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_encoder *psb_intel_encoder = - to_psb_intel_encoder(encoder); - struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - - if (!gma_power_begin(dev, true)) - return; - - mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); - mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & - BACKLIGHT_DUTY_CYCLE_MASK); - oaktrail_lvds_set_power(dev, psb_intel_encoder, false); - gma_power_end(dev); -} - -static u32 oaktrail_lvds_get_max_backlight(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 ret; - - if (gma_power_begin(dev, false)) { - ret = ((REG_READ(BLC_PWM_CTL) & - BACKLIGHT_MODULATION_FREQ_MASK) >> - BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; - - gma_power_end(dev); - } else - ret = ((dev_priv->regs.saveBLC_PWM_CTL & - BACKLIGHT_MODULATION_FREQ_MASK) >> - BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; - - return ret; -} - -static void oaktrail_lvds_commit(struct drm_encoder *encoder) -{ - struct drm_device *dev = encoder->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_encoder *psb_intel_encoder = - to_psb_intel_encoder(encoder); - struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - - if (mode_dev->backlight_duty_cycle == 0) - mode_dev->backlight_duty_cycle = - oaktrail_lvds_get_max_backlight(dev); - oaktrail_lvds_set_power(dev, psb_intel_encoder, true); -} - -static const struct drm_encoder_helper_funcs oaktrail_lvds_helper_funcs = { - .dpms = oaktrail_lvds_dpms, - .mode_fixup = psb_intel_lvds_mode_fixup, - .prepare = oaktrail_lvds_prepare, - .mode_set = oaktrail_lvds_mode_set, - .commit = oaktrail_lvds_commit, -}; - -static struct drm_display_mode lvds_configuration_modes[] = { - /* hard coded fixed mode for TPO LTPS LPJ040K001A */ - { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 33264, 800, 836, - 846, 1056, 0, 480, 489, 491, 525, 0, 0) }, - /* hard coded fixed mode for LVDS 800x480 */ - { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 30994, 800, 801, - 802, 1024, 0, 480, 481, 482, 525, 0, 0) }, - /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ - { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1072, - 1104, 1184, 0, 600, 603, 604, 608, 0, 0) }, - /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ - { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1104, - 1136, 1184, 0, 600, 603, 604, 608, 0, 0) }, - /* hard coded fixed mode for Sharp wsvga LVDS 1024x600 */ - { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 48885, 1024, 1124, - 1204, 1312, 0, 600, 607, 610, 621, 0, 0) }, - /* hard coded fixed mode for LVDS 1024x768 */ - { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, - 1184, 1344, 0, 768, 771, 777, 806, 0, 0) }, - /* hard coded fixed mode for LVDS 1366x768 */ - { DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 77500, 1366, 1430, - 1558, 1664, 0, 768, 769, 770, 776, 0, 0) }, -}; - -/* Returns the panel fixed mode from configuration. */ - -static void oaktrail_lvds_get_configuration_mode(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev) -{ - struct drm_display_mode *mode = NULL; - struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD; - - mode_dev->panel_fixed_mode = NULL; - - /* Use the firmware provided data on Moorestown */ - if (dev_priv->vbt_data.size != 0x00) { /*if non-zero, then use vbt*/ - mode = kzalloc(sizeof(*mode), GFP_KERNEL); - if (!mode) - return; - - mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; - mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; - mode->hsync_start = mode->hdisplay + \ - ((ti->hsync_offset_hi << 8) | \ - ti->hsync_offset_lo); - mode->hsync_end = mode->hsync_start + \ - ((ti->hsync_pulse_width_hi << 8) | \ - ti->hsync_pulse_width_lo); - mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ - ti->hblank_lo); - mode->vsync_start = \ - mode->vdisplay + ((ti->vsync_offset_hi << 4) | \ - ti->vsync_offset_lo); - mode->vsync_end = \ - mode->vsync_start + ((ti->vsync_pulse_width_hi << 4) | \ - ti->vsync_pulse_width_lo); - mode->vtotal = mode->vdisplay + \ - ((ti->vblank_hi << 8) | ti->vblank_lo); - mode->clock = ti->pixel_clock * 10; -#if 0 - printk(KERN_INFO "hdisplay is %d\n", mode->hdisplay); - printk(KERN_INFO "vdisplay is %d\n", mode->vdisplay); - printk(KERN_INFO "HSS is %d\n", mode->hsync_start); - printk(KERN_INFO "HSE is %d\n", mode->hsync_end); - printk(KERN_INFO "htotal is %d\n", mode->htotal); - printk(KERN_INFO "VSS is %d\n", mode->vsync_start); - printk(KERN_INFO "VSE is %d\n", mode->vsync_end); - printk(KERN_INFO "vtotal is %d\n", mode->vtotal); - printk(KERN_INFO "clock is %d\n", mode->clock); -#endif - mode_dev->panel_fixed_mode = mode; - } - - /* Use the BIOS VBT mode if available */ - if (mode_dev->panel_fixed_mode == NULL && mode_dev->vbt_mode) - mode_dev->panel_fixed_mode = drm_mode_duplicate(dev, - mode_dev->vbt_mode); - - /* Then try the LVDS VBT mode */ - if (mode_dev->panel_fixed_mode == NULL) - if (dev_priv->lfp_lvds_vbt_mode) - mode_dev->panel_fixed_mode = - drm_mode_duplicate(dev, - dev_priv->lfp_lvds_vbt_mode); - /* Then guess */ - if (mode_dev->panel_fixed_mode == NULL) - mode_dev->panel_fixed_mode - = drm_mode_duplicate(dev, &lvds_configuration_modes[2]); - - drm_mode_set_name(mode_dev->panel_fixed_mode); - drm_mode_set_crtcinfo(mode_dev->panel_fixed_mode, 0); -} - -/** - * oaktrail_lvds_init - setup LVDS connectors on this device - * @dev: drm device - * - * Create the connector, register the LVDS DDC bus, and try to figure out what - * modes we can display on the LVDS panel (if present). - */ -void oaktrail_lvds_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev) -{ - struct psb_intel_encoder *psb_intel_encoder; - struct psb_intel_connector *psb_intel_connector; - struct drm_connector *connector; - struct drm_encoder *encoder; - struct drm_psb_private *dev_priv = dev->dev_private; - struct edid *edid; - struct i2c_adapter *i2c_adap; - struct drm_display_mode *scan; /* *modes, *bios_mode; */ - - psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); - if (!psb_intel_encoder) - return; - - psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL); - if (!psb_intel_connector) - goto failed_connector; - - connector = &psb_intel_connector->base; - encoder = &psb_intel_encoder->base; - dev_priv->is_lvds_on = true; - drm_connector_init(dev, connector, - &psb_intel_lvds_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - - drm_encoder_init(dev, encoder, &psb_intel_lvds_enc_funcs, - DRM_MODE_ENCODER_LVDS); - - psb_intel_connector_attach_encoder(psb_intel_connector, - psb_intel_encoder); - psb_intel_encoder->type = INTEL_OUTPUT_LVDS; - - drm_encoder_helper_add(encoder, &oaktrail_lvds_helper_funcs); - drm_connector_helper_add(connector, - &psb_intel_lvds_connector_helper_funcs); - connector->display_info.subpixel_order = SubPixelHorizontalRGB; - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - - drm_connector_attach_property(connector, - dev->mode_config.scaling_mode_property, - DRM_MODE_SCALE_FULLSCREEN); - drm_connector_attach_property(connector, - dev_priv->backlight_property, - BRIGHTNESS_MAX_LEVEL); - - mode_dev->panel_wants_dither = false; - if (dev_priv->vbt_data.size != 0x00) - mode_dev->panel_wants_dither = (dev_priv->gct_data. - Panel_Port_Control & MRST_PANEL_8TO6_DITHER_ENABLE); - if (dev_priv->lvds_dither) - mode_dev->panel_wants_dither = 1; - - /* - * LVDS discovery: - * 1) check for EDID on DDC - * 2) check for VBT data - * 3) check to see if LVDS is already on - * if none of the above, no panel - * 4) make sure lid is open - * if closed, act like it's not there for now - */ - - i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus); - if (i2c_adap == NULL) - dev_err(dev->dev, "No ddc adapter available!\n"); - /* - * Attempt to get the fixed panel mode from DDC. Assume that the - * preferred mode is the right one. - */ - if (i2c_adap) { - edid = drm_get_edid(connector, i2c_adap); - if (edid) { - drm_mode_connector_update_edid_property(connector, - edid); - drm_add_edid_modes(connector, edid); - kfree(edid); - } - - list_for_each_entry(scan, &connector->probed_modes, head) { - if (scan->type & DRM_MODE_TYPE_PREFERRED) { - mode_dev->panel_fixed_mode = - drm_mode_duplicate(dev, scan); - goto out; /* FIXME: check for quirks */ - } - } - } - /* - * If we didn't get EDID, try geting panel timing - * from configuration data - */ - oaktrail_lvds_get_configuration_mode(dev, mode_dev); - - if (mode_dev->panel_fixed_mode) { - mode_dev->panel_fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; - goto out; /* FIXME: check for quirks */ - } - - /* If we still don't have a mode after all that, give up. */ - if (!mode_dev->panel_fixed_mode) { - dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n"); - goto failed_find; - } - -out: - drm_sysfs_connector_add(connector); - return; - -failed_find: - dev_dbg(dev->dev, "No LVDS modes found, disabling.\n"); - if (psb_intel_encoder->ddc_bus) - psb_intel_i2c_destroy(psb_intel_encoder->ddc_bus); - -/* failed_ddc: */ - - drm_encoder_cleanup(encoder); - drm_connector_cleanup(connector); - kfree(psb_intel_connector); -failed_connector: - kfree(psb_intel_encoder); -} - diff --git a/drivers/gpu/drm/gma500/power.c b/drivers/gpu/drm/gma500/power.c deleted file mode 100644 index 889b854..0000000 --- a/drivers/gpu/drm/gma500/power.c +++ /dev/null @@ -1,315 +0,0 @@ -/************************************************************************** - * Copyright (c) 2009-2011, Intel Corporation. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: - * Benjamin Defnet - * Rajesh Poornachandran - * Massively reworked - * Alan Cox - */ - -#include "power.h" -#include "psb_drv.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include -#include - -static struct mutex power_mutex; /* Serialize power ops */ -static spinlock_t power_ctrl_lock; /* Serialize power claim */ - -/** - * gma_power_init - initialise power manager - * @dev: our device - * - * Set up for power management tracking of our hardware. - */ -void gma_power_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - - /* FIXME: Move APM/OSPM base into relevant device code */ - dev_priv->apm_base = dev_priv->apm_reg & 0xffff; - dev_priv->ospm_base &= 0xffff; - - dev_priv->display_power = true; /* We start active */ - dev_priv->display_count = 0; /* Currently no users */ - dev_priv->suspended = false; /* And not suspended */ - spin_lock_init(&power_ctrl_lock); - mutex_init(&power_mutex); - - if (dev_priv->ops->init_pm) - dev_priv->ops->init_pm(dev); -} - -/** - * gma_power_uninit - end power manager - * @dev: device to end for - * - * Undo the effects of gma_power_init - */ -void gma_power_uninit(struct drm_device *dev) -{ - pm_runtime_disable(&dev->pdev->dev); - pm_runtime_set_suspended(&dev->pdev->dev); -} - -/** - * gma_suspend_display - suspend the display logic - * @dev: our DRM device - * - * Suspend the display logic of the graphics interface - */ -static void gma_suspend_display(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - - if (dev_priv->suspended) - return; - dev_priv->ops->save_regs(dev); - dev_priv->ops->power_down(dev); - dev_priv->display_power = false; -} - -/** - * gma_resume_display - resume display side logic - * - * Resume the display hardware restoring state and enabling - * as necessary. - */ -static void gma_resume_display(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - struct drm_psb_private *dev_priv = dev->dev_private; - - /* turn on the display power island */ - dev_priv->ops->power_up(dev); - dev_priv->suspended = false; - dev_priv->display_power = true; - - PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); - pci_write_config_word(pdev, PSB_GMCH_CTRL, - dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); - dev_priv->ops->restore_regs(dev); -} - -/** - * gma_suspend_pci - suspend PCI side - * @pdev: PCI device - * - * Perform the suspend processing on our PCI device state - */ -static void gma_suspend_pci(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - struct drm_psb_private *dev_priv = dev->dev_private; - int bsm, vbt; - - if (dev_priv->suspended) - return; - - pci_save_state(pdev); - pci_read_config_dword(pdev, 0x5C, &bsm); - dev_priv->regs.saveBSM = bsm; - pci_read_config_dword(pdev, 0xFC, &vbt); - dev_priv->regs.saveVBT = vbt; - pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr); - pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data); - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - dev_priv->suspended = true; -} - -/** - * gma_resume_pci - resume helper - * @dev: our PCI device - * - * Perform the resume processing on our PCI device state - rewrite - * register state and re-enable the PCI device - */ -static bool gma_resume_pci(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - struct drm_psb_private *dev_priv = dev->dev_private; - int ret; - - if (!dev_priv->suspended) - return true; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_write_config_dword(pdev, 0x5c, dev_priv->regs.saveBSM); - pci_write_config_dword(pdev, 0xFC, dev_priv->regs.saveVBT); - /* restoring MSI address and data in PCIx space */ - pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr); - pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data); - ret = pci_enable_device(pdev); - - if (ret != 0) - dev_err(&pdev->dev, "pci_enable failed: %d\n", ret); - else - dev_priv->suspended = false; - return !dev_priv->suspended; -} - -/** - * gma_power_suspend - bus callback for suspend - * @pdev: our PCI device - * @state: suspend type - * - * Called back by the PCI layer during a suspend of the system. We - * perform the necessary shut down steps and save enough state that - * we can undo this when resume is called. - */ -int gma_power_suspend(struct device *_dev) -{ - struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev); - struct drm_device *dev = pci_get_drvdata(pdev); - struct drm_psb_private *dev_priv = dev->dev_private; - - mutex_lock(&power_mutex); - if (!dev_priv->suspended) { - if (dev_priv->display_count) { - mutex_unlock(&power_mutex); - dev_err(dev->dev, "GPU hardware busy, cannot suspend\n"); - return -EBUSY; - } - psb_irq_uninstall(dev); - gma_suspend_display(dev); - gma_suspend_pci(pdev); - } - mutex_unlock(&power_mutex); - return 0; -} - -/** - * gma_power_resume - resume power - * @pdev: PCI device - * - * Resume the PCI side of the graphics and then the displays - */ -int gma_power_resume(struct device *_dev) -{ - struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev); - struct drm_device *dev = pci_get_drvdata(pdev); - - mutex_lock(&power_mutex); - gma_resume_pci(pdev); - gma_resume_display(pdev); - psb_irq_preinstall(dev); - psb_irq_postinstall(dev); - mutex_unlock(&power_mutex); - return 0; -} - -/** - * gma_power_is_on - returne true if power is on - * @dev: our DRM device - * - * Returns true if the display island power is on at this moment - */ -bool gma_power_is_on(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - return dev_priv->display_power; -} - -/** - * gma_power_begin - begin requiring power - * @dev: our DRM device - * @force_on: true to force power on - * - * Begin an action that requires the display power island is enabled. - * We refcount the islands. - */ -bool gma_power_begin(struct drm_device *dev, bool force_on) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - int ret; - unsigned long flags; - - spin_lock_irqsave(&power_ctrl_lock, flags); - /* Power already on ? */ - if (dev_priv->display_power) { - dev_priv->display_count++; - pm_runtime_get(&dev->pdev->dev); - spin_unlock_irqrestore(&power_ctrl_lock, flags); - return true; - } - if (force_on == false) - goto out_false; - - /* Ok power up needed */ - ret = gma_resume_pci(dev->pdev); - if (ret == 0) { - psb_irq_preinstall(dev); - psb_irq_postinstall(dev); - pm_runtime_get(&dev->pdev->dev); - dev_priv->display_count++; - spin_unlock_irqrestore(&power_ctrl_lock, flags); - return true; - } -out_false: - spin_unlock_irqrestore(&power_ctrl_lock, flags); - return false; -} - -/** - * gma_power_end - end use of power - * @dev: Our DRM device - * - * Indicate that one of our gma_power_begin() requested periods when - * the diplay island power is needed has completed. - */ -void gma_power_end(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - unsigned long flags; - spin_lock_irqsave(&power_ctrl_lock, flags); - dev_priv->display_count--; - WARN_ON(dev_priv->display_count < 0); - spin_unlock_irqrestore(&power_ctrl_lock, flags); - pm_runtime_put(&dev->pdev->dev); -} - -int psb_runtime_suspend(struct device *dev) -{ - return gma_power_suspend(dev); -} - -int psb_runtime_resume(struct device *dev) -{ - return gma_power_resume(dev); -} - -int psb_runtime_idle(struct device *dev) -{ - struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev)); - struct drm_psb_private *dev_priv = drmdev->dev_private; - if (dev_priv->display_count) - return 0; - else - return 1; -} diff --git a/drivers/gpu/drm/gma500/power.h b/drivers/gpu/drm/gma500/power.h deleted file mode 100644 index 1969d2e..0000000 --- a/drivers/gpu/drm/gma500/power.h +++ /dev/null @@ -1,67 +0,0 @@ -/************************************************************************** - * Copyright (c) 2009-2011, Intel Corporation. - * All Rights Reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: - * Benjamin Defnet - * Rajesh Poornachandran - * Massively reworked - * Alan Cox - */ -#ifndef _PSB_POWERMGMT_H_ -#define _PSB_POWERMGMT_H_ - -#include -#include - -void gma_power_init(struct drm_device *dev); -void gma_power_uninit(struct drm_device *dev); - -/* - * The kernel bus power management will call these functions - */ -int gma_power_suspend(struct device *dev); -int gma_power_resume(struct device *dev); - -/* - * These are the functions the driver should use to wrap all hw access - * (i.e. register reads and writes) - */ -bool gma_power_begin(struct drm_device *dev, bool force); -void gma_power_end(struct drm_device *dev); - -/* - * Use this function to do an instantaneous check for if the hw is on. - * Only use this in cases where you know the mutex is already held such - * as in irq install/uninstall and you need to - * prevent a deadlock situation. Otherwise use gma_power_begin(). - */ -bool gma_power_is_on(struct drm_device *dev); - -/* - * GFX-Runtime PM callbacks - */ -int psb_runtime_suspend(struct device *dev); -int psb_runtime_resume(struct device *dev); -int psb_runtime_idle(struct device *dev); - -#endif /*_PSB_POWERMGMT_H_*/ diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c deleted file mode 100644 index 95d163e..0000000 --- a/drivers/gpu/drm/gma500/psb_device.c +++ /dev/null @@ -1,330 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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 "gma_drm.h" -#include "psb_drv.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include "intel_bios.h" - - -static int psb_output_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - psb_intel_lvds_init(dev, &dev_priv->mode_dev); - psb_intel_sdvo_init(dev, SDVOB); - return 0; -} - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - -/* - * Poulsbo Backlight Interfaces - */ - -#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ -#define BLC_PWM_FREQ_CALC_CONSTANT 32 -#define MHz 1000000 - -#define PSB_BLC_PWM_PRECISION_FACTOR 10 -#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE -#define PSB_BLC_MIN_PWM_REG_FREQ 0x2 - -#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) -#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) - -static int psb_brightness; -static struct backlight_device *psb_backlight_device; - -static int psb_get_brightness(struct backlight_device *bd) -{ - /* return locally cached var instead of HW read (due to DPST etc.) */ - /* FIXME: ideally return actual value in case firmware fiddled with - it */ - return psb_brightness; -} - - -static int psb_backlight_setup(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - unsigned long core_clock; - /* u32 bl_max_freq; */ - /* unsigned long value; */ - u16 bl_max_freq; - uint32_t value; - uint32_t blc_pwm_precision_factor; - - /* get bl_max_freq and pol from dev_priv*/ - if (!dev_priv->lvds_bl) { - dev_err(dev->dev, "Has no valid LVDS backlight info\n"); - return -ENOENT; - } - bl_max_freq = dev_priv->lvds_bl->freq; - blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; - - core_clock = dev_priv->core_freq; - - value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; - value *= blc_pwm_precision_factor; - value /= bl_max_freq; - value /= blc_pwm_precision_factor; - - if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || - value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) - return -ERANGE; - else { - value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; - REG_WRITE(BLC_PWM_CTL, - (value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value)); - } - return 0; -} - -static int psb_set_brightness(struct backlight_device *bd) -{ - struct drm_device *dev = bl_get_data(psb_backlight_device); - int level = bd->props.brightness; - - /* Percentage 1-100% being valid */ - if (level < 1) - level = 1; - - psb_intel_lvds_set_brightness(dev, level); - psb_brightness = level; - return 0; -} - -static const struct backlight_ops psb_ops = { - .get_brightness = psb_get_brightness, - .update_status = psb_set_brightness, -}; - -static int psb_backlight_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - int ret; - struct backlight_properties props; - - memset(&props, 0, sizeof(struct backlight_properties)); - props.max_brightness = 100; - props.type = BACKLIGHT_PLATFORM; - - psb_backlight_device = backlight_device_register("psb-bl", - NULL, (void *)dev, &psb_ops, &props); - if (IS_ERR(psb_backlight_device)) - return PTR_ERR(psb_backlight_device); - - ret = psb_backlight_setup(dev); - if (ret < 0) { - backlight_device_unregister(psb_backlight_device); - psb_backlight_device = NULL; - return ret; - } - psb_backlight_device->props.brightness = 100; - psb_backlight_device->props.max_brightness = 100; - backlight_update_status(psb_backlight_device); - dev_priv->backlight_device = psb_backlight_device; - return 0; -} - -#endif - -/* - * Provide the Poulsbo specific chip logic and low level methods - * for power management - */ - -static void psb_init_pm(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - - u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL); - gating &= ~3; /* Disable 2D clock gating */ - gating |= 1; - PSB_WSGX32(gating, PSB_CR_CLKGATECTL); - PSB_RSGX32(PSB_CR_CLKGATECTL); -} - -/** - * psb_save_display_registers - save registers lost on suspend - * @dev: our DRM device - * - * Save the state we need in order to be able to restore the interface - * upon resume from suspend - */ -static int psb_save_display_registers(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct drm_crtc *crtc; - struct drm_connector *connector; - struct psb_state *regs = &dev_priv->regs.psb; - - /* Display arbitration control + watermarks */ - regs->saveDSPARB = PSB_RVDC32(DSPARB); - regs->saveDSPFW1 = PSB_RVDC32(DSPFW1); - regs->saveDSPFW2 = PSB_RVDC32(DSPFW2); - regs->saveDSPFW3 = PSB_RVDC32(DSPFW3); - regs->saveDSPFW4 = PSB_RVDC32(DSPFW4); - regs->saveDSPFW5 = PSB_RVDC32(DSPFW5); - regs->saveDSPFW6 = PSB_RVDC32(DSPFW6); - regs->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); - - /* Save crtc and output state */ - mutex_lock(&dev->mode_config.mutex); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (drm_helper_crtc_in_use(crtc)) - crtc->funcs->save(crtc); - } - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) - connector->funcs->save(connector); - - mutex_unlock(&dev->mode_config.mutex); - return 0; -} - -/** - * psb_restore_display_registers - restore lost register state - * @dev: our DRM device - * - * Restore register state that was lost during suspend and resume. - */ -static int psb_restore_display_registers(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct drm_crtc *crtc; - struct drm_connector *connector; - struct psb_state *regs = &dev_priv->regs.psb; - - /* Display arbitration + watermarks */ - PSB_WVDC32(regs->saveDSPARB, DSPARB); - PSB_WVDC32(regs->saveDSPFW1, DSPFW1); - PSB_WVDC32(regs->saveDSPFW2, DSPFW2); - PSB_WVDC32(regs->saveDSPFW3, DSPFW3); - PSB_WVDC32(regs->saveDSPFW4, DSPFW4); - PSB_WVDC32(regs->saveDSPFW5, DSPFW5); - PSB_WVDC32(regs->saveDSPFW6, DSPFW6); - PSB_WVDC32(regs->saveCHICKENBIT, DSPCHICKENBIT); - - /*make sure VGA plane is off. it initializes to on after reset!*/ - PSB_WVDC32(0x80000000, VGACNTRL); - - mutex_lock(&dev->mode_config.mutex); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - if (drm_helper_crtc_in_use(crtc)) - crtc->funcs->restore(crtc); - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) - connector->funcs->restore(connector); - - mutex_unlock(&dev->mode_config.mutex); - return 0; -} - -static int psb_power_down(struct drm_device *dev) -{ - return 0; -} - -static int psb_power_up(struct drm_device *dev) -{ - return 0; -} - -static void psb_get_core_freq(struct drm_device *dev) -{ - uint32_t clock; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); - struct drm_psb_private *dev_priv = dev->dev_private; - - /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/ - /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/ - - pci_write_config_dword(pci_root, 0xD0, 0xD0050300); - pci_read_config_dword(pci_root, 0xD4, &clock); - pci_dev_put(pci_root); - - switch (clock & 0x07) { - case 0: - dev_priv->core_freq = 100; - break; - case 1: - dev_priv->core_freq = 133; - break; - case 2: - dev_priv->core_freq = 150; - break; - case 3: - dev_priv->core_freq = 178; - break; - case 4: - dev_priv->core_freq = 200; - break; - case 5: - case 6: - case 7: - dev_priv->core_freq = 266; - default: - dev_priv->core_freq = 0; - } -} - -static int psb_chip_setup(struct drm_device *dev) -{ - psb_get_core_freq(dev); - gma_intel_setup_gmbus(dev); - gma_intel_opregion_init(dev); - psb_intel_init_bios(dev); - return 0; -} - -static void psb_chip_teardown(struct drm_device *dev) -{ - gma_intel_teardown_gmbus(dev); -} - -const struct psb_ops psb_chip_ops = { - .name = "Poulsbo", - .accel_2d = 1, - .pipes = 2, - .crtcs = 2, - .sgx_offset = PSB_SGX_OFFSET, - .chip_setup = psb_chip_setup, - .chip_teardown = psb_chip_teardown, - - .crtc_helper = &psb_intel_helper_funcs, - .crtc_funcs = &psb_intel_crtc_funcs, - - .output_init = psb_output_init, - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - .backlight_init = psb_backlight_init, -#endif - - .init_pm = psb_init_pm, - .save_regs = psb_save_display_registers, - .restore_regs = psb_restore_display_registers, - .power_down = psb_power_down, - .power_up = psb_power_up, -}; - diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c deleted file mode 100644 index c34adf9..0000000 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ /dev/null @@ -1,706 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2011, Intel Corporation. - * All Rights Reserved. - * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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 "gma_drm.h" -#include "psb_drv.h" -#include "framebuffer.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include "intel_bios.h" -#include "mid_bios.h" -#include -#include "power.h" -#include -#include -#include -#include -#include -#include - -static int drm_psb_trap_pagefaults; - -static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent); - -MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults"); -module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600); - - -static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { - { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, - { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, -#if defined(CONFIG_DRM_GMA600) - { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, - { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, - { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, - { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, - { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, - { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, - { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, - { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, - /* Atom E620 */ - { 0x8086, 0x4108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, -#endif -#if defined(CONFIG_DRM_MEDFIELD) - {0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, - {0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, - {0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, - {0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, - {0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, - {0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, - {0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, - {0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, -#endif -#if defined(CONFIG_DRM_GMA3600) - { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, - { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, - { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, - { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, - { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, - { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, - { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, - { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, -#endif - { 0, } -}; -MODULE_DEVICE_TABLE(pci, pciidlist); - -/* - * Standard IOCTLs. - */ - -#define DRM_IOCTL_GMA_ADB \ - DRM_IOWR(DRM_GMA_ADB + DRM_COMMAND_BASE, uint32_t) -#define DRM_IOCTL_GMA_MODE_OPERATION \ - DRM_IOWR(DRM_GMA_MODE_OPERATION + DRM_COMMAND_BASE, \ - struct drm_psb_mode_operation_arg) -#define DRM_IOCTL_GMA_STOLEN_MEMORY \ - DRM_IOWR(DRM_GMA_STOLEN_MEMORY + DRM_COMMAND_BASE, \ - struct drm_psb_stolen_memory_arg) -#define DRM_IOCTL_GMA_GAMMA \ - DRM_IOWR(DRM_GMA_GAMMA + DRM_COMMAND_BASE, \ - struct drm_psb_dpst_lut_arg) -#define DRM_IOCTL_GMA_DPST_BL \ - DRM_IOWR(DRM_GMA_DPST_BL + DRM_COMMAND_BASE, \ - uint32_t) -#define DRM_IOCTL_GMA_GET_PIPE_FROM_CRTC_ID \ - DRM_IOWR(DRM_GMA_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \ - struct drm_psb_get_pipe_from_crtc_id_arg) -#define DRM_IOCTL_GMA_GEM_CREATE \ - DRM_IOWR(DRM_GMA_GEM_CREATE + DRM_COMMAND_BASE, \ - struct drm_psb_gem_create) -#define DRM_IOCTL_GMA_GEM_MMAP \ - DRM_IOWR(DRM_GMA_GEM_MMAP + DRM_COMMAND_BASE, \ - struct drm_psb_gem_mmap) - -static int psb_adb_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -static int psb_gamma_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -static struct drm_ioctl_desc psb_ioctls[] = { - DRM_IOCTL_DEF_DRV(GMA_ADB, psb_adb_ioctl, DRM_AUTH), - DRM_IOCTL_DEF_DRV(GMA_MODE_OPERATION, psb_mode_operation_ioctl, - DRM_AUTH), - DRM_IOCTL_DEF_DRV(GMA_STOLEN_MEMORY, psb_stolen_memory_ioctl, - DRM_AUTH), - DRM_IOCTL_DEF_DRV(GMA_GAMMA, psb_gamma_ioctl, DRM_AUTH), - DRM_IOCTL_DEF_DRV(GMA_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH), - DRM_IOCTL_DEF_DRV(GMA_GET_PIPE_FROM_CRTC_ID, - psb_intel_get_pipe_from_crtc_id, 0), - DRM_IOCTL_DEF_DRV(GMA_GEM_CREATE, psb_gem_create_ioctl, - DRM_UNLOCKED | DRM_AUTH), - DRM_IOCTL_DEF_DRV(GMA_GEM_MMAP, psb_gem_mmap_ioctl, - DRM_UNLOCKED | DRM_AUTH), -}; - -static void psb_lastclose(struct drm_device *dev) -{ - return; -} - -static void psb_do_takedown(struct drm_device *dev) -{ -} - -static int psb_do_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_gtt *pg = &dev_priv->gtt; - - uint32_t stolen_gtt; - - int ret = -ENOMEM; - - if (pg->mmu_gatt_start & 0x0FFFFFFF) { - dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n"); - ret = -EINVAL; - goto out_err; - } - - - stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4; - stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT; - stolen_gtt = - (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages; - - dev_priv->gatt_free_offset = pg->mmu_gatt_start + - (stolen_gtt << PAGE_SHIFT) * 1024; - - if (1 || drm_debug) { - uint32_t core_id = PSB_RSGX32(PSB_CR_CORE_ID); - uint32_t core_rev = PSB_RSGX32(PSB_CR_CORE_REVISION); - DRM_INFO("SGX core id = 0x%08x\n", core_id); - DRM_INFO("SGX core rev major = 0x%02x, minor = 0x%02x\n", - (core_rev & _PSB_CC_REVISION_MAJOR_MASK) >> - _PSB_CC_REVISION_MAJOR_SHIFT, - (core_rev & _PSB_CC_REVISION_MINOR_MASK) >> - _PSB_CC_REVISION_MINOR_SHIFT); - DRM_INFO - ("SGX core rev maintenance = 0x%02x, designer = 0x%02x\n", - (core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK) >> - _PSB_CC_REVISION_MAINTENANCE_SHIFT, - (core_rev & _PSB_CC_REVISION_DESIGNER_MASK) >> - _PSB_CC_REVISION_DESIGNER_SHIFT); - } - - - spin_lock_init(&dev_priv->irqmask_lock); - spin_lock_init(&dev_priv->lock_2d); - - PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0); - PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1); - PSB_RSGX32(PSB_CR_BIF_BANK1); - PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK, - PSB_CR_BIF_CTRL); - psb_spank(dev_priv); - - /* mmu_gatt ?? */ - PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); - return 0; -out_err: - psb_do_takedown(dev); - return ret; -} - -static int psb_driver_unload(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - - /* Kill vblank etc here */ - - gma_backlight_exit(dev); - - psb_modeset_cleanup(dev); - - if (dev_priv) { - psb_lid_timer_takedown(dev_priv); - gma_intel_opregion_exit(dev); - - if (dev_priv->ops->chip_teardown) - dev_priv->ops->chip_teardown(dev); - psb_do_takedown(dev); - - - if (dev_priv->pf_pd) { - psb_mmu_free_pagedir(dev_priv->pf_pd); - dev_priv->pf_pd = NULL; - } - if (dev_priv->mmu) { - struct psb_gtt *pg = &dev_priv->gtt; - - down_read(&pg->sem); - psb_mmu_remove_pfn_sequence( - psb_mmu_get_default_pd - (dev_priv->mmu), - pg->mmu_gatt_start, - dev_priv->vram_stolen_size >> PAGE_SHIFT); - up_read(&pg->sem); - psb_mmu_driver_takedown(dev_priv->mmu); - dev_priv->mmu = NULL; - } - psb_gtt_takedown(dev); - if (dev_priv->scratch_page) { - __free_page(dev_priv->scratch_page); - dev_priv->scratch_page = NULL; - } - if (dev_priv->vdc_reg) { - iounmap(dev_priv->vdc_reg); - dev_priv->vdc_reg = NULL; - } - if (dev_priv->sgx_reg) { - iounmap(dev_priv->sgx_reg); - dev_priv->sgx_reg = NULL; - } - - kfree(dev_priv); - dev->dev_private = NULL; - - /*destroy VBT data*/ - psb_intel_destroy_bios(dev); - } - - gma_power_uninit(dev); - - return 0; -} - - -static int psb_driver_load(struct drm_device *dev, unsigned long chipset) -{ - struct drm_psb_private *dev_priv; - unsigned long resource_start; - unsigned long irqflags; - int ret = -ENOMEM; - struct drm_connector *connector; - struct psb_intel_encoder *psb_intel_encoder; - - dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); - if (dev_priv == NULL) - return -ENOMEM; - - dev_priv->ops = (struct psb_ops *)chipset; - dev_priv->dev = dev; - dev->dev_private = (void *) dev_priv; - - pci_set_master(dev->pdev); - - if (!IS_PSB(dev)) { - if (pci_enable_msi(dev->pdev)) - dev_warn(dev->dev, "Enabling MSI failed!\n"); - } - - dev_priv->num_pipe = dev_priv->ops->pipes; - - resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE); - - dev_priv->vdc_reg = - ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE); - if (!dev_priv->vdc_reg) - goto out_err; - - dev_priv->sgx_reg = ioremap(resource_start + dev_priv->ops->sgx_offset, - PSB_SGX_SIZE); - if (!dev_priv->sgx_reg) - goto out_err; - - ret = dev_priv->ops->chip_setup(dev); - if (ret) - goto out_err; - - /* Init OSPM support */ - gma_power_init(dev); - - ret = -ENOMEM; - - dev_priv->scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO); - if (!dev_priv->scratch_page) - goto out_err; - - set_pages_uc(dev_priv->scratch_page, 1); - - ret = psb_gtt_init(dev, 0); - if (ret) - goto out_err; - - dev_priv->mmu = psb_mmu_driver_init((void *)0, - drm_psb_trap_pagefaults, 0, - dev_priv); - if (!dev_priv->mmu) - goto out_err; - - dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0); - if (!dev_priv->pf_pd) - goto out_err; - - psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0); - psb_mmu_set_pd_context(dev_priv->pf_pd, 1); - - ret = psb_do_init(dev); - if (ret) - return ret; - - PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE); - PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE); - -/* igd_opregion_init(&dev_priv->opregion_dev); */ - acpi_video_register(); - if (dev_priv->lid_state) - psb_lid_timer_init(dev_priv); - - ret = drm_vblank_init(dev, dev_priv->num_pipe); - if (ret) - goto out_err; - - /* - * Install interrupt handlers prior to powering off SGX or else we will - * crash. - */ - dev_priv->vdc_irq_mask = 0; - dev_priv->pipestat[0] = 0; - dev_priv->pipestat[1] = 0; - dev_priv->pipestat[2] = 0; - spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R); - PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R); - spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); - if (IS_PSB(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) - drm_irq_install(dev); - - dev->vblank_disable_allowed = 1; - - dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ - - dev->driver->get_vblank_counter = psb_get_vblank_counter; - - psb_modeset_init(dev); - psb_fbdev_init(dev); - drm_kms_helper_poll_init(dev); - - /* Only add backlight support if we have LVDS output */ - list_for_each_entry(connector, &dev->mode_config.connector_list, - head) { - psb_intel_encoder = psb_intel_attached_encoder(connector); - - switch (psb_intel_encoder->type) { - case INTEL_OUTPUT_LVDS: - case INTEL_OUTPUT_MIPI: - ret = gma_backlight_init(dev); - break; - } - } - - if (ret) - return ret; -#if 0 - /*enable runtime pm at last*/ - pm_runtime_enable(&dev->pdev->dev); - pm_runtime_set_active(&dev->pdev->dev); -#endif - /*Intel drm driver load is done, continue doing pvr load*/ - return 0; -out_err: - psb_driver_unload(dev); - return ret; -} - -static int psb_driver_device_is_agp(struct drm_device *dev) -{ - return 0; -} - -static inline void get_brightness(struct backlight_device *bd) -{ -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - if (bd) { - bd->props.brightness = bd->ops->get_brightness(bd); - backlight_update_status(bd); - } -#endif -} - -static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_psb_private *dev_priv = psb_priv(dev); - uint32_t *arg = data; - - dev_priv->blc_adj2 = *arg; - get_brightness(dev_priv->backlight_device); - return 0; -} - -static int psb_adb_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_psb_private *dev_priv = psb_priv(dev); - uint32_t *arg = data; - - dev_priv->blc_adj1 = *arg; - get_brightness(dev_priv->backlight_device); - return 0; -} - -static int psb_gamma_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_psb_dpst_lut_arg *lut_arg = data; - struct drm_mode_object *obj; - struct drm_crtc *crtc; - struct drm_connector *connector; - struct psb_intel_crtc *psb_intel_crtc; - int i = 0; - int32_t obj_id; - - obj_id = lut_arg->output_id; - obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR); - if (!obj) { - dev_dbg(dev->dev, "Invalid Connector object.\n"); - return -EINVAL; - } - - connector = obj_to_connector(obj); - crtc = connector->encoder->crtc; - psb_intel_crtc = to_psb_intel_crtc(crtc); - - for (i = 0; i < 256; i++) - psb_intel_crtc->lut_adj[i] = lut_arg->lut[i]; - - psb_intel_crtc_load_lut(crtc); - - return 0; -} - -static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - uint32_t obj_id; - uint16_t op; - struct drm_mode_modeinfo *umode; - struct drm_display_mode *mode = NULL; - struct drm_psb_mode_operation_arg *arg; - struct drm_mode_object *obj; - struct drm_connector *connector; - struct drm_connector_helper_funcs *connector_funcs; - int ret = 0; - int resp = MODE_OK; - - arg = (struct drm_psb_mode_operation_arg *)data; - obj_id = arg->obj_id; - op = arg->operation; - - switch (op) { - case PSB_MODE_OPERATION_MODE_VALID: - umode = &arg->mode; - - mutex_lock(&dev->mode_config.mutex); - - obj = drm_mode_object_find(dev, obj_id, - DRM_MODE_OBJECT_CONNECTOR); - if (!obj) { - ret = -EINVAL; - goto mode_op_out; - } - - connector = obj_to_connector(obj); - - mode = drm_mode_create(dev); - if (!mode) { - ret = -ENOMEM; - goto mode_op_out; - } - - /* drm_crtc_convert_umode(mode, umode); */ - { - mode->clock = umode->clock; - mode->hdisplay = umode->hdisplay; - mode->hsync_start = umode->hsync_start; - mode->hsync_end = umode->hsync_end; - mode->htotal = umode->htotal; - mode->hskew = umode->hskew; - mode->vdisplay = umode->vdisplay; - mode->vsync_start = umode->vsync_start; - mode->vsync_end = umode->vsync_end; - mode->vtotal = umode->vtotal; - mode->vscan = umode->vscan; - mode->vrefresh = umode->vrefresh; - mode->flags = umode->flags; - mode->type = umode->type; - strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN); - mode->name[DRM_DISPLAY_MODE_LEN-1] = 0; - } - - connector_funcs = (struct drm_connector_helper_funcs *) - connector->helper_private; - - if (connector_funcs->mode_valid) { - resp = connector_funcs->mode_valid(connector, mode); - arg->data = resp; - } - - /*do some clean up work*/ - if (mode) - drm_mode_destroy(dev, mode); -mode_op_out: - mutex_unlock(&dev->mode_config.mutex); - return ret; - - default: - dev_dbg(dev->dev, "Unsupported psb mode operation\n"); - return -EOPNOTSUPP; - } - - return 0; -} - -static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_psb_private *dev_priv = psb_priv(dev); - struct drm_psb_stolen_memory_arg *arg = data; - - arg->base = dev_priv->stolen_base; - arg->size = dev_priv->vram_stolen_size; - - return 0; -} - -static int psb_driver_open(struct drm_device *dev, struct drm_file *priv) -{ - return 0; -} - -static void psb_driver_close(struct drm_device *dev, struct drm_file *priv) -{ -} - -static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct drm_file *file_priv = filp->private_data; - struct drm_device *dev = file_priv->minor->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - static unsigned int runtime_allowed; - - if (runtime_allowed == 1 && dev_priv->is_lvds_on) { - runtime_allowed++; - pm_runtime_allow(&dev->pdev->dev); - dev_priv->rpm_enabled = 1; - } - return drm_ioctl(filp, cmd, arg); - /* FIXME: do we need to wrap the other side of this */ -} - - -/* When a client dies: - * - Check for and clean up flipped page state - */ -static void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv) -{ -} - -static void psb_remove(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - drm_put_dev(dev); -} - -static const struct dev_pm_ops psb_pm_ops = { - .resume = gma_power_resume, - .suspend = gma_power_suspend, - .runtime_suspend = psb_runtime_suspend, - .runtime_resume = psb_runtime_resume, - .runtime_idle = psb_runtime_idle, -}; - -static struct vm_operations_struct psb_gem_vm_ops = { - .fault = psb_gem_fault, - .open = drm_gem_vm_open, - .close = drm_gem_vm_close, -}; - -static const struct file_operations psb_gem_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = psb_unlocked_ioctl, - .mmap = drm_gem_mmap, - .poll = drm_poll, - .fasync = drm_fasync, - .read = drm_read, -}; - -static struct drm_driver driver = { - .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \ - DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM , - .load = psb_driver_load, - .unload = psb_driver_unload, - - .ioctls = psb_ioctls, - .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls), - .device_is_agp = psb_driver_device_is_agp, - .irq_preinstall = psb_irq_preinstall, - .irq_postinstall = psb_irq_postinstall, - .irq_uninstall = psb_irq_uninstall, - .irq_handler = psb_irq_handler, - .enable_vblank = psb_enable_vblank, - .disable_vblank = psb_disable_vblank, - .get_vblank_counter = psb_get_vblank_counter, - .lastclose = psb_lastclose, - .open = psb_driver_open, - .preclose = psb_driver_preclose, - .postclose = psb_driver_close, - .reclaim_buffers = drm_core_reclaim_buffers, - - .gem_init_object = psb_gem_init_object, - .gem_free_object = psb_gem_free_object, - .gem_vm_ops = &psb_gem_vm_ops, - .dumb_create = psb_gem_dumb_create, - .dumb_map_offset = psb_gem_dumb_map_gtt, - .dumb_destroy = psb_gem_dumb_destroy, - .fops = &psb_gem_fops, - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = PSB_DRM_DRIVER_DATE, - .major = PSB_DRM_DRIVER_MAJOR, - .minor = PSB_DRM_DRIVER_MINOR, - .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL -}; - -static struct pci_driver psb_pci_driver = { - .name = DRIVER_NAME, - .id_table = pciidlist, - .probe = psb_probe, - .remove = psb_remove, - .driver = { - .pm = &psb_pm_ops, - } -}; - -static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - return drm_get_pci_dev(pdev, ent, &driver); -} - -static int __init psb_init(void) -{ - return drm_pci_init(&driver, &psb_pci_driver); -} - -static void __exit psb_exit(void) -{ - drm_pci_exit(&driver, &psb_pci_driver); -} - -late_initcall(psb_init); -module_exit(psb_exit); - -MODULE_AUTHOR("Alan Cox and others"); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h deleted file mode 100644 index 40ce2c9..0000000 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ /dev/null @@ -1,993 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - **************************************************************************/ - -#ifndef _PSB_DRV_H_ -#define _PSB_DRV_H_ - -#include - -#include -#include "drm_global.h" -#include "gem_glue.h" -#include "gma_drm.h" -#include "psb_reg.h" -#include "psb_intel_drv.h" -#include "gtt.h" -#include "power.h" -#include "oaktrail.h" - -/* Append new drm mode definition here, align with libdrm definition */ -#define DRM_MODE_SCALE_NO_SCALE 2 - -enum { - CHIP_PSB_8108 = 0, /* Poulsbo */ - CHIP_PSB_8109 = 1, /* Poulsbo */ - CHIP_MRST_4100 = 2, /* Moorestown/Oaktrail */ - CHIP_MFLD_0130 = 3, /* Medfield */ -}; - -#define IS_PSB(dev) (((dev)->pci_device & 0xfffe) == 0x8108) -#define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100) -#define IS_MFLD(dev) (((dev)->pci_device & 0xfff8) == 0x0130) - -/* - * Driver definitions - */ - -#define DRIVER_NAME "gma500" -#define DRIVER_DESC "DRM driver for the Intel GMA500" - -#define PSB_DRM_DRIVER_DATE "2011-06-06" -#define PSB_DRM_DRIVER_MAJOR 1 -#define PSB_DRM_DRIVER_MINOR 0 -#define PSB_DRM_DRIVER_PATCHLEVEL 0 - -/* - * Hardware offsets - */ -#define PSB_VDC_OFFSET 0x00000000 -#define PSB_VDC_SIZE 0x000080000 -#define MRST_MMIO_SIZE 0x0000C0000 -#define MDFLD_MMIO_SIZE 0x000100000 -#define PSB_SGX_SIZE 0x8000 -#define PSB_SGX_OFFSET 0x00040000 -#define MRST_SGX_OFFSET 0x00080000 -/* - * PCI resource identifiers - */ -#define PSB_MMIO_RESOURCE 0 -#define PSB_GATT_RESOURCE 2 -#define PSB_GTT_RESOURCE 3 -/* - * PCI configuration - */ -#define PSB_GMCH_CTRL 0x52 -#define PSB_BSM 0x5C -#define _PSB_GMCH_ENABLED 0x4 -#define PSB_PGETBL_CTL 0x2020 -#define _PSB_PGETBL_ENABLED 0x00000001 -#define PSB_SGX_2D_SLAVE_PORT 0x4000 - -/* To get rid of */ -#define PSB_TT_PRIV0_LIMIT (256*1024*1024) -#define PSB_TT_PRIV0_PLIMIT (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT) - -/* - * SGX side MMU definitions (these can probably go) - */ - -/* - * Flags for external memory type field. - */ -#define PSB_MMU_CACHED_MEMORY 0x0001 /* Bind to MMU only */ -#define PSB_MMU_RO_MEMORY 0x0002 /* MMU RO memory */ -#define PSB_MMU_WO_MEMORY 0x0004 /* MMU WO memory */ -/* - * PTE's and PDE's - */ -#define PSB_PDE_MASK 0x003FFFFF -#define PSB_PDE_SHIFT 22 -#define PSB_PTE_SHIFT 12 -/* - * Cache control - */ -#define PSB_PTE_VALID 0x0001 /* PTE / PDE valid */ -#define PSB_PTE_WO 0x0002 /* Write only */ -#define PSB_PTE_RO 0x0004 /* Read only */ -#define PSB_PTE_CACHED 0x0008 /* CPU cache coherent */ - -/* - * VDC registers and bits - */ -#define PSB_MSVDX_CLOCKGATING 0x2064 -#define PSB_TOPAZ_CLOCKGATING 0x2068 -#define PSB_HWSTAM 0x2098 -#define PSB_INSTPM 0x20C0 -#define PSB_INT_IDENTITY_R 0x20A4 -#define _MDFLD_PIPEC_EVENT_FLAG (1<<2) -#define _MDFLD_PIPEC_VBLANK_FLAG (1<<3) -#define _PSB_DPST_PIPEB_FLAG (1<<4) -#define _MDFLD_PIPEB_EVENT_FLAG (1<<4) -#define _PSB_VSYNC_PIPEB_FLAG (1<<5) -#define _PSB_DPST_PIPEA_FLAG (1<<6) -#define _PSB_PIPEA_EVENT_FLAG (1<<6) -#define _PSB_VSYNC_PIPEA_FLAG (1<<7) -#define _MDFLD_MIPIA_FLAG (1<<16) -#define _MDFLD_MIPIC_FLAG (1<<17) -#define _PSB_IRQ_SGX_FLAG (1<<18) -#define _PSB_IRQ_MSVDX_FLAG (1<<19) -#define _LNC_IRQ_TOPAZ_FLAG (1<<20) - -#define _PSB_PIPE_EVENT_FLAG (_PSB_VSYNC_PIPEA_FLAG | \ - _PSB_VSYNC_PIPEB_FLAG) - -/* This flag includes all the display IRQ bits excepts the vblank irqs. */ -#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \ - _MDFLD_PIPEB_EVENT_FLAG | \ - _PSB_PIPEA_EVENT_FLAG | \ - _PSB_VSYNC_PIPEA_FLAG | \ - _MDFLD_MIPIA_FLAG | \ - _MDFLD_MIPIC_FLAG) -#define PSB_INT_IDENTITY_R 0x20A4 -#define PSB_INT_MASK_R 0x20A8 -#define PSB_INT_ENABLE_R 0x20A0 - -#define _PSB_MMU_ER_MASK 0x0001FF00 -#define _PSB_MMU_ER_HOST (1 << 16) -#define GPIOA 0x5010 -#define GPIOB 0x5014 -#define GPIOC 0x5018 -#define GPIOD 0x501c -#define GPIOE 0x5020 -#define GPIOF 0x5024 -#define GPIOG 0x5028 -#define GPIOH 0x502c -#define GPIO_CLOCK_DIR_MASK (1 << 0) -#define GPIO_CLOCK_DIR_IN (0 << 1) -#define GPIO_CLOCK_DIR_OUT (1 << 1) -#define GPIO_CLOCK_VAL_MASK (1 << 2) -#define GPIO_CLOCK_VAL_OUT (1 << 3) -#define GPIO_CLOCK_VAL_IN (1 << 4) -#define GPIO_CLOCK_PULLUP_DISABLE (1 << 5) -#define GPIO_DATA_DIR_MASK (1 << 8) -#define GPIO_DATA_DIR_IN (0 << 9) -#define GPIO_DATA_DIR_OUT (1 << 9) -#define GPIO_DATA_VAL_MASK (1 << 10) -#define GPIO_DATA_VAL_OUT (1 << 11) -#define GPIO_DATA_VAL_IN (1 << 12) -#define GPIO_DATA_PULLUP_DISABLE (1 << 13) - -#define VCLK_DIVISOR_VGA0 0x6000 -#define VCLK_DIVISOR_VGA1 0x6004 -#define VCLK_POST_DIV 0x6010 - -#define PSB_COMM_2D (PSB_ENGINE_2D << 4) -#define PSB_COMM_3D (PSB_ENGINE_3D << 4) -#define PSB_COMM_TA (PSB_ENGINE_TA << 4) -#define PSB_COMM_HP (PSB_ENGINE_HP << 4) -#define PSB_COMM_USER_IRQ (1024 >> 2) -#define PSB_COMM_USER_IRQ_LOST (PSB_COMM_USER_IRQ + 1) -#define PSB_COMM_FW (2048 >> 2) - -#define PSB_UIRQ_VISTEST 1 -#define PSB_UIRQ_OOM_REPLY 2 -#define PSB_UIRQ_FIRE_TA_REPLY 3 -#define PSB_UIRQ_FIRE_RASTER_REPLY 4 - -#define PSB_2D_SIZE (256*1024*1024) -#define PSB_MAX_RELOC_PAGES 1024 - -#define PSB_LOW_REG_OFFS 0x0204 -#define PSB_HIGH_REG_OFFS 0x0600 - -#define PSB_NUM_VBLANKS 2 - - -#define PSB_2D_SIZE (256*1024*1024) -#define PSB_MAX_RELOC_PAGES 1024 - -#define PSB_LOW_REG_OFFS 0x0204 -#define PSB_HIGH_REG_OFFS 0x0600 - -#define PSB_NUM_VBLANKS 2 -#define PSB_WATCHDOG_DELAY (DRM_HZ * 2) -#define PSB_LID_DELAY (DRM_HZ / 10) - -#define MDFLD_PNW_B0 0x04 -#define MDFLD_PNW_C0 0x08 - -#define MDFLD_DSR_2D_3D_0 (1 << 0) -#define MDFLD_DSR_2D_3D_2 (1 << 1) -#define MDFLD_DSR_CURSOR_0 (1 << 2) -#define MDFLD_DSR_CURSOR_2 (1 << 3) -#define MDFLD_DSR_OVERLAY_0 (1 << 4) -#define MDFLD_DSR_OVERLAY_2 (1 << 5) -#define MDFLD_DSR_MIPI_CONTROL (1 << 6) -#define MDFLD_DSR_DAMAGE_MASK_0 ((1 << 0) | (1 << 2) | (1 << 4)) -#define MDFLD_DSR_DAMAGE_MASK_2 ((1 << 1) | (1 << 3) | (1 << 5)) -#define MDFLD_DSR_2D_3D (MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2) - -#define MDFLD_DSR_RR 45 -#define MDFLD_DPU_ENABLE (1 << 31) -#define MDFLD_DSR_FULLSCREEN (1 << 30) -#define MDFLD_DSR_DELAY (DRM_HZ / MDFLD_DSR_RR) - -#define PSB_PWR_STATE_ON 1 -#define PSB_PWR_STATE_OFF 2 - -#define PSB_PMPOLICY_NOPM 0 -#define PSB_PMPOLICY_CLOCKGATING 1 -#define PSB_PMPOLICY_POWERDOWN 2 - -#define PSB_PMSTATE_POWERUP 0 -#define PSB_PMSTATE_CLOCKGATED 1 -#define PSB_PMSTATE_POWERDOWN 2 -#define PSB_PCIx_MSI_ADDR_LOC 0x94 -#define PSB_PCIx_MSI_DATA_LOC 0x98 - -/* Medfield crystal settings */ -#define KSEL_CRYSTAL_19 1 -#define KSEL_BYPASS_19 5 -#define KSEL_BYPASS_25 6 -#define KSEL_BYPASS_83_100 7 - -struct opregion_header; -struct opregion_acpi; -struct opregion_swsci; -struct opregion_asle; - -struct psb_intel_opregion { - struct opregion_header *header; - struct opregion_acpi *acpi; - struct opregion_swsci *swsci; - struct opregion_asle *asle; - int enabled; -}; - -struct sdvo_device_mapping { - u8 initialized; - u8 dvo_port; - u8 slave_addr; - u8 dvo_wiring; - u8 i2c_pin; - u8 i2c_speed; - u8 ddc_pin; -}; - -struct intel_gmbus { - struct i2c_adapter adapter; - struct i2c_adapter *force_bit; - u32 reg0; -}; - -/* - * Register save state. This is used to hold the context when the - * device is powered off. In the case of Oaktrail this can (but does not - * yet) include screen blank. Operations occuring during the save - * update the register cache instead. - */ -struct psb_state { - uint32_t saveDSPACNTR; - uint32_t saveDSPBCNTR; - uint32_t savePIPEACONF; - uint32_t savePIPEBCONF; - uint32_t savePIPEASRC; - uint32_t savePIPEBSRC; - uint32_t saveFPA0; - uint32_t saveFPA1; - uint32_t saveDPLL_A; - uint32_t saveDPLL_A_MD; - uint32_t saveHTOTAL_A; - uint32_t saveHBLANK_A; - uint32_t saveHSYNC_A; - uint32_t saveVTOTAL_A; - uint32_t saveVBLANK_A; - uint32_t saveVSYNC_A; - uint32_t saveDSPASTRIDE; - uint32_t saveDSPASIZE; - uint32_t saveDSPAPOS; - uint32_t saveDSPABASE; - uint32_t saveDSPASURF; - uint32_t saveDSPASTATUS; - uint32_t saveFPB0; - uint32_t saveFPB1; - uint32_t saveDPLL_B; - uint32_t saveDPLL_B_MD; - uint32_t saveHTOTAL_B; - uint32_t saveHBLANK_B; - uint32_t saveHSYNC_B; - uint32_t saveVTOTAL_B; - uint32_t saveVBLANK_B; - uint32_t saveVSYNC_B; - uint32_t saveDSPBSTRIDE; - uint32_t saveDSPBSIZE; - uint32_t saveDSPBPOS; - uint32_t saveDSPBBASE; - uint32_t saveDSPBSURF; - uint32_t saveDSPBSTATUS; - uint32_t saveVCLK_DIVISOR_VGA0; - uint32_t saveVCLK_DIVISOR_VGA1; - uint32_t saveVCLK_POST_DIV; - uint32_t saveVGACNTRL; - uint32_t saveADPA; - uint32_t saveLVDS; - uint32_t saveDVOA; - uint32_t saveDVOB; - uint32_t saveDVOC; - uint32_t savePP_ON; - uint32_t savePP_OFF; - uint32_t savePP_CONTROL; - uint32_t savePP_CYCLE; - uint32_t savePFIT_CONTROL; - uint32_t savePaletteA[256]; - uint32_t savePaletteB[256]; - uint32_t saveCLOCKGATING; - uint32_t saveDSPARB; - uint32_t saveDSPATILEOFF; - uint32_t saveDSPBTILEOFF; - uint32_t saveDSPAADDR; - uint32_t saveDSPBADDR; - uint32_t savePFIT_AUTO_RATIOS; - uint32_t savePFIT_PGM_RATIOS; - uint32_t savePP_ON_DELAYS; - uint32_t savePP_OFF_DELAYS; - uint32_t savePP_DIVISOR; - uint32_t saveBCLRPAT_A; - uint32_t saveBCLRPAT_B; - uint32_t saveDSPALINOFF; - uint32_t saveDSPBLINOFF; - uint32_t savePERF_MODE; - uint32_t saveDSPFW1; - uint32_t saveDSPFW2; - uint32_t saveDSPFW3; - uint32_t saveDSPFW4; - uint32_t saveDSPFW5; - uint32_t saveDSPFW6; - uint32_t saveCHICKENBIT; - uint32_t saveDSPACURSOR_CTRL; - uint32_t saveDSPBCURSOR_CTRL; - uint32_t saveDSPACURSOR_BASE; - uint32_t saveDSPBCURSOR_BASE; - uint32_t saveDSPACURSOR_POS; - uint32_t saveDSPBCURSOR_POS; - uint32_t save_palette_a[256]; - uint32_t save_palette_b[256]; - uint32_t saveOV_OVADD; - uint32_t saveOV_OGAMC0; - uint32_t saveOV_OGAMC1; - uint32_t saveOV_OGAMC2; - uint32_t saveOV_OGAMC3; - uint32_t saveOV_OGAMC4; - uint32_t saveOV_OGAMC5; - uint32_t saveOVC_OVADD; - uint32_t saveOVC_OGAMC0; - uint32_t saveOVC_OGAMC1; - uint32_t saveOVC_OGAMC2; - uint32_t saveOVC_OGAMC3; - uint32_t saveOVC_OGAMC4; - uint32_t saveOVC_OGAMC5; - - /* DPST register save */ - uint32_t saveHISTOGRAM_INT_CONTROL_REG; - uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG; - uint32_t savePWM_CONTROL_LOGIC; -}; - -struct medfield_state { - uint32_t saveDPLL_A; - uint32_t saveFPA0; - uint32_t savePIPEACONF; - uint32_t saveHTOTAL_A; - uint32_t saveHBLANK_A; - uint32_t saveHSYNC_A; - uint32_t saveVTOTAL_A; - uint32_t saveVBLANK_A; - uint32_t saveVSYNC_A; - uint32_t savePIPEASRC; - uint32_t saveDSPASTRIDE; - uint32_t saveDSPALINOFF; - uint32_t saveDSPATILEOFF; - uint32_t saveDSPASIZE; - uint32_t saveDSPAPOS; - uint32_t saveDSPASURF; - uint32_t saveDSPACNTR; - uint32_t saveDSPASTATUS; - uint32_t save_palette_a[256]; - uint32_t saveMIPI; - - uint32_t saveDPLL_B; - uint32_t saveFPB0; - uint32_t savePIPEBCONF; - uint32_t saveHTOTAL_B; - uint32_t saveHBLANK_B; - uint32_t saveHSYNC_B; - uint32_t saveVTOTAL_B; - uint32_t saveVBLANK_B; - uint32_t saveVSYNC_B; - uint32_t savePIPEBSRC; - uint32_t saveDSPBSTRIDE; - uint32_t saveDSPBLINOFF; - uint32_t saveDSPBTILEOFF; - uint32_t saveDSPBSIZE; - uint32_t saveDSPBPOS; - uint32_t saveDSPBSURF; - uint32_t saveDSPBCNTR; - uint32_t saveDSPBSTATUS; - uint32_t save_palette_b[256]; - - uint32_t savePIPECCONF; - uint32_t saveHTOTAL_C; - uint32_t saveHBLANK_C; - uint32_t saveHSYNC_C; - uint32_t saveVTOTAL_C; - uint32_t saveVBLANK_C; - uint32_t saveVSYNC_C; - uint32_t savePIPECSRC; - uint32_t saveDSPCSTRIDE; - uint32_t saveDSPCLINOFF; - uint32_t saveDSPCTILEOFF; - uint32_t saveDSPCSIZE; - uint32_t saveDSPCPOS; - uint32_t saveDSPCSURF; - uint32_t saveDSPCCNTR; - uint32_t saveDSPCSTATUS; - uint32_t save_palette_c[256]; - uint32_t saveMIPI_C; - - uint32_t savePFIT_CONTROL; - uint32_t savePFIT_PGM_RATIOS; - uint32_t saveHDMIPHYMISCCTL; - uint32_t saveHDMIB_CONTROL; -}; - -struct cdv_state { - uint32_t saveDSPCLK_GATE_D; - uint32_t saveRAMCLK_GATE_D; - uint32_t saveDSPARB; - uint32_t saveDSPFW[6]; - uint32_t saveADPA; - uint32_t savePP_CONTROL; - uint32_t savePFIT_PGM_RATIOS; - uint32_t saveLVDS; - uint32_t savePFIT_CONTROL; - uint32_t savePP_ON_DELAYS; - uint32_t savePP_OFF_DELAYS; - uint32_t savePP_CYCLE; - uint32_t saveVGACNTRL; - uint32_t saveIER; - uint32_t saveIMR; - u8 saveLBB; -}; - -struct psb_save_area { - uint32_t saveBSM; - uint32_t saveVBT; - union { - struct psb_state psb; - struct medfield_state mdfld; - struct cdv_state cdv; - }; - uint32_t saveBLC_PWM_CTL2; - uint32_t saveBLC_PWM_CTL; -}; - -struct psb_ops; - -#define PSB_NUM_PIPE 3 - -struct drm_psb_private { - struct drm_device *dev; - const struct psb_ops *ops; - - struct psb_gtt gtt; - - /* GTT Memory manager */ - struct psb_gtt_mm *gtt_mm; - struct page *scratch_page; - u32 *gtt_map; - uint32_t stolen_base; - void *vram_addr; - unsigned long vram_stolen_size; - int gtt_initialized; - u16 gmch_ctrl; /* Saved GTT setup */ - u32 pge_ctl; - - struct mutex gtt_mutex; - struct resource *gtt_mem; /* Our PCI resource */ - - struct psb_mmu_driver *mmu; - struct psb_mmu_pd *pf_pd; - - /* - * Register base - */ - - uint8_t *sgx_reg; - uint8_t *vdc_reg; - uint32_t gatt_free_offset; - - /* - * Fencing / irq. - */ - - uint32_t vdc_irq_mask; - uint32_t pipestat[PSB_NUM_PIPE]; - - spinlock_t irqmask_lock; - - /* - * Power - */ - - bool suspended; - bool display_power; - int display_count; - - /* - * Modesetting - */ - struct psb_intel_mode_device mode_dev; - - struct drm_crtc *plane_to_crtc_mapping[PSB_NUM_PIPE]; - struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE]; - uint32_t num_pipe; - - /* - * OSPM info (Power management base) (can go ?) - */ - uint32_t ospm_base; - - /* - * Sizes info - */ - - u32 fuse_reg_value; - u32 video_device_fuse; - - /* PCI revision ID for B0:D2:F0 */ - uint8_t platform_rev_id; - - /* gmbus */ - struct intel_gmbus *gmbus; - - /* Used by SDVO */ - int crt_ddc_pin; - /* FIXME: The mappings should be parsed from bios but for now we can - pretend there are no mappings available */ - struct sdvo_device_mapping sdvo_mappings[2]; - u32 hotplug_supported_mask; - struct drm_property *broadcast_rgb_property; - struct drm_property *force_audio_property; - - /* - * LVDS info - */ - int backlight_duty_cycle; /* restore backlight to this value */ - bool panel_wants_dither; - struct drm_display_mode *panel_fixed_mode; - struct drm_display_mode *lfp_lvds_vbt_mode; - struct drm_display_mode *sdvo_lvds_vbt_mode; - - struct bdb_lvds_backlight *lvds_bl; /* LVDS backlight info from VBT */ - struct psb_intel_i2c_chan *lvds_i2c_bus; /* FIXME: Remove this? */ - - /* Feature bits from the VBIOS */ - unsigned int int_tv_support:1; - unsigned int lvds_dither:1; - unsigned int lvds_vbt:1; - unsigned int int_crt_support:1; - unsigned int lvds_use_ssc:1; - int lvds_ssc_freq; - bool is_lvds_on; - bool is_mipi_on; - u32 mipi_ctrl_display; - - unsigned int core_freq; - uint32_t iLVDS_enable; - - /* Runtime PM state */ - int rpm_enabled; - - /* MID specific */ - struct oaktrail_vbt vbt_data; - struct oaktrail_gct_data gct_data; - - /* Oaktrail HDMI state */ - struct oaktrail_hdmi_dev *hdmi_priv; - - /* - * Register state - */ - - struct psb_save_area regs; - - /* MSI reg save */ - uint32_t msi_addr; - uint32_t msi_data; - - - /* - * LID-Switch - */ - spinlock_t lid_lock; - struct timer_list lid_timer; - struct psb_intel_opregion opregion; - u32 *lid_state; - u32 lid_last_state; - - /* - * Watchdog - */ - - uint32_t apm_reg; - uint16_t apm_base; - - /* - * Used for modifying backlight from - * xrandr -- consider removing and using HAL instead - */ - struct backlight_device *backlight_device; - struct drm_property *backlight_property; - uint32_t blc_adj1; - uint32_t blc_adj2; - - void *fbdev; - - /* 2D acceleration */ - spinlock_t lock_2d; - - /* - * Panel brightness - */ - int brightness; - int brightness_adjusted; - - bool dsr_enable; - u32 dsr_fb_update; - bool dpi_panel_on[3]; - void *dsi_configs[2]; - u32 bpp; - u32 bpp2; - - u32 pipeconf[3]; - u32 dspcntr[3]; - - int mdfld_panel_id; -}; - - -/* - * Operations for each board type - */ - -struct psb_ops { - const char *name; - unsigned int accel_2d:1; - int pipes; /* Number of output pipes */ - int crtcs; /* Number of CRTCs */ - int sgx_offset; /* Base offset of SGX device */ - - /* Sub functions */ - struct drm_crtc_helper_funcs const *crtc_helper; - struct drm_crtc_funcs const *crtc_funcs; - - /* Setup hooks */ - int (*chip_setup)(struct drm_device *dev); - void (*chip_teardown)(struct drm_device *dev); - - /* Display management hooks */ - int (*output_init)(struct drm_device *dev); - /* Power management hooks */ - void (*init_pm)(struct drm_device *dev); - int (*save_regs)(struct drm_device *dev); - int (*restore_regs)(struct drm_device *dev); - int (*power_up)(struct drm_device *dev); - int (*power_down)(struct drm_device *dev); - - void (*lvds_bl_power)(struct drm_device *dev, bool on); -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - /* Backlight */ - int (*backlight_init)(struct drm_device *dev); -#endif - int i2c_bus; /* I2C bus identifier for Moorestown */ -}; - - - -struct psb_mmu_driver; - -extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int); -extern int drm_pick_crtcs(struct drm_device *dev); - -static inline struct drm_psb_private *psb_priv(struct drm_device *dev) -{ - return (struct drm_psb_private *) dev->dev_private; -} - -/* - * MMU stuff. - */ - -extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers, - int trap_pagefaults, - int invalid_type, - struct drm_psb_private *dev_priv); -extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver); -extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver - *driver); -extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset, - uint32_t gtt_start, uint32_t gtt_pages); -extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver, - int trap_pagefaults, - int invalid_type); -extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd); -extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot); -extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd, - unsigned long address, - uint32_t num_pages); -extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, - uint32_t start_pfn, - unsigned long address, - uint32_t num_pages, int type); -extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual, - unsigned long *pfn); - -/* - * Enable / disable MMU for different requestors. - */ - - -extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context); -extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages, - unsigned long address, uint32_t num_pages, - uint32_t desired_tile_stride, - uint32_t hw_tile_stride, int type); -extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd, - unsigned long address, uint32_t num_pages, - uint32_t desired_tile_stride, - uint32_t hw_tile_stride); -/* - *psb_irq.c - */ - -extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS); -extern int psb_irq_enable_dpst(struct drm_device *dev); -extern int psb_irq_disable_dpst(struct drm_device *dev); -extern void psb_irq_preinstall(struct drm_device *dev); -extern int psb_irq_postinstall(struct drm_device *dev); -extern void psb_irq_uninstall(struct drm_device *dev); -extern void psb_irq_turn_on_dpst(struct drm_device *dev); -extern void psb_irq_turn_off_dpst(struct drm_device *dev); - -extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands); -extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence); -extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence); -extern int psb_enable_vblank(struct drm_device *dev, int crtc); -extern void psb_disable_vblank(struct drm_device *dev, int crtc); -void -psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); - -void -psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); - -extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc); - -/* - * intel_opregion.c - */ -extern int gma_intel_opregion_init(struct drm_device *dev); -extern int gma_intel_opregion_exit(struct drm_device *dev); - -/* - * framebuffer.c - */ -extern int psbfb_probed(struct drm_device *dev); -extern int psbfb_remove(struct drm_device *dev, - struct drm_framebuffer *fb); -/* - * accel_2d.c - */ -extern void psbfb_copyarea(struct fb_info *info, - const struct fb_copyarea *region); -extern int psbfb_sync(struct fb_info *info); -extern void psb_spank(struct drm_psb_private *dev_priv); - -/* - * psb_reset.c - */ - -extern void psb_lid_timer_init(struct drm_psb_private *dev_priv); -extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv); -extern void psb_print_pagefault(struct drm_psb_private *dev_priv); - -/* modesetting */ -extern void psb_modeset_init(struct drm_device *dev); -extern void psb_modeset_cleanup(struct drm_device *dev); -extern int psb_fbdev_init(struct drm_device *dev); - -/* backlight.c */ -int gma_backlight_init(struct drm_device *dev); -void gma_backlight_exit(struct drm_device *dev); - -/* oaktrail_crtc.c */ -extern const struct drm_crtc_helper_funcs oaktrail_helper_funcs; - -/* oaktrail_lvds.c */ -extern void oaktrail_lvds_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev); - -/* psb_intel_display.c */ -extern const struct drm_crtc_helper_funcs psb_intel_helper_funcs; -extern const struct drm_crtc_funcs psb_intel_crtc_funcs; - -/* psb_intel_lvds.c */ -extern const struct drm_connector_helper_funcs - psb_intel_lvds_connector_helper_funcs; -extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs; - -/* gem.c */ -extern int psb_gem_init_object(struct drm_gem_object *obj); -extern void psb_gem_free_object(struct drm_gem_object *obj); -extern int psb_gem_get_aperture(struct drm_device *dev, void *data, - struct drm_file *file); -extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev, - struct drm_mode_create_dumb *args); -extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, - uint32_t handle); -extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, - uint32_t handle, uint64_t *offset); -extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); -extern int psb_gem_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file); -extern int psb_gem_mmap_ioctl(struct drm_device *dev, void *data, - struct drm_file *file); - -/* psb_device.c */ -extern const struct psb_ops psb_chip_ops; - -/* oaktrail_device.c */ -extern const struct psb_ops oaktrail_chip_ops; - -/* mdlfd_device.c */ -extern const struct psb_ops mdfld_chip_ops; - -/* cdv_device.c */ -extern const struct psb_ops cdv_chip_ops; - -/* - * Debug print bits setting - */ -#define PSB_D_GENERAL (1 << 0) -#define PSB_D_INIT (1 << 1) -#define PSB_D_IRQ (1 << 2) -#define PSB_D_ENTRY (1 << 3) -/* debug the get H/V BP/FP count */ -#define PSB_D_HV (1 << 4) -#define PSB_D_DBI_BF (1 << 5) -#define PSB_D_PM (1 << 6) -#define PSB_D_RENDER (1 << 7) -#define PSB_D_REG (1 << 8) -#define PSB_D_MSVDX (1 << 9) -#define PSB_D_TOPAZ (1 << 10) - -extern int drm_psb_no_fb; -extern int drm_idle_check_interval; - -/* - * Utilities - */ - -static inline u32 MRST_MSG_READ32(uint port, uint offset) -{ - int mcr = (0xD0<<24) | (port << 16) | (offset << 8); - uint32_t ret_val = 0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); - pci_write_config_dword(pci_root, 0xD0, mcr); - pci_read_config_dword(pci_root, 0xD4, &ret_val); - pci_dev_put(pci_root); - return ret_val; -} -static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value) -{ - int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); - pci_write_config_dword(pci_root, 0xD4, value); - pci_write_config_dword(pci_root, 0xD0, mcr); - pci_dev_put(pci_root); -} -static inline u32 MDFLD_MSG_READ32(uint port, uint offset) -{ - int mcr = (0x10<<24) | (port << 16) | (offset << 8); - uint32_t ret_val = 0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); - pci_write_config_dword(pci_root, 0xD0, mcr); - pci_read_config_dword(pci_root, 0xD4, &ret_val); - pci_dev_put(pci_root); - return ret_val; -} -static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value) -{ - int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); - pci_write_config_dword(pci_root, 0xD4, value); - pci_write_config_dword(pci_root, 0xD0, mcr); - pci_dev_put(pci_root); -} - -static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - return ioread32(dev_priv->vdc_reg + reg); -} - -#define REG_READ(reg) REGISTER_READ(dev, (reg)) - -static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg, - uint32_t val) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - iowrite32((val), dev_priv->vdc_reg + (reg)); -} - -#define REG_WRITE(reg, val) REGISTER_WRITE(dev, (reg), (val)) - -static inline void REGISTER_WRITE16(struct drm_device *dev, - uint32_t reg, uint32_t val) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - iowrite16((val), dev_priv->vdc_reg + (reg)); -} - -#define REG_WRITE16(reg, val) REGISTER_WRITE16(dev, (reg), (val)) - -static inline void REGISTER_WRITE8(struct drm_device *dev, - uint32_t reg, uint32_t val) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - iowrite8((val), dev_priv->vdc_reg + (reg)); -} - -#define REG_WRITE8(reg, val) REGISTER_WRITE8(dev, (reg), (val)) - -#define PSB_WVDC32(_val, _offs) iowrite32(_val, dev_priv->vdc_reg + (_offs)) -#define PSB_RVDC32(_offs) ioread32(dev_priv->vdc_reg + (_offs)) - -/* #define TRAP_SGX_PM_FAULT 1 */ -#ifdef TRAP_SGX_PM_FAULT -#define PSB_RSGX32(_offs) \ -({ \ - if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) { \ - printk(KERN_ERR \ - "access sgx when it's off!! (READ) %s, %d\n", \ - __FILE__, __LINE__); \ - melay(1000); \ - } \ - ioread32(dev_priv->sgx_reg + (_offs)); \ -}) -#else -#define PSB_RSGX32(_offs) ioread32(dev_priv->sgx_reg + (_offs)) -#endif -#define PSB_WSGX32(_val, _offs) iowrite32(_val, dev_priv->sgx_reg + (_offs)) - -#define MSVDX_REG_DUMP 0 - -#define PSB_WMSVDX32(_val, _offs) iowrite32(_val, dev_priv->msvdx_reg + (_offs)) -#define PSB_RMSVDX32(_offs) ioread32(dev_priv->msvdx_reg + (_offs)) - -#endif diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c deleted file mode 100644 index 2616558..0000000 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ /dev/null @@ -1,1436 +0,0 @@ -/* - * Copyright © 2006-2011 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: - * Eric Anholt - */ - -#include -#include - -#include -#include "framebuffer.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "psb_intel_display.h" -#include "power.h" - -struct psb_intel_clock_t { - /* given values */ - int n; - int m1, m2; - int p1, p2; - /* derived values */ - int dot; - int vco; - int m; - int p; -}; - -struct psb_intel_range_t { - int min, max; -}; - -struct psb_intel_p2_t { - int dot_limit; - int p2_slow, p2_fast; -}; - -#define INTEL_P2_NUM 2 - -struct psb_intel_limit_t { - struct psb_intel_range_t dot, vco, n, m, m1, m2, p, p1; - struct psb_intel_p2_t p2; -}; - -#define I8XX_DOT_MIN 25000 -#define I8XX_DOT_MAX 350000 -#define I8XX_VCO_MIN 930000 -#define I8XX_VCO_MAX 1400000 -#define I8XX_N_MIN 3 -#define I8XX_N_MAX 16 -#define I8XX_M_MIN 96 -#define I8XX_M_MAX 140 -#define I8XX_M1_MIN 18 -#define I8XX_M1_MAX 26 -#define I8XX_M2_MIN 6 -#define I8XX_M2_MAX 16 -#define I8XX_P_MIN 4 -#define I8XX_P_MAX 128 -#define I8XX_P1_MIN 2 -#define I8XX_P1_MAX 33 -#define I8XX_P1_LVDS_MIN 1 -#define I8XX_P1_LVDS_MAX 6 -#define I8XX_P2_SLOW 4 -#define I8XX_P2_FAST 2 -#define I8XX_P2_LVDS_SLOW 14 -#define I8XX_P2_LVDS_FAST 14 /* No fast option */ -#define I8XX_P2_SLOW_LIMIT 165000 - -#define I9XX_DOT_MIN 20000 -#define I9XX_DOT_MAX 400000 -#define I9XX_VCO_MIN 1400000 -#define I9XX_VCO_MAX 2800000 -#define I9XX_N_MIN 3 -#define I9XX_N_MAX 8 -#define I9XX_M_MIN 70 -#define I9XX_M_MAX 120 -#define I9XX_M1_MIN 10 -#define I9XX_M1_MAX 20 -#define I9XX_M2_MIN 5 -#define I9XX_M2_MAX 9 -#define I9XX_P_SDVO_DAC_MIN 5 -#define I9XX_P_SDVO_DAC_MAX 80 -#define I9XX_P_LVDS_MIN 7 -#define I9XX_P_LVDS_MAX 98 -#define I9XX_P1_MIN 1 -#define I9XX_P1_MAX 8 -#define I9XX_P2_SDVO_DAC_SLOW 10 -#define I9XX_P2_SDVO_DAC_FAST 5 -#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000 -#define I9XX_P2_LVDS_SLOW 14 -#define I9XX_P2_LVDS_FAST 7 -#define I9XX_P2_LVDS_SLOW_LIMIT 112000 - -#define INTEL_LIMIT_I8XX_DVO_DAC 0 -#define INTEL_LIMIT_I8XX_LVDS 1 -#define INTEL_LIMIT_I9XX_SDVO_DAC 2 -#define INTEL_LIMIT_I9XX_LVDS 3 - -static const struct psb_intel_limit_t psb_intel_limits[] = { - { /* INTEL_LIMIT_I8XX_DVO_DAC */ - .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, - .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, - .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, - .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, - .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, - .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, - .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, - .p1 = {.min = I8XX_P1_MIN, .max = I8XX_P1_MAX}, - .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, - .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST}, - }, - { /* INTEL_LIMIT_I8XX_LVDS */ - .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, - .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, - .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, - .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, - .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, - .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, - .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, - .p1 = {.min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX}, - .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, - .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST}, - }, - { /* INTEL_LIMIT_I9XX_SDVO_DAC */ - .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, - .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, - .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, - .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, - .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, - .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, - .p = {.min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX}, - .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, - .p2 = {.dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, - .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = - I9XX_P2_SDVO_DAC_FAST}, - }, - { /* INTEL_LIMIT_I9XX_LVDS */ - .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, - .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, - .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, - .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, - .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, - .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, - .p = {.min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX}, - .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, - /* The single-channel range is 25-112Mhz, and dual-channel - * is 80-224Mhz. Prefer single channel as much as possible. - */ - .p2 = {.dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, - .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST}, - }, -}; - -static const struct psb_intel_limit_t *psb_intel_limit(struct drm_crtc *crtc) -{ - const struct psb_intel_limit_t *limit; - - if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) - limit = &psb_intel_limits[INTEL_LIMIT_I9XX_LVDS]; - else - limit = &psb_intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; - return limit; -} - -/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ - -static void i8xx_clock(int refclk, struct psb_intel_clock_t *clock) -{ - clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); - clock->p = clock->p1 * clock->p2; - clock->vco = refclk * clock->m / (clock->n + 2); - clock->dot = clock->vco / clock->p; -} - -/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */ - -static void i9xx_clock(int refclk, struct psb_intel_clock_t *clock) -{ - clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); - clock->p = clock->p1 * clock->p2; - clock->vco = refclk * clock->m / (clock->n + 2); - clock->dot = clock->vco / clock->p; -} - -static void psb_intel_clock(struct drm_device *dev, int refclk, - struct psb_intel_clock_t *clock) -{ - return i9xx_clock(refclk, clock); -} - -/** - * Returns whether any output on the specified pipe is of the specified type - */ -bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type) -{ - struct drm_device *dev = crtc->dev; - struct drm_mode_config *mode_config = &dev->mode_config; - struct drm_connector *l_entry; - - list_for_each_entry(l_entry, &mode_config->connector_list, head) { - if (l_entry->encoder && l_entry->encoder->crtc == crtc) { - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(l_entry); - if (psb_intel_encoder->type == type) - return true; - } - } - return false; -} - -#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } -/** - * Returns whether the given set of divisors are valid for a given refclk with - * the given connectors. - */ - -static bool psb_intel_PLL_is_valid(struct drm_crtc *crtc, - struct psb_intel_clock_t *clock) -{ - const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); - - if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) - INTELPllInvalid("p1 out of range\n"); - if (clock->p < limit->p.min || limit->p.max < clock->p) - INTELPllInvalid("p out of range\n"); - if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) - INTELPllInvalid("m2 out of range\n"); - if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) - INTELPllInvalid("m1 out of range\n"); - if (clock->m1 <= clock->m2) - INTELPllInvalid("m1 <= m2\n"); - if (clock->m < limit->m.min || limit->m.max < clock->m) - INTELPllInvalid("m out of range\n"); - if (clock->n < limit->n.min || limit->n.max < clock->n) - INTELPllInvalid("n out of range\n"); - if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) - INTELPllInvalid("vco out of range\n"); - /* XXX: We may need to be checking "Dot clock" - * depending on the multiplier, connector, etc., - * rather than just a single range. - */ - if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) - INTELPllInvalid("dot out of range\n"); - - return true; -} - -/** - * Returns a set of divisors for the desired target clock with the given - * refclk, or FALSE. The returned values represent the clock equation: - * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. - */ -static bool psb_intel_find_best_PLL(struct drm_crtc *crtc, int target, - int refclk, - struct psb_intel_clock_t *best_clock) -{ - struct drm_device *dev = crtc->dev; - struct psb_intel_clock_t clock; - const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); - int err = target; - - if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && - (REG_READ(LVDS) & LVDS_PORT_EN) != 0) { - /* - * For LVDS, if the panel is on, just rely on its current - * settings for dual-channel. We haven't figured out how to - * reliably set up different single/dual channel state, if we - * even can. - */ - if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) - clock.p2 = limit->p2.p2_fast; - else - clock.p2 = limit->p2.p2_slow; - } else { - if (target < limit->p2.dot_limit) - clock.p2 = limit->p2.p2_slow; - else - clock.p2 = limit->p2.p2_fast; - } - - memset(best_clock, 0, sizeof(*best_clock)); - - for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; - clock.m1++) { - for (clock.m2 = limit->m2.min; - clock.m2 < clock.m1 && clock.m2 <= limit->m2.max; - clock.m2++) { - for (clock.n = limit->n.min; - clock.n <= limit->n.max; clock.n++) { - for (clock.p1 = limit->p1.min; - clock.p1 <= limit->p1.max; - clock.p1++) { - int this_err; - - psb_intel_clock(dev, refclk, &clock); - - if (!psb_intel_PLL_is_valid - (crtc, &clock)) - continue; - - this_err = abs(clock.dot - target); - if (this_err < err) { - *best_clock = clock; - err = this_err; - } - } - } - } - } - - return err != target; -} - -void psb_intel_wait_for_vblank(struct drm_device *dev) -{ - /* Wait for 20ms, i.e. one cycle at 50hz. */ - mdelay(20); -} - -static int psb_intel_pipe_set_base(struct drm_crtc *crtc, - int x, int y, struct drm_framebuffer *old_fb) -{ - struct drm_device *dev = crtc->dev; - /* struct drm_i915_master_private *master_priv; */ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); - int pipe = psb_intel_crtc->pipe; - unsigned long start, offset; - int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); - int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); - int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; - int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; - u32 dspcntr; - int ret = 0; - - if (!gma_power_begin(dev, true)) - return 0; - - /* no fb bound */ - if (!crtc->fb) { - dev_dbg(dev->dev, "No FB bound\n"); - goto psb_intel_pipe_cleaner; - } - - /* We are displaying this buffer, make sure it is actually loaded - into the GTT */ - ret = psb_gtt_pin(psbfb->gtt); - if (ret < 0) - goto psb_intel_pipe_set_base_exit; - start = psbfb->gtt->offset; - - offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); - - REG_WRITE(dspstride, crtc->fb->pitches[0]); - - dspcntr = REG_READ(dspcntr_reg); - dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - - switch (crtc->fb->bits_per_pixel) { - case 8: - dspcntr |= DISPPLANE_8BPP; - break; - case 16: - if (crtc->fb->depth == 15) - dspcntr |= DISPPLANE_15_16BPP; - else - dspcntr |= DISPPLANE_16BPP; - break; - case 24: - case 32: - dspcntr |= DISPPLANE_32BPP_NO_ALPHA; - break; - default: - dev_err(dev->dev, "Unknown color depth\n"); - ret = -EINVAL; - psb_gtt_unpin(psbfb->gtt); - goto psb_intel_pipe_set_base_exit; - } - REG_WRITE(dspcntr_reg, dspcntr); - - - if (0 /* FIXMEAC - check what PSB needs */) { - REG_WRITE(dspbase, offset); - REG_READ(dspbase); - REG_WRITE(dspsurf, start); - REG_READ(dspsurf); - } else { - REG_WRITE(dspbase, start + offset); - REG_READ(dspbase); - } - -psb_intel_pipe_cleaner: - /* If there was a previous display we can now unpin it */ - if (old_fb) - psb_gtt_unpin(to_psb_fb(old_fb)->gtt); - -psb_intel_pipe_set_base_exit: - gma_power_end(dev); - return ret; -} - -/** - * Sets the power management mode of the pipe and plane. - * - * This code should probably grow support for turning the cursor off and back - * on appropriately at the same time as we're turning the pipe off/on. - */ -static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode) -{ - struct drm_device *dev = crtc->dev; - /* struct drm_i915_master_private *master_priv; */ - /* struct drm_i915_private *dev_priv = dev->dev_private; */ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int pipe = psb_intel_crtc->pipe; - int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; - int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; - int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; - int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; - u32 temp; - - /* XXX: When our outputs are all unaware of DPMS modes other than off - * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. - */ - switch (mode) { - case DRM_MODE_DPMS_ON: - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - /* Enable the DPLL */ - temp = REG_READ(dpll_reg); - if ((temp & DPLL_VCO_ENABLE) == 0) { - REG_WRITE(dpll_reg, temp); - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - } - - /* Enable the pipe */ - temp = REG_READ(pipeconf_reg); - if ((temp & PIPEACONF_ENABLE) == 0) - REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); - - /* Enable the plane */ - temp = REG_READ(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) == 0) { - REG_WRITE(dspcntr_reg, - temp | DISPLAY_PLANE_ENABLE); - /* Flush the plane changes */ - REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); - } - - psb_intel_crtc_load_lut(crtc); - - /* Give the overlay scaler a chance to enable - * if it's on this pipe */ - /* psb_intel_crtc_dpms_video(crtc, true); TODO */ - break; - case DRM_MODE_DPMS_OFF: - /* Give the overlay scaler a chance to disable - * if it's on this pipe */ - /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ - - /* Disable the VGA plane that we never use */ - REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); - - /* Disable display plane */ - temp = REG_READ(dspcntr_reg); - if ((temp & DISPLAY_PLANE_ENABLE) != 0) { - REG_WRITE(dspcntr_reg, - temp & ~DISPLAY_PLANE_ENABLE); - /* Flush the plane changes */ - REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); - REG_READ(dspbase_reg); - } - - /* Next, disable display pipes */ - temp = REG_READ(pipeconf_reg); - if ((temp & PIPEACONF_ENABLE) != 0) { - REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); - REG_READ(pipeconf_reg); - } - - /* Wait for vblank for the disable to take effect. */ - psb_intel_wait_for_vblank(dev); - - temp = REG_READ(dpll_reg); - if ((temp & DPLL_VCO_ENABLE) != 0) { - REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); - REG_READ(dpll_reg); - } - - /* Wait for the clocks to turn off. */ - udelay(150); - break; - } - - /*Set FIFO Watermarks*/ - REG_WRITE(DSPARB, 0x3F3E); -} - -static void psb_intel_crtc_prepare(struct drm_crtc *crtc) -{ - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); -} - -static void psb_intel_crtc_commit(struct drm_crtc *crtc) -{ - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); -} - -void psb_intel_encoder_prepare(struct drm_encoder *encoder) -{ - struct drm_encoder_helper_funcs *encoder_funcs = - encoder->helper_private; - /* lvds has its own version of prepare see psb_intel_lvds_prepare */ - encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); -} - -void psb_intel_encoder_commit(struct drm_encoder *encoder) -{ - struct drm_encoder_helper_funcs *encoder_funcs = - encoder->helper_private; - /* lvds has its own version of commit see psb_intel_lvds_commit */ - encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); -} - -void psb_intel_encoder_destroy(struct drm_encoder *encoder) -{ - struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); - - drm_encoder_cleanup(encoder); - kfree(intel_encoder); -} - -static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - - -/** - * Return the pipe currently connected to the panel fitter, - * or -1 if the panel fitter is not present or not in use - */ -static int psb_intel_panel_fitter_pipe(struct drm_device *dev) -{ - u32 pfit_control; - - pfit_control = REG_READ(PFIT_CONTROL); - - /* See if the panel fitter is in use */ - if ((pfit_control & PFIT_ENABLE) == 0) - return -1; - /* Must be on PIPE 1 for PSB */ - return 1; -} - -static int psb_intel_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - int x, int y, - struct drm_framebuffer *old_fb) -{ - struct drm_device *dev = crtc->dev; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - int pipe = psb_intel_crtc->pipe; - int fp_reg = (pipe == 0) ? FPA0 : FPB0; - int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; - int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; - int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; - int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; - int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; - int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; - int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; - int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; - int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; - int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; - int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; - int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; - int refclk; - struct psb_intel_clock_t clock; - u32 dpll = 0, fp = 0, dspcntr, pipeconf; - bool ok, is_sdvo = false; - bool is_lvds = false, is_tv = false; - struct drm_mode_config *mode_config = &dev->mode_config; - struct drm_connector *connector; - - /* No scan out no play */ - if (crtc->fb == NULL) { - crtc_funcs->mode_set_base(crtc, x, y, old_fb); - return 0; - } - - list_for_each_entry(connector, &mode_config->connector_list, head) { - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - - if (!connector->encoder - || connector->encoder->crtc != crtc) - continue; - - switch (psb_intel_encoder->type) { - case INTEL_OUTPUT_LVDS: - is_lvds = true; - break; - case INTEL_OUTPUT_SDVO: - is_sdvo = true; - break; - case INTEL_OUTPUT_TVOUT: - is_tv = true; - break; - } - } - - refclk = 96000; - - ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, - &clock); - if (!ok) { - dev_err(dev->dev, "Couldn't find PLL settings for mode!\n"); - return 0; - } - - fp = clock.n << 16 | clock.m1 << 8 | clock.m2; - - dpll = DPLL_VGA_MODE_DIS; - if (is_lvds) { - dpll |= DPLLB_MODE_LVDS; - dpll |= DPLL_DVO_HIGH_SPEED; - } else - dpll |= DPLLB_MODE_DAC_SERIAL; - if (is_sdvo) { - int sdvo_pixel_multiply = - adjusted_mode->clock / mode->clock; - dpll |= DPLL_DVO_HIGH_SPEED; - dpll |= - (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; - } - - /* compute bitmask from p1 value */ - dpll |= (1 << (clock.p1 - 1)) << 16; - switch (clock.p2) { - case 5: - dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; - break; - case 7: - dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; - break; - case 10: - dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; - break; - case 14: - dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; - break; - } - - if (is_tv) { - /* XXX: just matching BIOS for now */ -/* dpll |= PLL_REF_INPUT_TVCLKINBC; */ - dpll |= 3; - } - dpll |= PLL_REF_INPUT_DREFCLK; - - /* setup pipeconf */ - pipeconf = REG_READ(pipeconf_reg); - - /* Set up the display plane register */ - dspcntr = DISPPLANE_GAMMA_ENABLE; - - if (pipe == 0) - dspcntr |= DISPPLANE_SEL_PIPE_A; - else - dspcntr |= DISPPLANE_SEL_PIPE_B; - - dspcntr |= DISPLAY_PLANE_ENABLE; - pipeconf |= PIPEACONF_ENABLE; - dpll |= DPLL_VCO_ENABLE; - - - /* Disable the panel fitter if it was on our pipe */ - if (psb_intel_panel_fitter_pipe(dev) == pipe) - REG_WRITE(PFIT_CONTROL, 0); - - drm_mode_debug_printmodeline(mode); - - if (dpll & DPLL_VCO_ENABLE) { - REG_WRITE(fp_reg, fp); - REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); - REG_READ(dpll_reg); - udelay(150); - } - - /* The LVDS pin pair needs to be on before the DPLLs are enabled. - * This is an exception to the general rule that mode_set doesn't turn - * things on. - */ - if (is_lvds) { - u32 lvds = REG_READ(LVDS); - - lvds &= ~LVDS_PIPEB_SELECT; - if (pipe == 1) - lvds |= LVDS_PIPEB_SELECT; - - lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; - /* Set the B0-B3 data pairs corresponding to - * whether we're going to - * set the DPLLs for dual-channel mode or not. - */ - lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); - if (clock.p2 == 7) - lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; - - /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) - * appropriately here, but we need to look more - * thoroughly into how panels behave in the two modes. - */ - - REG_WRITE(LVDS, lvds); - REG_READ(LVDS); - } - - REG_WRITE(fp_reg, fp); - REG_WRITE(dpll_reg, dpll); - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - - /* write it again -- the BIOS does, after all */ - REG_WRITE(dpll_reg, dpll); - - REG_READ(dpll_reg); - /* Wait for the clocks to stabilize. */ - udelay(150); - - REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | - ((adjusted_mode->crtc_htotal - 1) << 16)); - REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | - ((adjusted_mode->crtc_hblank_end - 1) << 16)); - REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | - ((adjusted_mode->crtc_hsync_end - 1) << 16)); - REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | - ((adjusted_mode->crtc_vtotal - 1) << 16)); - REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | - ((adjusted_mode->crtc_vblank_end - 1) << 16)); - REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | - ((adjusted_mode->crtc_vsync_end - 1) << 16)); - /* pipesrc and dspsize control the size that is scaled from, - * which should always be the user's requested size. - */ - REG_WRITE(dspsize_reg, - ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); - REG_WRITE(dsppos_reg, 0); - REG_WRITE(pipesrc_reg, - ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); - REG_WRITE(pipeconf_reg, pipeconf); - REG_READ(pipeconf_reg); - - psb_intel_wait_for_vblank(dev); - - REG_WRITE(dspcntr_reg, dspcntr); - - /* Flush the plane changes */ - crtc_funcs->mode_set_base(crtc, x, y, old_fb); - - psb_intel_wait_for_vblank(dev); - - return 0; -} - -/** Loads the palette/gamma unit for the CRTC with the prepared values */ -void psb_intel_crtc_load_lut(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_psb_private *dev_priv = - (struct drm_psb_private *)dev->dev_private; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int palreg = PALETTE_A; - int i; - - /* The clocks have to be on to load the palette. */ - if (!crtc->enabled) - return; - - switch (psb_intel_crtc->pipe) { - case 0: - break; - case 1: - palreg = PALETTE_B; - break; - case 2: - palreg = PALETTE_C; - break; - default: - dev_err(dev->dev, "Illegal Pipe Number.\n"); - return; - } - - if (gma_power_begin(dev, false)) { - for (i = 0; i < 256; i++) { - REG_WRITE(palreg + 4 * i, - ((psb_intel_crtc->lut_r[i] + - psb_intel_crtc->lut_adj[i]) << 16) | - ((psb_intel_crtc->lut_g[i] + - psb_intel_crtc->lut_adj[i]) << 8) | - (psb_intel_crtc->lut_b[i] + - psb_intel_crtc->lut_adj[i])); - } - gma_power_end(dev); - } else { - for (i = 0; i < 256; i++) { - dev_priv->regs.psb.save_palette_a[i] = - ((psb_intel_crtc->lut_r[i] + - psb_intel_crtc->lut_adj[i]) << 16) | - ((psb_intel_crtc->lut_g[i] + - psb_intel_crtc->lut_adj[i]) << 8) | - (psb_intel_crtc->lut_b[i] + - psb_intel_crtc->lut_adj[i]); - } - - } -} - -/** - * Save HW states of giving crtc - */ -static void psb_intel_crtc_save(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - /* struct drm_psb_private *dev_priv = - (struct drm_psb_private *)dev->dev_private; */ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; - int pipeA = (psb_intel_crtc->pipe == 0); - uint32_t paletteReg; - int i; - - if (!crtc_state) { - dev_err(dev->dev, "No CRTC state found\n"); - return; - } - - crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR); - crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF); - crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC); - crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0); - crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1); - crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B); - crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B); - crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B); - crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B); - crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B); - crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B); - crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B); - crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE); - - /*NOTE: DSPSIZE DSPPOS only for psb*/ - crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE); - crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS); - - crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE); - - paletteReg = pipeA ? PALETTE_A : PALETTE_B; - for (i = 0; i < 256; ++i) - crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2)); -} - -/** - * Restore HW states of giving crtc - */ -static void psb_intel_crtc_restore(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - /* struct drm_psb_private * dev_priv = - (struct drm_psb_private *)dev->dev_private; */ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; - /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */ - int pipeA = (psb_intel_crtc->pipe == 0); - uint32_t paletteReg; - int i; - - if (!crtc_state) { - dev_err(dev->dev, "No crtc state\n"); - return; - } - - if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) { - REG_WRITE(pipeA ? DPLL_A : DPLL_B, - crtc_state->saveDPLL & ~DPLL_VCO_ENABLE); - REG_READ(pipeA ? DPLL_A : DPLL_B); - udelay(150); - } - - REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0); - REG_READ(pipeA ? FPA0 : FPB0); - - REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1); - REG_READ(pipeA ? FPA1 : FPB1); - - REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL); - REG_READ(pipeA ? DPLL_A : DPLL_B); - udelay(150); - - REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL); - REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK); - REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC); - REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL); - REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK); - REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC); - REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE); - - REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE); - REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS); - - REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC); - REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); - REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF); - - psb_intel_wait_for_vblank(dev); - - REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR); - REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); - - psb_intel_wait_for_vblank(dev); - - paletteReg = pipeA ? PALETTE_A : PALETTE_B; - for (i = 0; i < 256; ++i) - REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]); -} - -static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, - uint32_t width, uint32_t height) -{ - struct drm_device *dev = crtc->dev; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int pipe = psb_intel_crtc->pipe; - uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; - uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; - uint32_t temp; - size_t addr = 0; - struct gtt_range *gt; - struct drm_gem_object *obj; - int ret; - - /* if we want to turn of the cursor ignore width and height */ - if (!handle) { - /* turn off the cursor */ - temp = CURSOR_MODE_DISABLE; - - if (gma_power_begin(dev, false)) { - REG_WRITE(control, temp); - REG_WRITE(base, 0); - gma_power_end(dev); - } - - /* Unpin the old GEM object */ - if (psb_intel_crtc->cursor_obj) { - gt = container_of(psb_intel_crtc->cursor_obj, - struct gtt_range, gem); - psb_gtt_unpin(gt); - drm_gem_object_unreference(psb_intel_crtc->cursor_obj); - psb_intel_crtc->cursor_obj = NULL; - } - - return 0; - } - - /* Currently we only support 64x64 cursors */ - if (width != 64 || height != 64) { - dev_dbg(dev->dev, "we currently only support 64x64 cursors\n"); - return -EINVAL; - } - - obj = drm_gem_object_lookup(dev, file_priv, handle); - if (!obj) - return -ENOENT; - - if (obj->size < width * height * 4) { - dev_dbg(dev->dev, "buffer is to small\n"); - return -ENOMEM; - } - - gt = container_of(obj, struct gtt_range, gem); - - /* Pin the memory into the GTT */ - ret = psb_gtt_pin(gt); - if (ret) { - dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); - return ret; - } - - - addr = gt->offset; /* Or resource.start ??? */ - - psb_intel_crtc->cursor_addr = addr; - - temp = 0; - /* set the pipe for the cursor */ - temp |= (pipe << 28); - temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; - - if (gma_power_begin(dev, false)) { - REG_WRITE(control, temp); - REG_WRITE(base, addr); - gma_power_end(dev); - } - - /* unpin the old bo */ - if (psb_intel_crtc->cursor_obj) { - gt = container_of(psb_intel_crtc->cursor_obj, - struct gtt_range, gem); - psb_gtt_unpin(gt); - drm_gem_object_unreference(psb_intel_crtc->cursor_obj); - psb_intel_crtc->cursor_obj = obj; - } - return 0; -} - -static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) -{ - struct drm_device *dev = crtc->dev; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int pipe = psb_intel_crtc->pipe; - uint32_t temp = 0; - uint32_t addr; - - - if (x < 0) { - temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); - x = -x; - } - if (y < 0) { - temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); - y = -y; - } - - temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); - temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); - - addr = psb_intel_crtc->cursor_addr; - - if (gma_power_begin(dev, false)) { - REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); - REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr); - gma_power_end(dev); - } - return 0; -} - -void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, - u16 *green, u16 *blue, uint32_t type, uint32_t size) -{ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int i; - - if (size != 256) - return; - - for (i = 0; i < 256; i++) { - psb_intel_crtc->lut_r[i] = red[i] >> 8; - psb_intel_crtc->lut_g[i] = green[i] >> 8; - psb_intel_crtc->lut_b[i] = blue[i] >> 8; - } - - psb_intel_crtc_load_lut(crtc); -} - -static int psb_crtc_set_config(struct drm_mode_set *set) -{ - int ret; - struct drm_device *dev = set->crtc->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - - if (!dev_priv->rpm_enabled) - return drm_crtc_helper_set_config(set); - - pm_runtime_forbid(&dev->pdev->dev); - ret = drm_crtc_helper_set_config(set); - pm_runtime_allow(&dev->pdev->dev); - return ret; -} - -/* Returns the clock of the currently programmed mode of the given pipe. */ -static int psb_intel_crtc_clock_get(struct drm_device *dev, - struct drm_crtc *crtc) -{ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int pipe = psb_intel_crtc->pipe; - u32 dpll; - u32 fp; - struct psb_intel_clock_t clock; - bool is_lvds; - struct drm_psb_private *dev_priv = dev->dev_private; - - if (gma_power_begin(dev, false)) { - dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B); - if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) - fp = REG_READ((pipe == 0) ? FPA0 : FPB0); - else - fp = REG_READ((pipe == 0) ? FPA1 : FPB1); - is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN); - gma_power_end(dev); - } else { - dpll = (pipe == 0) ? - dev_priv->regs.psb.saveDPLL_A : - dev_priv->regs.psb.saveDPLL_B; - - if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) - fp = (pipe == 0) ? - dev_priv->regs.psb.saveFPA0 : - dev_priv->regs.psb.saveFPB0; - else - fp = (pipe == 0) ? - dev_priv->regs.psb.saveFPA1 : - dev_priv->regs.psb.saveFPB1; - - is_lvds = (pipe == 1) && (dev_priv->regs.psb.saveLVDS & - LVDS_PORT_EN); - } - - clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; - clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; - clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; - - if (is_lvds) { - clock.p1 = - ffs((dpll & - DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> - DPLL_FPA01_P1_POST_DIV_SHIFT); - clock.p2 = 14; - - if ((dpll & PLL_REF_INPUT_MASK) == - PLLB_REF_INPUT_SPREADSPECTRUMIN) { - /* XXX: might not be 66MHz */ - i8xx_clock(66000, &clock); - } else - i8xx_clock(48000, &clock); - } else { - if (dpll & PLL_P1_DIVIDE_BY_TWO) - clock.p1 = 2; - else { - clock.p1 = - ((dpll & - DPLL_FPA01_P1_POST_DIV_MASK_I830) >> - DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; - } - if (dpll & PLL_P2_DIVIDE_BY_4) - clock.p2 = 4; - else - clock.p2 = 2; - - i8xx_clock(48000, &clock); - } - - /* XXX: It would be nice to validate the clocks, but we can't reuse - * i830PllIsValid() because it relies on the xf86_config connector - * configuration being accurate, which it isn't necessarily. - */ - - return clock.dot; -} - -/** Returns the currently programmed mode of the given pipe. */ -struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, - struct drm_crtc *crtc) -{ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - int pipe = psb_intel_crtc->pipe; - struct drm_display_mode *mode; - int htot; - int hsync; - int vtot; - int vsync; - struct drm_psb_private *dev_priv = dev->dev_private; - - if (gma_power_begin(dev, false)) { - htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); - hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B); - vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); - vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B); - gma_power_end(dev); - } else { - htot = (pipe == 0) ? - dev_priv->regs.psb.saveHTOTAL_A : - dev_priv->regs.psb.saveHTOTAL_B; - hsync = (pipe == 0) ? - dev_priv->regs.psb.saveHSYNC_A : - dev_priv->regs.psb.saveHSYNC_B; - vtot = (pipe == 0) ? - dev_priv->regs.psb.saveVTOTAL_A : - dev_priv->regs.psb.saveVTOTAL_B; - vsync = (pipe == 0) ? - dev_priv->regs.psb.saveVSYNC_A : - dev_priv->regs.psb.saveVSYNC_B; - } - - mode = kzalloc(sizeof(*mode), GFP_KERNEL); - if (!mode) - return NULL; - - mode->clock = psb_intel_crtc_clock_get(dev, crtc); - mode->hdisplay = (htot & 0xffff) + 1; - mode->htotal = ((htot & 0xffff0000) >> 16) + 1; - mode->hsync_start = (hsync & 0xffff) + 1; - mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; - mode->vdisplay = (vtot & 0xffff) + 1; - mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; - mode->vsync_start = (vsync & 0xffff) + 1; - mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; - - drm_mode_set_name(mode); - drm_mode_set_crtcinfo(mode, 0); - - return mode; -} - -void psb_intel_crtc_destroy(struct drm_crtc *crtc) -{ - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct gtt_range *gt; - - /* Unpin the old GEM object */ - if (psb_intel_crtc->cursor_obj) { - gt = container_of(psb_intel_crtc->cursor_obj, - struct gtt_range, gem); - psb_gtt_unpin(gt); - drm_gem_object_unreference(psb_intel_crtc->cursor_obj); - psb_intel_crtc->cursor_obj = NULL; - } - kfree(psb_intel_crtc->crtc_state); - drm_crtc_cleanup(crtc); - kfree(psb_intel_crtc); -} - -const struct drm_crtc_helper_funcs psb_intel_helper_funcs = { - .dpms = psb_intel_crtc_dpms, - .mode_fixup = psb_intel_crtc_mode_fixup, - .mode_set = psb_intel_crtc_mode_set, - .mode_set_base = psb_intel_pipe_set_base, - .prepare = psb_intel_crtc_prepare, - .commit = psb_intel_crtc_commit, -}; - -const struct drm_crtc_funcs psb_intel_crtc_funcs = { - .save = psb_intel_crtc_save, - .restore = psb_intel_crtc_restore, - .cursor_set = psb_intel_crtc_cursor_set, - .cursor_move = psb_intel_crtc_cursor_move, - .gamma_set = psb_intel_crtc_gamma_set, - .set_config = psb_crtc_set_config, - .destroy = psb_intel_crtc_destroy, -}; - -/* - * Set the default value of cursor control and base register - * to zero. This is a workaround for h/w defect on Oaktrail - */ -static void psb_intel_cursor_init(struct drm_device *dev, int pipe) -{ - u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR }; - u32 base[3] = { CURABASE, CURBBASE, CURCBASE }; - - REG_WRITE(control[pipe], 0); - REG_WRITE(base[pipe], 0); -} - -void psb_intel_crtc_init(struct drm_device *dev, int pipe, - struct psb_intel_mode_device *mode_dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_crtc *psb_intel_crtc; - int i; - uint16_t *r_base, *g_base, *b_base; - - /* We allocate a extra array of drm_connector pointers - * for fbdev after the crtc */ - psb_intel_crtc = - kzalloc(sizeof(struct psb_intel_crtc) + - (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), - GFP_KERNEL); - if (psb_intel_crtc == NULL) - return; - - psb_intel_crtc->crtc_state = - kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL); - if (!psb_intel_crtc->crtc_state) { - dev_err(dev->dev, "Crtc state error: No memory\n"); - kfree(psb_intel_crtc); - return; - } - - /* Set the CRTC operations from the chip specific data */ - drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs); - - drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256); - psb_intel_crtc->pipe = pipe; - psb_intel_crtc->plane = pipe; - - r_base = psb_intel_crtc->base.gamma_store; - g_base = r_base + 256; - b_base = g_base + 256; - for (i = 0; i < 256; i++) { - psb_intel_crtc->lut_r[i] = i; - psb_intel_crtc->lut_g[i] = i; - psb_intel_crtc->lut_b[i] = i; - r_base[i] = i << 8; - g_base[i] = i << 8; - b_base[i] = i << 8; - - psb_intel_crtc->lut_adj[i] = 0; - } - - psb_intel_crtc->mode_dev = mode_dev; - psb_intel_crtc->cursor_addr = 0; - - drm_crtc_helper_add(&psb_intel_crtc->base, - dev_priv->ops->crtc_helper); - - /* Setup the array of drm_connector pointer array */ - psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base; - BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || - dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL); - dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] = - &psb_intel_crtc->base; - dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] = - &psb_intel_crtc->base; - psb_intel_crtc->mode_set.connectors = - (struct drm_connector **) (psb_intel_crtc + 1); - psb_intel_crtc->mode_set.num_connectors = 0; - psb_intel_cursor_init(dev, pipe); -} - -int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data; - struct drm_mode_object *drmmode_obj; - struct psb_intel_crtc *crtc; - - if (!dev_priv) { - dev_err(dev->dev, "called with no initialization\n"); - return -EINVAL; - } - - drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id, - DRM_MODE_OBJECT_CRTC); - - if (!drmmode_obj) { - dev_err(dev->dev, "no such CRTC id\n"); - return -EINVAL; - } - - crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj)); - pipe_from_crtc_id->pipe = crtc->pipe; - - return 0; -} - -struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) -{ - struct drm_crtc *crtc = NULL; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - if (psb_intel_crtc->pipe == pipe) - break; - } - return crtc; -} - -int psb_intel_connector_clones(struct drm_device *dev, int type_mask) -{ - int index_mask = 0; - struct drm_connector *connector; - int entry = 0; - - list_for_each_entry(connector, &dev->mode_config.connector_list, - head) { - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - if (type_mask & (1 << psb_intel_encoder->type)) - index_mask |= (1 << entry); - entry++; - } - return index_mask; -} - -/* current intel driver doesn't take advantage of encoders - always give back the encoder for the connector -*/ -struct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector) -{ - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - - return &psb_intel_encoder->base; -} - -void psb_intel_connector_attach_encoder(struct psb_intel_connector *connector, - struct psb_intel_encoder *encoder) -{ - connector->encoder = encoder; - drm_mode_connector_attach_encoder(&connector->base, - &encoder->base); -} diff --git a/drivers/gpu/drm/gma500/psb_intel_display.h b/drivers/gpu/drm/gma500/psb_intel_display.h deleted file mode 100644 index 535b49a..0000000 --- a/drivers/gpu/drm/gma500/psb_intel_display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* copyright (c) 2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: - * Eric Anholt - */ - -#ifndef _INTEL_DISPLAY_H_ -#define _INTEL_DISPLAY_H_ - -bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type); -void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, - u16 *green, u16 *blue, uint32_t type, uint32_t size); -void psb_intel_crtc_destroy(struct drm_crtc *crtc); - -#endif diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h deleted file mode 100644 index f40535e..0000000 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2009-2011, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - */ - -#ifndef __INTEL_DRV_H__ -#define __INTEL_DRV_H__ - -#include -#include -#include -#include -#include - -/* - * Display related stuff - */ - -/* store information about an Ixxx DVO */ -/* The i830->i865 use multiple DVOs with multiple i2cs */ -/* the i915, i945 have a single sDVO i2c bus - which is different */ -#define MAX_OUTPUTS 6 -/* maximum connectors per crtcs in the mode set */ -#define INTELFB_CONN_LIMIT 4 - -#define INTEL_I2C_BUS_DVO 1 -#define INTEL_I2C_BUS_SDVO 2 - -/* Intel Pipe Clone Bit */ -#define INTEL_HDMIB_CLONE_BIT 1 -#define INTEL_HDMIC_CLONE_BIT 2 -#define INTEL_HDMID_CLONE_BIT 3 -#define INTEL_HDMIE_CLONE_BIT 4 -#define INTEL_HDMIF_CLONE_BIT 5 -#define INTEL_SDVO_NON_TV_CLONE_BIT 6 -#define INTEL_SDVO_TV_CLONE_BIT 7 -#define INTEL_SDVO_LVDS_CLONE_BIT 8 -#define INTEL_ANALOG_CLONE_BIT 9 -#define INTEL_TV_CLONE_BIT 10 -#define INTEL_DP_B_CLONE_BIT 11 -#define INTEL_DP_C_CLONE_BIT 12 -#define INTEL_DP_D_CLONE_BIT 13 -#define INTEL_LVDS_CLONE_BIT 14 -#define INTEL_DVO_TMDS_CLONE_BIT 15 -#define INTEL_DVO_LVDS_CLONE_BIT 16 -#define INTEL_EDP_CLONE_BIT 17 - -/* these are outputs from the chip - integrated only - * external chips are via DVO or SDVO output */ -#define INTEL_OUTPUT_UNUSED 0 -#define INTEL_OUTPUT_ANALOG 1 -#define INTEL_OUTPUT_DVO 2 -#define INTEL_OUTPUT_SDVO 3 -#define INTEL_OUTPUT_LVDS 4 -#define INTEL_OUTPUT_TVOUT 5 -#define INTEL_OUTPUT_HDMI 6 -#define INTEL_OUTPUT_MIPI 7 -#define INTEL_OUTPUT_MIPI2 8 - -#define INTEL_DVO_CHIP_NONE 0 -#define INTEL_DVO_CHIP_LVDS 1 -#define INTEL_DVO_CHIP_TMDS 2 -#define INTEL_DVO_CHIP_TVOUT 4 - -#define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0) -#define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT) - -static inline void -psb_intel_mode_set_pixel_multiplier(struct drm_display_mode *mode, - int multiplier) -{ - mode->clock *= multiplier; - mode->private_flags |= multiplier; -} - -static inline int -psb_intel_mode_get_pixel_multiplier(const struct drm_display_mode *mode) -{ - return (mode->private_flags & INTEL_MODE_PIXEL_MULTIPLIER_MASK) - >> INTEL_MODE_PIXEL_MULTIPLIER_SHIFT; -} - - -/* - * Hold information useally put on the device driver privates here, - * since it needs to be shared across multiple of devices drivers privates. - */ -struct psb_intel_mode_device { - - /* - * Abstracted memory manager operations - */ - size_t(*bo_offset) (struct drm_device *dev, void *bo); - - /* - * Cursor (Can go ?) - */ - int cursor_needs_physical; - - /* - * LVDS info - */ - int backlight_duty_cycle; /* restore backlight to this value */ - bool panel_wants_dither; - struct drm_display_mode *panel_fixed_mode; - struct drm_display_mode *panel_fixed_mode2; - struct drm_display_mode *vbt_mode; /* if any */ - - uint32_t saveBLC_PWM_CTL; -}; - -struct psb_intel_i2c_chan { - /* for getting at dev. private (mmio etc.) */ - struct drm_device *drm_dev; - u32 reg; /* GPIO reg */ - struct i2c_adapter adapter; - struct i2c_algo_bit_data algo; - u8 slave_addr; -}; - -struct psb_intel_encoder { - struct drm_encoder base; - int type; - bool needs_tv_clock; - void (*hot_plug)(struct psb_intel_encoder *); - int crtc_mask; - int clone_mask; - void *dev_priv; /* For sdvo_priv, lvds_priv, etc... */ - - /* FIXME: Either make SDVO and LVDS store it's i2c here or give CDV it's - own set of output privates */ - struct psb_intel_i2c_chan *i2c_bus; - struct psb_intel_i2c_chan *ddc_bus; -}; - -struct psb_intel_connector { - struct drm_connector base; - struct psb_intel_encoder *encoder; -}; - -struct psb_intel_crtc_state { - uint32_t saveDSPCNTR; - uint32_t savePIPECONF; - uint32_t savePIPESRC; - uint32_t saveDPLL; - uint32_t saveFP0; - uint32_t saveFP1; - uint32_t saveHTOTAL; - uint32_t saveHBLANK; - uint32_t saveHSYNC; - uint32_t saveVTOTAL; - uint32_t saveVBLANK; - uint32_t saveVSYNC; - uint32_t saveDSPSTRIDE; - uint32_t saveDSPSIZE; - uint32_t saveDSPPOS; - uint32_t saveDSPBASE; - uint32_t savePalette[256]; -}; - -struct psb_intel_crtc { - struct drm_crtc base; - int pipe; - int plane; - uint32_t cursor_addr; - u8 lut_r[256], lut_g[256], lut_b[256]; - u8 lut_adj[256]; - struct psb_intel_framebuffer *fbdev_fb; - /* a mode_set for fbdev users on this crtc */ - struct drm_mode_set mode_set; - - /* GEM object that holds our cursor */ - struct drm_gem_object *cursor_obj; - - struct drm_display_mode saved_mode; - struct drm_display_mode saved_adjusted_mode; - - struct psb_intel_mode_device *mode_dev; - - /*crtc mode setting flags*/ - u32 mode_flags; - - /* Saved Crtc HW states */ - struct psb_intel_crtc_state *crtc_state; -}; - -#define to_psb_intel_crtc(x) \ - container_of(x, struct psb_intel_crtc, base) -#define to_psb_intel_connector(x) \ - container_of(x, struct psb_intel_connector, base) -#define to_psb_intel_encoder(x) \ - container_of(x, struct psb_intel_encoder, base) -#define to_psb_intel_framebuffer(x) \ - container_of(x, struct psb_intel_framebuffer, base) - -struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev, - const u32 reg, const char *name); -void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan); -int psb_intel_ddc_get_modes(struct drm_connector *connector, - struct i2c_adapter *adapter); -extern bool psb_intel_ddc_probe(struct i2c_adapter *adapter); - -extern void psb_intel_crtc_init(struct drm_device *dev, int pipe, - struct psb_intel_mode_device *mode_dev); -extern void psb_intel_crt_init(struct drm_device *dev); -extern bool psb_intel_sdvo_init(struct drm_device *dev, int output_device); -extern void psb_intel_dvo_init(struct drm_device *dev); -extern void psb_intel_tv_init(struct drm_device *dev); -extern void psb_intel_lvds_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev); -extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level); -extern void oaktrail_lvds_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev); -extern void oaktrail_wait_for_INTR_PKT_SENT(struct drm_device *dev); -extern void oaktrail_dsi_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev); -extern void mid_dsi_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev, int dsi_num); - -extern void psb_intel_crtc_load_lut(struct drm_crtc *crtc); -extern void psb_intel_encoder_prepare(struct drm_encoder *encoder); -extern void psb_intel_encoder_commit(struct drm_encoder *encoder); -extern void psb_intel_encoder_destroy(struct drm_encoder *encoder); - -static inline struct psb_intel_encoder *psb_intel_attached_encoder( - struct drm_connector *connector) -{ - return to_psb_intel_connector(connector)->encoder; -} - -extern void psb_intel_connector_attach_encoder( - struct psb_intel_connector *connector, - struct psb_intel_encoder *encoder); - -extern struct drm_encoder *psb_intel_best_encoder(struct drm_connector - *connector); - -extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, - struct drm_crtc *crtc); -extern void psb_intel_wait_for_vblank(struct drm_device *dev); -extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, - int pipe); -extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, - int sdvoB); -extern int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector); -extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, - int enable); -extern int intelfb_probe(struct drm_device *dev); -extern int intelfb_remove(struct drm_device *dev, - struct drm_framebuffer *fb); -extern struct drm_framebuffer *psb_intel_framebuffer_create(struct drm_device - *dev, struct - drm_mode_fb_cmd - *mode_cmd, - void *mm_private); -extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); -extern int psb_intel_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode); -extern int psb_intel_lvds_set_property(struct drm_connector *connector, - struct drm_property *property, - uint64_t value); -extern void psb_intel_lvds_destroy(struct drm_connector *connector); -extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs; - -/* intel_gmbus.c */ -extern void gma_intel_i2c_reset(struct drm_device *dev); -extern int gma_intel_setup_gmbus(struct drm_device *dev); -extern void gma_intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed); -extern void gma_intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit); -extern void gma_intel_teardown_gmbus(struct drm_device *dev); - -#endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c deleted file mode 100644 index c83f5b5..0000000 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ /dev/null @@ -1,867 +0,0 @@ -/* - * Copyright © 2006-2007 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: - * Eric Anholt - * Dave Airlie - * Jesse Barnes - */ - -#include -#include - -#include "intel_bios.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "power.h" -#include - -/* - * LVDS I2C backlight control macros - */ -#define BRIGHTNESS_MAX_LEVEL 100 -#define BRIGHTNESS_MASK 0xFF -#define BLC_I2C_TYPE 0x01 -#define BLC_PWM_TYPT 0x02 - -#define BLC_POLARITY_NORMAL 0 -#define BLC_POLARITY_INVERSE 1 - -#define PSB_BLC_MAX_PWM_REG_FREQ (0xFFFE) -#define PSB_BLC_MIN_PWM_REG_FREQ (0x2) -#define PSB_BLC_PWM_PRECISION_FACTOR (10) -#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) -#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) - -struct psb_intel_lvds_priv { - /* - * Saved LVDO output states - */ - uint32_t savePP_ON; - uint32_t savePP_OFF; - uint32_t saveLVDS; - uint32_t savePP_CONTROL; - uint32_t savePP_CYCLE; - uint32_t savePFIT_CONTROL; - uint32_t savePFIT_PGM_RATIOS; - uint32_t saveBLC_PWM_CTL; - - struct psb_intel_i2c_chan *i2c_bus; - struct psb_intel_i2c_chan *ddc_bus; -}; - - -/* - * Returns the maximum level of the backlight duty cycle field. - */ -static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 ret; - - if (gma_power_begin(dev, false)) { - ret = REG_READ(BLC_PWM_CTL); - gma_power_end(dev); - } else /* Powered off, use the saved value */ - ret = dev_priv->regs.saveBLC_PWM_CTL; - - /* Top 15bits hold the frequency mask */ - ret = (ret & BACKLIGHT_MODULATION_FREQ_MASK) >> - BACKLIGHT_MODULATION_FREQ_SHIFT; - - ret *= 2; /* Return a 16bit range as needed for setting */ - if (ret == 0) - dev_err(dev->dev, "BL bug: Reg %08x save %08X\n", - REG_READ(BLC_PWM_CTL), dev_priv->regs.saveBLC_PWM_CTL); - return ret; -} - -/* - * Set LVDS backlight level by I2C command - * - * FIXME: at some point we need to both track this for PM and also - * disable runtime pm on MRST if the brightness is nil (ie blanked) - */ -static int psb_lvds_i2c_set_brightness(struct drm_device *dev, - unsigned int level) -{ - struct drm_psb_private *dev_priv = - (struct drm_psb_private *)dev->dev_private; - - struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus; - u8 out_buf[2]; - unsigned int blc_i2c_brightness; - - struct i2c_msg msgs[] = { - { - .addr = lvds_i2c_bus->slave_addr, - .flags = 0, - .len = 2, - .buf = out_buf, - } - }; - - blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level * - BRIGHTNESS_MASK / - BRIGHTNESS_MAX_LEVEL); - - if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) - blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness; - - out_buf[0] = dev_priv->lvds_bl->brightnesscmd; - out_buf[1] = (u8)blc_i2c_brightness; - - if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) { - dev_dbg(dev->dev, "I2C set brightness.(command, value) (%d, %d)\n", - dev_priv->lvds_bl->brightnesscmd, - blc_i2c_brightness); - return 0; - } - - dev_err(dev->dev, "I2C transfer error\n"); - return -1; -} - - -static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level) -{ - struct drm_psb_private *dev_priv = - (struct drm_psb_private *)dev->dev_private; - - u32 max_pwm_blc; - u32 blc_pwm_duty_cycle; - - max_pwm_blc = psb_intel_lvds_get_max_backlight(dev); - - /*BLC_PWM_CTL Should be initiated while backlight device init*/ - BUG_ON(max_pwm_blc == 0); - - blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL; - - if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) - blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle; - - blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; - REG_WRITE(BLC_PWM_CTL, - (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | - (blc_pwm_duty_cycle)); - - dev_info(dev->dev, "Backlight lvds set brightness %08x\n", - (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | - (blc_pwm_duty_cycle)); - - return 0; -} - -/* - * Set LVDS backlight level either by I2C or PWM - */ -void psb_intel_lvds_set_brightness(struct drm_device *dev, int level) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - - dev_dbg(dev->dev, "backlight level is %d\n", level); - - if (!dev_priv->lvds_bl) { - dev_err(dev->dev, "NO LVDS backlight info\n"); - return; - } - - if (dev_priv->lvds_bl->type == BLC_I2C_TYPE) - psb_lvds_i2c_set_brightness(dev, level); - else - psb_lvds_pwm_set_brightness(dev, level); -} - -/* - * Sets the backlight level. - * - * level: backlight level, from 0 to psb_intel_lvds_get_max_backlight(). - */ -static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 blc_pwm_ctl; - - if (gma_power_begin(dev, false)) { - blc_pwm_ctl = REG_READ(BLC_PWM_CTL); - blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK; - REG_WRITE(BLC_PWM_CTL, - (blc_pwm_ctl | - (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); - dev_priv->regs.saveBLC_PWM_CTL = (blc_pwm_ctl | - (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); - gma_power_end(dev); - } else { - blc_pwm_ctl = dev_priv->regs.saveBLC_PWM_CTL & - ~BACKLIGHT_DUTY_CYCLE_MASK; - dev_priv->regs.saveBLC_PWM_CTL = (blc_pwm_ctl | - (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); - } -} - -/* - * Sets the power state for the panel. - */ -static void psb_intel_lvds_set_power(struct drm_device *dev, bool on) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - u32 pp_status; - - if (!gma_power_begin(dev, true)) { - dev_err(dev->dev, "set power, chip off!\n"); - return; - } - - if (on) { - REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | - POWER_TARGET_ON); - do { - pp_status = REG_READ(PP_STATUS); - } while ((pp_status & PP_ON) == 0); - - psb_intel_lvds_set_backlight(dev, - mode_dev->backlight_duty_cycle); - } else { - psb_intel_lvds_set_backlight(dev, 0); - - REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & - ~POWER_TARGET_ON); - do { - pp_status = REG_READ(PP_STATUS); - } while (pp_status & PP_ON); - } - - gma_power_end(dev); -} - -static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - struct drm_device *dev = encoder->dev; - - if (mode == DRM_MODE_DPMS_ON) - psb_intel_lvds_set_power(dev, true); - else - psb_intel_lvds_set_power(dev, false); - - /* XXX: We never power down the LVDS pairs. */ -} - -static void psb_intel_lvds_save(struct drm_connector *connector) -{ - struct drm_device *dev = connector->dev; - struct drm_psb_private *dev_priv = - (struct drm_psb_private *)dev->dev_private; - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - struct psb_intel_lvds_priv *lvds_priv = - (struct psb_intel_lvds_priv *)psb_intel_encoder->dev_priv; - - lvds_priv->savePP_ON = REG_READ(LVDSPP_ON); - lvds_priv->savePP_OFF = REG_READ(LVDSPP_OFF); - lvds_priv->saveLVDS = REG_READ(LVDS); - lvds_priv->savePP_CONTROL = REG_READ(PP_CONTROL); - lvds_priv->savePP_CYCLE = REG_READ(PP_CYCLE); - /*lvds_priv->savePP_DIVISOR = REG_READ(PP_DIVISOR);*/ - lvds_priv->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); - lvds_priv->savePFIT_CONTROL = REG_READ(PFIT_CONTROL); - lvds_priv->savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS); - - /*TODO: move backlight_duty_cycle to psb_intel_lvds_priv*/ - dev_priv->backlight_duty_cycle = (dev_priv->regs.saveBLC_PWM_CTL & - BACKLIGHT_DUTY_CYCLE_MASK); - - /* - * If the light is off at server startup, - * just make it full brightness - */ - if (dev_priv->backlight_duty_cycle == 0) - dev_priv->backlight_duty_cycle = - psb_intel_lvds_get_max_backlight(dev); - - dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", - lvds_priv->savePP_ON, - lvds_priv->savePP_OFF, - lvds_priv->saveLVDS, - lvds_priv->savePP_CONTROL, - lvds_priv->savePP_CYCLE, - lvds_priv->saveBLC_PWM_CTL); -} - -static void psb_intel_lvds_restore(struct drm_connector *connector) -{ - struct drm_device *dev = connector->dev; - u32 pp_status; - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - struct psb_intel_lvds_priv *lvds_priv = - (struct psb_intel_lvds_priv *)psb_intel_encoder->dev_priv; - - dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", - lvds_priv->savePP_ON, - lvds_priv->savePP_OFF, - lvds_priv->saveLVDS, - lvds_priv->savePP_CONTROL, - lvds_priv->savePP_CYCLE, - lvds_priv->saveBLC_PWM_CTL); - - REG_WRITE(BLC_PWM_CTL, lvds_priv->saveBLC_PWM_CTL); - REG_WRITE(PFIT_CONTROL, lvds_priv->savePFIT_CONTROL); - REG_WRITE(PFIT_PGM_RATIOS, lvds_priv->savePFIT_PGM_RATIOS); - REG_WRITE(LVDSPP_ON, lvds_priv->savePP_ON); - REG_WRITE(LVDSPP_OFF, lvds_priv->savePP_OFF); - /*REG_WRITE(PP_DIVISOR, lvds_priv->savePP_DIVISOR);*/ - REG_WRITE(PP_CYCLE, lvds_priv->savePP_CYCLE); - REG_WRITE(PP_CONTROL, lvds_priv->savePP_CONTROL); - REG_WRITE(LVDS, lvds_priv->saveLVDS); - - if (lvds_priv->savePP_CONTROL & POWER_TARGET_ON) { - REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | - POWER_TARGET_ON); - do { - pp_status = REG_READ(PP_STATUS); - } while ((pp_status & PP_ON) == 0); - } else { - REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & - ~POWER_TARGET_ON); - do { - pp_status = REG_READ(PP_STATUS); - } while (pp_status & PP_ON); - } -} - -int psb_intel_lvds_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct drm_psb_private *dev_priv = connector->dev->dev_private; - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - struct drm_display_mode *fixed_mode = - dev_priv->mode_dev.panel_fixed_mode; - - if (psb_intel_encoder->type == INTEL_OUTPUT_MIPI2) - fixed_mode = dev_priv->mode_dev.panel_fixed_mode2; - - /* just in case */ - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - - /* just in case */ - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - return MODE_NO_INTERLACE; - - if (fixed_mode) { - if (mode->hdisplay > fixed_mode->hdisplay) - return MODE_PANEL; - if (mode->vdisplay > fixed_mode->vdisplay) - return MODE_PANEL; - } - return MODE_OK; -} - -bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_device *dev = encoder->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - struct psb_intel_crtc *psb_intel_crtc = - to_psb_intel_crtc(encoder->crtc); - struct drm_encoder *tmp_encoder; - struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode; - struct psb_intel_encoder *psb_intel_encoder = - to_psb_intel_encoder(encoder); - - if (psb_intel_encoder->type == INTEL_OUTPUT_MIPI2) - panel_fixed_mode = mode_dev->panel_fixed_mode2; - - /* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */ - if (!IS_MRST(dev) && psb_intel_crtc->pipe == 0) { - printk(KERN_ERR "Can't support LVDS on pipe A\n"); - return false; - } - if (IS_MRST(dev) && psb_intel_crtc->pipe != 0) { - printk(KERN_ERR "Must use PIPE A\n"); - return false; - } - /* Should never happen!! */ - list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, - head) { - if (tmp_encoder != encoder - && tmp_encoder->crtc == encoder->crtc) { - printk(KERN_ERR "Can't enable LVDS and another " - "encoder on the same pipe\n"); - return false; - } - } - - /* - * If we have timings from the BIOS for the panel, put them in - * to the adjusted mode. The CRTC will be set up for this mode, - * with the panel scaling set up to source from the H/VDisplay - * of the original mode. - */ - if (panel_fixed_mode != NULL) { - adjusted_mode->hdisplay = panel_fixed_mode->hdisplay; - adjusted_mode->hsync_start = panel_fixed_mode->hsync_start; - adjusted_mode->hsync_end = panel_fixed_mode->hsync_end; - adjusted_mode->htotal = panel_fixed_mode->htotal; - adjusted_mode->vdisplay = panel_fixed_mode->vdisplay; - adjusted_mode->vsync_start = panel_fixed_mode->vsync_start; - adjusted_mode->vsync_end = panel_fixed_mode->vsync_end; - adjusted_mode->vtotal = panel_fixed_mode->vtotal; - adjusted_mode->clock = panel_fixed_mode->clock; - drm_mode_set_crtcinfo(adjusted_mode, - CRTC_INTERLACE_HALVE_V); - } - - /* - * XXX: It would be nice to support lower refresh rates on the - * panels to reduce power consumption, and perhaps match the - * user's requested refresh rate. - */ - - return true; -} - -static void psb_intel_lvds_prepare(struct drm_encoder *encoder) -{ - struct drm_device *dev = encoder->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - - if (!gma_power_begin(dev, true)) - return; - - mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); - mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & - BACKLIGHT_DUTY_CYCLE_MASK); - - psb_intel_lvds_set_power(dev, false); - - gma_power_end(dev); -} - -static void psb_intel_lvds_commit(struct drm_encoder *encoder) -{ - struct drm_device *dev = encoder->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - - if (mode_dev->backlight_duty_cycle == 0) - mode_dev->backlight_duty_cycle = - psb_intel_lvds_get_max_backlight(dev); - - psb_intel_lvds_set_power(dev, true); -} - -static void psb_intel_lvds_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_device *dev = encoder->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - u32 pfit_control; - - /* - * The LVDS pin pair will already have been turned on in the - * psb_intel_crtc_mode_set since it has a large impact on the DPLL - * settings. - */ - - /* - * Enable automatic panel scaling so that non-native modes fill the - * screen. Should be enabled before the pipe is enabled, according to - * register description and PRM. - */ - if (mode->hdisplay != adjusted_mode->hdisplay || - mode->vdisplay != adjusted_mode->vdisplay) - pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | - HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | - HORIZ_INTERP_BILINEAR); - else - pfit_control = 0; - - if (dev_priv->lvds_dither) - pfit_control |= PANEL_8TO6_DITHER_ENABLE; - - REG_WRITE(PFIT_CONTROL, pfit_control); -} - -/* - * Detect the LVDS connection. - * - * This always returns CONNECTOR_STATUS_CONNECTED. - * This connector should only have - * been set up if the LVDS was actually connected anyway. - */ -static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector - *connector, bool force) -{ - return connector_status_connected; -} - -/* - * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. - */ -static int psb_intel_lvds_get_modes(struct drm_connector *connector) -{ - struct drm_device *dev = connector->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - struct psb_intel_lvds_priv *lvds_priv = psb_intel_encoder->dev_priv; - int ret = 0; - - if (!IS_MRST(dev)) - ret = psb_intel_ddc_get_modes(connector, &lvds_priv->i2c_bus->adapter); - - if (ret) - return ret; - - /* Didn't get an EDID, so - * Set wide sync ranges so we get all modes - * handed to valid_mode for checking - */ - connector->display_info.min_vfreq = 0; - connector->display_info.max_vfreq = 200; - connector->display_info.min_hfreq = 0; - connector->display_info.max_hfreq = 200; - - if (mode_dev->panel_fixed_mode != NULL) { - struct drm_display_mode *mode = - drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); - drm_mode_probed_add(connector, mode); - return 1; - } - - return 0; -} - -/** - * psb_intel_lvds_destroy - unregister and free LVDS structures - * @connector: connector to free - * - * Unregister the DDC bus for this connector then free the driver private - * structure. - */ -void psb_intel_lvds_destroy(struct drm_connector *connector) -{ - struct psb_intel_encoder *psb_intel_encoder = - psb_intel_attached_encoder(connector); - struct psb_intel_lvds_priv *lvds_priv = psb_intel_encoder->dev_priv; - - if (lvds_priv->ddc_bus) - psb_intel_i2c_destroy(lvds_priv->ddc_bus); - drm_sysfs_connector_remove(connector); - drm_connector_cleanup(connector); - kfree(connector); -} - -int psb_intel_lvds_set_property(struct drm_connector *connector, - struct drm_property *property, - uint64_t value) -{ - struct drm_encoder *encoder = connector->encoder; - - if (!encoder) - return -1; - - if (!strcmp(property->name, "scaling mode")) { - struct psb_intel_crtc *crtc = - to_psb_intel_crtc(encoder->crtc); - uint64_t curval; - - if (!crtc) - goto set_prop_error; - - switch (value) { - case DRM_MODE_SCALE_FULLSCREEN: - break; - case DRM_MODE_SCALE_NO_SCALE: - break; - case DRM_MODE_SCALE_ASPECT: - break; - default: - goto set_prop_error; - } - - if (drm_connector_property_get_value(connector, - property, - &curval)) - goto set_prop_error; - - if (curval == value) - goto set_prop_done; - - if (drm_connector_property_set_value(connector, - property, - value)) - goto set_prop_error; - - if (crtc->saved_mode.hdisplay != 0 && - crtc->saved_mode.vdisplay != 0) { - if (!drm_crtc_helper_set_mode(encoder->crtc, - &crtc->saved_mode, - encoder->crtc->x, - encoder->crtc->y, - encoder->crtc->fb)) - goto set_prop_error; - } - } else if (!strcmp(property->name, "backlight")) { - if (drm_connector_property_set_value(connector, - property, - value)) - goto set_prop_error; - else { -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - struct drm_psb_private *devp = - encoder->dev->dev_private; - struct backlight_device *bd = devp->backlight_device; - if (bd) { - bd->props.brightness = value; - backlight_update_status(bd); - } -#endif - } - } else if (!strcmp(property->name, "DPMS")) { - struct drm_encoder_helper_funcs *hfuncs - = encoder->helper_private; - hfuncs->dpms(encoder, value); - } - -set_prop_done: - return 0; -set_prop_error: - return -1; -} - -static const struct drm_encoder_helper_funcs psb_intel_lvds_helper_funcs = { - .dpms = psb_intel_lvds_encoder_dpms, - .mode_fixup = psb_intel_lvds_mode_fixup, - .prepare = psb_intel_lvds_prepare, - .mode_set = psb_intel_lvds_mode_set, - .commit = psb_intel_lvds_commit, -}; - -const struct drm_connector_helper_funcs - psb_intel_lvds_connector_helper_funcs = { - .get_modes = psb_intel_lvds_get_modes, - .mode_valid = psb_intel_lvds_mode_valid, - .best_encoder = psb_intel_best_encoder, -}; - -const struct drm_connector_funcs psb_intel_lvds_connector_funcs = { - .dpms = drm_helper_connector_dpms, - .save = psb_intel_lvds_save, - .restore = psb_intel_lvds_restore, - .detect = psb_intel_lvds_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .set_property = psb_intel_lvds_set_property, - .destroy = psb_intel_lvds_destroy, -}; - - -static void psb_intel_lvds_enc_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); -} - -const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = { - .destroy = psb_intel_lvds_enc_destroy, -}; - - - -/** - * psb_intel_lvds_init - setup LVDS connectors on this device - * @dev: drm device - * - * Create the connector, register the LVDS DDC bus, and try to figure out what - * modes we can display on the LVDS panel (if present). - */ -void psb_intel_lvds_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev) -{ - struct psb_intel_encoder *psb_intel_encoder; - struct psb_intel_connector *psb_intel_connector; - struct psb_intel_lvds_priv *lvds_priv; - struct drm_connector *connector; - struct drm_encoder *encoder; - struct drm_display_mode *scan; /* *modes, *bios_mode; */ - struct drm_crtc *crtc; - struct drm_psb_private *dev_priv = dev->dev_private; - u32 lvds; - int pipe; - - psb_intel_encoder = - kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); - if (!psb_intel_encoder) { - dev_err(dev->dev, "psb_intel_encoder allocation error\n"); - return; - } - - psb_intel_connector = - kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL); - if (!psb_intel_connector) { - dev_err(dev->dev, "psb_intel_connector allocation error\n"); - goto failed_encoder; - } - - lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL); - if (!lvds_priv) { - dev_err(dev->dev, "LVDS private allocation error\n"); - goto failed_connector; - } - - psb_intel_encoder->dev_priv = lvds_priv; - - connector = &psb_intel_connector->base; - encoder = &psb_intel_encoder->base; - drm_connector_init(dev, connector, - &psb_intel_lvds_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - - drm_encoder_init(dev, encoder, - &psb_intel_lvds_enc_funcs, - DRM_MODE_ENCODER_LVDS); - - psb_intel_connector_attach_encoder(psb_intel_connector, - psb_intel_encoder); - psb_intel_encoder->type = INTEL_OUTPUT_LVDS; - - drm_encoder_helper_add(encoder, &psb_intel_lvds_helper_funcs); - drm_connector_helper_add(connector, - &psb_intel_lvds_connector_helper_funcs); - connector->display_info.subpixel_order = SubPixelHorizontalRGB; - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - - /*Attach connector properties*/ - drm_connector_attach_property(connector, - dev->mode_config.scaling_mode_property, - DRM_MODE_SCALE_FULLSCREEN); - drm_connector_attach_property(connector, - dev_priv->backlight_property, - BRIGHTNESS_MAX_LEVEL); - - /* - * Set up I2C bus - * FIXME: distroy i2c_bus when exit - */ - lvds_priv->i2c_bus = psb_intel_i2c_create(dev, GPIOB, "LVDSBLC_B"); - if (!lvds_priv->i2c_bus) { - dev_printk(KERN_ERR, - &dev->pdev->dev, "I2C bus registration failed.\n"); - goto failed_blc_i2c; - } - lvds_priv->i2c_bus->slave_addr = 0x2C; - dev_priv->lvds_i2c_bus = lvds_priv->i2c_bus; - - /* - * LVDS discovery: - * 1) check for EDID on DDC - * 2) check for VBT data - * 3) check to see if LVDS is already on - * if none of the above, no panel - * 4) make sure lid is open - * if closed, act like it's not there for now - */ - - /* Set up the DDC bus. */ - lvds_priv->ddc_bus = psb_intel_i2c_create(dev, GPIOC, "LVDSDDC_C"); - if (!lvds_priv->ddc_bus) { - dev_printk(KERN_ERR, &dev->pdev->dev, - "DDC bus registration " "failed.\n"); - goto failed_ddc; - } - - /* - * Attempt to get the fixed panel mode from DDC. Assume that the - * preferred mode is the right one. - */ - psb_intel_ddc_get_modes(connector, &lvds_priv->ddc_bus->adapter); - list_for_each_entry(scan, &connector->probed_modes, head) { - if (scan->type & DRM_MODE_TYPE_PREFERRED) { - mode_dev->panel_fixed_mode = - drm_mode_duplicate(dev, scan); - goto out; /* FIXME: check for quirks */ - } - } - - /* Failed to get EDID, what about VBT? do we need this? */ - if (mode_dev->vbt_mode) - mode_dev->panel_fixed_mode = - drm_mode_duplicate(dev, mode_dev->vbt_mode); - - if (!mode_dev->panel_fixed_mode) - if (dev_priv->lfp_lvds_vbt_mode) - mode_dev->panel_fixed_mode = - drm_mode_duplicate(dev, - dev_priv->lfp_lvds_vbt_mode); - - /* - * If we didn't get EDID, try checking if the panel is already turned - * on. If so, assume that whatever is currently programmed is the - * correct mode. - */ - lvds = REG_READ(LVDS); - pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; - crtc = psb_intel_get_crtc_from_pipe(dev, pipe); - - if (crtc && (lvds & LVDS_PORT_EN)) { - mode_dev->panel_fixed_mode = - psb_intel_crtc_mode_get(dev, crtc); - if (mode_dev->panel_fixed_mode) { - mode_dev->panel_fixed_mode->type |= - DRM_MODE_TYPE_PREFERRED; - goto out; /* FIXME: check for quirks */ - } - } - - /* If we still don't have a mode after all that, give up. */ - if (!mode_dev->panel_fixed_mode) { - dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n"); - goto failed_find; - } - - /* - * Blacklist machines with BIOSes that list an LVDS panel without - * actually having one. - */ -out: - drm_sysfs_connector_add(connector); - return; - -failed_find: - if (lvds_priv->ddc_bus) - psb_intel_i2c_destroy(lvds_priv->ddc_bus); -failed_ddc: - if (lvds_priv->i2c_bus) - psb_intel_i2c_destroy(lvds_priv->i2c_bus); -failed_blc_i2c: - drm_encoder_cleanup(encoder); - drm_connector_cleanup(connector); -failed_connector: - kfree(psb_intel_connector); -failed_encoder: - kfree(psb_intel_encoder); -} - diff --git a/drivers/gpu/drm/gma500/psb_intel_modes.c b/drivers/gpu/drm/gma500/psb_intel_modes.c deleted file mode 100644 index 4fca0d6..0000000 --- a/drivers/gpu/drm/gma500/psb_intel_modes.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2007 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authers: Jesse Barnes - */ - -#include -#include -#include -#include "psb_intel_drv.h" - -/** - * psb_intel_ddc_probe - * - */ -bool psb_intel_ddc_probe(struct i2c_adapter *adapter) -{ - u8 out_buf[] = { 0x0, 0x0 }; - u8 buf[2]; - int ret; - struct i2c_msg msgs[] = { - { - .addr = 0x50, - .flags = 0, - .len = 1, - .buf = out_buf, - }, - { - .addr = 0x50, - .flags = I2C_M_RD, - .len = 1, - .buf = buf, - } - }; - - ret = i2c_transfer(adapter, msgs, 2); - if (ret == 2) - return true; - - return false; -} - -/** - * psb_intel_ddc_get_modes - get modelist from monitor - * @connector: DRM connector device to use - * - * Fetch the EDID information from @connector using the DDC bus. - */ -int psb_intel_ddc_get_modes(struct drm_connector *connector, - struct i2c_adapter *adapter) -{ - struct edid *edid; - int ret = 0; - - edid = drm_get_edid(connector, adapter); - if (edid) { - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - kfree(edid); - } - return ret; -} diff --git a/drivers/gpu/drm/gma500/psb_intel_reg.h b/drivers/gpu/drm/gma500/psb_intel_reg.h deleted file mode 100644 index e89d3a2..0000000 --- a/drivers/gpu/drm/gma500/psb_intel_reg.h +++ /dev/null @@ -1,1318 +0,0 @@ -/* - * Copyright (c) 2009, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - */ -#ifndef __PSB_INTEL_REG_H__ -#define __PSB_INTEL_REG_H__ - -/* - * GPIO regs - */ -#define GPIOA 0x5010 -#define GPIOB 0x5014 -#define GPIOC 0x5018 -#define GPIOD 0x501c -#define GPIOE 0x5020 -#define GPIOF 0x5024 -#define GPIOG 0x5028 -#define GPIOH 0x502c -# define GPIO_CLOCK_DIR_MASK (1 << 0) -# define GPIO_CLOCK_DIR_IN (0 << 1) -# define GPIO_CLOCK_DIR_OUT (1 << 1) -# define GPIO_CLOCK_VAL_MASK (1 << 2) -# define GPIO_CLOCK_VAL_OUT (1 << 3) -# define GPIO_CLOCK_VAL_IN (1 << 4) -# define GPIO_CLOCK_PULLUP_DISABLE (1 << 5) -# define GPIO_DATA_DIR_MASK (1 << 8) -# define GPIO_DATA_DIR_IN (0 << 9) -# define GPIO_DATA_DIR_OUT (1 << 9) -# define GPIO_DATA_VAL_MASK (1 << 10) -# define GPIO_DATA_VAL_OUT (1 << 11) -# define GPIO_DATA_VAL_IN (1 << 12) -# define GPIO_DATA_PULLUP_DISABLE (1 << 13) - -#define GMBUS0 0x5100 /* clock/port select */ -#define GMBUS_RATE_100KHZ (0<<8) -#define GMBUS_RATE_50KHZ (1<<8) -#define GMBUS_RATE_400KHZ (2<<8) /* reserved on Pineview */ -#define GMBUS_RATE_1MHZ (3<<8) /* reserved on Pineview */ -#define GMBUS_HOLD_EXT (1<<7) /* 300ns hold time, rsvd on Pineview */ -#define GMBUS_PORT_DISABLED 0 -#define GMBUS_PORT_SSC 1 -#define GMBUS_PORT_VGADDC 2 -#define GMBUS_PORT_PANEL 3 -#define GMBUS_PORT_DPC 4 /* HDMIC */ -#define GMBUS_PORT_DPB 5 /* SDVO, HDMIB */ - /* 6 reserved */ -#define GMBUS_PORT_DPD 7 /* HDMID */ -#define GMBUS_NUM_PORTS 8 -#define GMBUS1 0x5104 /* command/status */ -#define GMBUS_SW_CLR_INT (1<<31) -#define GMBUS_SW_RDY (1<<30) -#define GMBUS_ENT (1<<29) /* enable timeout */ -#define GMBUS_CYCLE_NONE (0<<25) -#define GMBUS_CYCLE_WAIT (1<<25) -#define GMBUS_CYCLE_INDEX (2<<25) -#define GMBUS_CYCLE_STOP (4<<25) -#define GMBUS_BYTE_COUNT_SHIFT 16 -#define GMBUS_SLAVE_INDEX_SHIFT 8 -#define GMBUS_SLAVE_ADDR_SHIFT 1 -#define GMBUS_SLAVE_READ (1<<0) -#define GMBUS_SLAVE_WRITE (0<<0) -#define GMBUS2 0x5108 /* status */ -#define GMBUS_INUSE (1<<15) -#define GMBUS_HW_WAIT_PHASE (1<<14) -#define GMBUS_STALL_TIMEOUT (1<<13) -#define GMBUS_INT (1<<12) -#define GMBUS_HW_RDY (1<<11) -#define GMBUS_SATOER (1<<10) -#define GMBUS_ACTIVE (1<<9) -#define GMBUS3 0x510c /* data buffer bytes 3-0 */ -#define GMBUS4 0x5110 /* interrupt mask (Pineview+) */ -#define GMBUS_SLAVE_TIMEOUT_EN (1<<4) -#define GMBUS_NAK_EN (1<<3) -#define GMBUS_IDLE_EN (1<<2) -#define GMBUS_HW_WAIT_EN (1<<1) -#define GMBUS_HW_RDY_EN (1<<0) -#define GMBUS5 0x5120 /* byte index */ -#define GMBUS_2BYTE_INDEX_EN (1<<31) - -#define BLC_PWM_CTL 0x61254 -#define BLC_PWM_CTL2 0x61250 -#define BLC_PWM_CTL_C 0x62254 -#define BLC_PWM_CTL2_C 0x62250 -#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) -/* - * This is the most significant 15 bits of the number of backlight cycles in a - * complete cycle of the modulated backlight control. - * - * The actual value is this field multiplied by two. - */ -#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) -#define BLM_LEGACY_MODE (1 << 16) -/* - * This is the number of cycles out of the backlight modulation cycle for which - * the backlight is on. - * - * This field must be no greater than the number of cycles in the complete - * backlight modulation cycle. - */ -#define BACKLIGHT_DUTY_CYCLE_SHIFT (0) -#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) - -#define I915_GCFGC 0xf0 -#define I915_LOW_FREQUENCY_ENABLE (1 << 7) -#define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4) -#define I915_DISPLAY_CLOCK_333_MHZ (4 << 4) -#define I915_DISPLAY_CLOCK_MASK (7 << 4) - -#define I855_HPLLCC 0xc0 -#define I855_CLOCK_CONTROL_MASK (3 << 0) -#define I855_CLOCK_133_200 (0 << 0) -#define I855_CLOCK_100_200 (1 << 0) -#define I855_CLOCK_100_133 (2 << 0) -#define I855_CLOCK_166_250 (3 << 0) - -/* I830 CRTC registers */ -#define HTOTAL_A 0x60000 -#define HBLANK_A 0x60004 -#define HSYNC_A 0x60008 -#define VTOTAL_A 0x6000c -#define VBLANK_A 0x60010 -#define VSYNC_A 0x60014 -#define PIPEASRC 0x6001c -#define BCLRPAT_A 0x60020 -#define VSYNCSHIFT_A 0x60028 - -#define HTOTAL_B 0x61000 -#define HBLANK_B 0x61004 -#define HSYNC_B 0x61008 -#define VTOTAL_B 0x6100c -#define VBLANK_B 0x61010 -#define VSYNC_B 0x61014 -#define PIPEBSRC 0x6101c -#define BCLRPAT_B 0x61020 -#define VSYNCSHIFT_B 0x61028 - -#define HTOTAL_C 0x62000 -#define HBLANK_C 0x62004 -#define HSYNC_C 0x62008 -#define VTOTAL_C 0x6200c -#define VBLANK_C 0x62010 -#define VSYNC_C 0x62014 -#define PIPECSRC 0x6201c -#define BCLRPAT_C 0x62020 -#define VSYNCSHIFT_C 0x62028 - -#define PP_STATUS 0x61200 -# define PP_ON (1 << 31) -/* - * Indicates that all dependencies of the panel are on: - * - * - PLL enabled - * - pipe enabled - * - LVDS/DVOB/DVOC on - */ -#define PP_READY (1 << 30) -#define PP_SEQUENCE_NONE (0 << 28) -#define PP_SEQUENCE_ON (1 << 28) -#define PP_SEQUENCE_OFF (2 << 28) -#define PP_SEQUENCE_MASK 0x30000000 -#define PP_CONTROL 0x61204 -#define POWER_TARGET_ON (1 << 0) - -#define LVDSPP_ON 0x61208 -#define LVDSPP_OFF 0x6120c -#define PP_CYCLE 0x61210 - -#define PP_ON_DELAYS 0x61208 /* Cedartrail */ -#define PP_OFF_DELAYS 0x6120c /* Cedartrail */ - -#define PFIT_CONTROL 0x61230 -#define PFIT_ENABLE (1 << 31) -#define PFIT_PIPE_MASK (3 << 29) -#define PFIT_PIPE_SHIFT 29 -#define PFIT_SCALING_MODE_PILLARBOX (1 << 27) -#define PFIT_SCALING_MODE_LETTERBOX (3 << 26) -#define VERT_INTERP_DISABLE (0 << 10) -#define VERT_INTERP_BILINEAR (1 << 10) -#define VERT_INTERP_MASK (3 << 10) -#define VERT_AUTO_SCALE (1 << 9) -#define HORIZ_INTERP_DISABLE (0 << 6) -#define HORIZ_INTERP_BILINEAR (1 << 6) -#define HORIZ_INTERP_MASK (3 << 6) -#define HORIZ_AUTO_SCALE (1 << 5) -#define PANEL_8TO6_DITHER_ENABLE (1 << 3) - -#define PFIT_PGM_RATIOS 0x61234 -#define PFIT_VERT_SCALE_MASK 0xfff00000 -#define PFIT_HORIZ_SCALE_MASK 0x0000fff0 - -#define PFIT_AUTO_RATIOS 0x61238 - -#define DPLL_A 0x06014 -#define DPLL_B 0x06018 -#define DPLL_VCO_ENABLE (1 << 31) -#define DPLL_DVO_HIGH_SPEED (1 << 30) -#define DPLL_SYNCLOCK_ENABLE (1 << 29) -#define DPLL_VGA_MODE_DIS (1 << 28) -#define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */ -#define DPLLB_MODE_LVDS (2 << 26) /* i915 */ -#define DPLL_MODE_MASK (3 << 26) -#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */ -#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */ -#define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */ -#define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ -#define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ -#define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ -#define DPLL_LOCK (1 << 15) /* CDV */ - -/* - * The i830 generation, in DAC/serial mode, defines p1 as two plus this - * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set. - */ -# define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 -/* - * The i830 generation, in LVDS mode, defines P1 as the bit number set within - * this field (only one bit may be set). - */ -#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 -#define DPLL_FPA01_P1_POST_DIV_SHIFT 16 -#define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required - * in DVO non-gang */ -# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ -#define PLL_REF_INPUT_DREFCLK (0 << 13) -#define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */ -#define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO - * TVCLKIN */ -#define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) -#define PLL_REF_INPUT_MASK (3 << 13) -#define PLL_LOAD_PULSE_PHASE_SHIFT 9 -/* - * Parallel to Serial Load Pulse phase selection. - * Selects the phase for the 10X DPLL clock for the PCIe - * digital display port. The range is 4 to 13; 10 or more - * is just a flip delay. The default is 6 - */ -#define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT) -#define DISPLAY_RATE_SELECT_FPA1 (1 << 8) - -/* - * SDVO multiplier for 945G/GM. Not used on 965. - * - * DPLL_MD_UDI_MULTIPLIER_MASK - */ -#define SDVO_MULTIPLIER_MASK 0x000000ff -#define SDVO_MULTIPLIER_SHIFT_HIRES 4 -#define SDVO_MULTIPLIER_SHIFT_VGA 0 - -/* - * PLL_MD - */ -/* Pipe A SDVO/UDI clock multiplier/divider register for G965. */ -#define DPLL_A_MD 0x0601c -/* Pipe B SDVO/UDI clock multiplier/divider register for G965. */ -#define DPLL_B_MD 0x06020 -/* - * UDI pixel divider, controlling how many pixels are stuffed into a packet. - * - * Value is pixels minus 1. Must be set to 1 pixel for SDVO. - */ -#define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000 -#define DPLL_MD_UDI_DIVIDER_SHIFT 24 -/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */ -#define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000 -#define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16 -/* - * SDVO/UDI pixel multiplier. - * - * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus - * clock rate is 10 times the DPLL clock. At low resolution/refresh rate - * modes, the bus rate would be below the limits, so SDVO allows for stuffing - * dummy bytes in the datastream at an increased clock rate, with both sides of - * the link knowing how many bytes are fill. - * - * So, for a mode with a dotclock of 65Mhz, we would want to double the clock - * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be - * set to 130Mhz, and the SDVO multiplier set to 2x in this register and - * through an SDVO command. - * - * This register field has values of multiplication factor minus 1, with - * a maximum multiplier of 5 for SDVO. - */ -#define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00 -#define DPLL_MD_UDI_MULTIPLIER_SHIFT 8 -/* - * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. - * This best be set to the default value (3) or the CRT won't work. No, - * I don't entirely understand what this does... - */ -#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f -#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 - -#define DPLL_TEST 0x606c -#define DPLLB_TEST_SDVO_DIV_1 (0 << 22) -#define DPLLB_TEST_SDVO_DIV_2 (1 << 22) -#define DPLLB_TEST_SDVO_DIV_4 (2 << 22) -#define DPLLB_TEST_SDVO_DIV_MASK (3 << 22) -#define DPLLB_TEST_N_BYPASS (1 << 19) -#define DPLLB_TEST_M_BYPASS (1 << 18) -#define DPLLB_INPUT_BUFFER_ENABLE (1 << 16) -#define DPLLA_TEST_N_BYPASS (1 << 3) -#define DPLLA_TEST_M_BYPASS (1 << 2) -#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) - -#define ADPA 0x61100 -#define ADPA_DAC_ENABLE (1 << 31) -#define ADPA_DAC_DISABLE 0 -#define ADPA_PIPE_SELECT_MASK (1 << 30) -#define ADPA_PIPE_A_SELECT 0 -#define ADPA_PIPE_B_SELECT (1 << 30) -#define ADPA_USE_VGA_HVPOLARITY (1 << 15) -#define ADPA_SETS_HVPOLARITY 0 -#define ADPA_VSYNC_CNTL_DISABLE (1 << 11) -#define ADPA_VSYNC_CNTL_ENABLE 0 -#define ADPA_HSYNC_CNTL_DISABLE (1 << 10) -#define ADPA_HSYNC_CNTL_ENABLE 0 -#define ADPA_VSYNC_ACTIVE_HIGH (1 << 4) -#define ADPA_VSYNC_ACTIVE_LOW 0 -#define ADPA_HSYNC_ACTIVE_HIGH (1 << 3) -#define ADPA_HSYNC_ACTIVE_LOW 0 - -#define FPA0 0x06040 -#define FPA1 0x06044 -#define FPB0 0x06048 -#define FPB1 0x0604c -#define FP_N_DIV_MASK 0x003f0000 -#define FP_N_DIV_SHIFT 16 -#define FP_M1_DIV_MASK 0x00003f00 -#define FP_M1_DIV_SHIFT 8 -#define FP_M2_DIV_MASK 0x0000003f -#define FP_M2_DIV_SHIFT 0 - -#define PORT_HOTPLUG_EN 0x61110 -#define SDVOB_HOTPLUG_INT_EN (1 << 26) -#define SDVOC_HOTPLUG_INT_EN (1 << 25) -#define TV_HOTPLUG_INT_EN (1 << 18) -#define CRT_HOTPLUG_INT_EN (1 << 9) -#define CRT_HOTPLUG_FORCE_DETECT (1 << 3) -/* CDV.. */ -#define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8) -#define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7) -#define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7) -#define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5) -#define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5) -#define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5) -#define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5) -#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5) -#define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4) -#define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4) -#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) -#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) -#define CRT_HOTPLUG_DETECT_MASK 0x000000F8 - -#define PORT_HOTPLUG_STAT 0x61114 -#define CRT_HOTPLUG_INT_STATUS (1 << 11) -#define TV_HOTPLUG_INT_STATUS (1 << 10) -#define CRT_HOTPLUG_MONITOR_MASK (3 << 8) -#define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) -#define CRT_HOTPLUG_MONITOR_MONO (2 << 8) -#define CRT_HOTPLUG_MONITOR_NONE (0 << 8) -#define SDVOC_HOTPLUG_INT_STATUS (1 << 7) -#define SDVOB_HOTPLUG_INT_STATUS (1 << 6) - -#define SDVOB 0x61140 -#define SDVOC 0x61160 -#define SDVO_ENABLE (1 << 31) -#define SDVO_PIPE_B_SELECT (1 << 30) -#define SDVO_STALL_SELECT (1 << 29) -#define SDVO_INTERRUPT_ENABLE (1 << 26) -#define SDVO_COLOR_RANGE_16_235 (1 << 8) -#define SDVO_AUDIO_ENABLE (1 << 6) - -/** - * 915G/GM SDVO pixel multiplier. - * - * Programmed value is multiplier - 1, up to 5x. - * - * DPLL_MD_UDI_MULTIPLIER_MASK - */ -#define SDVO_PORT_MULTIPLY_MASK (7 << 23) -#define SDVO_PORT_MULTIPLY_SHIFT 23 -#define SDVO_PHASE_SELECT_MASK (15 << 19) -#define SDVO_PHASE_SELECT_DEFAULT (6 << 19) -#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) -#define SDVOC_GANG_MODE (1 << 16) -#define SDVO_BORDER_ENABLE (1 << 7) -#define SDVOB_PCIE_CONCURRENCY (1 << 3) -#define SDVO_DETECTED (1 << 2) -/* Bits to be preserved when writing */ -#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14)) -#define SDVOC_PRESERVE_MASK (1 << 17) - -/* - * This register controls the LVDS output enable, pipe selection, and data - * format selection. - * - * All of the clock/data pairs are force powered down by power sequencing. - */ -#define LVDS 0x61180 -/* - * Enables the LVDS port. This bit must be set before DPLLs are enabled, as - * the DPLL semantics change when the LVDS is assigned to that pipe. - */ -#define LVDS_PORT_EN (1 << 31) -/* Selects pipe B for LVDS data. Must be set on pre-965. */ -#define LVDS_PIPEB_SELECT (1 << 30) - -/* Turns on border drawing to allow centered display. */ -#define LVDS_BORDER_EN (1 << 15) - -/* - * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per - * pixel. - */ -#define LVDS_A0A2_CLKA_POWER_MASK (3 << 8) -#define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8) -#define LVDS_A0A2_CLKA_POWER_UP (3 << 8) -/* - * Controls the A3 data pair, which contains the additional LSBs for 24 bit - * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be - * on. - */ -#define LVDS_A3_POWER_MASK (3 << 6) -#define LVDS_A3_POWER_DOWN (0 << 6) -#define LVDS_A3_POWER_UP (3 << 6) -/* - * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP - * is set. - */ -#define LVDS_CLKB_POWER_MASK (3 << 4) -#define LVDS_CLKB_POWER_DOWN (0 << 4) -#define LVDS_CLKB_POWER_UP (3 << 4) -/* - * Controls the B0-B3 data pairs. This must be set to match the DPLL p2 - * setting for whether we are in dual-channel mode. The B3 pair will - * additionally only be powered up when LVDS_A3_POWER_UP is set. - */ -#define LVDS_B0B3_POWER_MASK (3 << 2) -#define LVDS_B0B3_POWER_DOWN (0 << 2) -#define LVDS_B0B3_POWER_UP (3 << 2) - -#define PIPEACONF 0x70008 -#define PIPEACONF_ENABLE (1 << 31) -#define PIPEACONF_DISABLE 0 -#define PIPEACONF_DOUBLE_WIDE (1 << 30) -#define PIPECONF_ACTIVE (1 << 30) -#define I965_PIPECONF_ACTIVE (1 << 30) -#define PIPECONF_DSIPLL_LOCK (1 << 29) -#define PIPEACONF_SINGLE_WIDE 0 -#define PIPEACONF_PIPE_UNLOCKED 0 -#define PIPEACONF_DSR (1 << 26) -#define PIPEACONF_PIPE_LOCKED (1 << 25) -#define PIPEACONF_PALETTE 0 -#define PIPECONF_FORCE_BORDER (1 << 25) -#define PIPEACONF_GAMMA (1 << 24) -#define PIPECONF_PROGRESSIVE (0 << 21) -#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) -#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) -#define PIPECONF_PLANE_OFF (1 << 19) -#define PIPECONF_CURSOR_OFF (1 << 18) - -#define PIPEBCONF 0x71008 -#define PIPEBCONF_ENABLE (1 << 31) -#define PIPEBCONF_DISABLE 0 -#define PIPEBCONF_DOUBLE_WIDE (1 << 30) -#define PIPEBCONF_DISABLE 0 -#define PIPEBCONF_GAMMA (1 << 24) -#define PIPEBCONF_PALETTE 0 - -#define PIPECCONF 0x72008 - -#define PIPEBGCMAXRED 0x71010 -#define PIPEBGCMAXGREEN 0x71014 -#define PIPEBGCMAXBLUE 0x71018 - -#define PIPEASTAT 0x70024 -#define PIPEBSTAT 0x71024 -#define PIPECSTAT 0x72024 -#define PIPE_VBLANK_INTERRUPT_STATUS (1UL << 1) -#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL << 2) -#define PIPE_VBLANK_CLEAR (1 << 1) -#define PIPE_VBLANK_STATUS (1 << 1) -#define PIPE_TE_STATUS (1UL << 6) -#define PIPE_DPST_EVENT_STATUS (1UL << 7) -#define PIPE_VSYNC_CLEAR (1UL << 9) -#define PIPE_VSYNC_STATUS (1UL << 9) -#define PIPE_HDMI_AUDIO_UNDERRUN_STATUS (1UL << 10) -#define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS (1UL << 11) -#define PIPE_VBLANK_INTERRUPT_ENABLE (1UL << 17) -#define PIPE_START_VBLANK_INTERRUPT_ENABLE (1UL << 18) -#define PIPE_TE_ENABLE (1UL << 22) -#define PIPE_DPST_EVENT_ENABLE (1UL << 23) -#define PIPE_VSYNC_ENABL (1UL << 25) -#define PIPE_HDMI_AUDIO_UNDERRUN (1UL << 26) -#define PIPE_HDMI_AUDIO_BUFFER_DONE (1UL << 27) -#define PIPE_HDMI_AUDIO_INT_MASK (PIPE_HDMI_AUDIO_UNDERRUN | \ - PIPE_HDMI_AUDIO_BUFFER_DONE) -#define PIPE_EVENT_MASK ((1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)|(1 << 24)|(1 << 23)|(1 << 22)|(1 << 21)|(1 << 20)|(1 << 16)) -#define PIPE_VBLANK_MASK ((1 << 25)|(1 << 24)|(1 << 18)|(1 << 17)) -#define HISTOGRAM_INT_CONTROL 0x61268 -#define HISTOGRAM_BIN_DATA 0X61264 -#define HISTOGRAM_LOGIC_CONTROL 0x61260 -#define PWM_CONTROL_LOGIC 0x61250 -#define PIPE_HOTPLUG_INTERRUPT_STATUS (1UL << 10) -#define HISTOGRAM_INTERRUPT_ENABLE (1UL << 31) -#define HISTOGRAM_LOGIC_ENABLE (1UL << 31) -#define PWM_LOGIC_ENABLE (1UL << 31) -#define PWM_PHASEIN_ENABLE (1UL << 25) -#define PWM_PHASEIN_INT_ENABLE (1UL << 24) -#define PWM_PHASEIN_VB_COUNT 0x00001f00 -#define PWM_PHASEIN_INC 0x0000001f -#define HISTOGRAM_INT_CTRL_CLEAR (1UL << 30) -#define DPST_YUV_LUMA_MODE 0 - -struct dpst_ie_histogram_control { - union { - uint32_t data; - struct { - uint32_t bin_reg_index:7; - uint32_t reserved:4; - uint32_t bin_reg_func_select:1; - uint32_t sync_to_phase_in:1; - uint32_t alt_enhancement_mode:2; - uint32_t reserved1:1; - uint32_t sync_to_phase_in_count:8; - uint32_t histogram_mode_select:1; - uint32_t reserved2:4; - uint32_t ie_pipe_assignment:1; - uint32_t ie_mode_table_enabled:1; - uint32_t ie_histogram_enable:1; - }; - }; -}; - -struct dpst_guardband { - union { - uint32_t data; - struct { - uint32_t guardband:22; - uint32_t guardband_interrupt_delay:8; - uint32_t interrupt_status:1; - uint32_t interrupt_enable:1; - }; - }; -}; - -#define PIPEAFRAMEHIGH 0x70040 -#define PIPEAFRAMEPIXEL 0x70044 -#define PIPEBFRAMEHIGH 0x71040 -#define PIPEBFRAMEPIXEL 0x71044 -#define PIPECFRAMEHIGH 0x72040 -#define PIPECFRAMEPIXEL 0x72044 -#define PIPE_FRAME_HIGH_MASK 0x0000ffff -#define PIPE_FRAME_HIGH_SHIFT 0 -#define PIPE_FRAME_LOW_MASK 0xff000000 -#define PIPE_FRAME_LOW_SHIFT 24 -#define PIPE_PIXEL_MASK 0x00ffffff -#define PIPE_PIXEL_SHIFT 0 - -#define DSPARB 0x70030 -#define DSPFW1 0x70034 -#define DSPFW2 0x70038 -#define DSPFW3 0x7003c -#define DSPFW4 0x70050 -#define DSPFW5 0x70054 -#define DSPFW6 0x70058 -#define DSPCHICKENBIT 0x70400 -#define DSPACNTR 0x70180 -#define DSPBCNTR 0x71180 -#define DSPCCNTR 0x72180 -#define DISPLAY_PLANE_ENABLE (1 << 31) -#define DISPLAY_PLANE_DISABLE 0 -#define DISPPLANE_GAMMA_ENABLE (1 << 30) -#define DISPPLANE_GAMMA_DISABLE 0 -#define DISPPLANE_PIXFORMAT_MASK (0xf << 26) -#define DISPPLANE_8BPP (0x2 << 26) -#define DISPPLANE_15_16BPP (0x4 << 26) -#define DISPPLANE_16BPP (0x5 << 26) -#define DISPPLANE_32BPP_NO_ALPHA (0x6 << 26) -#define DISPPLANE_32BPP (0x7 << 26) -#define DISPPLANE_STEREO_ENABLE (1 << 25) -#define DISPPLANE_STEREO_DISABLE 0 -#define DISPPLANE_SEL_PIPE_MASK (1 << 24) -#define DISPPLANE_SEL_PIPE_POS 24 -#define DISPPLANE_SEL_PIPE_A 0 -#define DISPPLANE_SEL_PIPE_B (1 << 24) -#define DISPPLANE_SRC_KEY_ENABLE (1 << 22) -#define DISPPLANE_SRC_KEY_DISABLE 0 -#define DISPPLANE_LINE_DOUBLE (1 << 20) -#define DISPPLANE_NO_LINE_DOUBLE 0 -#define DISPPLANE_STEREO_POLARITY_FIRST 0 -#define DISPPLANE_STEREO_POLARITY_SECOND (1 << 18) -/* plane B only */ -#define DISPPLANE_ALPHA_TRANS_ENABLE (1 << 15) -#define DISPPLANE_ALPHA_TRANS_DISABLE 0 -#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0 -#define DISPPLANE_SPRITE_ABOVE_OVERLAY (1) -#define DISPPLANE_BOTTOM (4) - -#define DSPABASE 0x70184 -#define DSPALINOFF 0x70184 -#define DSPASTRIDE 0x70188 - -#define DSPBBASE 0x71184 -#define DSPBLINOFF 0X71184 -#define DSPBADDR DSPBBASE -#define DSPBSTRIDE 0x71188 - -#define DSPCBASE 0x72184 -#define DSPCLINOFF 0x72184 -#define DSPCSTRIDE 0x72188 - -#define DSPAKEYVAL 0x70194 -#define DSPAKEYMASK 0x70198 - -#define DSPAPOS 0x7018C /* reserved */ -#define DSPASIZE 0x70190 -#define DSPBPOS 0x7118C -#define DSPBSIZE 0x71190 -#define DSPCPOS 0x7218C -#define DSPCSIZE 0x72190 - -#define DSPASURF 0x7019C -#define DSPATILEOFF 0x701A4 - -#define DSPBSURF 0x7119C -#define DSPBTILEOFF 0x711A4 - -#define DSPCSURF 0x7219C -#define DSPCTILEOFF 0x721A4 -#define DSPCKEYMAXVAL 0x721A0 -#define DSPCKEYMINVAL 0x72194 -#define DSPCKEYMSK 0x72198 - -#define VGACNTRL 0x71400 -#define VGA_DISP_DISABLE (1 << 31) -#define VGA_2X_MODE (1 << 30) -#define VGA_PIPE_B_SELECT (1 << 29) - -/* - * Overlay registers - */ -#define OV_C_OFFSET 0x08000 -#define OV_OVADD 0x30000 -#define OV_DOVASTA 0x30008 -# define OV_PIPE_SELECT ((1 << 6)|(1 << 7)) -# define OV_PIPE_SELECT_POS 6 -# define OV_PIPE_A 0 -# define OV_PIPE_C 1 -#define OV_OGAMC5 0x30010 -#define OV_OGAMC4 0x30014 -#define OV_OGAMC3 0x30018 -#define OV_OGAMC2 0x3001C -#define OV_OGAMC1 0x30020 -#define OV_OGAMC0 0x30024 -#define OVC_OVADD 0x38000 -#define OVC_DOVCSTA 0x38008 -#define OVC_OGAMC5 0x38010 -#define OVC_OGAMC4 0x38014 -#define OVC_OGAMC3 0x38018 -#define OVC_OGAMC2 0x3801C -#define OVC_OGAMC1 0x38020 -#define OVC_OGAMC0 0x38024 - -/* - * Some BIOS scratch area registers. The 845 (and 830?) store the amount - * of video memory available to the BIOS in SWF1. - */ -#define SWF0 0x71410 -#define SWF1 0x71414 -#define SWF2 0x71418 -#define SWF3 0x7141c -#define SWF4 0x71420 -#define SWF5 0x71424 -#define SWF6 0x71428 - -/* - * 855 scratch registers. - */ -#define SWF00 0x70410 -#define SWF01 0x70414 -#define SWF02 0x70418 -#define SWF03 0x7041c -#define SWF04 0x70420 -#define SWF05 0x70424 -#define SWF06 0x70428 - -#define SWF10 SWF0 -#define SWF11 SWF1 -#define SWF12 SWF2 -#define SWF13 SWF3 -#define SWF14 SWF4 -#define SWF15 SWF5 -#define SWF16 SWF6 - -#define SWF30 0x72414 -#define SWF31 0x72418 -#define SWF32 0x7241c - - -/* - * Palette registers - */ -#define PALETTE_A 0x0a000 -#define PALETTE_B 0x0a800 -#define PALETTE_C 0x0ac00 - -/* Cursor A & B regs */ -#define CURACNTR 0x70080 -#define CURSOR_MODE_DISABLE 0x00 -#define CURSOR_MODE_64_32B_AX 0x07 -#define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX) -#define MCURSOR_GAMMA_ENABLE (1 << 26) -#define CURABASE 0x70084 -#define CURAPOS 0x70088 -#define CURSOR_POS_MASK 0x007FF -#define CURSOR_POS_SIGN 0x8000 -#define CURSOR_X_SHIFT 0 -#define CURSOR_Y_SHIFT 16 -#define CURBCNTR 0x700c0 -#define CURBBASE 0x700c4 -#define CURBPOS 0x700c8 -#define CURCCNTR 0x700e0 -#define CURCBASE 0x700e4 -#define CURCPOS 0x700e8 - -/* - * Interrupt Registers - */ -#define IER 0x020a0 -#define IIR 0x020a4 -#define IMR 0x020a8 -#define ISR 0x020ac - -/* - * MOORESTOWN delta registers - */ -#define MRST_DPLL_A 0x0f014 -#define MDFLD_DPLL_B 0x0f018 -#define MDFLD_INPUT_REF_SEL (1 << 14) -#define MDFLD_VCO_SEL (1 << 16) -#define DPLLA_MODE_LVDS (2 << 26) /* mrst */ -#define MDFLD_PLL_LATCHEN (1 << 28) -#define MDFLD_PWR_GATE_EN (1 << 30) -#define MDFLD_P1_MASK (0x1FF << 17) -#define MRST_FPA0 0x0f040 -#define MRST_FPA1 0x0f044 -#define MDFLD_DPLL_DIV0 0x0f048 -#define MDFLD_DPLL_DIV1 0x0f04c -#define MRST_PERF_MODE 0x020f4 - -/* - * MEDFIELD HDMI registers - */ -#define HDMIPHYMISCCTL 0x61134 -#define HDMI_PHY_POWER_DOWN 0x7f -#define HDMIB_CONTROL 0x61140 -#define HDMIB_PORT_EN (1 << 31) -#define HDMIB_PIPE_B_SELECT (1 << 30) -#define HDMIB_NULL_PACKET (1 << 9) -#define HDMIB_HDCP_PORT (1 << 5) - -/* #define LVDS 0x61180 */ -#define MRST_PANEL_8TO6_DITHER_ENABLE (1 << 25) -#define MRST_PANEL_24_DOT_1_FORMAT (1 << 24) -#define LVDS_A3_POWER_UP_0_OUTPUT (1 << 6) - -#define MIPI 0x61190 -#define MIPI_C 0x62190 -#define MIPI_PORT_EN (1 << 31) -/* Turns on border drawing to allow centered display. */ -#define SEL_FLOPPED_HSTX (1 << 23) -#define PASS_FROM_SPHY_TO_AFE (1 << 16) -#define MIPI_BORDER_EN (1 << 15) -#define MIPIA_3LANE_MIPIC_1LANE 0x1 -#define MIPIA_2LANE_MIPIC_2LANE 0x2 -#define TE_TRIGGER_DSI_PROTOCOL (1 << 2) -#define TE_TRIGGER_GPIO_PIN (1 << 3) -#define MIPI_TE_COUNT 0x61194 - -/* #define PP_CONTROL 0x61204 */ -#define POWER_DOWN_ON_RESET (1 << 1) - -/* #define PFIT_CONTROL 0x61230 */ -#define PFIT_PIPE_SELECT (3 << 29) -#define PFIT_PIPE_SELECT_SHIFT (29) - -/* #define BLC_PWM_CTL 0x61254 */ -#define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT (16) -#define MRST_BACKLIGHT_MODULATION_FREQ_MASK (0xffff << 16) - -/* #define PIPEACONF 0x70008 */ -#define PIPEACONF_PIPE_STATE (1 << 30) -/* #define DSPACNTR 0x70180 */ - -#define MRST_DSPABASE 0x7019c -#define MRST_DSPBBASE 0x7119c -#define MDFLD_DSPCBASE 0x7219c - -/* - * Moorestown registers. - */ - -/* - * MIPI IP registers - */ -#define MIPIC_REG_OFFSET 0x800 - -#define DEVICE_READY_REG 0xb000 -#define LP_OUTPUT_HOLD (1 << 16) -#define EXIT_ULPS_DEV_READY 0x3 -#define LP_OUTPUT_HOLD_RELEASE 0x810000 -# define ENTERING_ULPS (2 << 1) -# define EXITING_ULPS (1 << 1) -# define ULPS_MASK (3 << 1) -# define BUS_POSSESSION (1 << 3) -#define INTR_STAT_REG 0xb004 -#define RX_SOT_ERROR (1 << 0) -#define RX_SOT_SYNC_ERROR (1 << 1) -#define RX_ESCAPE_MODE_ENTRY_ERROR (1 << 3) -#define RX_LP_TX_SYNC_ERROR (1 << 4) -#define RX_HS_RECEIVE_TIMEOUT_ERROR (1 << 5) -#define RX_FALSE_CONTROL_ERROR (1 << 6) -#define RX_ECC_SINGLE_BIT_ERROR (1 << 7) -#define RX_ECC_MULTI_BIT_ERROR (1 << 8) -#define RX_CHECKSUM_ERROR (1 << 9) -#define RX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 10) -#define RX_DSI_VC_ID_INVALID (1 << 11) -#define TX_FALSE_CONTROL_ERROR (1 << 12) -#define TX_ECC_SINGLE_BIT_ERROR (1 << 13) -#define TX_ECC_MULTI_BIT_ERROR (1 << 14) -#define TX_CHECKSUM_ERROR (1 << 15) -#define TX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 16) -#define TX_DSI_VC_ID_INVALID (1 << 17) -#define HIGH_CONTENTION (1 << 18) -#define LOW_CONTENTION (1 << 19) -#define DPI_FIFO_UNDER_RUN (1 << 20) -#define HS_TX_TIMEOUT (1 << 21) -#define LP_RX_TIMEOUT (1 << 22) -#define TURN_AROUND_ACK_TIMEOUT (1 << 23) -#define ACK_WITH_NO_ERROR (1 << 24) -#define HS_GENERIC_WR_FIFO_FULL (1 << 27) -#define LP_GENERIC_WR_FIFO_FULL (1 << 28) -#define SPL_PKT_SENT (1 << 30) -#define INTR_EN_REG 0xb008 -#define DSI_FUNC_PRG_REG 0xb00c -#define DPI_CHANNEL_NUMBER_POS 0x03 -#define DBI_CHANNEL_NUMBER_POS 0x05 -#define FMT_DPI_POS 0x07 -#define FMT_DBI_POS 0x0A -#define DBI_DATA_WIDTH_POS 0x0D - -/* DPI PIXEL FORMATS */ -#define RGB_565_FMT 0x01 /* RGB 565 FORMAT */ -#define RGB_666_FMT 0x02 /* RGB 666 FORMAT */ -#define LRGB_666_FMT 0x03 /* RGB LOOSELY PACKED - * 666 FORMAT - */ -#define RGB_888_FMT 0x04 /* RGB 888 FORMAT */ -#define VIRTUAL_CHANNEL_NUMBER_0 0x00 /* Virtual channel 0 */ -#define VIRTUAL_CHANNEL_NUMBER_1 0x01 /* Virtual channel 1 */ -#define VIRTUAL_CHANNEL_NUMBER_2 0x02 /* Virtual channel 2 */ -#define VIRTUAL_CHANNEL_NUMBER_3 0x03 /* Virtual channel 3 */ - -#define DBI_NOT_SUPPORTED 0x00 /* command mode - * is not supported - */ -#define DBI_DATA_WIDTH_16BIT 0x01 /* 16 bit data */ -#define DBI_DATA_WIDTH_9BIT 0x02 /* 9 bit data */ -#define DBI_DATA_WIDTH_8BIT 0x03 /* 8 bit data */ -#define DBI_DATA_WIDTH_OPT1 0x04 /* option 1 */ -#define DBI_DATA_WIDTH_OPT2 0x05 /* option 2 */ - -#define HS_TX_TIMEOUT_REG 0xb010 -#define LP_RX_TIMEOUT_REG 0xb014 -#define TURN_AROUND_TIMEOUT_REG 0xb018 -#define DEVICE_RESET_REG 0xb01C -#define DPI_RESOLUTION_REG 0xb020 -#define RES_V_POS 0x10 -#define DBI_RESOLUTION_REG 0xb024 /* Reserved for MDFLD */ -#define HORIZ_SYNC_PAD_COUNT_REG 0xb028 -#define HORIZ_BACK_PORCH_COUNT_REG 0xb02C -#define HORIZ_FRONT_PORCH_COUNT_REG 0xb030 -#define HORIZ_ACTIVE_AREA_COUNT_REG 0xb034 -#define VERT_SYNC_PAD_COUNT_REG 0xb038 -#define VERT_BACK_PORCH_COUNT_REG 0xb03c -#define VERT_FRONT_PORCH_COUNT_REG 0xb040 -#define HIGH_LOW_SWITCH_COUNT_REG 0xb044 -#define DPI_CONTROL_REG 0xb048 -#define DPI_SHUT_DOWN (1 << 0) -#define DPI_TURN_ON (1 << 1) -#define DPI_COLOR_MODE_ON (1 << 2) -#define DPI_COLOR_MODE_OFF (1 << 3) -#define DPI_BACK_LIGHT_ON (1 << 4) -#define DPI_BACK_LIGHT_OFF (1 << 5) -#define DPI_LP (1 << 6) -#define DPI_DATA_REG 0xb04c -#define DPI_BACK_LIGHT_ON_DATA 0x07 -#define DPI_BACK_LIGHT_OFF_DATA 0x17 -#define INIT_COUNT_REG 0xb050 -#define MAX_RET_PAK_REG 0xb054 -#define VIDEO_FMT_REG 0xb058 -#define COMPLETE_LAST_PCKT (1 << 2) -#define EOT_DISABLE_REG 0xb05c -#define ENABLE_CLOCK_STOPPING (1 << 1) -#define LP_BYTECLK_REG 0xb060 -#define LP_GEN_DATA_REG 0xb064 -#define HS_GEN_DATA_REG 0xb068 -#define LP_GEN_CTRL_REG 0xb06C -#define HS_GEN_CTRL_REG 0xb070 -#define DCS_CHANNEL_NUMBER_POS 0x6 -#define MCS_COMMANDS_POS 0x8 -#define WORD_COUNTS_POS 0x8 -#define MCS_PARAMETER_POS 0x10 -#define GEN_FIFO_STAT_REG 0xb074 -#define HS_DATA_FIFO_FULL (1 << 0) -#define HS_DATA_FIFO_HALF_EMPTY (1 << 1) -#define HS_DATA_FIFO_EMPTY (1 << 2) -#define LP_DATA_FIFO_FULL (1 << 8) -#define LP_DATA_FIFO_HALF_EMPTY (1 << 9) -#define LP_DATA_FIFO_EMPTY (1 << 10) -#define HS_CTRL_FIFO_FULL (1 << 16) -#define HS_CTRL_FIFO_HALF_EMPTY (1 << 17) -#define HS_CTRL_FIFO_EMPTY (1 << 18) -#define LP_CTRL_FIFO_FULL (1 << 24) -#define LP_CTRL_FIFO_HALF_EMPTY (1 << 25) -#define LP_CTRL_FIFO_EMPTY (1 << 26) -#define DBI_FIFO_EMPTY (1 << 27) -#define DPI_FIFO_EMPTY (1 << 28) -#define HS_LS_DBI_ENABLE_REG 0xb078 -#define TXCLKESC_REG 0xb07c -#define DPHY_PARAM_REG 0xb080 -#define DBI_BW_CTRL_REG 0xb084 -#define CLK_LANE_SWT_REG 0xb088 - -/* - * MIPI Adapter registers - */ -#define MIPI_CONTROL_REG 0xb104 -#define MIPI_2X_CLOCK_BITS ((1 << 0) | (1 << 1)) -#define MIPI_DATA_ADDRESS_REG 0xb108 -#define MIPI_DATA_LENGTH_REG 0xb10C -#define MIPI_COMMAND_ADDRESS_REG 0xb110 -#define MIPI_COMMAND_LENGTH_REG 0xb114 -#define MIPI_READ_DATA_RETURN_REG0 0xb118 -#define MIPI_READ_DATA_RETURN_REG1 0xb11C -#define MIPI_READ_DATA_RETURN_REG2 0xb120 -#define MIPI_READ_DATA_RETURN_REG3 0xb124 -#define MIPI_READ_DATA_RETURN_REG4 0xb128 -#define MIPI_READ_DATA_RETURN_REG5 0xb12C -#define MIPI_READ_DATA_RETURN_REG6 0xb130 -#define MIPI_READ_DATA_RETURN_REG7 0xb134 -#define MIPI_READ_DATA_VALID_REG 0xb138 - -/* DBI COMMANDS */ -#define soft_reset 0x01 -/* - * The display module performs a software reset. - * Registers are written with their SW Reset default values. - */ -#define get_power_mode 0x0a -/* - * The display module returns the current power mode - */ -#define get_address_mode 0x0b -/* - * The display module returns the current status. - */ -#define get_pixel_format 0x0c -/* - * This command gets the pixel format for the RGB image data - * used by the interface. - */ -#define get_display_mode 0x0d -/* - * The display module returns the Display Image Mode status. - */ -#define get_signal_mode 0x0e -/* - * The display module returns the Display Signal Mode. - */ -#define get_diagnostic_result 0x0f -/* - * The display module returns the self-diagnostic results following - * a Sleep Out command. - */ -#define enter_sleep_mode 0x10 -/* - * This command causes the display module to enter the Sleep mode. - * In this mode, all unnecessary blocks inside the display module are - * disabled except interface communication. This is the lowest power - * mode the display module supports. - */ -#define exit_sleep_mode 0x11 -/* - * This command causes the display module to exit Sleep mode. - * All blocks inside the display module are enabled. - */ -#define enter_partial_mode 0x12 -/* - * This command causes the display module to enter the Partial Display - * Mode. The Partial Display Mode window is described by the - * set_partial_area command. - */ -#define enter_normal_mode 0x13 -/* - * This command causes the display module to enter the Normal mode. - * Normal Mode is defined as Partial Display mode and Scroll mode are off - */ -#define exit_invert_mode 0x20 -/* - * This command causes the display module to stop inverting the image - * data on the display device. The frame memory contents remain unchanged. - * No status bits are changed. - */ -#define enter_invert_mode 0x21 -/* - * This command causes the display module to invert the image data only on - * the display device. The frame memory contents remain unchanged. - * No status bits are changed. - */ -#define set_gamma_curve 0x26 -/* - * This command selects the desired gamma curve for the display device. - * Four fixed gamma curves are defined in section DCS spec. - */ -#define set_display_off 0x28 -/* ************************************************************************* *\ -This command causes the display module to stop displaying the image data -on the display device. The frame memory contents remain unchanged. -No status bits are changed. -\* ************************************************************************* */ -#define set_display_on 0x29 -/* ************************************************************************* *\ -This command causes the display module to start displaying the image data -on the display device. The frame memory contents remain unchanged. -No status bits are changed. -\* ************************************************************************* */ -#define set_column_address 0x2a -/* - * This command defines the column extent of the frame memory accessed by - * the hostprocessor with the read_memory_continue and - * write_memory_continue commands. - * No status bits are changed. - */ -#define set_page_addr 0x2b -/* - * This command defines the page extent of the frame memory accessed by - * the host processor with the write_memory_continue and - * read_memory_continue command. - * No status bits are changed. - */ -#define write_mem_start 0x2c -/* - * This command transfers image data from the host processor to the - * display modules frame memory starting at the pixel location specified - * by preceding set_column_address and set_page_address commands. - */ -#define set_partial_area 0x30 -/* - * This command defines the Partial Display mode s display area. - * There are two parameters associated with this command, the first - * defines the Start Row (SR) and the second the End Row (ER). SR and ER - * refer to the Frame Memory Line Pointer. - */ -#define set_scroll_area 0x33 -/* - * This command defines the display modules Vertical Scrolling Area. - */ -#define set_tear_off 0x34 -/* - * This command turns off the display modules Tearing Effect output - * signal on the TE signal line. - */ -#define set_tear_on 0x35 -/* - * This command turns on the display modules Tearing Effect output signal - * on the TE signal line. - */ -#define set_address_mode 0x36 -/* - * This command sets the data order for transfers from the host processor - * to display modules frame memory,bits B[7:5] and B3, and from the - * display modules frame memory to the display device, bits B[2:0] and B4. - */ -#define set_scroll_start 0x37 -/* - * This command sets the start of the vertical scrolling area in the frame - * memory. The vertical scrolling area is fully defined when this command - * is used with the set_scroll_area command The set_scroll_start command - * has one parameter, the Vertical Scroll Pointer. The VSP defines the - * line in the frame memory that is written to the display device as the - * first line of the vertical scroll area. - */ -#define exit_idle_mode 0x38 -/* - * This command causes the display module to exit Idle mode. - */ -#define enter_idle_mode 0x39 -/* - * This command causes the display module to enter Idle Mode. - * In Idle Mode, color expression is reduced. Colors are shown on the - * display device using the MSB of each of the R, G and B color - * components in the frame memory - */ -#define set_pixel_format 0x3a -/* - * This command sets the pixel format for the RGB image data used by the - * interface. - * Bits D[6:4] DPI Pixel Format Definition - * Bits D[2:0] DBI Pixel Format Definition - * Bits D7 and D3 are not used. - */ -#define DCS_PIXEL_FORMAT_3bpp 0x1 -#define DCS_PIXEL_FORMAT_8bpp 0x2 -#define DCS_PIXEL_FORMAT_12bpp 0x3 -#define DCS_PIXEL_FORMAT_16bpp 0x5 -#define DCS_PIXEL_FORMAT_18bpp 0x6 -#define DCS_PIXEL_FORMAT_24bpp 0x7 - -#define write_mem_cont 0x3c - -/* - * This command transfers image data from the host processor to the - * display module's frame memory continuing from the pixel location - * following the previous write_memory_continue or write_memory_start - * command. - */ -#define set_tear_scanline 0x44 -/* - * This command turns on the display modules Tearing Effect output signal - * on the TE signal line when the display module reaches line N. - */ -#define get_scanline 0x45 -/* - * The display module returns the current scanline, N, used to update the - * display device. The total number of scanlines on a display device is - * defined as VSYNC + VBP + VACT + VFP.The first scanline is defined as - * the first line of V Sync and is denoted as Line 0. - * When in Sleep Mode, the value returned by get_scanline is undefined. - */ - -/* MCS or Generic COMMANDS */ -/* MCS/generic data type */ -#define GEN_SHORT_WRITE_0 0x03 /* generic short write, no parameters */ -#define GEN_SHORT_WRITE_1 0x13 /* generic short write, 1 parameters */ -#define GEN_SHORT_WRITE_2 0x23 /* generic short write, 2 parameters */ -#define GEN_READ_0 0x04 /* generic read, no parameters */ -#define GEN_READ_1 0x14 /* generic read, 1 parameters */ -#define GEN_READ_2 0x24 /* generic read, 2 parameters */ -#define GEN_LONG_WRITE 0x29 /* generic long write */ -#define MCS_SHORT_WRITE_0 0x05 /* MCS short write, no parameters */ -#define MCS_SHORT_WRITE_1 0x15 /* MCS short write, 1 parameters */ -#define MCS_READ 0x06 /* MCS read, no parameters */ -#define MCS_LONG_WRITE 0x39 /* MCS long write */ -/* MCS/generic commands */ -/* TPO MCS */ -#define write_display_profile 0x50 -#define write_display_brightness 0x51 -#define write_ctrl_display 0x53 -#define write_ctrl_cabc 0x55 - #define UI_IMAGE 0x01 - #define STILL_IMAGE 0x02 - #define MOVING_IMAGE 0x03 -#define write_hysteresis 0x57 -#define write_gamma_setting 0x58 -#define write_cabc_min_bright 0x5e -#define write_kbbc_profile 0x60 -/* TMD MCS */ -#define tmd_write_display_brightness 0x8c - -/* - * This command is used to control ambient light, panel backlight - * brightness and gamma settings. - */ -#define BRIGHT_CNTL_BLOCK_ON (1 << 5) -#define AMBIENT_LIGHT_SENSE_ON (1 << 4) -#define DISPLAY_DIMMING_ON (1 << 3) -#define BACKLIGHT_ON (1 << 2) -#define DISPLAY_BRIGHTNESS_AUTO (1 << 1) -#define GAMMA_AUTO (1 << 0) - -/* DCS Interface Pixel Formats */ -#define DCS_PIXEL_FORMAT_3BPP 0x1 -#define DCS_PIXEL_FORMAT_8BPP 0x2 -#define DCS_PIXEL_FORMAT_12BPP 0x3 -#define DCS_PIXEL_FORMAT_16BPP 0x5 -#define DCS_PIXEL_FORMAT_18BPP 0x6 -#define DCS_PIXEL_FORMAT_24BPP 0x7 -/* ONE PARAMETER READ DATA */ -#define addr_mode_data 0xfc -#define diag_res_data 0x00 -#define disp_mode_data 0x23 -#define pxl_fmt_data 0x77 -#define pwr_mode_data 0x74 -#define sig_mode_data 0x00 -/* TWO PARAMETERS READ DATA */ -#define scanline_data1 0xff -#define scanline_data2 0xff -#define NON_BURST_MODE_SYNC_PULSE 0x01 /* Non Burst Mode - * with Sync Pulse - */ -#define NON_BURST_MODE_SYNC_EVENTS 0x02 /* Non Burst Mode - * with Sync events - */ -#define BURST_MODE 0x03 /* Burst Mode */ -#define DBI_COMMAND_BUFFER_SIZE 0x240 /* 0x32 */ /* 0x120 */ - /* Allocate at least - * 0x100 Byte with 32 - * byte alignment - */ -#define DBI_DATA_BUFFER_SIZE 0x120 /* Allocate at least - * 0x100 Byte with 32 - * byte alignment - */ -#define DBI_CB_TIME_OUT 0xFFFF - -#define GEN_FB_TIME_OUT 2000 - -#define SKU_83 0x01 -#define SKU_100 0x02 -#define SKU_100L 0x04 -#define SKU_BYPASS 0x08 - -/* Some handy macros for playing with bitfields. */ -#define PSB_MASK(high, low) (((1<<((high)-(low)+1))-1)<<(low)) -#define SET_FIELD(value, field) (((value) << field ## _SHIFT) & field ## _MASK) -#define GET_FIELD(word, field) (((word) & field ## _MASK) >> field ## _SHIFT) - -#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) - -/* PCI config space */ - -#define SB_PCKT 0x02100 /* cedarview */ -# define SB_OPCODE_MASK PSB_MASK(31, 16) -# define SB_OPCODE_SHIFT 16 -# define SB_OPCODE_READ 0 -# define SB_OPCODE_WRITE 1 -# define SB_DEST_MASK PSB_MASK(15, 8) -# define SB_DEST_SHIFT 8 -# define SB_DEST_DPLL 0x88 -# define SB_BYTE_ENABLE_MASK PSB_MASK(7, 4) -# define SB_BYTE_ENABLE_SHIFT 4 -# define SB_BUSY (1 << 0) - -#define DSPCLK_GATE_D 0x6200 -# define VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) /* Fixed value on CDV */ -# define DPOUNIT_CLOCK_GATE_DISABLE (1 << 11) -# define DPIOUNIT_CLOCK_GATE_DISABLE (1 << 6) - -#define RAMCLK_GATE_D 0x6210 - -/* 32-bit value read/written from the DPIO reg. */ -#define SB_DATA 0x02104 /* cedarview */ -/* 32-bit address of the DPIO reg to be read/written. */ -#define SB_ADDR 0x02108 /* cedarview */ -#define DPIO_CFG 0x02110 /* cedarview */ -# define DPIO_MODE_SELECT_1 (1 << 3) -# define DPIO_MODE_SELECT_0 (1 << 2) -# define DPIO_SFR_BYPASS (1 << 1) -/* reset is active low */ -# define DPIO_CMN_RESET_N (1 << 0) - -/* Cedarview sideband registers */ -#define _SB_M_A 0x8008 -#define _SB_M_B 0x8028 -#define SB_M(pipe) _PIPE(pipe, _SB_M_A, _SB_M_B) -# define SB_M_DIVIDER_MASK (0xFF << 24) -# define SB_M_DIVIDER_SHIFT 24 - -#define _SB_N_VCO_A 0x8014 -#define _SB_N_VCO_B 0x8034 -#define SB_N_VCO(pipe) _PIPE(pipe, _SB_N_VCO_A, _SB_N_VCO_B) -#define SB_N_VCO_SEL_MASK PSB_MASK(31, 30) -#define SB_N_VCO_SEL_SHIFT 30 -#define SB_N_DIVIDER_MASK PSB_MASK(29, 26) -#define SB_N_DIVIDER_SHIFT 26 -#define SB_N_CB_TUNE_MASK PSB_MASK(25, 24) -#define SB_N_CB_TUNE_SHIFT 24 - -#define _SB_REF_A 0x8018 -#define _SB_REF_B 0x8038 -#define SB_REF_SFR(pipe) _PIPE(pipe, _SB_REF_A, _SB_REF_B) - -#define _SB_P_A 0x801c -#define _SB_P_B 0x803c -#define SB_P(pipe) _PIPE(pipe, _SB_P_A, _SB_P_B) -#define SB_P2_DIVIDER_MASK PSB_MASK(31, 30) -#define SB_P2_DIVIDER_SHIFT 30 -#define SB_P2_10 0 /* HDMI, DP, DAC */ -#define SB_P2_5 1 /* DAC */ -#define SB_P2_14 2 /* LVDS single */ -#define SB_P2_7 3 /* LVDS double */ -#define SB_P1_DIVIDER_MASK PSB_MASK(15, 12) -#define SB_P1_DIVIDER_SHIFT 12 - -#define PSB_LANE0 0x120 -#define PSB_LANE1 0x220 -#define PSB_LANE2 0x2320 -#define PSB_LANE3 0x2420 - -#define LANE_PLL_MASK (0x7 << 20) -#define LANE_PLL_ENABLE (0x3 << 20) - - -#endif diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c deleted file mode 100644 index 36330ca..0000000 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ /dev/null @@ -1,2607 +0,0 @@ -/* - * Copyright 2006 Dave Airlie - * Copyright © 2006-2007 Intel Corporation - * Jesse Barnes - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Eric Anholt - */ -#include -#include -#include -#include -#include "drmP.h" -#include "drm.h" -#include "drm_crtc.h" -#include "drm_edid.h" -#include "psb_intel_drv.h" -#include "gma_drm.h" -#include "psb_drv.h" -#include "psb_intel_sdvo_regs.h" -#include "psb_intel_reg.h" - -#define SDVO_TMDS_MASK (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1) -#define SDVO_RGB_MASK (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1) -#define SDVO_LVDS_MASK (SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1) -#define SDVO_TV_MASK (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0) - -#define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK |\ - SDVO_TV_MASK) - -#define IS_TV(c) (c->output_flag & SDVO_TV_MASK) -#define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK) -#define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK) -#define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK)) - - -static const char *tv_format_names[] = { - "NTSC_M" , "NTSC_J" , "NTSC_443", - "PAL_B" , "PAL_D" , "PAL_G" , - "PAL_H" , "PAL_I" , "PAL_M" , - "PAL_N" , "PAL_NC" , "PAL_60" , - "SECAM_B" , "SECAM_D" , "SECAM_G" , - "SECAM_K" , "SECAM_K1", "SECAM_L" , - "SECAM_60" -}; - -#define TV_FORMAT_NUM (sizeof(tv_format_names) / sizeof(*tv_format_names)) - -struct psb_intel_sdvo { - struct psb_intel_encoder base; - - struct i2c_adapter *i2c; - u8 slave_addr; - - struct i2c_adapter ddc; - - /* Register for the SDVO device: SDVOB or SDVOC */ - int sdvo_reg; - - /* Active outputs controlled by this SDVO output */ - uint16_t controlled_output; - - /* - * Capabilities of the SDVO device returned by - * i830_sdvo_get_capabilities() - */ - struct psb_intel_sdvo_caps caps; - - /* Pixel clock limitations reported by the SDVO device, in kHz */ - int pixel_clock_min, pixel_clock_max; - - /* - * For multiple function SDVO device, - * this is for current attached outputs. - */ - uint16_t attached_output; - - /** - * This is used to select the color range of RBG outputs in HDMI mode. - * It is only valid when using TMDS encoding and 8 bit per color mode. - */ - uint32_t color_range; - - /** - * This is set if we're going to treat the device as TV-out. - * - * While we have these nice friendly flags for output types that ought - * to decide this for us, the S-Video output on our HDMI+S-Video card - * shows up as RGB1 (VGA). - */ - bool is_tv; - - /* This is for current tv format name */ - int tv_format_index; - - /** - * This is set if we treat the device as HDMI, instead of DVI. - */ - bool is_hdmi; - bool has_hdmi_monitor; - bool has_hdmi_audio; - - /** - * This is set if we detect output of sdvo device as LVDS and - * have a valid fixed mode to use with the panel. - */ - bool is_lvds; - - /** - * This is sdvo fixed pannel mode pointer - */ - struct drm_display_mode *sdvo_lvds_fixed_mode; - - /* DDC bus used by this SDVO encoder */ - uint8_t ddc_bus; - - /* Input timings for adjusted_mode */ - struct psb_intel_sdvo_dtd input_dtd; -}; - -struct psb_intel_sdvo_connector { - struct psb_intel_connector base; - - /* Mark the type of connector */ - uint16_t output_flag; - - int force_audio; - - /* This contains all current supported TV format */ - u8 tv_format_supported[TV_FORMAT_NUM]; - int format_supported_num; - struct drm_property *tv_format; - - /* add the property for the SDVO-TV */ - struct drm_property *left; - struct drm_property *right; - struct drm_property *top; - struct drm_property *bottom; - struct drm_property *hpos; - struct drm_property *vpos; - struct drm_property *contrast; - struct drm_property *saturation; - struct drm_property *hue; - struct drm_property *sharpness; - struct drm_property *flicker_filter; - struct drm_property *flicker_filter_adaptive; - struct drm_property *flicker_filter_2d; - struct drm_property *tv_chroma_filter; - struct drm_property *tv_luma_filter; - struct drm_property *dot_crawl; - - /* add the property for the SDVO-TV/LVDS */ - struct drm_property *brightness; - - /* Add variable to record current setting for the above property */ - u32 left_margin, right_margin, top_margin, bottom_margin; - - /* this is to get the range of margin.*/ - u32 max_hscan, max_vscan; - u32 max_hpos, cur_hpos; - u32 max_vpos, cur_vpos; - u32 cur_brightness, max_brightness; - u32 cur_contrast, max_contrast; - u32 cur_saturation, max_saturation; - u32 cur_hue, max_hue; - u32 cur_sharpness, max_sharpness; - u32 cur_flicker_filter, max_flicker_filter; - u32 cur_flicker_filter_adaptive, max_flicker_filter_adaptive; - u32 cur_flicker_filter_2d, max_flicker_filter_2d; - u32 cur_tv_chroma_filter, max_tv_chroma_filter; - u32 cur_tv_luma_filter, max_tv_luma_filter; - u32 cur_dot_crawl, max_dot_crawl; -}; - -static struct psb_intel_sdvo *to_psb_intel_sdvo(struct drm_encoder *encoder) -{ - return container_of(encoder, struct psb_intel_sdvo, base.base); -} - -static struct psb_intel_sdvo *intel_attached_sdvo(struct drm_connector *connector) -{ - return container_of(psb_intel_attached_encoder(connector), - struct psb_intel_sdvo, base); -} - -static struct psb_intel_sdvo_connector *to_psb_intel_sdvo_connector(struct drm_connector *connector) -{ - return container_of(to_psb_intel_connector(connector), struct psb_intel_sdvo_connector, base); -} - -static bool -psb_intel_sdvo_output_setup(struct psb_intel_sdvo *psb_intel_sdvo, uint16_t flags); -static bool -psb_intel_sdvo_tv_create_property(struct psb_intel_sdvo *psb_intel_sdvo, - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector, - int type); -static bool -psb_intel_sdvo_create_enhance_property(struct psb_intel_sdvo *psb_intel_sdvo, - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector); - -/** - * Writes the SDVOB or SDVOC with the given value, but always writes both - * SDVOB and SDVOC to work around apparent hardware issues (according to - * comments in the BIOS). - */ -static void psb_intel_sdvo_write_sdvox(struct psb_intel_sdvo *psb_intel_sdvo, u32 val) -{ - struct drm_device *dev = psb_intel_sdvo->base.base.dev; - u32 bval = val, cval = val; - int i; - - if (psb_intel_sdvo->sdvo_reg == SDVOB) { - cval = REG_READ(SDVOC); - } else { - bval = REG_READ(SDVOB); - } - /* - * Write the registers twice for luck. Sometimes, - * writing them only once doesn't appear to 'stick'. - * The BIOS does this too. Yay, magic - */ - for (i = 0; i < 2; i++) - { - REG_WRITE(SDVOB, bval); - REG_READ(SDVOB); - REG_WRITE(SDVOC, cval); - REG_READ(SDVOC); - } -} - -static bool psb_intel_sdvo_read_byte(struct psb_intel_sdvo *psb_intel_sdvo, u8 addr, u8 *ch) -{ - struct i2c_msg msgs[] = { - { - .addr = psb_intel_sdvo->slave_addr, - .flags = 0, - .len = 1, - .buf = &addr, - }, - { - .addr = psb_intel_sdvo->slave_addr, - .flags = I2C_M_RD, - .len = 1, - .buf = ch, - } - }; - int ret; - - if ((ret = i2c_transfer(psb_intel_sdvo->i2c, msgs, 2)) == 2) - return true; - - DRM_DEBUG_KMS("i2c transfer returned %d\n", ret); - return false; -} - -#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} -/** Mapping of command numbers to names, for debug output */ -static const struct _sdvo_cmd_name { - u8 cmd; - const char *name; -} sdvo_cmd_names[] = { - SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POWER_STATE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DISPLAY_POWER_STATE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS), - - /* Add the op code for SDVO enhancements */ - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HPOS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HPOS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HPOS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_VPOS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_VPOS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_VPOS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SATURATION), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SATURATION), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SATURATION), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HUE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HUE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HUE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_CONTRAST), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CONTRAST), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTRAST), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_BRIGHTNESS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_BRIGHTNESS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_BRIGHTNESS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_H), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_H), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_H), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_V), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_V), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_V), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_ADAPTIVE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_ADAPTIVE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_ADAPTIVE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_FLICKER_FILTER_2D), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FLICKER_FILTER_2D), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_FLICKER_FILTER_2D), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SHARPNESS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SHARPNESS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SHARPNESS), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DOT_CRAWL), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DOT_CRAWL), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_CHROMA_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_CHROMA_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_CHROMA_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_TV_LUMA_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_LUMA_FILTER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_LUMA_FILTER), - - /* HDMI op code */ - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_PIXEL_REPLI), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PIXEL_REPLI), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY_CAP), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_COLORIMETRY), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_AUDIO_STAT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_STAT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INDEX), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_INDEX), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INFO), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_AV_SPLIT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_AV_SPLIT), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_TXRATE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_TXRATE), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_DATA), - SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA), -}; - -#define IS_SDVOB(reg) (reg == SDVOB) -#define SDVO_NAME(svdo) (IS_SDVOB((svdo)->sdvo_reg) ? "SDVOB" : "SDVOC") - -static void psb_intel_sdvo_debug_write(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd, - const void *args, int args_len) -{ - int i; - - DRM_DEBUG_KMS("%s: W: %02X ", - SDVO_NAME(psb_intel_sdvo), cmd); - for (i = 0; i < args_len; i++) - DRM_LOG_KMS("%02X ", ((u8 *)args)[i]); - for (; i < 8; i++) - DRM_LOG_KMS(" "); - for (i = 0; i < ARRAY_SIZE(sdvo_cmd_names); i++) { - if (cmd == sdvo_cmd_names[i].cmd) { - DRM_LOG_KMS("(%s)", sdvo_cmd_names[i].name); - break; - } - } - if (i == ARRAY_SIZE(sdvo_cmd_names)) - DRM_LOG_KMS("(%02X)", cmd); - DRM_LOG_KMS("\n"); -} - -static const char *cmd_status_names[] = { - "Power on", - "Success", - "Not supported", - "Invalid arg", - "Pending", - "Target not specified", - "Scaling not supported" -}; - -static bool psb_intel_sdvo_write_cmd(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd, - const void *args, int args_len) -{ - u8 buf[args_len*2 + 2], status; - struct i2c_msg msgs[args_len + 3]; - int i, ret; - - psb_intel_sdvo_debug_write(psb_intel_sdvo, cmd, args, args_len); - - for (i = 0; i < args_len; i++) { - msgs[i].addr = psb_intel_sdvo->slave_addr; - msgs[i].flags = 0; - msgs[i].len = 2; - msgs[i].buf = buf + 2 *i; - buf[2*i + 0] = SDVO_I2C_ARG_0 - i; - buf[2*i + 1] = ((u8*)args)[i]; - } - msgs[i].addr = psb_intel_sdvo->slave_addr; - msgs[i].flags = 0; - msgs[i].len = 2; - msgs[i].buf = buf + 2*i; - buf[2*i + 0] = SDVO_I2C_OPCODE; - buf[2*i + 1] = cmd; - - /* the following two are to read the response */ - status = SDVO_I2C_CMD_STATUS; - msgs[i+1].addr = psb_intel_sdvo->slave_addr; - msgs[i+1].flags = 0; - msgs[i+1].len = 1; - msgs[i+1].buf = &status; - - msgs[i+2].addr = psb_intel_sdvo->slave_addr; - msgs[i+2].flags = I2C_M_RD; - msgs[i+2].len = 1; - msgs[i+2].buf = &status; - - ret = i2c_transfer(psb_intel_sdvo->i2c, msgs, i+3); - if (ret < 0) { - DRM_DEBUG_KMS("I2c transfer returned %d\n", ret); - return false; - } - if (ret != i+3) { - /* failure in I2C transfer */ - DRM_DEBUG_KMS("I2c transfer returned %d/%d\n", ret, i+3); - return false; - } - - return true; -} - -static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo, - void *response, int response_len) -{ - u8 retry = 5; - u8 status; - int i; - - DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(psb_intel_sdvo)); - - /* - * The documentation states that all commands will be - * processed within 15µs, and that we need only poll - * the status byte a maximum of 3 times in order for the - * command to be complete. - * - * Check 5 times in case the hardware failed to read the docs. - */ - if (!psb_intel_sdvo_read_byte(psb_intel_sdvo, - SDVO_I2C_CMD_STATUS, - &status)) - goto log_fail; - - while (status == SDVO_CMD_STATUS_PENDING && retry--) { - udelay(15); - if (!psb_intel_sdvo_read_byte(psb_intel_sdvo, - SDVO_I2C_CMD_STATUS, - &status)) - goto log_fail; - } - - if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) - DRM_LOG_KMS("(%s)", cmd_status_names[status]); - else - DRM_LOG_KMS("(??? %d)", status); - - if (status != SDVO_CMD_STATUS_SUCCESS) - goto log_fail; - - /* Read the command response */ - for (i = 0; i < response_len; i++) { - if (!psb_intel_sdvo_read_byte(psb_intel_sdvo, - SDVO_I2C_RETURN_0 + i, - &((u8 *)response)[i])) - goto log_fail; - DRM_LOG_KMS(" %02X", ((u8 *)response)[i]); - } - DRM_LOG_KMS("\n"); - return true; - -log_fail: - DRM_LOG_KMS("... failed\n"); - return false; -} - -static int psb_intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) -{ - if (mode->clock >= 100000) - return 1; - else if (mode->clock >= 50000) - return 2; - else - return 4; -} - -static bool psb_intel_sdvo_set_control_bus_switch(struct psb_intel_sdvo *psb_intel_sdvo, - u8 ddc_bus) -{ - /* This must be the immediately preceding write before the i2c xfer */ - return psb_intel_sdvo_write_cmd(psb_intel_sdvo, - SDVO_CMD_SET_CONTROL_BUS_SWITCH, - &ddc_bus, 1); -} - -static bool psb_intel_sdvo_set_value(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd, const void *data, int len) -{ - if (!psb_intel_sdvo_write_cmd(psb_intel_sdvo, cmd, data, len)) - return false; - - return psb_intel_sdvo_read_response(psb_intel_sdvo, NULL, 0); -} - -static bool -psb_intel_sdvo_get_value(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd, void *value, int len) -{ - if (!psb_intel_sdvo_write_cmd(psb_intel_sdvo, cmd, NULL, 0)) - return false; - - return psb_intel_sdvo_read_response(psb_intel_sdvo, value, len); -} - -static bool psb_intel_sdvo_set_target_input(struct psb_intel_sdvo *psb_intel_sdvo) -{ - struct psb_intel_sdvo_set_target_input_args targets = {0}; - return psb_intel_sdvo_set_value(psb_intel_sdvo, - SDVO_CMD_SET_TARGET_INPUT, - &targets, sizeof(targets)); -} - -/** - * Return whether each input is trained. - * - * This function is making an assumption about the layout of the response, - * which should be checked against the docs. - */ -static bool psb_intel_sdvo_get_trained_inputs(struct psb_intel_sdvo *psb_intel_sdvo, bool *input_1, bool *input_2) -{ - struct psb_intel_sdvo_get_trained_inputs_response response; - - BUILD_BUG_ON(sizeof(response) != 1); - if (!psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_TRAINED_INPUTS, - &response, sizeof(response))) - return false; - - *input_1 = response.input0_trained; - *input_2 = response.input1_trained; - return true; -} - -static bool psb_intel_sdvo_set_active_outputs(struct psb_intel_sdvo *psb_intel_sdvo, - u16 outputs) -{ - return psb_intel_sdvo_set_value(psb_intel_sdvo, - SDVO_CMD_SET_ACTIVE_OUTPUTS, - &outputs, sizeof(outputs)); -} - -static bool psb_intel_sdvo_set_encoder_power_state(struct psb_intel_sdvo *psb_intel_sdvo, - int mode) -{ - u8 state = SDVO_ENCODER_STATE_ON; - - switch (mode) { - case DRM_MODE_DPMS_ON: - state = SDVO_ENCODER_STATE_ON; - break; - case DRM_MODE_DPMS_STANDBY: - state = SDVO_ENCODER_STATE_STANDBY; - break; - case DRM_MODE_DPMS_SUSPEND: - state = SDVO_ENCODER_STATE_SUSPEND; - break; - case DRM_MODE_DPMS_OFF: - state = SDVO_ENCODER_STATE_OFF; - break; - } - - return psb_intel_sdvo_set_value(psb_intel_sdvo, - SDVO_CMD_SET_ENCODER_POWER_STATE, &state, sizeof(state)); -} - -static bool psb_intel_sdvo_get_input_pixel_clock_range(struct psb_intel_sdvo *psb_intel_sdvo, - int *clock_min, - int *clock_max) -{ - struct psb_intel_sdvo_pixel_clock_range clocks; - - BUILD_BUG_ON(sizeof(clocks) != 4); - if (!psb_intel_sdvo_get_value(psb_intel_sdvo, - SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, - &clocks, sizeof(clocks))) - return false; - - /* Convert the values from units of 10 kHz to kHz. */ - *clock_min = clocks.min * 10; - *clock_max = clocks.max * 10; - return true; -} - -static bool psb_intel_sdvo_set_target_output(struct psb_intel_sdvo *psb_intel_sdvo, - u16 outputs) -{ - return psb_intel_sdvo_set_value(psb_intel_sdvo, - SDVO_CMD_SET_TARGET_OUTPUT, - &outputs, sizeof(outputs)); -} - -static bool psb_intel_sdvo_set_timing(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd, - struct psb_intel_sdvo_dtd *dtd) -{ - return psb_intel_sdvo_set_value(psb_intel_sdvo, cmd, &dtd->part1, sizeof(dtd->part1)) && - psb_intel_sdvo_set_value(psb_intel_sdvo, cmd + 1, &dtd->part2, sizeof(dtd->part2)); -} - -static bool psb_intel_sdvo_set_input_timing(struct psb_intel_sdvo *psb_intel_sdvo, - struct psb_intel_sdvo_dtd *dtd) -{ - return psb_intel_sdvo_set_timing(psb_intel_sdvo, - SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd); -} - -static bool psb_intel_sdvo_set_output_timing(struct psb_intel_sdvo *psb_intel_sdvo, - struct psb_intel_sdvo_dtd *dtd) -{ - return psb_intel_sdvo_set_timing(psb_intel_sdvo, - SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd); -} - -static bool -psb_intel_sdvo_create_preferred_input_timing(struct psb_intel_sdvo *psb_intel_sdvo, - uint16_t clock, - uint16_t width, - uint16_t height) -{ - struct psb_intel_sdvo_preferred_input_timing_args args; - - memset(&args, 0, sizeof(args)); - args.clock = clock; - args.width = width; - args.height = height; - args.interlace = 0; - - if (psb_intel_sdvo->is_lvds && - (psb_intel_sdvo->sdvo_lvds_fixed_mode->hdisplay != width || - psb_intel_sdvo->sdvo_lvds_fixed_mode->vdisplay != height)) - args.scaled = 1; - - return psb_intel_sdvo_set_value(psb_intel_sdvo, - SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING, - &args, sizeof(args)); -} - -static bool psb_intel_sdvo_get_preferred_input_timing(struct psb_intel_sdvo *psb_intel_sdvo, - struct psb_intel_sdvo_dtd *dtd) -{ - BUILD_BUG_ON(sizeof(dtd->part1) != 8); - BUILD_BUG_ON(sizeof(dtd->part2) != 8); - return psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1, - &dtd->part1, sizeof(dtd->part1)) && - psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2, - &dtd->part2, sizeof(dtd->part2)); -} - -static bool psb_intel_sdvo_set_clock_rate_mult(struct psb_intel_sdvo *psb_intel_sdvo, u8 val) -{ - return psb_intel_sdvo_set_value(psb_intel_sdvo, SDVO_CMD_SET_CLOCK_RATE_MULT, &val, 1); -} - -static void psb_intel_sdvo_get_dtd_from_mode(struct psb_intel_sdvo_dtd *dtd, - const struct drm_display_mode *mode) -{ - uint16_t width, height; - uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len; - uint16_t h_sync_offset, v_sync_offset; - - width = mode->crtc_hdisplay; - height = mode->crtc_vdisplay; - - /* do some mode translations */ - h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start; - h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; - - v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start; - v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; - - h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start; - v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start; - - dtd->part1.clock = mode->clock / 10; - dtd->part1.h_active = width & 0xff; - dtd->part1.h_blank = h_blank_len & 0xff; - dtd->part1.h_high = (((width >> 8) & 0xf) << 4) | - ((h_blank_len >> 8) & 0xf); - dtd->part1.v_active = height & 0xff; - dtd->part1.v_blank = v_blank_len & 0xff; - dtd->part1.v_high = (((height >> 8) & 0xf) << 4) | - ((v_blank_len >> 8) & 0xf); - - dtd->part2.h_sync_off = h_sync_offset & 0xff; - dtd->part2.h_sync_width = h_sync_len & 0xff; - dtd->part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | - (v_sync_len & 0xf); - dtd->part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) | - ((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) | - ((v_sync_len & 0x30) >> 4); - - dtd->part2.dtd_flags = 0x18; - if (mode->flags & DRM_MODE_FLAG_PHSYNC) - dtd->part2.dtd_flags |= 0x2; - if (mode->flags & DRM_MODE_FLAG_PVSYNC) - dtd->part2.dtd_flags |= 0x4; - - dtd->part2.sdvo_flags = 0; - dtd->part2.v_sync_off_high = v_sync_offset & 0xc0; - dtd->part2.reserved = 0; -} - -static void psb_intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode, - const struct psb_intel_sdvo_dtd *dtd) -{ - mode->hdisplay = dtd->part1.h_active; - mode->hdisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8; - mode->hsync_start = mode->hdisplay + dtd->part2.h_sync_off; - mode->hsync_start += (dtd->part2.sync_off_width_high & 0xc0) << 2; - mode->hsync_end = mode->hsync_start + dtd->part2.h_sync_width; - mode->hsync_end += (dtd->part2.sync_off_width_high & 0x30) << 4; - mode->htotal = mode->hdisplay + dtd->part1.h_blank; - mode->htotal += (dtd->part1.h_high & 0xf) << 8; - - mode->vdisplay = dtd->part1.v_active; - mode->vdisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8; - mode->vsync_start = mode->vdisplay; - mode->vsync_start += (dtd->part2.v_sync_off_width >> 4) & 0xf; - mode->vsync_start += (dtd->part2.sync_off_width_high & 0x0c) << 2; - mode->vsync_start += dtd->part2.v_sync_off_high & 0xc0; - mode->vsync_end = mode->vsync_start + - (dtd->part2.v_sync_off_width & 0xf); - mode->vsync_end += (dtd->part2.sync_off_width_high & 0x3) << 4; - mode->vtotal = mode->vdisplay + dtd->part1.v_blank; - mode->vtotal += (dtd->part1.v_high & 0xf) << 8; - - mode->clock = dtd->part1.clock * 10; - - mode->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); - if (dtd->part2.dtd_flags & 0x2) - mode->flags |= DRM_MODE_FLAG_PHSYNC; - if (dtd->part2.dtd_flags & 0x4) - mode->flags |= DRM_MODE_FLAG_PVSYNC; -} - -static bool psb_intel_sdvo_check_supp_encode(struct psb_intel_sdvo *psb_intel_sdvo) -{ - struct psb_intel_sdvo_encode encode; - - BUILD_BUG_ON(sizeof(encode) != 2); - return psb_intel_sdvo_get_value(psb_intel_sdvo, - SDVO_CMD_GET_SUPP_ENCODE, - &encode, sizeof(encode)); -} - -static bool psb_intel_sdvo_set_encode(struct psb_intel_sdvo *psb_intel_sdvo, - uint8_t mode) -{ - return psb_intel_sdvo_set_value(psb_intel_sdvo, SDVO_CMD_SET_ENCODE, &mode, 1); -} - -static bool psb_intel_sdvo_set_colorimetry(struct psb_intel_sdvo *psb_intel_sdvo, - uint8_t mode) -{ - return psb_intel_sdvo_set_value(psb_intel_sdvo, SDVO_CMD_SET_COLORIMETRY, &mode, 1); -} - -#if 0 -static void psb_intel_sdvo_dump_hdmi_buf(struct psb_intel_sdvo *psb_intel_sdvo) -{ - int i, j; - uint8_t set_buf_index[2]; - uint8_t av_split; - uint8_t buf_size; - uint8_t buf[48]; - uint8_t *pos; - - psb_intel_sdvo_get_value(encoder, SDVO_CMD_GET_HBUF_AV_SPLIT, &av_split, 1); - - for (i = 0; i <= av_split; i++) { - set_buf_index[0] = i; set_buf_index[1] = 0; - psb_intel_sdvo_write_cmd(encoder, SDVO_CMD_SET_HBUF_INDEX, - set_buf_index, 2); - psb_intel_sdvo_write_cmd(encoder, SDVO_CMD_GET_HBUF_INFO, NULL, 0); - psb_intel_sdvo_read_response(encoder, &buf_size, 1); - - pos = buf; - for (j = 0; j <= buf_size; j += 8) { - psb_intel_sdvo_write_cmd(encoder, SDVO_CMD_GET_HBUF_DATA, - NULL, 0); - psb_intel_sdvo_read_response(encoder, pos, 8); - pos += 8; - } - } -} -#endif - -static bool psb_intel_sdvo_set_avi_infoframe(struct psb_intel_sdvo *psb_intel_sdvo) -{ - DRM_INFO("HDMI is not supported yet"); - - return false; -#if 0 - struct dip_infoframe avi_if = { - .type = DIP_TYPE_AVI, - .ver = DIP_VERSION_AVI, - .len = DIP_LEN_AVI, - }; - uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; - uint8_t set_buf_index[2] = { 1, 0 }; - uint64_t *data = (uint64_t *)&avi_if; - unsigned i; - - intel_dip_infoframe_csum(&avi_if); - - if (!psb_intel_sdvo_set_value(psb_intel_sdvo, - SDVO_CMD_SET_HBUF_INDEX, - set_buf_index, 2)) - return false; - - for (i = 0; i < sizeof(avi_if); i += 8) { - if (!psb_intel_sdvo_set_value(psb_intel_sdvo, - SDVO_CMD_SET_HBUF_DATA, - data, 8)) - return false; - data++; - } - - return psb_intel_sdvo_set_value(psb_intel_sdvo, - SDVO_CMD_SET_HBUF_TXRATE, - &tx_rate, 1); -#endif -} - -static bool psb_intel_sdvo_set_tv_format(struct psb_intel_sdvo *psb_intel_sdvo) -{ - struct psb_intel_sdvo_tv_format format; - uint32_t format_map; - - format_map = 1 << psb_intel_sdvo->tv_format_index; - memset(&format, 0, sizeof(format)); - memcpy(&format, &format_map, min(sizeof(format), sizeof(format_map))); - - BUILD_BUG_ON(sizeof(format) != 6); - return psb_intel_sdvo_set_value(psb_intel_sdvo, - SDVO_CMD_SET_TV_FORMAT, - &format, sizeof(format)); -} - -static bool -psb_intel_sdvo_set_output_timings_from_mode(struct psb_intel_sdvo *psb_intel_sdvo, - struct drm_display_mode *mode) -{ - struct psb_intel_sdvo_dtd output_dtd; - - if (!psb_intel_sdvo_set_target_output(psb_intel_sdvo, - psb_intel_sdvo->attached_output)) - return false; - - psb_intel_sdvo_get_dtd_from_mode(&output_dtd, mode); - if (!psb_intel_sdvo_set_output_timing(psb_intel_sdvo, &output_dtd)) - return false; - - return true; -} - -static bool -psb_intel_sdvo_set_input_timings_for_mode(struct psb_intel_sdvo *psb_intel_sdvo, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - /* Reset the input timing to the screen. Assume always input 0. */ - if (!psb_intel_sdvo_set_target_input(psb_intel_sdvo)) - return false; - - if (!psb_intel_sdvo_create_preferred_input_timing(psb_intel_sdvo, - mode->clock / 10, - mode->hdisplay, - mode->vdisplay)) - return false; - - if (!psb_intel_sdvo_get_preferred_input_timing(psb_intel_sdvo, - &psb_intel_sdvo->input_dtd)) - return false; - - psb_intel_sdvo_get_mode_from_dtd(adjusted_mode, &psb_intel_sdvo->input_dtd); - - drm_mode_set_crtcinfo(adjusted_mode, 0); - return true; -} - -static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); - int multiplier; - - /* We need to construct preferred input timings based on our - * output timings. To do that, we have to set the output - * timings, even though this isn't really the right place in - * the sequence to do it. Oh well. - */ - if (psb_intel_sdvo->is_tv) { - if (!psb_intel_sdvo_set_output_timings_from_mode(psb_intel_sdvo, mode)) - return false; - - (void) psb_intel_sdvo_set_input_timings_for_mode(psb_intel_sdvo, - mode, - adjusted_mode); - } else if (psb_intel_sdvo->is_lvds) { - if (!psb_intel_sdvo_set_output_timings_from_mode(psb_intel_sdvo, - psb_intel_sdvo->sdvo_lvds_fixed_mode)) - return false; - - (void) psb_intel_sdvo_set_input_timings_for_mode(psb_intel_sdvo, - mode, - adjusted_mode); - } - - /* Make the CRTC code factor in the SDVO pixel multiplier. The - * SDVO device will factor out the multiplier during mode_set. - */ - multiplier = psb_intel_sdvo_get_pixel_multiplier(adjusted_mode); - psb_intel_mode_set_pixel_multiplier(adjusted_mode, multiplier); - - return true; -} - -static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_device *dev = encoder->dev; - struct drm_crtc *crtc = encoder->crtc; - struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); - u32 sdvox; - struct psb_intel_sdvo_in_out_map in_out; - struct psb_intel_sdvo_dtd input_dtd; - int pixel_multiplier = psb_intel_mode_get_pixel_multiplier(adjusted_mode); - int rate; - - if (!mode) - return; - - /* First, set the input mapping for the first input to our controlled - * output. This is only correct if we're a single-input device, in - * which case the first input is the output from the appropriate SDVO - * channel on the motherboard. In a two-input device, the first input - * will be SDVOB and the second SDVOC. - */ - in_out.in0 = psb_intel_sdvo->attached_output; - in_out.in1 = 0; - - psb_intel_sdvo_set_value(psb_intel_sdvo, - SDVO_CMD_SET_IN_OUT_MAP, - &in_out, sizeof(in_out)); - - /* Set the output timings to the screen */ - if (!psb_intel_sdvo_set_target_output(psb_intel_sdvo, - psb_intel_sdvo->attached_output)) - return; - - /* We have tried to get input timing in mode_fixup, and filled into - * adjusted_mode. - */ - if (psb_intel_sdvo->is_tv || psb_intel_sdvo->is_lvds) { - input_dtd = psb_intel_sdvo->input_dtd; - } else { - /* Set the output timing to the screen */ - if (!psb_intel_sdvo_set_target_output(psb_intel_sdvo, - psb_intel_sdvo->attached_output)) - return; - - psb_intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); - (void) psb_intel_sdvo_set_output_timing(psb_intel_sdvo, &input_dtd); - } - - /* Set the input timing to the screen. Assume always input 0. */ - if (!psb_intel_sdvo_set_target_input(psb_intel_sdvo)) - return; - - if (psb_intel_sdvo->has_hdmi_monitor) { - psb_intel_sdvo_set_encode(psb_intel_sdvo, SDVO_ENCODE_HDMI); - psb_intel_sdvo_set_colorimetry(psb_intel_sdvo, - SDVO_COLORIMETRY_RGB256); - psb_intel_sdvo_set_avi_infoframe(psb_intel_sdvo); - } else - psb_intel_sdvo_set_encode(psb_intel_sdvo, SDVO_ENCODE_DVI); - - if (psb_intel_sdvo->is_tv && - !psb_intel_sdvo_set_tv_format(psb_intel_sdvo)) - return; - - (void) psb_intel_sdvo_set_input_timing(psb_intel_sdvo, &input_dtd); - - switch (pixel_multiplier) { - default: - case 1: rate = SDVO_CLOCK_RATE_MULT_1X; break; - case 2: rate = SDVO_CLOCK_RATE_MULT_2X; break; - case 4: rate = SDVO_CLOCK_RATE_MULT_4X; break; - } - if (!psb_intel_sdvo_set_clock_rate_mult(psb_intel_sdvo, rate)) - return; - - /* Set the SDVO control regs. */ - sdvox = REG_READ(psb_intel_sdvo->sdvo_reg); - switch (psb_intel_sdvo->sdvo_reg) { - case SDVOB: - sdvox &= SDVOB_PRESERVE_MASK; - break; - case SDVOC: - sdvox &= SDVOC_PRESERVE_MASK; - break; - } - sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; - - if (psb_intel_crtc->pipe == 1) - sdvox |= SDVO_PIPE_B_SELECT; - if (psb_intel_sdvo->has_hdmi_audio) - sdvox |= SDVO_AUDIO_ENABLE; - - /* FIXME: Check if this is needed for PSB - sdvox |= (pixel_multiplier - 1) << SDVO_PORT_MULTIPLY_SHIFT; - */ - - if (input_dtd.part2.sdvo_flags & SDVO_NEED_TO_STALL) - sdvox |= SDVO_STALL_SELECT; - psb_intel_sdvo_write_sdvox(psb_intel_sdvo, sdvox); -} - -static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode) -{ - struct drm_device *dev = encoder->dev; - struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); - u32 temp; - - switch (mode) { - case DRM_MODE_DPMS_ON: - DRM_DEBUG("DPMS_ON"); - break; - case DRM_MODE_DPMS_OFF: - DRM_DEBUG("DPMS_OFF"); - break; - default: - DRM_DEBUG("DPMS: %d", mode); - } - - if (mode != DRM_MODE_DPMS_ON) { - psb_intel_sdvo_set_active_outputs(psb_intel_sdvo, 0); - if (0) - psb_intel_sdvo_set_encoder_power_state(psb_intel_sdvo, mode); - - if (mode == DRM_MODE_DPMS_OFF) { - temp = REG_READ(psb_intel_sdvo->sdvo_reg); - if ((temp & SDVO_ENABLE) != 0) { - psb_intel_sdvo_write_sdvox(psb_intel_sdvo, temp & ~SDVO_ENABLE); - } - } - } else { - bool input1, input2; - int i; - u8 status; - - temp = REG_READ(psb_intel_sdvo->sdvo_reg); - if ((temp & SDVO_ENABLE) == 0) - psb_intel_sdvo_write_sdvox(psb_intel_sdvo, temp | SDVO_ENABLE); - for (i = 0; i < 2; i++) - psb_intel_wait_for_vblank(dev); - - status = psb_intel_sdvo_get_trained_inputs(psb_intel_sdvo, &input1, &input2); - /* Warn if the device reported failure to sync. - * A lot of SDVO devices fail to notify of sync, but it's - * a given it the status is a success, we succeeded. - */ - if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { - DRM_DEBUG_KMS("First %s output reported failure to " - "sync\n", SDVO_NAME(psb_intel_sdvo)); - } - - if (0) - psb_intel_sdvo_set_encoder_power_state(psb_intel_sdvo, mode); - psb_intel_sdvo_set_active_outputs(psb_intel_sdvo, psb_intel_sdvo->attached_output); - } - return; -} - -static int psb_intel_sdvo_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct drm_psb_private *dev_priv = connector->dev->dev_private; - struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); - - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - - if (psb_intel_sdvo->pixel_clock_min > mode->clock) - return MODE_CLOCK_LOW; - - if (psb_intel_sdvo->pixel_clock_max < mode->clock) - return MODE_CLOCK_HIGH; - - if (psb_intel_sdvo->is_lvds) { - if (mode->hdisplay > psb_intel_sdvo->sdvo_lvds_fixed_mode->hdisplay) - return MODE_PANEL; - - if (mode->vdisplay > psb_intel_sdvo->sdvo_lvds_fixed_mode->vdisplay) - return MODE_PANEL; - } - - /* We assume worst case scenario of 32 bpp here, since we don't know */ - if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) > - dev_priv->vram_stolen_size) - return MODE_MEM; - - return MODE_OK; -} - -static bool psb_intel_sdvo_get_capabilities(struct psb_intel_sdvo *psb_intel_sdvo, struct psb_intel_sdvo_caps *caps) -{ - BUILD_BUG_ON(sizeof(*caps) != 8); - if (!psb_intel_sdvo_get_value(psb_intel_sdvo, - SDVO_CMD_GET_DEVICE_CAPS, - caps, sizeof(*caps))) - return false; - - DRM_DEBUG_KMS("SDVO capabilities:\n" - " vendor_id: %d\n" - " device_id: %d\n" - " device_rev_id: %d\n" - " sdvo_version_major: %d\n" - " sdvo_version_minor: %d\n" - " sdvo_inputs_mask: %d\n" - " smooth_scaling: %d\n" - " sharp_scaling: %d\n" - " up_scaling: %d\n" - " down_scaling: %d\n" - " stall_support: %d\n" - " output_flags: %d\n", - caps->vendor_id, - caps->device_id, - caps->device_rev_id, - caps->sdvo_version_major, - caps->sdvo_version_minor, - caps->sdvo_inputs_mask, - caps->smooth_scaling, - caps->sharp_scaling, - caps->up_scaling, - caps->down_scaling, - caps->stall_support, - caps->output_flags); - - return true; -} - -/* No use! */ -#if 0 -struct drm_connector* psb_intel_sdvo_find(struct drm_device *dev, int sdvoB) -{ - struct drm_connector *connector = NULL; - struct psb_intel_sdvo *iout = NULL; - struct psb_intel_sdvo *sdvo; - - /* find the sdvo connector */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - iout = to_psb_intel_sdvo(connector); - - if (iout->type != INTEL_OUTPUT_SDVO) - continue; - - sdvo = iout->dev_priv; - - if (sdvo->sdvo_reg == SDVOB && sdvoB) - return connector; - - if (sdvo->sdvo_reg == SDVOC && !sdvoB) - return connector; - - } - - return NULL; -} - -int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector) -{ - u8 response[2]; - u8 status; - struct psb_intel_sdvo *psb_intel_sdvo; - DRM_DEBUG_KMS("\n"); - - if (!connector) - return 0; - - psb_intel_sdvo = to_psb_intel_sdvo(connector); - - return psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, - &response, 2) && response[0]; -} - -void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, int on) -{ - u8 response[2]; - u8 status; - struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(connector); - - psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); - psb_intel_sdvo_read_response(psb_intel_sdvo, &response, 2); - - if (on) { - psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0); - status = psb_intel_sdvo_read_response(psb_intel_sdvo, &response, 2); - - psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); - } else { - response[0] = 0; - response[1] = 0; - psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); - } - - psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); - psb_intel_sdvo_read_response(psb_intel_sdvo, &response, 2); -} -#endif - -static bool -psb_intel_sdvo_multifunc_encoder(struct psb_intel_sdvo *psb_intel_sdvo) -{ - /* Is there more than one type of output? */ - int caps = psb_intel_sdvo->caps.output_flags & 0xf; - return caps & -caps; -} - -static struct edid * -psb_intel_sdvo_get_edid(struct drm_connector *connector) -{ - struct psb_intel_sdvo *sdvo = intel_attached_sdvo(connector); - return drm_get_edid(connector, &sdvo->ddc); -} - -/* Mac mini hack -- use the same DDC as the analog connector */ -static struct edid * -psb_intel_sdvo_get_analog_edid(struct drm_connector *connector) -{ - struct drm_psb_private *dev_priv = connector->dev->dev_private; - - return drm_get_edid(connector, - &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); - return NULL; -} - -static enum drm_connector_status -psb_intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) -{ - struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); - enum drm_connector_status status; - struct edid *edid; - - edid = psb_intel_sdvo_get_edid(connector); - - if (edid == NULL && psb_intel_sdvo_multifunc_encoder(psb_intel_sdvo)) { - u8 ddc, saved_ddc = psb_intel_sdvo->ddc_bus; - - /* - * Don't use the 1 as the argument of DDC bus switch to get - * the EDID. It is used for SDVO SPD ROM. - */ - for (ddc = psb_intel_sdvo->ddc_bus >> 1; ddc > 1; ddc >>= 1) { - psb_intel_sdvo->ddc_bus = ddc; - edid = psb_intel_sdvo_get_edid(connector); - if (edid) - break; - } - /* - * If we found the EDID on the other bus, - * assume that is the correct DDC bus. - */ - if (edid == NULL) - psb_intel_sdvo->ddc_bus = saved_ddc; - } - - /* - * When there is no edid and no monitor is connected with VGA - * port, try to use the CRT ddc to read the EDID for DVI-connector. - */ - if (edid == NULL) - edid = psb_intel_sdvo_get_analog_edid(connector); - - status = connector_status_unknown; - if (edid != NULL) { - /* DDC bus is shared, match EDID to connector type */ - if (edid->input & DRM_EDID_INPUT_DIGITAL) { - status = connector_status_connected; - if (psb_intel_sdvo->is_hdmi) { - psb_intel_sdvo->has_hdmi_monitor = drm_detect_hdmi_monitor(edid); - psb_intel_sdvo->has_hdmi_audio = drm_detect_monitor_audio(edid); - } - } else - status = connector_status_disconnected; - connector->display_info.raw_edid = NULL; - kfree(edid); - } - - if (status == connector_status_connected) { - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); - if (psb_intel_sdvo_connector->force_audio) - psb_intel_sdvo->has_hdmi_audio = psb_intel_sdvo_connector->force_audio > 0; - } - - return status; -} - -static enum drm_connector_status -psb_intel_sdvo_detect(struct drm_connector *connector, bool force) -{ - uint16_t response; - struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); - enum drm_connector_status ret; - - if (!psb_intel_sdvo_write_cmd(psb_intel_sdvo, - SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0)) - return connector_status_unknown; - - /* add 30ms delay when the output type might be TV */ - if (psb_intel_sdvo->caps.output_flags & - (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_CVBS0)) - mdelay(30); - - if (!psb_intel_sdvo_read_response(psb_intel_sdvo, &response, 2)) - return connector_status_unknown; - - DRM_DEBUG_KMS("SDVO response %d %d [%x]\n", - response & 0xff, response >> 8, - psb_intel_sdvo_connector->output_flag); - - if (response == 0) - return connector_status_disconnected; - - psb_intel_sdvo->attached_output = response; - - psb_intel_sdvo->has_hdmi_monitor = false; - psb_intel_sdvo->has_hdmi_audio = false; - - if ((psb_intel_sdvo_connector->output_flag & response) == 0) - ret = connector_status_disconnected; - else if (IS_TMDS(psb_intel_sdvo_connector)) - ret = psb_intel_sdvo_hdmi_sink_detect(connector); - else { - struct edid *edid; - - /* if we have an edid check it matches the connection */ - edid = psb_intel_sdvo_get_edid(connector); - if (edid == NULL) - edid = psb_intel_sdvo_get_analog_edid(connector); - if (edid != NULL) { - if (edid->input & DRM_EDID_INPUT_DIGITAL) - ret = connector_status_disconnected; - else - ret = connector_status_connected; - connector->display_info.raw_edid = NULL; - kfree(edid); - } else - ret = connector_status_connected; - } - - /* May update encoder flag for like clock for SDVO TV, etc.*/ - if (ret == connector_status_connected) { - psb_intel_sdvo->is_tv = false; - psb_intel_sdvo->is_lvds = false; - psb_intel_sdvo->base.needs_tv_clock = false; - - if (response & SDVO_TV_MASK) { - psb_intel_sdvo->is_tv = true; - psb_intel_sdvo->base.needs_tv_clock = true; - } - if (response & SDVO_LVDS_MASK) - psb_intel_sdvo->is_lvds = psb_intel_sdvo->sdvo_lvds_fixed_mode != NULL; - } - - return ret; -} - -static void psb_intel_sdvo_get_ddc_modes(struct drm_connector *connector) -{ - struct edid *edid; - - /* set the bus switch and get the modes */ - edid = psb_intel_sdvo_get_edid(connector); - - /* - * Mac mini hack. On this device, the DVI-I connector shares one DDC - * link between analog and digital outputs. So, if the regular SDVO - * DDC fails, check to see if the analog output is disconnected, in - * which case we'll look there for the digital DDC data. - */ - if (edid == NULL) - edid = psb_intel_sdvo_get_analog_edid(connector); - - if (edid != NULL) { - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); - bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); - bool connector_is_digital = !!IS_TMDS(psb_intel_sdvo_connector); - - if (connector_is_digital == monitor_is_digital) { - drm_mode_connector_update_edid_property(connector, edid); - drm_add_edid_modes(connector, edid); - } - - connector->display_info.raw_edid = NULL; - kfree(edid); - } -} - -/* - * Set of SDVO TV modes. - * Note! This is in reply order (see loop in get_tv_modes). - * XXX: all 60Hz refresh? - */ -static const struct drm_display_mode sdvo_tv_modes[] = { - { DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815, 320, 321, 384, - 416, 0, 200, 201, 232, 233, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 6814, 320, 321, 384, - 416, 0, 240, 241, 272, 273, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 9910, 400, 401, 464, - 496, 0, 300, 301, 332, 333, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 16913, 640, 641, 704, - 736, 0, 350, 351, 382, 383, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121, 640, 641, 704, - 736, 0, 400, 401, 432, 433, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 22654, 640, 641, 704, - 736, 0, 480, 481, 512, 513, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("704x480", DRM_MODE_TYPE_DRIVER, 24624, 704, 705, 768, - 800, 0, 480, 481, 512, 513, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("704x576", DRM_MODE_TYPE_DRIVER, 29232, 704, 705, 768, - 800, 0, 576, 577, 608, 609, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("720x350", DRM_MODE_TYPE_DRIVER, 18751, 720, 721, 784, - 816, 0, 350, 351, 382, 383, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 21199, 720, 721, 784, - 816, 0, 400, 401, 432, 433, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 25116, 720, 721, 784, - 816, 0, 480, 481, 512, 513, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("720x540", DRM_MODE_TYPE_DRIVER, 28054, 720, 721, 784, - 816, 0, 540, 541, 572, 573, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 29816, 720, 721, 784, - 816, 0, 576, 577, 608, 609, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("768x576", DRM_MODE_TYPE_DRIVER, 31570, 768, 769, 832, - 864, 0, 576, 577, 608, 609, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 34030, 800, 801, 864, - 896, 0, 600, 601, 632, 633, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 36581, 832, 833, 896, - 928, 0, 624, 625, 656, 657, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("920x766", DRM_MODE_TYPE_DRIVER, 48707, 920, 921, 984, - 1016, 0, 766, 767, 798, 799, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 53827, 1024, 1025, 1088, - 1120, 0, 768, 769, 800, 801, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 87265, 1280, 1281, 1344, - 1376, 0, 1024, 1025, 1056, 1057, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, -}; - -static void psb_intel_sdvo_get_tv_modes(struct drm_connector *connector) -{ - struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); - struct psb_intel_sdvo_sdtv_resolution_request tv_res; - uint32_t reply = 0, format_map = 0; - int i; - - /* Read the list of supported input resolutions for the selected TV - * format. - */ - format_map = 1 << psb_intel_sdvo->tv_format_index; - memcpy(&tv_res, &format_map, - min(sizeof(format_map), sizeof(struct psb_intel_sdvo_sdtv_resolution_request))); - - if (!psb_intel_sdvo_set_target_output(psb_intel_sdvo, psb_intel_sdvo->attached_output)) - return; - - BUILD_BUG_ON(sizeof(tv_res) != 3); - if (!psb_intel_sdvo_write_cmd(psb_intel_sdvo, - SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, - &tv_res, sizeof(tv_res))) - return; - if (!psb_intel_sdvo_read_response(psb_intel_sdvo, &reply, 3)) - return; - - for (i = 0; i < ARRAY_SIZE(sdvo_tv_modes); i++) - if (reply & (1 << i)) { - struct drm_display_mode *nmode; - nmode = drm_mode_duplicate(connector->dev, - &sdvo_tv_modes[i]); - if (nmode) - drm_mode_probed_add(connector, nmode); - } -} - -static void psb_intel_sdvo_get_lvds_modes(struct drm_connector *connector) -{ - struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); - struct drm_psb_private *dev_priv = connector->dev->dev_private; - struct drm_display_mode *newmode; - - /* - * Attempt to get the mode list from DDC. - * Assume that the preferred modes are - * arranged in priority order. - */ - psb_intel_ddc_get_modes(connector, psb_intel_sdvo->i2c); - if (list_empty(&connector->probed_modes) == false) - goto end; - - /* Fetch modes from VBT */ - if (dev_priv->sdvo_lvds_vbt_mode != NULL) { - newmode = drm_mode_duplicate(connector->dev, - dev_priv->sdvo_lvds_vbt_mode); - if (newmode != NULL) { - /* Guarantee the mode is preferred */ - newmode->type = (DRM_MODE_TYPE_PREFERRED | - DRM_MODE_TYPE_DRIVER); - drm_mode_probed_add(connector, newmode); - } - } - -end: - list_for_each_entry(newmode, &connector->probed_modes, head) { - if (newmode->type & DRM_MODE_TYPE_PREFERRED) { - psb_intel_sdvo->sdvo_lvds_fixed_mode = - drm_mode_duplicate(connector->dev, newmode); - - drm_mode_set_crtcinfo(psb_intel_sdvo->sdvo_lvds_fixed_mode, - 0); - - psb_intel_sdvo->is_lvds = true; - break; - } - } - -} - -static int psb_intel_sdvo_get_modes(struct drm_connector *connector) -{ - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); - - if (IS_TV(psb_intel_sdvo_connector)) - psb_intel_sdvo_get_tv_modes(connector); - else if (IS_LVDS(psb_intel_sdvo_connector)) - psb_intel_sdvo_get_lvds_modes(connector); - else - psb_intel_sdvo_get_ddc_modes(connector); - - return !list_empty(&connector->probed_modes); -} - -static void -psb_intel_sdvo_destroy_enhance_property(struct drm_connector *connector) -{ - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); - struct drm_device *dev = connector->dev; - - if (psb_intel_sdvo_connector->left) - drm_property_destroy(dev, psb_intel_sdvo_connector->left); - if (psb_intel_sdvo_connector->right) - drm_property_destroy(dev, psb_intel_sdvo_connector->right); - if (psb_intel_sdvo_connector->top) - drm_property_destroy(dev, psb_intel_sdvo_connector->top); - if (psb_intel_sdvo_connector->bottom) - drm_property_destroy(dev, psb_intel_sdvo_connector->bottom); - if (psb_intel_sdvo_connector->hpos) - drm_property_destroy(dev, psb_intel_sdvo_connector->hpos); - if (psb_intel_sdvo_connector->vpos) - drm_property_destroy(dev, psb_intel_sdvo_connector->vpos); - if (psb_intel_sdvo_connector->saturation) - drm_property_destroy(dev, psb_intel_sdvo_connector->saturation); - if (psb_intel_sdvo_connector->contrast) - drm_property_destroy(dev, psb_intel_sdvo_connector->contrast); - if (psb_intel_sdvo_connector->hue) - drm_property_destroy(dev, psb_intel_sdvo_connector->hue); - if (psb_intel_sdvo_connector->sharpness) - drm_property_destroy(dev, psb_intel_sdvo_connector->sharpness); - if (psb_intel_sdvo_connector->flicker_filter) - drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter); - if (psb_intel_sdvo_connector->flicker_filter_2d) - drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_2d); - if (psb_intel_sdvo_connector->flicker_filter_adaptive) - drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_adaptive); - if (psb_intel_sdvo_connector->tv_luma_filter) - drm_property_destroy(dev, psb_intel_sdvo_connector->tv_luma_filter); - if (psb_intel_sdvo_connector->tv_chroma_filter) - drm_property_destroy(dev, psb_intel_sdvo_connector->tv_chroma_filter); - if (psb_intel_sdvo_connector->dot_crawl) - drm_property_destroy(dev, psb_intel_sdvo_connector->dot_crawl); - if (psb_intel_sdvo_connector->brightness) - drm_property_destroy(dev, psb_intel_sdvo_connector->brightness); -} - -static void psb_intel_sdvo_destroy(struct drm_connector *connector) -{ - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); - - if (psb_intel_sdvo_connector->tv_format) - drm_property_destroy(connector->dev, - psb_intel_sdvo_connector->tv_format); - - psb_intel_sdvo_destroy_enhance_property(connector); - drm_sysfs_connector_remove(connector); - drm_connector_cleanup(connector); - kfree(connector); -} - -static bool psb_intel_sdvo_detect_hdmi_audio(struct drm_connector *connector) -{ - struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); - struct edid *edid; - bool has_audio = false; - - if (!psb_intel_sdvo->is_hdmi) - return false; - - edid = psb_intel_sdvo_get_edid(connector); - if (edid != NULL && edid->input & DRM_EDID_INPUT_DIGITAL) - has_audio = drm_detect_monitor_audio(edid); - - return has_audio; -} - -static int -psb_intel_sdvo_set_property(struct drm_connector *connector, - struct drm_property *property, - uint64_t val) -{ - struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector); - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); - struct drm_psb_private *dev_priv = connector->dev->dev_private; - uint16_t temp_value; - uint8_t cmd; - int ret; - - ret = drm_connector_property_set_value(connector, property, val); - if (ret) - return ret; - - if (property == dev_priv->force_audio_property) { - int i = val; - bool has_audio; - - if (i == psb_intel_sdvo_connector->force_audio) - return 0; - - psb_intel_sdvo_connector->force_audio = i; - - if (i == 0) - has_audio = psb_intel_sdvo_detect_hdmi_audio(connector); - else - has_audio = i > 0; - - if (has_audio == psb_intel_sdvo->has_hdmi_audio) - return 0; - - psb_intel_sdvo->has_hdmi_audio = has_audio; - goto done; - } - - if (property == dev_priv->broadcast_rgb_property) { - if (val == !!psb_intel_sdvo->color_range) - return 0; - - psb_intel_sdvo->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0; - goto done; - } - -#define CHECK_PROPERTY(name, NAME) \ - if (psb_intel_sdvo_connector->name == property) { \ - if (psb_intel_sdvo_connector->cur_##name == temp_value) return 0; \ - if (psb_intel_sdvo_connector->max_##name < temp_value) return -EINVAL; \ - cmd = SDVO_CMD_SET_##NAME; \ - psb_intel_sdvo_connector->cur_##name = temp_value; \ - goto set_value; \ - } - - if (property == psb_intel_sdvo_connector->tv_format) { - if (val >= TV_FORMAT_NUM) - return -EINVAL; - - if (psb_intel_sdvo->tv_format_index == - psb_intel_sdvo_connector->tv_format_supported[val]) - return 0; - - psb_intel_sdvo->tv_format_index = psb_intel_sdvo_connector->tv_format_supported[val]; - goto done; - } else if (IS_TV_OR_LVDS(psb_intel_sdvo_connector)) { - temp_value = val; - if (psb_intel_sdvo_connector->left == property) { - drm_connector_property_set_value(connector, - psb_intel_sdvo_connector->right, val); - if (psb_intel_sdvo_connector->left_margin == temp_value) - return 0; - - psb_intel_sdvo_connector->left_margin = temp_value; - psb_intel_sdvo_connector->right_margin = temp_value; - temp_value = psb_intel_sdvo_connector->max_hscan - - psb_intel_sdvo_connector->left_margin; - cmd = SDVO_CMD_SET_OVERSCAN_H; - goto set_value; - } else if (psb_intel_sdvo_connector->right == property) { - drm_connector_property_set_value(connector, - psb_intel_sdvo_connector->left, val); - if (psb_intel_sdvo_connector->right_margin == temp_value) - return 0; - - psb_intel_sdvo_connector->left_margin = temp_value; - psb_intel_sdvo_connector->right_margin = temp_value; - temp_value = psb_intel_sdvo_connector->max_hscan - - psb_intel_sdvo_connector->left_margin; - cmd = SDVO_CMD_SET_OVERSCAN_H; - goto set_value; - } else if (psb_intel_sdvo_connector->top == property) { - drm_connector_property_set_value(connector, - psb_intel_sdvo_connector->bottom, val); - if (psb_intel_sdvo_connector->top_margin == temp_value) - return 0; - - psb_intel_sdvo_connector->top_margin = temp_value; - psb_intel_sdvo_connector->bottom_margin = temp_value; - temp_value = psb_intel_sdvo_connector->max_vscan - - psb_intel_sdvo_connector->top_margin; - cmd = SDVO_CMD_SET_OVERSCAN_V; - goto set_value; - } else if (psb_intel_sdvo_connector->bottom == property) { - drm_connector_property_set_value(connector, - psb_intel_sdvo_connector->top, val); - if (psb_intel_sdvo_connector->bottom_margin == temp_value) - return 0; - - psb_intel_sdvo_connector->top_margin = temp_value; - psb_intel_sdvo_connector->bottom_margin = temp_value; - temp_value = psb_intel_sdvo_connector->max_vscan - - psb_intel_sdvo_connector->top_margin; - cmd = SDVO_CMD_SET_OVERSCAN_V; - goto set_value; - } - CHECK_PROPERTY(hpos, HPOS) - CHECK_PROPERTY(vpos, VPOS) - CHECK_PROPERTY(saturation, SATURATION) - CHECK_PROPERTY(contrast, CONTRAST) - CHECK_PROPERTY(hue, HUE) - CHECK_PROPERTY(brightness, BRIGHTNESS) - CHECK_PROPERTY(sharpness, SHARPNESS) - CHECK_PROPERTY(flicker_filter, FLICKER_FILTER) - CHECK_PROPERTY(flicker_filter_2d, FLICKER_FILTER_2D) - CHECK_PROPERTY(flicker_filter_adaptive, FLICKER_FILTER_ADAPTIVE) - CHECK_PROPERTY(tv_chroma_filter, TV_CHROMA_FILTER) - CHECK_PROPERTY(tv_luma_filter, TV_LUMA_FILTER) - CHECK_PROPERTY(dot_crawl, DOT_CRAWL) - } - - return -EINVAL; /* unknown property */ - -set_value: - if (!psb_intel_sdvo_set_value(psb_intel_sdvo, cmd, &temp_value, 2)) - return -EIO; - - -done: - if (psb_intel_sdvo->base.base.crtc) { - struct drm_crtc *crtc = psb_intel_sdvo->base.base.crtc; - drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x, - crtc->y, crtc->fb); - } - - return 0; -#undef CHECK_PROPERTY -} - -static const struct drm_encoder_helper_funcs psb_intel_sdvo_helper_funcs = { - .dpms = psb_intel_sdvo_dpms, - .mode_fixup = psb_intel_sdvo_mode_fixup, - .prepare = psb_intel_encoder_prepare, - .mode_set = psb_intel_sdvo_mode_set, - .commit = psb_intel_encoder_commit, -}; - -static const struct drm_connector_funcs psb_intel_sdvo_connector_funcs = { - .dpms = drm_helper_connector_dpms, - .detect = psb_intel_sdvo_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .set_property = psb_intel_sdvo_set_property, - .destroy = psb_intel_sdvo_destroy, -}; - -static const struct drm_connector_helper_funcs psb_intel_sdvo_connector_helper_funcs = { - .get_modes = psb_intel_sdvo_get_modes, - .mode_valid = psb_intel_sdvo_mode_valid, - .best_encoder = psb_intel_best_encoder, -}; - -static void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder) -{ - struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); - - if (psb_intel_sdvo->sdvo_lvds_fixed_mode != NULL) - drm_mode_destroy(encoder->dev, - psb_intel_sdvo->sdvo_lvds_fixed_mode); - - i2c_del_adapter(&psb_intel_sdvo->ddc); - psb_intel_encoder_destroy(encoder); -} - -static const struct drm_encoder_funcs psb_intel_sdvo_enc_funcs = { - .destroy = psb_intel_sdvo_enc_destroy, -}; - -static void -psb_intel_sdvo_guess_ddc_bus(struct psb_intel_sdvo *sdvo) -{ - /* FIXME: At the moment, ddc_bus = 2 is the only thing that works. - * We need to figure out if this is true for all available poulsbo - * hardware, or if we need to fiddle with the guessing code above. - * The problem might go away if we can parse sdvo mappings from bios */ - sdvo->ddc_bus = 2; - -#if 0 - uint16_t mask = 0; - unsigned int num_bits; - - /* Make a mask of outputs less than or equal to our own priority in the - * list. - */ - switch (sdvo->controlled_output) { - case SDVO_OUTPUT_LVDS1: - mask |= SDVO_OUTPUT_LVDS1; - case SDVO_OUTPUT_LVDS0: - mask |= SDVO_OUTPUT_LVDS0; - case SDVO_OUTPUT_TMDS1: - mask |= SDVO_OUTPUT_TMDS1; - case SDVO_OUTPUT_TMDS0: - mask |= SDVO_OUTPUT_TMDS0; - case SDVO_OUTPUT_RGB1: - mask |= SDVO_OUTPUT_RGB1; - case SDVO_OUTPUT_RGB0: - mask |= SDVO_OUTPUT_RGB0; - break; - } - - /* Count bits to find what number we are in the priority list. */ - mask &= sdvo->caps.output_flags; - num_bits = hweight16(mask); - /* If more than 3 outputs, default to DDC bus 3 for now. */ - if (num_bits > 3) - num_bits = 3; - - /* Corresponds to SDVO_CONTROL_BUS_DDCx */ - sdvo->ddc_bus = 1 << num_bits; -#endif -} - -/** - * Choose the appropriate DDC bus for control bus switch command for this - * SDVO output based on the controlled output. - * - * DDC bus number assignment is in a priority order of RGB outputs, then TMDS - * outputs, then LVDS outputs. - */ -static void -psb_intel_sdvo_select_ddc_bus(struct drm_psb_private *dev_priv, - struct psb_intel_sdvo *sdvo, u32 reg) -{ - struct sdvo_device_mapping *mapping; - - if (IS_SDVOB(reg)) - mapping = &(dev_priv->sdvo_mappings[0]); - else - mapping = &(dev_priv->sdvo_mappings[1]); - - if (mapping->initialized) - sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4); - else - psb_intel_sdvo_guess_ddc_bus(sdvo); -} - -static void -psb_intel_sdvo_select_i2c_bus(struct drm_psb_private *dev_priv, - struct psb_intel_sdvo *sdvo, u32 reg) -{ - struct sdvo_device_mapping *mapping; - u8 pin, speed; - - if (IS_SDVOB(reg)) - mapping = &dev_priv->sdvo_mappings[0]; - else - mapping = &dev_priv->sdvo_mappings[1]; - - pin = GMBUS_PORT_DPB; - speed = GMBUS_RATE_1MHZ >> 8; - if (mapping->initialized) { - pin = mapping->i2c_pin; - speed = mapping->i2c_speed; - } - - if (pin < GMBUS_NUM_PORTS) { - sdvo->i2c = &dev_priv->gmbus[pin].adapter; - gma_intel_gmbus_set_speed(sdvo->i2c, speed); - gma_intel_gmbus_force_bit(sdvo->i2c, true); - } else - sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter; -} - -static bool -psb_intel_sdvo_is_hdmi_connector(struct psb_intel_sdvo *psb_intel_sdvo, int device) -{ - return psb_intel_sdvo_check_supp_encode(psb_intel_sdvo); -} - -static u8 -psb_intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct sdvo_device_mapping *my_mapping, *other_mapping; - - if (IS_SDVOB(sdvo_reg)) { - my_mapping = &dev_priv->sdvo_mappings[0]; - other_mapping = &dev_priv->sdvo_mappings[1]; - } else { - my_mapping = &dev_priv->sdvo_mappings[1]; - other_mapping = &dev_priv->sdvo_mappings[0]; - } - - /* If the BIOS described our SDVO device, take advantage of it. */ - if (my_mapping->slave_addr) - return my_mapping->slave_addr; - - /* If the BIOS only described a different SDVO device, use the - * address that it isn't using. - */ - if (other_mapping->slave_addr) { - if (other_mapping->slave_addr == 0x70) - return 0x72; - else - return 0x70; - } - - /* No SDVO device info is found for another DVO port, - * so use mapping assumption we had before BIOS parsing. - */ - if (IS_SDVOB(sdvo_reg)) - return 0x70; - else - return 0x72; -} - -static void -psb_intel_sdvo_connector_init(struct psb_intel_sdvo_connector *connector, - struct psb_intel_sdvo *encoder) -{ - drm_connector_init(encoder->base.base.dev, - &connector->base.base, - &psb_intel_sdvo_connector_funcs, - connector->base.base.connector_type); - - drm_connector_helper_add(&connector->base.base, - &psb_intel_sdvo_connector_helper_funcs); - - connector->base.base.interlace_allowed = 0; - connector->base.base.doublescan_allowed = 0; - connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB; - - psb_intel_connector_attach_encoder(&connector->base, &encoder->base); - drm_sysfs_connector_add(&connector->base.base); -} - -static void -psb_intel_sdvo_add_hdmi_properties(struct psb_intel_sdvo_connector *connector) -{ - /* FIXME: We don't support HDMI at the moment - struct drm_device *dev = connector->base.base.dev; - - intel_attach_force_audio_property(&connector->base.base); - if (INTEL_INFO(dev)->gen >= 4 && IS_MOBILE(dev)) - intel_attach_broadcast_rgb_property(&connector->base.base); - */ -} - -static bool -psb_intel_sdvo_dvi_init(struct psb_intel_sdvo *psb_intel_sdvo, int device) -{ - struct drm_encoder *encoder = &psb_intel_sdvo->base.base; - struct drm_connector *connector; - struct psb_intel_connector *intel_connector; - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector; - - psb_intel_sdvo_connector = kzalloc(sizeof(struct psb_intel_sdvo_connector), GFP_KERNEL); - if (!psb_intel_sdvo_connector) - return false; - - if (device == 0) { - psb_intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS0; - psb_intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS0; - } else if (device == 1) { - psb_intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS1; - psb_intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS1; - } - - intel_connector = &psb_intel_sdvo_connector->base; - connector = &intel_connector->base; - // connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; - encoder->encoder_type = DRM_MODE_ENCODER_TMDS; - connector->connector_type = DRM_MODE_CONNECTOR_DVID; - - if (psb_intel_sdvo_is_hdmi_connector(psb_intel_sdvo, device)) { - connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; - psb_intel_sdvo->is_hdmi = true; - } - psb_intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | - (1 << INTEL_ANALOG_CLONE_BIT)); - - psb_intel_sdvo_connector_init(psb_intel_sdvo_connector, psb_intel_sdvo); - if (psb_intel_sdvo->is_hdmi) - psb_intel_sdvo_add_hdmi_properties(psb_intel_sdvo_connector); - - return true; -} - -static bool -psb_intel_sdvo_tv_init(struct psb_intel_sdvo *psb_intel_sdvo, int type) -{ - struct drm_encoder *encoder = &psb_intel_sdvo->base.base; - struct drm_connector *connector; - struct psb_intel_connector *intel_connector; - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector; - - psb_intel_sdvo_connector = kzalloc(sizeof(struct psb_intel_sdvo_connector), GFP_KERNEL); - if (!psb_intel_sdvo_connector) - return false; - - intel_connector = &psb_intel_sdvo_connector->base; - connector = &intel_connector->base; - encoder->encoder_type = DRM_MODE_ENCODER_TVDAC; - connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO; - - psb_intel_sdvo->controlled_output |= type; - psb_intel_sdvo_connector->output_flag = type; - - psb_intel_sdvo->is_tv = true; - psb_intel_sdvo->base.needs_tv_clock = true; - psb_intel_sdvo->base.clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT; - - psb_intel_sdvo_connector_init(psb_intel_sdvo_connector, psb_intel_sdvo); - - if (!psb_intel_sdvo_tv_create_property(psb_intel_sdvo, psb_intel_sdvo_connector, type)) - goto err; - - if (!psb_intel_sdvo_create_enhance_property(psb_intel_sdvo, psb_intel_sdvo_connector)) - goto err; - - return true; - -err: - psb_intel_sdvo_destroy(connector); - return false; -} - -static bool -psb_intel_sdvo_analog_init(struct psb_intel_sdvo *psb_intel_sdvo, int device) -{ - struct drm_encoder *encoder = &psb_intel_sdvo->base.base; - struct drm_connector *connector; - struct psb_intel_connector *intel_connector; - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector; - - psb_intel_sdvo_connector = kzalloc(sizeof(struct psb_intel_sdvo_connector), GFP_KERNEL); - if (!psb_intel_sdvo_connector) - return false; - - intel_connector = &psb_intel_sdvo_connector->base; - connector = &intel_connector->base; - connector->polled = DRM_CONNECTOR_POLL_CONNECT; - encoder->encoder_type = DRM_MODE_ENCODER_DAC; - connector->connector_type = DRM_MODE_CONNECTOR_VGA; - - if (device == 0) { - psb_intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB0; - psb_intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB0; - } else if (device == 1) { - psb_intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB1; - psb_intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1; - } - - psb_intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) | - (1 << INTEL_ANALOG_CLONE_BIT)); - - psb_intel_sdvo_connector_init(psb_intel_sdvo_connector, - psb_intel_sdvo); - return true; -} - -static bool -psb_intel_sdvo_lvds_init(struct psb_intel_sdvo *psb_intel_sdvo, int device) -{ - struct drm_encoder *encoder = &psb_intel_sdvo->base.base; - struct drm_connector *connector; - struct psb_intel_connector *intel_connector; - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector; - - psb_intel_sdvo_connector = kzalloc(sizeof(struct psb_intel_sdvo_connector), GFP_KERNEL); - if (!psb_intel_sdvo_connector) - return false; - - intel_connector = &psb_intel_sdvo_connector->base; - connector = &intel_connector->base; - encoder->encoder_type = DRM_MODE_ENCODER_LVDS; - connector->connector_type = DRM_MODE_CONNECTOR_LVDS; - - if (device == 0) { - psb_intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS0; - psb_intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0; - } else if (device == 1) { - psb_intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS1; - psb_intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; - } - - psb_intel_sdvo->base.clone_mask = ((1 << INTEL_ANALOG_CLONE_BIT) | - (1 << INTEL_SDVO_LVDS_CLONE_BIT)); - - psb_intel_sdvo_connector_init(psb_intel_sdvo_connector, psb_intel_sdvo); - if (!psb_intel_sdvo_create_enhance_property(psb_intel_sdvo, psb_intel_sdvo_connector)) - goto err; - - return true; - -err: - psb_intel_sdvo_destroy(connector); - return false; -} - -static bool -psb_intel_sdvo_output_setup(struct psb_intel_sdvo *psb_intel_sdvo, uint16_t flags) -{ - psb_intel_sdvo->is_tv = false; - psb_intel_sdvo->base.needs_tv_clock = false; - psb_intel_sdvo->is_lvds = false; - - /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/ - - if (flags & SDVO_OUTPUT_TMDS0) - if (!psb_intel_sdvo_dvi_init(psb_intel_sdvo, 0)) - return false; - - if ((flags & SDVO_TMDS_MASK) == SDVO_TMDS_MASK) - if (!psb_intel_sdvo_dvi_init(psb_intel_sdvo, 1)) - return false; - - /* TV has no XXX1 function block */ - if (flags & SDVO_OUTPUT_SVID0) - if (!psb_intel_sdvo_tv_init(psb_intel_sdvo, SDVO_OUTPUT_SVID0)) - return false; - - if (flags & SDVO_OUTPUT_CVBS0) - if (!psb_intel_sdvo_tv_init(psb_intel_sdvo, SDVO_OUTPUT_CVBS0)) - return false; - - if (flags & SDVO_OUTPUT_RGB0) - if (!psb_intel_sdvo_analog_init(psb_intel_sdvo, 0)) - return false; - - if ((flags & SDVO_RGB_MASK) == SDVO_RGB_MASK) - if (!psb_intel_sdvo_analog_init(psb_intel_sdvo, 1)) - return false; - - if (flags & SDVO_OUTPUT_LVDS0) - if (!psb_intel_sdvo_lvds_init(psb_intel_sdvo, 0)) - return false; - - if ((flags & SDVO_LVDS_MASK) == SDVO_LVDS_MASK) - if (!psb_intel_sdvo_lvds_init(psb_intel_sdvo, 1)) - return false; - - if ((flags & SDVO_OUTPUT_MASK) == 0) { - unsigned char bytes[2]; - - psb_intel_sdvo->controlled_output = 0; - memcpy(bytes, &psb_intel_sdvo->caps.output_flags, 2); - DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%02x%02x)\n", - SDVO_NAME(psb_intel_sdvo), - bytes[0], bytes[1]); - return false; - } - psb_intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1); - - return true; -} - -static bool psb_intel_sdvo_tv_create_property(struct psb_intel_sdvo *psb_intel_sdvo, - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector, - int type) -{ - struct drm_device *dev = psb_intel_sdvo->base.base.dev; - struct psb_intel_sdvo_tv_format format; - uint32_t format_map, i; - - if (!psb_intel_sdvo_set_target_output(psb_intel_sdvo, type)) - return false; - - BUILD_BUG_ON(sizeof(format) != 6); - if (!psb_intel_sdvo_get_value(psb_intel_sdvo, - SDVO_CMD_GET_SUPPORTED_TV_FORMATS, - &format, sizeof(format))) - return false; - - memcpy(&format_map, &format, min(sizeof(format_map), sizeof(format))); - - if (format_map == 0) - return false; - - psb_intel_sdvo_connector->format_supported_num = 0; - for (i = 0 ; i < TV_FORMAT_NUM; i++) - if (format_map & (1 << i)) - psb_intel_sdvo_connector->tv_format_supported[psb_intel_sdvo_connector->format_supported_num++] = i; - - - psb_intel_sdvo_connector->tv_format = - drm_property_create(dev, DRM_MODE_PROP_ENUM, - "mode", psb_intel_sdvo_connector->format_supported_num); - if (!psb_intel_sdvo_connector->tv_format) - return false; - - for (i = 0; i < psb_intel_sdvo_connector->format_supported_num; i++) - drm_property_add_enum( - psb_intel_sdvo_connector->tv_format, i, - i, tv_format_names[psb_intel_sdvo_connector->tv_format_supported[i]]); - - psb_intel_sdvo->tv_format_index = psb_intel_sdvo_connector->tv_format_supported[0]; - drm_connector_attach_property(&psb_intel_sdvo_connector->base.base, - psb_intel_sdvo_connector->tv_format, 0); - return true; - -} - -#define ENHANCEMENT(name, NAME) do { \ - if (enhancements.name) { \ - if (!psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_MAX_##NAME, &data_value, 4) || \ - !psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_##NAME, &response, 2)) \ - return false; \ - psb_intel_sdvo_connector->max_##name = data_value[0]; \ - psb_intel_sdvo_connector->cur_##name = response; \ - psb_intel_sdvo_connector->name = \ - drm_property_create_range(dev, 0, #name, 0, data_value[0]); \ - if (!psb_intel_sdvo_connector->name) return false; \ - drm_connector_attach_property(connector, \ - psb_intel_sdvo_connector->name, \ - psb_intel_sdvo_connector->cur_##name); \ - DRM_DEBUG_KMS(#name ": max %d, default %d, current %d\n", \ - data_value[0], data_value[1], response); \ - } \ -} while(0) - -static bool -psb_intel_sdvo_create_enhance_property_tv(struct psb_intel_sdvo *psb_intel_sdvo, - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector, - struct psb_intel_sdvo_enhancements_reply enhancements) -{ - struct drm_device *dev = psb_intel_sdvo->base.base.dev; - struct drm_connector *connector = &psb_intel_sdvo_connector->base.base; - uint16_t response, data_value[2]; - - /* when horizontal overscan is supported, Add the left/right property */ - if (enhancements.overscan_h) { - if (!psb_intel_sdvo_get_value(psb_intel_sdvo, - SDVO_CMD_GET_MAX_OVERSCAN_H, - &data_value, 4)) - return false; - - if (!psb_intel_sdvo_get_value(psb_intel_sdvo, - SDVO_CMD_GET_OVERSCAN_H, - &response, 2)) - return false; - - psb_intel_sdvo_connector->max_hscan = data_value[0]; - psb_intel_sdvo_connector->left_margin = data_value[0] - response; - psb_intel_sdvo_connector->right_margin = psb_intel_sdvo_connector->left_margin; - psb_intel_sdvo_connector->left = - drm_property_create_range(dev, 0, "left_margin", 0, data_value[0]); - if (!psb_intel_sdvo_connector->left) - return false; - - drm_connector_attach_property(connector, - psb_intel_sdvo_connector->left, - psb_intel_sdvo_connector->left_margin); - - psb_intel_sdvo_connector->right = - drm_property_create_range(dev, 0, "right_margin", 0, data_value[0]); - if (!psb_intel_sdvo_connector->right) - return false; - - drm_connector_attach_property(connector, - psb_intel_sdvo_connector->right, - psb_intel_sdvo_connector->right_margin); - DRM_DEBUG_KMS("h_overscan: max %d, " - "default %d, current %d\n", - data_value[0], data_value[1], response); - } - - if (enhancements.overscan_v) { - if (!psb_intel_sdvo_get_value(psb_intel_sdvo, - SDVO_CMD_GET_MAX_OVERSCAN_V, - &data_value, 4)) - return false; - - if (!psb_intel_sdvo_get_value(psb_intel_sdvo, - SDVO_CMD_GET_OVERSCAN_V, - &response, 2)) - return false; - - psb_intel_sdvo_connector->max_vscan = data_value[0]; - psb_intel_sdvo_connector->top_margin = data_value[0] - response; - psb_intel_sdvo_connector->bottom_margin = psb_intel_sdvo_connector->top_margin; - psb_intel_sdvo_connector->top = - drm_property_create_range(dev, 0, "top_margin", 0, data_value[0]); - if (!psb_intel_sdvo_connector->top) - return false; - - drm_connector_attach_property(connector, - psb_intel_sdvo_connector->top, - psb_intel_sdvo_connector->top_margin); - - psb_intel_sdvo_connector->bottom = - drm_property_create_range(dev, 0, "bottom_margin", 0, data_value[0]); - if (!psb_intel_sdvo_connector->bottom) - return false; - - drm_connector_attach_property(connector, - psb_intel_sdvo_connector->bottom, - psb_intel_sdvo_connector->bottom_margin); - DRM_DEBUG_KMS("v_overscan: max %d, " - "default %d, current %d\n", - data_value[0], data_value[1], response); - } - - ENHANCEMENT(hpos, HPOS); - ENHANCEMENT(vpos, VPOS); - ENHANCEMENT(saturation, SATURATION); - ENHANCEMENT(contrast, CONTRAST); - ENHANCEMENT(hue, HUE); - ENHANCEMENT(sharpness, SHARPNESS); - ENHANCEMENT(brightness, BRIGHTNESS); - ENHANCEMENT(flicker_filter, FLICKER_FILTER); - ENHANCEMENT(flicker_filter_adaptive, FLICKER_FILTER_ADAPTIVE); - ENHANCEMENT(flicker_filter_2d, FLICKER_FILTER_2D); - ENHANCEMENT(tv_chroma_filter, TV_CHROMA_FILTER); - ENHANCEMENT(tv_luma_filter, TV_LUMA_FILTER); - - if (enhancements.dot_crawl) { - if (!psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_DOT_CRAWL, &response, 2)) - return false; - - psb_intel_sdvo_connector->max_dot_crawl = 1; - psb_intel_sdvo_connector->cur_dot_crawl = response & 0x1; - psb_intel_sdvo_connector->dot_crawl = - drm_property_create_range(dev, 0, "dot_crawl", 0, 1); - if (!psb_intel_sdvo_connector->dot_crawl) - return false; - - drm_connector_attach_property(connector, - psb_intel_sdvo_connector->dot_crawl, - psb_intel_sdvo_connector->cur_dot_crawl); - DRM_DEBUG_KMS("dot crawl: current %d\n", response); - } - - return true; -} - -static bool -psb_intel_sdvo_create_enhance_property_lvds(struct psb_intel_sdvo *psb_intel_sdvo, - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector, - struct psb_intel_sdvo_enhancements_reply enhancements) -{ - struct drm_device *dev = psb_intel_sdvo->base.base.dev; - struct drm_connector *connector = &psb_intel_sdvo_connector->base.base; - uint16_t response, data_value[2]; - - ENHANCEMENT(brightness, BRIGHTNESS); - - return true; -} -#undef ENHANCEMENT - -static bool psb_intel_sdvo_create_enhance_property(struct psb_intel_sdvo *psb_intel_sdvo, - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector) -{ - union { - struct psb_intel_sdvo_enhancements_reply reply; - uint16_t response; - } enhancements; - - BUILD_BUG_ON(sizeof(enhancements) != 2); - - enhancements.response = 0; - psb_intel_sdvo_get_value(psb_intel_sdvo, - SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS, - &enhancements, sizeof(enhancements)); - if (enhancements.response == 0) { - DRM_DEBUG_KMS("No enhancement is supported\n"); - return true; - } - - if (IS_TV(psb_intel_sdvo_connector)) - return psb_intel_sdvo_create_enhance_property_tv(psb_intel_sdvo, psb_intel_sdvo_connector, enhancements.reply); - else if(IS_LVDS(psb_intel_sdvo_connector)) - return psb_intel_sdvo_create_enhance_property_lvds(psb_intel_sdvo, psb_intel_sdvo_connector, enhancements.reply); - else - return true; -} - -static int psb_intel_sdvo_ddc_proxy_xfer(struct i2c_adapter *adapter, - struct i2c_msg *msgs, - int num) -{ - struct psb_intel_sdvo *sdvo = adapter->algo_data; - - if (!psb_intel_sdvo_set_control_bus_switch(sdvo, sdvo->ddc_bus)) - return -EIO; - - return sdvo->i2c->algo->master_xfer(sdvo->i2c, msgs, num); -} - -static u32 psb_intel_sdvo_ddc_proxy_func(struct i2c_adapter *adapter) -{ - struct psb_intel_sdvo *sdvo = adapter->algo_data; - return sdvo->i2c->algo->functionality(sdvo->i2c); -} - -static const struct i2c_algorithm psb_intel_sdvo_ddc_proxy = { - .master_xfer = psb_intel_sdvo_ddc_proxy_xfer, - .functionality = psb_intel_sdvo_ddc_proxy_func -}; - -static bool -psb_intel_sdvo_init_ddc_proxy(struct psb_intel_sdvo *sdvo, - struct drm_device *dev) -{ - sdvo->ddc.owner = THIS_MODULE; - sdvo->ddc.class = I2C_CLASS_DDC; - snprintf(sdvo->ddc.name, I2C_NAME_SIZE, "SDVO DDC proxy"); - sdvo->ddc.dev.parent = &dev->pdev->dev; - sdvo->ddc.algo_data = sdvo; - sdvo->ddc.algo = &psb_intel_sdvo_ddc_proxy; - - return i2c_add_adapter(&sdvo->ddc) == 0; -} - -bool psb_intel_sdvo_init(struct drm_device *dev, int sdvo_reg) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_encoder *psb_intel_encoder; - struct psb_intel_sdvo *psb_intel_sdvo; - int i; - - psb_intel_sdvo = kzalloc(sizeof(struct psb_intel_sdvo), GFP_KERNEL); - if (!psb_intel_sdvo) - return false; - - psb_intel_sdvo->sdvo_reg = sdvo_reg; - psb_intel_sdvo->slave_addr = psb_intel_sdvo_get_slave_addr(dev, sdvo_reg) >> 1; - psb_intel_sdvo_select_i2c_bus(dev_priv, psb_intel_sdvo, sdvo_reg); - if (!psb_intel_sdvo_init_ddc_proxy(psb_intel_sdvo, dev)) { - kfree(psb_intel_sdvo); - return false; - } - - /* encoder type will be decided later */ - psb_intel_encoder = &psb_intel_sdvo->base; - psb_intel_encoder->type = INTEL_OUTPUT_SDVO; - drm_encoder_init(dev, &psb_intel_encoder->base, &psb_intel_sdvo_enc_funcs, 0); - - /* Read the regs to test if we can talk to the device */ - for (i = 0; i < 0x40; i++) { - u8 byte; - - if (!psb_intel_sdvo_read_byte(psb_intel_sdvo, i, &byte)) { - DRM_DEBUG_KMS("No SDVO device found on SDVO%c\n", - IS_SDVOB(sdvo_reg) ? 'B' : 'C'); - goto err; - } - } - - if (IS_SDVOB(sdvo_reg)) - dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; - else - dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; - - drm_encoder_helper_add(&psb_intel_encoder->base, &psb_intel_sdvo_helper_funcs); - - /* In default case sdvo lvds is false */ - if (!psb_intel_sdvo_get_capabilities(psb_intel_sdvo, &psb_intel_sdvo->caps)) - goto err; - - if (psb_intel_sdvo_output_setup(psb_intel_sdvo, - psb_intel_sdvo->caps.output_flags) != true) { - DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n", - IS_SDVOB(sdvo_reg) ? 'B' : 'C'); - goto err; - } - - psb_intel_sdvo_select_ddc_bus(dev_priv, psb_intel_sdvo, sdvo_reg); - - /* Set the input timing to the screen. Assume always input 0. */ - if (!psb_intel_sdvo_set_target_input(psb_intel_sdvo)) - goto err; - - if (!psb_intel_sdvo_get_input_pixel_clock_range(psb_intel_sdvo, - &psb_intel_sdvo->pixel_clock_min, - &psb_intel_sdvo->pixel_clock_max)) - goto err; - - DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, " - "clock range %dMHz - %dMHz, " - "input 1: %c, input 2: %c, " - "output 1: %c, output 2: %c\n", - SDVO_NAME(psb_intel_sdvo), - psb_intel_sdvo->caps.vendor_id, psb_intel_sdvo->caps.device_id, - psb_intel_sdvo->caps.device_rev_id, - psb_intel_sdvo->pixel_clock_min / 1000, - psb_intel_sdvo->pixel_clock_max / 1000, - (psb_intel_sdvo->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', - (psb_intel_sdvo->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', - /* check currently supported outputs */ - psb_intel_sdvo->caps.output_flags & - (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N', - psb_intel_sdvo->caps.output_flags & - (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); - return true; - -err: - drm_encoder_cleanup(&psb_intel_encoder->base); - i2c_del_adapter(&psb_intel_sdvo->ddc); - kfree(psb_intel_sdvo); - - return false; -} diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo_regs.h b/drivers/gpu/drm/gma500/psb_intel_sdvo_regs.h deleted file mode 100644 index 600e797..0000000 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo_regs.h +++ /dev/null @@ -1,723 +0,0 @@ -/* - * Copyright ? 2006-2007 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Eric Anholt - */ - -/** - * @file SDVO command definitions and structures. - */ - -#define SDVO_OUTPUT_FIRST (0) -#define SDVO_OUTPUT_TMDS0 (1 << 0) -#define SDVO_OUTPUT_RGB0 (1 << 1) -#define SDVO_OUTPUT_CVBS0 (1 << 2) -#define SDVO_OUTPUT_SVID0 (1 << 3) -#define SDVO_OUTPUT_YPRPB0 (1 << 4) -#define SDVO_OUTPUT_SCART0 (1 << 5) -#define SDVO_OUTPUT_LVDS0 (1 << 6) -#define SDVO_OUTPUT_TMDS1 (1 << 8) -#define SDVO_OUTPUT_RGB1 (1 << 9) -#define SDVO_OUTPUT_CVBS1 (1 << 10) -#define SDVO_OUTPUT_SVID1 (1 << 11) -#define SDVO_OUTPUT_YPRPB1 (1 << 12) -#define SDVO_OUTPUT_SCART1 (1 << 13) -#define SDVO_OUTPUT_LVDS1 (1 << 14) -#define SDVO_OUTPUT_LAST (14) - -struct psb_intel_sdvo_caps { - u8 vendor_id; - u8 device_id; - u8 device_rev_id; - u8 sdvo_version_major; - u8 sdvo_version_minor; - unsigned int sdvo_inputs_mask:2; - unsigned int smooth_scaling:1; - unsigned int sharp_scaling:1; - unsigned int up_scaling:1; - unsigned int down_scaling:1; - unsigned int stall_support:1; - unsigned int pad:1; - u16 output_flags; -} __attribute__((packed)); - -/** This matches the EDID DTD structure, more or less */ -struct psb_intel_sdvo_dtd { - struct { - u16 clock; /**< pixel clock, in 10kHz units */ - u8 h_active; /**< lower 8 bits (pixels) */ - u8 h_blank; /**< lower 8 bits (pixels) */ - u8 h_high; /**< upper 4 bits each h_active, h_blank */ - u8 v_active; /**< lower 8 bits (lines) */ - u8 v_blank; /**< lower 8 bits (lines) */ - u8 v_high; /**< upper 4 bits each v_active, v_blank */ - } part1; - - struct { - u8 h_sync_off; /**< lower 8 bits, from hblank start */ - u8 h_sync_width; /**< lower 8 bits (pixels) */ - /** lower 4 bits each vsync offset, vsync width */ - u8 v_sync_off_width; - /** - * 2 high bits of hsync offset, 2 high bits of hsync width, - * bits 4-5 of vsync offset, and 2 high bits of vsync width. - */ - u8 sync_off_width_high; - u8 dtd_flags; - u8 sdvo_flags; - /** bits 6-7 of vsync offset at bits 6-7 */ - u8 v_sync_off_high; - u8 reserved; - } part2; -} __attribute__((packed)); - -struct psb_intel_sdvo_pixel_clock_range { - u16 min; /**< pixel clock, in 10kHz units */ - u16 max; /**< pixel clock, in 10kHz units */ -} __attribute__((packed)); - -struct psb_intel_sdvo_preferred_input_timing_args { - u16 clock; - u16 width; - u16 height; - u8 interlace:1; - u8 scaled:1; - u8 pad:6; -} __attribute__((packed)); - -/* I2C registers for SDVO */ -#define SDVO_I2C_ARG_0 0x07 -#define SDVO_I2C_ARG_1 0x06 -#define SDVO_I2C_ARG_2 0x05 -#define SDVO_I2C_ARG_3 0x04 -#define SDVO_I2C_ARG_4 0x03 -#define SDVO_I2C_ARG_5 0x02 -#define SDVO_I2C_ARG_6 0x01 -#define SDVO_I2C_ARG_7 0x00 -#define SDVO_I2C_OPCODE 0x08 -#define SDVO_I2C_CMD_STATUS 0x09 -#define SDVO_I2C_RETURN_0 0x0a -#define SDVO_I2C_RETURN_1 0x0b -#define SDVO_I2C_RETURN_2 0x0c -#define SDVO_I2C_RETURN_3 0x0d -#define SDVO_I2C_RETURN_4 0x0e -#define SDVO_I2C_RETURN_5 0x0f -#define SDVO_I2C_RETURN_6 0x10 -#define SDVO_I2C_RETURN_7 0x11 -#define SDVO_I2C_VENDOR_BEGIN 0x20 - -/* Status results */ -#define SDVO_CMD_STATUS_POWER_ON 0x0 -#define SDVO_CMD_STATUS_SUCCESS 0x1 -#define SDVO_CMD_STATUS_NOTSUPP 0x2 -#define SDVO_CMD_STATUS_INVALID_ARG 0x3 -#define SDVO_CMD_STATUS_PENDING 0x4 -#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED 0x5 -#define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6 - -/* SDVO commands, argument/result registers */ - -#define SDVO_CMD_RESET 0x01 - -/** Returns a struct intel_sdvo_caps */ -#define SDVO_CMD_GET_DEVICE_CAPS 0x02 - -#define SDVO_CMD_GET_FIRMWARE_REV 0x86 -# define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0 -# define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1 -# define SDVO_DEVICE_FIRMWARE_PATCH SDVO_I2C_RETURN_2 - -/** - * Reports which inputs are trained (managed to sync). - * - * Devices must have trained within 2 vsyncs of a mode change. - */ -#define SDVO_CMD_GET_TRAINED_INPUTS 0x03 -struct psb_intel_sdvo_get_trained_inputs_response { - unsigned int input0_trained:1; - unsigned int input1_trained:1; - unsigned int pad:6; -} __attribute__((packed)); - -/** Returns a struct intel_sdvo_output_flags of active outputs. */ -#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04 - -/** - * Sets the current set of active outputs. - * - * Takes a struct intel_sdvo_output_flags. Must be preceded by a SET_IN_OUT_MAP - * on multi-output devices. - */ -#define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05 - -/** - * Returns the current mapping of SDVO inputs to outputs on the device. - * - * Returns two struct intel_sdvo_output_flags structures. - */ -#define SDVO_CMD_GET_IN_OUT_MAP 0x06 -struct psb_intel_sdvo_in_out_map { - u16 in0, in1; -}; - -/** - * Sets the current mapping of SDVO inputs to outputs on the device. - * - * Takes two struct i380_sdvo_output_flags structures. - */ -#define SDVO_CMD_SET_IN_OUT_MAP 0x07 - -/** - * Returns a struct intel_sdvo_output_flags of attached displays. - */ -#define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b - -/** - * Returns a struct intel_sdvo_ouptut_flags of displays supporting hot plugging. - */ -#define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c - -/** - * Takes a struct intel_sdvo_output_flags. - */ -#define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d - -/** - * Returns a struct intel_sdvo_output_flags of displays with hot plug - * interrupts enabled. - */ -#define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e - -#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f -struct intel_sdvo_get_interrupt_event_source_response { - u16 interrupt_status; - unsigned int ambient_light_interrupt:1; - unsigned int hdmi_audio_encrypt_change:1; - unsigned int pad:6; -} __attribute__((packed)); - -/** - * Selects which input is affected by future input commands. - * - * Commands affected include SET_INPUT_TIMINGS_PART[12], - * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12], - * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS. - */ -#define SDVO_CMD_SET_TARGET_INPUT 0x10 -struct psb_intel_sdvo_set_target_input_args { - unsigned int target_1:1; - unsigned int pad:7; -} __attribute__((packed)); - -/** - * Takes a struct intel_sdvo_output_flags of which outputs are targeted by - * future output commands. - * - * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12], - * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE. - */ -#define SDVO_CMD_SET_TARGET_OUTPUT 0x11 - -#define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12 -#define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13 -#define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14 -#define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15 -#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16 -#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17 -#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18 -#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19 -/* Part 1 */ -# define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0 -# define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1 -# define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2 -# define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3 -# define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4 -# define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5 -# define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6 -# define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7 -/* Part 2 */ -# define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0 -# define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1 -# define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2 -# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3 -# define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4 -# define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7) -# define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5) -# define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3) -# define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1) -# define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5 -# define SDVO_DTD_SDVO_FLAG_STALL (1 << 7) -# define SDVO_DTD_SDVO_FLAG_CENTERED (0 << 6) -# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT (1 << 6) -# define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4) -# define SDVO_DTD_SDVO_FLAG_SCALING_NONE (0 << 4) -# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP (1 << 4) -# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH (2 << 4) -# define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6 - -/** - * Generates a DTD based on the given width, height, and flags. - * - * This will be supported by any device supporting scaling or interlaced - * modes. - */ -#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a -# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0 -# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1 -# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2 -# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3 -# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4 -# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5 -# define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6 -# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0) -# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1) - -#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b -#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c - -/** Returns a struct intel_sdvo_pixel_clock_range */ -#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d -/** Returns a struct intel_sdvo_pixel_clock_range */ -#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e - -/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */ -#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f - -/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ -#define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20 -/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ -#define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21 -# define SDVO_CLOCK_RATE_MULT_1X (1 << 0) -# define SDVO_CLOCK_RATE_MULT_2X (1 << 1) -# define SDVO_CLOCK_RATE_MULT_4X (1 << 3) - -#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 -/** 6 bytes of bit flags for TV formats shared by all TV format functions */ -struct psb_intel_sdvo_tv_format { - unsigned int ntsc_m:1; - unsigned int ntsc_j:1; - unsigned int ntsc_443:1; - unsigned int pal_b:1; - unsigned int pal_d:1; - unsigned int pal_g:1; - unsigned int pal_h:1; - unsigned int pal_i:1; - - unsigned int pal_m:1; - unsigned int pal_n:1; - unsigned int pal_nc:1; - unsigned int pal_60:1; - unsigned int secam_b:1; - unsigned int secam_d:1; - unsigned int secam_g:1; - unsigned int secam_k:1; - - unsigned int secam_k1:1; - unsigned int secam_l:1; - unsigned int secam_60:1; - unsigned int hdtv_std_smpte_240m_1080i_59:1; - unsigned int hdtv_std_smpte_240m_1080i_60:1; - unsigned int hdtv_std_smpte_260m_1080i_59:1; - unsigned int hdtv_std_smpte_260m_1080i_60:1; - unsigned int hdtv_std_smpte_274m_1080i_50:1; - - unsigned int hdtv_std_smpte_274m_1080i_59:1; - unsigned int hdtv_std_smpte_274m_1080i_60:1; - unsigned int hdtv_std_smpte_274m_1080p_23:1; - unsigned int hdtv_std_smpte_274m_1080p_24:1; - unsigned int hdtv_std_smpte_274m_1080p_25:1; - unsigned int hdtv_std_smpte_274m_1080p_29:1; - unsigned int hdtv_std_smpte_274m_1080p_30:1; - unsigned int hdtv_std_smpte_274m_1080p_50:1; - - unsigned int hdtv_std_smpte_274m_1080p_59:1; - unsigned int hdtv_std_smpte_274m_1080p_60:1; - unsigned int hdtv_std_smpte_295m_1080i_50:1; - unsigned int hdtv_std_smpte_295m_1080p_50:1; - unsigned int hdtv_std_smpte_296m_720p_59:1; - unsigned int hdtv_std_smpte_296m_720p_60:1; - unsigned int hdtv_std_smpte_296m_720p_50:1; - unsigned int hdtv_std_smpte_293m_480p_59:1; - - unsigned int hdtv_std_smpte_170m_480i_59:1; - unsigned int hdtv_std_iturbt601_576i_50:1; - unsigned int hdtv_std_iturbt601_576p_50:1; - unsigned int hdtv_std_eia_7702a_480i_60:1; - unsigned int hdtv_std_eia_7702a_480p_60:1; - unsigned int pad:3; -} __attribute__((packed)); - -#define SDVO_CMD_GET_TV_FORMAT 0x28 - -#define SDVO_CMD_SET_TV_FORMAT 0x29 - -/** Returns the resolutiosn that can be used with the given TV format */ -#define SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT 0x83 -struct psb_intel_sdvo_sdtv_resolution_request { - unsigned int ntsc_m:1; - unsigned int ntsc_j:1; - unsigned int ntsc_443:1; - unsigned int pal_b:1; - unsigned int pal_d:1; - unsigned int pal_g:1; - unsigned int pal_h:1; - unsigned int pal_i:1; - - unsigned int pal_m:1; - unsigned int pal_n:1; - unsigned int pal_nc:1; - unsigned int pal_60:1; - unsigned int secam_b:1; - unsigned int secam_d:1; - unsigned int secam_g:1; - unsigned int secam_k:1; - - unsigned int secam_k1:1; - unsigned int secam_l:1; - unsigned int secam_60:1; - unsigned int pad:5; -} __attribute__((packed)); - -struct psb_intel_sdvo_sdtv_resolution_reply { - unsigned int res_320x200:1; - unsigned int res_320x240:1; - unsigned int res_400x300:1; - unsigned int res_640x350:1; - unsigned int res_640x400:1; - unsigned int res_640x480:1; - unsigned int res_704x480:1; - unsigned int res_704x576:1; - - unsigned int res_720x350:1; - unsigned int res_720x400:1; - unsigned int res_720x480:1; - unsigned int res_720x540:1; - unsigned int res_720x576:1; - unsigned int res_768x576:1; - unsigned int res_800x600:1; - unsigned int res_832x624:1; - - unsigned int res_920x766:1; - unsigned int res_1024x768:1; - unsigned int res_1280x1024:1; - unsigned int pad:5; -} __attribute__((packed)); - -/* Get supported resolution with squire pixel aspect ratio that can be - scaled for the requested HDTV format */ -#define SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT 0x85 - -struct psb_intel_sdvo_hdtv_resolution_request { - unsigned int hdtv_std_smpte_240m_1080i_59:1; - unsigned int hdtv_std_smpte_240m_1080i_60:1; - unsigned int hdtv_std_smpte_260m_1080i_59:1; - unsigned int hdtv_std_smpte_260m_1080i_60:1; - unsigned int hdtv_std_smpte_274m_1080i_50:1; - unsigned int hdtv_std_smpte_274m_1080i_59:1; - unsigned int hdtv_std_smpte_274m_1080i_60:1; - unsigned int hdtv_std_smpte_274m_1080p_23:1; - - unsigned int hdtv_std_smpte_274m_1080p_24:1; - unsigned int hdtv_std_smpte_274m_1080p_25:1; - unsigned int hdtv_std_smpte_274m_1080p_29:1; - unsigned int hdtv_std_smpte_274m_1080p_30:1; - unsigned int hdtv_std_smpte_274m_1080p_50:1; - unsigned int hdtv_std_smpte_274m_1080p_59:1; - unsigned int hdtv_std_smpte_274m_1080p_60:1; - unsigned int hdtv_std_smpte_295m_1080i_50:1; - - unsigned int hdtv_std_smpte_295m_1080p_50:1; - unsigned int hdtv_std_smpte_296m_720p_59:1; - unsigned int hdtv_std_smpte_296m_720p_60:1; - unsigned int hdtv_std_smpte_296m_720p_50:1; - unsigned int hdtv_std_smpte_293m_480p_59:1; - unsigned int hdtv_std_smpte_170m_480i_59:1; - unsigned int hdtv_std_iturbt601_576i_50:1; - unsigned int hdtv_std_iturbt601_576p_50:1; - - unsigned int hdtv_std_eia_7702a_480i_60:1; - unsigned int hdtv_std_eia_7702a_480p_60:1; - unsigned int pad:6; -} __attribute__((packed)); - -struct psb_intel_sdvo_hdtv_resolution_reply { - unsigned int res_640x480:1; - unsigned int res_800x600:1; - unsigned int res_1024x768:1; - unsigned int res_1280x960:1; - unsigned int res_1400x1050:1; - unsigned int res_1600x1200:1; - unsigned int res_1920x1440:1; - unsigned int res_2048x1536:1; - - unsigned int res_2560x1920:1; - unsigned int res_3200x2400:1; - unsigned int res_3840x2880:1; - unsigned int pad1:5; - - unsigned int res_848x480:1; - unsigned int res_1064x600:1; - unsigned int res_1280x720:1; - unsigned int res_1360x768:1; - unsigned int res_1704x960:1; - unsigned int res_1864x1050:1; - unsigned int res_1920x1080:1; - unsigned int res_2128x1200:1; - - unsigned int res_2560x1400:1; - unsigned int res_2728x1536:1; - unsigned int res_3408x1920:1; - unsigned int res_4264x2400:1; - unsigned int res_5120x2880:1; - unsigned int pad2:3; - - unsigned int res_768x480:1; - unsigned int res_960x600:1; - unsigned int res_1152x720:1; - unsigned int res_1124x768:1; - unsigned int res_1536x960:1; - unsigned int res_1680x1050:1; - unsigned int res_1728x1080:1; - unsigned int res_1920x1200:1; - - unsigned int res_2304x1440:1; - unsigned int res_2456x1536:1; - unsigned int res_3072x1920:1; - unsigned int res_3840x2400:1; - unsigned int res_4608x2880:1; - unsigned int pad3:3; - - unsigned int res_1280x1024:1; - unsigned int pad4:7; - - unsigned int res_1280x768:1; - unsigned int pad5:7; -} __attribute__((packed)); - -/* Get supported power state returns info for encoder and monitor, rely on - last SetTargetInput and SetTargetOutput calls */ -#define SDVO_CMD_GET_SUPPORTED_POWER_STATES 0x2a -/* Get power state returns info for encoder and monitor, rely on last - SetTargetInput and SetTargetOutput calls */ -#define SDVO_CMD_GET_POWER_STATE 0x2b -#define SDVO_CMD_GET_ENCODER_POWER_STATE 0x2b -#define SDVO_CMD_SET_ENCODER_POWER_STATE 0x2c -# define SDVO_ENCODER_STATE_ON (1 << 0) -# define SDVO_ENCODER_STATE_STANDBY (1 << 1) -# define SDVO_ENCODER_STATE_SUSPEND (1 << 2) -# define SDVO_ENCODER_STATE_OFF (1 << 3) -# define SDVO_MONITOR_STATE_ON (1 << 4) -# define SDVO_MONITOR_STATE_STANDBY (1 << 5) -# define SDVO_MONITOR_STATE_SUSPEND (1 << 6) -# define SDVO_MONITOR_STATE_OFF (1 << 7) - -#define SDVO_CMD_GET_MAX_PANEL_POWER_SEQUENCING 0x2d -#define SDVO_CMD_GET_PANEL_POWER_SEQUENCING 0x2e -#define SDVO_CMD_SET_PANEL_POWER_SEQUENCING 0x2f -/** - * The panel power sequencing parameters are in units of milliseconds. - * The high fields are bits 8:9 of the 10-bit values. - */ -struct psb_sdvo_panel_power_sequencing { - u8 t0; - u8 t1; - u8 t2; - u8 t3; - u8 t4; - - unsigned int t0_high:2; - unsigned int t1_high:2; - unsigned int t2_high:2; - unsigned int t3_high:2; - - unsigned int t4_high:2; - unsigned int pad:6; -} __attribute__((packed)); - -#define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL 0x30 -struct sdvo_max_backlight_reply { - u8 max_value; - u8 default_value; -} __attribute__((packed)); - -#define SDVO_CMD_GET_BACKLIGHT_LEVEL 0x31 -#define SDVO_CMD_SET_BACKLIGHT_LEVEL 0x32 - -#define SDVO_CMD_GET_AMBIENT_LIGHT 0x33 -struct sdvo_get_ambient_light_reply { - u16 trip_low; - u16 trip_high; - u16 value; -} __attribute__((packed)); -#define SDVO_CMD_SET_AMBIENT_LIGHT 0x34 -struct sdvo_set_ambient_light_reply { - u16 trip_low; - u16 trip_high; - unsigned int enable:1; - unsigned int pad:7; -} __attribute__((packed)); - -/* Set display power state */ -#define SDVO_CMD_SET_DISPLAY_POWER_STATE 0x7d -# define SDVO_DISPLAY_STATE_ON (1 << 0) -# define SDVO_DISPLAY_STATE_STANDBY (1 << 1) -# define SDVO_DISPLAY_STATE_SUSPEND (1 << 2) -# define SDVO_DISPLAY_STATE_OFF (1 << 3) - -#define SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS 0x84 -struct psb_intel_sdvo_enhancements_reply { - unsigned int flicker_filter:1; - unsigned int flicker_filter_adaptive:1; - unsigned int flicker_filter_2d:1; - unsigned int saturation:1; - unsigned int hue:1; - unsigned int brightness:1; - unsigned int contrast:1; - unsigned int overscan_h:1; - - unsigned int overscan_v:1; - unsigned int hpos:1; - unsigned int vpos:1; - unsigned int sharpness:1; - unsigned int dot_crawl:1; - unsigned int dither:1; - unsigned int tv_chroma_filter:1; - unsigned int tv_luma_filter:1; -} __attribute__((packed)); - -/* Picture enhancement limits below are dependent on the current TV format, - * and thus need to be queried and set after it. - */ -#define SDVO_CMD_GET_MAX_FLICKER_FILTER 0x4d -#define SDVO_CMD_GET_MAX_FLICKER_FILTER_ADAPTIVE 0x7b -#define SDVO_CMD_GET_MAX_FLICKER_FILTER_2D 0x52 -#define SDVO_CMD_GET_MAX_SATURATION 0x55 -#define SDVO_CMD_GET_MAX_HUE 0x58 -#define SDVO_CMD_GET_MAX_BRIGHTNESS 0x5b -#define SDVO_CMD_GET_MAX_CONTRAST 0x5e -#define SDVO_CMD_GET_MAX_OVERSCAN_H 0x61 -#define SDVO_CMD_GET_MAX_OVERSCAN_V 0x64 -#define SDVO_CMD_GET_MAX_HPOS 0x67 -#define SDVO_CMD_GET_MAX_VPOS 0x6a -#define SDVO_CMD_GET_MAX_SHARPNESS 0x6d -#define SDVO_CMD_GET_MAX_TV_CHROMA_FILTER 0x74 -#define SDVO_CMD_GET_MAX_TV_LUMA_FILTER 0x77 -struct psb_intel_sdvo_enhancement_limits_reply { - u16 max_value; - u16 default_value; -} __attribute__((packed)); - -#define SDVO_CMD_GET_LVDS_PANEL_INFORMATION 0x7f -#define SDVO_CMD_SET_LVDS_PANEL_INFORMATION 0x80 -# define SDVO_LVDS_COLOR_DEPTH_18 (0 << 0) -# define SDVO_LVDS_COLOR_DEPTH_24 (1 << 0) -# define SDVO_LVDS_CONNECTOR_SPWG (0 << 2) -# define SDVO_LVDS_CONNECTOR_OPENLDI (1 << 2) -# define SDVO_LVDS_SINGLE_CHANNEL (0 << 4) -# define SDVO_LVDS_DUAL_CHANNEL (1 << 4) - -#define SDVO_CMD_GET_FLICKER_FILTER 0x4e -#define SDVO_CMD_SET_FLICKER_FILTER 0x4f -#define SDVO_CMD_GET_FLICKER_FILTER_ADAPTIVE 0x50 -#define SDVO_CMD_SET_FLICKER_FILTER_ADAPTIVE 0x51 -#define SDVO_CMD_GET_FLICKER_FILTER_2D 0x53 -#define SDVO_CMD_SET_FLICKER_FILTER_2D 0x54 -#define SDVO_CMD_GET_SATURATION 0x56 -#define SDVO_CMD_SET_SATURATION 0x57 -#define SDVO_CMD_GET_HUE 0x59 -#define SDVO_CMD_SET_HUE 0x5a -#define SDVO_CMD_GET_BRIGHTNESS 0x5c -#define SDVO_CMD_SET_BRIGHTNESS 0x5d -#define SDVO_CMD_GET_CONTRAST 0x5f -#define SDVO_CMD_SET_CONTRAST 0x60 -#define SDVO_CMD_GET_OVERSCAN_H 0x62 -#define SDVO_CMD_SET_OVERSCAN_H 0x63 -#define SDVO_CMD_GET_OVERSCAN_V 0x65 -#define SDVO_CMD_SET_OVERSCAN_V 0x66 -#define SDVO_CMD_GET_HPOS 0x68 -#define SDVO_CMD_SET_HPOS 0x69 -#define SDVO_CMD_GET_VPOS 0x6b -#define SDVO_CMD_SET_VPOS 0x6c -#define SDVO_CMD_GET_SHARPNESS 0x6e -#define SDVO_CMD_SET_SHARPNESS 0x6f -#define SDVO_CMD_GET_TV_CHROMA_FILTER 0x75 -#define SDVO_CMD_SET_TV_CHROMA_FILTER 0x76 -#define SDVO_CMD_GET_TV_LUMA_FILTER 0x78 -#define SDVO_CMD_SET_TV_LUMA_FILTER 0x79 -struct psb_intel_sdvo_enhancements_arg { - u16 value; -}__attribute__((packed)); - -#define SDVO_CMD_GET_DOT_CRAWL 0x70 -#define SDVO_CMD_SET_DOT_CRAWL 0x71 -# define SDVO_DOT_CRAWL_ON (1 << 0) -# define SDVO_DOT_CRAWL_DEFAULT_ON (1 << 1) - -#define SDVO_CMD_GET_DITHER 0x72 -#define SDVO_CMD_SET_DITHER 0x73 -# define SDVO_DITHER_ON (1 << 0) -# define SDVO_DITHER_DEFAULT_ON (1 << 1) - -#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a -# define SDVO_CONTROL_BUS_PROM (1 << 0) -# define SDVO_CONTROL_BUS_DDC1 (1 << 1) -# define SDVO_CONTROL_BUS_DDC2 (1 << 2) -# define SDVO_CONTROL_BUS_DDC3 (1 << 3) - -/* HDMI op codes */ -#define SDVO_CMD_GET_SUPP_ENCODE 0x9d -#define SDVO_CMD_GET_ENCODE 0x9e -#define SDVO_CMD_SET_ENCODE 0x9f - #define SDVO_ENCODE_DVI 0x0 - #define SDVO_ENCODE_HDMI 0x1 -#define SDVO_CMD_SET_PIXEL_REPLI 0x8b -#define SDVO_CMD_GET_PIXEL_REPLI 0x8c -#define SDVO_CMD_GET_COLORIMETRY_CAP 0x8d -#define SDVO_CMD_SET_COLORIMETRY 0x8e - #define SDVO_COLORIMETRY_RGB256 0x0 - #define SDVO_COLORIMETRY_RGB220 0x1 - #define SDVO_COLORIMETRY_YCrCb422 0x3 - #define SDVO_COLORIMETRY_YCrCb444 0x4 -#define SDVO_CMD_GET_COLORIMETRY 0x8f -#define SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER 0x90 -#define SDVO_CMD_SET_AUDIO_STAT 0x91 -#define SDVO_CMD_GET_AUDIO_STAT 0x92 -#define SDVO_CMD_SET_HBUF_INDEX 0x93 -#define SDVO_CMD_GET_HBUF_INDEX 0x94 -#define SDVO_CMD_GET_HBUF_INFO 0x95 -#define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 -#define SDVO_CMD_GET_HBUF_AV_SPLIT 0x97 -#define SDVO_CMD_SET_HBUF_DATA 0x98 -#define SDVO_CMD_GET_HBUF_DATA 0x99 -#define SDVO_CMD_SET_HBUF_TXRATE 0x9a -#define SDVO_CMD_GET_HBUF_TXRATE 0x9b - #define SDVO_HBUF_TX_DISABLED (0 << 6) - #define SDVO_HBUF_TX_ONCE (2 << 6) - #define SDVO_HBUF_TX_VSYNC (3 << 6) -#define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c -#define SDVO_NEED_TO_STALL (1 << 7) - -struct psb_intel_sdvo_encode { - u8 dvi_rev; - u8 hdmi_rev; -} __attribute__ ((packed)); diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c deleted file mode 100644 index 1869586..0000000 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ /dev/null @@ -1,622 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to - * develop this driver. - * - **************************************************************************/ -/* - */ - -#include -#include "psb_drv.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include "power.h" -#include "psb_irq.h" -#include "mdfld_output.h" - -/* - * inline functions - */ - -static inline u32 -psb_pipestat(int pipe) -{ - if (pipe == 0) - return PIPEASTAT; - if (pipe == 1) - return PIPEBSTAT; - if (pipe == 2) - return PIPECSTAT; - BUG(); -} - -static inline u32 -mid_pipe_event(int pipe) -{ - if (pipe == 0) - return _PSB_PIPEA_EVENT_FLAG; - if (pipe == 1) - return _MDFLD_PIPEB_EVENT_FLAG; - if (pipe == 2) - return _MDFLD_PIPEC_EVENT_FLAG; - BUG(); -} - -static inline u32 -mid_pipe_vsync(int pipe) -{ - if (pipe == 0) - return _PSB_VSYNC_PIPEA_FLAG; - if (pipe == 1) - return _PSB_VSYNC_PIPEB_FLAG; - if (pipe == 2) - return _MDFLD_PIPEC_VBLANK_FLAG; - BUG(); -} - -static inline u32 -mid_pipeconf(int pipe) -{ - if (pipe == 0) - return PIPEACONF; - if (pipe == 1) - return PIPEBCONF; - if (pipe == 2) - return PIPECCONF; - BUG(); -} - -void -psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) -{ - if ((dev_priv->pipestat[pipe] & mask) != mask) { - u32 reg = psb_pipestat(pipe); - dev_priv->pipestat[pipe] |= mask; - /* Enable the interrupt, clear any pending status */ - if (gma_power_begin(dev_priv->dev, false)) { - u32 writeVal = PSB_RVDC32(reg); - writeVal |= (mask | (mask >> 16)); - PSB_WVDC32(writeVal, reg); - (void) PSB_RVDC32(reg); - gma_power_end(dev_priv->dev); - } - } -} - -void -psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) -{ - if ((dev_priv->pipestat[pipe] & mask) != 0) { - u32 reg = psb_pipestat(pipe); - dev_priv->pipestat[pipe] &= ~mask; - if (gma_power_begin(dev_priv->dev, false)) { - u32 writeVal = PSB_RVDC32(reg); - writeVal &= ~mask; - PSB_WVDC32(writeVal, reg); - (void) PSB_RVDC32(reg); - gma_power_end(dev_priv->dev); - } - } -} - -static void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe) -{ - if (gma_power_begin(dev_priv->dev, false)) { - u32 pipe_event = mid_pipe_event(pipe); - dev_priv->vdc_irq_mask |= pipe_event; - PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); - PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); - gma_power_end(dev_priv->dev); - } -} - -static void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe) -{ - if (dev_priv->pipestat[pipe] == 0) { - if (gma_power_begin(dev_priv->dev, false)) { - u32 pipe_event = mid_pipe_event(pipe); - dev_priv->vdc_irq_mask &= ~pipe_event; - PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); - PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); - gma_power_end(dev_priv->dev); - } - } -} - -/** - * Display controller interrupt handler for pipe event. - * - */ -static void mid_pipe_event_handler(struct drm_device *dev, int pipe) -{ - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - - uint32_t pipe_stat_val = 0; - uint32_t pipe_stat_reg = psb_pipestat(pipe); - uint32_t pipe_enable = dev_priv->pipestat[pipe]; - uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16; - uint32_t pipe_clear; - uint32_t i = 0; - - spin_lock(&dev_priv->irqmask_lock); - - pipe_stat_val = PSB_RVDC32(pipe_stat_reg); - pipe_stat_val &= pipe_enable | pipe_status; - pipe_stat_val &= pipe_stat_val >> 16; - - spin_unlock(&dev_priv->irqmask_lock); - - /* Clear the 2nd level interrupt status bits - * Sometimes the bits are very sticky so we repeat until they unstick */ - for (i = 0; i < 0xffff; i++) { - PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg); - pipe_clear = PSB_RVDC32(pipe_stat_reg) & pipe_status; - - if (pipe_clear == 0) - break; - } - - if (pipe_clear) - dev_err(dev->dev, - "%s, can't clear status bits for pipe %d, its value = 0x%x.\n", - __func__, pipe, PSB_RVDC32(pipe_stat_reg)); - - if (pipe_stat_val & PIPE_VBLANK_STATUS) - drm_handle_vblank(dev, pipe); - - if (pipe_stat_val & PIPE_TE_STATUS) - drm_handle_vblank(dev, pipe); -} - -/* - * Display controller interrupt handler. - */ -static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) -{ - if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG) - mid_pipe_event_handler(dev, 0); - - if (vdc_stat & _PSB_VSYNC_PIPEB_FLAG) - mid_pipe_event_handler(dev, 1); -} - -irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) -{ - struct drm_device *dev = (struct drm_device *) arg; - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - - uint32_t vdc_stat, dsp_int = 0, sgx_int = 0; - int handled = 0; - - spin_lock(&dev_priv->irqmask_lock); - - vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R); - - if (vdc_stat & _PSB_PIPE_EVENT_FLAG) - dsp_int = 1; - - /* FIXME: Handle Medfield - if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG) - dsp_int = 1; - */ - - if (vdc_stat & _PSB_IRQ_SGX_FLAG) - sgx_int = 1; - - vdc_stat &= dev_priv->vdc_irq_mask; - spin_unlock(&dev_priv->irqmask_lock); - - if (dsp_int && gma_power_is_on(dev)) { - psb_vdc_interrupt(dev, vdc_stat); - handled = 1; - } - - if (sgx_int) { - /* Not expected - we have it masked, shut it up */ - u32 s, s2; - s = PSB_RSGX32(PSB_CR_EVENT_STATUS); - s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2); - PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR); - PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2); - /* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but - we may as well poll even if we add that ! */ - handled = 1; - } - - PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R); - (void) PSB_RVDC32(PSB_INT_IDENTITY_R); - DRM_READMEMORYBARRIER(); - - if (!handled) - return IRQ_NONE; - - return IRQ_HANDLED; -} - -void psb_irq_preinstall(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - - if (gma_power_is_on(dev)) - PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - if (dev->vblank_enabled[0]) - dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; - if (dev->vblank_enabled[1]) - dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; - - /* FIXME: Handle Medfield irq mask - if (dev->vblank_enabled[1]) - dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG; - if (dev->vblank_enabled[2]) - dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; - */ - - /* This register is safe even if display island is off */ - PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); - spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); -} - -int psb_irq_postinstall(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - - /* This register is safe even if display island is off */ - PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); - PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - - if (dev->vblank_enabled[0]) - psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - else - psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - - if (dev->vblank_enabled[1]) - psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); - else - psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); - - if (dev->vblank_enabled[2]) - psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); - else - psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); - - spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); - return 0; -} - -void psb_irq_uninstall(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - - PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - - if (dev->vblank_enabled[0]) - psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - - if (dev->vblank_enabled[1]) - psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); - - if (dev->vblank_enabled[2]) - psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); - - dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | - _PSB_IRQ_MSVDX_FLAG | - _LNC_IRQ_TOPAZ_FLAG; - - /* These two registers are safe even if display island is off */ - PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); - PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); - - wmb(); - - /* This register is safe even if display island is off */ - PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R); - spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); -} - -void psb_irq_turn_on_dpst(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - u32 hist_reg; - u32 pwm_reg; - - if (gma_power_begin(dev, false)) { - PSB_WVDC32(1 << 31, HISTOGRAM_LOGIC_CONTROL); - hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL); - PSB_WVDC32(1 << 31, HISTOGRAM_INT_CONTROL); - hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); - - PSB_WVDC32(0x80010100, PWM_CONTROL_LOGIC); - pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); - PSB_WVDC32(pwm_reg | PWM_PHASEIN_ENABLE - | PWM_PHASEIN_INT_ENABLE, - PWM_CONTROL_LOGIC); - pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); - - psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); - - hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); - PSB_WVDC32(hist_reg | HISTOGRAM_INT_CTRL_CLEAR, - HISTOGRAM_INT_CONTROL); - pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); - PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE, - PWM_CONTROL_LOGIC); - - gma_power_end(dev); - } -} - -int psb_irq_enable_dpst(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - - /* enable DPST */ - mid_enable_pipe_event(dev_priv, 0); - psb_irq_turn_on_dpst(dev); - - spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); - return 0; -} - -void psb_irq_turn_off_dpst(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - u32 hist_reg; - u32 pwm_reg; - - if (gma_power_begin(dev, false)) { - PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL); - hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); - - psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); - - pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); - PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE), - PWM_CONTROL_LOGIC); - pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); - - gma_power_end(dev); - } -} - -int psb_irq_disable_dpst(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - - mid_disable_pipe_event(dev_priv, 0); - psb_irq_turn_off_dpst(dev); - - spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); - - return 0; -} - -#ifdef PSB_FIXME -static int psb_vblank_do_wait(struct drm_device *dev, - unsigned int *sequence, atomic_t *counter) -{ - unsigned int cur_vblank; - int ret = 0; - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(counter)) - - *sequence) <= (1 << 23))); - *sequence = cur_vblank; - - return ret; -} -#endif - -/* - * It is used to enable VBLANK interrupt - */ -int psb_enable_vblank(struct drm_device *dev, int pipe) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - unsigned long irqflags; - uint32_t reg_val = 0; - uint32_t pipeconf_reg = mid_pipeconf(pipe); - - /* Medfield is different - we should perhaps extract out vblank - and blacklight etc ops */ - if (IS_MFLD(dev)) - return mdfld_enable_te(dev, pipe); - - if (gma_power_begin(dev, false)) { - reg_val = REG_READ(pipeconf_reg); - gma_power_end(dev); - } - - if (!(reg_val & PIPEACONF_ENABLE)) - return -EINVAL; - - spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - - if (pipe == 0) - dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; - else if (pipe == 1) - dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; - - PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); - PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); - psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); - - spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); - - return 0; -} - -/* - * It is used to disable VBLANK interrupt - */ -void psb_disable_vblank(struct drm_device *dev, int pipe) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - unsigned long irqflags; - - if (IS_MFLD(dev)) - mdfld_disable_te(dev, pipe); - spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - - if (pipe == 0) - dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEA_FLAG; - else if (pipe == 1) - dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEB_FLAG; - - PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); - PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); - psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); - - spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); -} - -/* - * It is used to enable TE interrupt - */ -int mdfld_enable_te(struct drm_device *dev, int pipe) -{ - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - unsigned long irqflags; - uint32_t reg_val = 0; - uint32_t pipeconf_reg = mid_pipeconf(pipe); - - if (gma_power_begin(dev, false)) { - reg_val = REG_READ(pipeconf_reg); - gma_power_end(dev); - } - - if (!(reg_val & PIPEACONF_ENABLE)) - return -EINVAL; - - spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - - mid_enable_pipe_event(dev_priv, pipe); - psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE); - - spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); - - return 0; -} - -/* - * It is used to disable TE interrupt - */ -void mdfld_disable_te(struct drm_device *dev, int pipe) -{ - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - unsigned long irqflags; - - if (!dev_priv->dsr_enable) - return; - - spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - - mid_disable_pipe_event(dev_priv, pipe); - psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE); - - spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); -} - -/* Called from drm generic code, passed a 'crtc', which - * we use as a pipe index - */ -u32 psb_get_vblank_counter(struct drm_device *dev, int pipe) -{ - uint32_t high_frame = PIPEAFRAMEHIGH; - uint32_t low_frame = PIPEAFRAMEPIXEL; - uint32_t pipeconf_reg = PIPEACONF; - uint32_t reg_val = 0; - uint32_t high1 = 0, high2 = 0, low = 0, count = 0; - - switch (pipe) { - case 0: - break; - case 1: - high_frame = PIPEBFRAMEHIGH; - low_frame = PIPEBFRAMEPIXEL; - pipeconf_reg = PIPEBCONF; - break; - case 2: - high_frame = PIPECFRAMEHIGH; - low_frame = PIPECFRAMEPIXEL; - pipeconf_reg = PIPECCONF; - break; - default: - dev_err(dev->dev, "%s, invalid pipe.\n", __func__); - return 0; - } - - if (!gma_power_begin(dev, false)) - return 0; - - reg_val = REG_READ(pipeconf_reg); - - if (!(reg_val & PIPEACONF_ENABLE)) { - dev_err(dev->dev, "trying to get vblank count for disabled pipe %d\n", - pipe); - goto psb_get_vblank_counter_exit; - } - - /* - * High & low register fields aren't synchronized, so make sure - * we get a low value that's stable across two reads of the high - * register. - */ - do { - high1 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> - PIPE_FRAME_HIGH_SHIFT); - low = ((REG_READ(low_frame) & PIPE_FRAME_LOW_MASK) >> - PIPE_FRAME_LOW_SHIFT); - high2 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> - PIPE_FRAME_HIGH_SHIFT); - } while (high1 != high2); - - count = (high1 << 8) | low; - -psb_get_vblank_counter_exit: - - gma_power_end(dev); - - return count; -} - diff --git a/drivers/gpu/drm/gma500/psb_irq.h b/drivers/gpu/drm/gma500/psb_irq.h deleted file mode 100644 index 603045b..0000000 --- a/drivers/gpu/drm/gma500/psb_irq.h +++ /dev/null @@ -1,47 +0,0 @@ -/************************************************************************** - * Copyright (c) 2009-2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: - * Benjamin Defnet - * Rajesh Poornachandran - * - **************************************************************************/ - -#ifndef _SYSIRQ_H_ -#define _SYSIRQ_H_ - -#include - -bool sysirq_init(struct drm_device *dev); -void sysirq_uninit(struct drm_device *dev); - -void psb_irq_preinstall(struct drm_device *dev); -int psb_irq_postinstall(struct drm_device *dev); -void psb_irq_uninstall(struct drm_device *dev); -irqreturn_t psb_irq_handler(DRM_IRQ_ARGS); - -int psb_irq_enable_dpst(struct drm_device *dev); -int psb_irq_disable_dpst(struct drm_device *dev); -void psb_irq_turn_on_dpst(struct drm_device *dev); -void psb_irq_turn_off_dpst(struct drm_device *dev); -int psb_enable_vblank(struct drm_device *dev, int pipe); -void psb_disable_vblank(struct drm_device *dev, int pipe); -u32 psb_get_vblank_counter(struct drm_device *dev, int pipe); - -int mdfld_enable_te(struct drm_device *dev, int pipe); -void mdfld_disable_te(struct drm_device *dev, int pipe); -#endif /* _SYSIRQ_H_ */ diff --git a/drivers/gpu/drm/gma500/psb_lid.c b/drivers/gpu/drm/gma500/psb_lid.c deleted file mode 100644 index b867aab..0000000 --- a/drivers/gpu/drm/gma500/psb_lid.c +++ /dev/null @@ -1,88 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Authors: Thomas Hellstrom - **************************************************************************/ - -#include -#include "psb_drv.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include - -static void psb_lid_timer_func(unsigned long data) -{ - struct drm_psb_private * dev_priv = (struct drm_psb_private *)data; - struct drm_device *dev = (struct drm_device *)dev_priv->dev; - struct timer_list *lid_timer = &dev_priv->lid_timer; - unsigned long irq_flags; - u32 *lid_state = dev_priv->lid_state; - u32 pp_status; - - if (readl(lid_state) == dev_priv->lid_last_state) - goto lid_timer_schedule; - - if ((readl(lid_state)) & 0x01) { - /*lid state is open*/ - REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON); - do { - pp_status = REG_READ(PP_STATUS); - } while ((pp_status & PP_ON) == 0); - - /*FIXME: should be backlight level before*/ - psb_intel_lvds_set_brightness(dev, 100); - } else { - psb_intel_lvds_set_brightness(dev, 0); - - REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON); - do { - pp_status = REG_READ(PP_STATUS); - } while ((pp_status & PP_ON) == 0); - } - dev_priv->lid_last_state = readl(lid_state); - -lid_timer_schedule: - spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); - if (!timer_pending(lid_timer)) { - lid_timer->expires = jiffies + PSB_LID_DELAY; - add_timer(lid_timer); - } - spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); -} - -void psb_lid_timer_init(struct drm_psb_private *dev_priv) -{ - struct timer_list *lid_timer = &dev_priv->lid_timer; - unsigned long irq_flags; - - spin_lock_init(&dev_priv->lid_lock); - spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); - - init_timer(lid_timer); - - lid_timer->data = (unsigned long)dev_priv; - lid_timer->function = psb_lid_timer_func; - lid_timer->expires = jiffies + PSB_LID_DELAY; - - add_timer(lid_timer); - spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); -} - -void psb_lid_timer_takedown(struct drm_psb_private *dev_priv) -{ - del_timer_sync(&dev_priv->lid_timer); -} - diff --git a/drivers/gpu/drm/gma500/psb_reg.h b/drivers/gpu/drm/gma500/psb_reg.h deleted file mode 100644 index b81c7c1..0000000 --- a/drivers/gpu/drm/gma500/psb_reg.h +++ /dev/null @@ -1,582 +0,0 @@ -/************************************************************************** - * - * Copyright (c) (2005-2007) Imagination Technologies Limited. - * Copyright (c) 2007, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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.. - * - **************************************************************************/ - -#ifndef _PSB_REG_H_ -#define _PSB_REG_H_ - -#define PSB_CR_CLKGATECTL 0x0000 -#define _PSB_C_CLKGATECTL_AUTO_MAN_REG (1 << 24) -#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT (20) -#define _PSB_C_CLKGATECTL_USE_CLKG_MASK (0x3 << 20) -#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT (16) -#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK (0x3 << 16) -#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT (12) -#define _PSB_C_CLKGATECTL_TA_CLKG_MASK (0x3 << 12) -#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT (8) -#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK (0x3 << 8) -#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT (4) -#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK (0x3 << 4) -#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT (0) -#define _PSB_C_CLKGATECTL_2D_CLKG_MASK (0x3 << 0) -#define _PSB_C_CLKGATECTL_CLKG_ENABLED (0) -#define _PSB_C_CLKGATECTL_CLKG_DISABLED (1) -#define _PSB_C_CLKGATECTL_CLKG_AUTO (2) - -#define PSB_CR_CORE_ID 0x0010 -#define _PSB_CC_ID_ID_SHIFT (16) -#define _PSB_CC_ID_ID_MASK (0xFFFF << 16) -#define _PSB_CC_ID_CONFIG_SHIFT (0) -#define _PSB_CC_ID_CONFIG_MASK (0xFFFF << 0) - -#define PSB_CR_CORE_REVISION 0x0014 -#define _PSB_CC_REVISION_DESIGNER_SHIFT (24) -#define _PSB_CC_REVISION_DESIGNER_MASK (0xFF << 24) -#define _PSB_CC_REVISION_MAJOR_SHIFT (16) -#define _PSB_CC_REVISION_MAJOR_MASK (0xFF << 16) -#define _PSB_CC_REVISION_MINOR_SHIFT (8) -#define _PSB_CC_REVISION_MINOR_MASK (0xFF << 8) -#define _PSB_CC_REVISION_MAINTENANCE_SHIFT (0) -#define _PSB_CC_REVISION_MAINTENANCE_MASK (0xFF << 0) - -#define PSB_CR_DESIGNER_REV_FIELD1 0x0018 - -#define PSB_CR_SOFT_RESET 0x0080 -#define _PSB_CS_RESET_TSP_RESET (1 << 6) -#define _PSB_CS_RESET_ISP_RESET (1 << 5) -#define _PSB_CS_RESET_USE_RESET (1 << 4) -#define _PSB_CS_RESET_TA_RESET (1 << 3) -#define _PSB_CS_RESET_DPM_RESET (1 << 2) -#define _PSB_CS_RESET_TWOD_RESET (1 << 1) -#define _PSB_CS_RESET_BIF_RESET (1 << 0) - -#define PSB_CR_DESIGNER_REV_FIELD2 0x001C - -#define PSB_CR_EVENT_HOST_ENABLE2 0x0110 - -#define PSB_CR_EVENT_STATUS2 0x0118 - -#define PSB_CR_EVENT_HOST_CLEAR2 0x0114 -#define _PSB_CE2_BIF_REQUESTER_FAULT (1 << 4) - -#define PSB_CR_EVENT_STATUS 0x012C - -#define PSB_CR_EVENT_HOST_ENABLE 0x0130 - -#define PSB_CR_EVENT_HOST_CLEAR 0x0134 -#define _PSB_CE_MASTER_INTERRUPT (1 << 31) -#define _PSB_CE_TA_DPM_FAULT (1 << 28) -#define _PSB_CE_TWOD_COMPLETE (1 << 27) -#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS (1 << 25) -#define _PSB_CE_DPM_TA_MEM_FREE (1 << 24) -#define _PSB_CE_PIXELBE_END_RENDER (1 << 18) -#define _PSB_CE_SW_EVENT (1 << 14) -#define _PSB_CE_TA_FINISHED (1 << 13) -#define _PSB_CE_TA_TERMINATE (1 << 12) -#define _PSB_CE_DPM_REACHED_MEM_THRESH (1 << 3) -#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL (1 << 2) -#define _PSB_CE_DPM_OUT_OF_MEMORY_MT (1 << 1) -#define _PSB_CE_DPM_3D_MEM_FREE (1 << 0) - - -#define PSB_USE_OFFSET_MASK 0x0007FFFF -#define PSB_USE_OFFSET_SIZE (PSB_USE_OFFSET_MASK + 1) -#define PSB_CR_USE_CODE_BASE0 0x0A0C -#define PSB_CR_USE_CODE_BASE1 0x0A10 -#define PSB_CR_USE_CODE_BASE2 0x0A14 -#define PSB_CR_USE_CODE_BASE3 0x0A18 -#define PSB_CR_USE_CODE_BASE4 0x0A1C -#define PSB_CR_USE_CODE_BASE5 0x0A20 -#define PSB_CR_USE_CODE_BASE6 0x0A24 -#define PSB_CR_USE_CODE_BASE7 0x0A28 -#define PSB_CR_USE_CODE_BASE8 0x0A2C -#define PSB_CR_USE_CODE_BASE9 0x0A30 -#define PSB_CR_USE_CODE_BASE10 0x0A34 -#define PSB_CR_USE_CODE_BASE11 0x0A38 -#define PSB_CR_USE_CODE_BASE12 0x0A3C -#define PSB_CR_USE_CODE_BASE13 0x0A40 -#define PSB_CR_USE_CODE_BASE14 0x0A44 -#define PSB_CR_USE_CODE_BASE15 0x0A48 -#define PSB_CR_USE_CODE_BASE(_i) (0x0A0C + ((_i) << 2)) -#define _PSB_CUC_BASE_DM_SHIFT (25) -#define _PSB_CUC_BASE_DM_MASK (0x3 << 25) -#define _PSB_CUC_BASE_ADDR_SHIFT (0) /* 1024-bit aligned address? */ -#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT (7) -#define _PSB_CUC_BASE_ADDR_MASK (0x1FFFFFF << 0) -#define _PSB_CUC_DM_VERTEX (0) -#define _PSB_CUC_DM_PIXEL (1) -#define _PSB_CUC_DM_RESERVED (2) -#define _PSB_CUC_DM_EDM (3) - -#define PSB_CR_PDS_EXEC_BASE 0x0AB8 -#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT (20) /* 1MB aligned address */ -#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT (20) - -#define PSB_CR_EVENT_KICKER 0x0AC4 -#define _PSB_CE_KICKER_ADDRESS_SHIFT (4) /* 128-bit aligned address */ - -#define PSB_CR_EVENT_KICK 0x0AC8 -#define _PSB_CE_KICK_NOW (1 << 0) - -#define PSB_CR_BIF_DIR_LIST_BASE1 0x0C38 - -#define PSB_CR_BIF_CTRL 0x0C00 -#define _PSB_CB_CTRL_CLEAR_FAULT (1 << 4) -#define _PSB_CB_CTRL_INVALDC (1 << 3) -#define _PSB_CB_CTRL_FLUSH (1 << 2) - -#define PSB_CR_BIF_INT_STAT 0x0C04 - -#define PSB_CR_BIF_FAULT 0x0C08 -#define _PSB_CBI_STAT_PF_N_RW (1 << 14) -#define _PSB_CBI_STAT_FAULT_SHIFT (0) -#define _PSB_CBI_STAT_FAULT_MASK (0x3FFF << 0) -#define _PSB_CBI_STAT_FAULT_CACHE (1 << 1) -#define _PSB_CBI_STAT_FAULT_TA (1 << 2) -#define _PSB_CBI_STAT_FAULT_VDM (1 << 3) -#define _PSB_CBI_STAT_FAULT_2D (1 << 4) -#define _PSB_CBI_STAT_FAULT_PBE (1 << 5) -#define _PSB_CBI_STAT_FAULT_TSP (1 << 6) -#define _PSB_CBI_STAT_FAULT_ISP (1 << 7) -#define _PSB_CBI_STAT_FAULT_USSEPDS (1 << 8) -#define _PSB_CBI_STAT_FAULT_HOST (1 << 9) - -#define PSB_CR_BIF_BANK0 0x0C78 -#define PSB_CR_BIF_BANK1 0x0C7C -#define PSB_CR_BIF_DIR_LIST_BASE0 0x0C84 -#define PSB_CR_BIF_TWOD_REQ_BASE 0x0C88 -#define PSB_CR_BIF_3D_REQ_BASE 0x0CAC - -#define PSB_CR_2D_SOCIF 0x0E18 -#define _PSB_C2_SOCIF_FREESPACE_SHIFT (0) -#define _PSB_C2_SOCIF_FREESPACE_MASK (0xFF << 0) -#define _PSB_C2_SOCIF_EMPTY (0x80 << 0) - -#define PSB_CR_2D_BLIT_STATUS 0x0E04 -#define _PSB_C2B_STATUS_BUSY (1 << 24) -#define _PSB_C2B_STATUS_COMPLETE_SHIFT (0) -#define _PSB_C2B_STATUS_COMPLETE_MASK (0xFFFFFF << 0) - -/* - * 2D defs. - */ - -/* - * 2D Slave Port Data : Block Header's Object Type - */ - -#define PSB_2D_CLIP_BH (0x00000000) -#define PSB_2D_PAT_BH (0x10000000) -#define PSB_2D_CTRL_BH (0x20000000) -#define PSB_2D_SRC_OFF_BH (0x30000000) -#define PSB_2D_MASK_OFF_BH (0x40000000) -#define PSB_2D_RESERVED1_BH (0x50000000) -#define PSB_2D_RESERVED2_BH (0x60000000) -#define PSB_2D_FENCE_BH (0x70000000) -#define PSB_2D_BLIT_BH (0x80000000) -#define PSB_2D_SRC_SURF_BH (0x90000000) -#define PSB_2D_DST_SURF_BH (0xA0000000) -#define PSB_2D_PAT_SURF_BH (0xB0000000) -#define PSB_2D_SRC_PAL_BH (0xC0000000) -#define PSB_2D_PAT_PAL_BH (0xD0000000) -#define PSB_2D_MASK_SURF_BH (0xE0000000) -#define PSB_2D_FLUSH_BH (0xF0000000) - -/* - * Clip Definition block (PSB_2D_CLIP_BH) - */ -#define PSB_2D_CLIPCOUNT_MAX (1) -#define PSB_2D_CLIPCOUNT_MASK (0x00000000) -#define PSB_2D_CLIPCOUNT_CLRMASK (0xFFFFFFFF) -#define PSB_2D_CLIPCOUNT_SHIFT (0) -/* clip rectangle min & max */ -#define PSB_2D_CLIP_XMAX_MASK (0x00FFF000) -#define PSB_2D_CLIP_XMAX_CLRMASK (0xFF000FFF) -#define PSB_2D_CLIP_XMAX_SHIFT (12) -#define PSB_2D_CLIP_XMIN_MASK (0x00000FFF) -#define PSB_2D_CLIP_XMIN_CLRMASK (0x00FFF000) -#define PSB_2D_CLIP_XMIN_SHIFT (0) -/* clip rectangle offset */ -#define PSB_2D_CLIP_YMAX_MASK (0x00FFF000) -#define PSB_2D_CLIP_YMAX_CLRMASK (0xFF000FFF) -#define PSB_2D_CLIP_YMAX_SHIFT (12) -#define PSB_2D_CLIP_YMIN_MASK (0x00000FFF) -#define PSB_2D_CLIP_YMIN_CLRMASK (0x00FFF000) -#define PSB_2D_CLIP_YMIN_SHIFT (0) - -/* - * Pattern Control (PSB_2D_PAT_BH) - */ -#define PSB_2D_PAT_HEIGHT_MASK (0x0000001F) -#define PSB_2D_PAT_HEIGHT_SHIFT (0) -#define PSB_2D_PAT_WIDTH_MASK (0x000003E0) -#define PSB_2D_PAT_WIDTH_SHIFT (5) -#define PSB_2D_PAT_YSTART_MASK (0x00007C00) -#define PSB_2D_PAT_YSTART_SHIFT (10) -#define PSB_2D_PAT_XSTART_MASK (0x000F8000) -#define PSB_2D_PAT_XSTART_SHIFT (15) - -/* - * 2D Control block (PSB_2D_CTRL_BH) - */ -/* Present Flags */ -#define PSB_2D_SRCCK_CTRL (0x00000001) -#define PSB_2D_DSTCK_CTRL (0x00000002) -#define PSB_2D_ALPHA_CTRL (0x00000004) -/* Colour Key Colour (SRC/DST)*/ -#define PSB_2D_CK_COL_MASK (0xFFFFFFFF) -#define PSB_2D_CK_COL_CLRMASK (0x00000000) -#define PSB_2D_CK_COL_SHIFT (0) -/* Colour Key Mask (SRC/DST)*/ -#define PSB_2D_CK_MASK_MASK (0xFFFFFFFF) -#define PSB_2D_CK_MASK_CLRMASK (0x00000000) -#define PSB_2D_CK_MASK_SHIFT (0) -/* Alpha Control (Alpha/RGB)*/ -#define PSB_2D_GBLALPHA_MASK (0x000FF000) -#define PSB_2D_GBLALPHA_CLRMASK (0xFFF00FFF) -#define PSB_2D_GBLALPHA_SHIFT (12) -#define PSB_2D_SRCALPHA_OP_MASK (0x00700000) -#define PSB_2D_SRCALPHA_OP_CLRMASK (0xFF8FFFFF) -#define PSB_2D_SRCALPHA_OP_SHIFT (20) -#define PSB_2D_SRCALPHA_OP_ONE (0x00000000) -#define PSB_2D_SRCALPHA_OP_SRC (0x00100000) -#define PSB_2D_SRCALPHA_OP_DST (0x00200000) -#define PSB_2D_SRCALPHA_OP_SG (0x00300000) -#define PSB_2D_SRCALPHA_OP_DG (0x00400000) -#define PSB_2D_SRCALPHA_OP_GBL (0x00500000) -#define PSB_2D_SRCALPHA_OP_ZERO (0x00600000) -#define PSB_2D_SRCALPHA_INVERT (0x00800000) -#define PSB_2D_SRCALPHA_INVERT_CLR (0xFF7FFFFF) -#define PSB_2D_DSTALPHA_OP_MASK (0x07000000) -#define PSB_2D_DSTALPHA_OP_CLRMASK (0xF8FFFFFF) -#define PSB_2D_DSTALPHA_OP_SHIFT (24) -#define PSB_2D_DSTALPHA_OP_ONE (0x00000000) -#define PSB_2D_DSTALPHA_OP_SRC (0x01000000) -#define PSB_2D_DSTALPHA_OP_DST (0x02000000) -#define PSB_2D_DSTALPHA_OP_SG (0x03000000) -#define PSB_2D_DSTALPHA_OP_DG (0x04000000) -#define PSB_2D_DSTALPHA_OP_GBL (0x05000000) -#define PSB_2D_DSTALPHA_OP_ZERO (0x06000000) -#define PSB_2D_DSTALPHA_INVERT (0x08000000) -#define PSB_2D_DSTALPHA_INVERT_CLR (0xF7FFFFFF) - -#define PSB_2D_PRE_MULTIPLICATION_ENABLE (0x10000000) -#define PSB_2D_PRE_MULTIPLICATION_CLRMASK (0xEFFFFFFF) -#define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE (0x20000000) -#define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK (0xDFFFFFFF) - -/* - *Source Offset (PSB_2D_SRC_OFF_BH) - */ -#define PSB_2D_SRCOFF_XSTART_MASK ((0x00000FFF) << 12) -#define PSB_2D_SRCOFF_XSTART_SHIFT (12) -#define PSB_2D_SRCOFF_YSTART_MASK (0x00000FFF) -#define PSB_2D_SRCOFF_YSTART_SHIFT (0) - -/* - * Mask Offset (PSB_2D_MASK_OFF_BH) - */ -#define PSB_2D_MASKOFF_XSTART_MASK ((0x00000FFF) << 12) -#define PSB_2D_MASKOFF_XSTART_SHIFT (12) -#define PSB_2D_MASKOFF_YSTART_MASK (0x00000FFF) -#define PSB_2D_MASKOFF_YSTART_SHIFT (0) - -/* - * 2D Fence (see PSB_2D_FENCE_BH): bits 0:27 are ignored - */ - -/* - *Blit Rectangle (PSB_2D_BLIT_BH) - */ - -#define PSB_2D_ROT_MASK (3 << 25) -#define PSB_2D_ROT_CLRMASK (~PSB_2D_ROT_MASK) -#define PSB_2D_ROT_NONE (0 << 25) -#define PSB_2D_ROT_90DEGS (1 << 25) -#define PSB_2D_ROT_180DEGS (2 << 25) -#define PSB_2D_ROT_270DEGS (3 << 25) - -#define PSB_2D_COPYORDER_MASK (3 << 23) -#define PSB_2D_COPYORDER_CLRMASK (~PSB_2D_COPYORDER_MASK) -#define PSB_2D_COPYORDER_TL2BR (0 << 23) -#define PSB_2D_COPYORDER_BR2TL (1 << 23) -#define PSB_2D_COPYORDER_TR2BL (2 << 23) -#define PSB_2D_COPYORDER_BL2TR (3 << 23) - -#define PSB_2D_DSTCK_CLRMASK (0xFF9FFFFF) -#define PSB_2D_DSTCK_DISABLE (0x00000000) -#define PSB_2D_DSTCK_PASS (0x00200000) -#define PSB_2D_DSTCK_REJECT (0x00400000) - -#define PSB_2D_SRCCK_CLRMASK (0xFFE7FFFF) -#define PSB_2D_SRCCK_DISABLE (0x00000000) -#define PSB_2D_SRCCK_PASS (0x00080000) -#define PSB_2D_SRCCK_REJECT (0x00100000) - -#define PSB_2D_CLIP_ENABLE (0x00040000) - -#define PSB_2D_ALPHA_ENABLE (0x00020000) - -#define PSB_2D_PAT_CLRMASK (0xFFFEFFFF) -#define PSB_2D_PAT_MASK (0x00010000) -#define PSB_2D_USE_PAT (0x00010000) -#define PSB_2D_USE_FILL (0x00000000) -/* - * Tungsten Graphics note on rop codes: If rop A and rop B are - * identical, the mask surface will not be read and need not be - * set up. - */ - -#define PSB_2D_ROP3B_MASK (0x0000FF00) -#define PSB_2D_ROP3B_CLRMASK (0xFFFF00FF) -#define PSB_2D_ROP3B_SHIFT (8) -/* rop code A */ -#define PSB_2D_ROP3A_MASK (0x000000FF) -#define PSB_2D_ROP3A_CLRMASK (0xFFFFFF00) -#define PSB_2D_ROP3A_SHIFT (0) - -#define PSB_2D_ROP4_MASK (0x0000FFFF) -/* - * DWORD0: (Only pass if Pattern control == Use Fill Colour) - * Fill Colour RGBA8888 - */ -#define PSB_2D_FILLCOLOUR_MASK (0xFFFFFFFF) -#define PSB_2D_FILLCOLOUR_SHIFT (0) -/* - * DWORD1: (Always Present) - * X Start (Dest) - * Y Start (Dest) - */ -#define PSB_2D_DST_XSTART_MASK (0x00FFF000) -#define PSB_2D_DST_XSTART_CLRMASK (0xFF000FFF) -#define PSB_2D_DST_XSTART_SHIFT (12) -#define PSB_2D_DST_YSTART_MASK (0x00000FFF) -#define PSB_2D_DST_YSTART_CLRMASK (0xFFFFF000) -#define PSB_2D_DST_YSTART_SHIFT (0) -/* - * DWORD2: (Always Present) - * X Size (Dest) - * Y Size (Dest) - */ -#define PSB_2D_DST_XSIZE_MASK (0x00FFF000) -#define PSB_2D_DST_XSIZE_CLRMASK (0xFF000FFF) -#define PSB_2D_DST_XSIZE_SHIFT (12) -#define PSB_2D_DST_YSIZE_MASK (0x00000FFF) -#define PSB_2D_DST_YSIZE_CLRMASK (0xFFFFF000) -#define PSB_2D_DST_YSIZE_SHIFT (0) - -/* - * Source Surface (PSB_2D_SRC_SURF_BH) - */ -/* - * WORD 0 - */ - -#define PSB_2D_SRC_FORMAT_MASK (0x00078000) -#define PSB_2D_SRC_1_PAL (0x00000000) -#define PSB_2D_SRC_2_PAL (0x00008000) -#define PSB_2D_SRC_4_PAL (0x00010000) -#define PSB_2D_SRC_8_PAL (0x00018000) -#define PSB_2D_SRC_8_ALPHA (0x00020000) -#define PSB_2D_SRC_4_ALPHA (0x00028000) -#define PSB_2D_SRC_332RGB (0x00030000) -#define PSB_2D_SRC_4444ARGB (0x00038000) -#define PSB_2D_SRC_555RGB (0x00040000) -#define PSB_2D_SRC_1555ARGB (0x00048000) -#define PSB_2D_SRC_565RGB (0x00050000) -#define PSB_2D_SRC_0888ARGB (0x00058000) -#define PSB_2D_SRC_8888ARGB (0x00060000) -#define PSB_2D_SRC_8888UYVY (0x00068000) -#define PSB_2D_SRC_RESERVED (0x00070000) -#define PSB_2D_SRC_1555ARGB_LOOKUP (0x00078000) - - -#define PSB_2D_SRC_STRIDE_MASK (0x00007FFF) -#define PSB_2D_SRC_STRIDE_CLRMASK (0xFFFF8000) -#define PSB_2D_SRC_STRIDE_SHIFT (0) -/* - * WORD 1 - Base Address - */ -#define PSB_2D_SRC_ADDR_MASK (0x0FFFFFFC) -#define PSB_2D_SRC_ADDR_CLRMASK (0x00000003) -#define PSB_2D_SRC_ADDR_SHIFT (2) -#define PSB_2D_SRC_ADDR_ALIGNSHIFT (2) - -/* - * Pattern Surface (PSB_2D_PAT_SURF_BH) - */ -/* - * WORD 0 - */ - -#define PSB_2D_PAT_FORMAT_MASK (0x00078000) -#define PSB_2D_PAT_1_PAL (0x00000000) -#define PSB_2D_PAT_2_PAL (0x00008000) -#define PSB_2D_PAT_4_PAL (0x00010000) -#define PSB_2D_PAT_8_PAL (0x00018000) -#define PSB_2D_PAT_8_ALPHA (0x00020000) -#define PSB_2D_PAT_4_ALPHA (0x00028000) -#define PSB_2D_PAT_332RGB (0x00030000) -#define PSB_2D_PAT_4444ARGB (0x00038000) -#define PSB_2D_PAT_555RGB (0x00040000) -#define PSB_2D_PAT_1555ARGB (0x00048000) -#define PSB_2D_PAT_565RGB (0x00050000) -#define PSB_2D_PAT_0888ARGB (0x00058000) -#define PSB_2D_PAT_8888ARGB (0x00060000) - -#define PSB_2D_PAT_STRIDE_MASK (0x00007FFF) -#define PSB_2D_PAT_STRIDE_CLRMASK (0xFFFF8000) -#define PSB_2D_PAT_STRIDE_SHIFT (0) -/* - * WORD 1 - Base Address - */ -#define PSB_2D_PAT_ADDR_MASK (0x0FFFFFFC) -#define PSB_2D_PAT_ADDR_CLRMASK (0x00000003) -#define PSB_2D_PAT_ADDR_SHIFT (2) -#define PSB_2D_PAT_ADDR_ALIGNSHIFT (2) - -/* - * Destination Surface (PSB_2D_DST_SURF_BH) - */ -/* - * WORD 0 - */ - -#define PSB_2D_DST_FORMAT_MASK (0x00078000) -#define PSB_2D_DST_332RGB (0x00030000) -#define PSB_2D_DST_4444ARGB (0x00038000) -#define PSB_2D_DST_555RGB (0x00040000) -#define PSB_2D_DST_1555ARGB (0x00048000) -#define PSB_2D_DST_565RGB (0x00050000) -#define PSB_2D_DST_0888ARGB (0x00058000) -#define PSB_2D_DST_8888ARGB (0x00060000) -#define PSB_2D_DST_8888AYUV (0x00070000) - -#define PSB_2D_DST_STRIDE_MASK (0x00007FFF) -#define PSB_2D_DST_STRIDE_CLRMASK (0xFFFF8000) -#define PSB_2D_DST_STRIDE_SHIFT (0) -/* - * WORD 1 - Base Address - */ -#define PSB_2D_DST_ADDR_MASK (0x0FFFFFFC) -#define PSB_2D_DST_ADDR_CLRMASK (0x00000003) -#define PSB_2D_DST_ADDR_SHIFT (2) -#define PSB_2D_DST_ADDR_ALIGNSHIFT (2) - -/* - * Mask Surface (PSB_2D_MASK_SURF_BH) - */ -/* - * WORD 0 - */ -#define PSB_2D_MASK_STRIDE_MASK (0x00007FFF) -#define PSB_2D_MASK_STRIDE_CLRMASK (0xFFFF8000) -#define PSB_2D_MASK_STRIDE_SHIFT (0) -/* - * WORD 1 - Base Address - */ -#define PSB_2D_MASK_ADDR_MASK (0x0FFFFFFC) -#define PSB_2D_MASK_ADDR_CLRMASK (0x00000003) -#define PSB_2D_MASK_ADDR_SHIFT (2) -#define PSB_2D_MASK_ADDR_ALIGNSHIFT (2) - -/* - * Source Palette (PSB_2D_SRC_PAL_BH) - */ - -#define PSB_2D_SRCPAL_ADDR_SHIFT (0) -#define PSB_2D_SRCPAL_ADDR_CLRMASK (0xF0000007) -#define PSB_2D_SRCPAL_ADDR_MASK (0x0FFFFFF8) -#define PSB_2D_SRCPAL_BYTEALIGN (1024) - -/* - * Pattern Palette (PSB_2D_PAT_PAL_BH) - */ - -#define PSB_2D_PATPAL_ADDR_SHIFT (0) -#define PSB_2D_PATPAL_ADDR_CLRMASK (0xF0000007) -#define PSB_2D_PATPAL_ADDR_MASK (0x0FFFFFF8) -#define PSB_2D_PATPAL_BYTEALIGN (1024) - -/* - * Rop3 Codes (2 LS bytes) - */ - -#define PSB_2D_ROP3_SRCCOPY (0xCCCC) -#define PSB_2D_ROP3_PATCOPY (0xF0F0) -#define PSB_2D_ROP3_WHITENESS (0xFFFF) -#define PSB_2D_ROP3_BLACKNESS (0x0000) -#define PSB_2D_ROP3_SRC (0xCC) -#define PSB_2D_ROP3_PAT (0xF0) -#define PSB_2D_ROP3_DST (0xAA) - -/* - * Sizes. - */ - -#define PSB_SCENE_HW_COOKIE_SIZE 16 -#define PSB_TA_MEM_HW_COOKIE_SIZE 16 - -/* - * Scene stuff. - */ - -#define PSB_NUM_HW_SCENES 2 - -/* - * Scheduler completion actions. - */ - -#define PSB_RASTER_BLOCK 0 -#define PSB_RASTER 1 -#define PSB_RETURN 2 -#define PSB_TA 3 - -/* Power management */ -#define PSB_PUNIT_PORT 0x04 -#define PSB_OSPMBA 0x78 -#define PSB_APMBA 0x7a -#define PSB_APM_CMD 0x0 -#define PSB_APM_STS 0x04 -#define PSB_PWRGT_VID_ENC_MASK 0x30 -#define PSB_PWRGT_VID_DEC_MASK 0xc -#define PSB_PWRGT_GL3_MASK 0xc0 - -#define PSB_PM_SSC 0x20 -#define PSB_PM_SSS 0x30 -#define PSB_PWRGT_DISPLAY_MASK 0xc /*on a different BA than video/gfx*/ -#define MDFLD_PWRGT_DISPLAY_A_CNTR 0x0000000c -#define MDFLD_PWRGT_DISPLAY_B_CNTR 0x0000c000 -#define MDFLD_PWRGT_DISPLAY_C_CNTR 0x00030000 -#define MDFLD_PWRGT_DISP_MIPI_CNTR 0x000c0000 -#define MDFLD_PWRGT_DISPLAY_CNTR (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR) /* 0x000fc00c */ -/* Display SSS register bits are different in A0 vs. B0 */ -#define PSB_PWRGT_GFX_MASK 0x3 -#define MDFLD_PWRGT_DISPLAY_A_STS 0x000000c0 -#define MDFLD_PWRGT_DISPLAY_B_STS 0x00000300 -#define MDFLD_PWRGT_DISPLAY_C_STS 0x00000c00 -#define PSB_PWRGT_GFX_MASK_B0 0xc3 -#define MDFLD_PWRGT_DISPLAY_A_STS_B0 0x0000000c -#define MDFLD_PWRGT_DISPLAY_B_STS_B0 0x0000c000 -#define MDFLD_PWRGT_DISPLAY_C_STS_B0 0x00030000 -#define MDFLD_PWRGT_DISP_MIPI_STS 0x000c0000 -#define MDFLD_PWRGT_DISPLAY_STS_A0 (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */ -#define MDFLD_PWRGT_DISPLAY_STS_B0 (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */ -#endif diff --git a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c deleted file mode 100644 index 4a07ab5..0000000 --- a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c +++ /dev/null @@ -1,829 +0,0 @@ -/* - * Copyright © 2011 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -#include "mdfld_dsi_dpi.h" -#include "mdfld_output.h" -#include "mdfld_dsi_pkg_sender.h" -#include "tc35876x-dsi-lvds.h" -#include -#include -#include -#include - -static struct i2c_client *tc35876x_client; -static struct i2c_client *cmi_lcd_i2c_client; - -#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end)) -#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end)) - -/* DSI D-PHY Layer Registers */ -#define D0W_DPHYCONTTX 0x0004 -#define CLW_DPHYCONTRX 0x0020 -#define D0W_DPHYCONTRX 0x0024 -#define D1W_DPHYCONTRX 0x0028 -#define D2W_DPHYCONTRX 0x002C -#define D3W_DPHYCONTRX 0x0030 -#define COM_DPHYCONTRX 0x0038 -#define CLW_CNTRL 0x0040 -#define D0W_CNTRL 0x0044 -#define D1W_CNTRL 0x0048 -#define D2W_CNTRL 0x004C -#define D3W_CNTRL 0x0050 -#define DFTMODE_CNTRL 0x0054 - -/* DSI PPI Layer Registers */ -#define PPI_STARTPPI 0x0104 -#define PPI_BUSYPPI 0x0108 -#define PPI_LINEINITCNT 0x0110 -#define PPI_LPTXTIMECNT 0x0114 -#define PPI_LANEENABLE 0x0134 -#define PPI_TX_RX_TA 0x013C -#define PPI_CLS_ATMR 0x0140 -#define PPI_D0S_ATMR 0x0144 -#define PPI_D1S_ATMR 0x0148 -#define PPI_D2S_ATMR 0x014C -#define PPI_D3S_ATMR 0x0150 -#define PPI_D0S_CLRSIPOCOUNT 0x0164 -#define PPI_D1S_CLRSIPOCOUNT 0x0168 -#define PPI_D2S_CLRSIPOCOUNT 0x016C -#define PPI_D3S_CLRSIPOCOUNT 0x0170 -#define CLS_PRE 0x0180 -#define D0S_PRE 0x0184 -#define D1S_PRE 0x0188 -#define D2S_PRE 0x018C -#define D3S_PRE 0x0190 -#define CLS_PREP 0x01A0 -#define D0S_PREP 0x01A4 -#define D1S_PREP 0x01A8 -#define D2S_PREP 0x01AC -#define D3S_PREP 0x01B0 -#define CLS_ZERO 0x01C0 -#define D0S_ZERO 0x01C4 -#define D1S_ZERO 0x01C8 -#define D2S_ZERO 0x01CC -#define D3S_ZERO 0x01D0 -#define PPI_CLRFLG 0x01E0 -#define PPI_CLRSIPO 0x01E4 -#define HSTIMEOUT 0x01F0 -#define HSTIMEOUTENABLE 0x01F4 - -/* DSI Protocol Layer Registers */ -#define DSI_STARTDSI 0x0204 -#define DSI_BUSYDSI 0x0208 -#define DSI_LANEENABLE 0x0210 -#define DSI_LANESTATUS0 0x0214 -#define DSI_LANESTATUS1 0x0218 -#define DSI_INTSTATUS 0x0220 -#define DSI_INTMASK 0x0224 -#define DSI_INTCLR 0x0228 -#define DSI_LPTXTO 0x0230 - -/* DSI General Registers */ -#define DSIERRCNT 0x0300 - -/* DSI Application Layer Registers */ -#define APLCTRL 0x0400 -#define RDPKTLN 0x0404 - -/* Video Path Registers */ -#define VPCTRL 0x0450 -#define HTIM1 0x0454 -#define HTIM2 0x0458 -#define VTIM1 0x045C -#define VTIM2 0x0460 -#define VFUEN 0x0464 - -/* LVDS Registers */ -#define LVMX0003 0x0480 -#define LVMX0407 0x0484 -#define LVMX0811 0x0488 -#define LVMX1215 0x048C -#define LVMX1619 0x0490 -#define LVMX2023 0x0494 -#define LVMX2427 0x0498 -#define LVCFG 0x049C -#define LVPHY0 0x04A0 -#define LVPHY1 0x04A4 - -/* System Registers */ -#define SYSSTAT 0x0500 -#define SYSRST 0x0504 - -/* GPIO Registers */ -/*#define GPIOC 0x0520*/ -#define GPIOO 0x0524 -#define GPIOI 0x0528 - -/* I2C Registers */ -#define I2CTIMCTRL 0x0540 -#define I2CMADDR 0x0544 -#define WDATAQ 0x0548 -#define RDATAQ 0x054C - -/* Chip/Rev Registers */ -#define IDREG 0x0580 - -/* Debug Registers */ -#define DEBUG00 0x05A0 -#define DEBUG01 0x05A4 - -/* Panel CABC registers */ -#define PANEL_PWM_CONTROL 0x90 -#define PANEL_FREQ_DIVIDER_HI 0x91 -#define PANEL_FREQ_DIVIDER_LO 0x92 -#define PANEL_DUTY_CONTROL 0x93 -#define PANEL_MODIFY_RGB 0x94 -#define PANEL_FRAMERATE_CONTROL 0x96 -#define PANEL_PWM_MIN 0x97 -#define PANEL_PWM_REF 0x98 -#define PANEL_PWM_MAX 0x99 -#define PANEL_ALLOW_DISTORT 0x9A -#define PANEL_BYPASS_PWMI 0x9B - -/* Panel color management registers */ -#define PANEL_CM_ENABLE 0x700 -#define PANEL_CM_HUE 0x701 -#define PANEL_CM_SATURATION 0x702 -#define PANEL_CM_INTENSITY 0x703 -#define PANEL_CM_BRIGHTNESS 0x704 -#define PANEL_CM_CE_ENABLE 0x705 -#define PANEL_CM_PEAK_EN 0x710 -#define PANEL_CM_GAIN 0x711 -#define PANEL_CM_HUETABLE_START 0x730 -#define PANEL_CM_HUETABLE_END 0x747 /* inclusive */ - -/* Input muxing for registers LVMX0003...LVMX2427 */ -enum { - INPUT_R0, /* 0 */ - INPUT_R1, - INPUT_R2, - INPUT_R3, - INPUT_R4, - INPUT_R5, - INPUT_R6, - INPUT_R7, - INPUT_G0, /* 8 */ - INPUT_G1, - INPUT_G2, - INPUT_G3, - INPUT_G4, - INPUT_G5, - INPUT_G6, - INPUT_G7, - INPUT_B0, /* 16 */ - INPUT_B1, - INPUT_B2, - INPUT_B3, - INPUT_B4, - INPUT_B5, - INPUT_B6, - INPUT_B7, - INPUT_HSYNC, /* 24 */ - INPUT_VSYNC, - INPUT_DE, - LOGIC_0, - /* 28...31 undefined */ -}; - -#define INPUT_MUX(lvmx03, lvmx02, lvmx01, lvmx00) \ - (FLD_VAL(lvmx03, 29, 24) | FLD_VAL(lvmx02, 20, 16) | \ - FLD_VAL(lvmx01, 12, 8) | FLD_VAL(lvmx00, 4, 0)) - -/** - * tc35876x_regw - Write DSI-LVDS bridge register using I2C - * @client: struct i2c_client to use - * @reg: register address - * @value: value to write - * - * Returns 0 on success, or a negative error value. - */ -static int tc35876x_regw(struct i2c_client *client, u16 reg, u32 value) -{ - int r; - u8 tx_data[] = { - /* NOTE: Register address big-endian, data little-endian. */ - (reg >> 8) & 0xff, - reg & 0xff, - value & 0xff, - (value >> 8) & 0xff, - (value >> 16) & 0xff, - (value >> 24) & 0xff, - }; - struct i2c_msg msgs[] = { - { - .addr = client->addr, - .flags = 0, - .buf = tx_data, - .len = ARRAY_SIZE(tx_data), - }, - }; - - r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (r < 0) { - dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x error %d\n", - __func__, reg, value, r); - return r; - } - - if (r < ARRAY_SIZE(msgs)) { - dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x msgs %d\n", - __func__, reg, value, r); - return -EAGAIN; - } - - dev_dbg(&client->dev, "%s: reg 0x%04x val 0x%08x\n", - __func__, reg, value); - - return 0; -} - -/** - * tc35876x_regr - Read DSI-LVDS bridge register using I2C - * @client: struct i2c_client to use - * @reg: register address - * @value: pointer for storing the value - * - * Returns 0 on success, or a negative error value. - */ -static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value) -{ - int r; - u8 tx_data[] = { - (reg >> 8) & 0xff, - reg & 0xff, - }; - u8 rx_data[4]; - struct i2c_msg msgs[] = { - { - .addr = client->addr, - .flags = 0, - .buf = tx_data, - .len = ARRAY_SIZE(tx_data), - }, - { - .addr = client->addr, - .flags = I2C_M_RD, - .buf = rx_data, - .len = ARRAY_SIZE(rx_data), - }, - }; - - r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (r < 0) { - dev_err(&client->dev, "%s: reg 0x%04x error %d\n", __func__, - reg, r); - return r; - } - - if (r < ARRAY_SIZE(msgs)) { - dev_err(&client->dev, "%s: reg 0x%04x msgs %d\n", __func__, - reg, r); - return -EAGAIN; - } - - *value = rx_data[0] << 24 | rx_data[1] << 16 | - rx_data[2] << 8 | rx_data[3]; - - dev_dbg(&client->dev, "%s: reg 0x%04x value 0x%08x\n", __func__, - reg, *value); - - return 0; -} - -void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state) -{ - struct tc35876x_platform_data *pdata; - - if (WARN(!tc35876x_client, "%s called before probe", __func__)) - return; - - dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state); - - pdata = dev_get_platdata(&tc35876x_client->dev); - - if (pdata->gpio_bridge_reset == -1) - return; - - if (state) { - gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0); - mdelay(10); - } else { - /* Pull MIPI Bridge reset pin to Low */ - gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0); - mdelay(20); - /* Pull MIPI Bridge reset pin to High */ - gpio_set_value_cansleep(pdata->gpio_bridge_reset, 1); - mdelay(40); - } -} - -void tc35876x_configure_lvds_bridge(struct drm_device *dev) -{ - struct i2c_client *i2c = tc35876x_client; - u32 ppi_lptxtimecnt; - u32 txtagocnt; - u32 txtasurecnt; - u32 id; - - if (WARN(!tc35876x_client, "%s called before probe", __func__)) - return; - - dev_dbg(&tc35876x_client->dev, "%s\n", __func__); - - if (!tc35876x_regr(i2c, IDREG, &id)) - dev_info(&tc35876x_client->dev, "tc35876x ID 0x%08x\n", id); - else - dev_err(&tc35876x_client->dev, "Cannot read ID\n"); - - ppi_lptxtimecnt = 4; - txtagocnt = (5 * ppi_lptxtimecnt - 3) / 4; - txtasurecnt = 3 * ppi_lptxtimecnt / 2; - tc35876x_regw(i2c, PPI_TX_RX_TA, FLD_VAL(txtagocnt, 26, 16) | - FLD_VAL(txtasurecnt, 10, 0)); - tc35876x_regw(i2c, PPI_LPTXTIMECNT, FLD_VAL(ppi_lptxtimecnt, 10, 0)); - - tc35876x_regw(i2c, PPI_D0S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0)); - tc35876x_regw(i2c, PPI_D1S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0)); - tc35876x_regw(i2c, PPI_D2S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0)); - tc35876x_regw(i2c, PPI_D3S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0)); - - /* Enabling MIPI & PPI lanes, Enable 4 lanes */ - tc35876x_regw(i2c, PPI_LANEENABLE, - BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); - tc35876x_regw(i2c, DSI_LANEENABLE, - BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); - tc35876x_regw(i2c, PPI_STARTPPI, BIT(0)); - tc35876x_regw(i2c, DSI_STARTDSI, BIT(0)); - - /* Setting LVDS output frequency */ - tc35876x_regw(i2c, LVPHY0, FLD_VAL(1, 20, 16) | - FLD_VAL(2, 15, 14) | FLD_VAL(6, 4, 0)); /* 0x00048006 */ - - /* Setting video panel control register,0x00000120 VTGen=ON ?!?!? */ - tc35876x_regw(i2c, VPCTRL, BIT(8) | BIT(5)); - - /* Horizontal back porch and horizontal pulse width. 0x00280028 */ - tc35876x_regw(i2c, HTIM1, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0)); - - /* Horizontal front porch and horizontal active video size. 0x00500500*/ - tc35876x_regw(i2c, HTIM2, FLD_VAL(80, 24, 16) | FLD_VAL(1280, 10, 0)); - - /* Vertical back porch and vertical sync pulse width. 0x000e000a */ - tc35876x_regw(i2c, VTIM1, FLD_VAL(14, 23, 16) | FLD_VAL(10, 7, 0)); - - /* Vertical front porch and vertical display size. 0x000e0320 */ - tc35876x_regw(i2c, VTIM2, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0)); - - /* Set above HTIM1, HTIM2, VTIM1, and VTIM2 at next VSYNC. */ - tc35876x_regw(i2c, VFUEN, BIT(0)); - - /* Soft reset LCD controller. */ - tc35876x_regw(i2c, SYSRST, BIT(2)); - - /* LVDS-TX input muxing */ - tc35876x_regw(i2c, LVMX0003, - INPUT_MUX(INPUT_R5, INPUT_R4, INPUT_R3, INPUT_R2)); - tc35876x_regw(i2c, LVMX0407, - INPUT_MUX(INPUT_G2, INPUT_R7, INPUT_R1, INPUT_R6)); - tc35876x_regw(i2c, LVMX0811, - INPUT_MUX(INPUT_G1, INPUT_G0, INPUT_G4, INPUT_G3)); - tc35876x_regw(i2c, LVMX1215, - INPUT_MUX(INPUT_B2, INPUT_G7, INPUT_G6, INPUT_G5)); - tc35876x_regw(i2c, LVMX1619, - INPUT_MUX(INPUT_B4, INPUT_B3, INPUT_B1, INPUT_B0)); - tc35876x_regw(i2c, LVMX2023, - INPUT_MUX(LOGIC_0, INPUT_B7, INPUT_B6, INPUT_B5)); - tc35876x_regw(i2c, LVMX2427, - INPUT_MUX(INPUT_R0, INPUT_DE, INPUT_VSYNC, INPUT_HSYNC)); - - /* Enable LVDS transmitter. */ - tc35876x_regw(i2c, LVCFG, BIT(0)); - - /* Clear notifications. Don't write reserved bits. Was write 0xffffffff - * to 0x0288, must be in error?! */ - tc35876x_regw(i2c, DSI_INTCLR, FLD_MASK(31, 30) | FLD_MASK(22, 0)); -} - -#define GPIOPWMCTRL 0x38F -#define PWM0CLKDIV0 0x62 /* low byte */ -#define PWM0CLKDIV1 0x61 /* high byte */ - -#define SYSTEMCLK 19200000UL /* 19.2 MHz */ -#define PWM_FREQUENCY 9600 /* Hz */ - -/* f = baseclk / (clkdiv + 1) => clkdiv = (baseclk - f) / f */ -static inline u16 calc_clkdiv(unsigned long baseclk, unsigned int f) -{ - return (baseclk - f) / f; -} - -static void tc35876x_brightness_init(struct drm_device *dev) -{ - int ret; - u8 pwmctrl; - u16 clkdiv; - - /* Make sure the PWM reference is the 19.2 MHz system clock. Read first - * instead of setting directly to catch potential conflicts between PWM - * users. */ - ret = intel_scu_ipc_ioread8(GPIOPWMCTRL, &pwmctrl); - if (ret || pwmctrl != 0x01) { - if (ret) - dev_err(&dev->pdev->dev, "GPIOPWMCTRL read failed\n"); - else - dev_warn(&dev->pdev->dev, "GPIOPWMCTRL was not set to system clock (pwmctrl = 0x%02x)\n", pwmctrl); - - ret = intel_scu_ipc_iowrite8(GPIOPWMCTRL, 0x01); - if (ret) - dev_err(&dev->pdev->dev, "GPIOPWMCTRL set failed\n"); - } - - clkdiv = calc_clkdiv(SYSTEMCLK, PWM_FREQUENCY); - - ret = intel_scu_ipc_iowrite8(PWM0CLKDIV1, (clkdiv >> 8) & 0xff); - if (!ret) - ret = intel_scu_ipc_iowrite8(PWM0CLKDIV0, clkdiv & 0xff); - - if (ret) - dev_err(&dev->pdev->dev, "PWM0CLKDIV set failed\n"); - else - dev_dbg(&dev->pdev->dev, "PWM0CLKDIV set to 0x%04x (%d Hz)\n", - clkdiv, PWM_FREQUENCY); -} - -#define PWM0DUTYCYCLE 0x67 - -void tc35876x_brightness_control(struct drm_device *dev, int level) -{ - int ret; - u8 duty_val; - u8 panel_duty_val; - - level = clamp(level, 0, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL); - - /* PWM duty cycle 0x00...0x63 corresponds to 0...99% */ - duty_val = level * 0x63 / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL; - - /* I won't pretend to understand this formula. The panel spec is quite - * bad engrish. - */ - panel_duty_val = (2 * level - 100) * 0xA9 / - MDFLD_DSI_BRIGHTNESS_MAX_LEVEL + 0x56; - - ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val); - if (ret) - dev_err(&tc35876x_client->dev, "%s: ipc write fail\n", - __func__); - - if (cmi_lcd_i2c_client) { - ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client, - PANEL_PWM_MAX, panel_duty_val); - if (ret < 0) - dev_err(&cmi_lcd_i2c_client->dev, "%s: i2c write failed\n", - __func__); - } -} - -void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev) -{ - struct tc35876x_platform_data *pdata; - - if (WARN(!tc35876x_client, "%s called before probe", __func__)) - return; - - dev_dbg(&tc35876x_client->dev, "%s\n", __func__); - - pdata = dev_get_platdata(&tc35876x_client->dev); - - if (pdata->gpio_panel_bl_en != -1) - gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 0); - - if (pdata->gpio_panel_vadd != -1) - gpio_set_value_cansleep(pdata->gpio_panel_vadd, 0); -} - -void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev) -{ - struct tc35876x_platform_data *pdata; - struct drm_psb_private *dev_priv = dev->dev_private; - - if (WARN(!tc35876x_client, "%s called before probe", __func__)) - return; - - dev_dbg(&tc35876x_client->dev, "%s\n", __func__); - - pdata = dev_get_platdata(&tc35876x_client->dev); - - if (pdata->gpio_panel_vadd != -1) { - gpio_set_value_cansleep(pdata->gpio_panel_vadd, 1); - msleep(260); - } - - if (cmi_lcd_i2c_client) { - int ret; - dev_dbg(&cmi_lcd_i2c_client->dev, "setting TCON\n"); - /* Bit 4 is average_saving. Setting it to 1, the brightness is - * referenced to the average of the frame content. 0 means - * reference to the maximum of frame contents. Bits 3:0 are - * allow_distort. When set to a nonzero value, all color values - * between 255-allow_distort*2 and 255 are mapped to the - * 255-allow_distort*2 value. - */ - ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client, - PANEL_ALLOW_DISTORT, 0x10); - if (ret < 0) - dev_err(&cmi_lcd_i2c_client->dev, - "i2c write failed (%d)\n", ret); - ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client, - PANEL_BYPASS_PWMI, 0); - if (ret < 0) - dev_err(&cmi_lcd_i2c_client->dev, - "i2c write failed (%d)\n", ret); - /* Set minimum brightness value - this is tunable */ - ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client, - PANEL_PWM_MIN, 0x35); - if (ret < 0) - dev_err(&cmi_lcd_i2c_client->dev, - "i2c write failed (%d)\n", ret); - } - - if (pdata->gpio_panel_bl_en != -1) - gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 1); - - tc35876x_brightness_control(dev, dev_priv->brightness_adjusted); -} - -static struct drm_display_mode *tc35876x_get_config_mode(struct drm_device *dev) -{ - struct drm_display_mode *mode; - - dev_dbg(&dev->pdev->dev, "%s\n", __func__); - - mode = kzalloc(sizeof(*mode), GFP_KERNEL); - if (!mode) - return NULL; - - /* FIXME: do this properly. */ - mode->hdisplay = 1280; - mode->vdisplay = 800; - mode->hsync_start = 1360; - mode->hsync_end = 1400; - mode->htotal = 1440; - mode->vsync_start = 814; - mode->vsync_end = 824; - mode->vtotal = 838; - mode->clock = 33324 << 1; - - dev_info(&dev->pdev->dev, "hdisplay(w) = %d\n", mode->hdisplay); - dev_info(&dev->pdev->dev, "vdisplay(h) = %d\n", mode->vdisplay); - dev_info(&dev->pdev->dev, "HSS = %d\n", mode->hsync_start); - dev_info(&dev->pdev->dev, "HSE = %d\n", mode->hsync_end); - dev_info(&dev->pdev->dev, "htotal = %d\n", mode->htotal); - dev_info(&dev->pdev->dev, "VSS = %d\n", mode->vsync_start); - dev_info(&dev->pdev->dev, "VSE = %d\n", mode->vsync_end); - dev_info(&dev->pdev->dev, "vtotal = %d\n", mode->vtotal); - dev_info(&dev->pdev->dev, "clock = %d\n", mode->clock); - - drm_mode_set_name(mode); - drm_mode_set_crtcinfo(mode, 0); - - mode->type |= DRM_MODE_TYPE_PREFERRED; - - return mode; -} - -/* DV1 Active area 216.96 x 135.6 mm */ -#define DV1_PANEL_WIDTH 217 -#define DV1_PANEL_HEIGHT 136 - -static int tc35876x_get_panel_info(struct drm_device *dev, int pipe, - struct panel_info *pi) -{ - if (!dev || !pi) - return -EINVAL; - - pi->width_mm = DV1_PANEL_WIDTH; - pi->height_mm = DV1_PANEL_HEIGHT; - - return 0; -} - -static int tc35876x_bridge_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct tc35876x_platform_data *pdata; - - dev_info(&client->dev, "%s\n", __func__); - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - dev_err(&client->dev, "%s: i2c_check_functionality() failed\n", - __func__); - return -ENODEV; - } - - pdata = dev_get_platdata(&client->dev); - if (!pdata) { - dev_err(&client->dev, "%s: no platform data\n", __func__); - return -ENODEV; - } - - if (pdata->gpio_bridge_reset != -1) { - gpio_request(pdata->gpio_bridge_reset, "tc35876x bridge reset"); - gpio_direction_output(pdata->gpio_bridge_reset, 0); - } - - if (pdata->gpio_panel_bl_en != -1) { - gpio_request(pdata->gpio_panel_bl_en, "tc35876x panel bl en"); - gpio_direction_output(pdata->gpio_panel_bl_en, 0); - } - - if (pdata->gpio_panel_vadd != -1) { - gpio_request(pdata->gpio_panel_vadd, "tc35876x panel vadd"); - gpio_direction_output(pdata->gpio_panel_vadd, 0); - } - - tc35876x_client = client; - - return 0; -} - -static int tc35876x_bridge_remove(struct i2c_client *client) -{ - struct tc35876x_platform_data *pdata = dev_get_platdata(&client->dev); - - dev_dbg(&client->dev, "%s\n", __func__); - - if (pdata->gpio_bridge_reset != -1) - gpio_free(pdata->gpio_bridge_reset); - - if (pdata->gpio_panel_bl_en != -1) - gpio_free(pdata->gpio_panel_bl_en); - - if (pdata->gpio_panel_vadd != -1) - gpio_free(pdata->gpio_panel_vadd); - - tc35876x_client = NULL; - - return 0; -} - -static const struct i2c_device_id tc35876x_bridge_id[] = { - { "i2c_disp_brig", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, tc35876x_bridge_id); - -static struct i2c_driver tc35876x_bridge_i2c_driver = { - .driver = { - .name = "i2c_disp_brig", - }, - .id_table = tc35876x_bridge_id, - .probe = tc35876x_bridge_probe, - .remove = __devexit_p(tc35876x_bridge_remove), -}; - -/* LCD panel I2C */ -static int cmi_lcd_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - dev_info(&client->dev, "%s\n", __func__); - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - dev_err(&client->dev, "%s: i2c_check_functionality() failed\n", - __func__); - return -ENODEV; - } - - cmi_lcd_i2c_client = client; - - return 0; -} - -static int cmi_lcd_i2c_remove(struct i2c_client *client) -{ - dev_dbg(&client->dev, "%s\n", __func__); - - cmi_lcd_i2c_client = NULL; - - return 0; -} - -static const struct i2c_device_id cmi_lcd_i2c_id[] = { - { "cmi-lcd", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, cmi_lcd_i2c_id); - -static struct i2c_driver cmi_lcd_i2c_driver = { - .driver = { - .name = "cmi-lcd", - }, - .id_table = cmi_lcd_i2c_id, - .probe = cmi_lcd_i2c_probe, - .remove = __devexit_p(cmi_lcd_i2c_remove), -}; - -/* HACK to create I2C device while it's not created by platform code */ -#define CMI_LCD_I2C_ADAPTER 2 -#define CMI_LCD_I2C_ADDR 0x60 - -static int cmi_lcd_hack_create_device(void) -{ - struct i2c_adapter *adapter; - struct i2c_client *client; - struct i2c_board_info info = { - .type = "cmi-lcd", - .addr = CMI_LCD_I2C_ADDR, - }; - - pr_debug("%s\n", __func__); - - adapter = i2c_get_adapter(CMI_LCD_I2C_ADAPTER); - if (!adapter) { - pr_err("%s: i2c_get_adapter(%d) failed\n", __func__, - CMI_LCD_I2C_ADAPTER); - return -EINVAL; - } - - client = i2c_new_device(adapter, &info); - if (!client) { - pr_err("%s: i2c_new_device() failed\n", __func__); - i2c_put_adapter(adapter); - return -EINVAL; - } - - return 0; -} - -static const struct drm_encoder_helper_funcs tc35876x_encoder_helper_funcs = { - .dpms = mdfld_dsi_dpi_dpms, - .mode_fixup = mdfld_dsi_dpi_mode_fixup, - .prepare = mdfld_dsi_dpi_prepare, - .mode_set = mdfld_dsi_dpi_mode_set, - .commit = mdfld_dsi_dpi_commit, -}; - -static const struct drm_encoder_funcs tc35876x_encoder_funcs = { - .destroy = drm_encoder_cleanup, -}; - -const struct panel_funcs mdfld_tc35876x_funcs = { - .encoder_funcs = &tc35876x_encoder_funcs, - .encoder_helper_funcs = &tc35876x_encoder_helper_funcs, - .get_config_mode = tc35876x_get_config_mode, - .get_panel_info = tc35876x_get_panel_info, -}; - -void tc35876x_init(struct drm_device *dev) -{ - int r; - - dev_dbg(&dev->pdev->dev, "%s\n", __func__); - - cmi_lcd_hack_create_device(); - - r = i2c_add_driver(&cmi_lcd_i2c_driver); - if (r < 0) - dev_err(&dev->pdev->dev, - "%s: i2c_add_driver() for %s failed (%d)\n", - __func__, cmi_lcd_i2c_driver.driver.name, r); - - r = i2c_add_driver(&tc35876x_bridge_i2c_driver); - if (r < 0) - dev_err(&dev->pdev->dev, - "%s: i2c_add_driver() for %s failed (%d)\n", - __func__, tc35876x_bridge_i2c_driver.driver.name, r); - - tc35876x_brightness_init(dev); -} - -void tc35876x_exit(void) -{ - pr_debug("%s\n", __func__); - - i2c_del_driver(&tc35876x_bridge_i2c_driver); - - if (cmi_lcd_i2c_client) - i2c_del_driver(&cmi_lcd_i2c_driver); -} diff --git a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h deleted file mode 100644 index b14b7f9..0000000 --- a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright © 2011 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef __MDFLD_DSI_LVDS_BRIDGE_H__ -#define __MDFLD_DSI_LVDS_BRIDGE_H__ - -void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state); -void tc35876x_configure_lvds_bridge(struct drm_device *dev); -void tc35876x_brightness_control(struct drm_device *dev, int level); -void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev); -void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev); -void tc35876x_init(struct drm_device *dev); -void tc35876x_exit(void); - -extern const struct panel_funcs mdfld_tc35876x_funcs; - -#endif /*__MDFLD_DSI_LVDS_BRIDGE_H__*/ diff --git a/drivers/gpu/drm/udl/Kconfig b/drivers/gpu/drm/udl/Kconfig deleted file mode 100644 index 0b5e096..0000000 --- a/drivers/gpu/drm/udl/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -config DRM_UDL - tristate "DisplayLink" - depends on DRM && EXPERIMENTAL - select DRM_USB - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_DEFERRED_IO - select DRM_KMS_HELPER - help - This is a KMS driver for the USB displaylink video adapters. - Say M/Y to add support for these devices via drm/kms interfaces. diff --git a/drivers/gpu/drm/udl/Makefile b/drivers/gpu/drm/udl/Makefile deleted file mode 100644 index 05c7481..0000000 --- a/drivers/gpu/drm/udl/Makefile +++ /dev/null @@ -1,6 +0,0 @@ - -ccflags-y := -Iinclude/drm - -udl-y := udl_drv.o udl_modeset.o udl_connector.o udl_encoder.o udl_main.o udl_fb.o udl_transfer.o udl_gem.o - -obj-$(CONFIG_DRM_UDL) := udl.o diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c deleted file mode 100644 index ba055e9..0000000 --- a/drivers/gpu/drm/udl/udl_connector.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2012 Red Hat - * based in parts on udlfb.c: - * Copyright (C) 2009 Roberto De Ioris - * Copyright (C) 2009 Jaya Kumar - * Copyright (C) 2009 Bernie Thompson - * - * This file is subject to the terms and conditions of the GNU General Public - * License v2. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include "drmP.h" -#include "drm_crtc.h" -#include "drm_edid.h" -#include "drm_crtc_helper.h" -#include "udl_drv.h" - -/* dummy connector to just get EDID, - all UDL appear to have a DVI-D */ - -static u8 *udl_get_edid(struct udl_device *udl) -{ - u8 *block; - char rbuf[3]; - int ret, i; - - block = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (block == NULL) - return NULL; - - for (i = 0; i < EDID_LENGTH; i++) { - ret = usb_control_msg(udl->ddev->usbdev, - usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), - (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2, - HZ); - if (ret < 1) { - DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); - i--; - goto error; - } - block[i] = rbuf[1]; - } - - return block; - -error: - kfree(block); - return NULL; -} - -static int udl_get_modes(struct drm_connector *connector) -{ - struct udl_device *udl = connector->dev->dev_private; - struct edid *edid; - int ret; - - edid = (struct edid *)udl_get_edid(udl); - - connector->display_info.raw_edid = (char *)edid; - - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - connector->display_info.raw_edid = NULL; - kfree(edid); - return ret; -} - -static int udl_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - return 0; -} - -static enum drm_connector_status -udl_detect(struct drm_connector *connector, bool force) -{ - if (drm_device_is_unplugged(connector->dev)) - return connector_status_disconnected; - return connector_status_connected; -} - -struct drm_encoder *udl_best_single_encoder(struct drm_connector *connector) -{ - int enc_id = connector->encoder_ids[0]; - struct drm_mode_object *obj; - struct drm_encoder *encoder; - - obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); - if (!obj) - return NULL; - encoder = obj_to_encoder(obj); - return encoder; -} - -int udl_connector_set_property(struct drm_connector *connector, struct drm_property *property, - uint64_t val) -{ - return 0; -} - -static void udl_connector_destroy(struct drm_connector *connector) -{ - drm_sysfs_connector_remove(connector); - drm_connector_cleanup(connector); - kfree(connector); -} - -struct drm_connector_helper_funcs udl_connector_helper_funcs = { - .get_modes = udl_get_modes, - .mode_valid = udl_mode_valid, - .best_encoder = udl_best_single_encoder, -}; - -struct drm_connector_funcs udl_connector_funcs = { - .dpms = drm_helper_connector_dpms, - .detect = udl_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = udl_connector_destroy, - .set_property = udl_connector_set_property, -}; - -int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder) -{ - struct drm_connector *connector; - - connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL); - if (!connector) - return -ENOMEM; - - drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_DVII); - drm_connector_helper_add(connector, &udl_connector_helper_funcs); - - drm_sysfs_connector_add(connector); - drm_mode_connector_attach_encoder(connector, encoder); - - drm_connector_attach_property(connector, - dev->mode_config.dirty_info_property, - 1); - return 0; -} diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c deleted file mode 100644 index 5340c5f..0000000 --- a/drivers/gpu/drm/udl/udl_drv.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2012 Red Hat - * - * This file is subject to the terms and conditions of the GNU General Public - * License v2. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include -#include "drm_usb.h" -#include "drm_crtc_helper.h" -#include "udl_drv.h" - -static struct drm_driver driver; - -static struct usb_device_id id_table[] = { - {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,}, - {}, -}; -MODULE_DEVICE_TABLE(usb, id_table); - -MODULE_LICENSE("GPL"); - -static int udl_usb_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - return drm_get_usb_dev(interface, id, &driver); -} - -static void udl_usb_disconnect(struct usb_interface *interface) -{ - struct drm_device *dev = usb_get_intfdata(interface); - - drm_kms_helper_poll_disable(dev); - drm_connector_unplug_all(dev); - udl_fbdev_unplug(dev); - udl_drop_usb(dev); - drm_unplug_dev(dev); -} - -static struct vm_operations_struct udl_gem_vm_ops = { - .fault = udl_gem_fault, - .open = drm_gem_vm_open, - .close = drm_gem_vm_close, -}; - -static const struct file_operations udl_driver_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .mmap = drm_gem_mmap, - .poll = drm_poll, - .read = drm_read, - .unlocked_ioctl = drm_ioctl, - .release = drm_release, - .fasync = drm_fasync, - .llseek = noop_llseek, -}; - -static struct drm_driver driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM, - .load = udl_driver_load, - .unload = udl_driver_unload, - - /* gem hooks */ - .gem_init_object = udl_gem_init_object, - .gem_free_object = udl_gem_free_object, - .gem_vm_ops = &udl_gem_vm_ops, - - .dumb_create = udl_dumb_create, - .dumb_map_offset = udl_gem_mmap, - .dumb_destroy = udl_dumb_destroy, - .fops = &udl_driver_fops, - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, - .patchlevel = DRIVER_PATCHLEVEL, -}; - -static struct usb_driver udl_driver = { - .name = "udl", - .probe = udl_usb_probe, - .disconnect = udl_usb_disconnect, - .id_table = id_table, -}; - -static int __init udl_init(void) -{ - return drm_usb_init(&driver, &udl_driver); -} - -static void __exit udl_exit(void) -{ - drm_usb_exit(&driver, &udl_driver); -} - -module_init(udl_init); -module_exit(udl_exit); diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h deleted file mode 100644 index 1612954..0000000 --- a/drivers/gpu/drm/udl/udl_drv.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2012 Red Hat - * - * based in parts on udlfb.c: - * Copyright (C) 2009 Roberto De Ioris - * Copyright (C) 2009 Jaya Kumar - * Copyright (C) 2009 Bernie Thompson - * - * This file is subject to the terms and conditions of the GNU General Public - * License v2. See the file COPYING in the main directory of this archive for - * more details. - */ - -#ifndef UDL_DRV_H -#define UDL_DRV_H - -#include - -#define DRIVER_NAME "udl" -#define DRIVER_DESC "DisplayLink" -#define DRIVER_DATE "20120220" - -#define DRIVER_MAJOR 0 -#define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 1 - -struct udl_device; - -struct urb_node { - struct list_head entry; - struct udl_device *dev; - struct delayed_work release_urb_work; - struct urb *urb; -}; - -struct urb_list { - struct list_head list; - spinlock_t lock; - struct semaphore limit_sem; - int available; - int count; - size_t size; -}; - -struct udl_fbdev; - -struct udl_device { - struct device *dev; - struct drm_device *ddev; - - int sku_pixel_limit; - - struct urb_list urbs; - atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */ - - struct udl_fbdev *fbdev; - char mode_buf[1024]; - uint32_t mode_buf_len; - atomic_t bytes_rendered; /* raw pixel-bytes driver asked to render */ - atomic_t bytes_identical; /* saved effort with backbuffer comparison */ - atomic_t bytes_sent; /* to usb, after compression including overhead */ - atomic_t cpu_kcycles_used; /* transpired during pixel processing */ -}; - -struct udl_gem_object { - struct drm_gem_object base; - struct page **pages; - void *vmapping; -}; - -#define to_udl_bo(x) container_of(x, struct udl_gem_object, base) - -struct udl_framebuffer { - struct drm_framebuffer base; - struct udl_gem_object *obj; - bool active_16; /* active on the 16-bit channel */ -}; - -#define to_udl_fb(x) container_of(x, struct udl_framebuffer, base) - -/* modeset */ -int udl_modeset_init(struct drm_device *dev); -void udl_modeset_cleanup(struct drm_device *dev); -int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder); - -struct drm_encoder *udl_encoder_init(struct drm_device *dev); - -struct urb *udl_get_urb(struct drm_device *dev); - -int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len); -void udl_urb_completion(struct urb *urb); - -int udl_driver_load(struct drm_device *dev, unsigned long flags); -int udl_driver_unload(struct drm_device *dev); - -int udl_fbdev_init(struct drm_device *dev); -void udl_fbdev_cleanup(struct drm_device *dev); -void udl_fbdev_unplug(struct drm_device *dev); -struct drm_framebuffer * -udl_fb_user_fb_create(struct drm_device *dev, - struct drm_file *file, - struct drm_mode_fb_cmd2 *mode_cmd); - -int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, - const char *front, char **urb_buf_ptr, - u32 byte_offset, u32 byte_width, - int *ident_ptr, int *sent_ptr); - -int udl_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, - struct drm_mode_create_dumb *args); -int udl_gem_mmap(struct drm_file *file_priv, struct drm_device *dev, - uint32_t handle, uint64_t *offset); -int udl_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev, - uint32_t handle); - -int udl_gem_init_object(struct drm_gem_object *obj); -void udl_gem_free_object(struct drm_gem_object *gem_obj); -struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, - size_t size); - -int udl_gem_vmap(struct udl_gem_object *obj); -void udl_gem_vunmap(struct udl_gem_object *obj); -int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); - -int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, - int width, int height); - -int udl_drop_usb(struct drm_device *dev); - -#define CMD_WRITE_RAW8 "\xAF\x60" /**< 8 bit raw write command. */ -#define CMD_WRITE_RL8 "\xAF\x61" /**< 8 bit run length command. */ -#define CMD_WRITE_COPY8 "\xAF\x62" /**< 8 bit copy command. */ -#define CMD_WRITE_RLX8 "\xAF\x63" /**< 8 bit extended run length command. */ - -#define CMD_WRITE_RAW16 "\xAF\x68" /**< 16 bit raw write command. */ -#define CMD_WRITE_RL16 "\xAF\x69" /**< 16 bit run length command. */ -#define CMD_WRITE_COPY16 "\xAF\x6A" /**< 16 bit copy command. */ -#define CMD_WRITE_RLX16 "\xAF\x6B" /**< 16 bit extended run length command. */ - -#endif diff --git a/drivers/gpu/drm/udl/udl_encoder.c b/drivers/gpu/drm/udl/udl_encoder.c deleted file mode 100644 index 56e75f0..0000000 --- a/drivers/gpu/drm/udl/udl_encoder.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2012 Red Hat - * based in parts on udlfb.c: - * Copyright (C) 2009 Roberto De Ioris - * Copyright (C) 2009 Jaya Kumar - * Copyright (C) 2009 Bernie Thompson - * - * This file is subject to the terms and conditions of the GNU General Public - * License v2. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include "drmP.h" -#include "drm_crtc.h" -#include "drm_crtc_helper.h" -#include "udl_drv.h" - -/* dummy encoder */ -void udl_enc_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); - kfree(encoder); -} - -static void udl_encoder_disable(struct drm_encoder *encoder) -{ -} - -static bool udl_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static void udl_encoder_prepare(struct drm_encoder *encoder) -{ -} - -static void udl_encoder_commit(struct drm_encoder *encoder) -{ -} - -static void udl_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ -} - -static void -udl_encoder_dpms(struct drm_encoder *encoder, int mode) -{ -} - -static const struct drm_encoder_helper_funcs udl_helper_funcs = { - .dpms = udl_encoder_dpms, - .mode_fixup = udl_mode_fixup, - .prepare = udl_encoder_prepare, - .mode_set = udl_encoder_mode_set, - .commit = udl_encoder_commit, - .disable = udl_encoder_disable, -}; - -static const struct drm_encoder_funcs udl_enc_funcs = { - .destroy = udl_enc_destroy, -}; - -struct drm_encoder *udl_encoder_init(struct drm_device *dev) -{ - struct drm_encoder *encoder; - - encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL); - if (!encoder) - return NULL; - - drm_encoder_init(dev, encoder, &udl_enc_funcs, DRM_MODE_ENCODER_TMDS); - drm_encoder_helper_add(encoder, &udl_helper_funcs); - encoder->possible_crtcs = 1; - return encoder; -} diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c deleted file mode 100644 index 4d9c3a5..0000000 --- a/drivers/gpu/drm/udl/udl_fb.c +++ /dev/null @@ -1,611 +0,0 @@ -/* - * Copyright (C) 2012 Red Hat - * - * based in parts on udlfb.c: - * Copyright (C) 2009 Roberto De Ioris - * Copyright (C) 2009 Jaya Kumar - * Copyright (C) 2009 Bernie Thompson - * - * This file is subject to the terms and conditions of the GNU General Public - * License v2. See the file COPYING in the main directory of this archive for - * more details. - */ -#include -#include -#include - -#include "drmP.h" -#include "drm.h" -#include "drm_crtc.h" -#include "drm_crtc_helper.h" -#include "udl_drv.h" - -#include "drm_fb_helper.h" - -#define DL_DEFIO_WRITE_DELAY 5 /* fb_deferred_io.delay in jiffies */ - -static int fb_defio = 1; /* Optionally enable experimental fb_defio mmap support */ -static int fb_bpp = 16; - -module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); -module_param(fb_defio, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); - -struct udl_fbdev { - struct drm_fb_helper helper; - struct udl_framebuffer ufb; - struct list_head fbdev_list; - int fb_count; -}; - -#define DL_ALIGN_UP(x, a) ALIGN(x, a) -#define DL_ALIGN_DOWN(x, a) ALIGN(x-(a-1), a) - -/** Read the red component (0..255) of a 32 bpp colour. */ -#define DLO_RGB_GETRED(col) (uint8_t)((col) & 0xFF) - -/** Read the green component (0..255) of a 32 bpp colour. */ -#define DLO_RGB_GETGRN(col) (uint8_t)(((col) >> 8) & 0xFF) - -/** Read the blue component (0..255) of a 32 bpp colour. */ -#define DLO_RGB_GETBLU(col) (uint8_t)(((col) >> 16) & 0xFF) - -/** Return red/green component of a 16 bpp colour number. */ -#define DLO_RG16(red, grn) (uint8_t)((((red) & 0xF8) | ((grn) >> 5)) & 0xFF) - -/** Return green/blue component of a 16 bpp colour number. */ -#define DLO_GB16(grn, blu) (uint8_t)(((((grn) & 0x1C) << 3) | ((blu) >> 3)) & 0xFF) - -/** Return 8 bpp colour number from red, green and blue components. */ -#define DLO_RGB8(red, grn, blu) ((((red) << 5) | (((grn) & 3) << 3) | ((blu) & 7)) & 0xFF) - -#if 0 -static uint8_t rgb8(uint32_t col) -{ - uint8_t red = DLO_RGB_GETRED(col); - uint8_t grn = DLO_RGB_GETGRN(col); - uint8_t blu = DLO_RGB_GETBLU(col); - - return DLO_RGB8(red, grn, blu); -} - -static uint16_t rgb16(uint32_t col) -{ - uint8_t red = DLO_RGB_GETRED(col); - uint8_t grn = DLO_RGB_GETGRN(col); - uint8_t blu = DLO_RGB_GETBLU(col); - - return (DLO_RG16(red, grn) << 8) + DLO_GB16(grn, blu); -} -#endif - -/* - * NOTE: fb_defio.c is holding info->fbdefio.mutex - * Touching ANY framebuffer memory that triggers a page fault - * in fb_defio will cause a deadlock, when it also tries to - * grab the same mutex. - */ -static void udlfb_dpy_deferred_io(struct fb_info *info, - struct list_head *pagelist) -{ - struct page *cur; - struct fb_deferred_io *fbdefio = info->fbdefio; - struct udl_fbdev *ufbdev = info->par; - struct drm_device *dev = ufbdev->ufb.base.dev; - struct udl_device *udl = dev->dev_private; - struct urb *urb; - char *cmd; - cycles_t start_cycles, end_cycles; - int bytes_sent = 0; - int bytes_identical = 0; - int bytes_rendered = 0; - - if (!fb_defio) - return; - - start_cycles = get_cycles(); - - urb = udl_get_urb(dev); - if (!urb) - return; - - cmd = urb->transfer_buffer; - - /* walk the written page list and render each to device */ - list_for_each_entry(cur, &fbdefio->pagelist, lru) { - - if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), - &urb, (char *) info->fix.smem_start, - &cmd, cur->index << PAGE_SHIFT, - PAGE_SIZE, &bytes_identical, &bytes_sent)) - goto error; - bytes_rendered += PAGE_SIZE; - } - - if (cmd > (char *) urb->transfer_buffer) { - /* Send partial buffer remaining before exiting */ - int len = cmd - (char *) urb->transfer_buffer; - udl_submit_urb(dev, urb, len); - bytes_sent += len; - } else - udl_urb_completion(urb); - -error: - atomic_add(bytes_sent, &udl->bytes_sent); - atomic_add(bytes_identical, &udl->bytes_identical); - atomic_add(bytes_rendered, &udl->bytes_rendered); - end_cycles = get_cycles(); - atomic_add(((unsigned int) ((end_cycles - start_cycles) - >> 10)), /* Kcycles */ - &udl->cpu_kcycles_used); -} - -int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, - int width, int height) -{ - struct drm_device *dev = fb->base.dev; - struct udl_device *udl = dev->dev_private; - int i, ret; - char *cmd; - cycles_t start_cycles, end_cycles; - int bytes_sent = 0; - int bytes_identical = 0; - struct urb *urb; - int aligned_x; - int bpp = (fb->base.bits_per_pixel / 8); - - if (!fb->active_16) - return 0; - - if (!fb->obj->vmapping) - udl_gem_vmap(fb->obj); - - start_cycles = get_cycles(); - - aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long)); - width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long)); - x = aligned_x; - - if ((width <= 0) || - (x + width > fb->base.width) || - (y + height > fb->base.height)) - return -EINVAL; - - urb = udl_get_urb(dev); - if (!urb) - return 0; - cmd = urb->transfer_buffer; - - for (i = y; i < y + height ; i++) { - const int line_offset = fb->base.pitches[0] * i; - const int byte_offset = line_offset + (x * bpp); - - if (udl_render_hline(dev, bpp, &urb, - (char *) fb->obj->vmapping, - &cmd, byte_offset, width * bpp, - &bytes_identical, &bytes_sent)) - goto error; - } - - if (cmd > (char *) urb->transfer_buffer) { - /* Send partial buffer remaining before exiting */ - int len = cmd - (char *) urb->transfer_buffer; - ret = udl_submit_urb(dev, urb, len); - bytes_sent += len; - } else - udl_urb_completion(urb); - -error: - atomic_add(bytes_sent, &udl->bytes_sent); - atomic_add(bytes_identical, &udl->bytes_identical); - atomic_add(width*height*bpp, &udl->bytes_rendered); - end_cycles = get_cycles(); - atomic_add(((unsigned int) ((end_cycles - start_cycles) - >> 10)), /* Kcycles */ - &udl->cpu_kcycles_used); - - return 0; -} - -static int udl_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ - unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end - vma->vm_start; - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - unsigned long page, pos; - - if (offset + size > info->fix.smem_len) - return -EINVAL; - - pos = (unsigned long)info->fix.smem_start + offset; - - pr_notice("mmap() framebuffer addr:%lu size:%lu\n", - pos, size); - - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) - return -EAGAIN; - - start += PAGE_SIZE; - pos += PAGE_SIZE; - if (size > PAGE_SIZE) - size -= PAGE_SIZE; - else - size = 0; - } - - vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ - return 0; -} - -static void udl_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) -{ - struct udl_fbdev *ufbdev = info->par; - - sys_fillrect(info, rect); - - udl_handle_damage(&ufbdev->ufb, rect->dx, rect->dy, rect->width, - rect->height); -} - -static void udl_fb_copyarea(struct fb_info *info, const struct fb_copyarea *region) -{ - struct udl_fbdev *ufbdev = info->par; - - sys_copyarea(info, region); - - udl_handle_damage(&ufbdev->ufb, region->dx, region->dy, region->width, - region->height); -} - -static void udl_fb_imageblit(struct fb_info *info, const struct fb_image *image) -{ - struct udl_fbdev *ufbdev = info->par; - - sys_imageblit(info, image); - - udl_handle_damage(&ufbdev->ufb, image->dx, image->dy, image->width, - image->height); -} - -/* - * It's common for several clients to have framebuffer open simultaneously. - * e.g. both fbcon and X. Makes things interesting. - * Assumes caller is holding info->lock (for open and release at least) - */ -static int udl_fb_open(struct fb_info *info, int user) -{ - struct udl_fbdev *ufbdev = info->par; - struct drm_device *dev = ufbdev->ufb.base.dev; - struct udl_device *udl = dev->dev_private; - - /* If the USB device is gone, we don't accept new opens */ - if (drm_device_is_unplugged(udl->ddev)) - return -ENODEV; - - ufbdev->fb_count++; - - if (fb_defio && (info->fbdefio == NULL)) { - /* enable defio at last moment if not disabled by client */ - - struct fb_deferred_io *fbdefio; - - fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); - - if (fbdefio) { - fbdefio->delay = DL_DEFIO_WRITE_DELAY; - fbdefio->deferred_io = udlfb_dpy_deferred_io; - } - - info->fbdefio = fbdefio; - fb_deferred_io_init(info); - } - - pr_notice("open /dev/fb%d user=%d fb_info=%p count=%d\n", - info->node, user, info, ufbdev->fb_count); - - return 0; -} - - -/* - * Assumes caller is holding info->lock mutex (for open and release at least) - */ -static int udl_fb_release(struct fb_info *info, int user) -{ - struct udl_fbdev *ufbdev = info->par; - - ufbdev->fb_count--; - - if ((ufbdev->fb_count == 0) && (info->fbdefio)) { - fb_deferred_io_cleanup(info); - kfree(info->fbdefio); - info->fbdefio = NULL; - info->fbops->fb_mmap = udl_fb_mmap; - } - - pr_warn("released /dev/fb%d user=%d count=%d\n", - info->node, user, ufbdev->fb_count); - - return 0; -} - -static struct fb_ops udlfb_ops = { - .owner = THIS_MODULE, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, - .fb_fillrect = udl_fb_fillrect, - .fb_copyarea = udl_fb_copyarea, - .fb_imageblit = udl_fb_imageblit, - .fb_pan_display = drm_fb_helper_pan_display, - .fb_blank = drm_fb_helper_blank, - .fb_setcmap = drm_fb_helper_setcmap, - .fb_debug_enter = drm_fb_helper_debug_enter, - .fb_debug_leave = drm_fb_helper_debug_leave, - .fb_mmap = udl_fb_mmap, - .fb_open = udl_fb_open, - .fb_release = udl_fb_release, -}; - -void udl_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno) -{ -} - -void udl_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, int regno) -{ - *red = 0; - *green = 0; - *blue = 0; -} - -static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb, - struct drm_file *file, - unsigned flags, unsigned color, - struct drm_clip_rect *clips, - unsigned num_clips) -{ - struct udl_framebuffer *ufb = to_udl_fb(fb); - int i; - - if (!ufb->active_16) - return 0; - - for (i = 0; i < num_clips; i++) { - udl_handle_damage(ufb, clips[i].x1, clips[i].y1, - clips[i].x2 - clips[i].x1, - clips[i].y2 - clips[i].y1); - } - return 0; -} - -static void udl_user_framebuffer_destroy(struct drm_framebuffer *fb) -{ - struct udl_framebuffer *ufb = to_udl_fb(fb); - - if (ufb->obj) - drm_gem_object_unreference_unlocked(&ufb->obj->base); - - drm_framebuffer_cleanup(fb); - kfree(ufb); -} - -static const struct drm_framebuffer_funcs udlfb_funcs = { - .destroy = udl_user_framebuffer_destroy, - .dirty = udl_user_framebuffer_dirty, - .create_handle = NULL, -}; - - -static int -udl_framebuffer_init(struct drm_device *dev, - struct udl_framebuffer *ufb, - struct drm_mode_fb_cmd2 *mode_cmd, - struct udl_gem_object *obj) -{ - int ret; - - ufb->obj = obj; - ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs); - drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd); - return ret; -} - - -static int udlfb_create(struct udl_fbdev *ufbdev, - struct drm_fb_helper_surface_size *sizes) -{ - struct drm_device *dev = ufbdev->helper.dev; - struct fb_info *info; - struct device *device = &dev->usbdev->dev; - struct drm_framebuffer *fb; - struct drm_mode_fb_cmd2 mode_cmd; - struct udl_gem_object *obj; - uint32_t size; - int ret = 0; - - if (sizes->surface_bpp == 24) - sizes->surface_bpp = 32; - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8); - - mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, - sizes->surface_depth); - - size = mode_cmd.pitches[0] * mode_cmd.height; - size = ALIGN(size, PAGE_SIZE); - - obj = udl_gem_alloc_object(dev, size); - if (!obj) - goto out; - - ret = udl_gem_vmap(obj); - if (ret) { - DRM_ERROR("failed to vmap fb\n"); - goto out_gfree; - } - - info = framebuffer_alloc(0, device); - if (!info) { - ret = -ENOMEM; - goto out_gfree; - } - info->par = ufbdev; - - ret = udl_framebuffer_init(dev, &ufbdev->ufb, &mode_cmd, obj); - if (ret) - goto out_gfree; - - fb = &ufbdev->ufb.base; - - ufbdev->helper.fb = fb; - ufbdev->helper.fbdev = info; - - strcpy(info->fix.id, "udldrmfb"); - - info->screen_base = ufbdev->ufb.obj->vmapping; - info->fix.smem_len = size; - info->fix.smem_start = (unsigned long)ufbdev->ufb.obj->vmapping; - - info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; - info->fbops = &udlfb_ops; - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); - drm_fb_helper_fill_var(info, &ufbdev->helper, sizes->fb_width, sizes->fb_height); - - ret = fb_alloc_cmap(&info->cmap, 256, 0); - if (ret) { - ret = -ENOMEM; - goto out_gfree; - } - - - DRM_DEBUG_KMS("allocated %dx%d vmal %p\n", - fb->width, fb->height, - ufbdev->ufb.obj->vmapping); - - return ret; -out_gfree: - drm_gem_object_unreference(&ufbdev->ufb.obj->base); -out: - return ret; -} - -static int udl_fb_find_or_create_single(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct udl_fbdev *ufbdev = (struct udl_fbdev *)helper; - int new_fb = 0; - int ret; - - if (!helper->fb) { - ret = udlfb_create(ufbdev, sizes); - if (ret) - return ret; - - new_fb = 1; - } - return new_fb; -} - -static struct drm_fb_helper_funcs udl_fb_helper_funcs = { - .gamma_set = udl_crtc_fb_gamma_set, - .gamma_get = udl_crtc_fb_gamma_get, - .fb_probe = udl_fb_find_or_create_single, -}; - -static void udl_fbdev_destroy(struct drm_device *dev, - struct udl_fbdev *ufbdev) -{ - struct fb_info *info; - if (ufbdev->helper.fbdev) { - info = ufbdev->helper.fbdev; - unregister_framebuffer(info); - if (info->cmap.len) - fb_dealloc_cmap(&info->cmap); - framebuffer_release(info); - } - drm_fb_helper_fini(&ufbdev->helper); - drm_framebuffer_cleanup(&ufbdev->ufb.base); - drm_gem_object_unreference_unlocked(&ufbdev->ufb.obj->base); -} - -int udl_fbdev_init(struct drm_device *dev) -{ - struct udl_device *udl = dev->dev_private; - int bpp_sel = fb_bpp; - struct udl_fbdev *ufbdev; - int ret; - - ufbdev = kzalloc(sizeof(struct udl_fbdev), GFP_KERNEL); - if (!ufbdev) - return -ENOMEM; - - udl->fbdev = ufbdev; - ufbdev->helper.funcs = &udl_fb_helper_funcs; - - ret = drm_fb_helper_init(dev, &ufbdev->helper, - 1, 1); - if (ret) { - kfree(ufbdev); - return ret; - - } - - drm_fb_helper_single_add_all_connectors(&ufbdev->helper); - drm_fb_helper_initial_config(&ufbdev->helper, bpp_sel); - return 0; -} - -void udl_fbdev_cleanup(struct drm_device *dev) -{ - struct udl_device *udl = dev->dev_private; - if (!udl->fbdev) - return; - - udl_fbdev_destroy(dev, udl->fbdev); - kfree(udl->fbdev); - udl->fbdev = NULL; -} - -void udl_fbdev_unplug(struct drm_device *dev) -{ - struct udl_device *udl = dev->dev_private; - struct udl_fbdev *ufbdev; - if (!udl->fbdev) - return; - - ufbdev = udl->fbdev; - if (ufbdev->helper.fbdev) { - struct fb_info *info; - info = ufbdev->helper.fbdev; - unlink_framebuffer(info); - } -} - -struct drm_framebuffer * -udl_fb_user_fb_create(struct drm_device *dev, - struct drm_file *file, - struct drm_mode_fb_cmd2 *mode_cmd) -{ - struct drm_gem_object *obj; - struct udl_framebuffer *ufb; - int ret; - - obj = drm_gem_object_lookup(dev, file, mode_cmd->handles[0]); - if (obj == NULL) - return ERR_PTR(-ENOENT); - - ufb = kzalloc(sizeof(*ufb), GFP_KERNEL); - if (ufb == NULL) - return ERR_PTR(-ENOMEM); - - ret = udl_framebuffer_init(dev, ufb, mode_cmd, to_udl_bo(obj)); - if (ret) { - kfree(ufb); - return ERR_PTR(-EINVAL); - } - return &ufb->base; -} diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c deleted file mode 100644 index 852642d..0000000 --- a/drivers/gpu/drm/udl/udl_gem.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (C) 2012 Red Hat - * - * This file is subject to the terms and conditions of the GNU General Public - * License v2. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include "drmP.h" -#include "udl_drv.h" -#include - -struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, - size_t size) -{ - struct udl_gem_object *obj; - - obj = kzalloc(sizeof(*obj), GFP_KERNEL); - if (obj == NULL) - return NULL; - - if (drm_gem_object_init(dev, &obj->base, size) != 0) { - kfree(obj); - return NULL; - } - - return obj; -} - -static int -udl_gem_create(struct drm_file *file, - struct drm_device *dev, - uint64_t size, - uint32_t *handle_p) -{ - struct udl_gem_object *obj; - int ret; - u32 handle; - - size = roundup(size, PAGE_SIZE); - - obj = udl_gem_alloc_object(dev, size); - if (obj == NULL) - return -ENOMEM; - - ret = drm_gem_handle_create(file, &obj->base, &handle); - if (ret) { - drm_gem_object_release(&obj->base); - kfree(obj); - return ret; - } - - drm_gem_object_unreference(&obj->base); - *handle_p = handle; - return 0; -} - -int udl_dumb_create(struct drm_file *file, - struct drm_device *dev, - struct drm_mode_create_dumb *args) -{ - args->pitch = args->width * ((args->bpp + 1) / 8); - args->size = args->pitch * args->height; - return udl_gem_create(file, dev, - args->size, &args->handle); -} - -int udl_dumb_destroy(struct drm_file *file, struct drm_device *dev, - uint32_t handle) -{ - return drm_gem_handle_delete(file, handle); -} - -int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - struct udl_gem_object *obj = to_udl_bo(vma->vm_private_data); - struct page *page; - unsigned int page_offset; - int ret = 0; - - page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> - PAGE_SHIFT; - - if (!obj->pages) - return VM_FAULT_SIGBUS; - - page = obj->pages[page_offset]; - ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, page); - switch (ret) { - case -EAGAIN: - set_need_resched(); - case 0: - case -ERESTARTSYS: - return VM_FAULT_NOPAGE; - case -ENOMEM: - return VM_FAULT_OOM; - default: - return VM_FAULT_SIGBUS; - } -} - -int udl_gem_init_object(struct drm_gem_object *obj) -{ - BUG(); - - return 0; -} - -static int udl_gem_get_pages(struct udl_gem_object *obj, gfp_t gfpmask) -{ - int page_count, i; - struct page *page; - struct inode *inode; - struct address_space *mapping; - - if (obj->pages) - return 0; - - page_count = obj->base.size / PAGE_SIZE; - BUG_ON(obj->pages != NULL); - obj->pages = drm_malloc_ab(page_count, sizeof(struct page *)); - if (obj->pages == NULL) - return -ENOMEM; - - inode = obj->base.filp->f_path.dentry->d_inode; - mapping = inode->i_mapping; - gfpmask |= mapping_gfp_mask(mapping); - - for (i = 0; i < page_count; i++) { - page = shmem_read_mapping_page_gfp(mapping, i, gfpmask); - if (IS_ERR(page)) - goto err_pages; - obj->pages[i] = page; - } - - return 0; -err_pages: - while (i--) - page_cache_release(obj->pages[i]); - drm_free_large(obj->pages); - obj->pages = NULL; - return PTR_ERR(page); -} - -static void udl_gem_put_pages(struct udl_gem_object *obj) -{ - int page_count = obj->base.size / PAGE_SIZE; - int i; - - for (i = 0; i < page_count; i++) - page_cache_release(obj->pages[i]); - - drm_free_large(obj->pages); - obj->pages = NULL; -} - -int udl_gem_vmap(struct udl_gem_object *obj) -{ - int page_count = obj->base.size / PAGE_SIZE; - int ret; - - ret = udl_gem_get_pages(obj, GFP_KERNEL); - if (ret) - return ret; - - obj->vmapping = vmap(obj->pages, page_count, 0, PAGE_KERNEL); - if (!obj->vmapping) - return -ENOMEM; - return 0; -} - -void udl_gem_vunmap(struct udl_gem_object *obj) -{ - if (obj->vmapping) - vunmap(obj->vmapping); - - udl_gem_put_pages(obj); -} - -void udl_gem_free_object(struct drm_gem_object *gem_obj) -{ - struct udl_gem_object *obj = to_udl_bo(gem_obj); - - if (obj->vmapping) - udl_gem_vunmap(obj); - - if (obj->pages) - udl_gem_put_pages(obj); - - if (gem_obj->map_list.map) - drm_gem_free_mmap_offset(gem_obj); -} - -/* the dumb interface doesn't work with the GEM straight MMAP - interface, it expects to do MMAP on the drm fd, like normal */ -int udl_gem_mmap(struct drm_file *file, struct drm_device *dev, - uint32_t handle, uint64_t *offset) -{ - struct udl_gem_object *gobj; - struct drm_gem_object *obj; - int ret = 0; - - mutex_lock(&dev->struct_mutex); - obj = drm_gem_object_lookup(dev, file, handle); - if (obj == NULL) { - ret = -ENOENT; - goto unlock; - } - gobj = to_udl_bo(obj); - - ret = udl_gem_get_pages(gobj, GFP_KERNEL); - if (ret) - return ret; - if (!gobj->base.map_list.map) { - ret = drm_gem_create_mmap_offset(obj); - if (ret) - goto out; - } - - *offset = (u64)gobj->base.map_list.hash.key << PAGE_SHIFT; - -out: - drm_gem_object_unreference(&gobj->base); -unlock: - mutex_unlock(&dev->struct_mutex); - return ret; -} diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c deleted file mode 100644 index a8d5f09..0000000 --- a/drivers/gpu/drm/udl/udl_main.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (C) 2012 Red Hat - * - * based in parts on udlfb.c: - * Copyright (C) 2009 Roberto De Ioris - * Copyright (C) 2009 Jaya Kumar - * Copyright (C) 2009 Bernie Thompson - * - * This file is subject to the terms and conditions of the GNU General Public - * License v2. See the file COPYING in the main directory of this archive for - * more details. - */ -#include "drmP.h" -#include "udl_drv.h" - -/* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */ -#define BULK_SIZE 512 - -#define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE) -#define WRITES_IN_FLIGHT (4) -#define MAX_VENDOR_DESCRIPTOR_SIZE 256 - -#define GET_URB_TIMEOUT HZ -#define FREE_URB_TIMEOUT (HZ*2) - -static int udl_parse_vendor_descriptor(struct drm_device *dev, - struct usb_device *usbdev) -{ - struct udl_device *udl = dev->dev_private; - char *desc; - char *buf; - char *desc_end; - - u8 total_len = 0; - - buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL); - if (!buf) - return false; - desc = buf; - - total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */ - 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE); - if (total_len > 5) { - DRM_INFO("vendor descriptor length:%x data:%02x %02x %02x %02x" \ - "%02x %02x %02x %02x %02x %02x %02x\n", - total_len, desc[0], - desc[1], desc[2], desc[3], desc[4], desc[5], desc[6], - desc[7], desc[8], desc[9], desc[10]); - - if ((desc[0] != total_len) || /* descriptor length */ - (desc[1] != 0x5f) || /* vendor descriptor type */ - (desc[2] != 0x01) || /* version (2 bytes) */ - (desc[3] != 0x00) || - (desc[4] != total_len - 2)) /* length after type */ - goto unrecognized; - - desc_end = desc + total_len; - desc += 5; /* the fixed header we've already parsed */ - - while (desc < desc_end) { - u8 length; - u16 key; - - key = *((u16 *) desc); - desc += sizeof(u16); - length = *desc; - desc++; - - switch (key) { - case 0x0200: { /* max_area */ - u32 max_area; - max_area = le32_to_cpu(*((u32 *)desc)); - DRM_DEBUG("DL chip limited to %d pixel modes\n", - max_area); - udl->sku_pixel_limit = max_area; - break; - } - default: - break; - } - desc += length; - } - } - - goto success; - -unrecognized: - /* allow udlfb to load for now even if firmware unrecognized */ - DRM_ERROR("Unrecognized vendor firmware descriptor\n"); - -success: - kfree(buf); - return true; -} - -static void udl_release_urb_work(struct work_struct *work) -{ - struct urb_node *unode = container_of(work, struct urb_node, - release_urb_work.work); - - up(&unode->dev->urbs.limit_sem); -} - -void udl_urb_completion(struct urb *urb) -{ - struct urb_node *unode = urb->context; - struct udl_device *udl = unode->dev; - unsigned long flags; - - /* sync/async unlink faults aren't errors */ - if (urb->status) { - if (!(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN)) { - DRM_ERROR("%s - nonzero write bulk status received: %d\n", - __func__, urb->status); - atomic_set(&udl->lost_pixels, 1); - } - } - - urb->transfer_buffer_length = udl->urbs.size; /* reset to actual */ - - spin_lock_irqsave(&udl->urbs.lock, flags); - list_add_tail(&unode->entry, &udl->urbs.list); - udl->urbs.available++; - spin_unlock_irqrestore(&udl->urbs.lock, flags); - -#if 0 - /* - * When using fb_defio, we deadlock if up() is called - * while another is waiting. So queue to another process. - */ - if (fb_defio) - schedule_delayed_work(&unode->release_urb_work, 0); - else -#endif - up(&udl->urbs.limit_sem); -} - -static void udl_free_urb_list(struct drm_device *dev) -{ - struct udl_device *udl = dev->dev_private; - int count = udl->urbs.count; - struct list_head *node; - struct urb_node *unode; - struct urb *urb; - int ret; - unsigned long flags; - - DRM_DEBUG("Waiting for completes and freeing all render urbs\n"); - - /* keep waiting and freeing, until we've got 'em all */ - while (count--) { - - /* Getting interrupted means a leak, but ok at shutdown*/ - ret = down_interruptible(&udl->urbs.limit_sem); - if (ret) - break; - - spin_lock_irqsave(&udl->urbs.lock, flags); - - node = udl->urbs.list.next; /* have reserved one with sem */ - list_del_init(node); - - spin_unlock_irqrestore(&udl->urbs.lock, flags); - - unode = list_entry(node, struct urb_node, entry); - urb = unode->urb; - - /* Free each separately allocated piece */ - usb_free_coherent(urb->dev, udl->urbs.size, - urb->transfer_buffer, urb->transfer_dma); - usb_free_urb(urb); - kfree(node); - } - udl->urbs.count = 0; -} - -static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) -{ - struct udl_device *udl = dev->dev_private; - int i = 0; - struct urb *urb; - struct urb_node *unode; - char *buf; - - spin_lock_init(&udl->urbs.lock); - - udl->urbs.size = size; - INIT_LIST_HEAD(&udl->urbs.list); - - while (i < count) { - unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL); - if (!unode) - break; - unode->dev = udl; - - INIT_DELAYED_WORK(&unode->release_urb_work, - udl_release_urb_work); - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - kfree(unode); - break; - } - unode->urb = urb; - - buf = usb_alloc_coherent(udl->ddev->usbdev, MAX_TRANSFER, GFP_KERNEL, - &urb->transfer_dma); - if (!buf) { - kfree(unode); - usb_free_urb(urb); - break; - } - - /* urb->transfer_buffer_length set to actual before submit */ - usb_fill_bulk_urb(urb, udl->ddev->usbdev, usb_sndbulkpipe(udl->ddev->usbdev, 1), - buf, size, udl_urb_completion, unode); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - list_add_tail(&unode->entry, &udl->urbs.list); - - i++; - } - - sema_init(&udl->urbs.limit_sem, i); - udl->urbs.count = i; - udl->urbs.available = i; - - DRM_DEBUG("allocated %d %d byte urbs\n", i, (int) size); - - return i; -} - -struct urb *udl_get_urb(struct drm_device *dev) -{ - struct udl_device *udl = dev->dev_private; - int ret = 0; - struct list_head *entry; - struct urb_node *unode; - struct urb *urb = NULL; - unsigned long flags; - - /* Wait for an in-flight buffer to complete and get re-queued */ - ret = down_timeout(&udl->urbs.limit_sem, GET_URB_TIMEOUT); - if (ret) { - atomic_set(&udl->lost_pixels, 1); - DRM_INFO("wait for urb interrupted: %x available: %d\n", - ret, udl->urbs.available); - goto error; - } - - spin_lock_irqsave(&udl->urbs.lock, flags); - - BUG_ON(list_empty(&udl->urbs.list)); /* reserved one with limit_sem */ - entry = udl->urbs.list.next; - list_del_init(entry); - udl->urbs.available--; - - spin_unlock_irqrestore(&udl->urbs.lock, flags); - - unode = list_entry(entry, struct urb_node, entry); - urb = unode->urb; - -error: - return urb; -} - -int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len) -{ - struct udl_device *udl = dev->dev_private; - int ret; - - BUG_ON(len > udl->urbs.size); - - urb->transfer_buffer_length = len; /* set to actual payload len */ - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) { - udl_urb_completion(urb); /* because no one else will */ - atomic_set(&udl->lost_pixels, 1); - DRM_ERROR("usb_submit_urb error %x\n", ret); - } - return ret; -} - -int udl_driver_load(struct drm_device *dev, unsigned long flags) -{ - struct udl_device *udl; - int ret; - - DRM_DEBUG("\n"); - udl = kzalloc(sizeof(struct udl_device), GFP_KERNEL); - if (!udl) - return -ENOMEM; - - udl->ddev = dev; - dev->dev_private = udl; - - if (!udl_parse_vendor_descriptor(dev, dev->usbdev)) { - DRM_ERROR("firmware not recognized. Assume incompatible device\n"); - goto err; - } - - if (!udl_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) { - ret = -ENOMEM; - DRM_ERROR("udl_alloc_urb_list failed\n"); - goto err; - } - - DRM_DEBUG("\n"); - ret = udl_modeset_init(dev); - - ret = udl_fbdev_init(dev); - return 0; -err: - kfree(udl); - DRM_ERROR("%d\n", ret); - return ret; -} - -int udl_drop_usb(struct drm_device *dev) -{ - udl_free_urb_list(dev); - return 0; -} - -int udl_driver_unload(struct drm_device *dev) -{ - struct udl_device *udl = dev->dev_private; - - if (udl->urbs.count) - udl_free_urb_list(dev); - - udl_fbdev_cleanup(dev); - udl_modeset_cleanup(dev); - kfree(udl); - return 0; -} diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c deleted file mode 100644 index b3ecb3d..0000000 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (C) 2012 Red Hat - * - * based in parts on udlfb.c: - * Copyright (C) 2009 Roberto De Ioris - * Copyright (C) 2009 Jaya Kumar - * Copyright (C) 2009 Bernie Thompson - - * This file is subject to the terms and conditions of the GNU General Public - * License v2. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include "drmP.h" -#include "drm_crtc.h" -#include "drm_crtc_helper.h" -#include "udl_drv.h" - -/* - * All DisplayLink bulk operations start with 0xAF, followed by specific code - * All operations are written to buffers which then later get sent to device - */ -static char *udl_set_register(char *buf, u8 reg, u8 val) -{ - *buf++ = 0xAF; - *buf++ = 0x20; - *buf++ = reg; - *buf++ = val; - return buf; -} - -static char *udl_vidreg_lock(char *buf) -{ - return udl_set_register(buf, 0xFF, 0x00); -} - -static char *udl_vidreg_unlock(char *buf) -{ - return udl_set_register(buf, 0xFF, 0xFF); -} - -/* - * On/Off for driving the DisplayLink framebuffer to the display - * 0x00 H and V sync on - * 0x01 H and V sync off (screen blank but powered) - * 0x07 DPMS powerdown (requires modeset to come back) - */ -static char *udl_enable_hvsync(char *buf, bool enable) -{ - if (enable) - return udl_set_register(buf, 0x1F, 0x00); - else - return udl_set_register(buf, 0x1F, 0x07); -} - -static char *udl_set_color_depth(char *buf, u8 selection) -{ - return udl_set_register(buf, 0x00, selection); -} - -static char *udl_set_base16bpp(char *wrptr, u32 base) -{ - /* the base pointer is 16 bits wide, 0x20 is hi byte. */ - wrptr = udl_set_register(wrptr, 0x20, base >> 16); - wrptr = udl_set_register(wrptr, 0x21, base >> 8); - return udl_set_register(wrptr, 0x22, base); -} - -/* - * DisplayLink HW has separate 16bpp and 8bpp framebuffers. - * In 24bpp modes, the low 323 RGB bits go in the 8bpp framebuffer - */ -static char *udl_set_base8bpp(char *wrptr, u32 base) -{ - wrptr = udl_set_register(wrptr, 0x26, base >> 16); - wrptr = udl_set_register(wrptr, 0x27, base >> 8); - return udl_set_register(wrptr, 0x28, base); -} - -static char *udl_set_register_16(char *wrptr, u8 reg, u16 value) -{ - wrptr = udl_set_register(wrptr, reg, value >> 8); - return udl_set_register(wrptr, reg+1, value); -} - -/* - * This is kind of weird because the controller takes some - * register values in a different byte order than other registers. - */ -static char *udl_set_register_16be(char *wrptr, u8 reg, u16 value) -{ - wrptr = udl_set_register(wrptr, reg, value); - return udl_set_register(wrptr, reg+1, value >> 8); -} - -/* - * LFSR is linear feedback shift register. The reason we have this is - * because the display controller needs to minimize the clock depth of - * various counters used in the display path. So this code reverses the - * provided value into the lfsr16 value by counting backwards to get - * the value that needs to be set in the hardware comparator to get the - * same actual count. This makes sense once you read above a couple of - * times and think about it from a hardware perspective. - */ -static u16 udl_lfsr16(u16 actual_count) -{ - u32 lv = 0xFFFF; /* This is the lfsr value that the hw starts with */ - - while (actual_count--) { - lv = ((lv << 1) | - (((lv >> 15) ^ (lv >> 4) ^ (lv >> 2) ^ (lv >> 1)) & 1)) - & 0xFFFF; - } - - return (u16) lv; -} - -/* - * This does LFSR conversion on the value that is to be written. - * See LFSR explanation above for more detail. - */ -static char *udl_set_register_lfsr16(char *wrptr, u8 reg, u16 value) -{ - return udl_set_register_16(wrptr, reg, udl_lfsr16(value)); -} - -/* - * This takes a standard fbdev screeninfo struct and all of its monitor mode - * details and converts them into the DisplayLink equivalent register commands. - ERR(vreg(dev, 0x00, (color_depth == 16) ? 0 : 1)); - ERR(vreg_lfsr16(dev, 0x01, xDisplayStart)); - ERR(vreg_lfsr16(dev, 0x03, xDisplayEnd)); - ERR(vreg_lfsr16(dev, 0x05, yDisplayStart)); - ERR(vreg_lfsr16(dev, 0x07, yDisplayEnd)); - ERR(vreg_lfsr16(dev, 0x09, xEndCount)); - ERR(vreg_lfsr16(dev, 0x0B, hSyncStart)); - ERR(vreg_lfsr16(dev, 0x0D, hSyncEnd)); - ERR(vreg_big_endian(dev, 0x0F, hPixels)); - ERR(vreg_lfsr16(dev, 0x11, yEndCount)); - ERR(vreg_lfsr16(dev, 0x13, vSyncStart)); - ERR(vreg_lfsr16(dev, 0x15, vSyncEnd)); - ERR(vreg_big_endian(dev, 0x17, vPixels)); - ERR(vreg_little_endian(dev, 0x1B, pixelClock5KHz)); - - ERR(vreg(dev, 0x1F, 0)); - - ERR(vbuf(dev, WRITE_VIDREG_UNLOCK, DSIZEOF(WRITE_VIDREG_UNLOCK))); - */ -static char *udl_set_vid_cmds(char *wrptr, struct drm_display_mode *mode) -{ - u16 xds, yds; - u16 xde, yde; - u16 yec; - - /* x display start */ - xds = mode->crtc_htotal - mode->crtc_hsync_start; - wrptr = udl_set_register_lfsr16(wrptr, 0x01, xds); - /* x display end */ - xde = xds + mode->crtc_hdisplay; - wrptr = udl_set_register_lfsr16(wrptr, 0x03, xde); - - /* y display start */ - yds = mode->crtc_vtotal - mode->crtc_vsync_start; - wrptr = udl_set_register_lfsr16(wrptr, 0x05, yds); - /* y display end */ - yde = yds + mode->crtc_vdisplay; - wrptr = udl_set_register_lfsr16(wrptr, 0x07, yde); - - /* x end count is active + blanking - 1 */ - wrptr = udl_set_register_lfsr16(wrptr, 0x09, - mode->crtc_htotal - 1); - - /* libdlo hardcodes hsync start to 1 */ - wrptr = udl_set_register_lfsr16(wrptr, 0x0B, 1); - - /* hsync end is width of sync pulse + 1 */ - wrptr = udl_set_register_lfsr16(wrptr, 0x0D, - mode->crtc_hsync_end - mode->crtc_hsync_start + 1); - - /* hpixels is active pixels */ - wrptr = udl_set_register_16(wrptr, 0x0F, mode->hdisplay); - - /* yendcount is vertical active + vertical blanking */ - yec = mode->crtc_vtotal; - wrptr = udl_set_register_lfsr16(wrptr, 0x11, yec); - - /* libdlo hardcodes vsync start to 0 */ - wrptr = udl_set_register_lfsr16(wrptr, 0x13, 0); - - /* vsync end is width of vsync pulse */ - wrptr = udl_set_register_lfsr16(wrptr, 0x15, mode->crtc_vsync_end - mode->crtc_vsync_start); - - /* vpixels is active pixels */ - wrptr = udl_set_register_16(wrptr, 0x17, mode->crtc_vdisplay); - - wrptr = udl_set_register_16be(wrptr, 0x1B, - mode->clock / 5); - - return wrptr; -} - -static int udl_crtc_write_mode_to_hw(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct udl_device *udl = dev->dev_private; - struct urb *urb; - char *buf; - int retval; - - urb = udl_get_urb(dev); - if (!urb) - return -ENOMEM; - - buf = (char *)urb->transfer_buffer; - - memcpy(buf, udl->mode_buf, udl->mode_buf_len); - retval = udl_submit_urb(dev, urb, udl->mode_buf_len); - DRM_INFO("write mode info %d\n", udl->mode_buf_len); - return retval; -} - - -static void udl_crtc_dpms(struct drm_crtc *crtc, int mode) -{ - struct drm_device *dev = crtc->dev; - struct udl_device *udl = dev->dev_private; - int retval; - - if (mode == DRM_MODE_DPMS_OFF) { - char *buf; - struct urb *urb; - urb = udl_get_urb(dev); - if (!urb) - return; - - buf = (char *)urb->transfer_buffer; - buf = udl_vidreg_lock(buf); - buf = udl_enable_hvsync(buf, false); - buf = udl_vidreg_unlock(buf); - - retval = udl_submit_urb(dev, urb, buf - (char *) - urb->transfer_buffer); - } else { - if (udl->mode_buf_len == 0) { - DRM_ERROR("Trying to enable DPMS with no mode\n"); - return; - } - udl_crtc_write_mode_to_hw(crtc); - } - -} - -static bool udl_crtc_mode_fixup(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) - -{ - return true; -} - -#if 0 -static int -udl_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - int x, int y, enum mode_set_atomic state) -{ - return 0; -} - -static int -udl_pipe_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) -{ - return 0; -} -#endif - -static int udl_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - int x, int y, - struct drm_framebuffer *old_fb) - -{ - struct drm_device *dev = crtc->dev; - struct udl_framebuffer *ufb = to_udl_fb(crtc->fb); - struct udl_device *udl = dev->dev_private; - char *buf; - char *wrptr; - int color_depth = 0; - - buf = (char *)udl->mode_buf; - - /* for now we just clip 24 -> 16 - if we fix that fix this */ - /*if (crtc->fb->bits_per_pixel != 16) - color_depth = 1; */ - - /* This first section has to do with setting the base address on the - * controller * associated with the display. There are 2 base - * pointers, currently, we only * use the 16 bpp segment. - */ - wrptr = udl_vidreg_lock(buf); - wrptr = udl_set_color_depth(wrptr, color_depth); - /* set base for 16bpp segment to 0 */ - wrptr = udl_set_base16bpp(wrptr, 0); - /* set base for 8bpp segment to end of fb */ - wrptr = udl_set_base8bpp(wrptr, 2 * mode->vdisplay * mode->hdisplay); - - wrptr = udl_set_vid_cmds(wrptr, adjusted_mode); - wrptr = udl_enable_hvsync(wrptr, true); - wrptr = udl_vidreg_unlock(wrptr); - - ufb->active_16 = true; - if (old_fb) { - struct udl_framebuffer *uold_fb = to_udl_fb(old_fb); - uold_fb->active_16 = false; - } - udl->mode_buf_len = wrptr - buf; - - /* damage all of it */ - udl_handle_damage(ufb, 0, 0, ufb->base.width, ufb->base.height); - return 0; -} - - -static void udl_crtc_disable(struct drm_crtc *crtc) -{ - - -} - -static void udl_crtc_destroy(struct drm_crtc *crtc) -{ - drm_crtc_cleanup(crtc); - kfree(crtc); -} - -static void udl_load_lut(struct drm_crtc *crtc) -{ -} - -static void udl_crtc_prepare(struct drm_crtc *crtc) -{ -} - -static void udl_crtc_commit(struct drm_crtc *crtc) -{ - udl_crtc_dpms(crtc, DRM_MODE_DPMS_ON); -} - -static struct drm_crtc_helper_funcs udl_helper_funcs = { - .dpms = udl_crtc_dpms, - .mode_fixup = udl_crtc_mode_fixup, - .mode_set = udl_crtc_mode_set, - .prepare = udl_crtc_prepare, - .commit = udl_crtc_commit, - .disable = udl_crtc_disable, - .load_lut = udl_load_lut, -}; - -static const struct drm_crtc_funcs udl_crtc_funcs = { - .set_config = drm_crtc_helper_set_config, - .destroy = udl_crtc_destroy, -}; - -int udl_crtc_init(struct drm_device *dev) -{ - struct drm_crtc *crtc; - - crtc = kzalloc(sizeof(struct drm_crtc) + sizeof(struct drm_connector *), GFP_KERNEL); - if (crtc == NULL) - return -ENOMEM; - - drm_crtc_init(dev, crtc, &udl_crtc_funcs); - drm_crtc_helper_add(crtc, &udl_helper_funcs); - - return 0; -} - -static const struct drm_mode_config_funcs udl_mode_funcs = { - .fb_create = udl_fb_user_fb_create, - .output_poll_changed = NULL, -}; - -int udl_modeset_init(struct drm_device *dev) -{ - struct drm_encoder *encoder; - drm_mode_config_init(dev); - - dev->mode_config.min_width = 640; - dev->mode_config.min_height = 480; - - dev->mode_config.max_width = 2048; - dev->mode_config.max_height = 2048; - - dev->mode_config.prefer_shadow = 0; - dev->mode_config.preferred_depth = 24; - - dev->mode_config.funcs = (void *)&udl_mode_funcs; - - drm_mode_create_dirty_info_property(dev); - - udl_crtc_init(dev); - - encoder = udl_encoder_init(dev); - - udl_connector_init(dev, encoder); - - return 0; -} - -void udl_modeset_cleanup(struct drm_device *dev) -{ - drm_mode_config_cleanup(dev); -} diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c deleted file mode 100644 index b9320e2..0000000 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (C) 2012 Red Hat - * based in parts on udlfb.c: - * Copyright (C) 2009 Roberto De Ioris - * Copyright (C) 2009 Jaya Kumar - * Copyright (C) 2009 Bernie Thompson - * - * This file is subject to the terms and conditions of the GNU General Public - * License v2. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include -#include -#include -#include - -#include "drmP.h" -#include "udl_drv.h" - -#define MAX_CMD_PIXELS 255 - -#define RLX_HEADER_BYTES 7 -#define MIN_RLX_PIX_BYTES 4 -#define MIN_RLX_CMD_BYTES (RLX_HEADER_BYTES + MIN_RLX_PIX_BYTES) - -#define RLE_HEADER_BYTES 6 -#define MIN_RLE_PIX_BYTES 3 -#define MIN_RLE_CMD_BYTES (RLE_HEADER_BYTES + MIN_RLE_PIX_BYTES) - -#define RAW_HEADER_BYTES 6 -#define MIN_RAW_PIX_BYTES 2 -#define MIN_RAW_CMD_BYTES (RAW_HEADER_BYTES + MIN_RAW_PIX_BYTES) - -/* - * Trims identical data from front and back of line - * Sets new front buffer address and width - * And returns byte count of identical pixels - * Assumes CPU natural alignment (unsigned long) - * for back and front buffer ptrs and width - */ -#if 0 -static int udl_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes) -{ - int j, k; - const unsigned long *back = (const unsigned long *) bback; - const unsigned long *front = (const unsigned long *) *bfront; - const int width = *width_bytes / sizeof(unsigned long); - int identical = width; - int start = width; - int end = width; - - prefetch((void *) front); - prefetch((void *) back); - - for (j = 0; j < width; j++) { - if (back[j] != front[j]) { - start = j; - break; - } - } - - for (k = width - 1; k > j; k--) { - if (back[k] != front[k]) { - end = k+1; - break; - } - } - - identical = start + (width - end); - *bfront = (u8 *) &front[start]; - *width_bytes = (end - start) * sizeof(unsigned long); - - return identical * sizeof(unsigned long); -} -#endif - -static inline u16 pixel32_to_be16p(const uint8_t *pixel) -{ - uint32_t pix = *(uint32_t *)pixel; - u16 retval; - - retval = (((pix >> 3) & 0x001f) | - ((pix >> 5) & 0x07e0) | - ((pix >> 8) & 0xf800)); - return retval; -} - -/* - * Render a command stream for an encoded horizontal line segment of pixels. - * - * A command buffer holds several commands. - * It always begins with a fresh command header - * (the protocol doesn't require this, but we enforce it to allow - * multiple buffers to be potentially encoded and sent in parallel). - * A single command encodes one contiguous horizontal line of pixels - * - * The function relies on the client to do all allocation, so that - * rendering can be done directly to output buffers (e.g. USB URBs). - * The function fills the supplied command buffer, providing information - * on where it left off, so the client may call in again with additional - * buffers if the line will take several buffers to complete. - * - * A single command can transmit a maximum of 256 pixels, - * regardless of the compression ratio (protocol design limit). - * To the hardware, 0 for a size byte means 256 - * - * Rather than 256 pixel commands which are either rl or raw encoded, - * the rlx command simply assumes alternating raw and rl spans within one cmd. - * This has a slightly larger header overhead, but produces more even results. - * It also processes all data (read and write) in a single pass. - * Performance benchmarks of common cases show it having just slightly better - * compression than 256 pixel raw or rle commands, with similar CPU consumpion. - * But for very rl friendly data, will compress not quite as well. - */ -static void udl_compress_hline16( - const u8 **pixel_start_ptr, - const u8 *const pixel_end, - uint32_t *device_address_ptr, - uint8_t **command_buffer_ptr, - const uint8_t *const cmd_buffer_end, int bpp) -{ - const u8 *pixel = *pixel_start_ptr; - uint32_t dev_addr = *device_address_ptr; - uint8_t *cmd = *command_buffer_ptr; - - while ((pixel_end > pixel) && - (cmd_buffer_end - MIN_RLX_CMD_BYTES > cmd)) { - uint8_t *raw_pixels_count_byte = 0; - uint8_t *cmd_pixels_count_byte = 0; - const u8 *raw_pixel_start = 0; - const u8 *cmd_pixel_start, *cmd_pixel_end = 0; - - prefetchw((void *) cmd); /* pull in one cache line at least */ - - *cmd++ = 0xaf; - *cmd++ = 0x6b; - *cmd++ = (uint8_t) ((dev_addr >> 16) & 0xFF); - *cmd++ = (uint8_t) ((dev_addr >> 8) & 0xFF); - *cmd++ = (uint8_t) ((dev_addr) & 0xFF); - - cmd_pixels_count_byte = cmd++; /* we'll know this later */ - cmd_pixel_start = pixel; - - raw_pixels_count_byte = cmd++; /* we'll know this later */ - raw_pixel_start = pixel; - - cmd_pixel_end = pixel + (min(MAX_CMD_PIXELS + 1, - min((int)(pixel_end - pixel) / bpp, - (int)(cmd_buffer_end - cmd) / 2))) * bpp; - - prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp); - - while (pixel < cmd_pixel_end) { - const u8 * const repeating_pixel = pixel; - - if (bpp == 2) - *(uint16_t *)cmd = cpu_to_be16p((uint16_t *)pixel); - else if (bpp == 4) - *(uint16_t *)cmd = cpu_to_be16(pixel32_to_be16p(pixel)); - - cmd += 2; - pixel += bpp; - - if (unlikely((pixel < cmd_pixel_end) && - (!memcmp(pixel, repeating_pixel, bpp)))) { - /* go back and fill in raw pixel count */ - *raw_pixels_count_byte = (((repeating_pixel - - raw_pixel_start) / bpp) + 1) & 0xFF; - - while ((pixel < cmd_pixel_end) - && (!memcmp(pixel, repeating_pixel, bpp))) { - pixel += bpp; - } - - /* immediately after raw data is repeat byte */ - *cmd++ = (((pixel - repeating_pixel) / bpp) - 1) & 0xFF; - - /* Then start another raw pixel span */ - raw_pixel_start = pixel; - raw_pixels_count_byte = cmd++; - } - } - - if (pixel > raw_pixel_start) { - /* finalize last RAW span */ - *raw_pixels_count_byte = ((pixel-raw_pixel_start) / bpp) & 0xFF; - } - - *cmd_pixels_count_byte = ((pixel - cmd_pixel_start) / bpp) & 0xFF; - dev_addr += ((pixel - cmd_pixel_start) / bpp) * 2; - } - - if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) { - /* Fill leftover bytes with no-ops */ - if (cmd_buffer_end > cmd) - memset(cmd, 0xAF, cmd_buffer_end - cmd); - cmd = (uint8_t *) cmd_buffer_end; - } - - *command_buffer_ptr = cmd; - *pixel_start_ptr = pixel; - *device_address_ptr = dev_addr; - - return; -} - -/* - * There are 3 copies of every pixel: The front buffer that the fbdev - * client renders to, the actual framebuffer across the USB bus in hardware - * (that we can only write to, slowly, and can never read), and (optionally) - * our shadow copy that tracks what's been sent to that hardware buffer. - */ -int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, - const char *front, char **urb_buf_ptr, - u32 byte_offset, u32 byte_width, - int *ident_ptr, int *sent_ptr) -{ - const u8 *line_start, *line_end, *next_pixel; - u32 base16 = 0 + (byte_offset / bpp) * 2; - struct urb *urb = *urb_ptr; - u8 *cmd = *urb_buf_ptr; - u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; - - line_start = (u8 *) (front + byte_offset); - next_pixel = line_start; - line_end = next_pixel + byte_width; - - while (next_pixel < line_end) { - - udl_compress_hline16(&next_pixel, - line_end, &base16, - (u8 **) &cmd, (u8 *) cmd_end, bpp); - - if (cmd >= cmd_end) { - int len = cmd - (u8 *) urb->transfer_buffer; - if (udl_submit_urb(dev, urb, len)) - return 1; /* lost pixels is set */ - *sent_ptr += len; - urb = udl_get_urb(dev); - if (!urb) - return 1; /* lost_pixels is set */ - *urb_ptr = urb; - cmd = urb->transfer_buffer; - cmd_end = &cmd[urb->transfer_buffer_length]; - } - } - - *urb_buf_ptr = cmd; - - return 0; -} - diff --git a/drivers/gpu/ion/Kconfig b/drivers/gpu/ion/Kconfig index 68aa440..32d9f3f 100644 --- a/drivers/gpu/ion/Kconfig +++ b/drivers/gpu/ion/Kconfig @@ -4,12 +4,6 @@ menuconfig ION help Chose this option to enable the ION Memory Manager. -config ION_TEGRA - tristate "Ion for Tegra" - depends on ARCH_TEGRA && ION - help - Choose this option if you wish to use ion on an nVidia Tegra. - config ION_EXYNOS tristate "Ion for Exynos" depends on ARCH_EXYNOS && ION diff --git a/drivers/gpu/ion/Makefile b/drivers/gpu/ion/Makefile index b7a6956..d44a052 100644 --- a/drivers/gpu/ion/Makefile +++ b/drivers/gpu/ion/Makefile @@ -1,3 +1,2 @@ obj-$(CONFIG_ION) += ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o -obj-$(CONFIG_ION_TEGRA) += tegra/ obj-$(CONFIG_ION_EXYNOS) += exynos/ diff --git a/drivers/gpu/ion/tegra/Makefile b/drivers/gpu/ion/tegra/Makefile deleted file mode 100644 index 11cd003..0000000 --- a/drivers/gpu/ion/tegra/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += tegra_ion.o diff --git a/drivers/gpu/ion/tegra/tegra_ion.c b/drivers/gpu/ion/tegra/tegra_ion.c deleted file mode 100644 index 7af6e16..0000000 --- a/drivers/gpu/ion/tegra/tegra_ion.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * drivers/gpu/tegra/tegra_ion.c - * - * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include "../ion_priv.h" - -struct ion_device *idev; -struct ion_mapper *tegra_user_mapper; -int num_heaps; -struct ion_heap **heaps; - -int tegra_ion_probe(struct platform_device *pdev) -{ - struct ion_platform_data *pdata = pdev->dev.platform_data; - int err; - int i; - - num_heaps = pdata->nr; - - heaps = kzalloc(sizeof(struct ion_heap *) * pdata->nr, GFP_KERNEL); - - idev = ion_device_create(NULL); - if (IS_ERR_OR_NULL(idev)) { - kfree(heaps); - return PTR_ERR(idev); - } - - /* create the heaps as specified in the board file */ - for (i = 0; i < num_heaps; i++) { - struct ion_platform_heap *heap_data = &pdata->heaps[i]; - - heaps[i] = ion_heap_create(heap_data); - if (IS_ERR_OR_NULL(heaps[i])) { - err = PTR_ERR(heaps[i]); - goto err; - } - ion_device_add_heap(idev, heaps[i]); - } - platform_set_drvdata(pdev, idev); - return 0; -err: - for (i = 0; i < num_heaps; i++) { - if (heaps[i]) - ion_heap_destroy(heaps[i]); - } - kfree(heaps); - return err; -} - -int tegra_ion_remove(struct platform_device *pdev) -{ - struct ion_device *idev = platform_get_drvdata(pdev); - int i; - - ion_device_destroy(idev); - for (i = 0; i < num_heaps; i++) - ion_heap_destroy(heaps[i]); - kfree(heaps); - return 0; -} - -static struct platform_driver ion_driver = { - .probe = tegra_ion_probe, - .remove = tegra_ion_remove, - .driver = { .name = "ion-tegra" } -}; - -static int __init ion_init(void) -{ - return platform_driver_register(&ion_driver); -} - -static void __exit ion_exit(void) -{ - platform_driver_unregister(&ion_driver); -} - -module_init(ion_init); -module_exit(ion_exit); - -- cgit v1.1