dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* (unknown)
@ 2010-10-27  1:26 Dave Airlie
  0 siblings, 0 replies; 35+ messages in thread
From: Dave Airlie @ 2010-10-27  1:26 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel, DRI mailing list

[-- Attachment #1: Type: TEXT/PLAIN, Size: 45956 bytes --]


Hi Linus,

sorry this is a bit later than I expected got sidetracked into a real-life 
gastro bug for a couple of days just after merge window opened,

Main features amongst it all:
new stub driver for poulsbo backlight support
drm core: kdb lut support, lots of cleanups, edid enhancement for audio 
capability
ttm: optimised eviction process (saves a lot of unnecessary object 
movement) + allow an alternate underlying memory manager to be plugged in
vmware: bring in line with upstream changes + use alternate memory manager
nouveau: iniital power management support, hardware inter-channel sync,
better handling of gpu errors and non-mappable VRAM, tiling corruption 
fixes, nvaf support
radeon: new fences on r6xx+, spread spectrum improvements on r5xx+ (DP 
support and LVDS fixes), evergreen blit support, ppl fixes, lots of tiling 
fixes
intel: rework of AGP/DRM driver interfaces to be a lot cleaner, support 
for using the whole GTT range instead of just the CPU mappable region
lots of eDP fixes, unload fixes, DP audio support, also a lot of output 
from the Chris Wilson bugfixing machine.

Dave.

The following changes since commit 2b666ca4a68cbc22483b0f2e1ba3c0e59b01ae9e:

  Merge branch 'fix/misc' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6 (2010-10-17 09:38:08 -0700)

are available in the git repository at:

  ssh://master.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git drm-core-next

Alex Deucher (18):
      drm/radeon/kms: clean up r6xx/r7xx blit init (v2)
      drm/radeon/kms: enable writeback (v2)
      drm/radeon/kms/r6xx+: use new style fencing (v3)
      drm/radeon/kms: properly handle 40 bit MC addresses in the cursor code
      drm/radeon/kms: prefer high post dividers in legacy pll algo
      drm/radeon/kms: remove some pll algo flags
      drm/radeon/kms: remove new pll algo
      drm/radeon/kms: rework spread spectrum handling
      drm/radeon/kms: add drm blit support for evergreen
      drm/radeon/kms: make sure blit addr masks are 64 bit
      drm/radeon/kms: avivo cursor workaround applies to evergreen as well
      drm/radeon/kms/evergreen: add some additional safe regs v2
      drm/radeon/kms: implement display watermark support for evergreen
      drm/radeon/kms: MC vram map needs to be >= pci aperture size
      drm/radeon/kms/evergreen: set the clear state to the blit state
      drm/radeon/kms: fix 2D tile height alignment in the r600 CS checker
      drm/radeon/kms: properly compute group_size on 6xx/7xx
      drm/radeon/kms: fix r6xx/7xx 1D tiling CS checker v2

Andrea Gelmini (1):
      drivers: gpu: drm: i915: Fix a typo.

Ben Skeggs (56):
      drm/nv50: add new accelerated bo move funtion
      drm/nouveau: move check for no-op bo move before memcpy fallback
      drm/nouveau: remove second map of notifier bo
      drm/nouveau: require explicit unmap of kmapped bos
      drm/nouveau: have nv_mask return original register value
      drm/nouveau: move ramht code out of nouveau_object.c, nothing to see here
      drm/nouveau: modify object accessors, offset in bytes rather than dwords
      drm/nouveau: rebase per-channel pramin heap offsets to 0
      drm/nouveau: remove nouveau_gpuobj_ref completely, replace with sanity
      drm/nouveau: simplify fake gpu objects
      drm/nv50: allow gpuobjs that aren't mapped into aperture
      drm/nv50: calculate vram reordering block size
      drm/nouveau: rework init ordering so nv50_instmem.c can be less bad
      drm/nouveau: tidy ram{ht,fc,ro} a bit
      drm/nouveau: add spinlock around ramht modifications
      drm/nouveau: fix gpuobj refcount to use atomics
      drm/nouveau: protect gpuobj list + global instmem heap with spinlock
      drm/nouveau: remove nouveau_gpuobj_late_takedown
      drm/nouveau: protect ramht_find() from oopsing if on channel without ramht
      drm/nv50: move vm trap to nv50_fb.c
      drm/nv50: report BAR access faults
      drm/nv50: fix SOR count for early chipsets
      drm/nouveau: better handling of unmappable vram
      drm/nouveau: handle fifo pusher errors better
      drm/nouveau: we can't free ACPI EDID, so make a copy that we can
      drm/nv50: mark PCIEGART pages non-present rather than using dummy page
      drm/nouveau: zero dummy page
      drm/nv50: fix 100c90 write on nva3
      drm/nouveau: make the behaviour of get_pll_limits() consistent
      drm/nouveau: make bios code easier to use externally
      drm/nouveau: import initial work on vbios performance table parsing
      drm/nv50: import initial clock get/set routines + hook up pm engine
      drm/nv04-nv40: import initial pm backend
      drm/nouveau: allow static performance level setting
      drm/nouveau: restore perflvl on resume, and restore boot perflvl on unload
      drm/nouveau: fix potential accuracy loss when parsing perf 0x1c tables
      drm/nouveau: implement parsing of DCB 2.2 GPIO table
      drm/nouveau: fix thinko in volt 0x1x parsing
      drm/nv50: flush bar1 vm / dma object setup before poking 0x1708
      drm/nouveau: correct INIT_DP_CONDITION subcondition 5
      drm/nouveau: add debugfs file to forcibly evict everything from vram
      drm/nv50: assume smaller tiles for bo moves
      drm/nouveau: fix chipset vs card_type thinko
      drm/nouveau: fix panels using straps-based mode detection
      drm/nouveau: v3.0 pll limits tables have type<->register mapping too
      drm/nv50: use pll type rather than register for CRTC PLL
      drm/nouveau: enable enhanced framing only if DP display supports it
      drm/nouveau: pass perflvl struct to clock_pre()
      drm/nouveau: run perflvl and M table scripts on mem clock change
      drm/nva3: split pm backend out from nv50
      drm/nouveau: fix typo in c2aa91afea5f7e7ae4530fabd37414a79c03328c
      drm/nouveau: fix required mode bandwidth calculation for DP
      drm/nv50: prevent (IB_PUT == IB_GET) for occurring unless idle
      drm/nouveau: parse voltage from perf 0x40 entires
      drm/ttm: introduce utility function to free an allocated memory node
      drm/ttm: restructure to allow driver to plug in alternate memory manager

Bryan Freed (1):
      drm/i915: Initialize panel timing registers if VBIOS did not

Chia-I Wu (1):
      drm/i915: Fix current fb blocking for page flip

Chris Ball (3):
      drm/radeon/kms: Implement KDB debug hooks for radeon KMS.
      drm/nouveau/kms: Implement KDB debug hooks for nouveau KMS.
      drm/nouveau/kms: Avoid a hang entering KDB with VT accel on.

Chris Wilson (190):
      Merge remote branch 'airlied/drm-core-next' into HEAD
      drm/i915: Drop the msleep parameter to wait_for()
      drm/i915: Avoid using msleep under kdb and wait_for()
      drm/i915/crt: Flush register prior to waiting for vblank.
      drm/i915: Rename i915_opregion.c to intel_opregion.c
      drm/i915: Use the VBT from OpRegion when available (v3)
      drm/i915: Addin-offset is an unreliable indicator of LVDS presence (v2)
      drm/i915: Ironlake page-flipping is per-plane not per-pipe
      drm/i915/tv: Preserve reserved DAC bits during mode-setting
      drm/i915/tv: Poll for DAC state change
      drm/i915/tv: Mark the format names as constant and so avoid the memleak
      drm/i915: Sanity check user framebuffer parameters on creation
      drm/i915/sdvo: Preserve pixel-multiplier
      drm/i915/overlay: Whitespace
      drm/i915/overlay: Missing breaks between case statements for color depth
      drm/i915/overlay: Ensure that the reg_bo is in the GTT prior to writing.
      drm/i915/overlay: Move capabilities bits to common info block.
      drm/i915/overlay: Use non-atomic mappings for the common case.
      drm/i915/overlay: Tidy attribute checking.
      drm/i915/overlay: Use the recommended page alignment for physical regs
      drm/i915/overlay: Destroy reg_bo on shutdown.
      drm/i915/overlay: Remove duplicated definition of OFC_UPDATE
      drm/i915/overlay: Tidy update_pfit_vscale_ratio()
      drm/i915/overlay: Tidy check_overlay_dst()
      drm/i915/overlay: Refactor do_wait_request()
      drm/i915/overlay: Explicitly pass regs from map to unmap
      drm/i915/overlay: Combine SWITCH_OFF into a single step
      drm/i915/overlay: Tidy release_old_vid()
      drm/i915: Preallocate requests
      drm/i915/overlay: Make do_put_image() as static
      drm/i915/overlay: Workaround i830 overlay activation bug.
      drm/i915/overlay: Pass interruptible to switch_off()
      drm/i915/overlay: Make the overlay control struct opaque.
      drm/i915/overlay: Use a continuation hook to finish work after a flip.
      drm/i915: Compile out error state without DEBUG_FS
      drm/i915: Remove the random SyncFlush during initialisation
      drm/i915: Kill the active list spinlock
      drm/i915: Quieten sparse warnings for missing prototypes.
      drm/i915: Remove redundant initialisation of fb_base
      drm/i915: Refactor panel backlight controls
      drm/i915/tv: After disabling the pipe, use wait_for_vblank_off()
      drm/i915: Show device capabilities in debugfs
      drm/i915: Show framebuffer info in debugfs
      drm/i915: Clear scanline waits after disabling the pipe.
      drm/i915: Add ringbuffer wait reset to hangcheck
      drm/i915: Remove impossible error handling from bit17 swizzling
      drm/i915/dp: Flush the PLL register write before sleeping
      drm/i915: Rename intel_encoder->enc to base for consistency
      drm/i915: Use the direct mapping of pipe->crtc
      drm/i915: Make the connector->encoder relationship explicit
      drm/i915/debug: Include Ironlake in self-refresh status
      drm/i915: Adapt workqueue to new alloc_workqueue interface
      drm/i915: Ensure all PLL registers are flushed before a udelay()
      drm/i915: Only call udelay() when waiting for clocks to stabilise
      drm/i915: Use the real FDI frequency for determining b/w
      Merge branch 'drm-intel-fixes' into drm-intel-next
      drm/i915: Fix updating FBC
      drm/i915: Tidy Ironlake watermark computation
      drm/i915: Use macros to switch between equivalent pipe registers
      drm/i915/dp: Convert a udelay(17000) to a sleep during link-off
      drm/i915/i2c: The bit-banging interface controls the delay, drop ours
      drm/i915/lvds: Remove busy wait for powering down the panel
      drm/i915/lvds: Remove busy wait for powering up the panel.
      drm/i915: Use msleep instead of mdelay during wait_vblank_off
      drm/i915/sdvo: Poll command status 5 times without delay on read
      drm/i915/bios: Prevent NULL dereference after allocation failure
      drm/i915/lvds: Ensure panel is unlocked for Ironlake or the panel fitter
      drm/i915/lvds: Remove incorrect mode locking
      drm/i915/lvds: Move private data to the connector from the device.
      drm/i915: Share crtc setup and teardown between dpms and disable/enable
      drm/i915: Fix an overlay regression from 7e7d76c
      drm/i915: Initialize intel_crtc->active
      drm/i915: Remove redundant initialisation of crtc->pipe
      drm/i915: Reduce hangcheck frequency
      drm/i915: Consolidate flushing the display plane
      drm/i915: Fix regression in ba3d8d749b
      agp/intel: Use macro to set the count of the size array
      drm/i915: Push pipelining of display plane flushes to the caller
      drm/i915: Allow get_fence_reg() to be uninterruptible
      drm/i915/i2c: Track the parent encoder rather than just the dev
      drm/i915: Remove unused intel_ringbuffer->ring_flag
      drm/i915/sdvo: Tidy intel_sdvo_hdmi_sink_detect
      drm/i915/sdvo: Propagate i2c error from switching DDC control bus.
      agp/intel: Remove redundant setting of gtt_mappable_entries
      agp/intel: Fix resume regression from 2d2430cf
      drm/i915/sdvo: Only create the analog encoder as required
      drm/i915/sdvo: Mark the status as unknown if attached with EDID
      drm/i915: call drm_encoder_init first
      drm/i915: use GMBUS to manage i2c links
      Merge branch 'drm-intel-fixes' into HEAD
      drm/i915: Cache LVDS EDID
      drm/i915: INTEL_INFO->gen supercedes i8xx, i9xx, i965g
      drm/i915: After a reset perform a forced modeset
      drm/i915/debug: Dump BSD ring buffers to debugfs
      drm/i915: Inline i915_gem_ring_retire_request()
      drm/i915: Only emit a flush request on the active ring.
      drm/i915: Clear flushing lists on GPU reset
      drm/i915: Clear GPU read domains on reset
      drm/i915: Clean up bo lists on all hung gpus
      drm/i915/ringbuffer: Implement advance using set_tail
      drm/i915/ringbuffer: Mark the initialisation structs as constant.
      drm/i915: Use ring->flush() instead of MI_FLUSH
      drm/i915/ringbuffer: whitespace cleanup
      drm/i915: Track gpu fence usage
      drm/i915: Merge ring flushing and lazy requests
      drm/i915: Drain any pending flips on the fb prior to unpinning
      drm/i915: Track pinned objects
      drm/i915: Disable output polling across suspend & resume
      drm/i915: Drop crtc->fb pin on disable.
      drm/i915: Use the correct DPB GMBUS port for GPIOE
      drm/i915/lvds: Unlock the PP register when panel-fitting
      drm/i915: Don't overwrite the returned error-code
      drm/i915: Clear the gpu_write_list on resetting write_domain upon hang
      drm/i915: Don't offset the pin used for crt_ddc
      drm/i915: Drop ring->lazy_request
      drm/i915: Disable "disabled FBC" message when a no-op
      drm/i915/crt: Use a DDC probe on 0xA0 before load-detect
      drm/i915: Remove the broken flush_ring from page-flip
      drm/i915/tv: Sleep before checking for state changes.
      drm/i915/lvds: Probe DDC on creation
      drm/i915: Remove idle timer debugging messages
      drm/i915/ringbuffer: Fix sign of ring space.
      drm/i915: Remove unused dev_priv->panel_wants_dither
      drm/i915: Use an uninterruptible wait for page-flips during modeset
      drm/i915/lvds: Use the GMBUS pin if specified in VBT
      drm/i915: Parse the eDP link configuration from the vBIOS
      drm/i915: Only hold a process-local lock whilst throttling.
      drm/i915: Adjust hangcheck EIO semantics
      drm/i915: Make the mutex_lock interruptible on ioctl paths
      drm/i915: Convert the file mutex into a spinlock
      drm/i915: fix debugging compilation error from previous commit
      drm/i915: Ensure that the mode change flushing is currently uninterruptible
      Revert "drm/i915: Drop ring->lazy_request"
      drm/i915/sdvo: Fix GMBUSification
      drm/i915: Use i2c bit banging instead of GMBUS
      MAINTAINERS: Add contact details for drm/i915
      Merge branch 'drm-intel-fixes' into drm-intel-next
      drm/i915: Disable LVDS i2c probing when using GPIO bit banging
      drm/i915: Tidy dvo_ch7017 and print out which chip we detect
      drm/i915/dvo: Fix panel and DDC i2c pins
      drm/i915/debug: Remove defunct WATCH_LRU
      drm/i915/debug: Remove default WATCH_BUF
      drm/i915: Avoid blocking the kworker thread on a stuck mutex
      drm/i915/debug: Convert i915_verify_active() to scan all lists
      drm/i915: Report the deferred free list in debugfs
      drm/i915/debugfs: Include list totals
      drm/i915: Make get/put pages static
      drm/i915: Remove redundant deletion of obj->gpu_write_list
      drm: Move the GTT accounting to i915
      drm/i915: Force the domain to CPU on unbinding whilst wedged.
      drm/i915: Clear fence registers on GPU reset
      drm/i915: Try to reset gen2 devices.
      drm/i915: Only print 'generating error event' if we actually are
      drm/i915: If the GPU hangs twice within 5 seconds, declare it wedged.
      drm/i915: Don't mask the return code whilst relocating.
      Merge branch 'drm-intel-fixes' into drm-intel-next
      Merge branch 'drm-intel-fixes' into drm-intel-next
      drm/i915: Skip pread/pwrite if size to copy is 0.
      drm/i915: Avoid circular locking from intel_fbdev_fini()
      drm/i915: Wait for pending flips on the GPU
      Merge remote branch 'airlied/drm-core-next' into tmp
      Revert "drm/i915: Prevent module unload to avoid random memory corruption"
      drm/i915: Remove duplicate set of ADPA definitions
      drm/i915: restore fixed FDI link rate on Sandybridge
      drm/i915: Sleep whilst waiting for the ring
      drm/i915/dp: Add 'force_audio' property
      drm/i915/sdvo: Add 'force_audio' property
      drm/i915/hdmi: Add 'force_audio' property
      drm/i915: Avoid vmallocing a buffer for the relocations
      drm/i915: Perform relocations in CPU domain [if in CPU domain]
      drm/i915: Avoid taking the mutex for dropping the refcnt upon creation
      drm/i915: Attempt to prefault user pages for pread/pwrite
      drm/i915: Rearrange acquisition of mutex during pwrite
      drm/i915: rearrange mutex acquisition for pread
      agp/intel: Also add B43.1 to list of supported devices
      drm/i915: Do interrupible mutex lock first to avoid locking for unreference
      drm/i915: cache the last object lookup during pin_and_relocate()
      drm/i915: Simplify most HAS_BSD() checks
      drm/i915: Track objects in global active list (as well as per-ring)
      drm/i915: Copy the updated reloc->presumed_offset back to the user
      drm/i915/ringbuffer: Fix emit batch buffer regression from 8187a2b
      drm/i915/ringbuffer: Remove broken intel_fill_struct()
      drm/i915: Enable SandyBridge blitter ring
      drm/i915: IS_IRONLAKE is synonymous with gen == 5
      drm/i915/sdvo: Remove unused encoding member
      drm/i915: Fix flushing regression from 9af90d19f
      agp/intel: Restore valid PTE bit for Sandybridge after bdd3072
      drm/i915/ringbuffer: Write the value passed in to the tail register
      drm/i915: Invalidate the to-ring, flush the old-ring when updating domains
      drm/i915: Move gpu_write_list to per-ring

Dan Carpenter (1):
      i915: snprintf returns large values

Daniel Vetter (85):
      drm: don't export drm_sg_alloc
      drm: kill kernel_context_switch callbacks
      drm: kill procfs callbacks
      drm: kill dma_ready callbacks
      drm: kill gem_free_object_unlocked driver callback
      drm: kill context_ctor callback
      drm: don't export drm_get_drawable_info
      drm: drop return value of drm_free_agp
      drm: kill drm_map_ofs callbacks
      drm: don't export dri1 locking functions
      drm: replace drawable ioctl by noops
      drm: kill agp indirection mess
      drm: kill dev->timer
      drm: kill get_reg_ofs callback
      drm/i915: unload: fix intel dp encoder cleanup
      drm/i915: unload: fix error_work races
      drm/i915: unload: fix hotplug_work races
      drm/i915: unload: don't leak error state
      drm/i915: unload: fix idle_timer/idle_work races
      drm/i915: unload: fix unpin_work related races
      drm/i915: unload: ensure that gem is idle
      drm/i915: unload: fix retire_work races
      drm/i915: allow lazy emitting of requests
      drm/i915: move flushing list processing to i915_gem_flush
      drm/i915: only one interrupt per batchbuffer is not enough!
      drm/i915: move flushing list processing to i915_retire_commands
      drm/i915: kill a no longer necessary BUG_ON
      drm/i915: drop seqno argument from i915_gem_object_move_to_active
      drm/i915: move the wait_rendering call into flush_gpu_write_domain
      drm/i915: drop i915_add_request right in front of i915_wait_request
      agp/intel: split out gmch/gtt probe, part 2
      agp/intel: make intel-gtt.c into a real source file
      intel-gtt: introduce drm/intel-gtt.h
      intel-gtt: store a local pointer to the bridge pci dev
      intel-gtt: s/intel_i830_init_gtt_entries/intel_gtt_stolen_entries
      intel-gtt: new function intel_gtt_mappable_entries
      intel-gtt: generic intel_fake_agp_fetch_size
      intel-gtt: sane variable names for intel_gtt_stolen_entries
      intel-gtt: drop unnecessary conditions in intel_gtt_stolen_entries
      intel-gtt: adjust overhead entries in intel_gtt_stolen_entries
      intel-gtt: s/i8[13]0/fake_agp for generic functions
      intel-gtt: fix gtt_total_entries detection
      intel-gtt: introduce intel_gtt_driver
      intel-gtt: i915: use detected gtt size for mapping
      intel-gtt: i965: use detected gtt size for mapping
      intel-gtt: i830: adjust ioremap of regs and gtt to i9xx
      intel-gtt: consolidate the gtt ioremap calls
      intel-gtt: consolidate i830 setup
      intel-gtt: consolidate i9xx setup
      intel-gtt: call init_gtt_init in probe function
      intel-gtt: use chipset generation number some more
      drm/i915: drop prealloc_start from i915_dma gtt init
      drm/i915: die, i915_probe_agp, die
      drm/i915: kill duplicated/unneeded register defines
      drm/i915: add relative ring register macros
      drm/i915: use new macros to access the ring tail register
      drm/i915: use new macros to access the ring start register
      drm/i915: use new macros to access the ring head register
      drm/i915: use new macros to access the ring ctl register
      drm/i915: don't explicitly initialize ringbuffer members to zero
      drm/i915: drop alignment ringbuffer parameter
      intel-gtt: initialize our own scratch page
      intel-gtt: introduce pte write function for i8xx/i915/i945
      intel-gtt: introduce pte write function for g33/i965/gm45
      intel-gtt: introduce pte write function for gen6
      intel-gtt: drop agp scratch page support stuff
      agp: kill agp_(map|unmap)_page
      intel-gtt: generic (insert|remove)_entries for i830
      intel-gtt: generic (insert|remove)_entries for i915
      intel-gtt: generic (insert|remove)_entries for g33/i965
      intel-gtt: generic (insert|remove)_entries for sandybridge
      intel-gtt: kill mask_memory functions
      intel-gtt: move chipset flush to the gtt driver struct
      intel-gtt: consolidate fake_agp driver structs
      agp: kill agp_(unmap|map)_memory
      intel-gtt: clean up gtt size reporting
      intel-gtt: store the dma mask size in intel_gtt_driver
      intel-gtt add a cleanup function for chipset specific stuff
      drm/i915: kill now unnecessary gtt defines from i915_reg.h
      drm/i915: fix ACTHD for gen <= 3
      drm/i915: kill per-ring macros
      drm/i915: kill ring->get_active_head
      drm/i915: kill ring->setup_status_page
      drm: readd drm_lock_free in drm_unlock
      drm/i915: Fix oops on HWS unload

Dave Airlie (13):
      Merge remote branch 'origin/master' of /home/airlied/kernel//linux-2.6 into drm-core-next
      Merge remote branch 'intel/drm-intel-next' of ../drm-next into drm-core-next
      Merge remote branch 'korg/drm-fixes' into drm-vmware-next
      Merge branch 'drm-vmware-next' into drm-core-next
      Merge remote branch 'nouveau/for-airlied' of ../drm-nouveau-next into drm-core-next
      Merge branch 'drm-kdb-next' into drm-core-next
      Merge branch 'drm-radeon-next' of ../drm-radeon-next into drm-core-next
      Merge branch 'drm-fixes' of /home/airlied/kernel/linux-2.6 into drm-core-next
      drm/ttm: add unlocked variant of new manager put node.
      Revert "drm/radeon/kms: remove some pll algo flags"
      Merge remote branch 'intel/drm-intel-next' of ../drm-next into drm-core-next
      drm/radeon/r600: fix tiling issues in CS checker.
      drm/radeon/kms: don't poll dac load detect.

David Härdeman (1):
      i915: enable AVI infoframe for intel_hdmi.c [v4]

Emil Velikov (1):
      drm/nouveau: don't use the default pll limits in table v2.1 on nv50+ cards

Francesco Marella (1):
      drm/nv40: fix reading temp value

Francisco Jerez (30):
      drm/nouveau: Fix suspend on some nv4x AGP cards.
      drm/nv20: Use the nv30 CRTC bandwidth calculation code.
      drm/nv17-nv4x: Fix analog load detection false positive on rare occasions.
      drm/nv40: Try to set up CRE_LCD even if it has unknown bits set.
      drm/nouveau: Break some long lines in the TV-out code.
      drm/nouveau: Don't remove ramht entries from the neighboring channels.
      drm/nouveau: Don't enable AGP FW on nv18.
      drm/nouveau: Add module parameter to override the default AGP rate.
      drm/nouveau: PRAMIN is available from the start on pre-nv50.
      drm/nouveau: Remove implicit argument from nv_wait().
      drm/nouveau: Simplify tile region handling.
      drm/nouveau: Try to fetch an EDID from OF if DDC fails.
      drm/nouveau: Parse old style perf tables.
      drm/nv10: Don't oops if the card wants to switch to a channel with no grctx.
      drm/nouveau: Don't try to parse a GPIO table on early DCBv2.2 BIOSes.
      drm/nouveau: Add sane sensor correction defaults for nv4a.
      drm/nouveau: Fix parsing of the temperature constant correction.
      drm/nouveau: Double the perf table memory clocks on pre-G71 cards.
      drm/nouveau: Refactor nouveau_temp_get() into engine pointers.
      drm/nouveau: Add support for I2C hardware monitoring devices.
      drm/nouveau: Misc cleanup of the PM code.
      drm/nouveau: Fix perf table parsing on BMP v5.25.
      drm/nv30-nv40: Fix postdivider mask when writing engine/memory PLLs.
      drm/nv0x-nv4x: Leave the 0x40 bit untouched when changing CRE_LCD.
      drm/nouveau: Minor refactoring/cleanup of the fence code.
      drm/nouveau: Provide a means to have arbitrary work run on fence completion.
      drm/nouveau: Use semaphores to handle inter-channel sync in hardware.
      drm/nouveau: Synchronize buffer object moves in hardware.
      drm/nv50: Fix large 3D performance regression caused by the interchannel sync patches.
      agp/amd-k7: Allow binding user memory to the AGP GART.

Hette Visser (1):
      drm/i915/dp: Wait for PP_CONTROL to take effect.

Jan Beulich (1):
      some clean up to intel-gtt.c

Jason Wessel (5):
      drm, kdb, kms: Add an enter argument to mode_set_base_atomic() API
      radeon, kdb, kms: Save and restore the LUT on atomic KMS enter/exit
      Revert "radeon, kdb, kms: Save and restore the LUT on atomic KMS enter/exit"
      kdb, kms: Save and restore the LUT on atomic KMS enter/exit
      drm, kdb, kms: Change mode_set_base_atomic() enter argument to be an enum

Jean Delvare (1):
      drm/ttm: Simplify ttm_bo_wait_unreserved

Jesse Barnes (40):
      drm/i915: add MMIO debug output
      drm/i915: fix pipeconf dither bit definitions
      drm/i915: set dither bits on eDP panels too
      drm/i915: fix eDP detection
      drm/i915: use 125MHz reference clock for PCH attached eDP
      drm/i915: use VDD AUX for panel power around detection and in prepare
      drm/i915: split DP link training across panel power sequencing
      drm/i915: don't change VDD AUX status in panel power functions
      drm/i915: make sure VDD AUX power has time to settle
      drm/i915: make sure panel is sequenced off when starting a mode set
      drm/i915: split Ironlake CRTC enable/disable code
      drm/i915: split i9xx CRTC enable/disable code
      drm/i915: don't unlock panel regs
      drm/i915: use i915 and Ironlake CRTC enable/disable functions in prepare/commit
      drm/i915: enable PCH PLL, FDI training and transcoder even for eDP
      drm/i915: split Ironlake FDI enable function
      drm/i915: don't write TU size to N1 reg
      drm/i915: set FDI RX TU size to match transmit size
      drm/i915: enable thermal reporting for IPS
      drm/i915/dp: convert eDP checks to functions and document
      drm/i915/dp: remove redundant is_pch_edp checks
      drm/i915/dp: correct eDP lane count and bpp
      drm/i915: add eDP checking functions for the display code
      drm/i915: remove broken intel_pch_has_edp function
      drm/i915: fix CPU vs PCH eDP confusion
      drm/i915/dp: eDP power sequencing fixes
      drm/i915: add _DSM support
      drm/i915: fetch eDP configuration data from the VBT
      drm/i915: add Ironlake clock gating workaround for FDI link training
      drm/i915: fix PCH eDP SSC support
      drm/i915: use 120MHz refclk in PCH eDP case too
      drm/i915: use DPLL_DVO_HIGH_SPEED for PCH eDP
      drm/i915: fix ironlake CRTC enable/disable
      drm/i915: don't program FDI RX/TX in mode_set
      drm/i915/dp: cache eDP DPCD data
      drm/i915/dp: use VBT provided eDP params if available
      drm/i915/dp: don't bother with DP PLL for PCH attached eDP
      drm/i915/dp: make eDP PLL functions work as advertised
      drm/i915: diasable clock gating for the panel power sequencer
      drm/i915/dp: down the DP link even if the reg indicates it's already down

Keith Packard (3):
      drm/i915: avoid struct mutex output_poll mutex lock loop on unload
      drm/i915: mark display port DPMS state as 'ON' when enabling output
      drm/i915: Free hardware status page on unload when physically mapped

Kenneth Graunke (3):
      drm/i915: Actually set the reset bit in i965_reset.
      drm/i915: Rename graphics reset registers.
      drm/i915: Add support for GPU soft reset on Ironlake.

Lee, Chun-Yi (1):
      gpu: Add Intel GMA500(Poulsbo) Stub Driver

Marcin Kościelnicki (2):
      drm/nv50: demagic grctx, and add NVAF support
      drm/nouveau: Add a module option to force card POST.

Mario Kleiner (2):
      drm/radeon: Add function for display scanout position query.
      drm/radeon: Modify radeon_pm_in_vbl to use radeon_get_crtc_scanoutpos()

Marius Gröger (1):
      drm/radeon: add properties to configure the width of the underscan borders

Martin Peres (1):
      drm/nouveau: Add temperature support (vbios parsing, readings, hwmon)

Matthew Garrett (1):
      drm/i915: Don't disable panel for modesetting if pfit hasn't changed

Phil Turmel (1):
      drm/nouveau: Fix build regression, undefined reference to `acpi_video_get_edid'

Roy Spliet (2):
      drm/nouveau: Import initial memory timing work
      drm/nouveau: fix thinkos in mem timing table recordlen check

Simon Que (1):
      i915: Added function to initialize VBT settings

Sitsofe Wheeler (1):
      drm/i915: Revert extra intel_wait_for_vblank to prevent stalls.

Thomas Hellstrom (14):
      drm/vmwgfx: Really support other depths than 32
      drm/vmwgfx: Fix ACPI S3 & S4 functionality.
      drm/vmwgfx: Add new-style PM hooks to improve hibernation behavior
      drm: vmwgfx: Add a struct drm_file parameter to the dirty framebuffer callback
      drm/vmwgfx: Take the ttm lock around the dirty ioctl
      drm/vmwgfx: Prune modes based on available VRAM size
      drm/vmwgfx: Don't flush fb if we're in the suspended state.
      drm/vmwgfx: Add a parameter to get the max fb size
      drm/vmwgfx: Add modinfo version
      drm/vmwgfx: Save at least one screen layout
      drm/vmwgfx: Bump minor and driver date
      drm/ttm: Avoid using the ttm_mem_type_manager::put_locked function
      drm/ttm: Optimize delayed buffer destruction
      vmwgfx: Implement a proper GMR eviction mechanism

Xiang, Haihao (4):
      drm/i915: fix HAS_BSD with a device info flag
      drm/i915: do not export the instances of struct intel_ring_buffer
      drm/i915: add set_tail hook in struct intel_ring_buffer
      drm/i915: add a new BSD ring buffer for Sandybridge

Yuanhan Liu (2):
      drm/i915/crt: Make sure the hotplug interrupt is enabled
      drm/i915: Update hotplug interrupts register definitions for Sandybridge

Zhenyu Wang (4):
      drm/i915: Fix GPIO pin to register mapping
      drm/edid: add helper function to detect monitor audio capability
      drm/i915: Enable DisplayPort audio
      drm/i915: Enable HDMI audio for monitor with audio support

 MAINTAINERS                                        |    9 +
 drivers/char/agp/Makefile                          |    1 +
 drivers/char/agp/agp.h                             |    5 -
 drivers/char/agp/amd-k7-agp.c                      |    6 +-
 drivers/char/agp/backend.c                         |   22 +-
 drivers/char/agp/generic.c                         |    8 -
 drivers/char/agp/intel-agp.c                       |  201 +--
 drivers/char/agp/intel-agp.h                       |   43 +-
 drivers/char/agp/intel-gtt.c                       | 1612 +++++-----
 drivers/gpu/Makefile                               |    2 +-
 drivers/gpu/drm/Makefile                           |    2 +-
 drivers/gpu/drm/drm_agpsupport.c                   |   40 +-
 drivers/gpu/drm/drm_context.c                      |    8 -
 drivers/gpu/drm/drm_crtc.c                         |    3 +-
 drivers/gpu/drm/drm_debugfs.c                      |    1 -
 drivers/gpu/drm/drm_drawable.c                     |  198 --
 drivers/gpu/drm/drm_drv.c                          |   10 +-
 drivers/gpu/drm/drm_edid.c                         |   93 +-
 drivers/gpu/drm/drm_fb_helper.c                    |   32 +-
 drivers/gpu/drm/drm_gem.c                          |   14 -
 drivers/gpu/drm/drm_info.c                         |   14 -
 drivers/gpu/drm/drm_lock.c                         |   30 +-
 drivers/gpu/drm/drm_memory.c                       |   14 +-
 drivers/gpu/drm/drm_proc.c                         |   14 -
 drivers/gpu/drm/drm_scatter.c                      |    2 -
 drivers/gpu/drm/drm_stub.c                         |    4 -
 drivers/gpu/drm/drm_vm.c                           |   13 +-
 drivers/gpu/drm/i810/i810_drv.c                    |    2 -
 drivers/gpu/drm/i830/i830_drv.c                    |    2 -
 drivers/gpu/drm/i915/Makefile                      |    4 +-
 drivers/gpu/drm/i915/dvo_ch7017.c                  |   66 +-
 drivers/gpu/drm/i915/dvo_ch7xxx.c                  |   10 +-
 drivers/gpu/drm/i915/dvo_ivch.c                    |   10 +-
 drivers/gpu/drm/i915/dvo_sil164.c                  |   10 +-
 drivers/gpu/drm/i915/dvo_tfp410.c                  |   10 +-
 drivers/gpu/drm/i915/i915_debugfs.c                |  336 ++-
 drivers/gpu/drm/i915/i915_dma.c                    |  360 +--
 drivers/gpu/drm/i915/i915_drv.c                    |  214 +-
 drivers/gpu/drm/i915/i915_drv.h                    |  271 ++-
 drivers/gpu/drm/i915/i915_gem.c                    | 2211 +++++++-------
 drivers/gpu/drm/i915/i915_gem_debug.c              |  148 +-
 drivers/gpu/drm/i915/i915_gem_evict.c              |   72 +-
 drivers/gpu/drm/i915/i915_gem_tiling.c             |   54 +-
 drivers/gpu/drm/i915/i915_irq.c                    |  259 +-
 drivers/gpu/drm/i915/i915_reg.h                    |  335 ++-
 drivers/gpu/drm/i915/i915_suspend.c                |   28 +-
 drivers/gpu/drm/i915/intel_acpi.c                  |  286 ++
 drivers/gpu/drm/i915/intel_bios.c                  |  234 +-
 drivers/gpu/drm/i915/intel_bios.h                  |    6 +-
 drivers/gpu/drm/i915/intel_crt.c                   |  127 +-
 drivers/gpu/drm/i915/intel_display.c               | 2357 ++++++++-------
 drivers/gpu/drm/i915/intel_dp.c                    |  658 +++--
 drivers/gpu/drm/i915/intel_drv.h                   |  160 +-
 drivers/gpu/drm/i915/intel_dvo.c                   |   69 +-
 drivers/gpu/drm/i915/intel_fb.c                    |   29 +-
 drivers/gpu/drm/i915/intel_hdmi.c                  |  193 +-
 drivers/gpu/drm/i915/intel_i2c.c                   |  484 +++-
 drivers/gpu/drm/i915/intel_lvds.c                  |  435 ++--
 drivers/gpu/drm/i915/intel_modes.c                 |   16 +-
 .../drm/i915/{i915_opregion.c => intel_opregion.c} |  181 +-
 drivers/gpu/drm/i915/intel_overlay.c               | 1006 ++++---
 drivers/gpu/drm/i915/intel_panel.c                 |  109 +
 drivers/gpu/drm/i915/intel_ringbuffer.c            |  457 ++--
 drivers/gpu/drm/i915/intel_ringbuffer.h            |   81 +-
 drivers/gpu/drm/i915/intel_sdvo.c                  | 1076 +++----
 drivers/gpu/drm/i915/intel_tv.c                    |  165 +-
 drivers/gpu/drm/mga/mga_drv.c                      |    2 -
 drivers/gpu/drm/nouveau/Kconfig                    |    1 +
 drivers/gpu/drm/nouveau/Makefile                   |    6 +-
 drivers/gpu/drm/nouveau/nouveau_acpi.c             |    2 +-
 drivers/gpu/drm/nouveau/nouveau_bios.c             |  366 ++-
 drivers/gpu/drm/nouveau/nouveau_bios.h             |   43 +-
 drivers/gpu/drm/nouveau/nouveau_bo.c               |  290 ++-
 drivers/gpu/drm/nouveau/nouveau_calc.c             |   10 +-
 drivers/gpu/drm/nouveau/nouveau_channel.c          |   23 +-
 drivers/gpu/drm/nouveau/nouveau_connector.c        |   54 +-
 drivers/gpu/drm/nouveau/nouveau_connector.h        |    3 +
 drivers/gpu/drm/nouveau/nouveau_debugfs.c          |   16 +
 drivers/gpu/drm/nouveau/nouveau_dma.c              |   32 +-
 drivers/gpu/drm/nouveau/nouveau_dma.h              |    1 +
 drivers/gpu/drm/nouveau/nouveau_dp.c               |   10 +-
 drivers/gpu/drm/nouveau/nouveau_drv.c              |   23 +-
 drivers/gpu/drm/nouveau/nouveau_drv.h              |  253 +-
 drivers/gpu/drm/nouveau/nouveau_encoder.h          |    1 +
 drivers/gpu/drm/nouveau/nouveau_fbcon.c            |    6 +
 drivers/gpu/drm/nouveau/nouveau_fence.c            |  318 ++-
 drivers/gpu/drm/nouveau/nouveau_gem.c              |    4 +-
 drivers/gpu/drm/nouveau/nouveau_grctx.h            |    2 +-
 drivers/gpu/drm/nouveau/nouveau_hw.c               |   45 +-
 drivers/gpu/drm/nouveau/nouveau_i2c.c              |    8 +-
 drivers/gpu/drm/nouveau/nouveau_i2c.h              |    5 +-
 drivers/gpu/drm/nouveau/nouveau_irq.c              |  123 +-
 drivers/gpu/drm/nouveau/nouveau_mem.c              |  363 ++-
 drivers/gpu/drm/nouveau/nouveau_notifier.c         |    9 +-
 drivers/gpu/drm/nouveau/nouveau_object.c           |  776 ++----
 drivers/gpu/drm/nouveau/nouveau_perf.c             |  205 ++
 drivers/gpu/drm/nouveau/nouveau_pm.c               |  518 +++
 drivers/gpu/drm/nouveau/nouveau_pm.h               |   74 +
 drivers/gpu/drm/nouveau/nouveau_ramht.c            |  289 ++
 drivers/gpu/drm/nouveau/nouveau_ramht.h            |   55 +
 drivers/gpu/drm/nouveau/nouveau_reg.h              |    9 +-
 drivers/gpu/drm/nouveau/nouveau_sgdma.c            |   68 +-
 drivers/gpu/drm/nouveau/nouveau_state.c            |  123 +-
 drivers/gpu/drm/nouveau/nouveau_temp.c             |  309 ++
 drivers/gpu/drm/nouveau/nouveau_volt.c             |  212 ++
 drivers/gpu/drm/nouveau/nv04_crtc.c                |   60 +-
 drivers/gpu/drm/nouveau/nv04_dac.c                 |   11 +-
 drivers/gpu/drm/nouveau/nv04_dfp.c                 |   39 +-
 drivers/gpu/drm/nouveau/nv04_fbcon.c               |    9 +-
 drivers/gpu/drm/nouveau/nv04_fifo.c                |   68 +-
 drivers/gpu/drm/nouveau/nv04_instmem.c             |  140 +-
 drivers/gpu/drm/nouveau/nv04_pm.c                  |   81 +
 drivers/gpu/drm/nouveau/nv04_tv.c                  |   10 +-
 drivers/gpu/drm/nouveau/nv10_fifo.c                |   19 +-
 drivers/gpu/drm/nouveau/nv10_graph.c               |    2 +-
 drivers/gpu/drm/nouveau/nv17_tv.c                  |  110 +-
 drivers/gpu/drm/nouveau/nv17_tv.h                  |   15 +-
 drivers/gpu/drm/nouveau/nv17_tv_modes.c            |   48 +-
 drivers/gpu/drm/nouveau/nv20_graph.c               |  506 ++--
 drivers/gpu/drm/nouveau/nv40_fifo.c                |   20 +-
 drivers/gpu/drm/nouveau/nv40_graph.c               |   16 +-
 drivers/gpu/drm/nouveau/nv40_grctx.c               |    6 +-
 drivers/gpu/drm/nouveau/nv50_crtc.c                |   87 +-
 drivers/gpu/drm/nouveau/nv50_cursor.c              |    2 +-
 drivers/gpu/drm/nouveau/nv50_dac.c                 |    4 +-
 drivers/gpu/drm/nouveau/nv50_display.c             |   92 +-
 drivers/gpu/drm/nouveau/nv50_fb.c                  |   40 +
 drivers/gpu/drm/nouveau/nv50_fbcon.c               |    4 +-
 drivers/gpu/drm/nouveau/nv50_fifo.c                |  286 +-
 drivers/gpu/drm/nouveau/nv50_graph.c               |   51 +-
 drivers/gpu/drm/nouveau/nv50_grctx.c               | 3305 +++++++++++++-------
 drivers/gpu/drm/nouveau/nv50_instmem.c             |  418 ++--
 drivers/gpu/drm/nouveau/nv50_pm.c                  |  131 +
 drivers/gpu/drm/nouveau/nv50_sor.c                 |    4 +-
 drivers/gpu/drm/nouveau/nva3_pm.c                  |   95 +
 drivers/gpu/drm/nouveau/nvc0_fifo.c                |    6 -
 drivers/gpu/drm/nouveau/nvc0_instmem.c             |   13 +-
 drivers/gpu/drm/nouveau/nvreg.h                    |    1 +
 drivers/gpu/drm/r128/r128_drv.c                    |    2 -
 drivers/gpu/drm/radeon/Makefile                    |    2 +-
 drivers/gpu/drm/radeon/atombios_crtc.c             |  406 ++-
 drivers/gpu/drm/radeon/evergreen.c                 |  564 ++++-
 drivers/gpu/drm/radeon/evergreen_blit_kms.c        |  772 +++++
 drivers/gpu/drm/radeon/evergreen_blit_shaders.c    |  348 ++
 drivers/gpu/drm/radeon/evergreen_blit_shaders.h    |   35 +
 drivers/gpu/drm/radeon/evergreend.h                |   20 +
 drivers/gpu/drm/radeon/r100.c                      |  100 +-
 drivers/gpu/drm/radeon/r300.c                      |   15 +-
 drivers/gpu/drm/radeon/r420.c                      |   16 +-
 drivers/gpu/drm/radeon/r520.c                      |   11 +-
 drivers/gpu/drm/radeon/r600.c                      |  179 +-
 drivers/gpu/drm/radeon/r600_blit_kms.c             |   51 +-
 drivers/gpu/drm/radeon/r600_cs.c                   |   36 +-
 drivers/gpu/drm/radeon/r600d.h                     |   21 +
 drivers/gpu/drm/radeon/radeon.h                    |   23 +-
 drivers/gpu/drm/radeon/radeon_asic.c               |    6 +-
 drivers/gpu/drm/radeon/radeon_asic.h               |   11 +-
 drivers/gpu/drm/radeon/radeon_atombios.c           |  129 +-
 drivers/gpu/drm/radeon/radeon_connectors.c         |   65 +-
 drivers/gpu/drm/radeon/radeon_cursor.c             |   43 +-
 drivers/gpu/drm/radeon/radeon_device.c             |   83 +-
 drivers/gpu/drm/radeon/radeon_display.c            |  405 ++--
 drivers/gpu/drm/radeon/radeon_drv.c                |   11 +-
 drivers/gpu/drm/radeon/radeon_encoders.c           |   16 +-
 drivers/gpu/drm/radeon/radeon_fb.c                 |    2 +
 drivers/gpu/drm/radeon/radeon_fence.c              |   10 +-
 drivers/gpu/drm/radeon/radeon_legacy_crtc.c        |   49 +-
 drivers/gpu/drm/radeon/radeon_mode.h               |   53 +-
 drivers/gpu/drm/radeon/radeon_object.c             |    6 +-
 drivers/gpu/drm/radeon/radeon_pm.c                 |   70 +-
 drivers/gpu/drm/radeon/radeon_ring.c               |   12 +-
 drivers/gpu/drm/radeon/radeon_ttm.c                |   34 +-
 drivers/gpu/drm/radeon/reg_srcs/evergreen          |    8 +
 drivers/gpu/drm/radeon/rs400.c                     |   15 +-
 drivers/gpu/drm/radeon/rs600.c                     |   15 +-
 drivers/gpu/drm/radeon/rs690.c                     |   15 +-
 drivers/gpu/drm/radeon/rv515.c                     |   15 +-
 drivers/gpu/drm/radeon/rv770.c                     |   38 +-
 drivers/gpu/drm/savage/savage_drv.c                |    2 -
 drivers/gpu/drm/sis/sis_drv.c                      |    3 -
 drivers/gpu/drm/tdfx/tdfx_drv.c                    |    2 -
 drivers/gpu/drm/ttm/Makefile                       |    3 +-
 drivers/gpu/drm/ttm/ttm_agp_backend.c              |    3 +-
 drivers/gpu/drm/ttm/ttm_bo.c                       |  305 +-
 drivers/gpu/drm/ttm/ttm_bo_manager.c               |  148 +
 drivers/gpu/drm/ttm/ttm_bo_util.c                  |   12 +-
 drivers/gpu/drm/via/via_drv.c                      |    2 -
 drivers/gpu/drm/vmwgfx/Makefile                    |    2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c             |   84 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c                |  130 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h                |   40 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c            |   29 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_fb.c                 |   13 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c                |   38 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c      |  137 +
 drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c              |    3 +
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c                |  200 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c                |   28 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_resource.c           |   75 -
 drivers/gpu/stub/Kconfig                           |   13 +
 drivers/gpu/stub/Makefile                          |    1 +
 drivers/gpu/stub/poulsbo.c                         |   64 +
 drivers/video/Kconfig                              |    2 +
 include/drm/drmP.h                                 |   45 +-
 include/drm/drm_crtc.h                             |    4 +-
 include/drm/drm_crtc_helper.h                      |    8 +-
 include/drm/drm_dp_helper.h                        |    3 +
 include/drm/i915_drm.h                             |    6 +-
 include/drm/intel-gtt.h                            |   18 +
 include/drm/ttm/ttm_bo_api.h                       |    3 +-
 include/drm/ttm/ttm_bo_driver.h                    |   27 +-
 include/drm/vmwgfx_drm.h                           |    1 +
 212 files changed, 18764 insertions(+), 11690 deletions(-)
 delete mode 100644 drivers/gpu/drm/drm_drawable.c
 create mode 100644 drivers/gpu/drm/i915/intel_acpi.c
 rename drivers/gpu/drm/i915/{i915_opregion.c => intel_opregion.c} (81%)
 create mode 100644 drivers/gpu/drm/nouveau/nouveau_perf.c
 create mode 100644 drivers/gpu/drm/nouveau/nouveau_pm.c
 create mode 100644 drivers/gpu/drm/nouveau/nouveau_pm.h
 create mode 100644 drivers/gpu/drm/nouveau/nouveau_ramht.c
 create mode 100644 drivers/gpu/drm/nouveau/nouveau_ramht.h
 create mode 100644 drivers/gpu/drm/nouveau/nouveau_temp.c
 create mode 100644 drivers/gpu/drm/nouveau/nouveau_volt.c
 create mode 100644 drivers/gpu/drm/nouveau/nv04_pm.c
 create mode 100644 drivers/gpu/drm/nouveau/nv50_pm.c
 create mode 100644 drivers/gpu/drm/nouveau/nva3_pm.c
 create mode 100644 drivers/gpu/drm/radeon/evergreen_blit_kms.c
 create mode 100644 drivers/gpu/drm/radeon/evergreen_blit_shaders.c
 create mode 100644 drivers/gpu/drm/radeon/evergreen_blit_shaders.h
 create mode 100644 drivers/gpu/drm/ttm/ttm_bo_manager.c
 create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
 create mode 100644 drivers/gpu/stub/Kconfig
 create mode 100644 drivers/gpu/stub/Makefile
 create mode 100644 drivers/gpu/stub/poulsbo.c
 create mode 100644 include/drm/intel-gtt.h

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2011-09-30  9:39 Inki Dae
  0 siblings, 0 replies; 35+ messages in thread
From: Inki Dae @ 2011-09-30  9:39 UTC (permalink / raw)
  To: airlied, 'Dave Airlie'; +Cc: kyungmin.park, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 910 bytes --]

Hi, Dave.

 

I am sending a mail I wonder where are we on this. I had sent DRM Driver
patch v5 for Samsung SoC Exynos4210 a week ago but I didn't received any
comments from you.

 

You can refer to these patches I sent from links below.

v1: < https://lwn.net/Articles/454380/ >

v2: < http://www.spinics.net/lists/kernel/msg1224275.html >

v3: < http://www.spinics.net/lists/dri-devel/msg13755.html >

v4: < http://permalink.gmane.org/gmane.comp.video.dri.devel/60439 >

v5: < http://comments.gmane.org/gmane.comp.video.dri.devel/60802 >

 

and also you can refer to our working repository below.

< http://git.infradead.org/users/kmpark/linux-2.6-samsung >

Branch name : dev/samsung-drm

 

If there are any problems regarding our driver then please give me your
comments or advices so that we are going to prepare next patch; otherwise we
wish our driver be applied to mainline.

 

Thanks,

Inki Dae.


[-- Attachment #1.2: Type: text/html, Size: 4205 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2012-04-12  0:54 Rodrigo Vivi
  0 siblings, 0 replies; 35+ messages in thread
From: Rodrigo Vivi @ 2012-04-12  0:54 UTC (permalink / raw)
  To: DRI Development; +Cc: Intel Graphics Development, Rodrigo Vivi

There are many bugs open on fd.o regarding missing modes that are supported on Windows and other closed source drivers.
>From EDID spec we can (might?) infer modes using GTF and CVT when monitor allows it trough range limited flag... obviously limiting by the range.
>From our code:
 * EDID spec says modes should be preferred in this order:
 * - preferred detailed mode
 * - other detailed modes from base block
 * - detailed modes from extension blocks
 * - CVT 3-byte code modes
 * - standard timing codes
 * - established timing codes
 * - modes inferred from GTF or CVT range information
 *
 * We get this pretty much right.

Not actually so right... We were inferring just using GTF... not CVT or even GTF2.
This patch not just add some common cvt modes but also allows some modes been inferred when using gtf2 as well.

Cheers,
Rodrigo.

>From 4b7a88d0d812583d850ca691d1ac491355230d11 Mon Sep 17 00:00:00 2001
From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Date: Wed, 11 Apr 2012 15:36:31 -0300
Subject: [PATCH] drm/edid: Adding common CVT inferred modes when monitor
 allows range limited ones trough EDID.

Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
---
 drivers/gpu/drm/drm_edid.c       |   37 +++++++++++++-
 drivers/gpu/drm/drm_edid_modes.h |  101 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 136 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 7ee7be1..3179572 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1020,17 +1020,50 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
 	return modes;
 }
 
+static int
+drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid,
+			struct detailed_timing *timing)
+{
+	int i, modes = 0;
+	struct drm_display_mode *newmode;
+	struct drm_device *dev = connector->dev;
+
+	for (i = 0; i < drm_num_cvt_inferred_modes; i++) {
+		if (mode_in_range(drm_cvt_inferred_modes + i, edid, timing)) {
+			newmode = drm_mode_duplicate(dev, &drm_cvt_inferred_modes[i]);
+			if (newmode) {
+				drm_mode_probed_add(connector, newmode);
+				modes++;
+			}
+		}
+	}
+
+	return modes;
+}
+
 static void
 do_inferred_modes(struct detailed_timing *timing, void *c)
 {
 	struct detailed_mode_closure *closure = c;
 	struct detailed_non_pixel *data = &timing->data.other_data;
-	int gtf = (closure->edid->features & DRM_EDID_FEATURE_DEFAULT_GTF);
+	int timing_level = standard_timing_level(closure->edid);
 
-	if (gtf && data->type == EDID_DETAIL_MONITOR_RANGE)
+	if (data->type == EDID_DETAIL_MONITOR_RANGE)
+	    switch (timing_level) {
+	    case LEVEL_DMT:
+		break;
+	    case LEVEL_GTF:
+	    case LEVEL_GTF2:
 		closure->modes += drm_gtf_modes_for_range(closure->connector,
 							  closure->edid,
 							  timing);
+		break;
+	    case LEVEL_CVT:
+		closure->modes += drm_cvt_modes_for_range(closure->connector,
+							  closure->edid,
+							  timing);
+		break;
+	    }
 }
 
 static int
diff --git a/drivers/gpu/drm/drm_edid_modes.h b/drivers/gpu/drm/drm_edid_modes.h
index a91ffb1..7e14a32 100644
--- a/drivers/gpu/drm/drm_edid_modes.h
+++ b/drivers/gpu/drm/drm_edid_modes.h
@@ -266,6 +266,107 @@ static const struct drm_display_mode drm_dmt_modes[] = {
 static const int drm_num_dmt_modes =
 	sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
 
+static const struct drm_display_mode drm_cvt_inferred_modes[] = {
+	/* 640x480@60Hz */
+	{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 23750  640, 664,
+		   720, 800, 0, 480, 483, 487, 500, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 800x600@60Hz */
+	{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 38250, 800, 832,
+		   912, 1024, 0, 600, 603, 607, 624, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 900x600@60Hz */
+	{ DRM_MODE("900x600", DRM_MODE_TYPE_DRIVER, 45250, 960, 992,
+		   1088, 1216, 0, 600, 603, 609, 624, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1024x576@60Hz */
+	{ DRM_MODE("1024x576", DRM_MODE_TYPE_DRIVER, 46500, 1024, 1064,
+		   1160, 1296, 0, 576, 579, 584, 599, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1024x768@60Hz */
+	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 63500, 1024, 1072,
+		   1176, 1328, 0, 768, 771, 775, 798, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1152x864@60Hz */
+	{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 81750, 1152, 1216,
+		   1336, 1520, 0, 864, 867, 871, 897, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1280x720@60Hz */
+	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74500, 1280, 1344,
+		   1472, 1664, 0, 720, 723, 728, 748, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1280x768@60Hz */
+	{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
+		   1472, 1664, 0, 768, 771, 781, 798, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1280x800@60Hz */
+	{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
+		   1480, 1680, 0, 800, 803, 809, 831, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1280x1024@60Hz */
+	{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 109000, 1280, 1368,
+		   1496, 1712, 0, 1024, 1027, 1034, 1063, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1360x768@60Hz */
+	{ DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 84750, 1360, 1432,
+		   1568, 1776, 0, 768, 771, 781, 798, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1366x768@60Hz */
+	{ DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 85250, 1368, 1440,
+		   1576, 1784, 0, 768, 771, 781, 798, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1440x900@60Hz */
+	{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1528,
+		   1672, 1904, 0, 900, 903, 909, 934, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1400x1050@60Hz */
+	{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
+		   1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1600x900@60Hz */
+	{ DRM_MODE("1600x900", DRM_MODE_TYPE_DRIVER, 118250, 1600, 1696,
+		   1856, 2112, 0, 900, 903, 908, 934, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1600x1200@60Hz */
+	{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 161000, 1600, 1712,
+		   1880, 2160, 0, 1200, 1203, 1207, 1245, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1680x945@60Hz */
+	{ DRM_MODE("1680x945", DRM_MODE_TYPE_DRIVER, 130750, 1680, 1776,
+		   1952, 2224, 0, 945, 948, 953, 981, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1680x1050@60Hz */
+	{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
+		   1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1920x1080@60Hz */
+	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 73000, 1920, 2048,
+		   2248, 2576, 0, 1080, 1083, 1088, 1120, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1920x1200@60Hz */
+	{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
+		   2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1920x1440@60Hz */
+	{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 233500, 1920, 2064,
+		   2264, 2608, 0, 1440, 1443, 1447, 1493, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 2048x1152@60Hz */
+	{ DRM_MODE("2048x1152", DRM_MODE_TYPE_DRIVER, 197000, 2048, 2184,
+		   2400, 2752, 0, 1152, 1155, 1160, 1195, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 2048x1536@60Hz */
+	{ DRM_MODE("2048x1536", DRM_MODE_TYPE_DRIVER, 272000, 2048, 2208,
+		   2424, 2800, 0, 1563, 1566, 1576, 1620, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 2560x1600@60Hz */
+	{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2760,
+		   3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+};
+static const int drm_num_cvt_inferred_modes =
+	sizeof(drm_cvt_inferred_modes) / sizeof(struct drm_display_mode);
+
 static const struct drm_display_mode edid_est_modes[] = {
 	{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
 		   968, 1056, 0, 600, 601, 605, 628, 0,
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2012-05-18 12:27 Sascha Hauer
  2012-05-18 12:27 ` [PATCH 1/2] DRM: add Freescale i.MX LCDC driver Sascha Hauer
                   ` (2 more replies)
  0 siblings, 3 replies; 35+ messages in thread
From: Sascha Hauer @ 2012-05-18 12:27 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-arm-kernel

Hi All,

The following adds a drm/kms driver for the Freescale i.MX LCDC
controller. Most notable change to the last SDRM based version is that
the SDRM layer has been removed and the driver now is purely i.MX
specific. I hope that this is more acceptable now.

Another change is that the probe is now devicetree based. For now I
took the easy way out and only put an edid blob into the devicetree.
I haven't documented the binding yet, I would add that when the rest
is considered ok.

Comments very welcome.

Thanks
 Sascha

----------------------------------------------------------------
Sascha Hauer (2):
      DRM: add Freescale i.MX LCDC driver
      pcm038 lcdc support

 arch/arm/boot/dts/imx27-phytec-phycore.dts |   39 ++
 arch/arm/boot/dts/imx27.dtsi               |    7 +
 arch/arm/mach-imx/clock-imx27.c            |    1 +
 drivers/gpu/drm/Kconfig                    |    2 +
 drivers/gpu/drm/Makefile                   |    1 +
 drivers/gpu/drm/imx/Kconfig                |   18 +
 drivers/gpu/drm/imx/Makefile               |    8 +
 drivers/gpu/drm/imx/imx-drm-core.c         |  745 ++++++++++++++++++++++++++++
 drivers/gpu/drm/imx/imx-fb.c               |  179 +++++++
 drivers/gpu/drm/imx/imx-fbdev.c            |  275 ++++++++++
 drivers/gpu/drm/imx/imx-gem.c              |  343 +++++++++++++
 drivers/gpu/drm/imx/imx-lcdc-crtc.c        |  517 +++++++++++++++++++
 drivers/gpu/drm/imx/imx-parallel-display.c |  228 +++++++++
 13 files changed, 2363 insertions(+)
 create mode 100644 drivers/gpu/drm/imx/Kconfig
 create mode 100644 drivers/gpu/drm/imx/Makefile
 create mode 100644 drivers/gpu/drm/imx/imx-drm-core.c
 create mode 100644 drivers/gpu/drm/imx/imx-fb.c
 create mode 100644 drivers/gpu/drm/imx/imx-fbdev.c
 create mode 100644 drivers/gpu/drm/imx/imx-gem.c
 create mode 100644 drivers/gpu/drm/imx/imx-lcdc-crtc.c
 create mode 100644 drivers/gpu/drm/imx/imx-parallel-display.c

^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH 1/2] DRM: add Freescale i.MX LCDC driver
  2012-05-18 12:27 (unknown), Sascha Hauer
@ 2012-05-18 12:27 ` Sascha Hauer
  2012-05-22 21:28   ` Rob Clark
  2012-05-18 12:27 ` [PATCH 2/2] pcm038 lcdc support Sascha Hauer
  2012-05-22 14:06 ` Lars-Peter Clausen
  2 siblings, 1 reply; 35+ messages in thread
From: Sascha Hauer @ 2012-05-18 12:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Sascha Hauer, linux-arm-kernel

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/Kconfig                    |    2 +
 drivers/gpu/drm/Makefile                   |    1 +
 drivers/gpu/drm/imx/Kconfig                |   18 +
 drivers/gpu/drm/imx/Makefile               |    8 +
 drivers/gpu/drm/imx/imx-drm-core.c         |  745 ++++++++++++++++++++++++++++
 drivers/gpu/drm/imx/imx-fb.c               |  179 +++++++
 drivers/gpu/drm/imx/imx-fbdev.c            |  275 ++++++++++
 drivers/gpu/drm/imx/imx-gem.c              |  343 +++++++++++++
 drivers/gpu/drm/imx/imx-lcdc-crtc.c        |  517 +++++++++++++++++++
 drivers/gpu/drm/imx/imx-parallel-display.c |  228 +++++++++
 10 files changed, 2316 insertions(+)
 create mode 100644 drivers/gpu/drm/imx/Kconfig
 create mode 100644 drivers/gpu/drm/imx/Makefile
 create mode 100644 drivers/gpu/drm/imx/imx-drm-core.c
 create mode 100644 drivers/gpu/drm/imx/imx-fb.c
 create mode 100644 drivers/gpu/drm/imx/imx-fbdev.c
 create mode 100644 drivers/gpu/drm/imx/imx-gem.c
 create mode 100644 drivers/gpu/drm/imx/imx-lcdc-crtc.c
 create mode 100644 drivers/gpu/drm/imx/imx-parallel-display.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index e354bc0..759502c 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -186,3 +186,5 @@ source "drivers/gpu/drm/vmwgfx/Kconfig"
 source "drivers/gpu/drm/gma500/Kconfig"
 
 source "drivers/gpu/drm/udl/Kconfig"
+
+source "drivers/gpu/drm/imx/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index c20da5b..6569d8d 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -42,4 +42,5 @@ obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
 obj-$(CONFIG_DRM_EXYNOS) +=exynos/
 obj-$(CONFIG_DRM_GMA500) += gma500/
 obj-$(CONFIG_DRM_UDL) += udl/
+obj-$(CONFIG_DRM_IMX) += imx/
 obj-y			+= i2c/
diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig
new file mode 100644
index 0000000..5fc3a44
--- /dev/null
+++ b/drivers/gpu/drm/imx/Kconfig
@@ -0,0 +1,18 @@
+config DRM_IMX
+	tristate "DRM Support for Freescale i.MX"
+	select DRM_KMS_HELPER
+	depends on DRM && ARCH_MXC
+
+config DRM_IMX_FB_HELPER
+	tristate "provide legacy framebuffer /dev/fb0"
+	depends on DRM_IMX
+
+config DRM_IMX_LCDC
+	tristate "DRM Support for Freescale i.MX1 and i.MX2"
+	depends on DRM_IMX
+	help
+	  Choose this if you have a i.MX1, i.MX21, i.MX25 or i.MX27 processor.
+
+config DRM_IMX_PARALLEL_DISPLAY
+	tristate "Support for parallel displays"
+	depends on DRM_IMX
diff --git a/drivers/gpu/drm/imx/Makefile b/drivers/gpu/drm/imx/Makefile
new file mode 100644
index 0000000..0f7c038
--- /dev/null
+++ b/drivers/gpu/drm/imx/Makefile
@@ -0,0 +1,8 @@
+
+imxdrm-objs := imx-drm-core.o imx-fb.o imx-gem.o
+
+obj-$(CONFIG_DRM_IMX) += imxdrm.o
+
+obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += imx-parallel-display.o
+obj-$(CONFIG_DRM_IMX_LCDC) += imx-lcdc-crtc.o
+obj-$(CONFIG_DRM_IMX_FB_HELPER) += imx-fbdev.o
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
new file mode 100644
index 0000000..29f5f10
--- /dev/null
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -0,0 +1,745 @@
+/*
+ * simple drm driver
+ *
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <linux/fb.h>
+#include <asm/fb.h>
+#include <linux/module.h>
+
+#include "imx-drm.h"
+
+#define MAX_CRTC	4
+
+struct imx_drm_device {
+	struct drm_device			*drm;
+	struct device				*dev;
+	struct list_head			crtc_list;
+	struct list_head			encoder_list;
+	struct list_head			connector_list;
+	struct mutex				mutex;
+	int					references;
+};
+
+struct imx_drm_crtc {
+	struct drm_crtc				*crtc;
+	struct list_head			list;
+	struct imx_drm_device			*imxdrm;
+	int					pipe;
+	struct drm_crtc_helper_funcs		crtc_helper_funcs;
+	struct drm_crtc_funcs			crtc_funcs;
+	struct imx_drm_crtc_helper_funcs	imx_drm_helper_funcs;
+	struct module				*owner;
+};
+
+struct imx_drm_encoder {
+	struct drm_encoder			*encoder;
+	struct list_head			list;
+	struct module				*owner;
+};
+
+struct imx_drm_connector {
+	struct drm_connector			*connector;
+	struct list_head			list;
+	struct module				*owner;
+};
+
+static int imx_drm_driver_firstopen(struct drm_device *drm)
+{
+	if (!imx_drm_device_get())
+		return -EINVAL;
+
+	return 0;
+}
+
+static void imx_drm_driver_lastclose(struct drm_device *drm)
+{
+	imx_drm_device_put();
+}
+
+static int imx_drm_driver_unload(struct drm_device *drm)
+{
+	struct imx_drm_device *imxdrm = drm->dev_private;
+
+	drm_mode_config_cleanup(imxdrm->drm);
+	drm_kms_helper_poll_fini(imxdrm->drm);
+
+	return 0;
+}
+
+/*
+ * We don't care at all for crtc numbers, but the core expects the
+ * crtcs to be numbered
+ */
+static struct imx_drm_crtc *imx_drm_crtc_by_num(struct imx_drm_device *imxdrm,
+		int num)
+{
+	struct imx_drm_crtc *imx_drm_crtc;
+
+	list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list)
+		if (imx_drm_crtc->pipe == num)
+			return imx_drm_crtc;
+	return NULL;
+}
+
+int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
+{
+	return drm_vblank_get(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe);
+}
+EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get);
+
+void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc)
+{
+	drm_vblank_put(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe);
+}
+EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put);
+
+void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc)
+{
+	drm_handle_vblank(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe);
+}
+EXPORT_SYMBOL_GPL(imx_drm_handle_vblank);
+
+static int imx_drm_enable_vblank(struct drm_device *drm, int crtc)
+{
+	struct imx_drm_device *imxdrm = drm->dev_private;
+	struct imx_drm_crtc *imx_drm_crtc;
+	int ret;
+
+	imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc);
+	if (!imx_drm_crtc)
+		return -EINVAL;
+
+	if (!imx_drm_crtc->imx_drm_helper_funcs.enable_vblank)
+		return -ENOSYS;
+
+	ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank(imx_drm_crtc->crtc);
+	return ret;
+}
+
+static void imx_drm_disable_vblank(struct drm_device *drm, int crtc)
+{
+	struct imx_drm_device *imxdrm = drm->dev_private;
+	struct imx_drm_crtc *imx_drm_crtc;
+
+	imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc);
+	if (!imx_drm_crtc)
+		return;
+
+	if (!imx_drm_crtc->imx_drm_helper_funcs.disable_vblank)
+		return;
+
+	imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc);
+}
+
+static struct vm_operations_struct imx_drm_gem_vm_ops = {
+	.fault = imx_drm_gem_fault,
+	.open = drm_gem_vm_open,
+	.close = drm_gem_vm_close,
+};
+
+static const struct file_operations imx_drm_driver_fops = {
+	.owner = THIS_MODULE,
+	.open = drm_open,
+	.release = drm_release,
+	.unlocked_ioctl = drm_ioctl,
+	.mmap = imx_drm_gem_mmap,
+	.poll = drm_poll,
+	.fasync = drm_fasync,
+	.read = drm_read,
+	.llseek = noop_llseek,
+};
+
+static struct imx_drm_device *imx_drm_device;
+
+static struct imx_drm_device *__imx_drm_device(void)
+{
+	return imx_drm_device;
+}
+
+struct drm_device *imx_drm_device_get(void)
+{
+	struct imx_drm_device *imxdrm = __imx_drm_device();
+	struct imx_drm_encoder *enc;
+	struct imx_drm_connector *con;
+	struct imx_drm_crtc *crtc;
+
+	mutex_lock(&imxdrm->mutex);
+
+	list_for_each_entry(enc, &imxdrm->encoder_list, list) {
+		if (!try_module_get(enc->owner)) {
+			dev_err(imxdrm->dev, "could not get module %s\n",
+					module_name(enc->owner));
+			goto unwind_enc;
+		}
+	}
+
+	list_for_each_entry(con, &imxdrm->connector_list, list) {
+		if (!try_module_get(con->owner)) {
+			dev_err(imxdrm->dev, "could not get module %s\n",
+					module_name(con->owner));
+			goto unwind_con;
+		}
+	}
+
+	list_for_each_entry(crtc, &imxdrm->crtc_list, list) {
+		if (!try_module_get(crtc->owner)) {
+			dev_err(imxdrm->dev, "could not get module %s\n",
+					module_name(crtc->owner));
+			goto unwind_crtc;
+		}
+	}
+
+	imxdrm->references++;
+
+	mutex_unlock(&imxdrm->mutex);
+
+	return imx_drm_device->drm;
+
+unwind_crtc:
+	list_for_each_entry_continue_reverse(crtc, &imxdrm->crtc_list, list)
+		module_put(crtc->owner);
+unwind_con:
+	list_for_each_entry_continue_reverse(con, &imxdrm->connector_list, list)
+		module_put(con->owner);
+unwind_enc:
+	list_for_each_entry_continue_reverse(enc, &imxdrm->encoder_list, list)
+		module_put(enc->owner);
+
+	mutex_unlock(&imxdrm->mutex);
+
+	return NULL;
+
+}
+EXPORT_SYMBOL_GPL(imx_drm_device_get);
+
+void imx_drm_device_put(void)
+{
+	struct imx_drm_device *imxdrm = __imx_drm_device();
+	struct imx_drm_encoder *enc;
+	struct imx_drm_connector *con;
+	struct imx_drm_crtc *crtc;
+
+	mutex_lock(&imxdrm->mutex);
+
+	list_for_each_entry(crtc, &imxdrm->crtc_list, list)
+		module_put(crtc->owner);
+
+	list_for_each_entry(con, &imxdrm->connector_list, list)
+		module_put(con->owner);
+
+	list_for_each_entry(enc, &imxdrm->encoder_list, list)
+		module_put(enc->owner);
+
+	imxdrm->references--;
+
+	mutex_unlock(&imxdrm->mutex);
+}
+EXPORT_SYMBOL_GPL(imx_drm_device_put);
+
+static int drm_mode_group_reinit(struct drm_device *dev)
+{
+	struct drm_mode_group *group = &dev->primary->mode_group;
+	uint32_t *id_list = group->id_list;
+	int ret;
+
+	ret = drm_mode_group_init_legacy_group(dev, group);
+	if (ret < 0)
+		return ret;
+
+	kfree(id_list);
+	return 0;
+}
+
+/*
+ * register an encoder to the drm core
+ */
+static int imx_drm_encoder_register(struct imx_drm_encoder *imx_drm_encoder)
+{
+	struct imx_drm_device *imxdrm = __imx_drm_device();
+
+	drm_encoder_init(imxdrm->drm, imx_drm_encoder->encoder,
+			imx_drm_encoder->encoder->funcs,
+			DRM_MODE_ENCODER_TMDS);
+
+	drm_mode_group_reinit(imxdrm->drm);
+
+	return 0;
+}
+
+/*
+ * unregister an encoder from the drm core
+ */
+static void imx_drm_encoder_unregister(struct imx_drm_encoder *imx_drm_encoder)
+{
+	struct imx_drm_device *imxdrm = __imx_drm_device();
+
+	drm_encoder_cleanup(imx_drm_encoder->encoder);
+
+	drm_mode_group_reinit(imxdrm->drm);
+}
+
+/*
+ * register a connector to the drm core
+ */
+static int imx_drm_connector_register(struct imx_drm_connector *imx_drm_connector)
+{
+	struct imx_drm_device *imxdrm = __imx_drm_device();
+	int ret;
+
+	drm_connector_init(imxdrm->drm, imx_drm_connector->connector,
+			imx_drm_connector->connector->funcs,
+			DRM_MODE_CONNECTOR_VGA);
+	drm_mode_group_reinit(imxdrm->drm);
+	ret = drm_sysfs_connector_add(imx_drm_connector->connector);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+
+	return ret;
+}
+
+/*
+ * unregister a connector from the drm core
+ */
+static void imx_drm_connector_unregister(struct imx_drm_connector *imx_drm_connector)
+{
+	struct imx_drm_device *imxdrm = __imx_drm_device();
+
+	drm_sysfs_connector_remove(imx_drm_connector->connector);
+	drm_connector_cleanup(imx_drm_connector->connector);
+
+	drm_mode_group_reinit(imxdrm->drm);
+}
+
+/*
+ * register a crtc to the drm core
+ */
+static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc)
+{
+	struct imx_drm_device *imxdrm = __imx_drm_device();
+	int ret;
+
+	drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc, &imx_drm_crtc->crtc_funcs);
+	ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256);
+	if (ret)
+		return ret;
+
+	drm_crtc_helper_add(imx_drm_crtc->crtc, &imx_drm_crtc->crtc_helper_funcs);
+
+	return 0;
+}
+
+/*
+ * Called by the CRTC driver when all CRTCs are registered. This
+ * puts all the pieces together and initializes the driver.
+ * Once this is called no more CRTCs can be registered since
+ * the drm core has hardcoded the number of crtcs in several
+ * places.
+ */
+static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
+{
+	struct imx_drm_device *imxdrm = __imx_drm_device();
+	int ret;
+
+	imxdrm->drm = drm;
+
+	drm->dev_private = imxdrm;
+
+	/*
+	 * 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 and
+	 *      drivers can well take care of their interrupts
+	 */
+	drm->irq_enabled = 1;
+
+	drm_mode_config_init(drm);
+	imx_drm_mode_config_init(drm);
+
+	mutex_lock(&imxdrm->mutex);
+
+	drm_kms_helper_poll_init(imxdrm->drm);
+
+	/* setup the grouping for the legacy output */
+	ret = drm_mode_group_init_legacy_group(imxdrm->drm,
+			&imxdrm->drm->primary->mode_group);
+	if (ret)
+		goto err_init;
+
+	ret = drm_vblank_init(imxdrm->drm, MAX_CRTC);
+	if (ret)
+		goto err_init;
+
+	/*
+	 * 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)
+	 */
+	imxdrm->drm->vblank_disable_allowed = 1;
+
+	ret = 0;
+
+err_init:
+	mutex_unlock(&imxdrm->mutex);
+
+	return ret;
+}
+
+/*
+ * imx_drm_add_crtc - add a new crtc
+ *
+ * The return value if !NULL is a cookie for the caller to pass to
+ * imx_drm_remove_crtc later.
+ */
+int imx_drm_add_crtc(struct drm_crtc *crtc,
+		struct imx_drm_crtc **new_crtc,
+		const struct drm_crtc_funcs *crtc_funcs,
+		const struct drm_crtc_helper_funcs *crtc_helper_funcs,
+		const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
+		struct module *owner)
+{
+	struct imx_drm_device *imxdrm = __imx_drm_device();
+	struct imx_drm_crtc *imx_drm_crtc;
+	int ret;
+
+	mutex_lock(&imxdrm->mutex);
+
+	if (imxdrm->references) {
+		ret = -EBUSY;
+		goto err_busy;
+	}
+
+	imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL);
+	if (!imx_drm_crtc) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	imx_drm_crtc->crtc_funcs = *crtc_funcs;
+	imx_drm_crtc->crtc_helper_funcs = *crtc_helper_funcs;
+	imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs;
+
+	WARN_ON(crtc_funcs->set_config);
+	WARN_ON(crtc_funcs->destroy);
+
+	imx_drm_crtc->crtc_funcs.set_config = drm_crtc_helper_set_config;
+	imx_drm_crtc->crtc_funcs.destroy = drm_crtc_cleanup;
+
+	imx_drm_crtc->crtc = crtc;
+	imx_drm_crtc->imxdrm = imxdrm;
+
+	imx_drm_crtc->owner = owner;
+
+	list_add_tail(&imx_drm_crtc->list, &imxdrm->crtc_list);
+
+	*new_crtc = imx_drm_crtc;
+
+	ret = imx_drm_crtc_register(imx_drm_crtc);
+	if (ret)
+		goto err_register;
+
+	mutex_unlock(&imxdrm->mutex);
+
+	return 0;
+
+err_register:
+	kfree(imx_drm_crtc);
+err_alloc:
+err_busy:
+	mutex_unlock(&imxdrm->mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(imx_drm_add_crtc);
+
+/*
+ * imx_drm_remove_crtc - remove a crtc
+ */
+int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc)
+{
+	struct imx_drm_device *imxdrm = imx_drm_crtc->imxdrm;
+
+	mutex_lock(&imxdrm->mutex);
+
+	drm_crtc_cleanup(imx_drm_crtc->crtc);
+
+	list_del(&imx_drm_crtc->list);
+
+	mutex_unlock(&imxdrm->mutex);
+
+	kfree(imx_drm_crtc);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(imx_drm_remove_crtc);
+
+/*
+ * imx_drm_add_encoder - add a new encoder
+ */
+int imx_drm_add_encoder(struct drm_encoder *encoder,
+		struct imx_drm_encoder **newenc, struct module *owner)
+{
+	struct imx_drm_device *imxdrm = __imx_drm_device();
+	struct imx_drm_encoder *imx_drm_encoder;
+	int ret;
+
+	mutex_lock(&imxdrm->mutex);
+
+	if (imxdrm->references) {
+		ret = -EBUSY;
+		goto err_busy;
+	}
+
+	imx_drm_encoder = kzalloc(sizeof(struct imx_drm_encoder), GFP_KERNEL);
+	if (!imx_drm_encoder) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	imx_drm_encoder->encoder = encoder;
+	imx_drm_encoder->owner = owner;
+
+	ret = imx_drm_encoder_register(imx_drm_encoder);
+	if (ret) {
+		kfree(imx_drm_encoder);
+		ret = -ENOMEM;
+		goto err_register;
+	}
+
+	list_add_tail(&imx_drm_encoder->list, &imxdrm->encoder_list);
+
+	*newenc = imx_drm_encoder;
+
+	mutex_unlock(&imxdrm->mutex);
+
+	return 0;
+
+err_register:
+	kfree(imx_drm_encoder);
+err_alloc:
+err_busy:
+	mutex_unlock(&imxdrm->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(imx_drm_add_encoder);
+
+/*
+ * imx_drm_remove_encoder - remove an encoder
+ */
+int imx_drm_remove_encoder(struct imx_drm_encoder *imx_drm_encoder)
+{
+	struct imx_drm_device *imxdrm = __imx_drm_device();
+
+	mutex_lock(&imxdrm->mutex);
+
+	imx_drm_encoder_unregister(imx_drm_encoder);
+
+	list_del(&imx_drm_encoder->list);
+
+	mutex_unlock(&imxdrm->mutex);
+
+	kfree(imx_drm_encoder);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(imx_drm_remove_encoder);
+
+/*
+ * imx_drm_add_connector - add a connector
+ */
+int imx_drm_add_connector(struct drm_connector *connector,
+		struct imx_drm_connector **new_con,
+		struct module *owner)
+{
+	struct imx_drm_device *imxdrm = __imx_drm_device();
+	struct imx_drm_connector *imx_drm_connector;
+	int ret;
+
+	mutex_lock(&imxdrm->mutex);
+
+	if (imxdrm->references) {
+		ret = -EBUSY;
+		goto err_busy;
+	}
+
+	imx_drm_connector = kzalloc(sizeof(struct imx_drm_connector), GFP_KERNEL);
+	if (!imx_drm_connector) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	imx_drm_connector->connector = connector;
+	imx_drm_connector->owner = owner;
+
+	ret = imx_drm_connector_register(imx_drm_connector);
+	if (ret)
+		goto err_register;
+
+	list_add_tail(&imx_drm_connector->list, &imxdrm->connector_list);
+
+	*new_con = imx_drm_connector;
+
+	mutex_unlock(&imxdrm->mutex);
+
+	return 0;
+
+err_register:
+	kfree(imx_drm_connector);
+err_alloc:
+err_busy:
+	mutex_unlock(&imxdrm->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(imx_drm_add_connector);
+
+/*
+ * imx_drm_remove_connector - remove a connector
+ */
+int imx_drm_remove_connector(struct imx_drm_connector *imx_drm_connector)
+{
+	struct imx_drm_device *imxdrm = __imx_drm_device();
+
+	mutex_lock(&imxdrm->mutex);
+
+	imx_drm_connector_unregister(imx_drm_connector);
+
+	list_del(&imx_drm_connector->list);
+
+	mutex_unlock(&imxdrm->mutex);
+
+	kfree(imx_drm_connector);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(imx_drm_remove_connector);
+
+static struct drm_ioctl_desc imx_drm_ioctls[] = {
+	/* none so far */
+};
+
+static struct drm_driver imx_drm_driver = {
+	.driver_features	= DRIVER_MODESET | DRIVER_GEM,
+	.load			= imx_drm_driver_load,
+	.unload			= imx_drm_driver_unload,
+	.firstopen		= imx_drm_driver_firstopen,
+	.lastclose		= imx_drm_driver_lastclose,
+	.gem_free_object	= imx_drm_gem_free_object,
+	.gem_vm_ops		= &imx_drm_gem_vm_ops,
+	.dumb_create		= imx_drm_gem_dumb_create,
+	.dumb_map_offset	= imx_drm_gem_dumb_map_offset,
+	.dumb_destroy		= imx_drm_gem_dumb_destroy,
+
+	.get_vblank_counter	= drm_vblank_count,
+	.enable_vblank		= imx_drm_enable_vblank,
+	.disable_vblank		= imx_drm_disable_vblank,
+	.reclaim_buffers	= drm_core_reclaim_buffers,
+	.ioctls			= imx_drm_ioctls,
+	.num_ioctls		= ARRAY_SIZE(imx_drm_ioctls),
+	.fops			= &imx_drm_driver_fops,
+	.name			= "imx-drm",
+	.desc			= "i.MX DRM graphics",
+	.date			= "20120507",
+	.major			= 1,
+	.minor			= 0,
+	.patchlevel		= 0,
+};
+
+static int imx_drm_platform_probe(struct platform_device *pdev)
+{
+	imx_drm_device->dev = &pdev->dev;
+
+	return drm_platform_init(&imx_drm_driver, pdev);
+}
+
+static int imx_drm_platform_remove(struct platform_device *pdev)
+{
+	drm_platform_exit(&imx_drm_driver, pdev);
+
+	return 0;
+}
+
+static struct platform_driver imx_drm_pdrv = {
+	.probe		= imx_drm_platform_probe,
+	.remove		= __devexit_p(imx_drm_platform_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "imx-drm",
+	},
+};
+
+static struct platform_device *imx_drm_pdev;
+
+static int __init imx_drm_init(void)
+{
+	int ret;
+
+	imx_drm_device = kzalloc(sizeof(*imx_drm_device), GFP_KERNEL);
+	if (!imx_drm_device)
+		return -ENOMEM;
+
+	mutex_init(&imx_drm_device->mutex);
+	INIT_LIST_HEAD(&imx_drm_device->crtc_list);
+	INIT_LIST_HEAD(&imx_drm_device->connector_list);
+	INIT_LIST_HEAD(&imx_drm_device->encoder_list);
+
+	imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0);
+	if (!imx_drm_pdev) {
+		ret = -EINVAL;
+		goto err_pdev;
+	}
+
+	imx_drm_pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32),
+
+	ret = platform_driver_register(&imx_drm_pdrv);
+	if (ret)
+		goto err_pdrv;
+
+	return 0;
+
+err_pdev:
+	kfree(imx_drm_device);
+err_pdrv:
+	platform_device_unregister(imx_drm_pdev);
+
+	return ret;
+}
+
+static void __exit imx_drm_exit(void)
+{
+	DRM_DEBUG_DRIVER("%s\n", __FILE__);
+
+	platform_device_unregister(imx_drm_pdev);
+	platform_driver_unregister(&imx_drm_pdrv);
+
+	kfree(imx_drm_device);
+}
+
+module_init(imx_drm_init);
+module_exit(imx_drm_exit);
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_DESCRIPTION("i.MX drm driver core");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/imx/imx-fb.c b/drivers/gpu/drm/imx/imx-fb.c
new file mode 100644
index 0000000..5a08c86
--- /dev/null
+++ b/drivers/gpu/drm/imx/imx-fb.c
@@ -0,0 +1,179 @@
+/*
+ * i.MX drm driver
+ *
+ * Copyright (C) 2012 Sascha Hauer, Pengutronix
+ *
+ * Based on Samsung Exynos code
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "imx-drm.h"
+
+#define to_imx_drm_fb(x)	container_of(x, struct imx_drm_fb, fb)
+
+/*
+ * imx specific framebuffer structure.
+ *
+ * @fb: drm framebuffer obejct.
+ * @imx_drm_gem_obj: drm ec specific gem object containing a gem object.
+ * @entry: pointer to ec drm buffer entry object.
+ *	- containing only the information to physically continuous memory
+ *	region allocated at default framebuffer creation.
+ */
+struct imx_drm_fb {
+	struct drm_framebuffer		fb;
+	struct imx_drm_gem_obj	*imx_drm_gem_obj;
+	struct imx_drm_buf_entry	*entry;
+};
+
+static void imx_drm_fb_destroy(struct drm_framebuffer *fb)
+{
+	struct imx_drm_fb *imx_drm_fb = to_imx_drm_fb(fb);
+
+	drm_framebuffer_cleanup(fb);
+
+	/*
+	 * default framebuffer has no gem object so
+	 * a buffer of the default framebuffer should be released at here.
+	 */
+	if (!imx_drm_fb->imx_drm_gem_obj && imx_drm_fb->entry)
+		imx_drm_buf_destroy(fb->dev, imx_drm_fb->entry);
+
+	kfree(imx_drm_fb);
+}
+
+static int imx_drm_fb_create_handle(struct drm_framebuffer *fb,
+		struct drm_file *file_priv, unsigned int *handle)
+{
+	struct imx_drm_fb *imx_drm_fb = to_imx_drm_fb(fb);
+
+	return drm_gem_handle_create(file_priv,
+			&imx_drm_fb->imx_drm_gem_obj->base, handle);
+}
+
+static struct drm_framebuffer_funcs imx_drm_fb_funcs = {
+	.destroy	= imx_drm_fb_destroy,
+	.create_handle	= imx_drm_fb_create_handle,
+};
+
+static struct drm_framebuffer *imx_drm_fb_create(struct drm_device *dev,
+		struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd)
+{
+	struct imx_drm_fb *imx_drm_fb;
+	struct drm_framebuffer *fb;
+	struct drm_gem_object *obj;
+	unsigned int size;
+	int ret;
+	u32 bpp, depth;
+
+	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
+
+	mode_cmd->pitches[0] = max(mode_cmd->pitches[0],
+			mode_cmd->width * (bpp >> 3));
+
+	dev_dbg(dev->dev, "drm fb create(%dx%d)\n",
+			mode_cmd->width, mode_cmd->height);
+
+	imx_drm_fb = kzalloc(sizeof(*imx_drm_fb), GFP_KERNEL);
+	if (!imx_drm_fb) {
+		dev_err(dev->dev, "failed to allocate drm framebuffer.\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	fb = &imx_drm_fb->fb;
+	ret = drm_framebuffer_init(dev, fb, &imx_drm_fb_funcs);
+	if (ret) {
+		dev_err(dev->dev, "failed to initialize framebuffer.\n");
+		goto err_init;
+	}
+
+	dev_dbg(dev->dev, "create: fb id: %d\n", fb->base.id);
+
+	size = mode_cmd->pitches[0] * mode_cmd->height;
+
+	/*
+	 * without file_priv we are called from imx_drm_fbdev_create in which
+	 * case we only create a framebuffer without a handle.
+	 */
+	if (!file_priv) {
+		struct imx_drm_buf_entry *entry;
+
+		entry = imx_drm_buf_create(dev, size);
+		if (IS_ERR(entry)) {
+			ret = PTR_ERR(entry);
+			goto err_buffer;
+		}
+
+		imx_drm_fb->entry = entry;
+	} else {
+		obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
+		if (!obj) {
+			ret = -EINVAL;
+			goto err_buffer;
+		}
+
+		imx_drm_fb->imx_drm_gem_obj = to_imx_drm_gem_obj(obj);
+
+		drm_gem_object_unreference_unlocked(obj);
+
+		imx_drm_fb->entry = imx_drm_fb->imx_drm_gem_obj->entry;
+	}
+
+	drm_helper_mode_fill_fb_struct(fb, mode_cmd);
+
+	return fb;
+
+err_buffer:
+	drm_framebuffer_cleanup(fb);
+
+err_init:
+	kfree(imx_drm_fb);
+
+	return ERR_PTR(ret);
+}
+
+struct imx_drm_buf_entry *imx_drm_fb_get_buf(struct drm_framebuffer *fb)
+{
+	struct imx_drm_fb *imx_drm_fb = to_imx_drm_fb(fb);
+	struct imx_drm_buf_entry *entry;
+
+	entry = imx_drm_fb->entry;
+
+	return entry;
+}
+EXPORT_SYMBOL_GPL(imx_drm_fb_get_buf);
+
+static struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
+	.fb_create = imx_drm_fb_create,
+};
+
+void imx_drm_mode_config_init(struct drm_device *dev)
+{
+	dev->mode_config.min_width = 64;
+	dev->mode_config.min_height = 64;
+
+	/*
+	 * 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 = &imx_drm_mode_config_funcs;
+}
diff --git a/drivers/gpu/drm/imx/imx-fbdev.c b/drivers/gpu/drm/imx/imx-fbdev.c
new file mode 100644
index 0000000..f038797
--- /dev/null
+++ b/drivers/gpu/drm/imx/imx-fbdev.c
@@ -0,0 +1,275 @@
+/*
+ * i.MX drm driver
+ *
+ * Copyright (C) 2012 Sascha Hauer, Pengutronix
+ *
+ * Based on Samsung Exynos code
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "imx-drm.h"
+
+#define MAX_CONNECTOR		4
+#define PREFERRED_BPP		16
+
+static struct fb_ops imx_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 imx_drm_fbdev_update(struct drm_fb_helper *helper,
+				     struct drm_framebuffer *fb,
+				     unsigned int fb_width,
+				     unsigned int fb_height)
+{
+	struct fb_info *fbi = helper->fbdev;
+	struct drm_device *drm = helper->dev;
+	struct imx_drm_buf_entry *entry;
+	unsigned int size = fb_width * fb_height * (fb->bits_per_pixel >> 3);
+	unsigned long offset;
+
+	drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
+	drm_fb_helper_fill_var(fbi, helper, fb_width, fb_height);
+
+	entry = imx_drm_fb_get_buf(fb);
+	if (!entry) {
+		dev_dbg(drm->dev, "entry is null.\n");
+		return -EFAULT;
+	}
+
+	offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
+	offset += fbi->var.yoffset * fb->pitches[0];
+
+	drm->mode_config.fb_base = entry->paddr;
+	fbi->screen_base = entry->vaddr + offset;
+	fbi->fix.smem_start = entry->paddr + offset;
+	fbi->screen_size = size;
+	fbi->fix.smem_len = size;
+	fbi->flags |= FBINFO_CAN_FORCE_OUTPUT;
+
+	return 0;
+}
+
+static int imx_drm_fbdev_create(struct drm_fb_helper *helper,
+				    struct drm_fb_helper_surface_size *sizes)
+{
+	struct drm_device *drm = helper->dev;
+	struct fb_info *fbi;
+	struct drm_framebuffer *fb;
+	struct drm_mode_fb_cmd2 mode_cmd = { 0 };
+	struct platform_device *pdev = drm->platformdev;
+	int ret;
+
+	dev_dbg(drm->dev, "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.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+			sizes->surface_depth);
+
+	mutex_lock(&drm->struct_mutex);
+
+	fbi = framebuffer_alloc(0, &pdev->dev);
+	if (!fbi) {
+		ret = -ENOMEM;
+		goto err_fb_alloc;
+	}
+
+	fb = drm->mode_config.funcs->fb_create(drm, NULL, &mode_cmd);
+	if (IS_ERR(fb)) {
+		dev_err(drm->dev, "failed to create drm framebuffer.\n");
+		ret = PTR_ERR(fb);
+		goto err_fb_create;
+	}
+
+	helper->fb = fb;
+	helper->fbdev = fbi;
+
+	fbi->par = helper;
+	fbi->flags = FBINFO_FLAG_DEFAULT;
+	fbi->fbops = &imx_drm_fb_ops;
+
+	ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+	if (ret)
+		goto err_alloc_cmap;
+
+	ret = imx_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
+			sizes->fb_height);
+	if (ret)
+		goto err_fbdev_update;
+
+	mutex_unlock(&drm->struct_mutex);
+
+	return 0;
+
+err_fbdev_update:
+	fb_dealloc_cmap(&fbi->cmap);
+
+err_alloc_cmap:
+	fb->funcs->destroy(fb);
+
+err_fb_create:
+	framebuffer_release(fbi);
+
+err_fb_alloc:
+	mutex_unlock(&drm->struct_mutex);
+
+	return ret;
+}
+
+static int imx_drm_fbdev_probe(struct drm_fb_helper *helper,
+				   struct drm_fb_helper_surface_size *sizes)
+{
+	int ret;
+
+	BUG_ON(helper->fb);
+
+	ret = imx_drm_fbdev_create(helper, sizes);
+	if (ret) {
+		dev_err(helper->dev->dev, "creating fbdev failed with %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * fb_helper expects a value more than 1 if succeed
+	 * because register_framebuffer() should be called.
+	 */
+	return 1;
+}
+
+static struct drm_fb_helper_funcs imx_drm_fb_helper_funcs = {
+	.fb_probe = imx_drm_fbdev_probe,
+};
+
+static struct drm_fb_helper *imx_drm_fbdev_init(struct drm_device *drm,
+		int preferred_bpp)
+{
+	struct drm_fb_helper *helper;
+	unsigned int num_crtc;
+	int ret;
+
+	helper = kzalloc(sizeof(*helper), GFP_KERNEL);
+	if (!helper)
+		return NULL;
+
+	helper->funcs = &imx_drm_fb_helper_funcs;
+
+	num_crtc = drm->mode_config.num_crtc;
+
+	ret = drm_fb_helper_init(drm, helper, num_crtc, MAX_CONNECTOR);
+	if (ret) {
+		dev_err(drm->dev, "initializing drm fb helper failed with %d\n",
+				ret);
+		goto err_init;
+	}
+
+	ret = drm_fb_helper_single_add_all_connectors(helper);
+	if (ret) {
+		dev_err(drm->dev, "registering drm_fb_helper_connector failed with %d\n",
+				ret);
+		goto err_setup;
+
+	}
+
+	ret = drm_fb_helper_initial_config(helper, preferred_bpp);
+	if (ret) {
+		dev_err(drm->dev, "initial config failed with %d\n", ret);
+		goto err_setup;
+	}
+
+	return helper;
+
+err_setup:
+	drm_fb_helper_fini(helper);
+
+err_init:
+	kfree(helper);
+
+	return NULL;
+}
+
+static void imx_drm_fbdev_fini(struct drm_fb_helper *helper)
+{
+	struct imx_drm_buf_entry *entry;
+
+	if (helper->fbdev) {
+		struct fb_info *info;
+		int ret;
+
+		info = helper->fbdev;
+		ret = unregister_framebuffer(info);
+		if (ret)
+			dev_err(helper->dev->dev, "unregister_framebuffer failed with %d\n",
+					ret);
+
+		if (info->cmap.len)
+			fb_dealloc_cmap(&info->cmap);
+
+		entry = imx_drm_fb_get_buf(helper->fb);
+
+		imx_drm_buf_destroy(helper->dev, entry);
+
+		framebuffer_release(info);
+	}
+
+	drm_fb_helper_fini(helper);
+
+	kfree(helper);
+}
+
+static struct drm_fb_helper *imx_fb_helper;
+
+static int __init imx_fb_helper_init(void)
+{
+	struct drm_device *drm = imx_drm_device_get();
+	int ret;
+
+	if (!drm)
+		return -EINVAL;
+
+	imx_fb_helper = imx_drm_fbdev_init(drm, PREFERRED_BPP);
+	if (!imx_fb_helper) {
+		imx_drm_device_put();
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void __exit imx_fb_helper_exit(void)
+{
+	imx_drm_fbdev_fini(imx_fb_helper);
+	imx_drm_device_put();
+}
+
+late_initcall(imx_fb_helper_init);
+module_exit(imx_fb_helper_exit);
+
+MODULE_DESCRIPTION("Freescale i.MX legacy fb driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/imx/imx-gem.c b/drivers/gpu/drm/imx/imx-gem.c
new file mode 100644
index 0000000..b0866fb
--- /dev/null
+++ b/drivers/gpu/drm/imx/imx-gem.c
@@ -0,0 +1,343 @@
+/*
+ * i.MX drm driver
+ *
+ * Copyright (C) 2012 Sascha Hauer, Pengutronix
+ *
+ * Based on Samsung Exynos code
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "imx-drm.h"
+
+static int lowlevel_buffer_allocate(struct drm_device *drm,
+		struct imx_drm_buf_entry *entry)
+{
+	entry->vaddr = dma_alloc_writecombine(drm->dev, entry->size,
+			(dma_addr_t *)&entry->paddr, GFP_KERNEL);
+	if (!entry->vaddr) {
+		dev_err(drm->dev, "failed to allocate buffer.\n");
+		return -ENOMEM;
+	}
+
+	dev_dbg(drm->dev, "allocated : vaddr(0x%x), paddr(0x%x), size(0x%x)\n",
+			(unsigned int)entry->vaddr, entry->paddr, entry->size);
+
+	return 0;
+}
+
+static void lowlevel_buffer_free(struct drm_device *drm,
+		struct imx_drm_buf_entry *entry)
+{
+	dma_free_writecombine(drm->dev, entry->size, entry->vaddr,
+			entry->paddr);
+}
+
+struct imx_drm_buf_entry *imx_drm_buf_create(struct drm_device *drm,
+		unsigned int size)
+{
+	struct imx_drm_buf_entry *entry;
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return ERR_PTR(-ENOMEM);
+
+	entry->size = size;
+
+	/*
+	 * allocate memory region with size and set the memory information
+	 * to vaddr and paddr of a entry object.
+	 */
+	if (lowlevel_buffer_allocate(drm, entry) < 0) {
+		kfree(entry);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	return entry;
+}
+
+void imx_drm_buf_destroy(struct drm_device *drm,
+		struct imx_drm_buf_entry *entry)
+{
+	lowlevel_buffer_free(drm, entry);
+
+	kfree(entry);
+	entry = NULL;
+}
+EXPORT_SYMBOL_GPL(imx_drm_buf_destroy);
+
+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 unsigned int get_gem_mmap_offset(struct drm_gem_object *obj)
+{
+	return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT;
+}
+
+static struct imx_drm_gem_obj *imx_drm_gem_create(struct drm_device *drm,
+		unsigned int size)
+{
+	struct imx_drm_gem_obj *imx_drm_gem_obj;
+	struct imx_drm_buf_entry *entry;
+	struct drm_gem_object *obj;
+	int ret;
+
+	size = roundup(size, PAGE_SIZE);
+
+	imx_drm_gem_obj = kzalloc(sizeof(*imx_drm_gem_obj), GFP_KERNEL);
+	if (!imx_drm_gem_obj)
+		return ERR_PTR(-ENOMEM);
+
+	/* allocate the new buffer object and memory region. */
+	entry = imx_drm_buf_create(drm, size);
+	if (!entry) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	imx_drm_gem_obj->entry = entry;
+
+	obj = &imx_drm_gem_obj->base;
+
+	ret = drm_gem_object_init(drm, obj, size);
+	if (ret) {
+		dev_err(drm->dev, "initializing GEM object failed with %d\n", ret);
+		goto err_obj_init;
+	}
+
+	ret = drm_gem_create_mmap_offset(obj);
+	if (ret) {
+		dev_err(drm->dev, "creating mmap offset failed with %d\n", ret);
+		goto err_create_mmap_offset;
+	}
+
+	return imx_drm_gem_obj;
+
+err_create_mmap_offset:
+	drm_gem_object_release(obj);
+
+err_obj_init:
+	imx_drm_buf_destroy(drm, imx_drm_gem_obj->entry);
+
+err_alloc:
+	kfree(imx_drm_gem_obj);
+
+	return ERR_PTR(ret);
+}
+
+static struct imx_drm_gem_obj *imx_drm_gem_create_with_handle(struct drm_file *file_priv,
+		struct drm_device *drm, unsigned int size,
+		unsigned int *handle)
+{
+	struct imx_drm_gem_obj *imx_drm_gem_obj;
+	struct drm_gem_object *obj;
+	int ret;
+
+	imx_drm_gem_obj = imx_drm_gem_create(drm, size);
+	if (IS_ERR(imx_drm_gem_obj))
+		return imx_drm_gem_obj;
+
+	obj = &imx_drm_gem_obj->base;
+
+	/*
+	 * 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)
+		goto err_handle_create;
+
+	/* drop reference from allocate - handle holds it now. */
+	drm_gem_object_unreference_unlocked(obj);
+
+	return imx_drm_gem_obj;
+
+err_handle_create:
+	imx_drm_gem_free_object(obj);
+
+	return ERR_PTR(ret);
+}
+
+static int imx_drm_gem_mmap_buffer(struct file *filp,
+		struct vm_area_struct *vma)
+{
+	struct drm_gem_object *obj = filp->private_data;
+	struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj);
+	struct imx_drm_buf_entry *entry;
+	unsigned long pfn, vm_size;
+
+	vma->vm_flags |= VM_IO | VM_RESERVED;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	vma->vm_file = filp;
+
+	vm_size = vma->vm_end - vma->vm_start;
+	/*
+	 * an entry contains information to physically continuous memory
+	 * allocated by user request or at framebuffer creation.
+	 */
+	entry = imx_drm_gem_obj->entry;
+
+	/* check if user-requested size is valid. */
+	if (vm_size > entry->size)
+		return -EINVAL;
+
+	/*
+	 * get page frame number to physical memory to be mapped
+	 * to user space.
+	 */
+	pfn = imx_drm_gem_obj->entry->paddr >> PAGE_SHIFT;
+
+	if (remap_pfn_range(vma, vma->vm_start, pfn, vm_size,
+				vma->vm_page_prot)) {
+		dev_err(obj->dev->dev, "failed to remap pfn range.\n");
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static const struct file_operations imx_drm_gem_fops = {
+	.mmap = imx_drm_gem_mmap_buffer,
+};
+
+int imx_drm_gem_init_object(struct drm_gem_object *obj)
+{
+	return 0;
+}
+
+void imx_drm_gem_free_object(struct drm_gem_object *gem_obj)
+{
+	struct imx_drm_gem_obj *imx_drm_gem_obj;
+
+	if (gem_obj->map_list.map)
+		drm_gem_free_mmap_offset(gem_obj);
+
+	drm_gem_object_release(gem_obj);
+
+	imx_drm_gem_obj = to_imx_drm_gem_obj(gem_obj);
+
+	imx_drm_buf_destroy(gem_obj->dev, imx_drm_gem_obj->entry);
+
+	kfree(imx_drm_gem_obj);
+}
+
+int imx_drm_gem_dumb_create(struct drm_file *file_priv,
+		struct drm_device *dev, struct drm_mode_create_dumb *args)
+{
+	struct imx_drm_gem_obj *imx_drm_gem_obj;
+
+	/* FIXME: This should be configured by the crtc driver */
+	args->pitch = args->width * args->bpp >> 3;
+	args->size = args->pitch * args->height;
+
+	imx_drm_gem_obj = imx_drm_gem_create_with_handle(file_priv, dev, args->size,
+			&args->handle);
+	if (IS_ERR(imx_drm_gem_obj))
+		return PTR_ERR(imx_drm_gem_obj);
+
+	return 0;
+}
+
+int imx_drm_gem_dumb_map_offset(struct drm_file *file_priv,
+		struct drm_device *drm, uint32_t handle, uint64_t *offset)
+{
+	struct imx_drm_gem_obj *imx_drm_gem_obj;
+	struct drm_gem_object *obj;
+
+	mutex_lock(&drm->struct_mutex);
+
+	obj = drm_gem_object_lookup(drm, file_priv, handle);
+	if (!obj) {
+		dev_err(drm->dev, "failed to lookup gem object\n");
+		mutex_unlock(&drm->struct_mutex);
+		return -EINVAL;
+	}
+
+	imx_drm_gem_obj = to_imx_drm_gem_obj(obj);
+
+	*offset = get_gem_mmap_offset(&imx_drm_gem_obj->base);
+
+	drm_gem_object_unreference(obj);
+
+	mutex_unlock(&drm->struct_mutex);
+
+	return 0;
+}
+
+int imx_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct drm_gem_object *obj = vma->vm_private_data;
+	struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj);
+	struct drm_device *dev = obj->dev;
+	unsigned long pfn;
+	pgoff_t page_offset;
+	int ret;
+
+	page_offset = ((unsigned long)vmf->virtual_address -
+			vma->vm_start) >> PAGE_SHIFT;
+
+	mutex_lock(&dev->struct_mutex);
+
+	pfn = (imx_drm_gem_obj->entry->paddr >> PAGE_SHIFT) + page_offset;
+
+	ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return convert_to_vm_err_msg(ret);
+}
+
+int imx_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	int ret;
+
+	ret = drm_gem_mmap(filp, vma);
+	if (ret)
+		return ret;
+
+	vma->vm_flags &= ~VM_PFNMAP;
+	vma->vm_flags |= VM_MIXEDMAP;
+
+	return ret;
+}
+
+
+int imx_drm_gem_dumb_destroy(struct drm_file *file_priv,
+		struct drm_device *dev, unsigned int handle)
+{
+	return drm_gem_handle_delete(file_priv, handle);
+}
diff --git a/drivers/gpu/drm/imx/imx-lcdc-crtc.c b/drivers/gpu/drm/imx/imx-lcdc-crtc.c
new file mode 100644
index 0000000..e77c015
--- /dev/null
+++ b/drivers/gpu/drm/imx/imx-lcdc-crtc.c
@@ -0,0 +1,517 @@
+/*
+ * i.MX LCDC crtc driver
+ *
+ * Copyright (C) 2012 Sascha Hauer, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <linux/fb.h>
+#include <linux/clk.h>
+#include <asm/fb.h>
+#include <linux/module.h>
+#include <mach/hardware.h>
+#include <mach/imxfb.h>
+#include <generated/mach-types.h>
+
+#include "imx-drm.h"
+
+#define LCDC_SSA		0x00
+#define LCDC_SIZE		0x04
+#define LCDC_VPW		0x08
+#define LCDC_CPOS		0x0C
+#define LCDC_LCWHB		0x10
+#define LCDC_LCHCC		0x14
+#define LCDC_PCR		0x18
+#define LCDC_HCR		0x1C
+#define LCDC_VCR		0x20
+#define LCDC_POS		0x24
+#define LCDC_LSCR1		0x28
+#define LCDC_PWMR		0x2C
+#define LCDC_DMACR		0x30
+#define LCDC_RMCR		0x34
+#define LCDC_LCDICR		0x38
+#define LCDC_LIER		0x3c
+#define LCDC_LISR		0x40
+
+#define SIZE_XMAX(x)		((((x) >> 4) & 0x3f) << 20)
+
+#define YMAX_MASK		(cpu_is_mx1() ? 0x1ff : 0x3ff)
+#define SIZE_YMAX(y)		((y) & YMAX_MASK)
+
+#define VPW_VPW(x)		((x) & 0x3ff)
+
+#define HCR_H_WIDTH(x)		(((x) & 0x3f) << 26)
+#define HCR_H_WAIT_1(x)		(((x) & 0xff) << 8)
+#define HCR_H_WAIT_2(x)		((x) & 0xff)
+
+#define VCR_V_WIDTH(x)		(((x) & 0x3f) << 26)
+#define VCR_V_WAIT_1(x)		(((x) & 0xff) << 8)
+#define VCR_V_WAIT_2(x)		((x) & 0xff)
+
+#define RMCR_LCDC_EN_MX1	(1 << 1)
+
+#define RMCR_SELF_REF		(1 << 0)
+
+#define LIER_EOF		(1 << 1)
+
+struct imx_crtc {
+	struct drm_crtc		base;
+	struct imx_drm_crtc	*imx_drm_crtc;
+	int			di_no;
+	int			enabled;
+	void __iomem		*regs;
+	u32			pwmr;
+	u32			lscr1;
+	u32			dmacr;
+	u32			pcr;
+	struct clk		*clk;
+	struct device		*dev;
+	int			vblank_enable;
+
+	struct drm_pending_vblank_event *page_flip_event;
+	struct drm_framebuffer	*newfb;
+};
+
+#define to_imx_crtc(x) container_of(x, struct imx_crtc, base)
+
+static void imx_crtc_load_lut(struct drm_crtc *crtc)
+{
+}
+
+#define PCR_BPIX_8		(3 << 25)
+#define PCR_BPIX_12		(4 << 25)
+#define PCR_BPIX_16		(5 << 25)
+#define PCR_BPIX_18		(6 << 25)
+#define PCR_END_SEL		(1 << 18)
+#define PCR_END_BYTE_SWAP	(1 << 17)
+
+const char *fourcc_to_str(u32 fourcc)
+{
+	static char buf[5];
+
+	*(u32 *)buf = fourcc;
+	buf[4] = 0;
+
+	return buf;
+}
+
+static int imx_drm_crtc_set(struct drm_crtc *crtc,
+		struct drm_display_mode *mode)
+{
+	struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
+	struct drm_framebuffer *fb = crtc->fb;
+	int lower_margin = mode->vsync_start - mode->vdisplay;
+	int upper_margin = mode->vtotal - mode->vsync_end;
+	int vsync_len = mode->vsync_end - mode->vsync_start;
+	int hsync_len = mode->hsync_end - mode->hsync_start;
+	int right_margin = mode->hsync_start - mode->hdisplay;
+	int left_margin = mode->htotal - mode->hsync_end;
+	unsigned long lcd_clk;
+	u32 pcr;
+
+	lcd_clk = clk_get_rate(imx_crtc->clk) / 1000;
+
+	if (!mode->clock)
+		return -EINVAL;
+
+	pcr = DIV_ROUND_CLOSEST(lcd_clk, mode->clock);
+	if (--pcr > 0x3f)
+		pcr = 0x3f;
+
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+		pcr |= PCR_BPIX_18;
+		pcr |= PCR_END_SEL | PCR_END_BYTE_SWAP;
+		break;
+	case DRM_FORMAT_RGB565:
+		if (cpu_is_mx1())
+			pcr |= PCR_BPIX_12;
+		else
+			pcr |= PCR_BPIX_16;
+		break;
+	case DRM_FORMAT_RGB332:
+		pcr |= PCR_BPIX_8;
+		break;
+	default:
+		dev_err(imx_crtc->dev, "unsupported pixel format %s\n",
+				fourcc_to_str(fb->pixel_format));
+		return -EINVAL;
+	}
+
+	/* add sync polarities */
+	pcr |= imx_crtc->pcr & ~(0x3f | (7 << 25));
+
+	dev_dbg(imx_crtc->dev,
+			"xres=%d hsync_len=%d left_margin=%d right_margin=%d\n",
+			mode->hdisplay, hsync_len,
+			left_margin, right_margin);
+	dev_dbg(imx_crtc->dev,
+			"yres=%d vsync_len=%d upper_margin=%d lower_margin=%d\n",
+			mode->vdisplay, vsync_len,
+			upper_margin, lower_margin);
+
+	writel(VPW_VPW(mode->hdisplay * fb->bits_per_pixel / 8 / 4),
+		imx_crtc->regs + LCDC_VPW);
+
+	writel(HCR_H_WIDTH(hsync_len - 1) |
+		HCR_H_WAIT_1(right_margin - 1) |
+		HCR_H_WAIT_2(left_margin - 3),
+		imx_crtc->regs + LCDC_HCR);
+
+	writel(VCR_V_WIDTH(vsync_len) |
+		VCR_V_WAIT_1(lower_margin) |
+		VCR_V_WAIT_2(upper_margin),
+		imx_crtc->regs + LCDC_VCR);
+
+	writel(SIZE_XMAX(mode->hdisplay) | SIZE_YMAX(mode->vdisplay),
+			imx_crtc->regs + LCDC_SIZE);
+
+	writel(pcr, imx_crtc->regs + LCDC_PCR);
+	writel(imx_crtc->pwmr, imx_crtc->regs + LCDC_PWMR);
+	writel(imx_crtc->lscr1, imx_crtc->regs + LCDC_LSCR1);
+	/* reset default */
+	writel(0x00040060, imx_crtc->regs + LCDC_DMACR);
+
+	return 0;
+}
+
+static int imx_drm_set_base(struct drm_crtc *crtc, int x, int y)
+{
+	struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
+	struct imx_drm_buf_entry *entry;
+	struct drm_framebuffer *fb = crtc->fb;
+	unsigned long phys;
+
+	entry = imx_drm_fb_get_buf(fb);
+	if (!entry)
+		return -EFAULT;
+
+	phys = entry->paddr;
+	phys += x * (fb->bits_per_pixel >> 3);
+	phys += y * fb->pitches[0];
+
+	dev_dbg(imx_crtc->dev, "%s: phys: 0x%lx\n", __func__, phys);
+	dev_dbg(imx_crtc->dev, "%s: xy: %dx%d\n", __func__, x, y);
+
+	writel(phys, imx_crtc->regs + LCDC_SSA);
+
+	return 0;
+}
+
+static int imx_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 imx_crtc *imx_crtc = to_imx_crtc(crtc);
+
+	imx_drm_set_base(crtc, x, y);
+
+	dev_dbg(imx_crtc->dev, "mode->hdisplay: %d\n", mode->hdisplay);
+	dev_dbg(imx_crtc->dev, "mode->vdisplay: %d\n", mode->vdisplay);
+
+	return imx_drm_crtc_set(crtc, mode);
+}
+
+static void imx_crtc_enable(struct imx_crtc *imx_crtc)
+{
+	if (!imx_crtc->enabled)
+		clk_enable(imx_crtc->clk);
+	imx_crtc->enabled = 1;
+}
+
+static void imx_crtc_disable(struct imx_crtc *imx_crtc)
+{
+	if (imx_crtc->enabled)
+		clk_disable(imx_crtc->clk);
+	imx_crtc->enabled = 0;
+}
+
+static void imx_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
+
+	dev_dbg(imx_crtc->dev, "%s mode: %d\n", __func__, mode);
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		imx_crtc_enable(imx_crtc);
+		break;
+	default:
+		imx_crtc_disable(imx_crtc);
+		break;
+	}
+}
+
+static bool imx_crtc_mode_fixup(struct drm_crtc *crtc,
+				  struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void imx_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
+
+	imx_crtc_disable(imx_crtc);
+}
+
+static void imx_crtc_commit(struct drm_crtc *crtc)
+{
+	struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
+
+	imx_crtc_enable(imx_crtc);
+}
+
+static struct drm_crtc_helper_funcs imx_helper_funcs = {
+	.dpms = imx_crtc_dpms,
+	.mode_fixup = imx_crtc_mode_fixup,
+	.mode_set = imx_crtc_mode_set,
+	.prepare = imx_crtc_prepare,
+	.commit = imx_crtc_commit,
+	.load_lut = imx_crtc_load_lut,
+};
+
+static void imx_drm_handle_pageflip(struct imx_crtc *imx_crtc)
+{
+	struct drm_pending_vblank_event *e;
+	struct timeval now;
+	unsigned long flags;
+	struct drm_device *drm = imx_crtc->base.dev;
+
+	spin_lock_irqsave(&drm->event_lock, flags);
+
+	e = imx_crtc->page_flip_event;
+
+	if (!e) {
+		spin_unlock_irqrestore(&drm->event_lock, flags);
+		return;
+	}
+
+	do_gettimeofday(&now);
+	e->event.sequence = 0;
+	e->event.tv_sec = now.tv_sec;
+	e->event.tv_usec = now.tv_usec;
+	imx_crtc->page_flip_event = NULL;
+
+	list_add_tail(&e->base.link, &e->base.file_priv->event_list);
+
+	wake_up_interruptible(&e->base.file_priv->event_wait);
+
+	spin_unlock_irqrestore(&drm->event_lock, flags);
+}
+
+static int imx_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+	struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
+
+	writel(LIER_EOF, imx_crtc->regs + LCDC_LIER);
+
+	return 0;
+}
+
+static void imx_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+	struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
+
+	writel(0, imx_crtc->regs + LCDC_LIER);
+}
+
+static irqreturn_t imx_irq_handler(int irq, void *dev_id)
+{
+	struct imx_crtc *imx_crtc = dev_id;
+	struct drm_device *drm = imx_crtc->base.dev;
+
+	/* Acknowledge interrupt */
+	readl(imx_crtc->regs + LCDC_LISR);
+
+	drm_handle_vblank(drm, 0);
+
+	if (imx_crtc->newfb) {
+		imx_crtc->base.fb = imx_crtc->newfb;
+		imx_crtc->newfb = NULL;
+		imx_drm_set_base(&imx_crtc->base, 0, 0);
+		imx_drm_handle_pageflip(imx_crtc);
+		imx_drm_crtc_vblank_put(imx_crtc->imx_drm_crtc);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int imx_page_flip(struct drm_crtc *crtc,
+                         struct drm_framebuffer *fb,
+                         struct drm_pending_vblank_event *event)
+{
+	struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
+
+	if (imx_crtc->newfb)
+		return -EBUSY;
+
+	imx_crtc->newfb = fb;
+	imx_crtc->page_flip_event = event;
+	imx_drm_crtc_vblank_get(imx_crtc->imx_drm_crtc);
+
+	return 0;
+}
+
+static const struct drm_crtc_funcs imx_crtc_funcs = {
+	.page_flip = imx_page_flip,
+};
+
+static const struct imx_drm_crtc_helper_funcs imx_imx_drm_helper = {
+	.enable_vblank = imx_crtc_enable_vblank,
+	.disable_vblank = imx_crtc_disable_vblank,
+};
+
+#define DRIVER_NAME "imx-lcdc-crtc"
+
+/*
+ * the pcr bits to be allowed to set in platform data
+ */
+#define PDATA_PCR	(PCR_PIXPOL | PCR_FLMPOL | PCR_LPPOL | \
+			PCR_CLKPOL | PCR_OEPOL | PCR_TFT | PCR_COLOR | \
+			PCR_PBSIZ_8 | PCR_ACD(0x7f) | PCR_ACD_SEL | \
+			PCR_SCLK_SEL | PCR_SHARP)
+
+static int __devinit imx_crtc_probe(struct platform_device *pdev)
+{
+	struct imx_crtc *imx_crtc;
+	struct resource *res;
+	int ret, irq;
+	u32 pcr_value = 0xf00080c0;
+	u32 lscr1_value = 0x00120300;
+	u32 pwmr_value = 0x00a903ff;
+
+	imx_crtc = devm_kzalloc(&pdev->dev, sizeof(*imx_crtc), GFP_KERNEL);
+	if (!imx_crtc)
+		return -ENOMEM;
+
+	imx_crtc->dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	res = devm_request_mem_region(&pdev->dev, res->start,
+			resource_size(res), DRIVER_NAME);
+	if (!res)
+		return -EBUSY;
+
+	imx_crtc->regs = devm_ioremap(&pdev->dev, res->start,
+			resource_size(res));
+	if (!imx_crtc->regs) {
+		dev_err(&pdev->dev, "Cannot map frame buffer registers\n");
+		return -EBUSY;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	ret = devm_request_irq(&pdev->dev, irq, imx_irq_handler, 0, "imx_drm",
+			imx_crtc);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "irq request failed with %d\n", ret);
+		return ret;
+	}
+
+	imx_crtc->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(imx_crtc->clk)) {
+		ret = PTR_ERR(imx_crtc->clk);
+		dev_err(&pdev->dev, "unable to get clock: %d\n", ret);
+		return ret;
+	}
+
+	clk_prepare_enable(imx_crtc->clk);
+	imx_crtc->enabled = 1;
+
+	platform_set_drvdata(pdev, imx_crtc);
+
+	imx_crtc->pcr = pcr_value & PDATA_PCR;
+
+	if (imx_crtc->pcr != pcr_value)
+		dev_err(&pdev->dev, "invalid bits set in pcr: 0x%08x\n",
+				pcr_value & ~PDATA_PCR);
+
+	imx_crtc->lscr1 = lscr1_value;
+	imx_crtc->pwmr = pwmr_value;
+
+	ret = imx_drm_add_crtc(&imx_crtc->base,
+			&imx_crtc->imx_drm_crtc,
+			&imx_crtc_funcs, &imx_helper_funcs,
+			&imx_imx_drm_helper, THIS_MODULE);
+	if (ret)
+		goto err_init;
+
+	dev_info(&pdev->dev, "probed\n");
+
+	return 0;
+
+err_init:
+	clk_disable_unprepare(imx_crtc->clk);
+	clk_put(imx_crtc->clk);
+
+	return ret;
+}
+
+static int __devexit imx_crtc_remove(struct platform_device *pdev)
+{
+	struct imx_crtc *imx_crtc = platform_get_drvdata(pdev);
+
+	imx_drm_remove_crtc(imx_crtc->imx_drm_crtc);
+
+	writel(0, imx_crtc->regs + LCDC_LIER);
+
+	clk_disable_unprepare(imx_crtc->clk);
+	clk_put(imx_crtc->clk);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static const struct of_device_id imx_lcdc_dt_ids[] = {
+	{ .compatible = "fsl,imx1-lcdc", .data = NULL, },
+	{ .compatible = "fsl,imx21-lcdc", .data = NULL, },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver imx_crtc_driver = {
+	.remove		= __devexit_p(imx_crtc_remove),
+	.probe		= imx_crtc_probe,
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = imx_lcdc_dt_ids,
+	},
+};
+
+static int __init imx_lcdc_init(void)
+{
+	return platform_driver_register(&imx_crtc_driver);
+}
+
+static void __exit imx_lcdc_exit(void)
+{
+	platform_driver_unregister(&imx_crtc_driver);
+}
+
+module_init(imx_lcdc_init);
+module_exit(imx_lcdc_exit)
+
+MODULE_DESCRIPTION("Freescale i.MX framebuffer driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/imx/imx-parallel-display.c b/drivers/gpu/drm/imx/imx-parallel-display.c
new file mode 100644
index 0000000..8c96113
--- /dev/null
+++ b/drivers/gpu/drm/imx/imx-parallel-display.c
@@ -0,0 +1,228 @@
+/*
+ * i.MX drm driver - parallel display implementation
+ *
+ * Copyright (C) 2012 Sascha Hauer, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "imx-drm.h"
+
+#define con_to_imxpd(x) container_of(x, struct imx_parallel_display, connector)
+#define enc_to_imxpd(x) container_of(x, struct imx_parallel_display, encoder)
+
+struct imx_parallel_display {
+	struct drm_connector connector;
+	struct imx_drm_connector *imx_drm_connector;
+	struct drm_encoder encoder;
+	struct imx_drm_encoder *imx_drm_encoder;
+	struct device *dev;
+	void *edid;
+	int edid_len;
+};
+
+static enum drm_connector_status imx_pd_connector_detect(struct drm_connector *connector,
+		bool force)
+{
+	return connector_status_connected;
+}
+
+static void imx_pd_connector_destroy(struct drm_connector *connector)
+{
+	/* do not free here */
+}
+
+static int imx_pd_connector_get_modes(struct drm_connector *connector)
+{
+	struct imx_parallel_display *imxpd = con_to_imxpd(connector);
+	int ret;
+
+	drm_mode_connector_update_edid_property(connector, imxpd->edid);
+	ret = drm_add_edid_modes(connector, imxpd->edid);
+	connector->display_info.raw_edid = NULL;
+
+	return ret;
+}
+
+static int imx_pd_connector_mode_valid(struct drm_connector *connector,
+			  struct drm_display_mode *mode)
+{
+	return 0;
+}
+
+static struct drm_encoder *imx_pd_connector_best_encoder(struct drm_connector *connector)
+{
+	struct imx_parallel_display *imxpd = con_to_imxpd(connector);
+
+	return &imxpd->encoder;
+}
+
+static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+}
+
+static bool imx_pd_encoder_mode_fixup(struct drm_encoder *encoder,
+			   struct drm_display_mode *mode,
+			   struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void imx_pd_encoder_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void imx_pd_encoder_commit(struct drm_encoder *encoder)
+{
+}
+
+static void imx_pd_encoder_mode_set(struct drm_encoder *encoder,
+			 struct drm_display_mode *mode,
+			 struct drm_display_mode *adjusted_mode)
+{
+}
+
+static void imx_pd_encoder_disable(struct drm_encoder *encoder)
+{
+}
+
+static void imx_pd_encoder_destroy(struct drm_encoder *encoder)
+{
+	/* do not free here */
+}
+
+struct drm_connector_funcs imx_pd_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = imx_pd_connector_detect,
+	.destroy = imx_pd_connector_destroy,
+};
+
+struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = {
+	.get_modes = imx_pd_connector_get_modes,
+	.best_encoder = imx_pd_connector_best_encoder,
+	.mode_valid = imx_pd_connector_mode_valid,
+};
+
+static struct drm_encoder_funcs imx_pd_encoder_funcs = {
+	.destroy = imx_pd_encoder_destroy,
+};
+
+static struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = {
+	.dpms = imx_pd_encoder_dpms,
+	.mode_fixup = imx_pd_encoder_mode_fixup,
+	.prepare = imx_pd_encoder_prepare,
+	.commit = imx_pd_encoder_commit,
+	.mode_set = imx_pd_encoder_mode_set,
+	.disable = imx_pd_encoder_disable,
+};
+
+static int imx_pd_register(struct imx_parallel_display *imxpd)
+{
+	int ret;
+
+	drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder);
+
+	imxpd->connector.funcs = &imx_pd_connector_funcs;
+	imxpd->encoder.funcs = &imx_pd_encoder_funcs;
+
+	drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs);
+	ret = imx_drm_add_encoder(&imxpd->encoder, &imxpd->imx_drm_encoder, THIS_MODULE);
+	if (ret) {
+		dev_err(imxpd->dev, "adding encoder failed with %d\n", ret);
+		return ret;
+	}
+
+	drm_connector_helper_add(&imxpd->connector, &imx_pd_connector_helper_funcs);
+
+	ret = imx_drm_add_connector(&imxpd->connector, &imxpd->imx_drm_connector,
+			THIS_MODULE);
+	if (ret) {
+		imx_drm_remove_encoder(imxpd->imx_drm_encoder);
+		dev_err(imxpd->dev, "adding connector failed with %d\n", ret);
+		return ret;
+	}
+
+	imxpd->connector.encoder = &imxpd->encoder;
+
+	return 0;
+}
+
+static int __devinit imx_pd_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	const u8 *edidp;
+	struct imx_parallel_display *imxpd;
+	int ret;
+
+	imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL);
+	if (!imxpd)
+		return -ENOMEM;
+
+	edidp = of_get_property(np, "edid", &imxpd->edid_len);
+
+	imxpd->edid = kmemdup(edidp, imxpd->edid_len, GFP_KERNEL);
+	imxpd->encoder.possible_crtcs = 0x1;
+	imxpd->encoder.possible_clones = 0x1;
+	imxpd->dev = &pdev->dev;
+
+	ret = imx_pd_register(imxpd);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, imxpd);
+
+	return 0;
+}
+
+static int __devexit imx_pd_remove(struct platform_device *pdev)
+{
+	struct imx_parallel_display *imxpd = platform_get_drvdata(pdev);
+	struct drm_connector *connector = &imxpd->connector;
+	struct drm_encoder *encoder = &imxpd->encoder;
+
+	drm_mode_connector_detach_encoder(connector, encoder);
+
+	imx_drm_remove_connector(imxpd->imx_drm_connector);
+	imx_drm_remove_encoder(imxpd->imx_drm_encoder);
+
+	return 0;
+}
+
+static const struct of_device_id imx_pd_dt_ids[] = {
+	{ .compatible = "fsl,imx-parallel-display", .data = NULL, },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver imx_pd_driver = {
+	.probe		= imx_pd_probe,
+	.remove		= __devexit_p(imx_pd_remove),
+	.driver		= {
+		.of_match_table = imx_pd_dt_ids,
+		.name	= "imx-parallel-display",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(imx_pd_driver);
+
+MODULE_DESCRIPTION("i.MX parallel display driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 2/2] pcm038 lcdc support
  2012-05-18 12:27 (unknown), Sascha Hauer
  2012-05-18 12:27 ` [PATCH 1/2] DRM: add Freescale i.MX LCDC driver Sascha Hauer
@ 2012-05-18 12:27 ` Sascha Hauer
  2012-05-18 14:03   ` Adam Jackson
  2012-05-22 14:06 ` Lars-Peter Clausen
  2 siblings, 1 reply; 35+ messages in thread
From: Sascha Hauer @ 2012-05-18 12:27 UTC (permalink / raw)
  To: dri-devel; +Cc: Sascha Hauer, linux-arm-kernel

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/boot/dts/imx27-phytec-phycore.dts |   39 ++++++++++++++++++++++++++++
 arch/arm/boot/dts/imx27.dtsi               |    7 +++++
 arch/arm/mach-imx/clock-imx27.c            |    1 +
 3 files changed, 47 insertions(+)

diff --git a/arch/arm/boot/dts/imx27-phytec-phycore.dts b/arch/arm/boot/dts/imx27-phytec-phycore.dts
index a51a08f..bdb7547 100644
--- a/arch/arm/boot/dts/imx27-phytec-phycore.dts
+++ b/arch/arm/boot/dts/imx27-phytec-phycore.dts
@@ -20,6 +20,41 @@
 		reg = <0x0 0x0>;
 	};
 
+	baseboard {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+                #size-cells = <1>;
+
+		display {
+			compatible = "fsl,imx-parallel-display";
+			edid = [00 ff ff ff ff ff ff 00 4c 2d 6c 03 36 32 49 4b
+				0f 13 01 03 80 37 22 a0 2a fe 21 a8 53 37 ae 24
+				11 50 54
+
+				/* est timings */
+				00 00 00
+
+				/* std timings */
+				00 00
+				00 00
+				00 00
+				00 00
+				00 00
+				00 00
+				00 00
+				00 00
+
+				/* detailed timings */
+				05 0D 20 A0 30 58 1C 20 28 20 14 00 26 57 21 00 00 1E
+				00 00 00 fd 00 32 4b 1b	51 11 00 0a 20 20 20 20 20 20
+				00 00 00 fc 00 53 79 6e 63 4d 61 73 74 65 72 0a 20 20
+				00 00 00 ff 00 48 39 58 53 34 30 30 34 34 32 0a 20 20
+				00 20];
+
+			crtc = <&lcdc 0>;
+		};
+	};
+
 	soc {
 		aipi@10000000 { /* aipi */
 
@@ -46,6 +81,10 @@
 				status = "okay";
 			};
 
+			lcdc@10021000 {
+				status = "okay";
+			};
+
 			i2c@1001d000 {
 				clock-frequency = <400000>;
 				status = "okay";
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
index bc5e7d5..eab9095 100644
--- a/arch/arm/boot/dts/imx27.dtsi
+++ b/arch/arm/boot/dts/imx27.dtsi
@@ -206,6 +206,13 @@
 				status = "disabled";
 			};
 
+			lcdc: lcdc@10021000 {
+				compatible = "fsl,imx27-lcdc", "fsl,imx21-lcdc";
+				reg = <0x10021000 0x4000>;
+				interrupts = <61>;
+				status = "enabled";
+			};
+
 			fec: fec@1002b000 {
 				compatible = "fsl,imx27-fec";
 				reg = <0x1002b000 0x4000>;
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c
index 98e04f5..a393483 100644
--- a/arch/arm/mach-imx/clock-imx27.c
+++ b/arch/arm/mach-imx/clock-imx27.c
@@ -646,6 +646,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("imx27-cspi.1", NULL, cspi2_clk)
 	_REGISTER_CLOCK("imx27-cspi.2", NULL, cspi3_clk)
 	_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
+	_REGISTER_CLOCK("10021000.lcdc", NULL, lcdc_clk)
 	_REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk)
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk1)
-- 
1.7.10

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH 2/2] pcm038 lcdc support
  2012-05-18 12:27 ` [PATCH 2/2] pcm038 lcdc support Sascha Hauer
@ 2012-05-18 14:03   ` Adam Jackson
  2012-05-18 15:13     ` Sascha Hauer
  0 siblings, 1 reply; 35+ messages in thread
From: Adam Jackson @ 2012-05-18 14:03 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: linux-arm-kernel, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 1062 bytes --]

On Fri, 2012-05-18 at 14:27 +0200, Sascha Hauer wrote:

> +			edid = [00 ff ff ff ff ff ff 00 4c 2d 6c 03 36 32 49 4b
> +				0f 13 01 03 80 37 22 a0 2a fe 21 a8 53 37 ae 24
> +				11 50 54
> +
> +				/* est timings */
> +				00 00 00
> +
> +				/* std timings */
> +				00 00
> +				00 00
> +				00 00
> +				00 00
> +				00 00
> +				00 00
> +				00 00
> +				00 00
> +
> +				/* detailed timings */
> +				05 0D 20 A0 30 58 1C 20 28 20 14 00 26 57 21 00 00 1E
> +				00 00 00 fd 00 32 4b 1b	51 11 00 0a 20 20 20 20 20 20
> +				00 00 00 fc 00 53 79 6e 63 4d 61 73 74 65 72 0a 20 20
> +				00 00 00 ff 00 48 39 58 53 34 30 30 34 34 32 0a 20 20
> +				00 20];

This EDID block claims to be a Samsung SyncMaster, which isn't really
the right thing to do.  The question is what to call it instead.  Red
Hat has a PNP ID we can use for virtual EDID blocks like this if we
want, I'd want to set up a little database to keep track of them but
that's pretty trivial.

Also, empty standard timing fields are 01 01, not 00 00.

- ajax

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 2/2] pcm038 lcdc support
  2012-05-18 14:03   ` Adam Jackson
@ 2012-05-18 15:13     ` Sascha Hauer
  2012-05-22 10:02       ` Dave Airlie
  0 siblings, 1 reply; 35+ messages in thread
From: Sascha Hauer @ 2012-05-18 15:13 UTC (permalink / raw)
  To: Adam Jackson; +Cc: linux-arm-kernel, dri-devel

On Fri, May 18, 2012 at 10:03:54AM -0400, Adam Jackson wrote:
> On Fri, 2012-05-18 at 14:27 +0200, Sascha Hauer wrote:
> 
> > +			edid = [00 ff ff ff ff ff ff 00 4c 2d 6c 03 36 32 49 4b
> > +				0f 13 01 03 80 37 22 a0 2a fe 21 a8 53 37 ae 24
> > +				11 50 54
> > +
> > +				/* est timings */
> > +				00 00 00
> > +
> > +				/* std timings */
> > +				00 00
> > +				00 00
> > +				00 00
> > +				00 00
> > +				00 00
> > +				00 00
> > +				00 00
> > +				00 00
> > +
> > +				/* detailed timings */
> > +				05 0D 20 A0 30 58 1C 20 28 20 14 00 26 57 21 00 00 1E
> > +				00 00 00 fd 00 32 4b 1b	51 11 00 0a 20 20 20 20 20 20
> > +				00 00 00 fc 00 53 79 6e 63 4d 61 73 74 65 72 0a 20 20
> > +				00 00 00 ff 00 48 39 58 53 34 30 30 34 34 32 0a 20 20
> > +				00 20];
> 
> This EDID block claims to be a Samsung SyncMaster, which isn't really
> the right thing to do.  The question is what to call it instead.  Red
> Hat has a PNP ID we can use for virtual EDID blocks like this if we
> want, I'd want to set up a little database to keep track of them but
> that's pretty trivial.

Sorry, should have mentioned this in the commit log. This in fact is a
hacked version of my office monitor. This patch is more meant as a usage
example and not for upstream. I don't know yet if it's even acceptable
to put edid data into the devicetree. I saw some discussion about it,
but also about some generic display description, which I would prefer.

BTW is there a more convenient tool than a hex editor around to generate
edid data? I only found some windows tools

> 
> Also, empty standard timing fields are 01 01, not 00 00.

Good to know

Thanks
 Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 2/2] pcm038 lcdc support
  2012-05-18 15:13     ` Sascha Hauer
@ 2012-05-22 10:02       ` Dave Airlie
  0 siblings, 0 replies; 35+ messages in thread
From: Dave Airlie @ 2012-05-22 10:02 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: dri-devel, linux-arm-kernel

On Fri, May 18, 2012 at 4:13 PM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Fri, May 18, 2012 at 10:03:54AM -0400, Adam Jackson wrote:
>> On Fri, 2012-05-18 at 14:27 +0200, Sascha Hauer wrote:
>>
>> > +                   edid = [00 ff ff ff ff ff ff 00 4c 2d 6c 03 36 32 49 4b
>> > +                           0f 13 01 03 80 37 22 a0 2a fe 21 a8 53 37 ae 24
>> > +                           11 50 54
>> > +
>> > +                           /* est timings */
>> > +                           00 00 00
>> > +
>> > +                           /* std timings */
>> > +                           00 00
>> > +                           00 00
>> > +                           00 00
>> > +                           00 00
>> > +                           00 00
>> > +                           00 00
>> > +                           00 00
>> > +                           00 00
>> > +
>> > +                           /* detailed timings */
>> > +                           05 0D 20 A0 30 58 1C 20 28 20 14 00 26 57 21 00 00 1E
>> > +                           00 00 00 fd 00 32 4b 1b 51 11 00 0a 20 20 20 20 20 20
>> > +                           00 00 00 fc 00 53 79 6e 63 4d 61 73 74 65 72 0a 20 20
>> > +                           00 00 00 ff 00 48 39 58 53 34 30 30 34 34 32 0a 20 20
>> > +                           00 20];
>>
>> This EDID block claims to be a Samsung SyncMaster, which isn't really
>> the right thing to do.  The question is what to call it instead.  Red
>> Hat has a PNP ID we can use for virtual EDID blocks like this if we
>> want, I'd want to set up a little database to keep track of them but
>> that's pretty trivial.
>
> Sorry, should have mentioned this in the commit log. This in fact is a
> hacked version of my office monitor. This patch is more meant as a usage
> example and not for upstream. I don't know yet if it's even acceptable
> to put edid data into the devicetree. I saw some discussion about it,
> but also about some generic display description, which I would prefer.
>
> BTW is there a more convenient tool than a hex editor around to generate
> edid data? I only found some windows tools

Some basic stuff in Documentation/EDID/ but yeah don't know of
anything graphical for Linux.

Dave.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re:
  2012-05-18 12:27 (unknown), Sascha Hauer
  2012-05-18 12:27 ` [PATCH 1/2] DRM: add Freescale i.MX LCDC driver Sascha Hauer
  2012-05-18 12:27 ` [PATCH 2/2] pcm038 lcdc support Sascha Hauer
@ 2012-05-22 14:06 ` Lars-Peter Clausen
  2012-05-23  8:12   ` Re: Sascha Hauer
  2012-05-24  6:31   ` Re: Sascha Hauer
  2 siblings, 2 replies; 35+ messages in thread
From: Lars-Peter Clausen @ 2012-05-22 14:06 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: linux-arm-kernel, dri-devel

On 05/18/2012 02:27 PM, Sascha Hauer wrote:
> Hi All,
> 
> The following adds a drm/kms driver for the Freescale i.MX LCDC
> controller. Most notable change to the last SDRM based version is that
> the SDRM layer has been removed and the driver now is purely i.MX
> specific. I hope that this is more acceptable now.
> 
> Another change is that the probe is now devicetree based. For now I
> took the easy way out and only put an edid blob into the devicetree.
> I haven't documented the binding yet, I would add that when the rest
> is considered ok.
> 
> Comments very welcome.
> 

Hi,

I really liked the sdrm layer. At least some bits of it. I've been working
on a "simple" DRM driver as well. The hardware has no fancy acceleration
features, just a simple buffer and some scanout logic. I'm basically using
the same gem buffer structure and the buffer is also allocated using
dma_alloc_writecombine, which means we can probably share all of the GEM
handling code and probably also most of the fbdev code. I also started with
the Exynos GEM code as a template, but reworked it later to be more like the
UDL code, which made it a bit more compact. I think it would be a good idea
to put at least the GEM handling in some common code as I expect that we'll
see more similar "simple" DRM drivers pop up.

The code in question can be found at
https://github.com/lclausen-adi/linux-2.6/commit/87a8fd6b98eeee317c7a486846cc8405d0bd68d8

Btw. the imx-drm.h is missing in your patch.

- Lars

> Thanks
>  Sascha
> 
> ----------------------------------------------------------------
> Sascha Hauer (2):
>       DRM: add Freescale i.MX LCDC driver
>       pcm038 lcdc support
> 
>  arch/arm/boot/dts/imx27-phytec-phycore.dts |   39 ++
>  arch/arm/boot/dts/imx27.dtsi               |    7 +
>  arch/arm/mach-imx/clock-imx27.c            |    1 +
>  drivers/gpu/drm/Kconfig                    |    2 +
>  drivers/gpu/drm/Makefile                   |    1 +
>  drivers/gpu/drm/imx/Kconfig                |   18 +
>  drivers/gpu/drm/imx/Makefile               |    8 +
>  drivers/gpu/drm/imx/imx-drm-core.c         |  745 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/imx/imx-fb.c               |  179 +++++++
>  drivers/gpu/drm/imx/imx-fbdev.c            |  275 ++++++++++
>  drivers/gpu/drm/imx/imx-gem.c              |  343 +++++++++++++
>  drivers/gpu/drm/imx/imx-lcdc-crtc.c        |  517 +++++++++++++++++++
>  drivers/gpu/drm/imx/imx-parallel-display.c |  228 +++++++++
>  13 files changed, 2363 insertions(+)
>  create mode 100644 drivers/gpu/drm/imx/Kconfig
>  create mode 100644 drivers/gpu/drm/imx/Makefile
>  create mode 100644 drivers/gpu/drm/imx/imx-drm-core.c
>  create mode 100644 drivers/gpu/drm/imx/imx-fb.c
>  create mode 100644 drivers/gpu/drm/imx/imx-fbdev.c
>  create mode 100644 drivers/gpu/drm/imx/imx-gem.c
>  create mode 100644 drivers/gpu/drm/imx/imx-lcdc-crtc.c
>  create mode 100644 drivers/gpu/drm/imx/imx-parallel-display.c
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 1/2] DRM: add Freescale i.MX LCDC driver
  2012-05-18 12:27 ` [PATCH 1/2] DRM: add Freescale i.MX LCDC driver Sascha Hauer
@ 2012-05-22 21:28   ` Rob Clark
  2012-05-23  7:47     ` Sascha Hauer
  0 siblings, 1 reply; 35+ messages in thread
From: Rob Clark @ 2012-05-22 21:28 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: linux-arm-kernel, dri-devel

just a few comments from a cursory review..  I need a bit more time
for a more in-depth review but that won't be tonight so I thought I'd
send what I have so far..


On Fri, May 18, 2012 at 6:27 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  drivers/gpu/drm/Kconfig                    |    2 +
>  drivers/gpu/drm/Makefile                   |    1 +
>  drivers/gpu/drm/imx/Kconfig                |   18 +
>  drivers/gpu/drm/imx/Makefile               |    8 +
>  drivers/gpu/drm/imx/imx-drm-core.c         |  745 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/imx/imx-fb.c               |  179 +++++++
>  drivers/gpu/drm/imx/imx-fbdev.c            |  275 ++++++++++
>  drivers/gpu/drm/imx/imx-gem.c              |  343 +++++++++++++
>  drivers/gpu/drm/imx/imx-lcdc-crtc.c        |  517 +++++++++++++++++++
>  drivers/gpu/drm/imx/imx-parallel-display.c |  228 +++++++++
>  10 files changed, 2316 insertions(+)
>  create mode 100644 drivers/gpu/drm/imx/Kconfig
>  create mode 100644 drivers/gpu/drm/imx/Makefile
>  create mode 100644 drivers/gpu/drm/imx/imx-drm-core.c
>  create mode 100644 drivers/gpu/drm/imx/imx-fb.c
>  create mode 100644 drivers/gpu/drm/imx/imx-fbdev.c
>  create mode 100644 drivers/gpu/drm/imx/imx-gem.c
>  create mode 100644 drivers/gpu/drm/imx/imx-lcdc-crtc.c
>  create mode 100644 drivers/gpu/drm/imx/imx-parallel-display.c
>
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index e354bc0..759502c 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -186,3 +186,5 @@ source "drivers/gpu/drm/vmwgfx/Kconfig"
>  source "drivers/gpu/drm/gma500/Kconfig"
>
>  source "drivers/gpu/drm/udl/Kconfig"
> +
> +source "drivers/gpu/drm/imx/Kconfig"
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index c20da5b..6569d8d 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -42,4 +42,5 @@ obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
>  obj-$(CONFIG_DRM_EXYNOS) +=exynos/
>  obj-$(CONFIG_DRM_GMA500) += gma500/
>  obj-$(CONFIG_DRM_UDL) += udl/
> +obj-$(CONFIG_DRM_IMX) += imx/
>  obj-y                  += i2c/
> diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig
> new file mode 100644
> index 0000000..5fc3a44
> --- /dev/null
> +++ b/drivers/gpu/drm/imx/Kconfig
> @@ -0,0 +1,18 @@
> +config DRM_IMX
> +       tristate "DRM Support for Freescale i.MX"
> +       select DRM_KMS_HELPER
> +       depends on DRM && ARCH_MXC
> +
> +config DRM_IMX_FB_HELPER
> +       tristate "provide legacy framebuffer /dev/fb0"
> +       depends on DRM_IMX
> +
> +config DRM_IMX_LCDC
> +       tristate "DRM Support for Freescale i.MX1 and i.MX2"
> +       depends on DRM_IMX
> +       help
> +         Choose this if you have a i.MX1, i.MX21, i.MX25 or i.MX27 processor.

do you have something like cpu_is_imx2() type macros?  It would be
preferable not to have a compile time config option for building for
certain hw versions.  Ie. on OMAP we could do something like 'if
(cpu_is_omap3xxx()) { ... }' if there was something that needed to be
done different on omap3 family of devices.  This way you could choose
to build a kernel supporting either a single omap variants, or all
omap variants.

> +
> +config DRM_IMX_PARALLEL_DISPLAY
> +       tristate "Support for parallel displays"
> +       depends on DRM_IMX
> diff --git a/drivers/gpu/drm/imx/Makefile b/drivers/gpu/drm/imx/Makefile
> new file mode 100644
> index 0000000..0f7c038
> --- /dev/null
> +++ b/drivers/gpu/drm/imx/Makefile
> @@ -0,0 +1,8 @@
> +
> +imxdrm-objs := imx-drm-core.o imx-fb.o imx-gem.o
> +
> +obj-$(CONFIG_DRM_IMX) += imxdrm.o
> +
> +obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += imx-parallel-display.o
> +obj-$(CONFIG_DRM_IMX_LCDC) += imx-lcdc-crtc.o
> +obj-$(CONFIG_DRM_IMX_FB_HELPER) += imx-fbdev.o
> diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
> new file mode 100644
> index 0000000..29f5f10
> --- /dev/null
> +++ b/drivers/gpu/drm/imx/imx-drm-core.c
> @@ -0,0 +1,745 @@
> +/*
> + * simple drm driver
> + *
> + * Copyright (C) 2011 Sascha Hauer, Pengutronix
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <linux/fb.h>
> +#include <asm/fb.h>
> +#include <linux/module.h>
> +
> +#include "imx-drm.h"
> +
> +#define MAX_CRTC       4
> +
> +struct imx_drm_device {
> +       struct drm_device                       *drm;
> +       struct device                           *dev;
> +       struct list_head                        crtc_list;
> +       struct list_head                        encoder_list;
> +       struct list_head                        connector_list;
> +       struct mutex                            mutex;
> +       int                                     references;
> +};
> +
> +struct imx_drm_crtc {
> +       struct drm_crtc                         *crtc;
> +       struct list_head                        list;
> +       struct imx_drm_device                   *imxdrm;
> +       int                                     pipe;
> +       struct drm_crtc_helper_funcs            crtc_helper_funcs;
> +       struct drm_crtc_funcs                   crtc_funcs;
> +       struct imx_drm_crtc_helper_funcs        imx_drm_helper_funcs;
> +       struct module                           *owner;
> +};
> +
> +struct imx_drm_encoder {
> +       struct drm_encoder                      *encoder;
> +       struct list_head                        list;
> +       struct module                           *owner;
> +};
> +
> +struct imx_drm_connector {
> +       struct drm_connector                    *connector;
> +       struct list_head                        list;
> +       struct module                           *owner;
> +};
> +
> +static int imx_drm_driver_firstopen(struct drm_device *drm)
> +{
> +       if (!imx_drm_device_get())
> +               return -EINVAL;
> +
> +       return 0;
> +}
> +
> +static void imx_drm_driver_lastclose(struct drm_device *drm)
> +{
> +       imx_drm_device_put();
> +}
> +
> +static int imx_drm_driver_unload(struct drm_device *drm)
> +{
> +       struct imx_drm_device *imxdrm = drm->dev_private;
> +
> +       drm_mode_config_cleanup(imxdrm->drm);
> +       drm_kms_helper_poll_fini(imxdrm->drm);
> +
> +       return 0;
> +}
> +
> +/*
> + * We don't care at all for crtc numbers, but the core expects the
> + * crtcs to be numbered
> + */
> +static struct imx_drm_crtc *imx_drm_crtc_by_num(struct imx_drm_device *imxdrm,
> +               int num)
> +{
> +       struct imx_drm_crtc *imx_drm_crtc;
> +
> +       list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list)
> +               if (imx_drm_crtc->pipe == num)
> +                       return imx_drm_crtc;
> +       return NULL;
> +}
> +
> +int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
> +{
> +       return drm_vblank_get(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe);
> +}
> +EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get);
> +
> +void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc)
> +{
> +       drm_vblank_put(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe);
> +}
> +EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put);
> +
> +void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc)
> +{
> +       drm_handle_vblank(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe);
> +}
> +EXPORT_SYMBOL_GPL(imx_drm_handle_vblank);
> +
> +static int imx_drm_enable_vblank(struct drm_device *drm, int crtc)
> +{
> +       struct imx_drm_device *imxdrm = drm->dev_private;
> +       struct imx_drm_crtc *imx_drm_crtc;
> +       int ret;
> +
> +       imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc);
> +       if (!imx_drm_crtc)
> +               return -EINVAL;
> +
> +       if (!imx_drm_crtc->imx_drm_helper_funcs.enable_vblank)
> +               return -ENOSYS;
> +
> +       ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank(imx_drm_crtc->crtc);
> +       return ret;
> +}
> +
> +static void imx_drm_disable_vblank(struct drm_device *drm, int crtc)
> +{
> +       struct imx_drm_device *imxdrm = drm->dev_private;
> +       struct imx_drm_crtc *imx_drm_crtc;
> +
> +       imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc);
> +       if (!imx_drm_crtc)
> +               return;
> +
> +       if (!imx_drm_crtc->imx_drm_helper_funcs.disable_vblank)
> +               return;
> +
> +       imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc);
> +}
> +
> +static struct vm_operations_struct imx_drm_gem_vm_ops = {
> +       .fault = imx_drm_gem_fault,
> +       .open = drm_gem_vm_open,
> +       .close = drm_gem_vm_close,
> +};
> +
> +static const struct file_operations imx_drm_driver_fops = {
> +       .owner = THIS_MODULE,
> +       .open = drm_open,
> +       .release = drm_release,
> +       .unlocked_ioctl = drm_ioctl,
> +       .mmap = imx_drm_gem_mmap,
> +       .poll = drm_poll,
> +       .fasync = drm_fasync,
> +       .read = drm_read,
> +       .llseek = noop_llseek,
> +};
> +
> +static struct imx_drm_device *imx_drm_device;
> +
> +static struct imx_drm_device *__imx_drm_device(void)
> +{
> +       return imx_drm_device;
> +}
> +
> +struct drm_device *imx_drm_device_get(void)
> +{
> +       struct imx_drm_device *imxdrm = __imx_drm_device();
> +       struct imx_drm_encoder *enc;
> +       struct imx_drm_connector *con;
> +       struct imx_drm_crtc *crtc;
> +
> +       mutex_lock(&imxdrm->mutex);
> +
> +       list_for_each_entry(enc, &imxdrm->encoder_list, list) {
> +               if (!try_module_get(enc->owner)) {
> +                       dev_err(imxdrm->dev, "could not get module %s\n",
> +                                       module_name(enc->owner));
> +                       goto unwind_enc;
> +               }
> +       }
> +
> +       list_for_each_entry(con, &imxdrm->connector_list, list) {
> +               if (!try_module_get(con->owner)) {
> +                       dev_err(imxdrm->dev, "could not get module %s\n",
> +                                       module_name(con->owner));
> +                       goto unwind_con;
> +               }
> +       }
> +
> +       list_for_each_entry(crtc, &imxdrm->crtc_list, list) {
> +               if (!try_module_get(crtc->owner)) {
> +                       dev_err(imxdrm->dev, "could not get module %s\n",
> +                                       module_name(crtc->owner));
> +                       goto unwind_crtc;
> +               }
> +       }
> +
> +       imxdrm->references++;
> +
> +       mutex_unlock(&imxdrm->mutex);
> +
> +       return imx_drm_device->drm;
> +
> +unwind_crtc:
> +       list_for_each_entry_continue_reverse(crtc, &imxdrm->crtc_list, list)
> +               module_put(crtc->owner);
> +unwind_con:
> +       list_for_each_entry_continue_reverse(con, &imxdrm->connector_list, list)
> +               module_put(con->owner);
> +unwind_enc:
> +       list_for_each_entry_continue_reverse(enc, &imxdrm->encoder_list, list)
> +               module_put(enc->owner);
> +
> +       mutex_unlock(&imxdrm->mutex);
> +
> +       return NULL;
> +
> +}
> +EXPORT_SYMBOL_GPL(imx_drm_device_get);
> +
> +void imx_drm_device_put(void)
> +{
> +       struct imx_drm_device *imxdrm = __imx_drm_device();
> +       struct imx_drm_encoder *enc;
> +       struct imx_drm_connector *con;
> +       struct imx_drm_crtc *crtc;
> +
> +       mutex_lock(&imxdrm->mutex);
> +
> +       list_for_each_entry(crtc, &imxdrm->crtc_list, list)
> +               module_put(crtc->owner);
> +
> +       list_for_each_entry(con, &imxdrm->connector_list, list)
> +               module_put(con->owner);
> +
> +       list_for_each_entry(enc, &imxdrm->encoder_list, list)
> +               module_put(enc->owner);
> +
> +       imxdrm->references--;
> +
> +       mutex_unlock(&imxdrm->mutex);
> +}
> +EXPORT_SYMBOL_GPL(imx_drm_device_put);
> +
> +static int drm_mode_group_reinit(struct drm_device *dev)
> +{
> +       struct drm_mode_group *group = &dev->primary->mode_group;
> +       uint32_t *id_list = group->id_list;
> +       int ret;
> +
> +       ret = drm_mode_group_init_legacy_group(dev, group);
> +       if (ret < 0)
> +               return ret;
> +
> +       kfree(id_list);
> +       return 0;
> +}
> +
> +/*
> + * register an encoder to the drm core
> + */
> +static int imx_drm_encoder_register(struct imx_drm_encoder *imx_drm_encoder)
> +{
> +       struct imx_drm_device *imxdrm = __imx_drm_device();
> +
> +       drm_encoder_init(imxdrm->drm, imx_drm_encoder->encoder,
> +                       imx_drm_encoder->encoder->funcs,
> +                       DRM_MODE_ENCODER_TMDS);
> +
> +       drm_mode_group_reinit(imxdrm->drm);
> +
> +       return 0;
> +}
> +
> +/*
> + * unregister an encoder from the drm core
> + */
> +static void imx_drm_encoder_unregister(struct imx_drm_encoder *imx_drm_encoder)
> +{
> +       struct imx_drm_device *imxdrm = __imx_drm_device();
> +
> +       drm_encoder_cleanup(imx_drm_encoder->encoder);
> +
> +       drm_mode_group_reinit(imxdrm->drm);
> +}
> +
> +/*
> + * register a connector to the drm core
> + */
> +static int imx_drm_connector_register(struct imx_drm_connector *imx_drm_connector)
> +{
> +       struct imx_drm_device *imxdrm = __imx_drm_device();
> +       int ret;
> +
> +       drm_connector_init(imxdrm->drm, imx_drm_connector->connector,
> +                       imx_drm_connector->connector->funcs,
> +                       DRM_MODE_CONNECTOR_VGA);
> +       drm_mode_group_reinit(imxdrm->drm);
> +       ret = drm_sysfs_connector_add(imx_drm_connector->connector);
> +       if (ret)
> +               goto err;
> +
> +       return 0;
> +err:
> +
> +       return ret;
> +}
> +
> +/*
> + * unregister a connector from the drm core
> + */
> +static void imx_drm_connector_unregister(struct imx_drm_connector *imx_drm_connector)
> +{
> +       struct imx_drm_device *imxdrm = __imx_drm_device();
> +
> +       drm_sysfs_connector_remove(imx_drm_connector->connector);
> +       drm_connector_cleanup(imx_drm_connector->connector);
> +
> +       drm_mode_group_reinit(imxdrm->drm);
> +}
> +
> +/*
> + * register a crtc to the drm core
> + */
> +static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc)
> +{
> +       struct imx_drm_device *imxdrm = __imx_drm_device();
> +       int ret;
> +
> +       drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc, &imx_drm_crtc->crtc_funcs);
> +       ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256);
> +       if (ret)
> +               return ret;
> +
> +       drm_crtc_helper_add(imx_drm_crtc->crtc, &imx_drm_crtc->crtc_helper_funcs);
> +
> +       return 0;
> +}
> +
> +/*
> + * Called by the CRTC driver when all CRTCs are registered. This
> + * puts all the pieces together and initializes the driver.
> + * Once this is called no more CRTCs can be registered since
> + * the drm core has hardcoded the number of crtcs in several
> + * places.
> + */
> +static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
> +{
> +       struct imx_drm_device *imxdrm = __imx_drm_device();
> +       int ret;
> +
> +       imxdrm->drm = drm;
> +
> +       drm->dev_private = imxdrm;
> +
> +       /*
> +        * 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 and
> +        *      drivers can well take care of their interrupts
> +        */
> +       drm->irq_enabled = 1;
> +
> +       drm_mode_config_init(drm);
> +       imx_drm_mode_config_init(drm);
> +
> +       mutex_lock(&imxdrm->mutex);
> +
> +       drm_kms_helper_poll_init(imxdrm->drm);
> +
> +       /* setup the grouping for the legacy output */
> +       ret = drm_mode_group_init_legacy_group(imxdrm->drm,
> +                       &imxdrm->drm->primary->mode_group);
> +       if (ret)
> +               goto err_init;
> +
> +       ret = drm_vblank_init(imxdrm->drm, MAX_CRTC);
> +       if (ret)
> +               goto err_init;
> +
> +       /*
> +        * 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)
> +        */
> +       imxdrm->drm->vblank_disable_allowed = 1;
> +
> +       ret = 0;
> +
> +err_init:
> +       mutex_unlock(&imxdrm->mutex);
> +
> +       return ret;
> +}
> +
> +/*
> + * imx_drm_add_crtc - add a new crtc
> + *
> + * The return value if !NULL is a cookie for the caller to pass to
> + * imx_drm_remove_crtc later.
> + */
> +int imx_drm_add_crtc(struct drm_crtc *crtc,
> +               struct imx_drm_crtc **new_crtc,
> +               const struct drm_crtc_funcs *crtc_funcs,
> +               const struct drm_crtc_helper_funcs *crtc_helper_funcs,
> +               const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
> +               struct module *owner)
> +{
> +       struct imx_drm_device *imxdrm = __imx_drm_device();
> +       struct imx_drm_crtc *imx_drm_crtc;
> +       int ret;
> +
> +       mutex_lock(&imxdrm->mutex);
> +
> +       if (imxdrm->references) {
> +               ret = -EBUSY;
> +               goto err_busy;
> +       }
> +
> +       imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL);
> +       if (!imx_drm_crtc) {
> +               ret = -ENOMEM;
> +               goto err_alloc;
> +       }
> +
> +       imx_drm_crtc->crtc_funcs = *crtc_funcs;
> +       imx_drm_crtc->crtc_helper_funcs = *crtc_helper_funcs;
> +       imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs;
> +
> +       WARN_ON(crtc_funcs->set_config);
> +       WARN_ON(crtc_funcs->destroy);
> +
> +       imx_drm_crtc->crtc_funcs.set_config = drm_crtc_helper_set_config;
> +       imx_drm_crtc->crtc_funcs.destroy = drm_crtc_cleanup;
> +
> +       imx_drm_crtc->crtc = crtc;
> +       imx_drm_crtc->imxdrm = imxdrm;
> +
> +       imx_drm_crtc->owner = owner;
> +
> +       list_add_tail(&imx_drm_crtc->list, &imxdrm->crtc_list);
> +
> +       *new_crtc = imx_drm_crtc;
> +
> +       ret = imx_drm_crtc_register(imx_drm_crtc);
> +       if (ret)
> +               goto err_register;
> +
> +       mutex_unlock(&imxdrm->mutex);
> +
> +       return 0;
> +
> +err_register:
> +       kfree(imx_drm_crtc);
> +err_alloc:
> +err_busy:
> +       mutex_unlock(&imxdrm->mutex);
> +       return ret;
> +}
> +EXPORT_SYMBOL_GPL(imx_drm_add_crtc);
> +
> +/*
> + * imx_drm_remove_crtc - remove a crtc
> + */
> +int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc)
> +{
> +       struct imx_drm_device *imxdrm = imx_drm_crtc->imxdrm;
> +
> +       mutex_lock(&imxdrm->mutex);
> +
> +       drm_crtc_cleanup(imx_drm_crtc->crtc);
> +
> +       list_del(&imx_drm_crtc->list);
> +
> +       mutex_unlock(&imxdrm->mutex);
> +
> +       kfree(imx_drm_crtc);
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(imx_drm_remove_crtc);
> +
> +/*
> + * imx_drm_add_encoder - add a new encoder
> + */
> +int imx_drm_add_encoder(struct drm_encoder *encoder,
> +               struct imx_drm_encoder **newenc, struct module *owner)
> +{
> +       struct imx_drm_device *imxdrm = __imx_drm_device();
> +       struct imx_drm_encoder *imx_drm_encoder;
> +       int ret;
> +
> +       mutex_lock(&imxdrm->mutex);
> +
> +       if (imxdrm->references) {
> +               ret = -EBUSY;
> +               goto err_busy;
> +       }
> +
> +       imx_drm_encoder = kzalloc(sizeof(struct imx_drm_encoder), GFP_KERNEL);
> +       if (!imx_drm_encoder) {
> +               ret = -ENOMEM;
> +               goto err_alloc;
> +       }
> +
> +       imx_drm_encoder->encoder = encoder;
> +       imx_drm_encoder->owner = owner;
> +
> +       ret = imx_drm_encoder_register(imx_drm_encoder);
> +       if (ret) {
> +               kfree(imx_drm_encoder);
> +               ret = -ENOMEM;
> +               goto err_register;
> +       }
> +
> +       list_add_tail(&imx_drm_encoder->list, &imxdrm->encoder_list);
> +
> +       *newenc = imx_drm_encoder;
> +
> +       mutex_unlock(&imxdrm->mutex);
> +
> +       return 0;
> +
> +err_register:
> +       kfree(imx_drm_encoder);
> +err_alloc:
> +err_busy:
> +       mutex_unlock(&imxdrm->mutex);
> +
> +       return ret;
> +}
> +EXPORT_SYMBOL_GPL(imx_drm_add_encoder);
> +
> +/*
> + * imx_drm_remove_encoder - remove an encoder
> + */
> +int imx_drm_remove_encoder(struct imx_drm_encoder *imx_drm_encoder)
> +{
> +       struct imx_drm_device *imxdrm = __imx_drm_device();
> +
> +       mutex_lock(&imxdrm->mutex);
> +
> +       imx_drm_encoder_unregister(imx_drm_encoder);
> +
> +       list_del(&imx_drm_encoder->list);
> +
> +       mutex_unlock(&imxdrm->mutex);
> +
> +       kfree(imx_drm_encoder);
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(imx_drm_remove_encoder);
> +
> +/*
> + * imx_drm_add_connector - add a connector
> + */
> +int imx_drm_add_connector(struct drm_connector *connector,
> +               struct imx_drm_connector **new_con,
> +               struct module *owner)
> +{
> +       struct imx_drm_device *imxdrm = __imx_drm_device();
> +       struct imx_drm_connector *imx_drm_connector;
> +       int ret;
> +
> +       mutex_lock(&imxdrm->mutex);
> +
> +       if (imxdrm->references) {
> +               ret = -EBUSY;
> +               goto err_busy;
> +       }
> +
> +       imx_drm_connector = kzalloc(sizeof(struct imx_drm_connector), GFP_KERNEL);
> +       if (!imx_drm_connector) {
> +               ret = -ENOMEM;
> +               goto err_alloc;
> +       }
> +
> +       imx_drm_connector->connector = connector;
> +       imx_drm_connector->owner = owner;
> +
> +       ret = imx_drm_connector_register(imx_drm_connector);
> +       if (ret)
> +               goto err_register;
> +
> +       list_add_tail(&imx_drm_connector->list, &imxdrm->connector_list);
> +
> +       *new_con = imx_drm_connector;
> +
> +       mutex_unlock(&imxdrm->mutex);
> +
> +       return 0;
> +
> +err_register:
> +       kfree(imx_drm_connector);
> +err_alloc:
> +err_busy:
> +       mutex_unlock(&imxdrm->mutex);
> +
> +       return ret;
> +}
> +EXPORT_SYMBOL_GPL(imx_drm_add_connector);
> +
> +/*
> + * imx_drm_remove_connector - remove a connector
> + */
> +int imx_drm_remove_connector(struct imx_drm_connector *imx_drm_connector)
> +{
> +       struct imx_drm_device *imxdrm = __imx_drm_device();
> +
> +       mutex_lock(&imxdrm->mutex);
> +
> +       imx_drm_connector_unregister(imx_drm_connector);
> +
> +       list_del(&imx_drm_connector->list);
> +
> +       mutex_unlock(&imxdrm->mutex);
> +
> +       kfree(imx_drm_connector);
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(imx_drm_remove_connector);
> +
> +static struct drm_ioctl_desc imx_drm_ioctls[] = {
> +       /* none so far */
> +};
> +
> +static struct drm_driver imx_drm_driver = {
> +       .driver_features        = DRIVER_MODESET | DRIVER_GEM,
> +       .load                   = imx_drm_driver_load,
> +       .unload                 = imx_drm_driver_unload,
> +       .firstopen              = imx_drm_driver_firstopen,
> +       .lastclose              = imx_drm_driver_lastclose,
> +       .gem_free_object        = imx_drm_gem_free_object,
> +       .gem_vm_ops             = &imx_drm_gem_vm_ops,
> +       .dumb_create            = imx_drm_gem_dumb_create,
> +       .dumb_map_offset        = imx_drm_gem_dumb_map_offset,
> +       .dumb_destroy           = imx_drm_gem_dumb_destroy,
> +
> +       .get_vblank_counter     = drm_vblank_count,
> +       .enable_vblank          = imx_drm_enable_vblank,
> +       .disable_vblank         = imx_drm_disable_vblank,
> +       .reclaim_buffers        = drm_core_reclaim_buffers,
> +       .ioctls                 = imx_drm_ioctls,
> +       .num_ioctls             = ARRAY_SIZE(imx_drm_ioctls),
> +       .fops                   = &imx_drm_driver_fops,
> +       .name                   = "imx-drm",
> +       .desc                   = "i.MX DRM graphics",
> +       .date                   = "20120507",
> +       .major                  = 1,
> +       .minor                  = 0,
> +       .patchlevel             = 0,
> +};
> +
> +static int imx_drm_platform_probe(struct platform_device *pdev)
> +{
> +       imx_drm_device->dev = &pdev->dev;
> +
> +       return drm_platform_init(&imx_drm_driver, pdev);
> +}
> +
> +static int imx_drm_platform_remove(struct platform_device *pdev)
> +{
> +       drm_platform_exit(&imx_drm_driver, pdev);
> +
> +       return 0;
> +}
> +
> +static struct platform_driver imx_drm_pdrv = {
> +       .probe          = imx_drm_platform_probe,
> +       .remove         = __devexit_p(imx_drm_platform_remove),
> +       .driver         = {
> +               .owner  = THIS_MODULE,
> +               .name   = "imx-drm",
> +       },
> +};
> +
> +static struct platform_device *imx_drm_pdev;
> +
> +static int __init imx_drm_init(void)
> +{
> +       int ret;
> +
> +       imx_drm_device = kzalloc(sizeof(*imx_drm_device), GFP_KERNEL);
> +       if (!imx_drm_device)
> +               return -ENOMEM;
> +
> +       mutex_init(&imx_drm_device->mutex);
> +       INIT_LIST_HEAD(&imx_drm_device->crtc_list);
> +       INIT_LIST_HEAD(&imx_drm_device->connector_list);
> +       INIT_LIST_HEAD(&imx_drm_device->encoder_list);
> +
> +       imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0);
> +       if (!imx_drm_pdev) {
> +               ret = -EINVAL;
> +               goto err_pdev;
> +       }
> +
> +       imx_drm_pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32),
> +
> +       ret = platform_driver_register(&imx_drm_pdrv);
> +       if (ret)
> +               goto err_pdrv;
> +
> +       return 0;
> +
> +err_pdev:
> +       kfree(imx_drm_device);
> +err_pdrv:
> +       platform_device_unregister(imx_drm_pdev);
> +
> +       return ret;
> +}
> +
> +static void __exit imx_drm_exit(void)
> +{
> +       DRM_DEBUG_DRIVER("%s\n", __FILE__);
> +
> +       platform_device_unregister(imx_drm_pdev);
> +       platform_driver_unregister(&imx_drm_pdrv);
> +
> +       kfree(imx_drm_device);
> +}
> +
> +module_init(imx_drm_init);
> +module_exit(imx_drm_exit);
> +
> +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
> +MODULE_DESCRIPTION("i.MX drm driver core");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/imx/imx-fb.c b/drivers/gpu/drm/imx/imx-fb.c
> new file mode 100644
> index 0000000..5a08c86
> --- /dev/null
> +++ b/drivers/gpu/drm/imx/imx-fb.c
> @@ -0,0 +1,179 @@
> +/*
> + * i.MX drm driver
> + *
> + * Copyright (C) 2012 Sascha Hauer, Pengutronix
> + *
> + * Based on Samsung Exynos code
> + *
> + * Copyright (c) 2011 Samsung Electronics Co., Ltd.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +#include <linux/module.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +
> +#include "imx-drm.h"
> +
> +#define to_imx_drm_fb(x)       container_of(x, struct imx_drm_fb, fb)
> +
> +/*
> + * imx specific framebuffer structure.
> + *
> + * @fb: drm framebuffer obejct.
> + * @imx_drm_gem_obj: drm ec specific gem object containing a gem object.
> + * @entry: pointer to ec drm buffer entry object.
> + *     - containing only the information to physically continuous memory
> + *     region allocated at default framebuffer creation.
> + */
> +struct imx_drm_fb {
> +       struct drm_framebuffer          fb;
> +       struct imx_drm_gem_obj  *imx_drm_gem_obj;
> +       struct imx_drm_buf_entry        *entry;
> +};
> +
> +static void imx_drm_fb_destroy(struct drm_framebuffer *fb)
> +{
> +       struct imx_drm_fb *imx_drm_fb = to_imx_drm_fb(fb);
> +
> +       drm_framebuffer_cleanup(fb);
> +
> +       /*
> +        * default framebuffer has no gem object so
> +        * a buffer of the default framebuffer should be released at here.
> +        */
> +       if (!imx_drm_fb->imx_drm_gem_obj && imx_drm_fb->entry)
> +               imx_drm_buf_destroy(fb->dev, imx_drm_fb->entry);
> +
> +       kfree(imx_drm_fb);
> +}
> +
> +static int imx_drm_fb_create_handle(struct drm_framebuffer *fb,
> +               struct drm_file *file_priv, unsigned int *handle)
> +{
> +       struct imx_drm_fb *imx_drm_fb = to_imx_drm_fb(fb);
> +
> +       return drm_gem_handle_create(file_priv,
> +                       &imx_drm_fb->imx_drm_gem_obj->base, handle);
> +}
> +
> +static struct drm_framebuffer_funcs imx_drm_fb_funcs = {
> +       .destroy        = imx_drm_fb_destroy,
> +       .create_handle  = imx_drm_fb_create_handle,
> +};
> +
> +static struct drm_framebuffer *imx_drm_fb_create(struct drm_device *dev,
> +               struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd)
> +{
> +       struct imx_drm_fb *imx_drm_fb;
> +       struct drm_framebuffer *fb;
> +       struct drm_gem_object *obj;
> +       unsigned int size;
> +       int ret;
> +       u32 bpp, depth;
> +
> +       drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
> +
> +       mode_cmd->pitches[0] = max(mode_cmd->pitches[0],
> +                       mode_cmd->width * (bpp >> 3));
> +
> +       dev_dbg(dev->dev, "drm fb create(%dx%d)\n",
> +                       mode_cmd->width, mode_cmd->height);
> +
> +       imx_drm_fb = kzalloc(sizeof(*imx_drm_fb), GFP_KERNEL);
> +       if (!imx_drm_fb) {
> +               dev_err(dev->dev, "failed to allocate drm framebuffer.\n");
> +               return ERR_PTR(-ENOMEM);
> +       }
> +
> +       fb = &imx_drm_fb->fb;
> +       ret = drm_framebuffer_init(dev, fb, &imx_drm_fb_funcs);
> +       if (ret) {
> +               dev_err(dev->dev, "failed to initialize framebuffer.\n");
> +               goto err_init;
> +       }
> +
> +       dev_dbg(dev->dev, "create: fb id: %d\n", fb->base.id);
> +
> +       size = mode_cmd->pitches[0] * mode_cmd->height;
> +
> +       /*
> +        * without file_priv we are called from imx_drm_fbdev_create in which
> +        * case we only create a framebuffer without a handle.
> +        */
> +       if (!file_priv) {
> +               struct imx_drm_buf_entry *entry;
> +
> +               entry = imx_drm_buf_create(dev, size);
> +               if (IS_ERR(entry)) {
> +                       ret = PTR_ERR(entry);
> +                       goto err_buffer;
> +               }
> +
> +               imx_drm_fb->entry = entry;
> +       } else {
> +               obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
> +               if (!obj) {
> +                       ret = -EINVAL;
> +                       goto err_buffer;
> +               }
> +
> +               imx_drm_fb->imx_drm_gem_obj = to_imx_drm_gem_obj(obj);
> +
> +               drm_gem_object_unreference_unlocked(obj);


the fb probably should hold the reference to the GEM obj until it is
deleted..  so you don't end up freeing the buffer you are scanning out
until you are done scanning it out.  Possibly this gets a bit more
straightforward if you don't have to special case the default/fbcon
framebuffer?

IIRC, Laurent had sent a patch recently to fix the same issue in the
exynos driver.

> +               imx_drm_fb->entry = imx_drm_fb->imx_drm_gem_obj->entry;
> +       }
> +
> +       drm_helper_mode_fill_fb_struct(fb, mode_cmd);
> +
> +       return fb;
> +
> +err_buffer:
> +       drm_framebuffer_cleanup(fb);
> +
> +err_init:
> +       kfree(imx_drm_fb);
> +
> +       return ERR_PTR(ret);
> +}
> +
> +struct imx_drm_buf_entry *imx_drm_fb_get_buf(struct drm_framebuffer *fb)
> +{
> +       struct imx_drm_fb *imx_drm_fb = to_imx_drm_fb(fb);
> +       struct imx_drm_buf_entry *entry;
> +
> +       entry = imx_drm_fb->entry;
> +
> +       return entry;
> +}
> +EXPORT_SYMBOL_GPL(imx_drm_fb_get_buf);
> +
> +static struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
> +       .fb_create = imx_drm_fb_create,
> +};
> +
> +void imx_drm_mode_config_init(struct drm_device *dev)
> +{
> +       dev->mode_config.min_width = 64;
> +       dev->mode_config.min_height = 64;
> +
> +       /*
> +        * 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 = &imx_drm_mode_config_funcs;
> +}
> diff --git a/drivers/gpu/drm/imx/imx-fbdev.c b/drivers/gpu/drm/imx/imx-fbdev.c
> new file mode 100644
> index 0000000..f038797
> --- /dev/null
> +++ b/drivers/gpu/drm/imx/imx-fbdev.c
> @@ -0,0 +1,275 @@
> +/*
> + * i.MX drm driver
> + *
> + * Copyright (C) 2012 Sascha Hauer, Pengutronix
> + *
> + * Based on Samsung Exynos code
> + *
> + * Copyright (c) 2011 Samsung Electronics Co., Ltd.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +#include <linux/module.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +
> +#include "imx-drm.h"
> +
> +#define MAX_CONNECTOR          4
> +#define PREFERRED_BPP          16
> +
> +static struct fb_ops imx_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 imx_drm_fbdev_update(struct drm_fb_helper *helper,
> +                                    struct drm_framebuffer *fb,
> +                                    unsigned int fb_width,
> +                                    unsigned int fb_height)
> +{
> +       struct fb_info *fbi = helper->fbdev;
> +       struct drm_device *drm = helper->dev;
> +       struct imx_drm_buf_entry *entry;
> +       unsigned int size = fb_width * fb_height * (fb->bits_per_pixel >> 3);
> +       unsigned long offset;
> +
> +       drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
> +       drm_fb_helper_fill_var(fbi, helper, fb_width, fb_height);
> +
> +       entry = imx_drm_fb_get_buf(fb);
> +       if (!entry) {
> +               dev_dbg(drm->dev, "entry is null.\n");
> +               return -EFAULT;
> +       }
> +
> +       offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
> +       offset += fbi->var.yoffset * fb->pitches[0];
> +
> +       drm->mode_config.fb_base = entry->paddr;
> +       fbi->screen_base = entry->vaddr + offset;
> +       fbi->fix.smem_start = entry->paddr + offset;
> +       fbi->screen_size = size;
> +       fbi->fix.smem_len = size;
> +       fbi->flags |= FBINFO_CAN_FORCE_OUTPUT;
> +
> +       return 0;
> +}
> +
> +static int imx_drm_fbdev_create(struct drm_fb_helper *helper,
> +                                   struct drm_fb_helper_surface_size *sizes)
> +{
> +       struct drm_device *drm = helper->dev;
> +       struct fb_info *fbi;
> +       struct drm_framebuffer *fb;
> +       struct drm_mode_fb_cmd2 mode_cmd = { 0 };
> +       struct platform_device *pdev = drm->platformdev;
> +       int ret;
> +
> +       dev_dbg(drm->dev, "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.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
> +                       sizes->surface_depth);
> +
> +       mutex_lock(&drm->struct_mutex);
> +
> +       fbi = framebuffer_alloc(0, &pdev->dev);
> +       if (!fbi) {
> +               ret = -ENOMEM;
> +               goto err_fb_alloc;
> +       }
> +
> +       fb = drm->mode_config.funcs->fb_create(drm, NULL, &mode_cmd);
> +       if (IS_ERR(fb)) {
> +               dev_err(drm->dev, "failed to create drm framebuffer.\n");
> +               ret = PTR_ERR(fb);
> +               goto err_fb_create;
> +       }
> +
> +       helper->fb = fb;
> +       helper->fbdev = fbi;
> +
> +       fbi->par = helper;
> +       fbi->flags = FBINFO_FLAG_DEFAULT;
> +       fbi->fbops = &imx_drm_fb_ops;
> +
> +       ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
> +       if (ret)
> +               goto err_alloc_cmap;
> +
> +       ret = imx_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
> +                       sizes->fb_height);
> +       if (ret)
> +               goto err_fbdev_update;
> +
> +       mutex_unlock(&drm->struct_mutex);
> +
> +       return 0;
> +
> +err_fbdev_update:
> +       fb_dealloc_cmap(&fbi->cmap);
> +
> +err_alloc_cmap:
> +       fb->funcs->destroy(fb);
> +
> +err_fb_create:
> +       framebuffer_release(fbi);
> +
> +err_fb_alloc:
> +       mutex_unlock(&drm->struct_mutex);
> +
> +       return ret;
> +}
> +
> +static int imx_drm_fbdev_probe(struct drm_fb_helper *helper,
> +                                  struct drm_fb_helper_surface_size *sizes)
> +{
> +       int ret;
> +
> +       BUG_ON(helper->fb);
> +
> +       ret = imx_drm_fbdev_create(helper, sizes);
> +       if (ret) {
> +               dev_err(helper->dev->dev, "creating fbdev failed with %d\n", ret);
> +               return ret;
> +       }
> +
> +       /*
> +        * fb_helper expects a value more than 1 if succeed
> +        * because register_framebuffer() should be called.
> +        */
> +       return 1;
> +}
> +
> +static struct drm_fb_helper_funcs imx_drm_fb_helper_funcs = {
> +       .fb_probe = imx_drm_fbdev_probe,
> +};
> +
> +static struct drm_fb_helper *imx_drm_fbdev_init(struct drm_device *drm,
> +               int preferred_bpp)
> +{
> +       struct drm_fb_helper *helper;
> +       unsigned int num_crtc;
> +       int ret;
> +
> +       helper = kzalloc(sizeof(*helper), GFP_KERNEL);
> +       if (!helper)
> +               return NULL;
> +
> +       helper->funcs = &imx_drm_fb_helper_funcs;
> +
> +       num_crtc = drm->mode_config.num_crtc;
> +
> +       ret = drm_fb_helper_init(drm, helper, num_crtc, MAX_CONNECTOR);
> +       if (ret) {
> +               dev_err(drm->dev, "initializing drm fb helper failed with %d\n",
> +                               ret);
> +               goto err_init;
> +       }
> +
> +       ret = drm_fb_helper_single_add_all_connectors(helper);
> +       if (ret) {
> +               dev_err(drm->dev, "registering drm_fb_helper_connector failed with %d\n",
> +                               ret);
> +               goto err_setup;
> +
> +       }
> +
> +       ret = drm_fb_helper_initial_config(helper, preferred_bpp);
> +       if (ret) {
> +               dev_err(drm->dev, "initial config failed with %d\n", ret);
> +               goto err_setup;
> +       }
> +
> +       return helper;
> +
> +err_setup:
> +       drm_fb_helper_fini(helper);
> +
> +err_init:
> +       kfree(helper);
> +
> +       return NULL;
> +}
> +
> +static void imx_drm_fbdev_fini(struct drm_fb_helper *helper)
> +{
> +       struct imx_drm_buf_entry *entry;
> +
> +       if (helper->fbdev) {
> +               struct fb_info *info;
> +               int ret;
> +
> +               info = helper->fbdev;
> +               ret = unregister_framebuffer(info);
> +               if (ret)
> +                       dev_err(helper->dev->dev, "unregister_framebuffer failed with %d\n",
> +                                       ret);
> +
> +               if (info->cmap.len)
> +                       fb_dealloc_cmap(&info->cmap);
> +
> +               entry = imx_drm_fb_get_buf(helper->fb);
> +
> +               imx_drm_buf_destroy(helper->dev, entry);
> +
> +               framebuffer_release(info);
> +       }
> +
> +       drm_fb_helper_fini(helper);
> +
> +       kfree(helper);
> +}
> +
> +static struct drm_fb_helper *imx_fb_helper;
> +
> +static int __init imx_fb_helper_init(void)
> +{
> +       struct drm_device *drm = imx_drm_device_get();
> +       int ret;
> +
> +       if (!drm)
> +               return -EINVAL;
> +
> +       imx_fb_helper = imx_drm_fbdev_init(drm, PREFERRED_BPP);
> +       if (!imx_fb_helper) {
> +               imx_drm_device_put();
> +               return -EINVAL;
> +       }
> +
> +       return 0;
> +}
> +
> +static void __exit imx_fb_helper_exit(void)
> +{
> +       imx_drm_fbdev_fini(imx_fb_helper);
> +       imx_drm_device_put();
> +}
> +
> +late_initcall(imx_fb_helper_init);
> +module_exit(imx_fb_helper_exit);
> +
> +MODULE_DESCRIPTION("Freescale i.MX legacy fb driver");
> +MODULE_AUTHOR("Sascha Hauer, Pengutronix");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/imx/imx-gem.c b/drivers/gpu/drm/imx/imx-gem.c
> new file mode 100644
> index 0000000..b0866fb
> --- /dev/null
> +++ b/drivers/gpu/drm/imx/imx-gem.c
> @@ -0,0 +1,343 @@
> +/*
> + * i.MX drm driver
> + *
> + * Copyright (C) 2012 Sascha Hauer, Pengutronix
> + *
> + * Based on Samsung Exynos code
> + *
> + * Copyright (c) 2011 Samsung Electronics Co., Ltd.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +#include <drm/drmP.h>
> +#include <drm/drm.h>
> +#include <drm/drm_crtc_helper.h>
> +
> +#include "imx-drm.h"
> +
> +static int lowlevel_buffer_allocate(struct drm_device *drm,
> +               struct imx_drm_buf_entry *entry)
> +{
> +       entry->vaddr = dma_alloc_writecombine(drm->dev, entry->size,
> +                       (dma_addr_t *)&entry->paddr, GFP_KERNEL);
> +       if (!entry->vaddr) {
> +               dev_err(drm->dev, "failed to allocate buffer.\n");
> +               return -ENOMEM;
> +       }
> +
> +       dev_dbg(drm->dev, "allocated : vaddr(0x%x), paddr(0x%x), size(0x%x)\n",
> +                       (unsigned int)entry->vaddr, entry->paddr, entry->size);
> +
> +       return 0;
> +}
> +
> +static void lowlevel_buffer_free(struct drm_device *drm,
> +               struct imx_drm_buf_entry *entry)
> +{
> +       dma_free_writecombine(drm->dev, entry->size, entry->vaddr,
> +                       entry->paddr);
> +}
> +
> +struct imx_drm_buf_entry *imx_drm_buf_create(struct drm_device *drm,
> +               unsigned int size)
> +{
> +       struct imx_drm_buf_entry *entry;
> +
> +       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
> +       if (!entry)
> +               return ERR_PTR(-ENOMEM);
> +
> +       entry->size = size;
> +
> +       /*
> +        * allocate memory region with size and set the memory information
> +        * to vaddr and paddr of a entry object.
> +        */
> +       if (lowlevel_buffer_allocate(drm, entry) < 0) {
> +               kfree(entry);
> +               return ERR_PTR(-ENOMEM);
> +       }
> +
> +       return entry;
> +}
> +
> +void imx_drm_buf_destroy(struct drm_device *drm,
> +               struct imx_drm_buf_entry *entry)
> +{
> +       lowlevel_buffer_free(drm, entry);
> +
> +       kfree(entry);
> +       entry = NULL;
> +}
> +EXPORT_SYMBOL_GPL(imx_drm_buf_destroy);
> +
> +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 unsigned int get_gem_mmap_offset(struct drm_gem_object *obj)
> +{
> +       return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT;
> +}
> +
> +static struct imx_drm_gem_obj *imx_drm_gem_create(struct drm_device *drm,
> +               unsigned int size)
> +{
> +       struct imx_drm_gem_obj *imx_drm_gem_obj;
> +       struct imx_drm_buf_entry *entry;
> +       struct drm_gem_object *obj;
> +       int ret;
> +
> +       size = roundup(size, PAGE_SIZE);
> +
> +       imx_drm_gem_obj = kzalloc(sizeof(*imx_drm_gem_obj), GFP_KERNEL);
> +       if (!imx_drm_gem_obj)
> +               return ERR_PTR(-ENOMEM);
> +
> +       /* allocate the new buffer object and memory region. */
> +       entry = imx_drm_buf_create(drm, size);
> +       if (!entry) {
> +               ret = -ENOMEM;
> +               goto err_alloc;
> +       }
> +
> +       imx_drm_gem_obj->entry = entry;
> +
> +       obj = &imx_drm_gem_obj->base;
> +
> +       ret = drm_gem_object_init(drm, obj, size);
> +       if (ret) {
> +               dev_err(drm->dev, "initializing GEM object failed with %d\n", ret);
> +               goto err_obj_init;
> +       }
> +
> +       ret = drm_gem_create_mmap_offset(obj);
> +       if (ret) {
> +               dev_err(drm->dev, "creating mmap offset failed with %d\n", ret);
> +               goto err_create_mmap_offset;
> +       }
> +
> +       return imx_drm_gem_obj;
> +
> +err_create_mmap_offset:
> +       drm_gem_object_release(obj);
> +
> +err_obj_init:
> +       imx_drm_buf_destroy(drm, imx_drm_gem_obj->entry);
> +
> +err_alloc:
> +       kfree(imx_drm_gem_obj);
> +
> +       return ERR_PTR(ret);
> +}
> +
> +static struct imx_drm_gem_obj *imx_drm_gem_create_with_handle(struct drm_file *file_priv,
> +               struct drm_device *drm, unsigned int size,
> +               unsigned int *handle)
> +{
> +       struct imx_drm_gem_obj *imx_drm_gem_obj;
> +       struct drm_gem_object *obj;
> +       int ret;
> +
> +       imx_drm_gem_obj = imx_drm_gem_create(drm, size);
> +       if (IS_ERR(imx_drm_gem_obj))
> +               return imx_drm_gem_obj;
> +
> +       obj = &imx_drm_gem_obj->base;
> +
> +       /*
> +        * 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)
> +               goto err_handle_create;
> +
> +       /* drop reference from allocate - handle holds it now. */
> +       drm_gem_object_unreference_unlocked(obj);
> +
> +       return imx_drm_gem_obj;
> +
> +err_handle_create:
> +       imx_drm_gem_free_object(obj);
> +
> +       return ERR_PTR(ret);
> +}
> +
> +static int imx_drm_gem_mmap_buffer(struct file *filp,
> +               struct vm_area_struct *vma)
> +{
> +       struct drm_gem_object *obj = filp->private_data;
> +       struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj);
> +       struct imx_drm_buf_entry *entry;
> +       unsigned long pfn, vm_size;
> +
> +       vma->vm_flags |= VM_IO | VM_RESERVED;
> +
> +       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);

pgprot_writecombine()?

> +       vma->vm_file = filp;
> +
> +       vm_size = vma->vm_end - vma->vm_start;
> +       /*
> +        * an entry contains information to physically continuous memory
> +        * allocated by user request or at framebuffer creation.
> +        */
> +       entry = imx_drm_gem_obj->entry;
> +
> +       /* check if user-requested size is valid. */
> +       if (vm_size > entry->size)
> +               return -EINVAL;
> +
> +       /*
> +        * get page frame number to physical memory to be mapped
> +        * to user space.
> +        */
> +       pfn = imx_drm_gem_obj->entry->paddr >> PAGE_SHIFT;
> +
> +       if (remap_pfn_range(vma, vma->vm_start, pfn, vm_size,
> +                               vma->vm_page_prot)) {
> +               dev_err(obj->dev->dev, "failed to remap pfn range.\n");
> +               return -EAGAIN;
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct file_operations imx_drm_gem_fops = {
> +       .mmap = imx_drm_gem_mmap_buffer,
> +};
> +
> +int imx_drm_gem_init_object(struct drm_gem_object *obj)
> +{
> +       return 0;
> +}
> +
> +void imx_drm_gem_free_object(struct drm_gem_object *gem_obj)
> +{
> +       struct imx_drm_gem_obj *imx_drm_gem_obj;
> +
> +       if (gem_obj->map_list.map)
> +               drm_gem_free_mmap_offset(gem_obj);
> +
> +       drm_gem_object_release(gem_obj);
> +
> +       imx_drm_gem_obj = to_imx_drm_gem_obj(gem_obj);
> +
> +       imx_drm_buf_destroy(gem_obj->dev, imx_drm_gem_obj->entry);
> +
> +       kfree(imx_drm_gem_obj);
> +}
> +
> +int imx_drm_gem_dumb_create(struct drm_file *file_priv,
> +               struct drm_device *dev, struct drm_mode_create_dumb *args)
> +{
> +       struct imx_drm_gem_obj *imx_drm_gem_obj;
> +
> +       /* FIXME: This should be configured by the crtc driver */
> +       args->pitch = args->width * args->bpp >> 3;
> +       args->size = args->pitch * args->height;
> +
> +       imx_drm_gem_obj = imx_drm_gem_create_with_handle(file_priv, dev, args->size,
> +                       &args->handle);
> +       if (IS_ERR(imx_drm_gem_obj))
> +               return PTR_ERR(imx_drm_gem_obj);
> +
> +       return 0;
> +}
> +
> +int imx_drm_gem_dumb_map_offset(struct drm_file *file_priv,
> +               struct drm_device *drm, uint32_t handle, uint64_t *offset)
> +{
> +       struct imx_drm_gem_obj *imx_drm_gem_obj;
> +       struct drm_gem_object *obj;
> +
> +       mutex_lock(&drm->struct_mutex);
> +
> +       obj = drm_gem_object_lookup(drm, file_priv, handle);
> +       if (!obj) {
> +               dev_err(drm->dev, "failed to lookup gem object\n");
> +               mutex_unlock(&drm->struct_mutex);
> +               return -EINVAL;
> +       }
> +
> +       imx_drm_gem_obj = to_imx_drm_gem_obj(obj);
> +
> +       *offset = get_gem_mmap_offset(&imx_drm_gem_obj->base);
> +
> +       drm_gem_object_unreference(obj);
> +
> +       mutex_unlock(&drm->struct_mutex);
> +
> +       return 0;
> +}
> +
> +int imx_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
> +{
> +       struct drm_gem_object *obj = vma->vm_private_data;
> +       struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj);
> +       struct drm_device *dev = obj->dev;
> +       unsigned long pfn;
> +       pgoff_t page_offset;
> +       int ret;
> +
> +       page_offset = ((unsigned long)vmf->virtual_address -
> +                       vma->vm_start) >> PAGE_SHIFT;
> +
> +       mutex_lock(&dev->struct_mutex);
> +
> +       pfn = (imx_drm_gem_obj->entry->paddr >> PAGE_SHIFT) + page_offset;
> +
> +       ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
> +
> +       mutex_unlock(&dev->struct_mutex);
> +
> +       return convert_to_vm_err_msg(ret);
> +}
> +
> +int imx_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
> +{
> +       int ret;
> +
> +       ret = drm_gem_mmap(filp, vma);
> +       if (ret)
> +               return ret;
> +
> +       vma->vm_flags &= ~VM_PFNMAP;
> +       vma->vm_flags |= VM_MIXEDMAP;
> +
> +       return ret;
> +}
> +
> +
> +int imx_drm_gem_dumb_destroy(struct drm_file *file_priv,
> +               struct drm_device *dev, unsigned int handle)
> +{
> +       return drm_gem_handle_delete(file_priv, handle);
> +}
> diff --git a/drivers/gpu/drm/imx/imx-lcdc-crtc.c b/drivers/gpu/drm/imx/imx-lcdc-crtc.c
> new file mode 100644
> index 0000000..e77c015
> --- /dev/null
> +++ b/drivers/gpu/drm/imx/imx-lcdc-crtc.c
> @@ -0,0 +1,517 @@
> +/*
> + * i.MX LCDC crtc driver
> + *
> + * Copyright (C) 2012 Sascha Hauer, Pengutronix
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <linux/fb.h>
> +#include <linux/clk.h>
> +#include <asm/fb.h>
> +#include <linux/module.h>
> +#include <mach/hardware.h>
> +#include <mach/imxfb.h>
> +#include <generated/mach-types.h>
> +
> +#include "imx-drm.h"
> +
> +#define LCDC_SSA               0x00
> +#define LCDC_SIZE              0x04
> +#define LCDC_VPW               0x08
> +#define LCDC_CPOS              0x0C
> +#define LCDC_LCWHB             0x10
> +#define LCDC_LCHCC             0x14
> +#define LCDC_PCR               0x18
> +#define LCDC_HCR               0x1C
> +#define LCDC_VCR               0x20
> +#define LCDC_POS               0x24
> +#define LCDC_LSCR1             0x28
> +#define LCDC_PWMR              0x2C
> +#define LCDC_DMACR             0x30
> +#define LCDC_RMCR              0x34
> +#define LCDC_LCDICR            0x38
> +#define LCDC_LIER              0x3c
> +#define LCDC_LISR              0x40
> +
> +#define SIZE_XMAX(x)           ((((x) >> 4) & 0x3f) << 20)
> +
> +#define YMAX_MASK              (cpu_is_mx1() ? 0x1ff : 0x3ff)
> +#define SIZE_YMAX(y)           ((y) & YMAX_MASK)
> +
> +#define VPW_VPW(x)             ((x) & 0x3ff)
> +
> +#define HCR_H_WIDTH(x)         (((x) & 0x3f) << 26)
> +#define HCR_H_WAIT_1(x)                (((x) & 0xff) << 8)
> +#define HCR_H_WAIT_2(x)                ((x) & 0xff)
> +
> +#define VCR_V_WIDTH(x)         (((x) & 0x3f) << 26)
> +#define VCR_V_WAIT_1(x)                (((x) & 0xff) << 8)
> +#define VCR_V_WAIT_2(x)                ((x) & 0xff)
> +
> +#define RMCR_LCDC_EN_MX1       (1 << 1)
> +
> +#define RMCR_SELF_REF          (1 << 0)
> +
> +#define LIER_EOF               (1 << 1)
> +
> +struct imx_crtc {
> +       struct drm_crtc         base;
> +       struct imx_drm_crtc     *imx_drm_crtc;
> +       int                     di_no;
> +       int                     enabled;
> +       void __iomem            *regs;
> +       u32                     pwmr;
> +       u32                     lscr1;
> +       u32                     dmacr;
> +       u32                     pcr;
> +       struct clk              *clk;
> +       struct device           *dev;
> +       int                     vblank_enable;
> +
> +       struct drm_pending_vblank_event *page_flip_event;
> +       struct drm_framebuffer  *newfb;
> +};
> +
> +#define to_imx_crtc(x) container_of(x, struct imx_crtc, base)
> +
> +static void imx_crtc_load_lut(struct drm_crtc *crtc)
> +{
> +}
> +
> +#define PCR_BPIX_8             (3 << 25)
> +#define PCR_BPIX_12            (4 << 25)
> +#define PCR_BPIX_16            (5 << 25)
> +#define PCR_BPIX_18            (6 << 25)
> +#define PCR_END_SEL            (1 << 18)
> +#define PCR_END_BYTE_SWAP      (1 << 17)
> +
> +const char *fourcc_to_str(u32 fourcc)
> +{
> +       static char buf[5];
> +
> +       *(u32 *)buf = fourcc;
> +       buf[4] = 0;
> +
> +       return buf;
> +}
> +
> +static int imx_drm_crtc_set(struct drm_crtc *crtc,
> +               struct drm_display_mode *mode)
> +{
> +       struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
> +       struct drm_framebuffer *fb = crtc->fb;
> +       int lower_margin = mode->vsync_start - mode->vdisplay;
> +       int upper_margin = mode->vtotal - mode->vsync_end;
> +       int vsync_len = mode->vsync_end - mode->vsync_start;
> +       int hsync_len = mode->hsync_end - mode->hsync_start;
> +       int right_margin = mode->hsync_start - mode->hdisplay;
> +       int left_margin = mode->htotal - mode->hsync_end;
> +       unsigned long lcd_clk;
> +       u32 pcr;
> +
> +       lcd_clk = clk_get_rate(imx_crtc->clk) / 1000;
> +
> +       if (!mode->clock)
> +               return -EINVAL;
> +
> +       pcr = DIV_ROUND_CLOSEST(lcd_clk, mode->clock);
> +       if (--pcr > 0x3f)
> +               pcr = 0x3f;
> +
> +       switch (fb->pixel_format) {
> +       case DRM_FORMAT_XRGB8888:
> +       case DRM_FORMAT_ARGB8888:
> +               pcr |= PCR_BPIX_18;
> +               pcr |= PCR_END_SEL | PCR_END_BYTE_SWAP;
> +               break;
> +       case DRM_FORMAT_RGB565:
> +               if (cpu_is_mx1())
> +                       pcr |= PCR_BPIX_12;
> +               else
> +                       pcr |= PCR_BPIX_16;
> +               break;
> +       case DRM_FORMAT_RGB332:
> +               pcr |= PCR_BPIX_8;
> +               break;
> +       default:
> +               dev_err(imx_crtc->dev, "unsupported pixel format %s\n",
> +                               fourcc_to_str(fb->pixel_format));
> +               return -EINVAL;
> +       }
> +
> +       /* add sync polarities */
> +       pcr |= imx_crtc->pcr & ~(0x3f | (7 << 25));
> +
> +       dev_dbg(imx_crtc->dev,
> +                       "xres=%d hsync_len=%d left_margin=%d right_margin=%d\n",
> +                       mode->hdisplay, hsync_len,
> +                       left_margin, right_margin);
> +       dev_dbg(imx_crtc->dev,
> +                       "yres=%d vsync_len=%d upper_margin=%d lower_margin=%d\n",
> +                       mode->vdisplay, vsync_len,
> +                       upper_margin, lower_margin);
> +
> +       writel(VPW_VPW(mode->hdisplay * fb->bits_per_pixel / 8 / 4),
> +               imx_crtc->regs + LCDC_VPW);
> +
> +       writel(HCR_H_WIDTH(hsync_len - 1) |
> +               HCR_H_WAIT_1(right_margin - 1) |
> +               HCR_H_WAIT_2(left_margin - 3),
> +               imx_crtc->regs + LCDC_HCR);
> +
> +       writel(VCR_V_WIDTH(vsync_len) |
> +               VCR_V_WAIT_1(lower_margin) |
> +               VCR_V_WAIT_2(upper_margin),
> +               imx_crtc->regs + LCDC_VCR);
> +
> +       writel(SIZE_XMAX(mode->hdisplay) | SIZE_YMAX(mode->vdisplay),
> +                       imx_crtc->regs + LCDC_SIZE);
> +
> +       writel(pcr, imx_crtc->regs + LCDC_PCR);
> +       writel(imx_crtc->pwmr, imx_crtc->regs + LCDC_PWMR);
> +       writel(imx_crtc->lscr1, imx_crtc->regs + LCDC_LSCR1);
> +       /* reset default */
> +       writel(0x00040060, imx_crtc->regs + LCDC_DMACR);
> +
> +       return 0;
> +}
> +
> +static int imx_drm_set_base(struct drm_crtc *crtc, int x, int y)
> +{
> +       struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
> +       struct imx_drm_buf_entry *entry;
> +       struct drm_framebuffer *fb = crtc->fb;
> +       unsigned long phys;
> +
> +       entry = imx_drm_fb_get_buf(fb);
> +       if (!entry)
> +               return -EFAULT;
> +
> +       phys = entry->paddr;
> +       phys += x * (fb->bits_per_pixel >> 3);
> +       phys += y * fb->pitches[0];
> +
> +       dev_dbg(imx_crtc->dev, "%s: phys: 0x%lx\n", __func__, phys);
> +       dev_dbg(imx_crtc->dev, "%s: xy: %dx%d\n", __func__, x, y);
> +
> +       writel(phys, imx_crtc->regs + LCDC_SSA);
> +
> +       return 0;
> +}
> +
> +static int imx_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 imx_crtc *imx_crtc = to_imx_crtc(crtc);
> +
> +       imx_drm_set_base(crtc, x, y);
> +
> +       dev_dbg(imx_crtc->dev, "mode->hdisplay: %d\n", mode->hdisplay);
> +       dev_dbg(imx_crtc->dev, "mode->vdisplay: %d\n", mode->vdisplay);
> +
> +       return imx_drm_crtc_set(crtc, mode);
> +}
> +
> +static void imx_crtc_enable(struct imx_crtc *imx_crtc)
> +{
> +       if (!imx_crtc->enabled)
> +               clk_enable(imx_crtc->clk);
> +       imx_crtc->enabled = 1;
> +}
> +
> +static void imx_crtc_disable(struct imx_crtc *imx_crtc)
> +{
> +       if (imx_crtc->enabled)
> +               clk_disable(imx_crtc->clk);
> +       imx_crtc->enabled = 0;
> +}
> +
> +static void imx_crtc_dpms(struct drm_crtc *crtc, int mode)
> +{
> +       struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
> +
> +       dev_dbg(imx_crtc->dev, "%s mode: %d\n", __func__, mode);
> +
> +       switch (mode) {
> +       case DRM_MODE_DPMS_ON:
> +               imx_crtc_enable(imx_crtc);
> +               break;
> +       default:
> +               imx_crtc_disable(imx_crtc);
> +               break;
> +       }
> +}
> +
> +static bool imx_crtc_mode_fixup(struct drm_crtc *crtc,
> +                                 struct drm_display_mode *mode,
> +                                 struct drm_display_mode *adjusted_mode)
> +{
> +       return true;
> +}
> +
> +static void imx_crtc_prepare(struct drm_crtc *crtc)
> +{
> +       struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
> +
> +       imx_crtc_disable(imx_crtc);
> +}
> +
> +static void imx_crtc_commit(struct drm_crtc *crtc)
> +{
> +       struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
> +
> +       imx_crtc_enable(imx_crtc);
> +}
> +
> +static struct drm_crtc_helper_funcs imx_helper_funcs = {
> +       .dpms = imx_crtc_dpms,
> +       .mode_fixup = imx_crtc_mode_fixup,
> +       .mode_set = imx_crtc_mode_set,
> +       .prepare = imx_crtc_prepare,
> +       .commit = imx_crtc_commit,
> +       .load_lut = imx_crtc_load_lut,
> +};
> +
> +static void imx_drm_handle_pageflip(struct imx_crtc *imx_crtc)
> +{
> +       struct drm_pending_vblank_event *e;
> +       struct timeval now;
> +       unsigned long flags;
> +       struct drm_device *drm = imx_crtc->base.dev;
> +
> +       spin_lock_irqsave(&drm->event_lock, flags);
> +
> +       e = imx_crtc->page_flip_event;
> +
> +       if (!e) {
> +               spin_unlock_irqrestore(&drm->event_lock, flags);
> +               return;
> +       }
> +
> +       do_gettimeofday(&now);
> +       e->event.sequence = 0;
> +       e->event.tv_sec = now.tv_sec;
> +       e->event.tv_usec = now.tv_usec;
> +       imx_crtc->page_flip_event = NULL;
> +
> +       list_add_tail(&e->base.link, &e->base.file_priv->event_list);
> +
> +       wake_up_interruptible(&e->base.file_priv->event_wait);
> +
> +       spin_unlock_irqrestore(&drm->event_lock, flags);
> +}
> +
> +static int imx_crtc_enable_vblank(struct drm_crtc *crtc)
> +{
> +       struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
> +
> +       writel(LIER_EOF, imx_crtc->regs + LCDC_LIER);
> +
> +       return 0;
> +}
> +
> +static void imx_crtc_disable_vblank(struct drm_crtc *crtc)
> +{
> +       struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
> +
> +       writel(0, imx_crtc->regs + LCDC_LIER);
> +}
> +
> +static irqreturn_t imx_irq_handler(int irq, void *dev_id)
> +{
> +       struct imx_crtc *imx_crtc = dev_id;
> +       struct drm_device *drm = imx_crtc->base.dev;
> +
> +       /* Acknowledge interrupt */
> +       readl(imx_crtc->regs + LCDC_LISR);
> +
> +       drm_handle_vblank(drm, 0);
> +
> +       if (imx_crtc->newfb) {
> +               imx_crtc->base.fb = imx_crtc->newfb;
> +               imx_crtc->newfb = NULL;
> +               imx_drm_set_base(&imx_crtc->base, 0, 0);
> +               imx_drm_handle_pageflip(imx_crtc);
> +               imx_drm_crtc_vblank_put(imx_crtc->imx_drm_crtc);
> +       }
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static int imx_page_flip(struct drm_crtc *crtc,
> +                         struct drm_framebuffer *fb,
> +                         struct drm_pending_vblank_event *event)
> +{
> +       struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
> +
> +       if (imx_crtc->newfb)
> +               return -EBUSY;
> +
> +       imx_crtc->newfb = fb;
> +       imx_crtc->page_flip_event = event;
> +       imx_drm_crtc_vblank_get(imx_crtc->imx_drm_crtc);
> +
> +       return 0;
> +}
> +
> +static const struct drm_crtc_funcs imx_crtc_funcs = {
> +       .page_flip = imx_page_flip,
> +};
> +
> +static const struct imx_drm_crtc_helper_funcs imx_imx_drm_helper = {
> +       .enable_vblank = imx_crtc_enable_vblank,
> +       .disable_vblank = imx_crtc_disable_vblank,
> +};
> +
> +#define DRIVER_NAME "imx-lcdc-crtc"
> +
> +/*
> + * the pcr bits to be allowed to set in platform data
> + */
> +#define PDATA_PCR      (PCR_PIXPOL | PCR_FLMPOL | PCR_LPPOL | \
> +                       PCR_CLKPOL | PCR_OEPOL | PCR_TFT | PCR_COLOR | \
> +                       PCR_PBSIZ_8 | PCR_ACD(0x7f) | PCR_ACD_SEL | \
> +                       PCR_SCLK_SEL | PCR_SHARP)
> +
> +static int __devinit imx_crtc_probe(struct platform_device *pdev)
> +{
> +       struct imx_crtc *imx_crtc;
> +       struct resource *res;
> +       int ret, irq;
> +       u32 pcr_value = 0xf00080c0;
> +       u32 lscr1_value = 0x00120300;
> +       u32 pwmr_value = 0x00a903ff;
> +
> +       imx_crtc = devm_kzalloc(&pdev->dev, sizeof(*imx_crtc), GFP_KERNEL);
> +       if (!imx_crtc)
> +               return -ENOMEM;
> +
> +       imx_crtc->dev = &pdev->dev;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!res)
> +               return -ENODEV;
> +
> +       res = devm_request_mem_region(&pdev->dev, res->start,
> +                       resource_size(res), DRIVER_NAME);
> +       if (!res)
> +               return -EBUSY;
> +
> +       imx_crtc->regs = devm_ioremap(&pdev->dev, res->start,
> +                       resource_size(res));
> +       if (!imx_crtc->regs) {
> +               dev_err(&pdev->dev, "Cannot map frame buffer registers\n");
> +               return -EBUSY;
> +       }
> +
> +       irq = platform_get_irq(pdev, 0);
> +       ret = devm_request_irq(&pdev->dev, irq, imx_irq_handler, 0, "imx_drm",
> +                       imx_crtc);
> +       if (ret < 0) {
> +               dev_err(&pdev->dev, "irq request failed with %d\n", ret);
> +               return ret;
> +       }
> +
> +       imx_crtc->clk = clk_get(&pdev->dev, NULL);
> +       if (IS_ERR(imx_crtc->clk)) {
> +               ret = PTR_ERR(imx_crtc->clk);
> +               dev_err(&pdev->dev, "unable to get clock: %d\n", ret);
> +               return ret;
> +       }
> +
> +       clk_prepare_enable(imx_crtc->clk);
> +       imx_crtc->enabled = 1;
> +
> +       platform_set_drvdata(pdev, imx_crtc);
> +
> +       imx_crtc->pcr = pcr_value & PDATA_PCR;
> +
> +       if (imx_crtc->pcr != pcr_value)
> +               dev_err(&pdev->dev, "invalid bits set in pcr: 0x%08x\n",
> +                               pcr_value & ~PDATA_PCR);
> +
> +       imx_crtc->lscr1 = lscr1_value;
> +       imx_crtc->pwmr = pwmr_value;
> +
> +       ret = imx_drm_add_crtc(&imx_crtc->base,
> +                       &imx_crtc->imx_drm_crtc,
> +                       &imx_crtc_funcs, &imx_helper_funcs,
> +                       &imx_imx_drm_helper, THIS_MODULE);
> +       if (ret)
> +               goto err_init;
> +
> +       dev_info(&pdev->dev, "probed\n");
> +
> +       return 0;
> +
> +err_init:
> +       clk_disable_unprepare(imx_crtc->clk);
> +       clk_put(imx_crtc->clk);
> +
> +       return ret;
> +}
> +
> +static int __devexit imx_crtc_remove(struct platform_device *pdev)
> +{
> +       struct imx_crtc *imx_crtc = platform_get_drvdata(pdev);
> +
> +       imx_drm_remove_crtc(imx_crtc->imx_drm_crtc);
> +
> +       writel(0, imx_crtc->regs + LCDC_LIER);
> +
> +       clk_disable_unprepare(imx_crtc->clk);
> +       clk_put(imx_crtc->clk);
> +
> +       platform_set_drvdata(pdev, NULL);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id imx_lcdc_dt_ids[] = {
> +       { .compatible = "fsl,imx1-lcdc", .data = NULL, },
> +       { .compatible = "fsl,imx21-lcdc", .data = NULL, },
> +       { /* sentinel */ }
> +};
> +
> +static struct platform_driver imx_crtc_driver = {
> +       .remove         = __devexit_p(imx_crtc_remove),
> +       .probe          = imx_crtc_probe,
> +       .driver         = {
> +               .name   = DRIVER_NAME,
> +               .owner  = THIS_MODULE,
> +               .of_match_table = imx_lcdc_dt_ids,
> +       },
> +};
> +
> +static int __init imx_lcdc_init(void)
> +{
> +       return platform_driver_register(&imx_crtc_driver);
> +}
> +
> +static void __exit imx_lcdc_exit(void)
> +{
> +       platform_driver_unregister(&imx_crtc_driver);
> +}
> +
> +module_init(imx_lcdc_init);
> +module_exit(imx_lcdc_exit)
> +
> +MODULE_DESCRIPTION("Freescale i.MX framebuffer driver");
> +MODULE_AUTHOR("Sascha Hauer, Pengutronix");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/imx/imx-parallel-display.c b/drivers/gpu/drm/imx/imx-parallel-display.c
> new file mode 100644
> index 0000000..8c96113
> --- /dev/null
> +++ b/drivers/gpu/drm/imx/imx-parallel-display.c
> @@ -0,0 +1,228 @@
> +/*
> + * i.MX drm driver - parallel display implementation
> + *
> + * Copyright (C) 2012 Sascha Hauer, Pengutronix
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
> + * MA 02110-1301, USA.
> + */
> +
> +#include <linux/module.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +
> +#include "imx-drm.h"
> +
> +#define con_to_imxpd(x) container_of(x, struct imx_parallel_display, connector)
> +#define enc_to_imxpd(x) container_of(x, struct imx_parallel_display, encoder)
> +
> +struct imx_parallel_display {
> +       struct drm_connector connector;
> +       struct imx_drm_connector *imx_drm_connector;
> +       struct drm_encoder encoder;
> +       struct imx_drm_encoder *imx_drm_encoder;
> +       struct device *dev;
> +       void *edid;
> +       int edid_len;
> +};
> +
> +static enum drm_connector_status imx_pd_connector_detect(struct drm_connector *connector,
> +               bool force)
> +{
> +       return connector_status_connected;
> +}
> +
> +static void imx_pd_connector_destroy(struct drm_connector *connector)
> +{
> +       /* do not free here */
> +}
> +
> +static int imx_pd_connector_get_modes(struct drm_connector *connector)
> +{
> +       struct imx_parallel_display *imxpd = con_to_imxpd(connector);
> +       int ret;
> +
> +       drm_mode_connector_update_edid_property(connector, imxpd->edid);
> +       ret = drm_add_edid_modes(connector, imxpd->edid);
> +       connector->display_info.raw_edid = NULL;
> +
> +       return ret;
> +}
> +
> +static int imx_pd_connector_mode_valid(struct drm_connector *connector,
> +                         struct drm_display_mode *mode)
> +{
> +       return 0;
> +}
> +
> +static struct drm_encoder *imx_pd_connector_best_encoder(struct drm_connector *connector)
> +{
> +       struct imx_parallel_display *imxpd = con_to_imxpd(connector);
> +
> +       return &imxpd->encoder;
> +}
> +
> +static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode)
> +{
> +}
> +
> +static bool imx_pd_encoder_mode_fixup(struct drm_encoder *encoder,
> +                          struct drm_display_mode *mode,
> +                          struct drm_display_mode *adjusted_mode)
> +{
> +       return true;
> +}
> +
> +static void imx_pd_encoder_prepare(struct drm_encoder *encoder)
> +{
> +}
> +
> +static void imx_pd_encoder_commit(struct drm_encoder *encoder)
> +{
> +}
> +
> +static void imx_pd_encoder_mode_set(struct drm_encoder *encoder,
> +                        struct drm_display_mode *mode,
> +                        struct drm_display_mode *adjusted_mode)
> +{
> +}
> +
> +static void imx_pd_encoder_disable(struct drm_encoder *encoder)
> +{
> +}
> +
> +static void imx_pd_encoder_destroy(struct drm_encoder *encoder)
> +{
> +       /* do not free here */
> +}
> +
> +struct drm_connector_funcs imx_pd_connector_funcs = {
> +       .dpms = drm_helper_connector_dpms,
> +       .fill_modes = drm_helper_probe_single_connector_modes,
> +       .detect = imx_pd_connector_detect,
> +       .destroy = imx_pd_connector_destroy,
> +};
> +
> +struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = {
> +       .get_modes = imx_pd_connector_get_modes,
> +       .best_encoder = imx_pd_connector_best_encoder,
> +       .mode_valid = imx_pd_connector_mode_valid,
> +};
> +
> +static struct drm_encoder_funcs imx_pd_encoder_funcs = {
> +       .destroy = imx_pd_encoder_destroy,
> +};
> +
> +static struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = {
> +       .dpms = imx_pd_encoder_dpms,
> +       .mode_fixup = imx_pd_encoder_mode_fixup,
> +       .prepare = imx_pd_encoder_prepare,
> +       .commit = imx_pd_encoder_commit,
> +       .mode_set = imx_pd_encoder_mode_set,
> +       .disable = imx_pd_encoder_disable,
> +};
> +
> +static int imx_pd_register(struct imx_parallel_display *imxpd)
> +{
> +       int ret;
> +
> +       drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder);
> +
> +       imxpd->connector.funcs = &imx_pd_connector_funcs;
> +       imxpd->encoder.funcs = &imx_pd_encoder_funcs;
> +
> +       drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs);
> +       ret = imx_drm_add_encoder(&imxpd->encoder, &imxpd->imx_drm_encoder, THIS_MODULE);
> +       if (ret) {
> +               dev_err(imxpd->dev, "adding encoder failed with %d\n", ret);
> +               return ret;
> +       }
> +
> +       drm_connector_helper_add(&imxpd->connector, &imx_pd_connector_helper_funcs);
> +
> +       ret = imx_drm_add_connector(&imxpd->connector, &imxpd->imx_drm_connector,
> +                       THIS_MODULE);
> +       if (ret) {
> +               imx_drm_remove_encoder(imxpd->imx_drm_encoder);
> +               dev_err(imxpd->dev, "adding connector failed with %d\n", ret);
> +               return ret;
> +       }
> +
> +       imxpd->connector.encoder = &imxpd->encoder;
> +
> +       return 0;
> +}
> +
> +static int __devinit imx_pd_probe(struct platform_device *pdev)
> +{
> +       struct device_node *np = pdev->dev.of_node;
> +       const u8 *edidp;
> +       struct imx_parallel_display *imxpd;
> +       int ret;
> +
> +       imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL);
> +       if (!imxpd)
> +               return -ENOMEM;
> +
> +       edidp = of_get_property(np, "edid", &imxpd->edid_len);
> +
> +       imxpd->edid = kmemdup(edidp, imxpd->edid_len, GFP_KERNEL);
> +       imxpd->encoder.possible_crtcs = 0x1;
> +       imxpd->encoder.possible_clones = 0x1;
> +       imxpd->dev = &pdev->dev;
> +
> +       ret = imx_pd_register(imxpd);
> +       if (ret)
> +               return ret;
> +
> +       platform_set_drvdata(pdev, imxpd);
> +
> +       return 0;
> +}
> +
> +static int __devexit imx_pd_remove(struct platform_device *pdev)
> +{
> +       struct imx_parallel_display *imxpd = platform_get_drvdata(pdev);
> +       struct drm_connector *connector = &imxpd->connector;
> +       struct drm_encoder *encoder = &imxpd->encoder;
> +
> +       drm_mode_connector_detach_encoder(connector, encoder);
> +
> +       imx_drm_remove_connector(imxpd->imx_drm_connector);
> +       imx_drm_remove_encoder(imxpd->imx_drm_encoder);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id imx_pd_dt_ids[] = {
> +       { .compatible = "fsl,imx-parallel-display", .data = NULL, },
> +       { /* sentinel */ }
> +};
> +
> +static struct platform_driver imx_pd_driver = {
> +       .probe          = imx_pd_probe,
> +       .remove         = __devexit_p(imx_pd_remove),
> +       .driver         = {
> +               .of_match_table = imx_pd_dt_ids,
> +               .name   = "imx-parallel-display",
> +               .owner  = THIS_MODULE,
> +       },
> +};
> +
> +module_platform_driver(imx_pd_driver);
> +
> +MODULE_DESCRIPTION("i.MX parallel display driver");
> +MODULE_AUTHOR("Sascha Hauer, Pengutronix");
> +MODULE_LICENSE("GPL");
> --
> 1.7.10
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 1/2] DRM: add Freescale i.MX LCDC driver
  2012-05-22 21:28   ` Rob Clark
@ 2012-05-23  7:47     ` Sascha Hauer
  2012-05-23  8:37       ` Lars-Peter Clausen
  0 siblings, 1 reply; 35+ messages in thread
From: Sascha Hauer @ 2012-05-23  7:47 UTC (permalink / raw)
  To: Rob Clark; +Cc: linux-arm-kernel, dri-devel

Hi Rob,

On Tue, May 22, 2012 at 03:28:20PM -0600, Rob Clark wrote:
> just a few comments from a cursory review..  I need a bit more time
> for a more in-depth review but that won't be tonight so I thought I'd
> send what I have so far..

Thanks for this.

> > +++ b/drivers/gpu/drm/imx/Kconfig
> > @@ -0,0 +1,18 @@
> > +config DRM_IMX
> > +       tristate "DRM Support for Freescale i.MX"
> > +       select DRM_KMS_HELPER
> > +       depends on DRM && ARCH_MXC
> > +
> > +config DRM_IMX_FB_HELPER
> > +       tristate "provide legacy framebuffer /dev/fb0"
> > +       depends on DRM_IMX
> > +
> > +config DRM_IMX_LCDC
> > +       tristate "DRM Support for Freescale i.MX1 and i.MX2"
> > +       depends on DRM_IMX
> > +       help
> > +         Choose this if you have a i.MX1, i.MX21, i.MX25 or i.MX27 processor.
> 
> do you have something like cpu_is_imx2() type macros?  It would be
> preferable not to have a compile time config option for building for
> certain hw versions.  Ie. on OMAP we could do something like 'if
> (cpu_is_omap3xxx()) { ... }' if there was something that needed to be
> done different on omap3 family of devices.  This way you could choose
> to build a kernel supporting either a single omap variants, or all
> omap variants.

Yes, we have cpu_is_* macros. I don't see though why we should use them
here. The result of DRM_IMX_LCDC will be a platform driver for which a
suitable device exists only on the correct SoCs. There will be a second
DRM_IMX_IPU option next to this one for the newer i.MX SoCs which will
be a second platform driver.

> > +
> > +       /*
> > +        * without file_priv we are called from imx_drm_fbdev_create in which
> > +        * case we only create a framebuffer without a handle.
> > +        */
> > +       if (!file_priv) {
> > +               struct imx_drm_buf_entry *entry;
> > +
> > +               entry = imx_drm_buf_create(dev, size);
> > +               if (IS_ERR(entry)) {
> > +                       ret = PTR_ERR(entry);
> > +                       goto err_buffer;
> > +               }
> > +
> > +               imx_drm_fb->entry = entry;
> > +       } else {
> > +               obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
> > +               if (!obj) {
> > +                       ret = -EINVAL;
> > +                       goto err_buffer;
> > +               }
> > +
> > +               imx_drm_fb->imx_drm_gem_obj = to_imx_drm_gem_obj(obj);
> > +
> > +               drm_gem_object_unreference_unlocked(obj);
> 
> 
> the fb probably should hold the reference to the GEM obj until it is
> deleted..  so you don't end up freeing the buffer you are scanning out
> until you are done scanning it out.  Possibly this gets a bit more
> straightforward if you don't have to special case the default/fbcon
> framebuffer?
> 
> IIRC, Laurent had sent a patch recently to fix the same issue in the
> exynos driver.

Yes, just for reference, here is a link:

http://permalink.gmane.org/gmane.comp.video.dri.devel/69203

Will fix this.

> > +
> > +static int imx_drm_gem_mmap_buffer(struct file *filp,
> > +               struct vm_area_struct *vma)
> > +{
> > +       struct drm_gem_object *obj = filp->private_data;
> > +       struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj);
> > +       struct imx_drm_buf_entry *entry;
> > +       unsigned long pfn, vm_size;
> > +
> > +       vma->vm_flags |= VM_IO | VM_RESERVED;
> > +
> > +       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> 
> pgprot_writecombine()?

copied from the exynos driver. The exynos driver recently gained support
for different cache attribute flags and I could do the same. I would
prefer not to even have to think about it by using some generic code
here instead of duplicating other peoples bugs.

Do you think it's possible to share this code as suggested by Lars?
Every SoC not having a IOMMU could share the same code here, it's just
not clear to me how we can put this in a form that is acceptable
upstream.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re:
  2012-05-22 14:06 ` Lars-Peter Clausen
@ 2012-05-23  8:12   ` Sascha Hauer
  2012-05-24  6:31   ` Re: Sascha Hauer
  1 sibling, 0 replies; 35+ messages in thread
From: Sascha Hauer @ 2012-05-23  8:12 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: linux-arm-kernel, dri-devel

On Tue, May 22, 2012 at 04:06:41PM +0200, Lars-Peter Clausen wrote:
> On 05/18/2012 02:27 PM, Sascha Hauer wrote:
> > Hi All,
> > 
> > The following adds a drm/kms driver for the Freescale i.MX LCDC
> > controller. Most notable change to the last SDRM based version is that
> > the SDRM layer has been removed and the driver now is purely i.MX
> > specific. I hope that this is more acceptable now.
> > 
> > Another change is that the probe is now devicetree based. For now I
> > took the easy way out and only put an edid blob into the devicetree.
> > I haven't documented the binding yet, I would add that when the rest
> > is considered ok.
> > 
> > Comments very welcome.
> > 
> 
> Hi,
> 
> I really liked the sdrm layer. At least some bits of it. I've been working
> on a "simple" DRM driver as well. The hardware has no fancy acceleration
> features, just a simple buffer and some scanout logic. I'm basically using
> the same gem buffer structure and the buffer is also allocated using
> dma_alloc_writecombine, which means we can probably share all of the GEM
> handling code and probably also most of the fbdev code. I also started with
> the Exynos GEM code as a template, but reworked it later to be more like the
> UDL code, which made it a bit more compact. I think it would be a good idea
> to put at least the GEM handling in some common code as I expect that we'll
> see more similar "simple" DRM drivers pop up.

I totally agree. Having to track other drivers for bug fixes to apply
them on the own driver is not very convenient. As answered to Rob I do
not really have a clue how to accomplish this.

> 
> The code in question can be found at
> https://github.com/lclausen-adi/linux-2.6/commit/87a8fd6b98eeee317c7a486846cc8405d0bd68d8
> 
> Btw. the imx-drm.h is missing in your patch.

Oops, here it is for reference, will include it in the next round.


#ifndef _IMX_DRM_H_
#define _IMX_DRM_H_

/**
 * User-desired buffer creation information structure.
 *
 * @size: requested size for the object.
 *	- this size value would be page-aligned internally.
 * @flags: user request for setting memory type or cache attributes.
 * @handle: returned handle for the object.
 */
struct imx_drm_gem_create {
	unsigned int size;
	unsigned int flags;
	unsigned int handle;
};

struct imx_drm_device;
struct imx_drm_crtc;

struct imx_drm_crtc_helper_funcs {
	int (*enable_vblank)(struct drm_crtc *crtc);
	void (*disable_vblank)(struct drm_crtc *crtc);
};

int imx_drm_add_crtc(struct drm_crtc *crtc,
		struct imx_drm_crtc **new_crtc,
		const struct drm_crtc_funcs *crtc_funcs,
		const struct drm_crtc_helper_funcs *crtc_helper_funcs,
		const struct imx_drm_crtc_helper_funcs *ec_helper_funcs,
		struct module *owner);
int imx_drm_remove_crtc(struct imx_drm_crtc *);
int imx_drm_init_drm(struct platform_device *pdev,
		int preferred_bpp);
int imx_drm_exit_drm(void);

int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc);
void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc);
void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc);

/*
 * imx drm buffer entry structure.
 *
 * @paddr: physical address of allocated memory.
 * @vaddr: kernel virtual address of allocated memory.
 * @size: size of allocated memory.
 */
struct imx_drm_buf_entry {
	dma_addr_t paddr;
	void __iomem *vaddr;
	unsigned int size;
};

/* get physical memory information of a drm framebuffer. */
struct imx_drm_buf_entry *imx_drm_fb_get_buf(struct drm_framebuffer *fb);

struct imx_drm_encoder;
int imx_drm_add_encoder(struct drm_encoder *encoder,
		struct imx_drm_encoder **new_enc,
		struct module *owner);
int imx_drm_remove_encoder(struct imx_drm_encoder *);

struct imx_drm_connector;
int imx_drm_add_connector(struct drm_connector *connector,
		struct imx_drm_connector **new_con,
		struct module *owner);
int imx_drm_remove_connector(struct imx_drm_connector *);

void imx_drm_mode_config_init(struct drm_device *drm);

#define to_imx_drm_gem_obj(x)	container_of(x,\
			struct imx_drm_gem_obj, base)

struct imx_drm_gem_obj {
	struct drm_gem_object base;
	struct imx_drm_buf_entry *entry;
};

/* unmap a buffer from user space. */
int imx_drm_gem_munmap_ioctl(struct drm_device *drm, void *data,
		struct drm_file *file_priv);

/* initialize gem object. */
int imx_drm_gem_init_object(struct drm_gem_object *obj);

/* free gem object. */
void imx_drm_gem_free_object(struct drm_gem_object *gem_obj);

/* create memory region for drm framebuffer. */
int imx_drm_gem_dumb_create(struct drm_file *file_priv,
		struct drm_device *drm, struct drm_mode_create_dumb *args);

/* map memory region for drm framebuffer to user space. */
int imx_drm_gem_dumb_map_offset(struct drm_file *file_priv,
		struct drm_device *drm, uint32_t handle, uint64_t *offset);

/* page fault handler and mmap fault address(virtual) to physical memory. */
int imx_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 imx_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);

/*
 * 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 imx_drm_gem_dumb_destroy(struct drm_file *file_priv,
		struct drm_device *drm, unsigned int handle);

/* allocate physical memory. */
struct imx_drm_buf_entry *imx_drm_buf_create(struct drm_device *drm,
		unsigned int size);

/* remove allocated physical memory. */
void imx_drm_buf_destroy(struct drm_device *drm, struct imx_drm_buf_entry *entry);

struct drm_device *imx_drm_device_get(void);
void imx_drm_device_put(void);

#endif /* _IMX_DRM_H_ */
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 1/2] DRM: add Freescale i.MX LCDC driver
  2012-05-23  7:47     ` Sascha Hauer
@ 2012-05-23  8:37       ` Lars-Peter Clausen
  2012-05-23  9:09         ` Daniel Vetter
  0 siblings, 1 reply; 35+ messages in thread
From: Lars-Peter Clausen @ 2012-05-23  8:37 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: dri-devel, linux-arm-kernel, Rob Clark

[...]
>>> +
>>> +static int imx_drm_gem_mmap_buffer(struct file *filp,
>>> +               struct vm_area_struct *vma)
>>> +{
>>> +       struct drm_gem_object *obj = filp->private_data;
>>> +       struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj);
>>> +       struct imx_drm_buf_entry *entry;
>>> +       unsigned long pfn, vm_size;
>>> +
>>> +       vma->vm_flags |= VM_IO | VM_RESERVED;
>>> +
>>> +       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
>>
>> pgprot_writecombine()?
> 
> copied from the exynos driver. The exynos driver recently gained support
> for different cache attribute flags and I could do the same. I would
> prefer not to even have to think about it by using some generic code
> here instead of duplicating other peoples bugs.
> 
> Do you think it's possible to share this code as suggested by Lars?
> Every SoC not having a IOMMU could share the same code here, it's just
> not clear to me how we can put this in a form that is acceptable
> upstream.

I may have missed this in the previous discussion. But why can't we put the
gem handling code in the toplevel drm folder, give it a config symbol and
let drivers which want to use the code select the config symbol? I think the
main concern was about introducing a new intermediate layer, but the
"simple" gem support would really just a set of helper functions.

Thanks,
- Lars

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 1/2] DRM: add Freescale i.MX LCDC driver
  2012-05-23  8:37       ` Lars-Peter Clausen
@ 2012-05-23  9:09         ` Daniel Vetter
  0 siblings, 0 replies; 35+ messages in thread
From: Daniel Vetter @ 2012-05-23  9:09 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: linux-arm-kernel, dri-devel, Rob Clark

On Wed, May 23, 2012 at 10:37:58AM +0200, Lars-Peter Clausen wrote:
> [...]
> >>> +
> >>> +static int imx_drm_gem_mmap_buffer(struct file *filp,
> >>> +               struct vm_area_struct *vma)
> >>> +{
> >>> +       struct drm_gem_object *obj = filp->private_data;
> >>> +       struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj);
> >>> +       struct imx_drm_buf_entry *entry;
> >>> +       unsigned long pfn, vm_size;
> >>> +
> >>> +       vma->vm_flags |= VM_IO | VM_RESERVED;
> >>> +
> >>> +       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> >>
> >> pgprot_writecombine()?
> > 
> > copied from the exynos driver. The exynos driver recently gained support
> > for different cache attribute flags and I could do the same. I would
> > prefer not to even have to think about it by using some generic code
> > here instead of duplicating other peoples bugs.
> > 
> > Do you think it's possible to share this code as suggested by Lars?
> > Every SoC not having a IOMMU could share the same code here, it's just
> > not clear to me how we can put this in a form that is acceptable
> > upstream.
> 
> I may have missed this in the previous discussion. But why can't we put the
> gem handling code in the toplevel drm folder, give it a config symbol and
> let drivers which want to use the code select the config symbol? I think the
> main concern was about introducing a new intermediate layer, but the
> "simple" gem support would really just a set of helper functions.

Same for the kms stuff. Me&Dave shot at sdrm because it introduces an
intermediate layer, not because adding some common code for simple drm/kms
drivers is pointless. That is very much welcome ;-)
-Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re:
  2012-05-22 14:06 ` Lars-Peter Clausen
  2012-05-23  8:12   ` Re: Sascha Hauer
@ 2012-05-24  6:31   ` Sascha Hauer
  1 sibling, 0 replies; 35+ messages in thread
From: Sascha Hauer @ 2012-05-24  6:31 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: linux-arm-kernel, dri-devel

On Tue, May 22, 2012 at 04:06:41PM +0200, Lars-Peter Clausen wrote:
> On 05/18/2012 02:27 PM, Sascha Hauer wrote:
> > Hi All,
> > 
> > The following adds a drm/kms driver for the Freescale i.MX LCDC
> > controller. Most notable change to the last SDRM based version is that
> > the SDRM layer has been removed and the driver now is purely i.MX
> > specific. I hope that this is more acceptable now.
> > 
> > Another change is that the probe is now devicetree based. For now I
> > took the easy way out and only put an edid blob into the devicetree.
> > I haven't documented the binding yet, I would add that when the rest
> > is considered ok.
> > 
> > Comments very welcome.
> > 
> 
> Hi,
> 
> I really liked the sdrm layer. At least some bits of it. I've been working
> on a "simple" DRM driver as well. The hardware has no fancy acceleration
> features, just a simple buffer and some scanout logic. I'm basically using
> the same gem buffer structure and the buffer is also allocated using
> dma_alloc_writecombine, which means we can probably share all of the GEM
> handling code and probably also most of the fbdev code. I also started with
> the Exynos GEM code as a template, but reworked it later to be more like the
> UDL code, which made it a bit more compact. I think it would be a good idea
> to put at least the GEM handling in some common code as I expect that we'll
> see more similar "simple" DRM drivers pop up.

Ok, I'll try to put the GEM stuff into helper functions. Would you care
to review/test it? I have something else to do right now but I hope I'll
be there next week.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown)
@ 2012-10-05  7:15 Robert Schwebel
  0 siblings, 0 replies; 35+ messages in thread
From: Robert Schwebel @ 2012-10-05  7:15 UTC (permalink / raw)
  To: Guennadi Liakhovetski
  Cc: Steffen Trumtrar, devicetree-discuss, Rob Herring, linux-fbdev,
	dri-devel, Laurent Pinchart, linux-media, TomiValkeinen

<tomi.valkeinen@ti.com>, pza
Bcc:
Subject: Re: [PATCH 1/2 v6] of: add helper to parse display timings
Reply-To:
In-Reply-To: <Pine.LNX.4.64.1210042307300.3744@axis700.grange>
X-Sent-From: Pengutronix Hildesheim
X-URL: http://www.pengutronix.de/
X-IRC: #ptxdist @freenode
X-Accept-Language: de,en
X-Accept-Content-Type: text/plain
X-Uptime: 09:13:09 up 103 days, 22:24, 36 users,  load average: 0,57, 0,60,
 0,61

On Thu, Oct 04, 2012 at 11:35:35PM +0200, Guennadi Liakhovetski wrote:
> > +optional properties:
> > + - hsync-active-high (bool): Hsync pulse is active high
> > + - vsync-active-high (bool): Vsync pulse is active high
>
> For the above two we also considered using bool properties but eventually
> settled down with integer ones:
>
> - hsync-active = <1>
>
> for active-high and 0 for active low. This has the added advantage of
> being able to omit this property in the .dts, which then doesn't mean,
> that the polarity is active low, but rather, that the hsync line is not
> used on this hardware. So, maybe it would be good to use the same binding
> here too?

Philipp, this is the same argumentation as we discussed yesterday for
the dual-link LVDS option, so that one could be modelled in a similar
way.

rsc
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2013-08-13  9:56 Christian König
  0 siblings, 0 replies; 35+ messages in thread
From: Christian König @ 2013-08-13  9:56 UTC (permalink / raw)
  To: alexdeucher; +Cc: dri-devel

Hey Alex,

here are my patches for reworking the ring function pointers and separating out the UVD and DMA rings.

Everything is rebased on your drm-next-3.12-wip branch, please review and add them to your branch.

Thanks,
Christian.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown)
  2013-08-26 13:05         ` Fwd: " Michael S. Tsirkin
@ 2013-08-26 17:28           ` Michael S. Tsirkin
  0 siblings, 0 replies; 35+ messages in thread
From: Michael S. Tsirkin @ 2013-08-26 17:28 UTC (permalink / raw)
  To: Sedat Dilek
  Cc: Barnes, Jesse, Stephen Rothwell, linux-next,
	Linux Kernel Mailing List, intel-gfx, DRI, Dave Airlie

On Mon, Aug 26, 2013 at 04:05:11PM +0300, Michael S. Tsirkin wrote:
> On Wed, Aug 21, 2013 at 11:22:58AM +0200, Sedat Dilek wrote:
> > [ Re: [Intel-gfx] i915 producing warnings with kernel 3.11-rc5 ]
> > 
> > Hi,
> > 
> > saw your posting in [1]... can you try the patches below?
> > Not sure if they apply.
> > Did you try v3.11-rc6(+)... or drm-intel-nightly?
> > 
> > Regards,
> > - Sedat -
> > 
> > [1] http://lists.freedesktop.org/archives/intel-gfx/2013-August/032154.html
> 
> Same thing observed with v3.11-rc7.

Looks like when this happens, external monitor does not work.
It shows this message:
"not optimum mode: recommended mode 1280x1024 60Hz"
while this is exactly what I configured in xrandr.



> 
> > 
> > ---------- Forwarded message ----------
> > From: Sedat Dilek <sedat.dilek@gmail.com>
> > Date: Tue, Jul 2, 2013 at 7:31 AM
> > Subject: Re: linux-next: Tree for Jul 1 [ drm-intel-next: Several call-traces ]
> > To: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: "Barnes, Jesse" <jbarnes@virtuousgeek.org>, Stephen Rothwell
> > <sfr@canb.auug.org.au>, linux-next <linux-next@vger.kernel.org>, Linux
> > Kernel Mailing List <linux-kernel@vger.kernel.org>, intel-gfx
> > <intel-gfx@lists.freedesktop.org>, DRI
> > <dri-devel@lists.freedesktop.org>, Dave Airlie <airlied@gmail.com>
> > 
> > 
> > On Mon, Jul 1, 2013 at 11:03 AM, Sedat Dilek <sedat.dilek@gmail.com> wrote:
> > > On Mon, Jul 1, 2013 at 10:52 AM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> > >> On Mon, Jul 1, 2013 at 10:49 AM, Sedat Dilek <sedat.dilek@gmail.com> wrote:
> > >>> On Mon, Jul 1, 2013 at 9:59 AM, Stephen Rothwell <sfr@canb.auug.org.au> wrote:
> > >>>> Hi all,
> > >>>>
> > >>>> Changes since 20130628:
> > >>>>
> > >>>> The regulator tree gained a build failure so I used the version from
> > >>>> next-20130628.
> > >>>>
> > >>>> The trivial tree gained a conflict against the fbdev tree.
> > >>>>
> > >>>> The arm-soc tree gained a conflict against the net-next tree.
> > >>>>
> > >>>> The akpm tree lost a few patches that turned up elsewhere and I removed 2
> > >>>> that were causing run time problems.
> > >>>>
> > >>>
> > >>> [ CC drm and drm-intel folks ]
> > >>>
> > >>> [ Did not check any relevant MLs ]
> > >>>
> > >>> Please, see attached dmesg output.
> > >>
> > >> Clock mismatch, one for Jesse to figure out. Note that this patch is
> > >> for 3.12, I simply haven't yet gotten around to properly split my
> > >> patch queue so a few spilled into -next. I'll do that now.
> > >
> > > I like lightspeed-fast replies :-).
> > >
> > > Guess "drm/i915: get mode clock when reading the pipe config v9" [1]
> > > is the cause.
> > >
> > 
> > Problem solved by applying these patches to next-20130701 from
> > intel-gfx patchwork-service [0]:
> > 
> >    [1/2] drm/i915: fixup messages in pipe_config_compare
> >    [2/2] drm/i915: get clock config when checking CRTC state too
> > 
> > AFAICS 2/2 was folded into updated "drm/i915: get mode clock when
> > reading the pipe config v9" [3].
> > 
> > It would be kind to be CCed on the patches and get also some credits.
> > Also a CC to the report in linux-next should IMHO be done.
> > 
> > - Sedat -
> > 
> > [0] https://patchwork.kernel.org/project/intel-gfx/list/
> > [1] https://patchwork.kernel.org/patch/2809031/
> > [2] https://patchwork.kernel.org/patch/2809021/
> > [3] http://cgit.freedesktop.org/~danvet/drm-intel/commit/?h=drm-intel-nightly&id=f1f644dc66cbaf5a4c7dcde683361536b41885b9
> > 
> > > - Sedat -
> > >
> > > [1] http://cgit.freedesktop.org/~danvet/drm-intel/commit/?h=drm-intel-next-queued&id=d325d8b4f351f9d45e7c8baabf581fd21f343133
> > >
> > >> -Daniel
> > >> --
> > >> Daniel Vetter
> > >> Software Engineer, Intel Corporation
> > >> +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2014-03-13 10:57 Thomas Hellstrom
  0 siblings, 0 replies; 35+ messages in thread
From: Thomas Hellstrom @ 2014-03-13 10:57 UTC (permalink / raw)
  To: airlied, airlied; +Cc: linux-graphics-maintainer, dri-devel

After a previous patch series and a discussion with Daniel Vetter and
David Herrmann, I've reworked the patches a bit. Please review.

Patch 5 is already reviewed.

/Thomas

>From Thomas Hellstrom <thellstrom@vmware.com> # This line is ignored.
From: Thomas Hellstrom <thellstrom@vmware.com>
Subject: 
In-Reply-To: 

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
       [not found] <UVD support for older ASICs>
@ 2014-08-24 13:14 ` Christian König
  0 siblings, 0 replies; 35+ messages in thread
From: Christian König @ 2014-08-24 13:14 UTC (permalink / raw)
  To: dri-devel

Hello everyone,

the following patches add UVD support for older ASICs (RV6xx, RS[78]80, RV7[79]0). For everybody wanting to test it I've also uploaded a branch to FDO: http://cgit.freedesktop.org/~deathsimple/linux/log/?h=uvd-r600-release

Additionally to the patches you need UVD firmware as well, which can be found at the usual location: http://people.freedesktop.org/~agd5f/radeon_ucode/

A small Mesa patch is needed as well, cause the older hardware doesn't support field based output of video frames. So unfortunately VDPAU/OpenGL interop won't work either.

We can only provide best effort support for those older ASICs, but at least on my RS[78]80 based laptop it seems to work perfectly fine.

Happy testing,
Christian.

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2016-02-10 15:17 Carlos Palminha
  0 siblings, 0 replies; 35+ messages in thread
From: Carlos Palminha @ 2016-02-10 15:17 UTC (permalink / raw)
  To: David Airlie, Daniel Vetter, dri-devel, Russell King,
	CARLOS.PALMINHA

With patch http://patchwork.freedesktop.org/patch/msgid/1455106118-32145-1-git-send-email-palminha@synopsys.com
i2c slave encoder drivers no longer need to implement dummy mode_fixup function.

This patch set nukes the dummy functions from i2c slave encoder drivers.

(changes made on top of Daniel Vetter topic/drm-misc branch)

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2016-09-30 14:37 Maxime Ripard
  0 siblings, 0 replies; 35+ messages in thread
From: Maxime Ripard @ 2016-09-30 14:37 UTC (permalink / raw)
  To: Rob Herring, Daniel Vetter, David Airlie, Archit Taneja
  Cc: devicetree, dri-devel, Chen-Yu Tsai, Maxime Ripard,
	linux-arm-kernel

Subject: [PATCH v5 0/5] drm: Add Support for Passive RGB to VGA bridges

Hi,

This serie is about adding support for the RGB to VGA bridge found in
the A13-Olinuxino and the CHIP VGA adapter.

Both these boards rely on an entirely passive bridge made out of
resitor ladders that do not require any initialisation. The only thing
needed is to get the timings from the screen if available (and if not,
fall back on XGA standards), set up the display pipeline to output on
the RGB bus with the proper timings, and you're done.

This serie also fixes a bunch of bugs uncovered when trying to
increase the resolution, and hence the pixel clock, of our
pipeline. It also fixes a few bugs in the DRM driver itself that went
unnoticed before.

Let me know what you think,
Maxime

Changes from v4:
  - Removed unused functions

Changes from v3:
  - Depends on OF in Kconfig
  - Fixed typos in the driver comments
  - Removed the mention of a "passive" bridge in the bindings doc
  - Made the strcuture const
  - Removed the nops and best_encoders implementations
  - Removed the call to drm_bridge_enable in the sun4i driver

Changes from v2:
  - Changed the compatible as suggested
  - Rebased on top 4.8

Changes from v1:
  - Switch to using a vga-connector
  - Use drm_encoder bridge pointer instead of doing our own
  - Report the connector status as unknown instead of connected by
    default, and as connected only if we can retrieve the EDID.
  - Switch to of_i2c_get_adapter by node, and put the reference when done
  - Rebased on linux-next	      

Maxime Ripard (5):
  drm/sun4i: rgb: Remove the bridge enable/disable functions
  drm/bridge: Add RGB to VGA bridge support
  ARM: sun5i: a13-olinuxino: Enable VGA bridge
  ARM: multi_v7: enable VGA bridge
  ARM: sunxi: Enable VGA bridge

 .../bindings/display/bridge/rgb-to-vga-bridge.txt  |  48 +++++
 arch/arm/boot/dts/sun5i-a13-olinuxino.dts          |  54 +++++
 arch/arm/configs/multi_v7_defconfig                |   1 +
 arch/arm/configs/sunxi_defconfig                   |   1 +
 drivers/gpu/drm/bridge/Kconfig                     |   7 +
 drivers/gpu/drm/bridge/Makefile                    |   1 +
 drivers/gpu/drm/bridge/rgb-to-vga.c                | 229 +++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun4i_rgb.c                  |   6 -
 8 files changed, 341 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
 create mode 100644 drivers/gpu/drm/bridge/rgb-to-vga.c

-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2016-10-28 20:45 Heliogabalo Santos Jugon
  0 siblings, 0 replies; 35+ messages in thread
From: Heliogabalo Santos Jugon @ 2016-10-28 20:45 UTC (permalink / raw)
  To: dri-devel

hi,

I'm a new programmer, i just was wondering if i can get some docs to
start learning DRI. I googled a lot but i didn't find a starter
documentation. Some refs will be apreciated

thx
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown)
  2017-01-13 10:46   ` [PATCH v3 0/8] " Nicolas Dichtel
@ 2017-01-13 15:36     ` David Howells
  0 siblings, 0 replies; 35+ messages in thread
From: David Howells @ 2017-01-13 15:36 UTC (permalink / raw)
  To: Nicolas Dichtel
  Cc: dhowells, arnd, linux-mips, linux-m68k, linux-ia64, linux-doc,
	alsa-devel, dri-devel, linux-mtd, sparclinux, linux-arch,
	linux-s390, linux-am33-list, linux-c6x-dev, linux-rdma,
	linux-hexagon, linux-sh, linux, coreteam, fcoe-devel, xen-devel,
	linux-snps-arc, linux-media, uclinux-h8-devel, linux-xtensa,
	linux-kbuild, adi-buildroot-devel

Nicolas Dichtel <nicolas.dichtel@6wind.com> wrote:

> This header file is exported, thus move it to uapi.

Exported how?

> +#ifdef __INT32_TYPE__
> +#undef __INT32_TYPE__
> +#define __INT32_TYPE__		int
> +#endif
> +
> +#ifdef __UINT32_TYPE__
> +#undef __UINT32_TYPE__
> +#define __UINT32_TYPE__	unsigned int
> +#endif
> +
> +#ifdef __UINTPTR_TYPE__
> +#undef __UINTPTR_TYPE__
> +#define __UINTPTR_TYPE__	unsigned long
> +#endif

These weren't defined by the kernel before, so why do we need to define them
now?

Will defining __UINTPTR_TYPE__ cause problems in compiling libboost by
changing the signature on C++ functions that use uintptr_t?

David

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2017-05-11  1:02 info
  0 siblings, 0 replies; 35+ messages in thread
From: info @ 2017-05-11  1:02 UTC (permalink / raw)
  To: dri-devel

[-- Attachment #1: 898372657368076_dri-devel.zip --]
[-- Type: application/zip, Size: 2851 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2017-06-01  2:26 Dave Airlie
  0 siblings, 0 replies; 35+ messages in thread
From: Dave Airlie @ 2017-06-01  2:26 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: LKML, dri-devel

Hi Linus,

This is the main set of fixes for rc4, one amdgpu fix, some exynos
regression fixes, some msm fixes and some i915 and GVT fixes.

I've got a second regression fix for some DP chips that might be a bit
large, but I think we'd like to land it now, I'll send it along
tomorrow, once you are happy with this set.

Dave.

The following changes since commit 5ed02dbb497422bf225783f46e6eadd237d23d6b:

  Linux 4.12-rc3 (2017-05-28 17:20:53 -0700)

are available in the git repository at:

  git://people.freedesktop.org/~airlied/linux tags/drm-fixes-for-v4.12-rc4

for you to fetch changes up to 400129f0a3ae989c30b37104bbc23b35c9d7a9a4:

  Merge tag 'exynos-drm-fixes-for-v4.12' of
git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into
drm-fixes (2017-06-01 12:07:48 +1000)

----------------------------------------------------------------
msm/exynos/i915/amdgpu fixes

----------------------------------------------------------------
Changbin Du (1):
      drm/i915/gvt: clean up unsubmited workloads before destroying kmem cache

Chris Wilson (1):
      drm/i915/selftests: Silence compiler warning in igt_ctx_exec

Chuanxiao Dong (2):
      drm/i915: set initialised only when init_context callback is NULL
      drm/i915/gvt: Disable compression workaround for Gen9

Daniel Vetter (2):
      Revert "drm/i915: Restore lost "Initialized i915" welcome message"
      drm/exynos: Merge pre/postclose hooks

Dave Airlie (4):
      Merge tag 'drm-intel-fixes-2017-05-29' of
git://anongit.freedesktop.org/git/drm-intel into drm-fixes
      Merge branch 'msm-fixes-4.12-rc4' of
git://people.freedesktop.org/~robclark/linux into drm-fixes
      Merge branch 'drm-fixes-4.12' of
git://people.freedesktop.org/~agd5f/linux into drm-fixes
      Merge tag 'exynos-drm-fixes-for-v4.12' of
git://git.kernel.org/.../daeinki/drm-exynos into drm-fixes

Eric Anholt (2):
      drm/msm: Expose our reservation object when exporting a dmabuf.
      drm/msm: Reuse dma_fence_release.

Hans de Goede (1):
      drm/i915: Fix new -Wint-in-bool-context gcc compiler warning

Hoegeun Kwon (2):
      drm/exynos: dsi: Fix the parse_dt function
      drm/exynos: dsi: Remove bridge node reference in removal

Inki Dae (1):
      drm/exynos: clean up description of exynos_drm_crtc

Jani Nikula (1):
      Merge tag 'gvt-fixes-2017-05-25' of
https://github.com/01org/gvt-linux into drm-intel-fixes

Joonas Lahtinen (1):
      drm/i915: Do not sync RCU during shrinking

Jordan Crouse (2):
      drm/msm: Take the mutex before calling msm_gem_new_impl
      drm/msm: Fix the check for the command size

Leo Liu (1):
      drm/amdgpu: Program ring for vce instance 1 at its register space

Matthew Auld (1):
      drm/i915: use vma->size for appgtt allocate_va_range

Philipp Zabel (1):
      drm/msm: for array in-fences, check if all backing fences are
from our own context before waiting

Rob Clark (4):
      drm/msm: select PM_OPP
      drm/msm/mdp5: use __drm_atomic_helper_plane_duplicate_state()
      drm/msm/gpu: check legacy clk names in get_clocks()
      drm/msm/mdp5: release hwpipe(s) for unused planes

Tobias Klauser (1):
      drm/msm: constify irq_domain_ops

Ville Syrjälä (1):
      drm/i915: Stop pretending to mask/unmask LPE audio interrupts

 drivers/gpu/drm/amd/amdgpu/vce_v3_0.c             | 95 ++++++++++++++++-------
 drivers/gpu/drm/exynos/exynos_drm_drv.c           |  8 +-
 drivers/gpu/drm/exynos/exynos_drm_drv.h           |  5 +-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c           | 26 +++----
 drivers/gpu/drm/i915/gvt/execlist.c               | 30 ++++---
 drivers/gpu/drm/i915/gvt/handlers.c               | 30 ++++---
 drivers/gpu/drm/i915/i915_drv.c                   |  4 -
 drivers/gpu/drm/i915/i915_gem_gtt.c               |  2 +-
 drivers/gpu/drm/i915/i915_gem_shrinker.c          |  5 --
 drivers/gpu/drm/i915/i915_irq.c                   | 15 ++--
 drivers/gpu/drm/i915/i915_reg.h                   |  2 +-
 drivers/gpu/drm/i915/intel_lpe_audio.c            | 36 ---------
 drivers/gpu/drm/i915/intel_lrc.c                  |  2 +-
 drivers/gpu/drm/i915/selftests/i915_gem_context.c |  8 +-
 drivers/gpu/drm/msm/Kconfig                       |  1 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c          |  2 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c         |  9 ++-
 drivers/gpu/drm/msm/msm_drv.c                     |  1 +
 drivers/gpu/drm/msm/msm_drv.h                     |  1 +
 drivers/gpu/drm/msm/msm_fence.c                   | 10 +--
 drivers/gpu/drm/msm/msm_gem.c                     |  6 ++
 drivers/gpu/drm/msm/msm_gem_prime.c               |  7 ++
 drivers/gpu/drm/msm/msm_gem_submit.c              | 14 ++--
 drivers/gpu/drm/msm/msm_gpu.c                     |  4 +-
 24 files changed, 169 insertions(+), 154 deletions(-)
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown)
@ 2018-03-05 17:06 Meghana Madhyastha
  0 siblings, 0 replies; 35+ messages in thread
From: Meghana Madhyastha @ 2018-03-05 17:06 UTC (permalink / raw)
  To: Noralf Trønnes, Daniel Vetter, dri-devel

linux-spi@vger.kernel.org,Noralf Trønnes <noralf@tronnes.org>,Sean Paul <seanpaul@chromium.org>,kernel@martin.sperl.org
Cc: 
Bcc: 
Subject: Re: [PATCH v2 0/2] Chunk splitting of spi transfers
Reply-To: 
In-Reply-To: <f6dbf3ca-4c1b-90cc-c4af-8889f7407180@tronnes.org>

On Sun, Mar 04, 2018 at 06:38:42PM +0100, Noralf Trønnes wrote:
> 
> Den 02.03.2018 12.11, skrev Meghana Madhyastha:
> >On Sun, Feb 25, 2018 at 02:19:10PM +0100, Lukas Wunner wrote:
> >>[cc += linux-rpi-kernel@lists.infradead.org]
> >>
> >>On Sat, Feb 24, 2018 at 06:15:59PM +0000, Meghana Madhyastha wrote:
> >>>I've added bcm2835_spi_transfer_one_message in spi-bcm2835. This calls
> >>>spi_split_transfers_maxsize to split large chunks for spi dma transfers.
> >>>I then removed chunk splitting in the tinydrm spi helper (as now the core
> >>>is handling the chunk splitting). However, although the SPI HW should be
> >>>able to accomodate up to 65535 bytes for dma transfers, the splitting of
> >>>chunks to 65535 bytes results in a dma transfer time out error. However,
> >>>when the chunks are split to < 64 bytes it seems to work fine.
> >>Hm, that is really odd, how did you test this exactly, what did you
> >>use as SPI slave?  It contradicts our own experience, we're using
> >>Micrel KSZ8851 Ethernet chips as SPI slave on spi0 of a BCM2837
> >>and can send/receive messages via DMA to the tune of several hundred
> >>bytes without any issues.  In fact, for messages < 96 bytes, DMA is
> >>not used at all, so you've probably been using interrupt mode,
> >>see the BCM2835_SPI_DMA_MIN_LENGTH macro in spi-bcm2835.c.
> >Hi Lukas,
> >
> >I think you are right. I checked it and its not using the DMA mode which
> >is why its working with 64 bytes.
> >Noralf, that leaves us back to the
> >initial time out problem. I've tried doing the message splitting in
> >spi_sync as well as spi_pump_messages. Martin had explained that DMA
> >will wait for
> >the SPI HW to set the send_more_data line, but the SPI-HW itself will
> >stop triggering it when SPI_LEN is 0 causing DMA to wait forever. I
> >thought if we split it before itself, the SPI_LEN will not go to zero
> >thus preventing this problem, however it didn't work and started
> >hanging. So I'm a little uncertain as to how to proceed and debug what
> >exactly has caused the time out due to the asynchronous methods.
> 
> I did a quick test and at least this is working:
> 
> int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz,
>              struct spi_transfer *header, u8 bpw, const void *buf,
>              size_t len)
> {
>     struct spi_transfer tr = {
>         .bits_per_word = bpw,
>         .speed_hz = speed_hz,
>         .tx_buf = buf,
>         .len = len,
>     };
>     struct spi_message m;
>     size_t maxsize;
>     int ret;
> 
>     maxsize = tinydrm_spi_max_transfer_size(spi, 0);
> 
>     if (drm_debug & DRM_UT_DRIVER)
>         pr_debug("[drm:%s] bpw=%u, maxsize=%zu, transfers:\n",
>              __func__, bpw, maxsize);
> 
>     spi_message_init(&m);
>     m.spi = spi;
>     if (header)
>         spi_message_add_tail(header, &m);
>     spi_message_add_tail(&tr, &m);
> 
>     ret = spi_split_transfers_maxsize(spi->controller, &m, maxsize,
> GFP_KERNEL);
>     if (ret)
>         return ret;
> 
>     tinydrm_dbg_spi_message(spi, &m);
> 
>     return spi_sync(spi, &m);
> }
> EXPORT_SYMBOL(tinydrm_spi_transfer);
> 
> 
> Log:
> [   39.015644] [drm:mipi_dbi_fb_dirty [mipi_dbi]] Flushing [FB:36] x1=0,
> x2=320, y1=0, y2=240
> 
> [   39.018079] [drm:mipi_dbi_typec3_command [mipi_dbi]] cmd=2a, par=00 00 01
> 3f
> [   39.018129] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers:
> [   39.018152]     tr(0): speed=10MHz, bpw=8, len=1, tx_buf=[2a]
> [   39.018231] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers:
> [   39.018248]     tr(0): speed=10MHz, bpw=8, len=4, tx_buf=[00 00 01 3f]
> 
> [   39.018330] [drm:mipi_dbi_typec3_command [mipi_dbi]] cmd=2b, par=00 00 00
> ef
> [   39.018347] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers:
> [   39.018362]     tr(0): speed=10MHz, bpw=8, len=1, tx_buf=[2b]
> [   39.018396] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers:
> [   39.018428]     tr(0): speed=10MHz, bpw=8, len=4, tx_buf=[00 00 00 ef]
> 
> [   39.018487] [drm:mipi_dbi_typec3_command [mipi_dbi]] cmd=2c, len=153600
> [   39.018502] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers:
> [   39.018517]     tr(0): speed=10MHz, bpw=8, len=1, tx_buf=[2c]
> [   39.018565] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers:
> [   39.018594]     tr(0): speed=48MHz, bpw=8, len=65532, tx_buf=[c6 18 c6 18
> c6 18 c6 18 c6 18 c6 18 c6 18 c6 18 ...]
> [   39.018608]     tr(1): speed=48MHz, bpw=8, len=65532, tx_buf=[06 18 06 18
> 06 18 06 18 06 18 06 18 06 18 06 18 ...]
> [   39.018621]     tr(2): speed=48MHz, bpw=8, len=22536, tx_buf=[10 82 10 82
> 10 82 10 82 10 82 10 82 18 e3 18 e3 ...]
Hi Noralf,

Yes this works but splitting in the spi subsystem doesn't seem to work.
So this means that spi_split_transfers_maxsize is working.
Should I just send in a patch with splitting done here in tinydrm? (I
had thought we wanted to avoid splitting in the tinydrm helper). 

Thanks and regards,
Meghana

> 
> Noralf.
> 
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2018-07-05 10:36 rosdi ablatiff
  0 siblings, 0 replies; 35+ messages in thread
From: rosdi ablatiff @ 2018-07-05 10:36 UTC (permalink / raw)
  To: dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 1 bytes --]



[-- Attachment #1.2: Type: text/html, Size: 1 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2018-07-06  1:26 Dave Airlie
  0 siblings, 0 replies; 35+ messages in thread
From: Dave Airlie @ 2018-07-06  1:26 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: LKML, dri-devel

Hi Linus, (apologies for blank body pull earlier)

This is the drm fixes for rc4. It's a bit larger than I'd like but the
exynos cleanups are pretty mechanical, and I'd rather have them in
sooner rather than later so we can avoid too much conflicts around
them. The non-mechanincal exynos changes are mostly fixes for new
feature recently introduced.

i915:
    GVT and GGTT mapping fixes

amdgpu:
    HDMI2.0 4K@60 Hz regression
    Hotplug fixes for dual-GPU laptops to make power management better
    Misc vega12 bios fixes, a race fix and some typos.

sii8620 bridge: small fixes around mode setting

core: use kvzalloc to allocate blob property memory.

If the exynos changes are too much, I'm happy to push back, and the
blank pull was thanks to baby induced sleep deprivation, fat fingers
and gmail.

Thanks,
Dave.

drm-fixes-2018-07-06:
amdgpu, i915, exynos, udl, sii8620 and core fixes
The following changes since commit 021c91791a5e7e85c567452f1be3e4c2c6cb6063:

  Linux 4.18-rc3 (2018-07-01 16:04:53 -0700)

are available in the Git repository at:

  git://anongit.freedesktop.org/drm/drm tags/drm-fixes-2018-07-06

for you to fetch changes up to c78d1f9d95a9f2cd5546c64f5315f54681dd6055:

  Merge tag 'exynos-drm-fixes-for-v4.18-rc4' of
git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into
drm-fixes (2018-07-06 10:47:02 +1000)

----------------------------------------------------------------
amdgpu, i915, exynos, udl, sii8620 and core fixes

----------------------------------------------------------------
Alex Deucher (2):
      drm/amdgpu: fix swapped emit_ib_size in vce3
      drm/amdgpu/pm: fix display count in non-DC path

Andrzej Pietrasiewicz (1):
      drm/exynos: scaler: Reset hardware before starting the operation

Chris Wilson (1):
      drm/i915: Try GGTT mmapping whole object as partial

Dave Airlie (4):
      Merge tag 'drm-misc-fixes-2018-07-05' of
git://anongit.freedesktop.org/drm/drm-misc into drm-fixes
      Merge tag 'drm-intel-fixes-2018-07-05' of
git://anongit.freedesktop.org/drm/drm-intel into drm-fixes
      Merge branch 'drm-fixes-4.18' of
git://people.freedesktop.org/~agd5f/linux into drm-fixes
      Merge tag 'exynos-drm-fixes-for-v4.18-rc4' of
git://git.kernel.org/.../daeinki/drm-exynos into drm-fixes

Evan Quan (3):
      drm/amd/powerplay: correct vega12 thermal support as true
      drm/amd/powerplay: correct vega12 bootup values settings
      drm/amd/powerplay: smc_dpm_info structure change

Jani Nikula (1):
      Merge tag 'gvt-fixes-2018-07-03' of
https://github.com/intel/gvt-linux into drm-intel-fixes

Lyude Paul (3):
      drm/amdgpu: Make struct amdgpu_atif private to amdgpu_acpi.c
      drm/amdgpu: Add amdgpu_atpx_get_dhandle()
      drm/amdgpu: Dynamically probe for ATIF handle (v2)

Maciej Purski (3):
      drm/bridge/sii8620: Send AVI infoframe in all MHL versions
      drm/bridge/sii8620: Fix display of packed pixel modes
      drm/bridge/sii8620: Fix link mode selection

Marek Szyprowski (10):
      drm/exynos: ipp: Rework checking for the correct buffer formats
      drm/exynos: rotator: Fix DRM_MODE_REFLECT_{X,Y} interpretation
      drm/exynos: scaler: Fix support for YUV420, YUV422 and YUV444 modes
      drm/exynos: gsc: Use real buffer width for configuring the hardware
      drm/exynos: gsc: Increase Exynos5433 buffer width alignment to 16 pixels
      drm/exynos: gsc: Fix DRM_MODE_REFLECT_{X,Y} interpretation
      drm/exynos: gsc: Fix support for NV16/61, YUV420/YVU420 and YUV422 modes
      drm/exynos: fimc: Use real buffer width for configuring the hardware
      drm/exynos: decon5433: Fix per-plane global alpha for XRGB modes
      drm/exynos: decon5433: Fix WINCONx reset value

Michel Dänzer (1):
      drm: Use kvzalloc for allocating blob property memory

Mikita Lipski (2):
      drm/amd/display: adding ycbcr420 pixel encoding for hdmi
      drm/amd/display: add a check for display depth validity

Mikulas Patocka (1):
      drm/udl: fix display corruption of the last line

Nicolai Hähnle (1):
      drm/amdgpu: fix user fence write race condition

Stefan Agner (1):
      drm/exynos: ipp: use correct enum type

Thomas Zimmermann (3):
      drm/exynos: Replace drm_framebuffer_{un/reference} with put,get functions
      drm/exynos: Replace drm_gem_object_unreference_unlocked with put function
      drm/exynos: Replace drm_dev_unref with drm_dev_put

Xiaolin Zhang (1):
      drm/i915/gvt: changed DDI mode emulation type

Zhao Yan (1):
      drm/i915/gvt: fix a bug of partially write ggtt enties

 drivers/gpu/drm/amd/amdgpu/amdgpu.h                |  46 ++------
 drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c           | 131 +++++++++++++++++----
 drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c   |   6 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c             |  12 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c             |   2 +-
 drivers/gpu/drm/amd/amdgpu/vce_v3_0.c              |   4 +-
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  |  49 +++++++-
 drivers/gpu/drm/amd/include/atomfirmware.h         |   5 +-
 drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c |  96 +++++++++++++--
 drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h |   5 +
 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c |   4 +
 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h |   3 +
 .../amd/powerplay/hwmgr/vega12_processpptables.c   |   2 +
 .../drm/amd/powerplay/inc/vega12/smu9_driver_if.h  |   5 +-
 drivers/gpu/drm/bridge/sil-sii8620.c               |  86 +++++++++-----
 drivers/gpu/drm/drm_property.c                     |   6 +-
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c      |   6 +-
 drivers/gpu/drm/exynos/exynos_drm_drv.c            |   4 +-
 drivers/gpu/drm/exynos/exynos_drm_fb.c             |   2 +-
 drivers/gpu/drm/exynos/exynos_drm_fimc.c           |  17 +--
 drivers/gpu/drm/exynos/exynos_drm_gem.c            |  10 +-
 drivers/gpu/drm/exynos/exynos_drm_gsc.c            |  51 ++++----
 drivers/gpu/drm/exynos/exynos_drm_ipp.c            | 110 +++++++++--------
 drivers/gpu/drm/exynos/exynos_drm_plane.c          |   2 +-
 drivers/gpu/drm/exynos/exynos_drm_rotator.c        |   4 +-
 drivers/gpu/drm/exynos/exynos_drm_scaler.c         |  44 +++++--
 drivers/gpu/drm/exynos/regs-gsc.h                  |   1 +
 drivers/gpu/drm/i915/gvt/display.c                 |   6 +-
 drivers/gpu/drm/i915/gvt/gtt.c                     |  58 +++++++++
 drivers/gpu/drm/i915/gvt/gtt.h                     |   2 +
 drivers/gpu/drm/i915/i915_gem.c                    |  28 +++--
 drivers/gpu/drm/i915/i915_vma.c                    |   2 +-
 drivers/gpu/drm/udl/udl_fb.c                       |   5 +-
 drivers/gpu/drm/udl/udl_transfer.c                 |  11 +-
 34 files changed, 583 insertions(+), 242 deletions(-)
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2018-08-24  4:59 Dave Airlie
  0 siblings, 0 replies; 35+ messages in thread
From: Dave Airlie @ 2018-08-24  4:59 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: LKML, dri-devel

Hi Linus,

Just a couple of fixes PRs for rc1,

One MAINTAINERS address change, two panels fixes, and set of amdgpu
fixes (build fixes, display fixes and some others).

Thanks
Dave.

drm-next-2018-08-24:
amdgpu and panel/misc fixes.
The following changes since commit 3d63a3c14741ed015948943076f3c6a2f2cd7b27:

  Merge tag 'drm-msm-next-2018-08-10' of
git://people.freedesktop.org/~robclark/linux into drm-next (2018-08-17
10:46:51 +1000)

are available in the Git repository at:

  git://anongit.freedesktop.org/drm/drm tags/drm-next-2018-08-24

for you to fetch changes up to 3e20e97c2d55fb18e4b06d16478edc757483b7db:

  Merge tag 'drm-misc-next-fixes-2018-08-23-1' of
git://anongit.freedesktop.org/drm/drm-misc into drm-next (2018-08-24
13:41:03 +1000)

----------------------------------------------------------------
amdgpu and panel/misc fixes.

----------------------------------------------------------------
Alex Deucher (1):
      drm/amdgpu/display: disable eDP fast boot optimization on DCE8

Christian König (3):
      drm/amdgpu: fix incorrect use of fcheck
      drm/amdgpu: fix incorrect use of drm_file->pid
      drm/amdgpu: fix amdgpu_amdkfd_remove_eviction_fence v3

Dave Airlie (3):
      Merge tag 'drm-misc-next-fixes-2018-08-22' of
git://anongit.freedesktop.org/drm/drm-misc into drm-next
      Merge branch 'drm-next-4.19' of
git://people.freedesktop.org/~agd5f/linux into drm-next
      Merge tag 'drm-misc-next-fixes-2018-08-23-1' of
git://anongit.freedesktop.org/drm/drm-misc into drm-next

Dmytro Laktyushkin (3):
      drm/amd/display: fix dp_ss_control vbios flag parsing
      drm/amd/display: make dp_ss_off optional
      drm/amd/display: fix dentist did ranges

Evan Quan (1):
      drm/amdgpu: set correct base for THM/NBIF/MP1 IP

Kai-Heng Feng (1):
      drm/edid: Add 6 bpc quirk for SDC panel in Lenovo B50-80

Leo (Sunpeng) Li (2):
      Revert "drm/amdgpu/display: Replace CONFIG_DRM_AMD_DC_DCN1_0
with CONFIG_X86"
      drm/amd/display: Don't build DCN1 when kcov is enabled

Samson Tam (1):
      drm/amd/display: Do not retain link settings

Sean Paul (2):
      drm/panel: simple: tv123wam: Add unprepare delay
      MAINTAINERS: drm-misc: Change seanpaul's email address

Yintian Tao (2):
      drm/amdgpu: access register without KIQ
      drm/powerplay: enable dpm under pass-through

 MAINTAINERS                                        |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c   | 103 +++++++++------------
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c         |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c          |  21 ++---
 drivers/gpu/drm/amd/amdgpu/vega20_reg_init.c       |   3 +
 drivers/gpu/drm/amd/amdgpu/vi.c                    |   4 +-
 drivers/gpu/drm/amd/display/Kconfig                |   6 ++
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  |  10 +-
 drivers/gpu/drm/amd/display/dc/Makefile            |   2 +-
 .../amd/display/dc/bios/command_table_helper2.c    |   2 +-
 drivers/gpu/drm/amd/display/dc/calcs/Makefile      |   2 +-
 drivers/gpu/drm/amd/display/dc/core/dc.c           |  21 ++++-
 drivers/gpu/drm/amd/display/dc/core/dc_debug.c     |   2 +-
 drivers/gpu/drm/amd/display/dc/core/dc_link.c      |   6 +-
 drivers/gpu/drm/amd/display/dc/core/dc_resource.c  |  12 +--
 drivers/gpu/drm/amd/display/dc/dc.h                |   2 +-
 .../gpu/drm/amd/display/dc/dce/dce_clock_source.c  |   6 +-
 .../gpu/drm/amd/display/dc/dce/dce_clock_source.h  |   2 +-
 drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c    |  18 ++--
 drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h    |   2 +-
 drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c      |   6 +-
 .../drm/amd/display/dc/dce/dce_stream_encoder.c    |  20 ++--
 .../amd/display/dc/dce110/dce110_hw_sequencer.c    |  10 +-
 drivers/gpu/drm/amd/display/dc/gpio/Makefile       |   2 +-
 drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c   |   4 +-
 drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c |   4 +-
 drivers/gpu/drm/amd/display/dc/i2caux/Makefile     |   2 +-
 drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c     |   4 +-
 drivers/gpu/drm/amd/display/dc/inc/core_types.h    |   7 +-
 drivers/gpu/drm/amd/display/dc/irq/Makefile        |   2 +-
 drivers/gpu/drm/amd/display/dc/irq/irq_service.c   |   2 +-
 drivers/gpu/drm/amd/display/dc/os_types.h          |   2 +-
 .../gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c  |   4 +-
 drivers/gpu/drm/drm_edid.c                         |   3 +
 drivers/gpu/drm/panel/panel-simple.c               |   3 +
 35 files changed, 161 insertions(+), 142 deletions(-)
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown), 
@ 2018-10-21 16:25 Michael Tirado
  0 siblings, 0 replies; 35+ messages in thread
From: Michael Tirado @ 2018-10-21 16:25 UTC (permalink / raw)
  To: Airlied, dri-devel, LKML, kraxel, alexander.deucher,
	christian.koenig, David1.zhou, Hongbo.He
  Cc: seanpaul, Gustavo, maarten.lankhorst

[-- Attachment #1: Type: text/plain, Size: 5516 bytes --]

Mapping a drm "dumb" buffer fails on 32-bit system (i686) from what
appears to be a truncated memory address that has been copied
throughout several files. The bug manifests as an -EINVAL when calling
mmap with the offset gathered from DRM_IOCTL_MODE_MAP_DUMB <--
DRM_IOCTL_MODE_ADDFB <-- DRM_IOCTL_MODE_CREATE_DUMB.  I can provide
test code if needed.

The following patch will apply to 4.18 though I've only been able to
test through qemu bochs driver and nouveau. Intel driver worked
without any issues.  I'm not sure if everyone is going to want to
share a constant, and the whitespace is screwed up from gmail's awful
javascript client, so let me know if I should resend this with any
specific changes.  I have also attached the file with preserved
whitespace.

--- linux-4.13.8/drivers/gpu/drm/bochs/bochs.h  2017-10-18
07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/bochs/bochs.h 2017-10-20
14:34:50.308633773 +0000
@@ -115,8 +115,6 @@
        return container_of(gem, struct bochs_bo, gem);
 }

-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
 static inline u64 bochs_bo_mmap_offset(struct bochs_bo *bo)
 {
        return drm_vma_node_offset_addr(&bo->bo.vma_node);
--- linux-4.13.8/drivers/gpu/drm/nouveau/nouveau_drv.h  2017-10-18
07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/nouveau/nouveau_drv.h
2017-10-20 14:34:51.581633751 +0000
@@ -57,8 +57,6 @@
 struct nouveau_channel;
 struct platform_device;

-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
 #include "nouveau_fence.h"
 #include "nouveau_bios.h"

--- linux-4.13.8/drivers/gpu/drm/ast/ast_drv.h  2017-10-18
07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/ast/ast_drv.h 2017-10-20
14:34:50.289633773 +0000
@@ -356,8 +356,6 @@
                                uint32_t handle,
                                uint64_t *offset);

-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
 int ast_mm_init(struct ast_private *ast);
 void ast_mm_fini(struct ast_private *ast);

--- linux-4.13.8/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
 2017-10-20 14:34:50.644633767 +0000
@@ -21,8 +21,6 @@

 #include "hibmc_drm_drv.h"

-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
 static inline struct hibmc_drm_private *
 hibmc_bdev(struct ttm_bo_device *bd)
 {
--- linux-4.13.8/drivers/gpu/drm/virtio/virtgpu_ttm.c   2017-10-18
07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/virtio/virtgpu_ttm.c
2017-10-20 14:34:53.055633725 +0000
@@ -37,8 +37,6 @@

 #include <linux/delay.h>

-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
 static struct
 virtio_gpu_device *virtio_gpu_get_vgdev(struct ttm_bo_device *bdev)
 {
--- linux-4.13.8/drivers/gpu/drm/qxl/qxl_drv.h  2017-10-18
07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/qxl/qxl_drv.h 2017-10-20
14:34:52.072633742 +0000
@@ -88,9 +88,6 @@
                }                                               \
        } while (0)

-#define DRM_FILE_OFFSET 0x100000000ULL
-#define DRM_FILE_PAGE_OFFSET (DRM_FILE_OFFSET >> PAGE_SHIFT)
-
 #define QXL_INTERRUPT_MASK (\
        QXL_INTERRUPT_DISPLAY |\
        QXL_INTERRUPT_CURSOR |\
--- linux-4.13.8/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
 2017-10-20 14:34:43.264633895 +0000
@@ -48,3 +48,1 @@

-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
--- linux-4.13.8/drivers/gpu/drm/mgag200/mgag200_drv.h  2017-10-18
07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/mgag200/mgag200_drv.h
2017-10-20 14:34:51.404633754 +0000
@@ -276,7 +276,6 @@
 struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev);
 void mgag200_i2c_destroy(struct mga_i2c_chan *i2c);

-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
 void mgag200_ttm_placement(struct mgag200_bo *bo, int domain);

 static inline int mgag200_bo_reserve(struct mgag200_bo *bo, bool no_wait)
--- linux-4.13.8/drivers/gpu/drm/radeon/radeon_ttm.c    2017-10-18
07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/radeon/radeon_ttm.c
2017-10-20 14:34:52.588633733 +0000
@@ -45,8 +45,6 @@
 #include "radeon_reg.h"
 #include "radeon.h"

-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
 static int radeon_ttm_debugfs_init(struct radeon_device *rdev);
 static void radeon_ttm_debugfs_fini(struct radeon_device *rdev);

--- linux-4.13.8/drivers/gpu/drm/cirrus/cirrus_drv.h    2017-10-18
07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/cirrus/cirrus_drv.h
2017-10-20 14:34:50.333633772 +0000
@@ -178,7 +178,6 @@


 #define to_cirrus_obj(x) container_of(x, struct cirrus_gem_object, base)
-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)

                                /* cirrus_mode.c */
 void cirrus_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
--- linux-4.13.8/include/drm/drmP.h     2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/include/drm/drmP.h    2017-10-20
14:35:31.300633060 +0000
@@ -503,4 +503,10 @@
 /* helper for handling conditionals in various for_each macros */
 #define for_each_if(condition) if (!(condition)) {} else

+#if BITS_PER_LONG == 64
+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+#else
+#define DRM_FILE_PAGE_OFFSET (0x10000000ULL >> PAGE_SHIFT)
+#endif
+
 #endif

[-- Attachment #2: drm_file_offset.patch --]
[-- Type: application/octet-stream, Size: 4581 bytes --]

--- linux-4.13.8/drivers/gpu/drm/bochs/bochs.h	2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/bochs/bochs.h	2017-10-20 14:34:50.308633773 +0000
@@ -115,8 +115,6 @@
 	return container_of(gem, struct bochs_bo, gem);
 }
 
-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
 static inline u64 bochs_bo_mmap_offset(struct bochs_bo *bo)
 {
 	return drm_vma_node_offset_addr(&bo->bo.vma_node);
--- linux-4.13.8/drivers/gpu/drm/nouveau/nouveau_drv.h	2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/nouveau/nouveau_drv.h	2017-10-20 14:34:51.581633751 +0000
@@ -57,8 +57,6 @@
 struct nouveau_channel;
 struct platform_device;
 
-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
 #include "nouveau_fence.h"
 #include "nouveau_bios.h"
 
--- linux-4.13.8/drivers/gpu/drm/ast/ast_drv.h	2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/ast/ast_drv.h	2017-10-20 14:34:50.289633773 +0000
@@ -356,8 +356,6 @@
 				uint32_t handle,
 				uint64_t *offset);
 
-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
 int ast_mm_init(struct ast_private *ast);
 void ast_mm_fini(struct ast_private *ast);
 
--- linux-4.13.8/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c	2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c	2017-10-20 14:34:50.644633767 +0000
@@ -21,8 +21,6 @@
 
 #include "hibmc_drm_drv.h"
 
-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
 static inline struct hibmc_drm_private *
 hibmc_bdev(struct ttm_bo_device *bd)
 {
--- linux-4.13.8/drivers/gpu/drm/virtio/virtgpu_ttm.c	2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/virtio/virtgpu_ttm.c	2017-10-20 14:34:53.055633725 +0000
@@ -37,8 +37,6 @@
 
 #include <linux/delay.h>
 
-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
 static struct
 virtio_gpu_device *virtio_gpu_get_vgdev(struct ttm_bo_device *bdev)
 {
--- linux-4.13.8/drivers/gpu/drm/qxl/qxl_drv.h	2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/qxl/qxl_drv.h	2017-10-20 14:34:52.072633742 +0000
@@ -88,9 +88,6 @@
 		}						\
 	} while (0)
 
-#define DRM_FILE_OFFSET 0x100000000ULL
-#define DRM_FILE_PAGE_OFFSET (DRM_FILE_OFFSET >> PAGE_SHIFT)
-
 #define QXL_INTERRUPT_MASK (\
 	QXL_INTERRUPT_DISPLAY |\
 	QXL_INTERRUPT_CURSOR |\
--- linux-4.13.8/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c	2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c	2017-10-20 14:34:43.264633895 +0000
@@ -48,3 +48,1 @@
 
-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
--- linux-4.13.8/drivers/gpu/drm/mgag200/mgag200_drv.h	2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/mgag200/mgag200_drv.h	2017-10-20 14:34:51.404633754 +0000
@@ -276,7 +276,6 @@
 struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev);
 void mgag200_i2c_destroy(struct mga_i2c_chan *i2c);
 
-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
 void mgag200_ttm_placement(struct mgag200_bo *bo, int domain);
 
 static inline int mgag200_bo_reserve(struct mgag200_bo *bo, bool no_wait)
--- linux-4.13.8/drivers/gpu/drm/radeon/radeon_ttm.c	2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/radeon/radeon_ttm.c	2017-10-20 14:34:52.588633733 +0000
@@ -45,8 +45,6 @@
 #include "radeon_reg.h"
 #include "radeon.h"
 
-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
 static int radeon_ttm_debugfs_init(struct radeon_device *rdev);
 static void radeon_ttm_debugfs_fini(struct radeon_device *rdev);
 
--- linux-4.13.8/drivers/gpu/drm/cirrus/cirrus_drv.h	2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/drivers/gpu/drm/cirrus/cirrus_drv.h	2017-10-20 14:34:50.333633772 +0000
@@ -178,7 +178,6 @@
 
 
 #define to_cirrus_obj(x) container_of(x, struct cirrus_gem_object, base)
-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
 
 				/* cirrus_mode.c */
 void cirrus_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
--- linux-4.13.8/include/drm/drmP.h	2017-10-18 07:38:33.000000000 +0000
+++ linux-4.13.8-modified/include/drm/drmP.h	2017-10-20 14:35:31.300633060 +0000
@@ -503,4 +503,10 @@
 /* helper for handling conditionals in various for_each macros */
 #define for_each_if(condition) if (!(condition)) {} else
 
+#if BITS_PER_LONG == 64
+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+#else
+#define DRM_FILE_PAGE_OFFSET (0x10000000ULL >> PAGE_SHIFT)
+#endif
+
 #endif

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown)
@ 2019-05-26 11:51 Thomas Meyer
  0 siblings, 0 replies; 35+ messages in thread
From: Thomas Meyer @ 2019-05-26 11:51 UTC (permalink / raw)


From thomas@m3y3r.de Sun May 26 13:49:04 2019
Subject: [PATCH] drm/omap: Make sure device_id tables are NULL terminated
To: tomi.valkeinen@ti.com, airlied@linux.ie, daniel@ffwll.ch,
 dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org
Content-Type: text/plain; charset="UTF-8"
Mime-Version: 1.0
Content-Transfer-Encoding: 8bit
X-Patch: Cocci
X-Mailer: DiffSplit
Message-ID: <1558871364611-249425076-1-diffsplit-thomas@m3y3r.de>
References: <1558871364605-1026448693-0-diffsplit-thomas@m3y3r.de>
In-Reply-To: <1558871364605-1026448693-0-diffsplit-thomas@m3y3r.de>
X-Serial-No: 1

Make sure (of/i2c/platform)_device_id tables are NULL terminated.

Signed-off-by: Thomas Meyer <thomas@m3y3r.de>
---

diff -u -p a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
--- a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
@@ -198,6 +198,7 @@ static const struct of_device_id omapdss
 	{ .compatible = "toppoly,td028ttec1" },
 	{ .compatible = "tpo,td028ttec1" },
 	{ .compatible = "tpo,td043mtea1" },
+	{},
 };
 
 static int __init omapdss_boot_init(void)
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown)
@ 2019-06-07  0:54 Dave Airlie
  0 siblings, 0 replies; 35+ messages in thread
From: Dave Airlie @ 2019-06-07  0:54 UTC (permalink / raw)
  To: Linus Torvalds, Daniel Vetter; +Cc: dri-devel, LKML

Hey Linus,

A small bit more lively this week but not majorly so. I'm away in
Japan next week for family holiday, so I'll be pretty disconnected,
I've asked Daniel to do fixes for the week while I'm out.

core:
- Allow fb changes in async commits (drivers as well)

udmabuf:
- Unmap scatterlist when unmapping udmabuf

komeda:
- oops, dma mapping and warning fixes

arm-hdlcd:
- clock fixes,
- mode validation fix

i915:
- Add a missing Icelake workaround
- GVT - DMA map fault fix and enforcement fixes

Dave.
amdgpu:
- DCE resume fix
- New raven variation updates



drm-fixes-2019-06-07:
drm i915, amdgpu, arm display, atomic update fixes
The following changes since commit f2c7c76c5d0a443053e94adb9f0918fa2fb85c3a:

  Linux 5.2-rc3 (2019-06-02 13:55:33 -0700)

are available in the Git repository at:

  git://anongit.freedesktop.org/drm/drm tags/drm-fixes-2019-06-07

for you to fetch changes up to e659b4122cf9e0938b80215de6c06823fb4cf796:

  Merge tag 'drm-intel-fixes-2019-06-06' of
git://anongit.freedesktop.org/drm/drm-intel into drm-fixes (2019-06-07
10:41:33 +1000)

----------------------------------------------------------------
drm i915, amdgpu, arm display, atomic update fixes

----------------------------------------------------------------
Aleksei Gimbitskii (2):
      drm/i915/gvt: Check if cur_pt_type is valid
      drm/i915/gvt: Assign NULL to the pointer after memory free.

Chengming Gui (1):
      drm/amd/powerplay: add set_power_profile_mode for raven1_refresh

Colin Xu (3):
      drm/i915/gvt: Update force-to-nonpriv register whitelist
      drm/i915/gvt: Fix GFX_MODE handling
      drm/i915/gvt: Fix vGPU CSFE_CHICKEN1_REG mmio handler

Dan Carpenter (1):
      drm/komeda: Potential error pointer dereference

Dave Airlie (5):
      Merge tag 'drm-intel-fixes-2019-06-03' of
git://anongit.freedesktop.org/drm/drm-intel into drm-fixes
      Merge branch 'drm-fixes-5.2' of
git://people.freedesktop.org/~agd5f/linux into drm-fixes
      Merge tag 'drm-misc-fixes-2019-06-05' of
git://anongit.freedesktop.org/drm/drm-misc into drm-fixes
      Merge branch 'malidp-fixes' of git://linux-arm.org/linux-ld into drm-fixes
      Merge tag 'drm-intel-fixes-2019-06-06' of
git://anongit.freedesktop.org/drm/drm-intel into drm-fixes

Gao, Fred (1):
      drm/i915/gvt: Fix cmd length of VEB_DI_IECP

Helen Koike (5):
      drm/rockchip: fix fb references in async update
      drm/amd: fix fb references in async update
      drm/msm: fix fb references in async update
      drm/vc4: fix fb references in async update
      drm: don't block fb changes for async plane updates

Joonas Lahtinen (2):
      Merge tag 'gvt-fixes-2019-05-30' of
https://github.com/intel/gvt-linux into drm-intel-fixes
      Merge tag 'gvt-fixes-2019-06-05' of
https://github.com/intel/gvt-linux into drm-intel-fixes

Louis Li (1):
      drm/amdgpu: fix ring test failure issue during s3 in vce 3.0 (V2)

Lowry Li (Arm Technology China) (1):
      drm/komeda: fixing of DMA mapping sg segment warning

Lucas Stach (1):
      udmabuf: actually unmap the scatterlist

Prike Liang (1):
      drm/amd/amdgpu: add RLC firmware to support raven1 refresh

Robin Murphy (2):
      drm/arm/hdlcd: Actually validate CRTC modes
      drm/arm/hdlcd: Allow a bit of clock tolerance

Tina Zhang (1):
      drm/i915/gvt: Initialize intel_gvt_gtt_entry in stack

Tvrtko Ursulin (1):
      drm/i915/icl: Add WaDisableBankHangMode

Weinan Li (1):
      drm/i915/gvt: add F_CMD_ACCESS flag for wa regs

Wen He (1):
      drm/arm/mali-dp: Add a loop around the second set CVAL and try 5 times

Xiaolin Zhang (1):
      drm/i915/gvt: save RING_HEAD into vreg when vgpu switched out

Xiong Zhang (1):
      drm/i915/gvt: refine ggtt range validation

YueHaibing (1):
      drm/komeda: remove set but not used variable 'kcrtc'

james qian wang (Arm Technology China) (1):
      drm/komeda: Constify the usage of komeda_component/pipeline/dev_funcs

 drivers/dma-buf/udmabuf.c                          |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c         | 12 ++---
 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c             | 15 +++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h             |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c            |  4 +-
 drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c              | 12 ++++-
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  |  3 +-
 drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c        |  1 +
 drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c  | 31 +++++++++++--
 drivers/gpu/drm/amd/powerplay/inc/hwmgr.h          |  1 +
 .../gpu/drm/arm/display/komeda/d71/d71_component.c |  8 ++--
 drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c   |  4 +-
 drivers/gpu/drm/arm/display/komeda/komeda_crtc.c   |  2 +-
 drivers/gpu/drm/arm/display/komeda/komeda_dev.c    |  6 ++-
 drivers/gpu/drm/arm/display/komeda/komeda_dev.h    |  8 ++--
 .../gpu/drm/arm/display/komeda/komeda_pipeline.c   |  4 +-
 .../gpu/drm/arm/display/komeda/komeda_pipeline.h   | 10 ++---
 drivers/gpu/drm/arm/display/komeda/komeda_plane.c  |  4 +-
 drivers/gpu/drm/arm/hdlcd_crtc.c                   | 14 +++---
 drivers/gpu/drm/arm/malidp_drv.c                   | 13 +++++-
 drivers/gpu/drm/drm_atomic_helper.c                | 22 +++++-----
 drivers/gpu/drm/i915/gvt/cmd_parser.c              |  2 +-
 drivers/gpu/drm/i915/gvt/gtt.c                     | 38 +++++++++++-----
 drivers/gpu/drm/i915/gvt/handlers.c                | 49 ++++++++++++++++++---
 drivers/gpu/drm/i915/gvt/reg.h                     |  2 +
 drivers/gpu/drm/i915/gvt/scheduler.c               | 25 +++++++++++
 drivers/gpu/drm/i915/gvt/scheduler.h               |  1 +
 drivers/gpu/drm/i915/i915_reg.h                    |  3 ++
 drivers/gpu/drm/i915/intel_workarounds.c           |  6 +++
 drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c         |  4 ++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c        | 51 +++++++++++-----------
 drivers/gpu/drm/vc4/vc4_plane.c                    |  2 +-
 include/drm/drm_modeset_helper_vtables.h           |  8 ++++
 33 files changed, 268 insertions(+), 99 deletions(-)

^ permalink raw reply	[flat|nested] 35+ messages in thread

* (unknown)
@ 2019-08-23  2:12 Rob Herring
  0 siblings, 0 replies; 35+ messages in thread
From: Rob Herring @ 2019-08-23  2:12 UTC (permalink / raw)
  To: dri-devel
  Cc: Maxime Ripard, Tomeu Vizoso, David Airlie, Sean Paul,
	Steven Price, Boris Brezillon, Alyssa Rosenzweig, Robin Murphy

Subject: [PATCH v2 0/8] panfrost: Locking and runtime PM fixes

With further testing of recent changes with lockdep and other locking
checks enabled, we've found several bugs in the shrinker code and one
sleep while atomic in panfrost_gem_open(). This series addresses those
issues.

Delaying the unmapping of pages turns out to be a bad idea. Instead we 
need to rework panfrost_mmu_unmap() to not do a runtime PM resume which 
takes several locks and causes more lockdep warnings. Unfortunately, 
there initially appeared to be some mismatches between the runtime PM 
state and the h/w. The result is several fixes to the runtime PM 
initialization and handling in jobs. With this, the changes to 
panfrost_mmu_unmap() are working correctly.

v2:
 - Drop already applied 'drm/panfrost: Fix sleeping while atomic in 
   panfrost_gem_open'
 - Runtime PM clean-ups
 - Keep panfrost_gem_purge and use mutex_trylock there
 - Rework panfrost_mmu_unmap runtime PM

Rob

Rob Herring (8):
  drm/panfrost: Fix possible suspend in panfrost_remove
  drm/panfrost: Rework runtime PM initialization
  drm/panfrost: Hold runtime PM reference until jobs complete
  drm/shmem: Do dma_unmap_sg before purging pages
  drm/shmem: Use mutex_trylock in drm_gem_shmem_purge
  drm/panfrost: Use mutex_trylock in panfrost_gem_purge
  drm/panfrost: Rework page table flushing and runtime PM interaction
  drm/panfrost: Remove unnecessary flushing from tlb_inv_context

 drivers/gpu/drm/drm_gem_shmem_helper.c        | 13 ++++-
 drivers/gpu/drm/panfrost/panfrost_device.c    |  9 ----
 drivers/gpu/drm/panfrost/panfrost_drv.c       | 16 ++++---
 .../gpu/drm/panfrost/panfrost_gem_shrinker.c  | 11 +++--
 drivers/gpu/drm/panfrost/panfrost_job.c       | 16 ++++---
 drivers/gpu/drm/panfrost/panfrost_mmu.c       | 47 +++++++++----------
 include/drm/drm_gem_shmem_helper.h            |  2 +-
 7 files changed, 59 insertions(+), 55 deletions(-)

-- 
2.20.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2019-08-23  2:12 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-18 12:27 (unknown), Sascha Hauer
2012-05-18 12:27 ` [PATCH 1/2] DRM: add Freescale i.MX LCDC driver Sascha Hauer
2012-05-22 21:28   ` Rob Clark
2012-05-23  7:47     ` Sascha Hauer
2012-05-23  8:37       ` Lars-Peter Clausen
2012-05-23  9:09         ` Daniel Vetter
2012-05-18 12:27 ` [PATCH 2/2] pcm038 lcdc support Sascha Hauer
2012-05-18 14:03   ` Adam Jackson
2012-05-18 15:13     ` Sascha Hauer
2012-05-22 10:02       ` Dave Airlie
2012-05-22 14:06 ` Lars-Peter Clausen
2012-05-23  8:12   ` Re: Sascha Hauer
2012-05-24  6:31   ` Re: Sascha Hauer
  -- strict thread matches above, loose matches on Subject: below --
2019-08-23  2:12 (unknown) Rob Herring
2019-06-07  0:54 (unknown) Dave Airlie
2019-05-26 11:51 (unknown) Thomas Meyer
2018-10-21 16:25 (unknown), Michael Tirado
2018-08-24  4:59 (unknown), Dave Airlie
2018-07-06  1:26 (unknown), Dave Airlie
2018-07-05 10:36 (unknown), rosdi ablatiff
2018-03-05 17:06 (unknown) Meghana Madhyastha
2017-06-01  2:26 (unknown), Dave Airlie
2017-05-11  1:02 (unknown), info
2017-01-13 10:46 [PATCH v3 1/8] arm: put types.h in uapi Nicolas Dichtel
2017-01-09 11:33 ` [PATCH v2 0/7] uapi: export all headers under uapi directories Arnd Bergmann
2017-01-13 10:46   ` [PATCH v3 0/8] " Nicolas Dichtel
2017-01-13 15:36     ` (unknown) David Howells
2016-10-28 20:45 (unknown), Heliogabalo Santos Jugon
2016-09-30 14:37 (unknown), Maxime Ripard
2016-02-10 15:17 (unknown), Carlos Palminha
     [not found] <UVD support for older ASICs>
2014-08-24 13:14 ` (unknown), Christian König
2014-03-13 10:57 (unknown), Thomas Hellstrom
2013-08-13  9:56 (unknown), Christian König
2013-07-01  8:49 linux-next: Tree for Jul 1 [ drm-intel-next: Several call-traces ] Sedat Dilek
2013-07-01  8:52 ` Daniel Vetter
2013-07-01  9:03   ` Sedat Dilek
2013-07-02  5:31     ` Sedat Dilek
     [not found]       ` <CA+icZUW3K7RyUcfdos7aOkrEOd3To0kSns+G3GSfkPqqwo7z=w@mail.gmail.com>
2013-08-26 13:05         ` Fwd: " Michael S. Tsirkin
2013-08-26 17:28           ` (unknown) Michael S. Tsirkin
2012-10-05  7:15 (unknown) Robert Schwebel
2012-04-12  0:54 (unknown), Rodrigo Vivi
2011-09-30  9:39 (unknown), Inki Dae
2010-10-27  1:26 (unknown) Dave Airlie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).